ranjith-dev #982
@@ -433,7 +433,6 @@ class Scheduler extends Command
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//..Laser Stop Final Report
|
//..Laser Stop Final Report
|
||||||
|
|
||||||
$laserStopFinalReport = AlertMailRule::where('module', 'LaserStopReport')
|
$laserStopFinalReport = AlertMailRule::where('module', 'LaserStopReport')
|
||||||
@@ -472,6 +471,45 @@ class Scheduler extends Command
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//..Panel Box Final Report
|
||||||
|
|
||||||
|
$panelBoxFinalReport = AlertMailRule::where('module', 'PanelBoxReport')
|
||||||
|
->where('rule_name', 'PanelBoxNotOkReportMail')
|
||||||
|
->select('plant', 'schedule_type', 'machine_id')
|
||||||
|
->distinct()
|
||||||
|
->get();
|
||||||
|
|
||||||
|
foreach ($panelBoxFinalReport as $rule) {
|
||||||
|
switch ($rule->schedule_type) {
|
||||||
|
case 'Live':
|
||||||
|
// Run every minute
|
||||||
|
\Artisan::call('send:panel-box-report', [
|
||||||
|
'schedule_type' => $rule->schedule_type,
|
||||||
|
'plant' => $rule->plant,
|
||||||
|
'machine_id' => $rule->machine_id,
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
case 'Hourly':
|
||||||
|
if (now()->minute == 0) {
|
||||||
|
\Artisan::call('send:panel-box-report', [
|
||||||
|
'schedule_type' => $rule->schedule_type,
|
||||||
|
'plant' => $rule->plant,
|
||||||
|
'machine_id' => $rule->machine_id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'Daily':
|
||||||
|
if (now()->format('H:i') == '08:00') {
|
||||||
|
\Artisan::call('send:panel-box-report', [
|
||||||
|
'schedule_type' => $rule->schedule_type,
|
||||||
|
'plant' => $rule->plant,
|
||||||
|
'machine_id' => $rule->machine_id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
117
app/Console/Commands/SendPanelBoxReport.php
Normal file
117
app/Console/Commands/SendPanelBoxReport.php
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Mail\PanelBoxReportMail;
|
||||||
|
use App\Models\Machine;
|
||||||
|
use App\Models\Plant;
|
||||||
|
use App\Models\ProductionCharacteristic;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
|
||||||
|
class SendPanelBoxReport extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'send:panel-box-report {schedule_type} {plant} {machine_id}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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');
|
||||||
|
$machineId = (int) $this->argument('machine_id');
|
||||||
|
|
||||||
|
$mailRules = \App\Models\AlertMailRule::where('module', 'PanelBoxReport')
|
||||||
|
->where('rule_name', 'PanelBoxNotOkReportMail')
|
||||||
|
->where('schedule_type', $scheduleType)
|
||||||
|
->where('plant', $plantId)
|
||||||
|
->where('machine_id', $machineId)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$emails = $mailRules
|
||||||
|
->pluck('email')
|
||||||
|
->filter()
|
||||||
|
->flatMap(function ($email) {
|
||||||
|
return array_map('trim', explode(',', $email));
|
||||||
|
})
|
||||||
|
->unique()
|
||||||
|
->values()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
$ccEmails = $mailRules
|
||||||
|
->pluck('cc_emails')
|
||||||
|
->filter()
|
||||||
|
->flatMap(function ($email) {
|
||||||
|
return array_map('trim', explode(',', $email));
|
||||||
|
})
|
||||||
|
->unique()
|
||||||
|
->values()
|
||||||
|
->toArray();
|
||||||
|
|
||||||
|
$plants = $plantId == 0
|
||||||
|
? Plant::all()
|
||||||
|
: Plant::where('id', $plantId)->get();
|
||||||
|
|
||||||
|
if ($plants->isEmpty()) {
|
||||||
|
$this->error('No valid plant(s) found.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$plant = Plant::find($plantId);
|
||||||
|
|
||||||
|
$plantName = $plant?->name ?? $plantId;
|
||||||
|
|
||||||
|
$machine = Machine::find($machineId);
|
||||||
|
|
||||||
|
$machineName = $machine?->work_center ?? $machineId;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
$records = ProductionCharacteristic::where('plant_id', $plantId)
|
||||||
|
->where('machine_id', $machineId)
|
||||||
|
->whereBetween('created_at', [$startDate, $endDate])
|
||||||
|
->where('status', 'NotOk')
|
||||||
|
->select('serial_number')
|
||||||
|
->distinct()
|
||||||
|
->get();
|
||||||
|
|
||||||
|
if ($records->isEmpty()) {
|
||||||
|
$this->info('No panel box records found.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send mail to mapped email IDs
|
||||||
|
Mail::to($emails)
|
||||||
|
->cc($ccEmails)
|
||||||
|
->send(
|
||||||
|
new PanelBoxReportMail(
|
||||||
|
$records,
|
||||||
|
$plantId,
|
||||||
|
$machineId,
|
||||||
|
$plantName,
|
||||||
|
$machineName,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->info('Panel box report mail sent successfully.');
|
||||||
|
}
|
||||||
|
}
|
||||||
71
app/Mail/PanelBoxReportMail.php
Normal file
71
app/Mail/PanelBoxReportMail.php
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
<?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;
|
||||||
|
|
||||||
|
class PanelBoxReportMail extends Mailable
|
||||||
|
{
|
||||||
|
use Queueable, SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new message instance.
|
||||||
|
*/
|
||||||
|
public $records;
|
||||||
|
public $plantId;
|
||||||
|
public $machineId;
|
||||||
|
public $plantName;
|
||||||
|
|
||||||
|
public $machineName;
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct($records,$plantId,$machineId, $plantName, $machineName)
|
||||||
|
{
|
||||||
|
$this->records = $records;
|
||||||
|
$this->plantId = $plantId;
|
||||||
|
$this->machineId = $machineId;
|
||||||
|
$this->plantName = $plantName;
|
||||||
|
$this->machineName = $machineName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message envelope.
|
||||||
|
*/
|
||||||
|
public function envelope(): Envelope
|
||||||
|
{
|
||||||
|
return new Envelope(
|
||||||
|
subject: 'Panel Box Inspection Report Mail',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the message content definition.
|
||||||
|
*/
|
||||||
|
public function content(): Content
|
||||||
|
{
|
||||||
|
$greeting = '<b>Dear Sir</b>';
|
||||||
|
return new Content(
|
||||||
|
view: 'mail.panel-box-report',
|
||||||
|
with: [
|
||||||
|
'company' => 'CRI Digital Manufacturing Solutions',
|
||||||
|
'greeting' => $greeting,
|
||||||
|
'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 [];
|
||||||
|
}
|
||||||
|
}
|
||||||
323
resources/views/mail/panel-box-report.blade.php
Normal file
323
resources/views/mail/panel-box-report.blade.php
Normal file
@@ -0,0 +1,323 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
background: #f4f6f8;
|
||||||
|
font-family: Arial, Helvetica, sans-serif;
|
||||||
|
color: #1f2937;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wrapper {
|
||||||
|
width: 100%;
|
||||||
|
padding: 30px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
width: 680px;
|
||||||
|
max-width: 94%;
|
||||||
|
margin: 0 auto;
|
||||||
|
background: #ffffff;
|
||||||
|
border-radius: 14px;
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 4px 18px rgba(0, 0, 0, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Header */
|
||||||
|
.header {
|
||||||
|
background: #111827;
|
||||||
|
padding: 28px 32px;
|
||||||
|
color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-title {
|
||||||
|
font-size: 24px;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-subtitle {
|
||||||
|
margin-top: 7px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: #d1d5db;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Info */
|
||||||
|
.info {
|
||||||
|
padding: 22px 32px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-label {
|
||||||
|
font-size: 11px;
|
||||||
|
color: #6b7280;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: bold;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-value {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #111827;
|
||||||
|
padding-top: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Summary */
|
||||||
|
.summary {
|
||||||
|
margin: 18px 32px;
|
||||||
|
padding: 22px;
|
||||||
|
background: #fff1f2;
|
||||||
|
border: 1px solid #fecdd3;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-label {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #9f1239;
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-count {
|
||||||
|
font-size: 34px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #e11d48;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.summary-text {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #881337;
|
||||||
|
margin-top: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Table */
|
||||||
|
.content {
|
||||||
|
padding: 5px 32px 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.section-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #111827;
|
||||||
|
margin: 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.serial-table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: separate;
|
||||||
|
border-spacing: 0;
|
||||||
|
border: 1px solid #e5e7eb;
|
||||||
|
border-radius: 10px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.serial-table th {
|
||||||
|
background: #f9fafb;
|
||||||
|
color: #6b7280;
|
||||||
|
font-size: 11px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.4px;
|
||||||
|
padding: 12px 14px;
|
||||||
|
text-align: left;
|
||||||
|
border-bottom: 1px solid #e5e7eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.serial-table td {
|
||||||
|
padding: 13px 14px;
|
||||||
|
font-size: 13px;
|
||||||
|
border-bottom: 1px solid #f0f1f3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.serial-table tr:last-child td {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.serial-number {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #111827;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.not-ok {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 5px 10px;
|
||||||
|
background: #ffe4e6;
|
||||||
|
color: #be123c;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 10px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Footer */
|
||||||
|
.footer {
|
||||||
|
background: #f9fafb;
|
||||||
|
padding: 18px 32px;
|
||||||
|
text-align: center;
|
||||||
|
border-top: 1px solid #e5e7eb;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-text {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 11px;
|
||||||
|
color: #9ca3af;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-warning {
|
||||||
|
margin-top: 5px;
|
||||||
|
font-size: 11px;
|
||||||
|
color: #6b7280;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="wrapper">
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
|
||||||
|
{{-- HEADER --}}
|
||||||
|
<div class="header">
|
||||||
|
<div class="header-title">
|
||||||
|
Panel Box Inspection Report
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="header-subtitle">
|
||||||
|
NOT OK Serial Number Report
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{{-- PLANT / MACHINE INFORMATION --}}
|
||||||
|
<div class="info">
|
||||||
|
|
||||||
|
<table class="info-table">
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<td width="33%">
|
||||||
|
<div class="info-label">Plant</div>
|
||||||
|
<div class="info-value">
|
||||||
|
{{ $plantName }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td width="33%">
|
||||||
|
<div class="info-label">Machine</div>
|
||||||
|
<div class="info-value">
|
||||||
|
{{ $machineName }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td width="34%">
|
||||||
|
<div class="info-label">Report Date</div>
|
||||||
|
<div class="info-value">
|
||||||
|
{{ now()->format('d M Y') }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{{-- SUMMARY --}}
|
||||||
|
<div class="summary">
|
||||||
|
|
||||||
|
<div class="summary-label">
|
||||||
|
NOT OK Inspections
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="summary-count">
|
||||||
|
{{ $records->count() }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="summary-text">
|
||||||
|
Panel box serial numbers requiring attention
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{{-- SERIAL NUMBER LIST --}}
|
||||||
|
<div class="content">
|
||||||
|
|
||||||
|
<div class="section-title">
|
||||||
|
NOT OK Serial Numbers
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<table class="serial-table">
|
||||||
|
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th width="12%">S.No</th>
|
||||||
|
<th>Serial Number</th>
|
||||||
|
<th width="20%">Status</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
@foreach($records as $index => $record)
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
{{ $index + 1 }}
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<span class="serial-number">
|
||||||
|
{{ $record->serial_number }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td>
|
||||||
|
<span class="not-ok">
|
||||||
|
NOT OK
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{{-- FOOTER --}}
|
||||||
|
<div class="footer">
|
||||||
|
|
||||||
|
<p class="footer-text">
|
||||||
|
This is an automated Panel Box Inspection Report.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="footer-warning">
|
||||||
|
Please review the above serial numbers for necessary action.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user