From 207c92b569978364a5c3c302727b7ce3fd50d192 Mon Sep 17 00:00:00 2001 From: dhanabalan Date: Tue, 13 Oct 2026 14:25:30 +0530 Subject: [PATCH 1/2] Added non planned production report command page --- .../SendNonPlannedProductionReport.php | 212 ++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 app/Console/Commands/SendNonPlannedProductionReport.php diff --git a/app/Console/Commands/SendNonPlannedProductionReport.php b/app/Console/Commands/SendNonPlannedProductionReport.php new file mode 100644 index 00000000..6eb7e872 --- /dev/null +++ b/app/Console/Commands/SendNonPlannedProductionReport.php @@ -0,0 +1,212 @@ +argument('schedule_type'); + $plantId = (int) $this->argument('plant'); + + $mailRules = \App\Models\AlertMailRule::where('module', 'ProductionNonPlanQuantities') + ->where('rule_name', 'NonPlanProductionMail') + ->where('schedule_type', $scheduleType) + ->where('plant', $plantId) + ->get(); + + $emails = $mailRules->pluck('email')->unique()->toArray(); + + $plants = $plantId == 0 + ? Plant::all() + : Plant::where('id', $plantId)->get(); + + if ($plants->isEmpty()) { + $this->error('No valid plant(s) found.'); + + return; + } + + if (strtolower($scheduleType) == 'daily') { + $startDate = now()->subDay()->setTime(8, 0, 0); + $endDate = now()->setTime(8, 0, 0); + } + else { + $startDate = now()->setTime(8, 0, 0); + $endDate = now()->copy()->addDay()->setTime(8, 0, 0); + } + + $tableData = []; + $no = 1; + + foreach ($plants as $plant) { + + $lines = Line::where('plant_id', $plant->id) + ->whereIn('type', [ + 'Base FG Line', + 'FG Line', + 'Process FG Line', + 'SFG Line', + ]) + ->orderByRaw(" + CASE + WHEN LOWER(type) = 'fg line' THEN 0 + WHEN LOWER(type) = 'base fg line' THEN 1 + WHEN LOWER(type) = 'process fg line' THEN 2 + WHEN LOWER(type) = 'sfg line' THEN 3 + ELSE 4 + END + ") + ->get(); + + $month = $startDate->month; + $year = $startDate->year; + + foreach ($lines as $line) { + + $dayproductionQuantity = 0; + $nightproductionQuantity = 0; + $nonPlannedproductionQuantity = 0; + $totalActualProduction = 0; + + $itemIds = ProductionPlan::where('plant_id', $plant->id) + ->where('line_id', $line->id) + ->whereMonth('created_at', $month) + ->whereYear('created_at', $year) + ->distinct() + ->pluck('item_id'); + + if (strtolower($line->type) == 'fg line') { + + $actualTotalQuantity = \App\Models\QualityValidation::where('plant_id', $plant->id) + ->where('line_id', $line->id) + ->whereBetween('created_at', [$startDate, $endDate]) + ->count(); + + $totalActualProduction = $actualTotalQuantity; + + $nonPlannedproductionQuantity = \App\Models\QualityValidation::where('plant_id', $plant->id) + ->where('line_id', $line->id) + ->whereHas('stickerMaster', function ($query) use ($itemIds) { + $query->whereNotIn('item_id', $itemIds); + }) + ->whereBetween('created_at', [$startDate, $endDate]) + ->count(); + + $nonPlannedPercentage = $totalActualProduction > 0 + ? round(($nonPlannedproductionQuantity / $totalActualProduction) * 100, 2) + : 0; + + } + else { + + $nonPlannedproductionQuantity = ProductionQuantity::where('plant_id', $plant->id) + ->where('line_id', $line->id) + ->whereBetween('created_at', [$startDate, $endDate]) + ->count(); + } + + if (strtolower($line->type) == 'fg line') { + + $dayproductionQuantity = \App\Models\QualityValidation::where('plant_id', $plant->id) + ->where('line_id', $line->id) + ->whereHas('stickerMaster', function ($query) use ($itemIds) { + $query->whereNotIn('item_id', $itemIds); + }) + ->whereBetween('created_at', [ + $startDate->copy()->setTime(8, 0, 0), + $startDate->copy()->setTime(19, 30, 0), + ]) + ->count(); + + $nightproductionQuantity = \App\Models\QualityValidation::where('plant_id', $plant->id) + ->where('line_id', $line->id) + ->whereHas('stickerMaster', function ($query) use ($itemIds) { + $query->whereNotIn('item_id', $itemIds); + }) + ->whereBetween('created_at', [ + $startDate->copy()->setTime(19, 30, 0), + $endDate->copy()->setTime(8, 0, 0), + ]) + ->count(); + } + + $tableData[] = [ + 'no' => $no++, + 'plant' => $plant->name, + 'type' => $line->type, + 'line' => $line->name, + 'dayShiftActualQuantity' => floor($dayproductionQuantity), + 'nightShiftActualQuantity' => floor($nightproductionQuantity), + 'uom' => $line->uom, + 'totalActualQuantity' => $totalActualProduction, + 'nonPlannedQuantity' => $nonPlannedproductionQuantity, + 'nonPlannedPercentage' => $nonPlannedPercentage, + ]; + } + } + + $mail = new NonPlanProductionMail($scheduleType, $tableData); + + $contentVars = $mail->content()->with; + + $this->info($contentVars['greeting'] ?? 'Production Report'); + $this->table( + ['No', 'Plant', 'Line', 'Type', 'Target Quantity', 'Production Quantity'], + $tableData + ); + $this->info($contentVars['wishes'] ?? ''); + + foreach ($mailRules as $rule) + { + $toEmails = collect(explode(',', $rule->email)) + ->map(fn ($e) => trim($e)) + ->filter() + ->unique() + ->values() + ->toArray(); + + $ccEmails = collect(explode(',', $rule->cc_emails)) + ->map(fn ($e) => trim($e)) + ->filter() + ->unique() + ->values() + ->toArray(); + + if (empty($toEmails)) { + $this->warn("Skipping rule ID {$rule->id} — no valid To emails found."); + + continue; + } + + \Mail::to($toEmails)->cc($ccEmails)->send($mail); + + $this->info("Mail sent for rule ID {$rule->id} → To: ".implode(', ', $toEmails).($ccEmails ? ' | CC: '.implode(', ', $ccEmails) : '')); + } + } +} -- 2.49.1 From 75f029cf74650cd257345930eb93b7bd68ea64ce Mon Sep 17 00:00:00 2001 From: dhanabalan Date: Tue, 13 Oct 2026 14:33:44 +0530 Subject: [PATCH 2/2] Added non plan production mail pages --- app/Mail/NonPlanProductionMail.php | 89 +++++++++++++++++++ .../mail/non_plan_production_report.blade.php | 63 +++++++++++++ 2 files changed, 152 insertions(+) create mode 100644 app/Mail/NonPlanProductionMail.php create mode 100644 resources/views/mail/non_plan_production_report.blade.php diff --git a/app/Mail/NonPlanProductionMail.php b/app/Mail/NonPlanProductionMail.php new file mode 100644 index 00000000..1dd351ad --- /dev/null +++ b/app/Mail/NonPlanProductionMail.php @@ -0,0 +1,89 @@ +scheduleType = $scheduleType; + $this->tableData = $tableData ?? []; + } + + /** + * Get the message envelope. + */ + public function envelope(): Envelope + { + return new Envelope( + subject: 'Non Planned Production Report', + ); + } + + /** + * Get the message content definition. + */ + public function content(): Content + { + $greeting = "Dear Sir/Madam,

Kindly find the attached non planned production report status details 'Production Quantity' count,"; + + if ($this->scheduleType == 'Daily') { + $fromDate = (new DateTime('yesterday 08:00'))->format('d/m/Y H:i').':000'; + $toDate = (new DateTime('today 07:59'))->format('d/m/Y H:i').':999'; + $reportPeriod = "The following report presents results from: $fromDate to $toDate."; + $greeting .= $reportPeriod; + } + + if ($this->scheduleType == 'Hourly') { + $now = now(); + $fromHour = $now->copy()->subHour()->format('H:i:s'); + $toHour = $now->format('H:i:s'); + $reportDate = $now->format('d/m/Y'); + $greeting .= "The following report presents results from: $reportDate, $fromHour to $toHour."; + } + + if ($this->scheduleType == 'Live') { + $now = now(); + $fromMinute = $now->copy()->subMinute()->format('d/m/Y H:i:s'); + $toMinute = $now->format('d/m/Y H:i:s'); + $greeting .= "The following report presents results from: $fromMinute to $toMinute."; + } + + return new Content( + view: 'mail.non_plan_production_report', + with: [ + 'company' => 'CRI Digital Manufacturing Solutions', + 'greeting' => $greeting, + 'tableData' => $this->tableData, + 'wishes' => 'Thanks & Regards,
CRI Digital Manufacturing Solutions', + ], + ); + } + + /** + * Get the attachments for the message. + * + * @return array + */ + public function attachments(): array + { + return []; + } +} diff --git a/resources/views/mail/non_plan_production_report.blade.php b/resources/views/mail/non_plan_production_report.blade.php new file mode 100644 index 00000000..df34d0ea --- /dev/null +++ b/resources/views/mail/non_plan_production_report.blade.php @@ -0,0 +1,63 @@ + + + + Non Plan Production Table + + + +
+ {{ $company }} +
+
+

{!! $greeting !!}

+ + + + + + + + + + {{-- --}} + + + + + + @foreach($tableData as $row) + + + + + + + + {{-- --}} + + + + @endforeach + +
NoPlantLineLine TypeDay Shift Non Plan ProductionNight Shift Non Plan ProductionActual ProductionActual Non Plan Production + Non Plan Production % +
{{ $row['no'] }}{{ $row['plant'] }}{{ $row['line'] }}{{ $row['type'] }}{{ $row['dayShiftActualQuantity'] }}{{ $row['nightShiftActualQuantity'] }}{{ $row['totalActualQuantity'] }}{{ $row['nonPlannedQuantity'] }} + {{ $row['nonPlannedPercentage'] }}% +
+ +

{!! $wishes !!}

+ + -- 2.49.1