ranjith-dev #1236
212
app/Console/Commands/SendNonPlannedProductionReport.php
Normal file
212
app/Console/Commands/SendNonPlannedProductionReport.php
Normal file
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Mail\NonPlanProductionMail;
|
||||
use App\Models\Line;
|
||||
use App\Models\Plant;
|
||||
use App\Models\ProductionPlan;
|
||||
use App\Models\ProductionQuantity;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class SendNonPlannedProductionReport extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'send:non-planned-production-report {schedule_type} {plant}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Command description';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
$scheduleType = $this->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) : ''));
|
||||
}
|
||||
}
|
||||
}
|
||||
89
app/Mail/NonPlanProductionMail.php
Normal file
89
app/Mail/NonPlanProductionMail.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use DateTime;
|
||||
|
||||
class NonPlanProductionMail extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
public $tableData;
|
||||
|
||||
public $scheduleType;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*/
|
||||
public function __construct($scheduleType, $tableData = [])
|
||||
{
|
||||
$this->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,<br><br>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,<br>CRI Digital Manufacturing Solutions',
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attachments for the message.
|
||||
*
|
||||
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
|
||||
*/
|
||||
public function attachments(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
63
resources/views/mail/non_plan_production_report.blade.php
Normal file
63
resources/views/mail/non_plan_production_report.blade.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Non Plan Production Table</title>
|
||||
<style>
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 60%;
|
||||
}
|
||||
th, td {
|
||||
border: 1px solid #444;
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
th {
|
||||
background: #f2f2f2;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div style="text-align: center; font-weight: bold;">
|
||||
{{ $company }}
|
||||
</div>
|
||||
<br>
|
||||
<p>{!! $greeting !!}</p>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="text-align: center; border: 1px solid #444; padding: 8px; background: #f2f2f2;">No</th>
|
||||
<th style="text-align: center; border: 1px solid #444; padding: 8px; background: #f2f2f2;">Plant</th>
|
||||
<th style="text-align: center; border: 1px solid #444; padding: 8px; background: #f2f2f2;">Line</th>
|
||||
<th style="text-align: center; border: 1px solid #444; padding: 8px; background: #f2f2f2;">Line Type</th>
|
||||
<th style="text-align: center; border: 1px solid #444; padding: 8px; background: #f2f2f2;">Day Shift Non Plan Production</th>
|
||||
<th style="text-align: center; border: 1px solid #444; padding: 8px; background: #f2f2f2;">Night Shift Non Plan Production</th>
|
||||
{{-- <th style="text-align: center; border: 1px solid #444; padding: 8px; background: #f2f2f2;">Actual Production</th> --}}
|
||||
<th style="text-align: center; border: 1px solid #444; padding: 8px; background: #f2f2f2;">Actual Non Plan Production</th>
|
||||
<th style="text-align: center; border: 1px solid #444; padding: 8px; background: #f2f2f2;">
|
||||
Non Plan Production %
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach($tableData as $row)
|
||||
<tr>
|
||||
<td style="border: 1px solid #444; padding: 8px; text-align: center;">{{ $row['no'] }}</td>
|
||||
<td style="border: 1px solid #444; padding: 8px; text-align: center; white-space: nowrap;">{{ $row['plant'] }}</td>
|
||||
<td style="border: 1px solid #444; padding: 8px; text-align: center; white-space: nowrap;">{{ $row['line'] }}</td>
|
||||
<td style="border: 1px solid #444; padding: 8px; text-align: center; white-space: nowrap;">{{ $row['type'] }}</td>
|
||||
<td style="border: 1px solid #444; padding: 8px; text-align: center;">{{ $row['dayShiftActualQuantity'] }}</td>
|
||||
<td style="border: 1px solid #444; padding: 8px; text-align: center;">{{ $row['nightShiftActualQuantity'] }}</td>
|
||||
{{-- <td style="border: 1px solid #444; padding: 8px; text-align: center;">{{ $row['totalActualQuantity'] }}</td> --}}
|
||||
<td style="border: 1px solid #444; padding: 8px; text-align: center;">{{ $row['nonPlannedQuantity'] }}</td>
|
||||
<td style="border: 1px solid #444; padding: 8px; text-align: center;">
|
||||
{{ $row['nonPlannedPercentage'] }}%
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<p>{!! $wishes !!}</p>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user