Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Has been cancelled
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Has been cancelled
Laravel Larastan / larastan (pull_request) Has been cancelled
Laravel Pint / pint (pull_request) Has been cancelled
417 lines
14 KiB
PHP
417 lines
14 KiB
PHP
<?php
|
|
|
|
namespace App\Filament\Resources\StickerValidationResource\Pages;
|
|
|
|
use App\Filament\Resources\StickerValidationResource;
|
|
use App\Models\Item;
|
|
use App\Models\ItemCharacteristic;
|
|
use App\Models\ProductionQuantity;
|
|
use App\Models\StickerDetail;
|
|
use App\Models\StickerMappingMaster;
|
|
use App\Models\StickerStructureDetail;
|
|
use App\Models\StickerValidation;
|
|
use App\Services\StickerPdfService;
|
|
use Filament\Actions;
|
|
use Filament\Facades\Filament;
|
|
use Filament\Notifications\Notification;
|
|
use Filament\Resources\Pages\CreateRecord;
|
|
|
|
class CreateStickerValidation extends CreateRecord
|
|
{
|
|
protected static string $resource = StickerValidationResource::class;
|
|
|
|
protected static string $view = 'filament.resources.sticker-validation-resource.create-sticker-validation';
|
|
|
|
public $ref_number;
|
|
|
|
public $plantId;
|
|
|
|
public $workCenter;
|
|
|
|
public $serNo;
|
|
|
|
public function getFormActions(): array
|
|
{
|
|
return [
|
|
$this->getCancelFormAction(),
|
|
];
|
|
}
|
|
|
|
protected function getRedirectUrl(): string
|
|
{
|
|
return $this->getResource()::getUrl('create');
|
|
}
|
|
|
|
|
|
public function processProOrder($value)
|
|
{
|
|
$plantId = $this->form->getState()['plant_id'];
|
|
|
|
$this->plantId = $plantId;
|
|
|
|
$this->ref_number = $value;
|
|
|
|
$this->dispatch('refreshEmptySticker', $plantId, $value);
|
|
|
|
$this->dispatch('focus-serial-number');
|
|
}
|
|
|
|
public function processSno($serNo)
|
|
{
|
|
$plantId = $this->form->getState()['plant_id'];
|
|
|
|
$this->plantId = $plantId;
|
|
|
|
$workCenter = $this->form->getState()['machine_id'];
|
|
|
|
$this->workCenter = $workCenter;
|
|
|
|
$this->ref_number = $this->form->getState()['production_order'];
|
|
|
|
$this->serNo = $serNo;
|
|
|
|
$user = Filament::auth()->user();
|
|
|
|
$operatorName = $user->name;
|
|
|
|
if (! preg_match('/^([a-zA-Z0-9]{6,})\|([1-9][a-zA-Z0-9]{8,})\|?$/', $this->serNo, $matches)) {
|
|
Notification::make()
|
|
->danger()
|
|
->title('Invalid Serial QR Format')
|
|
->body('Scan valid Serial QR code proceed!<br>Sample formats are:<br>123456|1234567890123| OR 123456|1234567890123')
|
|
->seconds(3)
|
|
->send();
|
|
|
|
$this->dispatch('playWarnSound');
|
|
|
|
$this->form->fill([
|
|
'plant_id' => $this->plantId,
|
|
'machine_id' => $this->workCenter,
|
|
'production_order' => $this->ref_number,
|
|
'serial_number' => null,
|
|
]);
|
|
|
|
$this->dispatch('focus-serial-number');
|
|
|
|
return;
|
|
}
|
|
else {
|
|
$itemCode = $matches[1];
|
|
$serialNumber = $matches[2];
|
|
|
|
$recFound = ProductionQuantity::where('plant_id', $this->plantId)
|
|
->where('production_order', $this->ref_number)
|
|
->where('serial_number', $serialNumber)
|
|
->first();
|
|
|
|
if(!$recFound){
|
|
Notification::make()
|
|
->danger()
|
|
->title('Unknown Serial Number')
|
|
->body("Scanned serial number '$serialNumber' not found for the given plant and production order")
|
|
->seconds(3)
|
|
->send();
|
|
$this->form->fill([
|
|
'plant_id' => $this->plantId,
|
|
'machine_id' => $this->workCenter,
|
|
'production_order' => $this->ref_number,
|
|
'serial_number' => null,
|
|
]);
|
|
return;
|
|
}
|
|
|
|
$duplicate = StickerValidation::where('plant_id', $this->plantId)
|
|
->where('production_order', $this->ref_number)
|
|
->where('serial_number', $serialNumber)
|
|
->first();
|
|
|
|
if ($duplicate) {
|
|
Notification::make()
|
|
->danger()
|
|
->title('Duplicate Serial Number')
|
|
->body("Serial number $serialNumber already exists for this plant and production order!")
|
|
->seconds(3)
|
|
->send();
|
|
|
|
$this->form->fill([
|
|
'plant_id' => $this->plantId,
|
|
'machine_id' => $this->workCenter,
|
|
'production_order' => $this->ref_number,
|
|
'serial_number' => null,
|
|
]);
|
|
return;
|
|
}
|
|
|
|
$itemC = Item::where('code', $itemCode)
|
|
->where('plant_id',$this->plantId)
|
|
->first();
|
|
|
|
$itemId = $itemC->id;
|
|
|
|
$item = ItemCharacteristic::where('item_id', $itemId)
|
|
->where('plant_id',$this->plantId)
|
|
->first();
|
|
|
|
$itemI = $item->id;
|
|
|
|
$mapping = StickerMappingMaster::where('plant_id', $this->plantId)
|
|
->where('item_characteristic_id', $itemI)
|
|
->first();
|
|
|
|
if (!$mapping) {
|
|
Notification::make()
|
|
->danger()
|
|
->title('Sticker Mapping Not Found')
|
|
->body("No sticker mapping found for this item and plant.")
|
|
->send();
|
|
return;
|
|
}
|
|
|
|
$stickers = [];
|
|
|
|
for ($i = 1; $i <= 8; $i++) {
|
|
$machineColumn = "sticker{$i}_machine_id";
|
|
$ipColumn = "sticker{$i}_print_ip";
|
|
$stickerColumn = "sticker_structure{$i}_id";
|
|
$itemColumn = "item_characteristic_id";
|
|
|
|
if (
|
|
!empty($mapping->$machineColumn) &&
|
|
!empty($mapping->$stickerColumn)
|
|
) {
|
|
$stickers[] = [
|
|
'machine_id' => $mapping->$machineColumn,
|
|
'sticker_id' => $mapping->$stickerColumn,
|
|
'item_characteristic' => $mapping->$itemColumn,
|
|
'print_ip' => $mapping->$ipColumn,
|
|
];
|
|
}
|
|
}
|
|
|
|
if (empty($stickers)) {
|
|
Notification::make()
|
|
->danger()
|
|
->title('No Sticker Configuration Found')
|
|
->body('No sticker and machine mappings configured for this item and plant.')
|
|
->send();
|
|
return;
|
|
}
|
|
|
|
StickerValidation::create([
|
|
'plant_id' => $this->plantId,
|
|
'machine_id' => $this->workCenter,
|
|
'production_order' => $this->ref_number ?? null,
|
|
'serial_number' => $serialNumber,
|
|
'status' => 'Printed',
|
|
// 'sticker_id' => $matchedSticker,
|
|
'created_by' => $operatorName,
|
|
'created_at' => now(),
|
|
'updated_at' => now(),
|
|
]);
|
|
|
|
Notification::make()
|
|
->success()
|
|
->title('Sticker Recorded')
|
|
->body("Item: $itemCode, Serial: $serialNumber recorded successfully!")
|
|
->seconds(3)
|
|
->send();
|
|
|
|
$this->form->fill([
|
|
'plant_id' => $this->plantId,
|
|
'machine_id' => $this->workCenter,
|
|
'production_order' => $this->ref_number,
|
|
'serial_number' => null,
|
|
]);
|
|
|
|
$this->dispatch('refreshEmptySticker', $plantId, $this->ref_number);
|
|
|
|
|
|
// foreach ($stickers as $sticker) {
|
|
|
|
// // $printerName = $this->getCupsPrinterNameByIp($sticker['print_ip']);
|
|
|
|
// \Log::info("Looking up printer for IP: " . $sticker['print_ip']);
|
|
// $printerName = $this->getCupsPrinterNameByIp($sticker['print_ip']);
|
|
// \Log::info("Found printer: " . ($printerName ?? 'NULL'));
|
|
|
|
// if (! $printerName) {
|
|
// Notification::make()
|
|
// ->danger()
|
|
// ->title('Printer Not Found')
|
|
// ->body("No CUPS printer configured for IP: {$sticker['print_ip']}")
|
|
// ->send();
|
|
// return;
|
|
// }
|
|
|
|
// $structure = StickerStructureDetail::findOrFail($sticker['sticker_id']);
|
|
// $itemCharacteristic = ItemCharacteristic::where('plant_id', $this->plantId)
|
|
// ->where('id', $sticker['item_characteristic'])
|
|
// ->firstOrFail();
|
|
|
|
// $dynamicElements = StickerDetail::where(
|
|
// 'sticker_structure_detail_id',
|
|
// $structure->id
|
|
// )->where('element_type', 'Dynamic')->get();
|
|
|
|
|
|
|
|
// /** STEP 3: Stream PDF to CUPS (STDIN) */
|
|
// $process = proc_open(
|
|
// 'lp -d ' . escapeshellarg($printerName) . ' -o fit-to-page -',
|
|
// [
|
|
// ['pipe', 'r'], // STDIN
|
|
// ['pipe', 'w'], // STDOUT
|
|
// ['pipe', 'w'], // STDERR
|
|
// ],
|
|
// $pipes
|
|
// );
|
|
|
|
|
|
// if (! is_resource($process)) {
|
|
// Notification::make()
|
|
// ->danger()
|
|
// ->title('Print Failed')
|
|
// ->body('Unable to start CUPS print process.')
|
|
// ->send();
|
|
// return;
|
|
// // continue;
|
|
// }
|
|
|
|
// $pdfContent = (new StickerPdfService())->generatePdf1(
|
|
// $structure->sticker_id,
|
|
// $dynamicElements,
|
|
// $itemCharacteristic,
|
|
// $serialNumber,
|
|
// $serNo
|
|
// );
|
|
|
|
// fwrite($pipes[0], $pdfContent);
|
|
// fclose($pipes[0]);
|
|
|
|
// $stderr = stream_get_contents($pipes[2]);
|
|
// fclose($pipes[1]);
|
|
// fclose($pipes[2]);
|
|
|
|
// $status = proc_close($process);
|
|
|
|
// if ($status != 0) {
|
|
// Notification::make()
|
|
// ->danger()
|
|
// ->title('Print Failed')
|
|
// ->body("CUPS error: {$stderr}")
|
|
// ->send();
|
|
// return;
|
|
// }
|
|
// }
|
|
|
|
|
|
foreach ($stickers as $sticker)
|
|
{
|
|
|
|
\Log::info("Looking up printer for IP: " . $sticker['print_ip']);
|
|
|
|
$printerName = $this->getCupsPrinterNameByIp($sticker['print_ip']);
|
|
|
|
\Log::info("Found printer: " . ($printerName ?? 'NULL'));
|
|
|
|
if (! $printerName) {
|
|
Notification::make()
|
|
->danger()
|
|
->title('Printer Not Found')
|
|
->body("No CUPS printer configured for IP: {$sticker['print_ip']}")
|
|
->send();
|
|
return;
|
|
}
|
|
|
|
$structure = StickerStructureDetail::findOrFail($sticker['sticker_id']);
|
|
|
|
$itemCharacteristic = ItemCharacteristic::where('plant_id', $this->plantId)
|
|
->where('id', $sticker['item_characteristic'])
|
|
->firstOrFail();
|
|
|
|
$dynamicElements = StickerDetail::where(
|
|
'sticker_structure_detail_id',
|
|
$structure->id
|
|
)->where('element_type', 'Dynamic')->get();
|
|
|
|
$pdfContent = (new StickerPdfService())->generatePdf1(
|
|
$structure->sticker_id,
|
|
$dynamicElements,
|
|
$itemCharacteristic,
|
|
$serialNumber,
|
|
$serNo
|
|
);
|
|
|
|
$tempPdfPath = storage_path('app/temp_sticker_' . uniqid() . '.pdf');
|
|
file_put_contents($tempPdfPath, $pdfContent);
|
|
|
|
exec(
|
|
"lp -d " . escapeshellarg($printerName) . " " . escapeshellarg($tempPdfPath),
|
|
$output,
|
|
$status
|
|
);
|
|
|
|
\Log::info("LP Output:", $output);
|
|
\Log::info("LP Status: " . $status);
|
|
|
|
if ($status != 0) {
|
|
Notification::make()
|
|
->danger()
|
|
->title('Print Failed')
|
|
->body("CUPS error while printing.")
|
|
->send();
|
|
|
|
if (file_exists($tempPdfPath)) {
|
|
unlink($tempPdfPath);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if (file_exists($tempPdfPath)) {
|
|
unlink($tempPdfPath);
|
|
}
|
|
}
|
|
|
|
Notification::make()
|
|
->success()
|
|
->title('Sticker Printed')
|
|
->body("Sticker for Serial Number: $serialNumber printed successfully!")
|
|
->seconds(3)
|
|
->send();
|
|
|
|
// [$itemCode, $serialNumber] = explode('|', $serNo);
|
|
|
|
// $this->dispatch('open-sticker-pdf', [
|
|
// 'url' => url("/sticker/pdf/{$itemCode}/{$serialNumber}/$this->plantId/$this->ref_number")
|
|
// ]);
|
|
|
|
}
|
|
}
|
|
|
|
protected function getCupsPrinterNameByIp(string $ip): ?string
|
|
{
|
|
|
|
// exec('lpstat -v 2>&1', $output, $status);
|
|
|
|
exec('lpstat -h cups:631 -v 2>&1', $output, $status);
|
|
|
|
if ($status != 0 || empty($output)) {
|
|
return null;
|
|
}
|
|
|
|
foreach ($output as $line){
|
|
$parts = explode(':', $line, 2);
|
|
if (count($parts) < 2) continue;
|
|
|
|
$printerName = trim(str_replace('device for', '', $parts[0]));
|
|
$deviceUri = trim($parts[1]);
|
|
|
|
if (str_contains($deviceUri, $ip)) {
|
|
return $printerName;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|