Merge pull request 'ranjith-dev' (#1056) from ranjith-dev into master
All checks were successful
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Successful in 15s
All checks were successful
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Successful in 15s
Reviewed-on: #1056
This commit was merged in pull request #1056.
This commit is contained in:
@@ -2,12 +2,18 @@
|
|||||||
|
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Mail\LaserStopMail;
|
||||||
use App\Mail\LaserStopReportMail;
|
use App\Mail\LaserStopReportMail;
|
||||||
|
use App\Models\CharacteristicApproverMaster;
|
||||||
use App\Models\ClassCharacteristic;
|
use App\Models\ClassCharacteristic;
|
||||||
use App\Models\Machine;
|
use App\Models\Machine;
|
||||||
use App\Models\Plant;
|
use App\Models\Plant;
|
||||||
|
use App\Models\RequestCharacteristic;
|
||||||
|
use App\Models\TempStopCharacteristic;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use Illuminate\Support\Facades\Mail;
|
use Illuminate\Support\Facades\Mail;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
|
|
||||||
class SendLaserStopReport extends Command
|
class SendLaserStopReport extends Command
|
||||||
{
|
{
|
||||||
@@ -16,7 +22,7 @@ class SendLaserStopReport extends Command
|
|||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $signature = 'send:laser-stop-report {schedule_type} {plant} {machine_id}';
|
protected $signature = 'approval:laser-stop';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The console command description.
|
* The console command description.
|
||||||
@@ -25,89 +31,194 @@ class SendLaserStopReport extends Command
|
|||||||
*/
|
*/
|
||||||
protected $description = 'Command description';
|
protected $description = 'Command description';
|
||||||
|
|
||||||
|
public $subjectLine;
|
||||||
|
|
||||||
|
// public $tempCharacteristics = [];
|
||||||
|
|
||||||
|
public $wfId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute the console command.
|
* Execute the console command.
|
||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$scheduleType = $this->argument('schedule_type');
|
$this->info('Approval mail job started');
|
||||||
$plantId = (int) $this->argument('plant');
|
|
||||||
$machineId = (int) $this->argument('machine_id');
|
|
||||||
|
|
||||||
$mailRules = \App\Models\AlertMailRule::where('module', 'LaserStopAlert')
|
// .. Laser Stop Mail trigger logic
|
||||||
->where('rule_name', 'LaserStopAlertMail')
|
|
||||||
->where('schedule_type', $scheduleType)
|
$stoppedRecords = RequestCharacteristic::where(function ($q) {
|
||||||
->where('plant', $plantId)
|
$q->whereNull('approver_status1')
|
||||||
->where('machine_id', $machineId)
|
->orWhere('approver_status1', 'Hold');
|
||||||
|
})
|
||||||
|
->where(function ($q) {
|
||||||
|
$q->whereNull('approver_status2')
|
||||||
|
->orWhere('approver_status2', 'Hold');
|
||||||
|
})
|
||||||
|
->where(function ($q) {
|
||||||
|
$q->whereNull('approver_status3')
|
||||||
|
->orWhere('approver_status3', 'Hold');
|
||||||
|
})
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
$emails = $mailRules
|
$stoppedRecords = $stoppedRecords->filter(function ($item) {
|
||||||
->pluck('email')
|
$approver = CharacteristicApproverMaster::find($item->characteristic_approver_master_id);
|
||||||
->filter()
|
return $approver && $approver->approver_type == 'Stop';
|
||||||
->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
|
if ($stoppedRecords->isEmpty()) {
|
||||||
? Plant::all()
|
$this->info('No laser stop pending approvals');
|
||||||
: Plant::where('id', $plantId)->get();
|
|
||||||
|
|
||||||
if ($plants->isEmpty()) {
|
|
||||||
$this->error('No valid plant(s) found.');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$plant = Plant::find($plantId);
|
$grouped = $stoppedRecords->groupBy(function ($item) {
|
||||||
|
$this->wfId = $item->work_flow_id;
|
||||||
|
return $item->plant_id . '|' . $item->machine_id . '|' . $item->aufnr . '|' . $item->work_flow_id;
|
||||||
|
});
|
||||||
|
|
||||||
$plantName = $plant?->name ?? $plantId;
|
$pendingApprovers = RequestCharacteristic::where('work_flow_id', $this->wfId)->latest()->first();
|
||||||
|
|
||||||
$machine = Machine::find($machineId);
|
$approverNameFromMaster = null;
|
||||||
|
if ($pendingApprovers && $pendingApprovers->characteristic_approver_master_id) {
|
||||||
$machineName = $machine?->work_center ?? $machineId;
|
$approverNameFromMaster = CharacteristicApproverMaster::find($pendingApprovers->characteristic_approver_master_id);
|
||||||
|
|
||||||
$records = ClassCharacteristic::where('is_stopped', 2)
|
|
||||||
->where('plant_id', $plantId)
|
|
||||||
->where('machine_id', $machineId)
|
|
||||||
->get();
|
|
||||||
|
|
||||||
if ($records->isEmpty()) {
|
|
||||||
$this->info('No laser stop records found.');
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$recordIds = $records->pluck('id');
|
$rows = [];
|
||||||
|
|
||||||
// Send mail to mapped email IDs
|
foreach ($grouped as $groupRecords) {
|
||||||
Mail::to($emails)
|
|
||||||
->cc($ccEmails)
|
$first = $groupRecords->first();
|
||||||
->send(
|
|
||||||
new LaserStopReportMail(
|
$approver = CharacteristicApproverMaster::where('plant_id', $first->plant_id)
|
||||||
$records,
|
->where('machine_id', $first->machine_id)
|
||||||
$plantId,
|
->where('id', $first->characteristic_approver_master_id)
|
||||||
$machineId,
|
->first();
|
||||||
$plantName,
|
|
||||||
$machineName,
|
if (!$approver) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$columns = Schema::getColumnListing('temp_stop_characteristics');
|
||||||
|
|
||||||
|
$exclude = ['id', 'plant_id', 'machine_id', 'item_id', 'aufnr', 'class', 'arbid', 'gamng', 'lmnga', 'zz1_cn_bill_ord', 'created_at', 'updated_at', 'deleted_at', 'has_work_flow_id', 'created_by', 'updated_by' ];
|
||||||
|
|
||||||
|
$filteredColumns = array_diff($columns, $exclude);
|
||||||
|
|
||||||
|
$row1 = TempStopCharacteristic::where('plant_id', $first->plant_id)
|
||||||
|
->where('machine_id', $first->machine_id)
|
||||||
|
->where('aufnr', $first->aufnr)
|
||||||
|
->where('model_type', $first->model_type)
|
||||||
|
->where('gernr', $first->gernr)
|
||||||
|
->latest()
|
||||||
|
->first();
|
||||||
|
|
||||||
|
$stopDetails = [
|
||||||
|
'samlight_logged_name' => $row1?->samlight_logged_name,
|
||||||
|
'zmm_heading' => $row1?->zmm_heading,
|
||||||
|
'machine_name' => $row1?->machine_name,
|
||||||
|
'stopped_at' => $row1?->stopped_at,
|
||||||
|
'stopped_by' => $row1?->stopped_by,
|
||||||
|
];
|
||||||
|
|
||||||
|
$data = [];
|
||||||
|
|
||||||
|
if ($row1) {
|
||||||
|
foreach ($filteredColumns as $column) {
|
||||||
|
|
||||||
|
$value = $row1->getAttribute($column);
|
||||||
|
|
||||||
|
if ($value != null && $value != '') {
|
||||||
|
$data[$column] = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$characteristics = $data;
|
||||||
|
|
||||||
|
$level = null;
|
||||||
|
$mail = null;
|
||||||
|
$name = null;
|
||||||
|
$updateData = [];
|
||||||
|
$now = Carbon::now();
|
||||||
|
|
||||||
|
// --- FIRST MAIL ---
|
||||||
|
if (is_null($first->mail_status)){
|
||||||
|
$level = 1;
|
||||||
|
$mail = $approver->mail1;
|
||||||
|
$name = $approver->name1;
|
||||||
|
|
||||||
|
$updateData['mail_status'] = 'Sent';
|
||||||
|
|
||||||
|
if ($approver->duration1 > 0)
|
||||||
|
{
|
||||||
|
|
||||||
|
$duration = number_format((float)$approver->duration1, 2, '.', '');
|
||||||
|
[$hours, $minutes] = explode('.', $duration);
|
||||||
|
|
||||||
|
$totalMinutes = ((int)$hours * 60) + (int)$minutes;
|
||||||
|
|
||||||
|
$updateData['trigger_at'] = $now
|
||||||
|
->copy()
|
||||||
|
->addMinutes($totalMinutes)
|
||||||
|
->startOfMinute();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$updateData['trigger_at'] = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$level || !$mail) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$subjectLine = 'Laser Stop Approval Mail';
|
||||||
|
|
||||||
|
$emails = array_map('trim', explode(',', $mail));
|
||||||
|
|
||||||
|
Mail::to($emails)->send(
|
||||||
|
new LaserStopMail(
|
||||||
|
$first,
|
||||||
|
$name,
|
||||||
|
$level,
|
||||||
|
$pendingApprovers,
|
||||||
|
$approverNameFromMaster,
|
||||||
|
$subjectLine,
|
||||||
|
$characteristics,
|
||||||
|
$stopDetails
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
ClassCharacteristic::whereIn('id', $recordIds)
|
RequestCharacteristic::whereIn('id', $groupRecords->pluck('id'))
|
||||||
->update([
|
->update($updateData);
|
||||||
'is_stopped' => 1,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$this->info('Laser stop report mail sent successfully.');
|
$rows[] = [
|
||||||
|
$first->id,
|
||||||
|
$first->plant_id,
|
||||||
|
$first->machine_id,
|
||||||
|
"Level $level",
|
||||||
|
$mail,
|
||||||
|
'SENT'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->table(
|
||||||
|
['ID', 'Plant', 'Machine', 'Level', 'Mail', 'Status'],
|
||||||
|
$rows
|
||||||
|
);
|
||||||
|
|
||||||
|
$this->info('Approval mail job completed');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function convertToMinutes($duration)
|
||||||
|
{
|
||||||
|
if (!$duration) return 0;
|
||||||
|
|
||||||
|
$parts = explode('.', (string)$duration);
|
||||||
|
|
||||||
|
$hours = (int)($parts[0] ?? 0);
|
||||||
|
$minutes = (int)($parts[1] ?? 0);
|
||||||
|
|
||||||
|
return ($hours * 60) + $minutes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -424,6 +424,93 @@ class CharacteristicApprovalController extends Controller
|
|||||||
return response()->json(['status' => true, 'message' => 'Status updated successfully']);
|
return response()->json(['status' => true, 'message' => 'Status updated successfully']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//..Laser Stop
|
||||||
|
|
||||||
|
public function laserApproveForm(Request $request)
|
||||||
|
{
|
||||||
|
$id = $request->query('id');
|
||||||
|
$level = (int) $request->query('level');
|
||||||
|
|
||||||
|
$record = RequestCharacteristic::findOrFail($id);
|
||||||
|
|
||||||
|
[$statusColumn, $approvedAtColumn, $remarkColumn] = match ($level) {
|
||||||
|
1 => ['approver_status1', 'approved1_at', 'approver_remark1'],
|
||||||
|
2 => ['approver_status2', 'approved2_at', 'approver_remark2'],
|
||||||
|
3 => ['approver_status3', 'approved3_at', 'approver_remark3'],
|
||||||
|
default => abort(403, 'Invalid approver level'),
|
||||||
|
};
|
||||||
|
|
||||||
|
$levels = [
|
||||||
|
1 => 'approver_status1',
|
||||||
|
2 => 'approver_status2',
|
||||||
|
3 => 'approver_status3',
|
||||||
|
];
|
||||||
|
|
||||||
|
$currentStatusColumn = $levels[$level];
|
||||||
|
|
||||||
|
$currentStatus = $record->$statusColumn;
|
||||||
|
|
||||||
|
if (in_array($currentStatus, ['Approved', 'Rejected'])) {
|
||||||
|
return view('approval.already-processed', [
|
||||||
|
'status' => $currentStatus,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($levels as $lvl => $column) {
|
||||||
|
if ($lvl != $level && in_array($record->$column, ['Approved', 'Rejected'])) {
|
||||||
|
return view('approval.already-processed', [
|
||||||
|
'status' => $record->$column,
|
||||||
|
'message' => 'Your request has already been processed by another approver',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// foreach ($levels as $lvl => $column) {
|
||||||
|
// if ($record->$column == 'Hold') {
|
||||||
|
|
||||||
|
// if ($lvl == $level) {
|
||||||
|
// return view('approval.reject-form', compact('id', 'level'));
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// return view('approval.already-processed', [
|
||||||
|
// 'status' => 'Hold',
|
||||||
|
// 'message' => 'On Hold',
|
||||||
|
// ]);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
$allowedMailStatusByLevel = [
|
||||||
|
1 => 'Sent',
|
||||||
|
2 => 'Sent-Mail2',
|
||||||
|
3 => 'Sent-Mail3',
|
||||||
|
];
|
||||||
|
|
||||||
|
$expectedMailStatus = $allowedMailStatusByLevel[$level] ?? null;
|
||||||
|
|
||||||
|
if ($record->mail_status != $expectedMailStatus) {
|
||||||
|
return view('approval.approve-level', [
|
||||||
|
'status' => $currentStatus,
|
||||||
|
'message' => 'Your approval time limit has expired.',
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('approval.approve-form', compact('id', 'level'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function laserApproveSave(Request $request)
|
||||||
|
{
|
||||||
|
$request->validate([
|
||||||
|
'id' => 'required|integer',
|
||||||
|
'level' => 'required|integer',
|
||||||
|
'remark' => 'nullable|string',
|
||||||
|
]);
|
||||||
|
|
||||||
|
return $this->updateStatus($request, 'Approved', false);
|
||||||
|
}
|
||||||
|
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -8,28 +8,40 @@ use Illuminate\Mail\Mailable;
|
|||||||
use Illuminate\Mail\Mailables\Content;
|
use Illuminate\Mail\Mailables\Content;
|
||||||
use Illuminate\Mail\Mailables\Envelope;
|
use Illuminate\Mail\Mailables\Envelope;
|
||||||
use Illuminate\Queue\SerializesModels;
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
use Illuminate\Support\Facades\URL;
|
||||||
|
|
||||||
class LaserStopMail extends Mailable
|
class LaserStopMail extends Mailable
|
||||||
{
|
{
|
||||||
use Queueable, SerializesModels;
|
use Queueable, SerializesModels;
|
||||||
|
|
||||||
public $records;
|
public $request;
|
||||||
public $plantId;
|
public $approverName;
|
||||||
public $machineId;
|
public $level;
|
||||||
public $plantName;
|
public $tableData;
|
||||||
|
|
||||||
public $machineName;
|
public $pendingApprovers;
|
||||||
|
|
||||||
|
public $approverNameFromMaster;
|
||||||
|
|
||||||
|
public $subjectLine;
|
||||||
|
|
||||||
|
public $characteristics;
|
||||||
|
|
||||||
|
public $stopDetails;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new message instance.
|
* Create a new message instance.
|
||||||
*/
|
*/
|
||||||
public function __construct($records,$plantId,$machineId, $plantName, $machineName)
|
public function __construct($request, $approverName, $level, $pendingApprovers, $approverNameFromMaster, $subjectLine, $characteristics = [], $stopDetails=[])
|
||||||
{
|
{
|
||||||
$this->records = $records;
|
$this->request = $request;
|
||||||
$this->plantId = $plantId;
|
$this->approverName = $approverName;
|
||||||
$this->machineId = $machineId;
|
$this->level = $level;
|
||||||
$this->plantName = $plantName;
|
$this->pendingApprovers = $pendingApprovers;
|
||||||
$this->machineName = $machineName;
|
$this->approverNameFromMaster = $approverNameFromMaster;
|
||||||
|
$this->subjectLine = $subjectLine;
|
||||||
|
$this->tableData = $characteristics;
|
||||||
|
$this->stopDetails = $stopDetails;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,7 +50,7 @@ class LaserStopMail extends Mailable
|
|||||||
public function envelope(): Envelope
|
public function envelope(): Envelope
|
||||||
{
|
{
|
||||||
return new Envelope(
|
return new Envelope(
|
||||||
subject: 'Laser Marking - Consolidated Stoppage Report',
|
subject: $this->subjectLine,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,17 +59,33 @@ class LaserStopMail extends Mailable
|
|||||||
*/
|
*/
|
||||||
public function content(): Content
|
public function content(): Content
|
||||||
{
|
{
|
||||||
$greeting = '<b>Dear Sir</b>';
|
|
||||||
return new Content(
|
return new Content(
|
||||||
view: 'mail.laser-stop-final-report',
|
view: 'mail.laser-stop-report',
|
||||||
with: [
|
with: [
|
||||||
'company' => 'CRI Digital Manufacturing Solutions',
|
'company' => 'CRI Digital Manufacturing Solutions',
|
||||||
'greeting' => $greeting,
|
'greeting' => 'Dear ' . $this->approverName . ',',
|
||||||
'wishes' => 'Thanks & Regards,<br>CRI Digital Manufacturing Solutions',
|
'request' => $this->request,
|
||||||
],
|
'level' => $this->level,
|
||||||
|
'tableData' => $this->tableData,
|
||||||
|
'tempstop' => $this->stopDetails,
|
||||||
|
'pendingApprovers' => $this->pendingApprovers,
|
||||||
|
'approverNameFromMaster' => $this->approverNameFromMaster,
|
||||||
|
'approveUrl' => $this->approveUrl(),
|
||||||
|
// 'holdUrl' => $this->holdUrl(),
|
||||||
|
// 'rejectUrl' => $this->rejectUrl(),
|
||||||
|
'wishes' => 'Thanks & Regards,<br>CRI Digital Manufacturing Solutions',
|
||||||
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function approveUrl()
|
||||||
|
{
|
||||||
|
return URL::signedRoute('laser.approve', [
|
||||||
|
'id' => $this->request->id,
|
||||||
|
'level' => $this->level
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the attachments for the message.
|
* Get the attachments for the message.
|
||||||
*
|
*
|
||||||
|
|||||||
77
resources/views/approval/laser-approve-success.blade.php
Normal file
77
resources/views/approval/laser-approve-success.blade.php
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Approval</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
background: #f6f6f6;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.card {
|
||||||
|
background: #ffffff;
|
||||||
|
padding: 20px;
|
||||||
|
max-width: 500px;
|
||||||
|
margin: 50px auto;
|
||||||
|
border-radius: 6px;
|
||||||
|
text-align: center;
|
||||||
|
box-shadow: 0 0 10px rgba(0,0,0,.1);
|
||||||
|
}
|
||||||
|
.hold {
|
||||||
|
color: Green;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.footer {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999999;
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
a.button {
|
||||||
|
display: inline-block;
|
||||||
|
margin-top: 15px;
|
||||||
|
padding: 10px 20px;
|
||||||
|
background-color: Green;
|
||||||
|
color: #ffffff;
|
||||||
|
text-decoration: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.pulse-darkred {
|
||||||
|
color: Green; /* #8B0000 */
|
||||||
|
background-color: #fff; /* White bg for contrast */
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.5em 0.75em;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 1em;
|
||||||
|
line-height: 1;
|
||||||
|
animation: pulse 1.5s ease-in-out infinite; /* Duration, easing, infinite loop */
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
0%, 100% {
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: scale(1.2); /* Gentle 5% expansion */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="hold"><span class="pulse-darkred">🟢</span> Approved Successfully</div>
|
||||||
|
<p>Your request has been approved.</p>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<div class="footer">
|
||||||
|
CRI Digital Manufacturing Solutions<br>
|
||||||
|
© 2026 All Rights Reserved
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
@@ -1,240 +1,137 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
{{-- <title>Invoice Data Report</title> --}}
|
||||||
|
|
||||||
<title>Laser Marking Stopped Report</title>
|
|
||||||
</head>
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
<body style="margin:0; padding:0; background-color:#f4f6f8; font-family:Arial, Helvetica, sans-serif;">
|
<div style="text-align: center; font-weight: bold;">
|
||||||
|
{{ $company }}
|
||||||
|
</div>
|
||||||
|
<br>
|
||||||
|
<p>{!! $greeting !!}</p>
|
||||||
|
|
||||||
<table width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color:#f4f6f8; padding:30px 10px;">
|
<table style="margin-left: 3%" border="1" width="30%" cellpadding="6" cellspacing="0">
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center">
|
<th width="30%">Title</th>
|
||||||
|
<th width="40%">Details</th>
|
||||||
<!-- Main Container -->
|
</tr>
|
||||||
<table width="700" cellpadding="0" cellspacing="0" border="0"
|
<tr>
|
||||||
style="max-width:700px; width:100%; background:#ffffff; border-radius:12px; overflow:hidden; box-shadow:0 4px 15px rgba(0,0,0,0.08);">
|
<td>Stopped Date Time</td>
|
||||||
|
{{-- <td style="text-align: center;">{{ $tempstop['stopped_at']->format('d-m-Y H:i:s') }}</td> --}}
|
||||||
<!-- Header -->
|
<td style="text-align: center;">
|
||||||
<tr>
|
{{ $tempstop['stopped_at']
|
||||||
<td style="background:#1f2937; padding:25px 30px;">
|
? \Carbon\Carbon::parse($tempstop['stopped_at'])->format('d-m-Y H:i:s')
|
||||||
|
: '' }}
|
||||||
<table width="100%" cellpadding="0" cellspacing="0">
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
<div style="font-size:13px; color:#cbd5e1; letter-spacing:1px; text-transform:uppercase;">
|
|
||||||
CRI Digital Manufacturing
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="font-size:28px; font-weight:bold; color:#ffffff; margin-top:6px;">
|
|
||||||
Laser Marking Stopped Alert
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="font-size:13px; color:#cbd5e1; margin-top:6px;">
|
|
||||||
Laser marking machine stoppage notification
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td align="right" valign="middle">
|
|
||||||
<div style="width:48px; height:48px; background:#ef4444; border-radius:50%; text-align:center; line-height:48px; color:#ffffff; font-size:22px; font-weight:bold;">
|
|
||||||
!
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Alert -->
|
|
||||||
<tr>
|
|
||||||
<td style="padding:25px 30px 10px 30px;">
|
|
||||||
|
|
||||||
<div style="background:#fff7ed; border-left:5px solid #f97316; padding:15px 18px; border-radius:6px;">
|
|
||||||
|
|
||||||
<div style="font-size:16px; font-weight:bold; color:#9a3412;">
|
|
||||||
⚠ Laser Marking Stop Detected
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="font-size:13px; color:#7c2d12; margin-top:5px;">
|
|
||||||
The following laser marking stopped records require your attention.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Report Title -->
|
|
||||||
<tr>
|
|
||||||
<td style="padding:20px 30px 10px 30px;">
|
|
||||||
|
|
||||||
<div style="font-size:18px; font-weight:bold; color:#111827;">
|
|
||||||
Stopped Machine Records
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="font-size:13px; color:#64748b; margin-top:4px;">
|
|
||||||
Total records: {{ $records->count() }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Table -->
|
|
||||||
<tr>
|
|
||||||
<td style="padding:10px 30px 30px 30px;">
|
|
||||||
|
|
||||||
<table width="100%" cellpadding="0" cellspacing="0" border="0"
|
|
||||||
style="border-collapse:collapse; font-size:13px;">
|
|
||||||
|
|
||||||
<thead>
|
|
||||||
<tr style="background:#1f2937;">
|
|
||||||
|
|
||||||
<th align="left"
|
|
||||||
style="padding:12px 10px; color:#ffffff; font-weight:bold;">
|
|
||||||
No
|
|
||||||
</th>
|
|
||||||
|
|
||||||
<th align="left"
|
|
||||||
style="padding:12px 10px; color:#ffffff; font-weight:bold;">
|
|
||||||
Plant
|
|
||||||
</th>
|
|
||||||
|
|
||||||
<th align="left"
|
|
||||||
style="padding:12px 10px; color:#ffffff; font-weight:bold;">
|
|
||||||
Machine
|
|
||||||
</th>
|
|
||||||
|
|
||||||
<th align="left"
|
|
||||||
style="padding:12px 10px; color:#ffffff; font-weight:bold;">
|
|
||||||
Production Order
|
|
||||||
</th>
|
|
||||||
|
|
||||||
|
|
||||||
<th align="left"
|
|
||||||
style="padding:12px 10px; color:#ffffff; font-weight:bold;">
|
|
||||||
Item Code
|
|
||||||
</th>
|
|
||||||
|
|
||||||
<th align="left"
|
|
||||||
style="padding:12px 10px; color:#ffffff; font-weight:bold;">
|
|
||||||
Serial Number
|
|
||||||
</th>
|
|
||||||
|
|
||||||
<th align="center"
|
|
||||||
style="padding:12px 10px; color:#ffffff; font-weight:bold;">
|
|
||||||
Status
|
|
||||||
</th>
|
|
||||||
|
|
||||||
<th align="center"
|
|
||||||
style="padding:12px 10px; color:#ffffff; font-weight:bold;">
|
|
||||||
Stopped At
|
|
||||||
</th>
|
|
||||||
|
|
||||||
<th align="center"
|
|
||||||
style="padding:12px 10px; color:#ffffff; font-weight:bold;">
|
|
||||||
Stopped By
|
|
||||||
</th>
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
|
|
||||||
<tbody>
|
|
||||||
|
|
||||||
@foreach($records as $index => $record)
|
|
||||||
|
|
||||||
<tr style="background:{{ $index % 2 == 0 ? '#ffffff' : '#f8fafc' }};">
|
|
||||||
|
|
||||||
<td style="padding:13px 10px; border-bottom:1px solid #e5e7eb; color:#374151;">
|
|
||||||
{{ $index + 1 }}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td style="padding:13px 10px; border-bottom:1px solid #e5e7eb; color:#374151; white-space: nowrap;">
|
|
||||||
{{ $plantName }}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td style="padding:13px 10px; border-bottom:1px solid #e5e7eb; color:#374151; font-weight:bold;">
|
|
||||||
{{ $machineName }}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td style="padding:13px 10px; border-bottom:1px solid #e5e7eb; color:#374151;">
|
|
||||||
{{ $record->aufnr }}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td style="padding:13px 10px; border-bottom:1px solid #e5e7eb; color:#374151;">
|
|
||||||
{{ $record->item?->code ?? $record->item_id }}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td style="padding:13px 10px; border-bottom:1px solid #e5e7eb; color:#374151;">
|
|
||||||
{{ $record->gernr }}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td align="center"
|
|
||||||
style="padding:13px 10px; border-bottom:1px solid #e5e7eb;">
|
|
||||||
|
|
||||||
<span style="display:inline-block; background:#fee2e2; color:#b91c1c; padding:5px 10px; border-radius:20px; font-size:11px; font-weight:bold;">
|
|
||||||
STOPPED
|
|
||||||
</span>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td style="padding:13px 10px; border-bottom:1px solid #e5e7eb; color:#374151; white-space: nowrap;">
|
|
||||||
{{ $record->stopped_datetime }}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td style="padding:13px 10px; border-bottom:1px solid #e5e7eb; color:#374151; white-space: nowrap;">
|
|
||||||
{{ $record->stopped_by }}
|
|
||||||
</td>
|
|
||||||
|
|
||||||
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
@endforeach
|
|
||||||
|
|
||||||
</tbody>
|
|
||||||
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<tr>
|
|
||||||
<td style="background:#f8fafc; padding:20px 30px; border-top:1px solid #e5e7eb;">
|
|
||||||
|
|
||||||
<div style="font-size:12px; color:#64748b; text-align:center;">
|
|
||||||
|
|
||||||
This is an automated notification from
|
|
||||||
<strong style="color:#374151;">CRI Digital Manufacturing</strong>.
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
Please take the necessary action regarding the stopped machine.
|
|
||||||
|
|
||||||
<br><br>
|
|
||||||
© {{ date('Y') }} {{ $company }}<br>
|
|
||||||
Automated Laser Marking Stop Alert Mail
|
|
||||||
|
|
||||||
{{-- <span style="color:#94a3b8;">
|
|
||||||
Laser Stop Report • {{ now()->format('d M Y, h:i A') }}
|
|
||||||
</span> --}}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
|
|
||||||
</table>
|
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Plant Name</td>
|
||||||
|
<td style="text-align: center;">{{ $request->plant->name ?? $request->plant_id }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Work Center</td>
|
||||||
|
<td style="text-align: center;">{{ $request->machine->work_center ?? $request->machine_id }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Machine Name</td>
|
||||||
|
<td style="text-align: center;">{{ $tempstop['machine_name'] }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Item Code</td>
|
||||||
|
<td style="text-align: center;">{{ $request->item->code ?? $request->code }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Description</td>
|
||||||
|
<td style="text-align: center;">{{ $request->item->description ?? $request->description }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Job Number</td>
|
||||||
|
<td style="text-align: center;">{{ $request->aufnr }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Serial Number</td>
|
||||||
|
<td style="text-align: center;">{{ $request->gernr }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>ZMM Heading</td>
|
||||||
|
<td style="text-align: center;">{{ $tempstop['zmm_heading'] }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Model Type</td>
|
||||||
|
<td style="text-align: center;">{{ $request->model_type }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>SL Logged Name</td>
|
||||||
|
<td style="text-align: center;">{{ $tempstop['samlight_logged_name'] }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Work Flow ID</td>
|
||||||
|
<td style="text-align: center;">{{ $request->work_flow_id }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Stopped By</td>
|
||||||
|
<td style="text-align: center;">{{ $tempstop['stopped_by'] }}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<br>
|
||||||
|
<table style="margin-left: 3%" border="1" width="50%" cellpadding="4" cellspacing="0">
|
||||||
|
<tr>
|
||||||
|
<th>Approver Name</th>
|
||||||
|
<th>Approve Status</th>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
@if($level == 2)
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;">{{ $approverNameFromMaster->name1 }}</td>
|
||||||
|
<td style="text-align: center;">{{ ucfirst($pendingApprovers->approver_status1 ?? '-') }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;">{{ $approverName }}</td>
|
||||||
|
<td style="text-align: center;">
|
||||||
|
<a href="{{ $approveUrl }}" style="color: #28a745; font-weight: bold; text-decoration: underline;">Approve</a>
|
||||||
|
{{-- |
|
||||||
|
<a href="{{ $holdUrl }}" style="color: #FF8800; font-weight: bold; text-decoration: underline;">Hold</a>
|
||||||
|
|
|
||||||
|
<a href="{{ $rejectUrl }}" style="color: #dc3545; font-weight: bold; text-decoration: underline;">Reject</a> --}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@elseif ($level == 3)
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;">{{ $approverNameFromMaster->name1 }}</td>
|
||||||
|
<td style="text-align: center;">{{ ucfirst($pendingApprovers->approver_status1 ?? '-') }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;">{{ $approverNameFromMaster->name2 }}</td>
|
||||||
|
<td style="text-align: center;">{{ ucfirst($pendingApprovers->approver_status2 ?? '-') }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;">{{ $approverName }}</td>
|
||||||
|
<td style="text-align: center;">
|
||||||
|
<a href="{{ $approveUrl }}" style="color: #28a745; font-weight: bold; text-decoration: underline;">Approve</a>
|
||||||
|
|
|
||||||
|
{{-- <a href="{{ $holdUrl }}" style="color: #FF8800; font-weight: bold; text-decoration: underline;">Hold</a>
|
||||||
|
| --}}
|
||||||
|
{{-- <a href="{{ $rejectUrl }}" style="color: #dc3545; font-weight: bold; text-decoration: underline;">Reject</a> --}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@else
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;">{{ $approverName }}</td>
|
||||||
|
<td style="text-align: center;">
|
||||||
|
<a href="{{ $approveUrl }}" style="color: #28a745; font-weight: bold; text-decoration: underline;">Approve</a>
|
||||||
|
{{-- |
|
||||||
|
<a href="{{ $holdUrl }}" style="color: #FF8800; font-weight: bold; text-decoration: underline;">Hold</a>
|
||||||
|
|
|
||||||
|
<a href="{{ $rejectUrl }}" style="color: #dc3545; font-weight: bold; text-decoration: underline;">Reject</a> --}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
@endif
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
<p>{!! $wishes !!}</p>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -17,42 +17,6 @@ Route::get('/', function () {
|
|||||||
return redirect('/admin');
|
return redirect('/admin');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Route::get('/admin', function () {
|
|
||||||
// return redirect('/admin/welcome');
|
|
||||||
// });
|
|
||||||
|
|
||||||
// Route::get('/password-reset/approve/{token}', function ($token) {
|
|
||||||
|
|
||||||
// // $workerId = cache()->pull("password-reset-approval-{$token}");
|
|
||||||
|
|
||||||
// $workerId = cache()->get("password-reset-approval-{$token}");
|
|
||||||
|
|
||||||
// if (! $workerId) {
|
|
||||||
// return response()->view('errors.password-reset-expired', [], 410);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// $worker = User::findOrFail($workerId);
|
|
||||||
|
|
||||||
|
|
||||||
// $resetToken = Password::broker()->createToken($worker);
|
|
||||||
|
|
||||||
|
|
||||||
// $resetUrl = URL::temporarySignedRoute(
|
|
||||||
// 'filament.admin.auth.password-reset.reset',
|
|
||||||
// Carbon::now()->addMinutes(60),
|
|
||||||
// [
|
|
||||||
// 'email' => $worker->email,
|
|
||||||
// 'token' => $resetToken,
|
|
||||||
// ]
|
|
||||||
// );
|
|
||||||
|
|
||||||
|
|
||||||
// return redirect()->to($resetUrl);
|
|
||||||
|
|
||||||
// })->middleware('signed')->name('password-reset.approve');
|
|
||||||
|
|
||||||
//..
|
|
||||||
|
|
||||||
Route::get('/sticker/preview/{path}', function ($path) {
|
Route::get('/sticker/preview/{path}', function ($path) {
|
||||||
$file = storage_path('app/' . $path);
|
$file = storage_path('app/' . $path);
|
||||||
|
|
||||||
@@ -101,6 +65,21 @@ Route::get('/approval/approve-success', function () {
|
|||||||
return view('approval.approve-success');
|
return view('approval.approve-success');
|
||||||
})->name('approval.approve.success');
|
})->name('approval.approve.success');
|
||||||
|
|
||||||
|
//..Laser Stop Approval
|
||||||
|
|
||||||
|
Route::get('/laser/stop/approve', [CharacteristicApprovalController::class, 'laserApproveForm'])
|
||||||
|
->name('laser.approve')
|
||||||
|
->middleware('signed');
|
||||||
|
|
||||||
|
Route::post('/laser/approve-save', [CharacteristicApprovalController::class, 'laserApproveSave'])
|
||||||
|
->name('laser.approve.save');
|
||||||
|
|
||||||
|
Route::get('/laser/stop/approval/approve-success', function () {
|
||||||
|
return view('approval.laser-approve-success');
|
||||||
|
})->name('approval.laser.approve.success');
|
||||||
|
|
||||||
|
//..
|
||||||
|
|
||||||
Route::get('/production-orders/print/{production_order}',
|
Route::get('/production-orders/print/{production_order}',
|
||||||
[ProductionOrderController::class, 'print']
|
[ProductionOrderController::class, 'print']
|
||||||
)->name('production-orders.print');
|
)->name('production-orders.print');
|
||||||
|
|||||||
Reference in New Issue
Block a user