From 2f9f7c020d0c2c5e81f4a1e2d5a8b02c14516604 Mon Sep 17 00:00:00 2001 From: dhanabalan Date: Wed, 16 Sep 2026 08:49:32 +0530 Subject: [PATCH] Added send daily task report command file --- app/Console/Commands/SendDailyTaskReport.php | 229 +++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 app/Console/Commands/SendDailyTaskReport.php diff --git a/app/Console/Commands/SendDailyTaskReport.php b/app/Console/Commands/SendDailyTaskReport.php new file mode 100644 index 0000000..5c02312 --- /dev/null +++ b/app/Console/Commands/SendDailyTaskReport.php @@ -0,0 +1,229 @@ +argument('schedule_type'); + + $mailRules = AlertMailRule::where('module', 'DailyTaskReport') + ->where('rule_name', 'DailyTaskReportMail') + ->where('schedule_type', $scheduleType) + ->get(); + + if (!$mailRules) { + $this->error('Daily Task Report mail rule not found.'); + return self::FAILURE; + } + + // Get all PDF files + $pdfFiles = collect(Storage::disk('local')->files($directory)) + ->filter(function ($file) { + return strtolower(pathinfo($file, PATHINFO_EXTENSION)) == 'pdf'; + }) + ->values(); + + if ($pdfFiles->isEmpty()) { + $this->info('No PDF files found.'); + return self::SUCCESS; + } + + $parser = new Parser(); + $attachments = []; + $rows = []; + $sno = 1; + + $attachments = []; + + foreach ($pdfFiles as $file) { + $fullPath = Storage::disk('local')->path($file); + $filename = basename($file, '.pdf'); + + $attachments[] = [ + 'path' => Storage::disk('local')->path($file), + 'name' => basename($file), + ]; + + // Read PDF content for name/task/status + try { + $pdf = $parser->parseFile($fullPath); + $text = $pdf->getText(); + + \Log::info('PDF RAW TEXT: ' . $text); + } catch (\Throwable $e) { + $text = ''; + } + + $rows[] = [ + 'sno' => $sno++, + 'name' => $this->extractNameFromFilename($filename), + 'project-name' => $this->extractProjectName($text), + 'task' => $this->extractTaskTitle($text), + 'status' => $this->extractStatus($text), + 'completed' => $this->extractPercentComplete($text), + ]; + + $this->info('Attached: ' . basename($file)); + } + + $toEmails = []; + $ccEmails = []; + + foreach ($mailRules as $mailRule) { + + // TO email + if (!empty($mailRule->email)) { + $toEmails[] = trim($mailRule->email); + } + + // CC emails + if (!empty($mailRule->cc_emails)) { + + $ccEmails = array_merge( + $ccEmails, + array_map( + 'trim', + explode(',', $mailRule->cc_emails) + ) + ); + } + } + + // Remove duplicate emails + $toEmails = array_values(array_unique(array_filter($toEmails))); + $ccEmails = array_values(array_unique(array_filter($ccEmails))); + + + try { + + $mail = Mail::to($toEmails); + + if (!empty($ccEmails)) { + $mail->cc($ccEmails); + } + + $mail->send( + new DailyTaskReportMail($attachments, $rows) + ); + + foreach ($pdfFiles as $file) { + + if (Storage::disk('local')->exists($file)) { + Storage::disk('local')->delete($file); + + $this->info('Deleted: ' . basename($file)); + } + } + + $this->info( + $pdfFiles->count() . ' PDF(s) mailed and deleted successfully.' + ); + + return self::SUCCESS; + + } catch (\Throwable $e) { + + // Mail failed -> DO NOT delete PDFs + $this->error('Mail sending failed.'); + $this->error($e->getMessage()); + + return self::FAILURE; + } + } + + protected function extractNameFromFilename(string $filename): string + { + $name = preg_replace('/[-_]?task.*$/i', '', $filename); + $name = preg_replace('/[-_]+/', ' ', $name); + $name = preg_replace('/(?knownStatuses as $status) { + $pos = stripos($title, $status); + if ($pos != false) { + $title = trim(substr($title, 0, $pos)); + break; + } + } + return $title; + } + return 'Unknown task'; + } + + protected function extractStatus(string $text): string + { + // Replace non-breaking spaces (common in OpenProject PDF exports) with regular spaces + $normalized = str_replace("\xC2\xA0", ' ', $text); + $normalized = preg_replace('/\s+/', ' ', $normalized); + + foreach ($this->knownStatuses as $status) { + if (stripos($normalized, $status) !== false) { + return ucwords($status); + } + } + return 'Unknown'; + } + + protected function extractPercentComplete(string $text): string + { + $normalized = str_replace("\xC2\xA0", ' ', $text); + $normalized = preg_replace('/[ \t]+/', ' ', $normalized); + + if (preg_match('/%\s*Complete\s*([0-9]{1,3}\s*%)/i', $normalized, $matches)) { + return trim(str_replace(' ', '', $matches[1])); + } + + return '0%'; + } + + protected function extractProjectName(string $text): string + { + $normalized = str_replace("\xC2\xA0", ' ', $text); + + // Footer pattern: \t at the very end of the PDF text + if (preg_match('/\d{1,2}-\d{2}-\d{4}\s*\t\s*(.+?)\s*$/s', $normalized, $matches)) { + return trim($matches[1]); + } + + return 'Unknown project'; + } + +}