Files
pds/app/Filament/Pages/BulkStickerPrinting.php
dhanabalan db76793c83
Some checks failed
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Has been cancelled
Gemini PR Review / Gemini PR Review (pull_request) Failing after 16s
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (pull_request) Successful in 12s
Laravel Pint / pint (pull_request) Successful in 3m45s
Laravel Larastan / larastan (pull_request) Failing after 5m28s
Added bulk sticker printing page
2026-09-10 17:42:45 +05:30

1052 lines
35 KiB
PHP

<?php
namespace App\Filament\Pages;
use App\Models\Item;
use App\Models\ItemCharacteristic;
use App\Models\Machine;
use App\Models\Plant;
use App\Models\ProductionOrder;
use App\Models\StickerDetail;
use App\Models\StickerMappingMaster;
use App\Models\StickerStructureDetail;
use App\Models\StickerValidation;
use App\Services\StickerPdfService;
use Filament\Facades\Filament;
use Filament\Forms\Components\Hidden;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Illuminate\Support\Facades\Auth;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Form;
use Filament\Forms\Components\Section;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
class BulkStickerPrinting extends Page implements HasForms
{
protected static ?string $navigationIcon = 'heroicon-o-document-text';
protected static string $view = 'filament.pages.bulk-sticker-printing';
protected static ?string $navigationGroup = 'Customized Sticker Printing';
public array $filters = [];
public $serNo;
public $ref_number;
//public $workCenter;
public function form(Form $form): Form
{
return $form
->statePath('filters')
->schema([
Section::make('')
->schema([
Select::make('plant_id')
->label('Plant')
->reactive()
->options(function(){
$plantId = Filament::auth()->user()->plant_id;
return $plantId
? Plant::where('id',$plantId)
->pluck('name','id')
: Plant::pluck('name','id');
})
->required(),
Select::make('machine_id')
->label('Work Center')
->reactive()
->options(function(callable $get){
$plantId = $get('plant_id');
if (empty($plantId)) {
return [];
}
return Machine::where('plant_id', $plantId)->pluck('work_center', 'id');
})
->afterStateUpdated(function ($state, callable $set) {
$set('production_order', null);
$set('from_serial_number', null);
$set('to_serial_number', null);
$set('sticker_options', []);
})
->required(),
TextInput::make('production_order')
->label('Production Order')
->reactive()
->required()
->afterStateUpdated(function ($state, callable $set, $get) {
for ($i = 1; $i <= 8; $i++) {
$set("sticker_structure{$i}_id", null);
}
if (blank($state)) {
return;
}
$machineId = $get('machine_id');
if (empty($machineId)) {
Notification::make()
->title('Work Center not selected')
->body('Please select a Work Center first.')
->warning()
->send();
return;
}
$productionOrder = ProductionOrder::where('production_order', $state)
->first();
if (! $productionOrder) {
Notification::make()
->title('Production Order not found')
->body("Production Order '{$state}' was not found.")
->danger()
->send();
return;
}
$plantId = $productionOrder->plant_id;
$itemId = $productionOrder->item_id;
$item = Item::find($itemId);
if (! $item) {
Notification::make()
->title('Item not found')
->body("Item ID '{$itemId}' was not found in item master.")
->danger()
->send();
return;
}
$itemCode = $item->code;
$item = Item::where('code', $itemCode)->where('plant_id', $plantId)->first();
if (! $item) {
Notification::make()
->title('Item not found')
->body("Item '{$itemCode}' was not found for the selected plant.")
->danger()
->send();
return;
}
$itemCharacteristic = ItemCharacteristic::where('plant_id', $plantId)->where('item_id', $item->id)->first();
if (! $itemCharacteristic) {
Notification::make()
->title('Item characteristic not found')
->body("No item characteristic found for item '{$itemCode}'.")
->danger()
->send();
return;
}
$itemCharacteristicId = $itemCharacteristic->id;
$stickerMappings = StickerMappingMaster::where('plant_id', $plantId)
->where('item_characteristic_id', $itemCharacteristicId)
->get();
if (! $stickerMappings) {
Notification::make()
->title('Sticker mapping not found')
->body("No sticker mapping found for this plant and item characteristic.")
->danger()
->send();
return;
}
$stickerOptions = [];
// foreach ($stickerMappings as $stickerMapping) {
// for ($i = 1; $i <= 8; $i++) {
// $stickerStructureId = $stickerMapping->{"sticker_structure{$i}_id"};
// if ($stickerStructureId) {
// $detail = StickerStructureDetail::where('id', $stickerStructureId)
// ->first();
// if ($detail && $detail->sticker_id) {
// $stickerOptions[$detail->sticker_id] = $detail->sticker_id;
// }
// }
// }
// }
foreach ($stickerMappings as $stickerMapping) {
for ($i = 1; $i <= 8; $i++) {
$machineColumn = "sticker{$i}_machine_id";
$stickerMachineId = $stickerMapping->$machineColumn;
if ((string) $stickerMachineId != (string) $machineId) {
continue;
}
$structureColumn = "sticker_structure{$i}_id";
$stickerStructureId = $stickerMapping->$structureColumn;
if (empty($stickerStructureId)) {
continue;
}
$detail = StickerStructureDetail::find($stickerStructureId);
if ($detail && $detail->sticker_id) {
$stickerOptions[$detail->sticker_id] =
$detail->sticker_id;
}
$set("sticker_structure{$i}_id", $stickerStructureId);
}
}
$set('sticker_options', $stickerOptions);
}),
Select::make('sticker_id')
->label('Sticker ID')
->options(fn (callable $get) => $get('sticker_options') ?? [])
->reactive()
->afterStateUpdated(function ($state, callable $set) {
if (blank($state)) {
return;
}
$sticker = StickerStructureDetail::where('sticker_id', $state)->first();
if (! $sticker) {
Notification::make()
->title('Sticker not found')
->body("Sticker ID '{$state}' was not found.")
->danger()
->send();
return;
}
$set('sticker_code', $state);
}),
Hidden::make('sticker_options')
->default([]),
TextInput::make('from_serial_number')
->label('From Serial Number')
->reactive(),
TextInput::make('to_serial_number')
->label('To Serial Number')
->reactive(),
])
->columns(6),
]);
}
public function processSnoNo($qrcode)
{
$parts = explode('|', $qrcode, 2);
$itemCode = $parts[0] ?? null;
$serialNumber = $parts[1] ?? null;
$plantId = $this->form->getState()['plant_id'];
$plantId = trim($plantId) ?? null;
$workCenter = $this->form->getState()['machine_id'];
$prodOrderNo= $this->form->getState()['production_order'];
$prodOrderNo = trim($prodOrderNo) ?? null;
if (!$qrcode || !preg_match('/^\d+\|\d+$/', $qrcode)) {
Notification::make()
->title('Invalid QR Code')
->body('QR code format should be like: 123456|12456456464')
->danger()
->send();
$this->form->fill([
'plant_id' => $plantId,
'machine_id' => $workCenter,
'production_order' => $prodOrderNo,
'serial_number' => null,
]);
return;
}
elseif (!preg_match('/^[A-Za-z0-9]+$/', $itemCode)) {
Notification::make()
->title('Invalid Item Code')
->body('Item code should contain only alpha-numeric values.')
->danger()
->send();
$this->form->fill([
'plant_id' => $plantId,
'machine_id' => $workCenter,
'production_order' => $prodOrderNo,
'serial_number' => null,
]);
return;
}
elseif (!preg_match('/^[A-Za-z0-9]+$/', $serialNumber)) {
Notification::make()
->title('Invalid Serial Number')
->body('Serial number should contain only alpha-numeric values.')
->danger()
->send();
$this->form->fill([
'plant_id' => $plantId,
'machine_id' => $workCenter,
'production_order' => $prodOrderNo,
'serial_number' => null,
]);
return;
}
$plant = Plant::find($plantId);
$plantName = $plant ? $plant->name : null;
$pOrderExist = ProductionOrder::where('plant_id', $plantId)
->where('production_order', $prodOrderNo)
->first();
if(!$pOrderExist){
Notification::make()
->title('Unknown Production Order')
->body("Production Order not found against plant '$plantName'.")
->danger()
->send();
$this->form->fill([
'plant_id' => $plantId,
'machine_id' => $workCenter,
'production_order' => $prodOrderNo,
'serial_number' => null,
]);
return;
}
$itemExist = Item::where('code', $itemCode)->first();
$itemAgaPlant = Item::where('code', $itemCode)->where('plant_id', $plantId)->first();
if(!$itemExist){
Notification::make()
->title('Unknown Item Code')
->body("Item code '$itemCode' not found.")
->danger()
->send();
$this->form->fill([
'plant_id' => $plantId,
'machine_id' => $workCenter,
'production_order' => $prodOrderNo,
'serial_number' => null,
]);
return;
}
elseif(!$itemAgaPlant){
Notification::make()
->title('Unknown Item Code')
->body("Item code '$itemCode' not found against the the plant '$plantName'.")
->danger()
->send();
$this->form->fill([
'plant_id' => $plantId,
'machine_id' => $workCenter,
'production_order' => $prodOrderNo,
'serial_number' => null,
]);
return;
}
elseif ($itemAgaPlant->id != $pOrderExist->item_id) {
Notification::make()
->title('Item Code Mismatch')
->body("Item code '$itemCode' does not match the item associated with production order '$prodOrderNo'.")
->danger()
->send();
$this->form->fill([
'plant_id' => $plantId,
'machine_id' => $workCenter,
'production_order' => $prodOrderNo,
'serial_number' => null,
]);
return;
}
$productionOrders = ProductionOrder::where('plant_id', $plantId)
->where('production_order', $prodOrderNo)
->where('item_id', $itemAgaPlant->id)
->get();
$serialExist = null;
foreach ($productionOrders as $productionOrder) {
for (
$serial = (int) $productionOrder->from_serial_number;
$serial <= (int) $productionOrder->to_serial_number;
$serial++
) {
if ($serial == (int) $serialNumber) {
$serialExist = $productionOrder;
break 2;
}
}
}
if(!$serialExist){
Notification::make()
->title('Serial Number Not Found')
->body("Serial number '$serialNumber' not found for production order '$prodOrderNo', item '$itemCode' and plant '$plantName'.")
->danger()
->send();
$this->form->fill([
'plant_id' => $plantId,
'machine_id' => $workCenter,
'production_order' => $prodOrderNo,
'serial_number' => null,
]);
return;
}
//..Generate Sticker PDF and download it
$this->ref_number = $this->form->getState()['production_order'];
$this->serNo = $serialNumber;
$user = Filament::auth()->user();
$operatorName = $user->name;
$duplicate = StickerValidation::where('plant_id', $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' => $plantId,
'machine_id' => $workCenter,
'production_order' => $this->ref_number,
'serial_number' => null,
]);
return;
}
$itemC = Item::where('code', $itemCode)
->where('plant_id',$plantId)
->first();
$itemId = $itemC->id;
$item = ItemCharacteristic::where('item_id', $itemId)
->where('plant_id',$plantId)
->first();
$itemI = $item->id;
$mapping = StickerMappingMaster::where('plant_id', $plantId)
->where('sticker1_machine_id', $workCenter)
->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' => $plantId,
'machine_id' => $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' => $plantId,
'machine_id' => $workCenter,
'production_order' => $this->ref_number,
'serial_number' => null,
]);
$pdfUrls = [];
foreach ($stickers as $sticker)
{
$structure = StickerStructureDetail::findOrFail($sticker['sticker_id']);
$itemCharacteristic = ItemCharacteristic::where('plant_id', $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,
$itemCode,
$plantId
);
$tempPdfPath = storage_path('app/temp_sticker_' . uniqid() . '.pdf');
file_put_contents($tempPdfPath, $pdfContent);
// $pdfUrl = route('sticker.preview', [
// 'path' => basename($tempPdfPath),
// ]);
$pdfUrls[] = route('sticker.preview', ['path' => basename($tempPdfPath)]);
}
$this->dispatch('open-sticker-pdf', urls: $pdfUrls);
Notification::make()
->success()
->title('Sticker Printed')
->body("Sticker for Serial Number: $serialNumber printed successfully!")
->seconds(3)
->send();
}
public function generateSticker()
{
$plantId = $this->form->getState()['plant_id'];
$plantId = trim($plantId) ?? null;
$workCenter = $this->form->getState()['machine_id'];
$prodOrderNo= $this->form->getState()['production_order'];
$prodOrderNo = trim($prodOrderNo) ?? null;
$fromSno= $this->form->getState()['from_serial_number'];
$fromSno = trim($fromSno) ?? null;
$toSno= $this->form->getState()['to_serial_number'];
$toSno = trim($toSno) ?? null;
$serialExist = ProductionOrder::where('plant_id', $plantId)
->where('production_order', $prodOrderNo)
->where('from_serial_number', '=', $fromSno)
->where('to_serial_number', '=', $toSno)
->first();
if(!$serialExist){
Notification::make()
->title('Serial Number Range Not Found')
->body("Serial number range '$fromSno' to '$toSno' not found for production order '$prodOrderNo'.")
->danger()
->send();
$this->form->fill([
'plant_id' => $plantId,
'machine_id' => $workCenter,
'production_order' => $prodOrderNo,
'from_serial_number' => null,
'to_serial_number' => null,
]);
return;
}
else
{
if($serialExist){
$itemId = $serialExist->item_id;
$itemCode = Item::where('id', $itemId)
->where('plant_id', $serialExist->plant_id)
->value('code');
}
$this->ref_number = $this->form->getState()['production_order'];
$fromSerNo = $this->form->getState()['from_serial_number'];
$toSerNo = $this->form->getState()['to_serial_number'];
$user = Filament::auth()->user();
$operatorName = $user->name;
$itemC = Item::where('code', $itemCode)
->where('plant_id',$plantId)
->first();
$itemId = $itemC->id;
$item = ItemCharacteristic::where('item_id', $itemId)
->where('plant_id',$plantId)
->first();
$itemI = $item->id;
$mapping = StickerMappingMaster::where('plant_id', $plantId)
->where('sticker1_machine_id', $workCenter)
->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;
}
$fromSerNo = (int) $this->form->getState()['from_serial_number'];
$toSerNo = (int) $this->form->getState()['to_serial_number'];
if ($fromSerNo > $toSerNo) {
Notification::make()
->danger()
->title('Invalid Serial Number Range')
->body("From Serial Number must be less than or equal to To Serial Number.")
->send();
return;
}
$pdfUrls = [];
$stickerService = new StickerPdfService();
foreach ($stickers as $sticker) {
$structure = StickerStructureDetail::findOrFail($sticker['sticker_id']);
$itemCharacteristic = ItemCharacteristic::where('plant_id',$plantId)->where('id',$sticker['item_characteristic'])->firstOrFail();
$elements = StickerDetail::where('sticker_structure_detail_id',$structure->id)->get();
$template = $stickerService->generateTemplate(
$structure->sticker_id,
$elements,
$itemCharacteristic,
$itemCode,
$plantId
);
$pdfContent = $stickerService->generateBulkFromTemplate(
$template,
$fromSerNo,
$toSerNo,
$itemCode
);
$fileName ='bulk_sticker_' .$fromSerNo .'_' .$toSerNo .'_' .uniqid() .'.pdf';
$tempPdfPath = storage_path('app/' . $fileName);
file_put_contents($tempPdfPath,$pdfContent);
$pdfUrls[] = route('sticker.preview',['path' => $fileName,]);
}
$this->dispatch('open-sticker-pdf',urls: $pdfUrls);
Notification::make()
->success()
->title('Sticker Printed')
->body("Sticker printed successfully!")
->seconds(3)
->send();
}
}
public function generateStickerId()
{
$state = $this->form->getState();
$plantId = trim($state['plant_id'] ?? '');
$machineId = trim($state['machine_id'] ?? '');
$stickerId = $state['sticker_id'] ?? null;
$pOrder = $state['production_order'] ?? null;
$fromSno = trim($state['from_serial_number'] ?? '');
$toSno = trim($state['to_serial_number'] ?? '');
$plantName = Plant::where('id', $plantId)->value('name');
if (!$stickerId) {
Notification::make()
->danger()
->title('Sticker ID Not Selected')
->body('Please Choose a Sticker ID.')
->send();
return;
}
if ($fromSno == '' || $toSno == '') {
Notification::make()
->danger()
->title('Serial Number Required')
->body('Please enter both From Serial Number and To Serial Number.')
->send();
return;
}
$fromSerNo = (int) $fromSno;
$toSerNo = (int) $toSno;
if ($fromSerNo > $toSerNo) {
Notification::make()
->danger()
->title('Invalid Serial Number Range')
->body('From Serial Number must be less than or equal to To Serial Number.')
->send();
return;
}
$pOrderEx = ProductionOrder::where('production_order', $pOrder)->first();
if(!$pOrderEx){
Notification::make()
->danger()
->title('Unknown Production Order')
->body("Production Order '$pOrder' not found.")
->send();
return;
}
$pOrderExist = ProductionOrder::where('plant_id', $plantId)->where('production_order', $pOrder)->first();
if(!$pOrderExist){
Notification::make()
->danger()
->title('Unknown Production Order')
->body("Production Order '$pOrder' not found against plant $plantName.")
->send();
return;
}
if($pOrderExist){
if((int) $pOrderExist->from_serial_number != $fromSerNo || (int) $pOrderExist->to_serial_number != $toSerNo){
Notification::make()
->danger()
->title('Unknown Serial Number')
->body("The entered serial number range does not match Production Order '$pOrder' for plant '$plantName'.")
->send();
return;
}
}
$structure = StickerStructureDetail::where('sticker_id',$stickerId)->first();
if (!$structure) {
Notification::make()
->danger()
->title('Sticker Structure Not Found')
->body("No sticker structure found for sticker ID '{$stickerId}'.")
->send();
return;
}
$stickerMappingMasterItems = StickerMappingMaster::where('plant_id', $plantId)->get();
if (!$stickerMappingMasterItems) {
Notification::make()
->danger()
->title('Sticker Mapping Not Found')
->body("No sticker mapping found for plant ID '{$plantId}'.")
->send();
return;
}
$structure = null;
$stickerMappingMasterItem = null;
foreach ($stickerMappingMasterItems as $mapping) {
// Check sticker_structure1_id to sticker_structure8_id
for ($i = 1; $i <= 8; $i++) {
$column = "sticker_structure{$i}_id";
$structureId = $mapping->{$column};
if (empty($structureId)) {
continue;
}
// Find structure detail
$detail = StickerStructureDetail::find($structureId);
if (!$detail) {
continue;
}
// Check whether this structure belongs to selected sticker
if ((string) $detail->sticker_id === (string) $stickerId) {
$structure = $detail;
// Keep the mapping record also
$stickerMappingMasterItem = $mapping;
break 2;
}
}
}
if (!$structure) {
Notification::make()
->danger()
->title('Sticker Structure Not Found')
->body("No sticker structure found for selected sticker ID '{$stickerId}'.")
->send();
return;
}
$itemCharacteristicId = $stickerMappingMasterItem->item_characteristic_id;
if (!$itemCharacteristicId) {
Notification::make()
->danger()
->title('Item Characteristic Not Found')
->body('No item characteristic is configured in sticker mapping.')
->send();
return;
}
$itemCharacteristic = ItemCharacteristic::where('plant_id', $plantId)->where('id',$itemCharacteristicId)->first();
if (!$itemCharacteristic) {
Notification::make()
->danger()
->title('Item Characteristic Not Found')
->body("Item characteristic '{$itemCharacteristicId}' was not found.")
->send();
return;
}
$itemCode = Item::where('id',$itemCharacteristic->item_id)->where('plant_id',$plantId)->value('code');
if (!$itemCode) {
Notification::make()
->danger()
->title('Item Not Found')
->body('No item code found for the selected item characteristic.')
->send();
return;
}
$elements = StickerDetail::where('sticker_structure_detail_id',$structure->id)->get();
if ($elements->isEmpty()) {
Notification::make()
->danger()
->title('Sticker Details Not Found')
->body('No sticker details configured for the selected sticker.')
->send();
return;
}
$stickerService = new StickerPdfService();
$template = $stickerService->generateTemplate(
$structure->sticker_id,
$elements,
$itemCharacteristic,
$itemCode,
$plantId
);
$pdfContent = $stickerService->generateBulkFromTemplate(
$template,
$fromSerNo,
$toSerNo,
$itemCode,
);
$fileName = 'bulk_sticker_'. $fromSerNo. '_'. $toSerNo. '_'. uniqid(). '.pdf';
$tempPdfPath = storage_path('app/' . $fileName);
file_put_contents(
$tempPdfPath,
$pdfContent
);
$pdfUrl = route(
'sticker.preview',
[
'path' => $fileName,
]
);
$this->dispatch('open-sticker-pdf',urls: [$pdfUrl]);
$totalStickers = ($toSerNo - $fromSerNo) + 1;
Notification::make()
->success()
->title('Sticker Generated')
->body("{$totalStickers} sticker(s) generated successfully.")
->seconds(3)
->send();
}
public static function canAccess(): bool
{
return Auth::check() && Auth::user()->can('view sticker bulk print page');
}
}