diff --git a/app/Console/Commands/SendLaserStopReport.php b/app/Console/Commands/SendLaserStopReport.php index 5407051..4dc53e5 100644 --- a/app/Console/Commands/SendLaserStopReport.php +++ b/app/Console/Commands/SendLaserStopReport.php @@ -2,12 +2,18 @@ namespace App\Console\Commands; +use App\Mail\LaserStopMail; use App\Mail\LaserStopReportMail; +use App\Models\CharacteristicApproverMaster; use App\Models\ClassCharacteristic; use App\Models\Machine; use App\Models\Plant; +use App\Models\RequestCharacteristic; +use App\Models\TempStopCharacteristic; use Illuminate\Console\Command; use Illuminate\Support\Facades\Mail; +use Illuminate\Support\Facades\Schema; +use Illuminate\Support\Carbon; class SendLaserStopReport extends Command { @@ -16,7 +22,7 @@ class SendLaserStopReport extends Command * * @var string */ - protected $signature = 'send:laser-stop-report {schedule_type} {plant} {machine_id}'; + protected $signature = 'approval:laser-stop'; /** * The console command description. @@ -25,89 +31,194 @@ class SendLaserStopReport extends Command */ protected $description = 'Command description'; + public $subjectLine; + + // public $tempCharacteristics = []; + + public $wfId; + /** * Execute the console command. */ public function handle() { - $scheduleType = $this->argument('schedule_type'); - $plantId = (int) $this->argument('plant'); - $machineId = (int) $this->argument('machine_id'); + $this->info('Approval mail job started'); - $mailRules = \App\Models\AlertMailRule::where('module', 'LaserStopAlert') - ->where('rule_name', 'LaserStopAlertMail') - ->where('schedule_type', $scheduleType) - ->where('plant', $plantId) - ->where('machine_id', $machineId) + // .. Laser Stop Mail trigger logic + + $stoppedRecords = RequestCharacteristic::where(function ($q) { + $q->whereNull('approver_status1') + ->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(); - $emails = $mailRules - ->pluck('email') - ->filter() - ->flatMap(function ($email) { - return array_map('trim', explode(',', $email)); - }) - ->unique() - ->values() - ->toArray(); + $stoppedRecords = $stoppedRecords->filter(function ($item) { + $approver = CharacteristicApproverMaster::find($item->characteristic_approver_master_id); + return $approver && $approver->approver_type == 'Stop'; + }); - $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.'); + if ($stoppedRecords->isEmpty()) { + $this->info('No laser stop pending approvals'); 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); - - $machineName = $machine?->work_center ?? $machineId; - - $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; + $approverNameFromMaster = null; + if ($pendingApprovers && $pendingApprovers->characteristic_approver_master_id) { + $approverNameFromMaster = CharacteristicApproverMaster::find($pendingApprovers->characteristic_approver_master_id); } - $recordIds = $records->pluck('id'); + $rows = []; - // Send mail to mapped email IDs - Mail::to($emails) - ->cc($ccEmails) - ->send( - new LaserStopReportMail( - $records, - $plantId, - $machineId, - $plantName, - $machineName, + foreach ($grouped as $groupRecords) { + + $first = $groupRecords->first(); + + $approver = CharacteristicApproverMaster::where('plant_id', $first->plant_id) + ->where('machine_id', $first->machine_id) + ->where('id', $first->characteristic_approver_master_id) + ->first(); + + 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) - ->update([ - 'is_stopped' => 1, - ]); + RequestCharacteristic::whereIn('id', $groupRecords->pluck('id')) + ->update($updateData); - $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; } } diff --git a/app/Http/Controllers/CharacteristicApprovalController.php b/app/Http/Controllers/CharacteristicApprovalController.php index 7a5fb3e..13ada9e 100644 --- a/app/Http/Controllers/CharacteristicApprovalController.php +++ b/app/Http/Controllers/CharacteristicApprovalController.php @@ -424,6 +424,93 @@ class CharacteristicApprovalController extends Controller 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() { // diff --git a/app/Mail/LaserStopMail.php b/app/Mail/LaserStopMail.php index 2916470..e249d4b 100644 --- a/app/Mail/LaserStopMail.php +++ b/app/Mail/LaserStopMail.php @@ -8,28 +8,40 @@ use Illuminate\Mail\Mailable; use Illuminate\Mail\Mailables\Content; use Illuminate\Mail\Mailables\Envelope; use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Facades\URL; class LaserStopMail extends Mailable { use Queueable, SerializesModels; - public $records; - public $plantId; - public $machineId; - public $plantName; + public $request; + public $approverName; + public $level; + public $tableData; - public $machineName; + public $pendingApprovers; + + public $approverNameFromMaster; + + public $subjectLine; + + public $characteristics; + + public $stopDetails; /** * 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->plantId = $plantId; - $this->machineId = $machineId; - $this->plantName = $plantName; - $this->machineName = $machineName; + $this->request = $request; + $this->approverName = $approverName; + $this->level = $level; + $this->pendingApprovers = $pendingApprovers; + $this->approverNameFromMaster = $approverNameFromMaster; + $this->subjectLine = $subjectLine; + $this->tableData = $characteristics; + $this->stopDetails = $stopDetails; } /** @@ -38,7 +50,7 @@ class LaserStopMail extends Mailable public function envelope(): 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 { - $greeting = 'Dear Sir'; return new Content( - view: 'mail.laser-stop-final-report', + view: 'mail.laser-stop-report', with: [ - 'company' => 'CRI Digital Manufacturing Solutions', - 'greeting' => $greeting, - 'wishes' => 'Thanks & Regards,
CRI Digital Manufacturing Solutions', - ], + 'company' => 'CRI Digital Manufacturing Solutions', + 'greeting' => 'Dear ' . $this->approverName . ',', + '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,
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. * diff --git a/resources/views/approval/laser-approve-success.blade.php b/resources/views/approval/laser-approve-success.blade.php new file mode 100644 index 0000000..107143a --- /dev/null +++ b/resources/views/approval/laser-approve-success.blade.php @@ -0,0 +1,77 @@ + + + + Approval + + + + +
+
🟢 Approved Successfully
+

Your request has been approved.

+ + + +
+ + + + diff --git a/resources/views/mail/laser-stop-report.blade.php b/resources/views/mail/laser-stop-report.blade.php index e5a1426..ef5c7b9 100644 --- a/resources/views/mail/laser-stop-report.blade.php +++ b/resources/views/mail/laser-stop-report.blade.php @@ -1,240 +1,137 @@ - + - - - Laser Marking Stopped Report + {{-- Invoice Data Report --}} + - +
+ {{ $company }} +
+
+

{!! $greeting !!}

- +
- + + + + + {{-- --}} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
-
- CRI Digital Manufacturing -
- -
- Laser Marking Stopped Alert -
- -
- Laser marking machine stoppage notification -
-
-
- ! -
-
- -
- -
- -
- âš  Laser Marking Stop Detected -
- -
- The following laser marking stopped records require your attention. -
- -
- -
- -
- Stopped Machine Records -
- -
- Total records: {{ $records->count() }} -
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @foreach($records as $index => $record) - - - - - - - - - - - - - - - - - - - - - - - - - @endforeach - - - -
- No - - Plant - - Machine - - Production Order - - Item Code - - Serial Number - - Status - - Stopped At - - Stopped By -
- {{ $index + 1 }} - - {{ $plantName }} - - {{ $machineName }} - - {{ $record->aufnr }} - - {{ $record->item?->code ?? $record->item_id }} - - {{ $record->gernr }} - - - - STOPPED - - - - {{ $record->stopped_datetime }} - - {{ $record->stopped_by }} -
- -
- -
- - This is an automated notification from - CRI Digital Manufacturing. - -
- - Please take the necessary action regarding the stopped machine. - -

- © {{ date('Y') }} {{ $company }}
- Automated Laser Marking Stop Alert Mail - - {{-- - Laser Stop Report • {{ now()->format('d M Y, h:i A') }} - --}} - -
- -
- +
TitleDetails
Stopped Date Time{{ $tempstop['stopped_at']->format('d-m-Y H:i:s') }} + {{ $tempstop['stopped_at'] + ? \Carbon\Carbon::parse($tempstop['stopped_at'])->format('d-m-Y H:i:s') + : '' }}
Plant Name{{ $request->plant->name ?? $request->plant_id }}
Work Center{{ $request->machine->work_center ?? $request->machine_id }}
Machine Name{{ $tempstop['machine_name'] }}
Item Code{{ $request->item->code ?? $request->code }}
Description{{ $request->item->description ?? $request->description }}
Job Number{{ $request->aufnr }}
Serial Number{{ $request->gernr }}
ZMM Heading{{ $tempstop['zmm_heading'] }}
Model Type{{ $request->model_type }}
SL Logged Name{{ $tempstop['samlight_logged_name'] }}
Work Flow ID{{ $request->work_flow_id }}
Stopped By{{ $tempstop['stopped_by'] }}
+
+ + + + + + + @if($level == 2) + + + + + + + + + @elseif ($level == 3) + + + + + + + + + + + + + @else + + + + + + @endif
Approver NameApprove Status
{{ $approverNameFromMaster->name1 }}{{ ucfirst($pendingApprovers->approver_status1 ?? '-') }}
{{ $approverName }} + Approve + {{--     |     + Hold +     |     + Reject --}} +
{{ $approverNameFromMaster->name1 }}{{ ucfirst($pendingApprovers->approver_status1 ?? '-') }}
{{ $approverNameFromMaster->name2 }}{{ ucfirst($pendingApprovers->approver_status2 ?? '-') }}
{{ $approverName }} + Approve +     |     + {{-- Hold +     |     --}} + {{-- Reject --}} +
{{ $approverName }} + Approve + {{--     |     + Hold +     |     + Reject --}} +
+

{!! $wishes !!}

+ diff --git a/routes/web.php b/routes/web.php index e33905e..9ab9f7b 100644 --- a/routes/web.php +++ b/routes/web.php @@ -17,42 +17,6 @@ Route::get('/', function () { 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) { $file = storage_path('app/' . $path); @@ -101,6 +65,21 @@ Route::get('/approval/approve-success', function () { return view('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}', [ProductionOrderController::class, 'print'] )->name('production-orders.print');