diff --git a/app/Filament/Pages/SpareMasterPrint.php b/app/Filament/Pages/SpareMasterPrint.php new file mode 100644 index 0000000..e932578 --- /dev/null +++ b/app/Filament/Pages/SpareMasterPrint.php @@ -0,0 +1,301 @@ +form->fill([ + 'plant_id'=>$this->plantId, + 'pallet_quantity' => 0, + ]); + } + + public function form(Form $form): Form + { + return $form + ->statePath('filters') + ->schema([ + Section::make('') + ->schema([ + Select::make('plant_id') + ->label('Plant') + ->reactive() + // ->options(Plant::pluck('name', 'id')) + ->options(function (callable $get) { + $userHas = Filament::auth()->user()->plant_id; + return ($userHas && strlen($userHas) > 0) ? Plant::where('id', $userHas)->pluck('name', 'id')->toArray() : Plant::pluck('name', 'id')->toArray(); + }) + ->required(), + Select::make('sale_order_master_id') + ->label('Sale Order Number') + ->reactive() + ->searchable() + ->options(function (callable $get) { + $plantId = $get('plant_id'); + if (empty($plantId)) { + return []; + } + + return SaleOrderMaster::where('plant_id', $plantId)->distinct()->pluck('sale_order_number', 'sale_order_number'); //->pluck('customer_po', 'id'); ->distinct() + }) + ->required() + ->afterStateUpdated(function ($state, callable $set) { + $set('scan_pallet_no', null); + }), + Select::make('scan_pallet_no') + ->label('Scan Pallet No') + ->reactive() + ->searchable() + ->options(function ($get) { + + $plantId = $get('plant_id'); + $saleOrder = $get('sale_order_master_id'); + + if (! $plantId || ! $saleOrder) + { + return []; + } + + $poIds = SaleOrderMaster::where('plant_id', $plantId)->where('sale_order_number', $saleOrder)->pluck('id'); + $palletNumbers = SparePacking::query() + ->where('plant_id', $plantId) + ->whereIn('sale_order_master_id', $poIds) + ->whereNotNull('spare_packing_number') + ->groupBy('spare_packing_number') + ->havingRaw('COUNT(*) = COUNT(spare_packing_status)') + ->havingRaw("SUM(CASE WHEN TRIM(spare_packing_status) = '' THEN 1 ELSE 0 END) = 0") + ->orderBy('spare_packing_number') + ->pluck('spare_packing_number') + ->toArray(); + return collect($palletNumbers) ->mapWithKeys(fn ($number) => [$number => $number]) ->toArray(); + }) + ->afterStateUpdated(function ($state, callable $set, $get) { + $palletNo = $state; + $plantId = $get('plant_id'); + + $this->dispatch('loadData', $palletNo, $plantId); + }) + ->extraAttributes([ + 'wire:keydown.enter' => 'processPalletNo($event.target.value)', + ]), + // TextInput::make('customer_name') + // ->label('Customer Name') + // ->required() + // ->reactive(), + ]) + ->columns(3) + ]); + } + + public function processPalletNo($palletNo) + { + $plantId = $this->form->getState()['plant_id']; + + $plantId = trim($plantId) ?? null; + + $palletNo= $this->form->getState()['scan_pallet_no']; + + $palletNo = trim($palletNo) ?? null; + + $operatorName = Filament::auth()->user()->name; + + if ($palletNo == null || $palletNo == '') + { + Notification::make() + ->title("Pallet number can't be empty!") + ->danger() + ->duration(5000) + ->send(); + + $this->dispatch('loadLocator' ,'',$plantId); + $this->form->fill + ([ + 'plant_id' => $plantId, + 'scan_serial_no' => null, + 'scan_pallet_no' => null, + 'scan_locator_no' => null, + 'pallet_quantity' => 0, + 'created_by' => $operatorName, + 'scanned_by' => $operatorName, + ]); + return; + } + // else if (strlen($palletNo) < 10) + // { + // Notification::make() + // ->title("Pallet number '$palletNo' must be at least 10 digits.") + // ->danger() + // ->duration(5000) + // ->send(); + + // $this->dispatch('loadLocator' ,'',$plantId); + // $this->form->fill + // ([ + // 'plant_id' => $plantId, + // 'scan_serial_no' => null, + // 'scan_pallet_no' => null, + // 'scan_locator_no' => null, + // 'pallet_quantity' => 0, + // 'created_by' => $operatorName, + // 'scanned_by' => $operatorName, + // ]); + // return; + // } + + $Palletexists = WireMasterPacking::where('wire_packing_number', $palletNo) + ->where('plant_id', $plantId)->first(); + if(!$Palletexists) + { + Notification::make() + ->title("Pallet number '$palletNo' does not found in wire master packing table.") + ->danger() + ->duration(5000) + ->send(); + + $this->dispatch('loadData' ,'',$plantId); + $this->form->fill + ([ + 'plant_id' => $plantId, + 'scan_pallet_no' => null, + 'pallet_quantity' => 0, + 'created_by' => $operatorName, + 'scanned_by' => $operatorName, + ]); + return; + } + else + { + $this->snoCount = WireMasterPacking::where('plant_id', $plantId) + ->where('wire_packing_number', $palletNo) + ->count(); + + $this->dispatch('loadData', $palletNo, $plantId); + $this->form->fill + ([ + 'plant_id' => $plantId, + 'scan_pallet_no' => $palletNo, + 'pallet_quantity' => $this->snoCount, + 'created_by' => $operatorName, + 'scanned_by' => $operatorName, + ]); + return; + } + } + + public function saveCustomerPO(){ + $plantId = $this->form->getState()['plant_id']; + + $plantId = trim($plantId) ?? null; + + $palletNo= $this->form->getState()['scan_pallet_no']; + + $palletNo = trim($palletNo) ?? null; + + $customerPO = $this->form->getState()['customer_po']; + + $customerPO = trim($customerPO) ?? null; + + $customerName = $this->form->getState()['customer_name']; + + $customerName = trim($customerName) ?? null; + + if (!$plantId || !$palletNo) { + return; // optional validation + } + + $record = WireMasterPacking::where('plant_id', $plantId) + ->where('wire_packing_number', $palletNo) + ->update([ + 'customer_po' => $customerPO, + 'customer_name' => $customerName, + 'updated_at' => now(), + ]); + + if($record){ + Notification::make() + ->title("Customer PO updated successfully for the pallet number '$palletNo'") + ->success() + ->send(); + return; + } + else + { + Notification::make() + ->title("Customer PO updation failed for the pallet number '$palletNo'") + ->success() + ->send(); + return; + } + } + + public function printPallet() + { + $palletNumber = $this->form->getState()['scan_pallet_no'] ?? null; + $plantId = $this->form->getState()['plant_id'] ?? null; + $customerId = $this->form->getState()['customer_po_master_id'] ?? null; + + $state = $this->form->getState(); + + // $customerCode = $state['customer_po'] ?? null; + // $customerName = $state['customer_name'] ?? null; + + if (!$palletNumber) { + Notification::make() + ->title("Pallet number cant't be empty!") + ->danger() + ->duration(5000) + ->send(); + return; + } + + $this->dispatch('open-pdf', url: route('print.sparepallet', [ + 'pallet' => $state['scan_pallet_no'], + 'plant' => $state['plant_id'], + 'customer' => $state['sale_order_master_id'], + ])); + } + + public static function canAccess(): bool + { + return Auth::check() && Auth::user()->can('view spare master print page'); + } +} diff --git a/app/Filament/Resources/RequestCharacteristicResource.php b/app/Filament/Resources/RequestCharacteristicResource.php index 305ef1e..f76f84b 100644 --- a/app/Filament/Resources/RequestCharacteristicResource.php +++ b/app/Filament/Resources/RequestCharacteristicResource.php @@ -95,6 +95,7 @@ class RequestCharacteristicResource extends Resource $set('machine_id', null); $set('item_id', null); $set('aufnr', null); + $set('gernr', null); $set('machine_name', null); $set('characteristic_approver_master_id', null); $set('approver_type', null); @@ -126,6 +127,7 @@ class RequestCharacteristicResource extends Resource ->afterStateUpdated(function ($state, callable $set, callable $get) { $set('item_id', null); $set('aufnr', null); + $set('gernr', null); $set('machine_name', null); $set('characteristic_approver_master_id', null); $set('approver_type', null); @@ -213,6 +215,7 @@ class RequestCharacteristicResource extends Resource ->afterStateUpdated(function ($state, callable $set, callable $get) { if (! $state) { $set('aufnr', null); + $set('gernr', null); } $set('updated_by', Filament::auth()->user()?->name); }) @@ -237,6 +240,9 @@ class RequestCharacteristicResource extends Resource return false; }) ->afterStateUpdated(function ($state, callable $set, callable $get) { + if (! $state) { + $set('gernr', null); + } $set('updated_by', Filament::auth()->user()?->name); }) ->default(function () { @@ -246,6 +252,32 @@ class RequestCharacteristicResource extends Resource }) ->readOnly(fn ($get) => ($get('item_id') == null)) ->disabled(fn ($get) => self::isFieldDisabled($get)), + Forms\Components\TextInput::make('gernr') + ->label('Serial Number') + ->reactive() + ->minLength(13) + ->readOnly(fn (callable $get) => (! $get('aufnr'))) + ->afterStateUpdated(function (callable $set) { + $set('updated_by', Filament::auth()->user()?->name); + }) + // ->rules([ + // function (callable $get) { + // return Rule::unique('class_characteristics', 'gernr') + // ->where('plant_id', $get('plant_id')) + // ->ignore($get('id')); + // }, + // ]) + // ->validationMessages([ + // 'unique' => "The 'GERNR' has already been taken.", // The GERNR has already been taken for this plant. + // ]) + ->required(function (callable $get) { + $appTyp = $get('approver_type'); + if ($appTyp == 'Stop') { + return true; + } + + return false; + }), Forms\Components\Select::make('machine_name') ->label('Machine Name') ->reactive() @@ -333,6 +365,9 @@ class RequestCharacteristicResource extends Resource $set('current_value', null); $set('update_value', null); } + if ($appTyp != 'Stop') { + $set('gernr', null); + } $set('updated_by', Filament::auth()->user()?->name); }) ->default(function () { @@ -443,8 +478,9 @@ class RequestCharacteristicResource extends Resource $plantId = $get('plant_id'); $jobNo = $get('aufnr'); + $sNo = $get('gernr'); $updId = $get('id'); - $pendingExists = RequestCharacteristic::where('plant_id', $plantId)->where('aufnr', $jobNo)->where('characteristic_name', $value)->latest()->first(); + $pendingExists = RequestCharacteristic::where('plant_id', $plantId)->where('aufnr', $jobNo)->where('gernr', $sNo)->where('characteristic_name', $value)->latest()->first(); if ($pendingExists) { if ($updId && $pendingExists->id == $updId) { @@ -966,6 +1002,11 @@ class RequestCharacteristicResource extends Resource ->alignCenter() ->searchable() ->sortable(), + Tables\Columns\TextColumn::make('gernr') + ->label('Serial Number') + ->alignCenter() + ->searchable() + ->sortable(), Tables\Columns\TextColumn::make('characteristicApproverMaster.machine_name') ->label('Machine Name') ->alignCenter() @@ -1236,8 +1277,11 @@ class RequestCharacteristicResource extends Resource ->label('Job Number') ->placeholder('Enter Job Number') ->numeric() - ->minlength(7) ->maxlength(10), + TextInput::make('gernr') + ->label('Serial Number') + ->placeholder('Enter Serial Number') + ->numeric(), TextInput::make('work_flow_id') ->label('Work Flow ID') ->placeholder('Enter Work Flow ID'), @@ -1313,7 +1357,7 @@ class RequestCharacteristicResource extends Resource ]) ->query(function ($query, array $data) { // Hide all records initially if no filters are applied - if (empty($data['Plant']) && empty($data['machine']) && empty($data['item_id']) && empty($data['aufnr']) && empty($data['model_type']) && empty($data['work_flow_id']) && empty($data['machine_name']) && empty($data['request_type']) && empty($data['master_characteristic_field']) && empty($data['approver_status1']) && empty($data['approver_status2']) && empty($data['approver_status3']) && empty($data['approver_status']) && empty($data['created_from']) && empty($data['created_to'])) { + if (empty($data['Plant']) && empty($data['machine']) && empty($data['item_id']) && empty($data['aufnr']) && empty($data['gernr']) && empty($data['model_type']) && empty($data['work_flow_id']) && empty($data['machine_name']) && empty($data['request_type']) && empty($data['master_characteristic_field']) && empty($data['approver_status1']) && empty($data['approver_status2']) && empty($data['approver_status3']) && empty($data['approver_status']) && empty($data['created_from']) && empty($data['created_to'])) { return $query->whereRaw('1 = 0'); } @@ -1339,6 +1383,10 @@ class RequestCharacteristicResource extends Resource $query->where('aufnr', 'like', '%'.$data['aufnr'].'%'); } + if (! empty($data['gernr'])) { + $query->where('gernr', 'like', '%'.$data['gernr'].'%'); + } + if (! empty($data['model_type'])) { $query->where('model_type', 'like', '%'.$data['model_type'].'%'); } @@ -1436,6 +1484,10 @@ class RequestCharacteristicResource extends Resource $indicators[] = 'Job No: '.$data['aufnr']; } + if (! empty($data['gernr'])) { + $indicators[] = 'Serial No: '.$data['gernr']; + } + if (! empty($data['model_type'])) { $indicators[] = 'Model Type: '.$data['model_type']; } diff --git a/app/Http/Controllers/PalletPrintController.php b/app/Http/Controllers/PalletPrintController.php index cdb9c3a..92b4654 100644 --- a/app/Http/Controllers/PalletPrintController.php +++ b/app/Http/Controllers/PalletPrintController.php @@ -4,6 +4,8 @@ namespace App\Http\Controllers; use App\Models\CustomerPoMaster; use App\Models\Plant; +use App\Models\SaleOrderMaster; +use App\Models\SparePacking; use App\Models\WireMasterPacking; use Barryvdh\DomPDF\Facade\Pdf; use Illuminate\Http\Request; @@ -279,9 +281,6 @@ class PalletPrintController extends Controller } - - - public function store(Request $request) { // @@ -310,4 +309,101 @@ class PalletPrintController extends Controller { // } + + public function printSpare(Request $request, $pallet, $plant) + { + + $customerPoMasterId = SparePacking::where('plant_id', $plant) + ->where('spare_packing_number', $pallet) + ->value('sale_order_master_id'); + + $masterIds = SparePacking::where('plant_id', $plant) + ->where('spare_packing_number', $pallet) + ->pluck('sale_order_master_id'); + + $customerPo = SaleOrderMaster::whereIn('id', $masterIds) + ->value('sale_order_number'); + + $customerPoMasterIds = SaleOrderMaster::where('sale_order_number', $customerPo) + ->pluck('id'); + + $items = SparePacking::with('item') + ->where('plant_id', $plant) + ->where('spare_packing_number', $pallet) + ->get() + ->map(function ($row) { + return (object) [ + 'code' => $row->item->code, + 'description' => $row->item->description, + 'box_count' => 1, // each row = one box + 'weight' => $row->quantity, + ]; + }); + + $customer = SaleOrderMaster::find($customerPoMasterId); + + $customerCode = $customer->sale_order_number ?? ''; + $customerName = $customer->supplier_name ?? ''; + + $totalBoxes = SparePacking::where('plant_id', $plant) + ->whereIn('sale_order_master_id', $customerPoMasterIds) + ->select('spare_packing_number') + ->groupBy('spare_packing_number') + ->havingRaw( + 'COUNT(*) = COUNT(CASE WHEN spare_packing_status = ? THEN 1 END)', + ['Completed'] + ) + ->count(); + + $completedPallets = SparePacking::where('plant_id', $plant) + ->whereIn('sale_order_master_id', $customerPoMasterIds) + ->select('spare_packing_number') + ->groupBy('spare_packing_number') + ->havingRaw( + 'COUNT(*) = COUNT(CASE WHEN spare_packing_status = ? THEN 1 END)', + ['Completed'] + ) + ->orderBy('spare_packing_number') + ->pluck('spare_packing_number') + ->values(); + + $index = $completedPallets->search($pallet); + + $currentPalletNo = ($index !== false) ? $index + 1 : 0; + + $boxLabel = $currentPalletNo.'/'.$totalBoxes; + + $grossWeight = $items->sum('weight'); + $widthPt = 85 * 2.83465; // 85mm → points + $heightPt = 100 * 2.83465; // 100mm → points + + $plantName = Plant::where('id', $plant)->value('name'); + + $plantAddress = Plant::where('id', $plant)->value('address'); + + $scannedAt = SparePacking::where('plant_id', $plant) + ->where('spare_packing_number', $pallet) + ->value('scanned_at'); + + $pdf = Pdf::loadView('pdf.spare-pallet', [ + 'product' => 'Spare Packing List', + 'plantName' => $plantName, + 'plantAddress' => $plantAddress, + // 'monthYear' => now()->format('M-y'), + 'monthYear' => $scannedAt + ? \Carbon\Carbon::parse($scannedAt)->format('M-y') + : '', + 'branch' => '', + 'customerCode' => $customerCode, + 'customerName' => $customerName, + 'masterBox' => $boxLabel, + 'items' => $items, + 'grossWeight' => $grossWeight + 3.050, + 'netWeight' => $grossWeight, + 'pallet' => $pallet, + ])->setPaper([0, 0, $widthPt, $heightPt], 'portrait'); + + return $pdf->stream("Pallet-{$pallet}.pdf"); + + } } diff --git a/app/Models/RequestCharacteristic.php b/app/Models/RequestCharacteristic.php index 67a2339..f4afad0 100644 --- a/app/Models/RequestCharacteristic.php +++ b/app/Models/RequestCharacteristic.php @@ -19,6 +19,7 @@ class RequestCharacteristic extends Model 'item_id', 'characteristic_approver_master_id', 'aufnr', + 'gernr', 'characteristic_name', 'current_value', 'update_value', diff --git a/app/Policies/SparePackingPolicy.php b/app/Policies/SparePackingPolicy.php index 0108163..76f29ea 100644 --- a/app/Policies/SparePackingPolicy.php +++ b/app/Policies/SparePackingPolicy.php @@ -2,7 +2,6 @@ namespace App\Policies; -use Illuminate\Auth\Access\Response; use App\Models\SparePacking; use App\Models\User; diff --git a/database/migrations/2026_09_04_113627_add_gernr_column_to_request_characteristics.php b/database/migrations/2026_09_04_113627_add_gernr_column_to_request_characteristics.php new file mode 100644 index 0000000..2cf0398 --- /dev/null +++ b/database/migrations/2026_09_04_113627_add_gernr_column_to_request_characteristics.php @@ -0,0 +1,32 @@ + + +
+
+
+
+
+ Master Packing Slip
+
+ |
+
+ |||
| + + | + ++ + | + +||
| MATERIAL CODE | +DESCRIPTION | +QTY in kg | +NO. OF BOXES | +
| + code; ?> + | + ++ description; ?> + | + ++ weight, 3); ?> + | + ++ box_count; ?> + | + +
| + No items available + | + +|||
| + TOTAL QUANTITY + | + ++ + | + +||
| + + MANUFACTURERS + + + MADE IN INDIA + + + *Under License + + | + +|||
|
+ C.R.I. PUMPS PRIVATE LIMITED
+ + + (Unit of {{ $plantName }}) + + + {{ $plantAddress }} + + + India Regd.Office : + 7/46-1, Keeranatham Road, + Saravanampatti, + Coimbatore- 641 035 + + + For Feedback/Complaint: + C.R.I. Customer care cell + Toll-Free: 1800 121 1243 + + |
+
+ |||