diff --git a/app/Filament/Resources/SerialValidationResource.php b/app/Filament/Resources/SerialValidationResource.php
new file mode 100644
index 0000000..a8c3e62
--- /dev/null
+++ b/app/Filament/Resources/SerialValidationResource.php
@@ -0,0 +1,1230 @@
+schema([
+ Section::make('')
+ ->schema([
+ Forms\Components\Select::make('plant_id')
+ ->relationship('plant', 'name')
+ ->required()
+ ->reactive()
+ ->columnSpan(1)
+ ->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();
+ })
+ ->default(function () {
+ return optional(SerialValidation::latest()->first())->plant_id;
+ })
+ ->disabled(fn (Get $get) => !empty($get('id')))
+ // ->afterStateUpdated(fn ($set) => $set('block_id', null) & $set('name', null) & $set('start_time', null) & $set('duration', null) & $set('end_time', null))
+ ->afterStateUpdated(function ($state, callable $set, callable $get) {
+ $plantId = $get('plant_id');
+ $set('update_invoice', null);
+ // Ensure `linestop_id` is not cleared
+ if (!$plantId) {
+ $set('invoice_number', null);
+ $set('serial_number', null);
+ $set('total_quantity', null);
+ $set('scanned_quantity', null);
+ $set('ivPlantError', 'Please select a plant first.');
+ return;
+ }
+ else
+ {
+ $set('ivPlantError', null);
+ }
+ })
+ ->extraAttributes(fn ($get) => [
+ 'class' => $get('ivPlantError') ? 'border-red-500' : '',
+ ])
+ ->hint(fn ($get) => $get('ivPlantError') ? $get('ivPlantError') : null)
+ ->hintColor('danger'),
+
+ Forms\Components\TextInput::make('invoice_number')
+ ->label('Invoice Number')
+ // ->required()
+ ->reactive()
+ ->disabled()
+ ->columnSpan(1)
+ //->readOnly(fn (callable $get) => !empty($get('serial_number')))
+ //->disabled(fn (Get $get) => !empty($get('serial_number')))
+ ->extraAttributes([
+ 'x-data' => '{ value: "" }',
+ 'x-model' => 'value',
+ 'x-on:keydown.enter.prevent' => '$wire.processInvoice(value)',
+ ])
+ // ->afterStateHydrated(function (TextInput $component, string $state) {
+ // $component->state(ucwords($state));
+ // })
+ ->afterStateUpdated(function ($state, callable $set, callable $get) {
+ $invNo = $get('invoice_number');
+ $set('serial_number', null);
+ $set('update_invoice', null);
+ // if (!$invNo) { return; } else { }
+ }),
+
+ Forms\Components\TextInput::make('serial_number')
+ ->label('Serial Number')
+ ->reactive()
+ // ->readOnly(fn (callable $get) => empty($get('invoice_number')))
+ //->disabled(fn (Get $get) => empty($get('invoice_number')))
+ ->extraAttributes([
+ 'id' => 'serial_number_input',
+ 'x-data' => '{ value: "" }',
+ 'x-model' => 'value',
+ 'wire:keydown.enter.prevent' => 'processSerialNumber(value)', // Using wire:keydown
+ ])
+ ->afterStateUpdated(function ($state, callable $set, callable $get) {
+ $set('update_invoice', 0);
+ // $this->dispatch('focus-serial-number');
+ // if (!$invNo) { return; } else { }
+ })
+ ->columnSpan(1),
+ Forms\Components\TextInput::make('total_quantity')
+ ->label('Total Quantity')
+ ->readOnly(true)
+ ->columnSpan(1),
+ Forms\Components\TextInput::make('scanned_quantity')
+ ->label('Scanned Quantity')
+ ->readOnly(true)
+ ->columnSpan(1),
+ ToggleButtons::make('update_invoice')
+ ->label('Update Invoice?')
+ ->boolean()
+ ->grouped()
+ ->reactive()
+ ->hidden(fn (callable $get) => ($get('invoice_number') == null || $get('update_invoice') == '0') || !empty($get('serial_number')))
+ ->afterStateUpdated(function ($state, callable $set, callable $get) {
+ if (!$get('plant_id'))
+ {
+ $set('update_invoice', null);
+ return;
+ }
+
+ if ($get('update_invoice') == "1")
+ {
+ $totQuan = SerialValidation::where('invoice_number', $get('invoice_number'))->where('plant_id', $get('plant_id'))->count();
+ if ($totQuan <= 0)
+ {
+ $set('update_invoice', null);
+ return;
+ }
+
+ $totMQuan = SerialValidation::where('invoice_number', $get('invoice_number'))->whereNotNull('quantity')->where('plant_id', $get('plant_id'))->count();
+ $scanMQuan = SerialValidation::where('invoice_number', $get('invoice_number'))->whereNotNull('serial_number')->where('serial_number', '!=', '')->where('plant_id', $get('plant_id'))->count();
+ $scanSQuan = SerialValidation::where('invoice_number', $get('invoice_number'))->where('scanned_status', 'Scanned')->where('plant_id', $get('plant_id'))->count();
+
+ if ($totMQuan > 0)
+ {
+ if ($totQuan == $scanMQuan)
+ {
+ $set('update_invoice', null);
+ return;
+ }
+ }
+ else
+ {
+ if ($totQuan == $scanSQuan)
+ {
+ $set('update_invoice', null);
+ return;
+ }
+ }
+ }
+ })
+ ->disabled(fn (Get $get) => empty($get('invoice_number'))),
+ Forms\Components\TextInput::make('id')
+ ->hidden()
+ ->readOnly(true),
+ ])
+ ->columns(5),
+ ]);
+ }
+
+ public static function table(Table $table): Table
+ {
+ return $table
+ ->columns([
+ Tables\Columns\TextColumn::make('No.')
+ ->label('No.')
+ ->getStateUsing(function ($record, $livewire, $column, $rowLoop) {
+ $paginator = $livewire->getTableRecords();
+ $perPage = method_exists($paginator, 'perPage') ? $paginator->perPage() : 10;
+ $currentPage = method_exists($paginator, 'currentPage') ? $paginator->currentPage() : 1;
+ return ($currentPage - 1) * $perPage + $rowLoop->iteration;
+ }),
+ Tables\Columns\TextColumn::make('invoice_number')
+ ->label('Invoice Number')
+ ->alignCenter()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('stickerMaster.item.code')
+ ->label('Item Code')
+ ->alignCenter()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('serial_number')
+ ->label('Serial Number')
+ ->alignCenter()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('motor_scanned_status')
+ ->label('Motor Scanned Status')
+ ->alignCenter(),
+ Tables\Columns\TextColumn::make('pump_scanned_status')
+ ->label('Pump Scanned Status')
+ ->alignCenter(),
+ Tables\Columns\TextColumn::make('scanned_status_set')
+ ->label('Pump Set Scanned Status')
+ ->alignCenter(),
+ Tables\Columns\TextColumn::make('capacitor_scanned_status')
+ ->label('Capacitor Scanned Status')
+ ->alignCenter(),
+ Tables\Columns\TextColumn::make('scanned_status')
+ ->label('Scanned Status')
+ ->alignCenter(),
+ Tables\Columns\TextColumn::make('panel_box_supplier')
+ ->label('Panel Box Supplier')
+ ->alignCenter(),
+ Tables\Columns\TextColumn::make('panel_box_serial_number')
+ ->label('Panel Box Serial Number')
+ ->alignCenter(),
+ Tables\Columns\TextColumn::make('load_rate')
+ ->label('Load Rate')
+ ->numeric()
+ ->alignCenter(),
+ Tables\Columns\TextColumn::make('upload_status')
+ ->label('Upload Status')
+ ->alignCenter(),
+ Tables\Columns\TextColumn::make('batch_number')
+ ->label('Batch Number')
+ ->alignCenter(),
+ Tables\Columns\TextColumn::make('quantity')
+ ->label('Quantity')
+ ->alignCenter()
+ ->numeric(),
+ Tables\Columns\TextColumn::make('plant.name')
+ ->label('Plant')
+ ->alignCenter()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('created_at')
+ ->label('Created At')
+ ->dateTime()
+ ->alignCenter()
+ ->sortable(),
+ Tables\Columns\TextColumn::make('updated_at')
+ ->label('Updated At')
+ ->dateTime()
+ ->alignCenter()
+ ->sortable()
+ ->toggleable(isToggledHiddenByDefault: true),
+ Tables\Columns\TextColumn::make('deleted_at')
+ ->label('Deleted At')
+ ->dateTime()
+ ->alignCenter()
+ ->sortable()
+ ->toggleable(isToggledHiddenByDefault: true),
+ Tables\Columns\TextColumn::make('operator_id')
+ ->label('Operator ID')
+ ->alignCenter()
+ ->sortable(),
+ ])
+ ->headerActions([
+
+ // Action::make('plant_id')
+ // ->label('Select Plant')
+ // ->form([
+ // Select::make('plant_id')
+ // ->options(Plant::pluck('name', 'id')->toArray()) // Fetch plant names and IDs
+ // ->label('Select Plant')
+ // ->required()
+ // ->reactive()
+ // ]),
+
+ Tables\Actions\Action::make('Import Serial Number')
+ ->label('Import Serial Invoice')
+ ->form([
+ Select::make('plant_id')
+ ->options(Plant::pluck('name', 'id')->toArray()) // Fetch plant names and IDs
+ ->label('Select Plant')
+ ->required()
+ ->default(function () {
+ return optional(SerialValidation::latest()->first())->plant_id;
+ })
+ ->afterStateUpdated(function ($state, callable $set, callable $get) {
+ $set('invoice_serial_number', null);
+ })
+ ->reactive(),
+
+ FileUpload::make('invoice_serial_number')
+ ->label('Invoice Serial Number')
+ // ->required()
+ ->preserveFilenames() // <- this keeps the original filename
+ ->storeFiles(false) // prevent auto-storing, we will store manually
+ ->reactive()
+ ->required()
+ ->disk('local') //'local' refers to the local storage disk defined in config/filesystems.php, typically pointing to storage/app.
+ ->visible(fn (Get $get) => !empty($get('plant_id')))
+ ->directory('uploads/temp'),
+ ])
+ ->action(function (array $data) {
+ $uploadedFile = $data['invoice_serial_number'];
+
+ $disk = Storage::disk('local');
+
+ $plantId = $data['plant_id'];
+
+ // Get original filename
+ $originalName = $uploadedFile->getClientOriginalName(); // e.g. 3RA0018732.xlsx
+
+ $originalNameOnly = pathinfo($originalName, PATHINFO_FILENAME);
+
+ // Store manually using storeAs to keep original name
+ $path = $uploadedFile->storeAs('uploads/temp', $originalName, 'local'); // returns relative path
+ // uploads/temp/3RA0018735.xlsx
+
+ $fullPath = Storage::disk('local')->path($path);
+ // /home/iot-dev/projects/pds/storage/app/private/uploads/temp/3RA0018735.xlsx
+
+ $totQuan = SerialValidation::where('invoice_number', $originalNameOnly)->count();
+ if ($totQuan > 0)
+ {
+ $scanSQuan = SerialValidation::where('invoice_number', $originalNameOnly)->where('scanned_status', 'Scanned')->count();
+ if ($totQuan == $scanSQuan)
+ {
+ $invoiceFirst = SerialValidation::with('plant')->where('invoice_number', $originalNameOnly)->first();
+ $plantName = $invoiceFirst ? (String)$invoiceFirst->plant->name : null;
+
+ Notification::make()
+ ->title("Serial invoice number : '$originalNameOnly' already completed the scanning process for plant : '$plantName'.")
+ ->danger()
+ ->send();
+
+ if ($disk->exists($path))
+ {
+ $disk->delete($path);
+ }
+ return;
+ }
+ else
+ {
+ $invoiceFirst = SerialValidation::with('plant')->where('invoice_number', $originalNameOnly)->first();
+ // $plantCode = $invoiceFirst ? (String)$invoiceFirst->plant->code : null;
+ $plantName = $invoiceFirst ? (String)$invoiceFirst->plant->name : null;
+ $invoicePlantId = $invoiceFirst->plant_id;
+ if ($plantId != $invoicePlantId)
+ {
+ Notification::make()
+ ->title("Serial invoice number : '$originalNameOnly' already exists for plant : '$plantName'.
Choose the valid 'Plant' to proceed!")
+ ->danger()
+ ->send();
+
+ if ($disk->exists($path))
+ {
+ $disk->delete($path);
+ }
+ return;
+ }
+ }
+ }
+
+ $totQuan = SerialValidation::where('invoice_number', $originalNameOnly)->where('plant_id', $plantId)->count();
+ $scanSQuan = SerialValidation::where('invoice_number', $originalNameOnly)->where('scanned_status', 'Scanned')->where('plant_id', $plantId)->count();
+
+ if ($totQuan > 0 && $totQuan == $scanSQuan)
+ {
+ Notification::make()
+ ->title('Serial invoice already completed the scanning process for selected plant.')
+ ->danger()
+ ->send();
+
+ if ($disk->exists($path))
+ {
+ $disk->delete($path);
+ }
+ return;
+ }
+
+ if ($fullPath && file_exists($fullPath))
+ {
+ $rows = Excel::toArray(null, $fullPath)[0];
+
+ if ((count($rows) - 1) <= 0)
+ {
+ Notification::make()
+ ->title('Records Not Found')
+ ->body("Import the valid 'Serial Invoice' file to proceed..!")
+ ->danger()
+ ->send();
+
+ if ($disk->exists($path)) {
+ $disk->delete($path);
+ }
+ return;
+ }
+
+ $invalidMatCodes = [];
+ $invalidSerialCodes = [];
+ $materialCodes = [];
+ $missingSerials = [];
+ $duplicateSerials = [];
+ $seenSerialNumbers = [];
+ $validRowsFound = false;
+
+ foreach ($rows as $index => $row)
+ {
+ if ($index == 0) continue; // Skip header
+
+ $materialCode = trim($row[0]);
+ $serialNumber = trim($row[1]);
+
+ if (empty($materialCode) && empty($serialNumber)) {
+ continue;
+ }
+
+ if (!empty($materialCode))
+ {
+ if (Str::length($materialCode) < 6 || !ctype_alnum($materialCode))
+ {
+ $invalidMatCodes[] = $materialCode;
+ }
+ else
+ {
+ if (empty($serialNumber)) {
+ $missingSerials[] = $materialCode;
+
+ }
+ else if (Str::length($serialNumber) < 9 || !ctype_alnum($serialNumber))
+ {
+ $invalidSerialCodes[] = $serialNumber;
+ }
+ else
+ {
+ if (in_array($serialNumber, $seenSerialNumbers)) {
+ $duplicateSerials[] = $serialNumber;
+ } else {
+ $seenSerialNumbers[] = $serialNumber;
+ $materialCodes[] = $materialCode;
+ $validRowsFound = true;
+ }
+ }
+ }
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ $uniqueInvalidCodes = array_unique($invalidMatCodes);
+
+ $uniqueMissingSerials = array_unique($missingSerials);
+
+ $uniqueSerialCodes = array_unique($invalidSerialCodes);
+
+ $duplicateSerialCodes = array_unique($duplicateSerials);
+
+ if (!empty($uniqueInvalidCodes)) {
+ Notification::make()
+ ->title('Invalid Item Codes')
+ ->body('The following item codes should contain minimum 6 digit alpha numeric values:
' . implode(', ', $uniqueInvalidCodes))
+ ->danger()
+ ->send();
+ if ($disk->exists($path)) {
+ $disk->delete($path);
+ }
+ return;
+ }
+ else if (!empty($uniqueMissingSerials)) {
+ Notification::make()
+ ->title('Missing Serial Numbers')
+ ->body("The following item codes doesn't have valid serial number:
" . implode(', ', $uniqueMissingSerials))
+ ->danger()
+ ->send();
+ if ($disk->exists($path)) {
+ $disk->delete($path);
+ }
+ return;
+ }
+ else if (!empty($uniqueSerialCodes)) {
+ Notification::make()
+ ->title('Invalid Serial Number')
+ ->body('The following serial numbers should contain minimum 9 digit alpha numeric values:
' . implode(', ', $uniqueSerialCodes))
+ ->danger()
+ ->send();
+ if ($disk->exists($path)) {
+ $disk->delete($path);
+ }
+ return;
+ }
+ else if (!empty($duplicateSerialCodes)) {
+ Notification::make()
+ ->title('Duplicate Serial Numbers')
+ ->body('The following serial numbers are already exist in imported excel:
' . implode(', ', $duplicateSerialCodes))
+ ->danger()
+ ->send();
+ if ($disk->exists($path)) {
+ $disk->delete($path);
+ }
+ return;
+ }
+
+ if (!$validRowsFound) {
+ Notification::make()
+ ->title('Invalid Serial Invoice')
+ ->danger() // This makes the notification red to indicate an error
+ ->body('Uploaded Excel sheet is empty or
contains no valid data.')
+ ->send();
+ if ($disk->exists($path)) {
+ $disk->delete($path);
+ }
+ return;
+ }
+
+ $uniqueCodes = array_unique($materialCodes);
+
+ $matchedItems = StickerMaster::with('item')
+ ->whereHas('item', function ($query) use ($uniqueCodes) {
+ $query->whereIn('code', $uniqueCodes);
+ })
+ ->get();
+
+ $matchedCodes = $matchedItems->pluck('item.code')->toArray();
+
+ $missingCodes = array_diff($uniqueCodes, $matchedCodes);
+
+ if (!empty($missingCodes))
+ {
+ $missingCount = count($missingCodes);
+
+ $message = $missingCount > 10 ? "'$missingCount' item codes are not found in database." : 'The following item codes are not found in database:
' . implode(', ', $missingCodes);
+
+ Notification::make()
+ ->title('Unknown Item Codes')
+ ->body($message)
+ ->danger()
+ ->send();
+
+ if ($disk->exists($path)) {
+ $disk->delete($path);
+ }
+ return;
+ }
+
+ // Check which codes have a material_type set (not null)
+ $invalidCodes = $matchedItems
+ ->filter(fn ($sticker) => !empty($sticker->material_type)) //filter invalid
+ ->pluck('item.code')
+ ->toArray();
+
+ if (count($invalidCodes) > 10)
+ {
+ Notification::make()
+ ->title('Invalid item codes found')
+ ->body('' . count($invalidCodes) . 'item codes found have material type.')
+ ->danger()
+ ->send();
+
+ if ($disk->exists($path)) {
+ $disk->delete($path);
+ }
+ return;
+ }
+ else if (count($invalidCodes) > 0)
+ {
+ Notification::make()
+ ->title('Invalid item codes found')
+ ->body('Material invoice Item Codes found : ' . implode(', ', $invalidCodes))
+ ->danger()
+ ->send();
+
+ if ($disk->exists($path)) {
+ $disk->delete($path);
+ }
+ return;
+ }
+ else
+ {
+ // Save full file path to session
+ session(['uploaded_invoice_path' => $fullPath]);
+ Notification::make()
+ ->title('Serial invoice imported successfully.')
+ ->success()
+ ->send();
+ }
+ }
+ })
+ ->visible(function() {
+ return Filament::auth()->user()->can('view import serial invoice');
+ }),
+ // Tables\Actions\Action::make('Import Invoice Material')
+ // ->label('Import Material Invoice')
+ // ->form([
+
+ // Select::make('plant_id')
+ // ->options(Plant::pluck('name', 'id')->toArray()) // Fetch plant names and IDs
+ // ->label('Select Plant')
+ // ->required()
+ // ->default(function () {
+ // return optional(SerialValidation::latest()->first())->plant_id;
+ // })
+ // ->afterStateUpdated(function ($state, callable $set, callable $get) {
+ // $set('invoice_material', null);
+ // })
+ // ->reactive(),
+
+ // FileUpload::make('invoice_material')
+ // ->label('Invoice Material')
+ // ->required()
+ // ->preserveFilenames()
+ // ->reactive() // <- this keeps the original filename
+ // ->storeFiles(false) // prevent auto-storing
+ // ->disk('local')
+ // ->visible(fn (Get $get) => !empty($get('plant_id')))
+ // ->directory('uploads/temp'),
+ // ])
+ // ->action(function (array $data) {
+ // $uploadedFile = $data['invoice_material'];
+
+ // $plantId = $data['plant_id']; // Access the selected plant_id
+
+ // $disk = Storage::disk('local');
+
+ // // Get original filename
+ // $originalName = $uploadedFile->getClientOriginalName();
+
+ // $originalNameOnly = pathinfo($originalName, PATHINFO_FILENAME);
+
+ // $path = $uploadedFile->storeAs('uploads/temp', $originalName, 'local');
+
+ // $fullPath = Storage::disk('local')->path($path);
+
+ // $totQuan = SerialValidation::where('invoice_number', $originalNameOnly)->count();
+ // if ($totQuan > 0)
+ // {
+ // $scanMQuan = SerialValidation::where('invoice_number', $originalNameOnly)->whereNotNull('serial_number')->where('serial_number', '!=', '')->count();
+ // if ($totQuan == $scanMQuan)
+ // {
+ // $invoiceFirst = SerialValidation::with('plant')->where('invoice_number', $originalNameOnly)->first();
+ // $plantName = $invoiceFirst ? (String)$invoiceFirst->plant->name : null;
+
+ // Notification::make()
+ // ->title("Material invoice number : '$originalNameOnly' already completed the scanning process for plant : '$plantName'.")
+ // ->danger()
+ // ->send();
+
+ // if ($disk->exists($path))
+ // {
+ // $disk->delete($path);
+ // }
+ // return;
+ // }
+ // else
+ // {
+ // $invoiceFirst = SerialValidation::with('plant')->where('invoice_number', $originalNameOnly)->first();
+ // // $plantCode = $invoiceFirst ? (String)$invoiceFirst->plant->code : null;
+ // $plantName = $invoiceFirst ? (String)$invoiceFirst->plant->name : null;
+ // $invoicePlantId = $invoiceFirst->plant_id;
+ // if ($plantId != $invoicePlantId)
+ // {
+ // Notification::make()
+ // ->title("Material invoice number : '$originalNameOnly' already exists for plant : '$plantName'.
Choose the valid 'Plant' to proceed!")
+ // ->danger()
+ // ->send();
+
+ // if ($disk->exists($path))
+ // {
+ // $disk->delete($path);
+ // }
+ // return;
+ // }
+ // }
+ // }
+
+ // $totQuan = SerialValidation::where('invoice_number', $originalNameOnly)->where('plant_id', $plantId)->count();
+ // $scanMQuan = SerialValidation::where('invoice_number', $originalNameOnly)->whereNotNull('serial_number')->where('serial_number', '!=', '')->where('plant_id', $plantId)->count();
+
+ // if ($totQuan > 0 && $totQuan == $scanMQuan)
+ // {
+ // Notification::make()
+ // ->title('Material invoice already completed the scanning process for selected plant.')
+ // ->danger()
+ // ->send();
+ // if ($disk->exists($path)) {
+ // $disk->delete($path);
+ // }
+ // return;
+ // }
+
+ // if ($fullPath && file_exists($fullPath))
+ // {
+ // $rows = Excel::toArray(null, $fullPath)[0];
+
+ // if ((count($rows) - 1) <= 0)
+ // {
+ // Notification::make()
+ // ->title('Records Not Found')
+ // ->body("Import the valid 'Material Invoice' file to proceed..!")
+ // ->danger()
+ // ->send();
+
+ // if ($disk->exists($path)) {
+ // $disk->delete($path);
+ // }
+ // return;
+ // }
+
+ // $invalidMatCodes = [];
+ // $materialCodes = [];
+ // $missingQuantities = [];
+ // $invalidMatQuan = [];
+ // $invalidMaterialQuan = [];
+ // $validRowsFound = false;
+
+ // foreach ($rows as $index => $row)
+ // {
+ // if ($index == 0) continue; // Skip header
+
+ // $materialCode = trim($row[0]);
+ // $materialQuantity = trim($row[1]);
+
+ // if (empty($materialCode) && empty($materialQuantity)) {
+ // continue;
+ // }
+
+ // if (!empty($materialCode)) {
+ // if (Str::length($materialCode) < 6 || !ctype_alnum($materialCode))
+ // {
+ // $invalidMatCodes[] = $materialCode;
+ // }
+ // else
+ // {
+ // if ($materialQuantity == 0)
+ // {
+ // $invalidMaterialQuan[] = $materialCode;
+ // }
+ // else if (empty($materialQuantity))
+ // {
+ // $missingQuantities[] = $materialCode;
+ // }
+ // else if (!is_numeric($materialQuantity))
+ // {
+ // $invalidMatQuan[] = $materialCode;
+ // }
+ // else
+ // {
+ // $materialCodes[] = $materialCode;
+ // $validRowsFound = true;
+ // }
+ // }
+ // }
+ // else
+ // {
+ // continue;
+ // }
+ // }
+
+ // $uniqueInvalidCodes = array_unique($invalidMatCodes);
+ // $uniqueaplhaMat = array_unique($invalidMatQuan);
+ // $uniqueZeroMat = array_unique($invalidMaterialQuan);
+ // $uniqueEmptyMat = array_unique($missingQuantities);
+
+ // if (!empty($uniqueInvalidCodes)) {
+ // Notification::make()
+ // ->title('Invalid Item Codes')
+ // ->body('The following item codes should contain minimum 6 digit alpha numeric values:
' . implode(', ', $uniqueInvalidCodes))
+ // ->danger()
+ // ->send();
+
+ // if ($disk->exists($path)) {
+ // $disk->delete($path);
+ // }
+ // return;
+ // }
+ // if (!empty($uniqueaplhaMat)) {
+ // Notification::make()
+ // ->title('Invalid Material Quantity')
+ // ->body("The following item codes material quantity must be a numeric values :
" . implode(', ', $uniqueaplhaMat))
+ // ->danger()
+ // ->send();
+
+ // if ($disk->exists($path)) {
+ // $disk->delete($path);
+ // }
+ // return;
+ // }
+ // if (!empty($uniqueZeroMat)) {
+ // Notification::make()
+ // ->title('Invalid Material Quantity')
+ // ->body("The following item codes material quantity should be greater than 0:
" . implode(', ', $uniqueZeroMat))
+ // ->danger()
+ // ->send();
+
+ // if ($disk->exists($path)) {
+ // $disk->delete($path);
+ // }
+ // return;
+ // }
+
+ // if (!empty($uniqueEmptyMat)) {
+ // Notification::make()
+ // ->title('Missing Material Quantity')
+ // ->body("The following item codes doesn't have valid material quantity:
" . implode(', ', $uniqueEmptyMat))
+ // ->danger()
+ // ->send();
+
+ // if ($disk->exists($path)) {
+ // $disk->delete($path);
+ // }
+ // return;
+ // }
+
+ // if (!$validRowsFound) {
+ // Notification::make()
+ // ->title('Invalid Material Invoice')
+ // ->danger() // This makes the notification red to indicate an error
+ // ->body('Uploaded Excel sheet is empty or
contains no valid data.')
+ // ->send();
+ // if ($disk->exists($path)) {
+ // $disk->delete($path);
+ // }
+ // return;
+ // }
+
+ // $uniqueCodes = array_unique($materialCodes);
+
+ // $matchedItems = StickerMaster::with('item')
+ // ->whereHas('item', function ($query) use ($uniqueCodes) {
+ // $query->whereIn('code', $uniqueCodes);
+ // })
+ // ->get();
+
+ // $matchedCodes = $matchedItems->pluck('item.code')->toArray();
+
+ // $missingCodes = array_diff($uniqueCodes, $matchedCodes);
+
+ // if (!empty($missingCodes))
+ // {
+ // $missingCount = count($missingCodes);
+
+ // $message = $missingCount > 10
+ // ? "'$missingCount' Item Codes are not found in sticker master."
+ // : 'Item Codes are not found in sticker master:
' . implode(', ', $missingCodes);
+
+ // Notification::make()
+ // ->title('Unknown Item Codes')
+ // ->body($message)
+ // ->danger()
+ // ->send();
+
+ // if ($disk->exists($path)) {
+ // $disk->delete($path);
+ // }
+ // return;
+ // }
+
+ // $invalidCodes = $matchedItems
+ // ->filter(fn ($sticker) => empty($sticker->material_type)) //filter invalid
+ // ->pluck('item.code')
+ // ->toArray();
+
+ // if (count($invalidCodes) > 10)
+ // {
+ // $invalidCodes = array_unique($invalidCodes);
+ // Notification::make()
+ // ->title('Invalid item codes found')
+ // ->body('' . count($invalidCodes) . 'invalid item codes found have serial number.')
+ // ->danger()
+ // ->send();
+
+ // if ($disk->exists($path)) {
+ // $disk->delete($path);
+ // }
+ // return;
+ // }
+ // else if (count($invalidCodes) > 0)
+ // {
+ // $invalidCodes = array_unique($invalidCodes);
+ // Notification::make()
+ // ->title('Invalid item codes found')
+ // ->body('Serial invoice Item Codes found : ' . implode(', ', $invalidCodes))
+ // ->danger()
+ // ->send();
+
+ // if ($disk->exists($path)) {
+ // $disk->delete($path);
+ // }
+ // return;
+ // }
+
+ // $nonNumericQtyCodes = [];
+ // $zeroQtyCodes = [];
+ // $notDivisibleCodes = [];
+
+ // foreach ($matchedItems as $sticker)
+ // {
+ // $code = $sticker->item->code;
+ // $materialType = $sticker->material_type;
+
+ // if ($materialType == 2)
+ // {
+ // $bundleQty = $sticker->bundle_quantity ?? 0;
+ // $totalExcelQty = 0;
+
+ // foreach ($rows as $index => $row)
+ // {
+ // if ($index == 0) continue; // Skip header
+
+ // $excelCode = trim($row[0]);
+ // $excelMatQty = trim($row[1]);
+
+
+ // if ($excelCode == $code && is_numeric($excelMatQty)) {
+ // $totalExcelQty += $excelMatQty; // Sum up the quantities
+ // }
+ // }
+
+ // if ($totalExcelQty == 0) {
+ // $zeroQtyCodes[] = $code;
+ // } elseif (!is_numeric($totalExcelQty)) {
+ // $nonNumericQtyCodes[] = $code; // Here you may want to check divisibility condition too
+ // } elseif ($bundleQty != 0 && $totalExcelQty % $bundleQty != 0) {
+ // $notDivisibleCodes[] = $code;
+ // }
+ // }
+ // }
+
+ // $showValidationNotification = function(array $codes, string $message) {
+ // if (count($codes) == 0) return;
+
+ // $uniqueCodes = array_unique($codes);
+ // $codeList = implode(', ', $uniqueCodes);
+
+ // Notification::make()
+ // ->title('Invalid Bundle Quantity')
+ // ->body("$message
$codeList")
+ // ->danger()
+ // ->send();
+ // };
+
+ // $nonNumericQtyCodes = array_unique($nonNumericQtyCodes);
+ // $zeroQtyCodes = array_unique($zeroQtyCodes);
+ // $notDivisibleCodes = array_unique($notDivisibleCodes);
+
+ // $showValidationNotification($nonNumericQtyCodes, "The following item codes contains invalid bundle quantity:");
+ // $showValidationNotification($zeroQtyCodes, "The following item codes quantity should be greater than '0':");
+ // $showValidationNotification($notDivisibleCodes, "The following item codes quantity is not divisible by bundle quantity.");
+
+ // if ($nonNumericQtyCodes || $zeroQtyCodes || $notDivisibleCodes) {
+ // if ($disk->exists($path))
+ // {
+ // $disk->delete($path);
+ // }
+ // return;
+ // }
+ // else
+ // {
+ // // Save full file path to session
+ // session(['uploaded_material_invoice' => $fullPath]);
+ // Notification::make()
+ // ->title('Material invoice imported successfully.')
+ // ->success()
+ // ->send();
+ // }
+
+ // }
+ // })
+ // ->visible(function() {
+ // return Filament::auth()->user()->can('view import material invoice');
+ // }),
+ ExportAction::make()
+ ->label('Export Invoices')
+ ->color('warning')
+ ->exporter(SerialValidationExporter::class)
+ ->visible(function() {
+ return Filament::auth()->user()->can('view export invoice');
+ }),
+ ])
+ // ->filters([
+ // Tables\Filters\TrashedFilter::make(),
+ // ])
+ ->filters([
+ Tables\Filters\TrashedFilter::make(),
+ Filter::make('advanced_filters')
+ ->label('Advanced Filters')
+ ->form([
+ Radio::make('invoice_type')
+ ->label('Type ?')
+ ->boolean()
+ ->options([
+ 'Serial' => 'Serial',
+ 'Material' => 'Material'
+ ])
+ ->default('Serial')
+ ->inlineLabel(false)
+ ->inline(),
+ Select::make('Plant')
+ ->label('Select Plant')
+ ->nullable()
+ ->options(function () {
+ return Plant::pluck('name', 'id');
+ })
+ ->reactive()
+ ->afterStateUpdated(function ($state, callable $set, callable $get): void {
+ $set('sticker_master_id', null);
+ $set('operator_id', null);
+ }),
+ TextInput::make('invoice_number')
+ ->label('Invoice Number')
+ // ->readOnly()
+ ->placeholder(placeholder: 'Enter Invoice Number'),
+ TextInput::make('serial_number')
+ ->label('Serial Number')
+ ->placeholder(placeholder: 'Enter Serial Number'),
+ Select::make('sticker_master_id')
+ ->label('Search by Item Code')
+ ->nullable()
+ ->options(function (callable $get) {
+ $pId = $get('Plant');
+ // if (empty($pId)) {
+ // return [];
+ // }
+ return Item::whereHas('stickerMasters', function ($query) use ($pId) {
+ if ($pId) {
+ $query->where('plant_id', $pId);
+ }
+ $query->whereHas('invoiceValidations');
+ })->pluck('code', 'id');
+ })
+ ->searchable()
+ ->reactive(),
+ Select::make('scanned_status')
+ ->label('Scanned Status')
+ ->nullable()
+ ->options([
+ 'Scanned' => 'Scanned',
+ 'Pending' => 'Pending',
+ ])
+ ->searchable()
+ ->reactive(),
+ Select::make('operator_id')
+ ->label('Created By')
+ ->nullable()
+ ->options(function (callable $get) {
+ $plantId = $get('Plant');
+ if (!$plantId)
+ {
+ return SerialValidation::whereNotNull('operator_id')->select('operator_id')->distinct()->pluck('operator_id', 'operator_id');
+ }
+ else
+ {
+ return SerialValidation::where('plant_id', $plantId)->whereNotNull('operator_id')->select('operator_id')->distinct()->pluck('operator_id', 'operator_id');
+ }
+ })
+ ->searchable()
+ ->reactive(),
+ DateTimePicker::make(name: 'created_from')
+ ->label('Created From')
+ ->placeholder(placeholder: 'Select From DateTime')
+ ->reactive()
+ ->native(false),
+ DateTimePicker::make('created_to')
+ ->label('Created To')
+ ->placeholder(placeholder: 'Select To DateTime')
+ ->reactive()
+ ->native(false),
+ ])
+ ->query(function ($query, array $data) {
+ // Hide all records initially if no filters are applied
+ if (empty($data['invoice_type']) || (empty($data['Plant']) && empty($data['invoice_number']) && empty($data['serial_number']) && empty($data['created_from']) && empty($data['created_to']) && empty($data['operator_id']) && empty($data['scanned_status']) && empty($data['sticker_master_id']))) {
+ if (empty($data['invoice_type']))
+ {
+ Notification::make()
+ ->title('Please, choose invoice type to filter.')
+ ->danger()
+ ->send();
+ }
+ return $query->whereRaw('1 = 0');
+ }
+
+ if ($data['invoice_type'] == 'Serial') {
+ $query->whereNull('quantity');
+
+ if (!empty($data['scanned_status'])) {
+ if ($data['scanned_status'] == 'Scanned') {
+ $query->whereNotNull('scanned_status')->where('scanned_status', '!=', '');
+ } elseif ($data['scanned_status'] == 'Pending') {
+ //$query->whereNull('scanned_status')->orWhere('scanned_status', '');
+ $query->where(function ($query) use ($data) {
+ // if (empty($data['scanned_status']) || $data['scanned_status'] == 'Pending') {
+ $query->whereNull('scanned_status')->orWhere('scanned_status', '!=', 'Scanned');
+ // }
+ });
+ }
+ }
+ } elseif ($data['invoice_type'] == 'Material') {
+ $query->whereNotNull('quantity');//->where('quantity', '>', 0)
+
+ if (!empty($data['scanned_status'])) {
+ if ($data['scanned_status'] == 'Scanned') {
+ $query->whereNotNull('serial_number')->where('serial_number', '!=', '');
+ } elseif ($data['scanned_status'] == 'Pending') {
+ $query->where(function ($query) use ($data) {
+ $query->whereNull('serial_number')->orWhere('serial_number', '=', '');
+ });
+ }
+ }
+ }
+
+ if (!empty($data['Plant'])) { //$plant = $data['Plant'] ?? null
+ $query->where('plant_id', $data['Plant']);
+ }
+
+ if (!empty($data['invoice_number'])) {
+ $query->where('invoice_number', 'like', '%' . $data['invoice_number'] . '%');
+ }
+
+ if (!empty($data['serial_number'])) {
+ $query->where('serial_number', 'like', '%' . $data['serial_number'] . '%');
+ }
+
+ if (!empty($data['created_from'])) {
+ $query->where('created_at', '>=', $data['created_from']);
+ }
+
+ if (!empty($data['created_to'])) {
+ $query->where('created_at', '<=', $data['created_to']);
+ }
+
+ if (!empty($data['operator_id'])) {
+ $query->where('operator_id', $data['operator_id']);
+ }
+
+ if (!empty($data['sticker_master_id'])) {
+ $stickerMasterIds = StickerMaster::where('item_id', $data['sticker_master_id'])
+ ->pluck('id')
+ ->toArray();
+
+ if (!empty($stickerMasterIds)) {
+ $query->whereIn('sticker_master_id', $stickerMasterIds);
+ }
+ }
+ })
+ ->indicateUsing(function (array $data) {
+ $indicators = [];
+
+ if (!empty($data['Plant'])) {
+ $indicators[] = 'Plant: ' . Plant::where('id', $data['Plant'])->value('name');
+ }
+
+ if (!empty($data['invoice_number'])) {
+ $indicators[] = 'Invoice Number: ' . $data['invoice_number'];
+ }
+
+ if (!empty($data['serial_number'])) {
+ $indicators[] = 'Serial Number: ' . $data['serial_number'];
+ }
+
+ if (!empty($data['sticker_master_id'])) {
+ $itemCode = Item::find($data['sticker_master_id'])->code ?? 'Unknown';
+ $indicators[] = 'Item Code: ' . $itemCode;
+ }
+
+ if (!empty($data['operator_id'])) {
+ $indicators[] = 'Created By: ' . $data['operator_id'];
+ }
+
+ if (!empty($data['created_from'])) {
+ $indicators[] = 'From: ' . $data['created_from'];
+ }
+
+ if (!empty($data['created_to'])) {
+ $indicators[] = 'To: ' . $data['created_to'];
+ }
+
+ if (!empty($data['scanned_status'])) {
+ $indicators[] = 'Scanned Status: ' . $data['scanned_status'];
+ }
+
+ return $indicators;
+ })
+ ])
+ ->filtersFormMaxHeight('280px')
+ ->actions([
+ Tables\Actions\ViewAction::make(),
+ Tables\Actions\EditAction::make(),
+ ])
+ ->bulkActions([
+ Tables\Actions\BulkActionGroup::make([
+ Tables\Actions\DeleteBulkAction::make(),
+ Tables\Actions\ForceDeleteBulkAction::make(),
+ Tables\Actions\RestoreBulkAction::make(),
+ ]),
+ ]);
+ }
+
+ public static function getRelations(): array
+ {
+ return [
+ //
+ ];
+ }
+
+ public static function getPages(): array
+ {
+ return [
+ 'index' => Pages\ListSerialValidations::route('/'),
+ 'create' => Pages\CreateSerialValidation::route('/create'),
+ 'view' => Pages\ViewSerialValidation::route('/{record}'),
+ 'edit' => Pages\EditSerialValidation::route('/{record}/edit'),
+ ];
+ }
+
+ public static function getEloquentQuery(): Builder
+ {
+ return parent::getEloquentQuery()
+ ->withoutGlobalScopes([
+ SoftDeletingScope::class,
+ ]);
+ }
+}
diff --git a/app/Filament/Resources/SerialValidationResource/Pages/CreateSerialValidation.php b/app/Filament/Resources/SerialValidationResource/Pages/CreateSerialValidation.php
new file mode 100644
index 0000000..15eea23
--- /dev/null
+++ b/app/Filament/Resources/SerialValidationResource/Pages/CreateSerialValidation.php
@@ -0,0 +1,2958 @@
+getCancelFormAction(),
+ ];
+ }
+
+ protected function getRedirectUrl(): string
+ {
+ return $this->getResource()::getUrl('create');
+ }
+
+ public function processInvoice($invoiceNumber)
+ {
+ $invoiceNumber = trim($invoiceNumber);
+
+ $this->showCapacitorInput = false;
+
+ $user = Filament::auth()->user();
+
+ $operatorName = $user->name;
+
+ $plantId = $this->form->getState()['plant_id'];
+
+ $this->plantId = $plantId;
+
+ $plant = Plant::find($plantId);
+
+ if ($plant)
+ {
+ $plantCode = $plant->code;
+ }
+ else
+ {
+ $plantCode = null;
+ }
+
+ //..GET SERIAL INVOICE API
+
+
+ //..
+
+ $updateStatus = $this->form->getState()['update_invoice'] ?? null;
+
+ $this->invoiceNumber = trim($this->form->getState()['invoice_number']) ?? $invoiceNumber;
+
+ $invoiceType = null;
+ //$this->invoiceNumber = $this->invoiceNumber ?? $invoiceNumber;
+
+ $invoiceExist = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->exists();
+
+ if (!$invoiceExist) {
+ Notification::make()
+ ->title("New invoice detected.")
+ ->info()
+ ->seconds(1)
+ ->send();
+ $this->dispatch('playNotificationSound');
+
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => 0,
+ 'scanned_quantity'=> 0,
+ ]);
+ $this->dispatch('refreshEmptyInvoice', invoiceNumber: $invoiceNumber, plantId: $plantId);
+ }
+ else
+ {
+ $totQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ $scanSQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('scanned_status', 'Scanned')->where('plant_id', $plantId)->count();
+ $totMQuan = SerialValidation::where('invoice_number', $invoiceNumber)->whereNotNull('quantity')->where('plant_id', $plantId)->count(); //->where('quantity', '!=', '')
+ $scanMQuan = SerialValidation::where('invoice_number', $invoiceNumber)->whereNotNull('serial_number')->where('serial_number', '!=', '')->where('plant_id', $plantId)->count();
+
+ if($totMQuan > 0)
+ {
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totQuan,
+ 'scanned_quantity'=> $scanMQuan,
+ ]);
+
+ if ($totQuan == $scanMQuan)
+ {
+ Notification::make()
+ ->title("Completed: Material Invoice")
+ ->body("Material invoice '$invoiceNumber' completed the scanning process.
Scan the next 'Material Invoice' to proceed!")
+ ->warning()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playNotificationSound');
+
+ $filename = $invoiceNumber . '.xlsx';
+ $directory = 'uploads/temp';
+ $disk = Storage::disk('local');
+ $filePath = $directory . '/' . $filename;
+ //$fullPath = null;
+ if ($disk->exists($filePath)) {
+ //$fullPath = $disk->path($filePath);
+ $disk->delete($filePath);
+ }
+ $this->dispatch('refreshCompletedInvoice', invoiceNumber: $invoiceNumber, plantId: $plantId, isSerial: false);
+ }
+ else
+ {
+ Notification::make()
+ ->title("Start the scanning process!")
+ ->info()
+ ->seconds(1)
+ ->send();
+ $this->dispatch('playNotificationSound');
+ // $hasRecords = InvoiceValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->first()->stickerMasterRelation->material_type ?? null;
+ // $this->dispatch( (!empty($hasRecords) && $hasRecords) ? 'refreshMaterialInvoiceData' : 'refreshInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId); //$this->invoiceNumber
+ $this->dispatch('refreshMaterialInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId);
+
+ if($updateStatus == '1')
+ {
+ //'Material invoice update in progress...';
+ $filename = $invoiceNumber . '.xlsx';
+ $directory = 'uploads/temp';
+ $disk = Storage::disk('local');
+ $filePath = $directory . '/' . $filename;
+ $fullPath = $disk->path($filePath);
+
+ if ($fullPath && file_exists($fullPath))
+ {
+ // Now you can read/process the file here
+ $rows = Excel::toArray(null, $fullPath)[0];
+
+ if((count($rows) - 1) <= 0)
+ {
+ Notification::make()
+ ->title('Records Not Found')
+ ->body("Import the valid updated 'Material Invoice' file to proceed..!")
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $invalidMatCodes = [];
+ $materialCodes = [];
+ $missingQuantities = [];
+ $invalidMatQuan = [];
+ $hasQuanTypIds = [];
+ $validRowsFound = false;
+
+ foreach ($rows as $index => $row)
+ {
+ if ($index == 0) continue; // Skip header
+
+ $materialCode = trim($row[0]);
+ $materialQuantity = trim($row[1]);
+
+ if (empty($materialCode) && empty($materialQuantity)) {
+ continue;
+ }
+
+ if (!empty($materialCode)) {
+ if(Str::length($materialCode) < 6 || !ctype_alnum($materialCode))
+ {
+ $invalidMatCodes[] = $materialCode;
+ }
+ else
+ {
+ if (empty($materialQuantity)) {
+ $missingQuantities[] = $materialCode;
+ }
+ else if(!is_numeric($materialQuantity))
+ {
+ $invalidMatQuan[] = $materialCode;
+ }
+ else if($materialQuantity == 0)
+ {
+ $invalidMatQuan[] = $materialCode;
+ }
+ else
+ {
+ $materialCodes[] = $materialCode;
+ $validRowsFound = true;
+ }
+ }
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ if (!$validRowsFound) {
+ Notification::make()
+ ->title('Invalid Material Invoice')
+ ->danger() // This makes the notification red to indicate an error
+ ->body('Uploaded Excel sheet is empty or
contains no valid data.')
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $uniqueInvalidCodes = array_unique($invalidMatCodes);
+
+ if (!empty($uniqueInvalidCodes)) {
+ Notification::make()
+ ->title('Invalid: Item Codes')
+ ->body('The following item codes should contain minimum 6 digit alpha numeric values:
' . implode(', ', $uniqueInvalidCodes))
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $uniqueMissingQuanCodes = array_unique($missingQuantities);
+
+ if (!empty($uniqueMissingQuanCodes)) {
+ Notification::make()
+ ->title('Missing Material Quantity')
+ ->body("The following item codes doesn't have valid material quantity:
" . implode(', ', $uniqueMissingQuanCodes))
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $uniqueInvalidMatQuan = array_unique($invalidMatQuan);
+
+ if (!empty($uniqueInvalidMatQuan)) {
+ Notification::make()
+ ->title('Invalid Material Quantity')
+ ->body("The following item codes doesn't have valid material quantity:
" . implode(', ', $uniqueInvalidMatQuan))
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $uniqueCodes = array_unique($materialCodes);
+
+ //itemNotFound
+ $matchedItems = StickerMaster::with('item')
+ ->whereHas('item', function ($query) use ($uniqueCodes) {
+ $query->whereIn('code', $uniqueCodes);
+ })
+ ->get();
+
+ $matchedCodes = $matchedItems->pluck('item.code')->toArray();
+
+ $missingCodes = array_diff($uniqueCodes, $matchedCodes);
+
+ if (!empty($missingCodes))
+ {
+ $missingCount = count($missingCodes);
+
+ $message = $missingCount > 10 ? "'$missingCount' item codes are not found in database." : 'The following item codes are not found in database:
' . implode(', ', $missingCodes);
+
+ Notification::make()
+ ->title('Unknown: Item Codes')
+ ->body($message)
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ //plantNotFound
+ $matchedItems = StickerMaster::with('item')
+ ->whereHas('item', function ($query) use ($uniqueCodes, $plantId) {
+ $query->whereIn('code', $uniqueCodes)->where('plant_id', $plantId);
+ })
+ ->get();
+
+ $matchedCodes = $matchedItems->pluck('item.code')->toArray();
+
+ $missingCodes = array_diff($uniqueCodes, $matchedCodes);
+
+ if (!empty($missingCodes))
+ {
+ $missingCount = count($missingCodes);
+
+ $message = $missingCount > 10 ? "'$missingCount' item codes are not found in database for choosed plant." : 'The following item codes are not found in database for choosed plant:
' . implode(', ', $missingCodes);
+
+ Notification::make()
+ ->title('Unknown: Item Codes')
+ ->body($message)
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $invalidCodes = $matchedItems
+ ->filter(fn ($sticker) => empty($sticker->material_type)) //filter invalid
+ ->pluck('item.code')
+ ->toArray();
+
+
+ if (!empty($invalidCodes))
+ {
+ $missingCount = count($invalidCodes);
+
+ $message = $missingCount > 10 ? "'$missingCount' Serial Invoice item codes found." : "'Serial Invoice' item codes found:
" . implode(', ', $invalidCodes);
+
+ Notification::make()
+ ->title('Invalid: Item Codes')
+ ->body($message)
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $nonNumericQtyCodes = [];
+ $zeroQtyCodes = [];
+ $notDivisibleCodes = [];
+ $hasQuanTyp = false;
+
+ foreach ($matchedItems as $sticker)
+ {
+ $code = $sticker->item->code;
+ $materialType = $sticker->material_type;
+
+ if ($materialType == 2)
+ {
+ $bundleQty = $sticker->bundle_quantity ?? 0;
+ $totalExcelQty = 0;
+
+ foreach ($rows as $index => $row)
+ {
+ if ($index == 0) continue; // Skip header
+
+ $excelCode = trim($row[0]);
+ $excelMatQty = trim($row[1]);
+
+ if (empty($excelCode) || empty($excelMatQty)) {
+ continue;
+ }
+
+ if ($excelCode == $code && is_numeric($excelMatQty)) {
+ $totalExcelQty += $excelMatQty; // Sum up the quantities
+ }
+ }
+
+ if ($totalExcelQty == 0) {
+ $zeroQtyCodes[] = $code;
+ } elseif (!is_numeric($totalExcelQty)) {
+ $nonNumericQtyCodes[] = $code; // Here you may want to check divisibility condition too
+ } elseif ($bundleQty != 0 && $totalExcelQty % $bundleQty != 0) {
+ $notDivisibleCodes[] = $code;
+ }
+ }
+ else if ($materialType == 3)
+ {
+ $hasQuanTyp = true;
+ $hasQuanTypIds[] = $sticker->id;
+ }
+ }
+
+ $showValidationNotification = function(array $codes, string $message) {
+ if (count($codes) == 0) return;
+
+ $uniqueCodes = array_unique($codes);
+ $codeList = implode(', ', $uniqueCodes);
+
+ Notification::make()
+ ->title('Invalid Bundle Quantity')
+ ->body("$message
$codeList")
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+ };
+
+ $showValidationNotification($nonNumericQtyCodes, "The following item codes contains invalid bundle quantity:");
+ $showValidationNotification($zeroQtyCodes, "The following item codes quantity should be greater than '0':");
+ $showValidationNotification($notDivisibleCodes, "The following item codes quantity is not divisible by bundle quantity.");
+
+
+ if ($nonNumericQtyCodes || $zeroQtyCodes || $notDivisibleCodes) {
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+ else
+ {
+ $oldQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ $newQuan = -1;
+
+ $inserted = 0;
+ foreach ($matchedItems as $sticker)
+ {
+ if ($newQuan == -1 && !$hasQuanTyp)
+ {
+ SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->where(function($query) {
+ $query->whereNull('serial_number')->orWhere('serial_number', '');
+ })
+ ->forceDelete(); //->delete();
+
+ $newQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ }
+ else if ($newQuan == -1 && $hasQuanTyp)
+ {
+ SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->where(function($query) {
+ $query->whereNull('serial_number')->orWhere('serial_number', '');
+ })->whereNotIn('sticker_master_id', $hasQuanTypIds)
+ ->forceDelete(); //->delete();
+
+ $newQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ }
+
+ $code = $sticker->item->code;
+ $materialType = $sticker->material_type;
+ // $sticker = StickerMaster::where('plant_id', $plantId)->whereHas('item', function ($query) use ($code) { $query->where('plant_id', $this->plantId)->where('code', $code); })->first();
+
+ if ($materialType == 1)
+ {
+ $totalExcelQty = 0;
+
+ foreach ($rows as $index => $row)
+ {
+ if ($index == 0) continue; // Skip header
+
+ $excelCode = trim($row[0]);
+ $excelMatQty = trim($row[1]);
+
+ if (empty($excelCode) || empty($excelMatQty)) {
+ continue;
+ }
+
+ if ($excelCode == $code && is_numeric($excelMatQty)) {
+ $totalExcelQty += $excelMatQty; // Sum up the quantities
+ }
+ }
+
+ $existQty = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->where('sticker_master_id', $sticker->id)->count();
+
+ if ($existQty < $totalExcelQty)
+ {
+ $newQty = $totalExcelQty - $existQty;
+ for ($i = 0; $i < $newQty; $i++)
+ {
+ if ($sticker) {
+ SerialValidation::create([
+ 'sticker_master_id' => $sticker->id,
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'quantity' => 1,
+ 'operator_id'=> $operatorName,
+ ]);
+ $inserted++;
+ }
+ }
+ }
+ }
+ else if ($materialType == 2)
+ {
+ $bundleQty = $sticker->bundle_quantity;
+ $totalExcelQty = 0;
+
+ foreach ($rows as $index => $row)
+ {
+ if ($index == 0) continue; // Skip header
+
+ $excelCode = trim($row[0]);
+ $excelMatQty = trim($row[1]);
+
+ if (empty($excelCode) || empty($excelMatQty)) {
+ continue;
+ }
+
+ if ($excelCode == $code && is_numeric($excelMatQty)) {
+ $totalExcelQty += $excelMatQty; // Sum up the quantities
+ }
+ }
+
+ $existQty = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->where('sticker_master_id', $sticker->id)->count();
+
+ //for ($i = 0; $i < ($totalExcelQty/$bundleQty); $i++)
+ $newTotQty = $totalExcelQty/$bundleQty;
+ if ($existQty < $newTotQty)
+ {
+ $newQty = $newTotQty - $existQty;
+ for ($i = 0; $i < $newQty; $i++)
+ {
+ if ($sticker) {
+ SerialValidation::create([
+ 'sticker_master_id' => $sticker->id,
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'quantity' => $bundleQty,
+ 'operator_id'=> $operatorName,
+ ]);
+ $inserted++;
+ }
+ }
+ }
+ }
+ else if ($materialType == 3)
+ {
+ $totalExcelQty = 0;
+
+ foreach ($rows as $index => $row)
+ {
+ if ($index == 0) continue; // Skip header
+
+ $excelCode = trim($row[0]);
+ $excelMatQty = trim($row[1]);
+
+ if (empty($excelCode) || empty($excelMatQty)) {
+ continue;
+ }
+
+ if ($excelCode == $code && is_numeric($excelMatQty)) {
+ $totalExcelQty += $excelMatQty;
+ }
+ }
+
+ $existEmpRecQty = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->where(function($query) {
+ $query->whereNull('serial_number')->orWhere('serial_number', '');
+ })->where('sticker_master_id', $sticker->id)->first();
+ $existEmpQty = $existEmpRecQty ? $existEmpRecQty->quantity : 0;
+
+ $existComQty = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->where(function($query) {
+ $query->whereNotNull('serial_number')->where('serial_number', '!=', '');
+ })
+ ->where('sticker_master_id', $sticker->id)
+ ->sum(column: 'quantity');
+ $existComQty = $existComQty ? $existComQty : 0;
+
+ // 8 = 3 + 5 // 8 = 5 + 3 // 8 = 0 + 8 // 8 = 8 + 0
+ // 8 = 3 + 5 // 8 = 5 + 3 // 8 = 0 + 8 // 8 = 8 + 0
+ // 0 = 0 + 0
+ $existQty = $existEmpQty + $existComQty;
+
+ // 8 <= 11 // 8 <= 8 // 8 <= 11 // 8 <= 9
+ // 8 <= 7 // 8 <= 7 // 8 <= 7 // 8 <= 7
+ // 0 <= 5
+
+ if ($existQty <= $totalExcelQty)
+ {
+ // 6 = 11 - 5 // 5 = 8 - 3 // 3 = 11 - 8 // 9 = 9 - 0
+ // 5 = 5 - 0
+ $newInsQty = $totalExcelQty - $existComQty;
+
+ // 3 > 0 // 5 > 0 // 0 > 0 // 8 > 0
+ // 0 > 0
+ if($existEmpQty > 0) // update
+ {
+ // 3 = 6 // 5 = 5 // 0 = 3 // 8 = 9
+ // 0 = 5
+ if($existEmpQty == $newInsQty) { continue; }
+ // $existEmpRecQty->delete();
+ $existEmpRecQty->update([
+ 'quantity' => $newInsQty,
+ 'operator_id'=> $operatorName,
+ 'updated_at' => now(),
+ ]);
+ $newQuan--;
+ $inserted++;
+ }
+ else if ($newInsQty > 0) // if ($sticker) // create
+ {
+ SerialValidation::create([
+ 'sticker_master_id' => $sticker->id,
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'quantity' => $newInsQty,
+ 'operator_id'=> $operatorName,
+ ]);
+ $inserted++;
+ }
+ }
+ // 8 > 7 // 8 > 7 // 8 > 7 // 8 > 7
+ else
+ {
+ // 2 = 7 - 5 // 4 = 7 - 3 // -1 = 7 - 8 // 7 = 7 - 0
+ $newInsQty = $totalExcelQty - $existComQty;
+
+ // 3 > 0 // 5 > 0 // 0 > 0 // 8 > 0
+ if($existEmpQty > 0) // update
+ {
+ // 3 = 2 // 5 = 4 // 0 = -1 // 8 = 7
+ if($existEmpQty == $newInsQty) { continue; }
+ // $existEmpRecQty->delete();
+ $existEmpRecQty->update([
+ 'quantity' => $newInsQty,
+ 'operator_id'=> $operatorName,
+ 'updated_at' => now(),
+ ]);
+ $newQuan--;
+ $inserted++;
+ }
+ else if ($newInsQty > 0) // create
+ {
+ SerialValidation::create([
+ 'sticker_master_id' => $sticker->id,
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'quantity' => $newInsQty,
+ 'operator_id'=> $operatorName,
+ ]);
+ $inserted++;
+ }
+ }
+
+ }
+ }
+
+ if ($inserted > 0 || $oldQuan != $newQuan)
+ {
+ Notification::make()
+ ->title("Material invoice successfully updatad.")
+ ->success()
+ ->seconds(1)
+ ->send();
+
+ Notification::make()
+ ->title("Start the scanning process!")
+ ->body("'$inserted' new material invoice records were inserted.")
+ ->info()
+ // ->success()
+ ->seconds(1)
+ ->send();
+ $this->dispatch('playNotificationSound');
+
+ // Update total quantity in the form
+ $totalQuantity = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ $scannedQuantity = SerialValidation::where('invoice_number', $invoiceNumber)->whereNotNull('serial_number')->where('serial_number', '!=', '')->where('plant_id', $plantId)->count();
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totalQuantity,
+ 'scanned_quantity'=> $scannedQuantity,
+ ]);
+
+ if ($totalQuantity == $scannedQuantity)
+ {
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+
+ $this->dispatch('refreshCompletedInvoice', invoiceNumber: $invoiceNumber, plantId: $plantId, isSerial: false);
+ }
+ else
+ {
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+
+ $this->dispatch('refreshMaterialInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId);
+ }
+ }
+ else
+ {
+ Notification::make()
+ ->title("Update Failed: Material Invoice")
+ ->body("No new records were inserted for Material Invoice : '$invoiceNumber'.")
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ $totalQuantity = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ $scannedQuantity = SerialValidation::where('invoice_number', $invoiceNumber)->whereNotNull('serial_number')->where('serial_number', '!=', '')->where('plant_id', $plantId)->count();
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totalQuantity,
+ 'scanned_quantity'=> $scannedQuantity,
+ ]);
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+
+ $this->dispatch('refreshEmptyInvoice', invoiceNumber: $invoiceNumber, plantId: $plantId);
+ return;
+ }
+ }
+ }
+ else
+ {
+ Notification::make()
+ ->title('Updated Invoice Not Found')
+ ->body("Import the updated 'Material Invoice' file to proceed..!")
+ ->danger()
+ ->seconds(2)
+ ->send();
+
+ $this->dispatch('playWarnSound');
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => 0,
+ 'scanned_quantity'=> 0,
+ ]);
+ $this->dispatch('refreshEmptyInvoice', invoiceNumber: $invoiceNumber, plantId: $plantId);
+ return;
+ }
+ }
+ }
+ return;
+ }
+ else
+ {
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totQuan,
+ 'scanned_quantity'=> $scanSQuan,
+ ]);
+ //$hasRecords = InvoiceValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->first()->stickerMasterRelation->material_type ?? null;
+ // $this->dispatch('refreshInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId);
+
+ if ($totQuan == $scanSQuan)
+ {
+ Notification::make()
+ ->title("Completed: Serial Invoice")
+ ->body("Serial invoice '$invoiceNumber' completed the scanning process.
Scan the next 'Serial Invoice' to proceed.!")
+ ->warning()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playNotificationSound');
+
+ $filename = $invoiceNumber . '.xlsx';
+ $directory = 'uploads/temp';
+ $disk = Storage::disk('local');
+ $filePath = $directory . '/' . $filename;
+ //$fullPath = null;
+ if ($disk->exists($filePath)) {
+ //$fullPath = $disk->path($filePath);
+ $disk->delete($filePath);
+ }
+ $this->dispatch('playNotificationSound');
+ $this->dispatch('refreshCompletedInvoice', invoiceNumber: $invoiceNumber, plantId: $plantId, isSerial: true);
+ }
+ else
+ {
+ Notification::make()
+ ->title("Start the scanning process!")
+ ->info()
+ ->seconds(1)
+ ->send();
+ $this->dispatch('playNotificationSound');
+ $this->dispatch('refreshInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId);
+
+ if($updateStatus == '1')
+ {
+ $filename = $invoiceNumber . '.xlsx';
+ $directory = 'uploads/temp';
+ $disk = Storage::disk('local');
+ $filePath = $directory . '/' . $filename;
+ $fullPath = $disk->path($filePath);
+
+ // Check if file exists //$disk->exists($filePath)
+ if ($fullPath && file_exists($fullPath))
+ {
+ // /home/iot-dev/projects/pds/storage/app/private/uploads/temp/3RA0018735.xlsx
+ // 'Serial invoice update in progress...'
+
+ // Now you can read/process the file here
+ $rows = Excel::toArray(null, $fullPath)[0];
+
+ if((count($rows) - 1) <= 0)
+ {
+ Notification::make()
+ ->title('Records Not Found')
+ ->body("Import the valid updated 'Serial Invoice' file to proceed..!")
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $invalidMatCodes = [];
+ $materialCodes = [];
+ $missingSerials = [];
+ $invalidSerCodes = [];
+ $duplicateSerials = [];
+ $serialNumbers = [];
+ $validRowsFound = false;
+
+ foreach ($rows as $index => $row)
+ {
+ if ($index == 0) continue; // Skip header
+
+ $materialCode = trim($row[0]);
+ $serialNumber = trim($row[1]);
+
+ if (empty($materialCode) && empty($serialNumber))
+ {
+ continue;
+ }
+
+ if (!empty($materialCode))
+ {
+ if(Str::length($materialCode) < 6 || !ctype_alnum($materialCode))
+ {
+ $invalidMatCodes[] = $materialCode;
+ continue;
+ }
+ else
+ {
+ if(empty($serialNumber)) {
+ $missingSerials[] = $materialCode;
+ }
+ else if(Str::length($serialNumber) < 9 || !ctype_alnum($serialNumber))
+ {
+ $invalidSerCodes[] = $serialNumber;
+ }
+ else
+ {
+ if (in_array($serialNumber, $serialNumbers))
+ {
+ $duplicateSerials[] = $serialNumber;
+ }
+ else
+ {
+ $serialNumbers[] = $serialNumber;
+ $materialCodes[] = $materialCode;
+ $validRowsFound = true;
+ }
+ }
+ }
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ if (!$validRowsFound) {
+ Notification::make()
+ ->title('Invalid Serial Invoice')
+ ->danger() // This makes the notification red to indicate an error
+ ->body('Uploaded excel sheet is empty or
contains no valid data.')
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $uniqueInvalidCodes = array_unique($invalidMatCodes);
+
+ if (!empty($uniqueInvalidCodes)) {
+ Notification::make()
+ ->title('Invalid: Item Codes')
+ ->body('The following item codes should contain minimum 6 digit alpha numeric values:
' . implode(', ', $uniqueInvalidCodes))
+ ->danger()
+ ->seconds(2)
+ ->send();
+
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $uniqueCodes = array_unique($materialCodes);
+
+ //itemNotFound
+ $matchedItems = StickerMaster::with('item')
+ ->whereHas('item', function ($query) use ($uniqueCodes) {
+ $query->whereIn('code', $uniqueCodes);
+ })
+ ->get();
+
+ $matchedCodes = $matchedItems->pluck('item.code')->toArray();
+
+ $missingCodes = array_diff($uniqueCodes, $matchedCodes);
+
+ if (!empty($missingCodes))
+ {
+ $missingCount = count($missingCodes);
+
+ $message = $missingCount > 10 ? "'$missingCount' item codes are not found in database." : 'The following item codes are not found in database:
' . implode(', ', $missingCodes); //->where('plant_id', $plantId)
+
+ Notification::make()
+ ->title('Unknown: Item Codes')
+ ->body($message)
+ ->danger()
+ ->seconds(2)
+ ->send();
+
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ //plantNotFound
+ $matchedItems = StickerMaster::with('item')
+ ->whereHas('item', function ($query) use ($uniqueCodes, $plantId) {
+ $query->whereIn('code', $uniqueCodes)->where('plant_id', $plantId);
+ })
+ ->get();
+
+ $matchedCodes = $matchedItems->pluck('item.code')->toArray();
+
+ $missingCodes = array_diff($uniqueCodes, $matchedCodes);
+
+ if (!empty($missingCodes))
+ {
+ $missingCount = count($missingCodes);
+
+ $message = $missingCount > 10 ? "'$missingCount' item codes are not found in database for choosed plant." : 'The following item codes are not found in database for choosed plant:
' . implode(', ', $missingCodes);
+
+ Notification::make()
+ ->title('Unknown: Item Codes')
+ ->body($message)
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $invalidCodes = $matchedItems
+ ->filter(fn ($sticker) => !empty($sticker->material_type)) //filter invalid
+ ->pluck('item.code')
+ ->toArray();
+
+ if (!empty($invalidCodes))
+ {
+ $missingCount = count($invalidCodes);
+
+ $message = $missingCount > 10 ? "'$missingCount' Material Invoice item codes found." : "'Material Invoice' item codes found:
" . implode(', ', $invalidCodes);
+
+ Notification::make()
+ ->title('Invalid: Item Codes')
+ ->body($message)
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $missPackCodes = $matchedItems
+ ->filter(fn ($sticker) => empty($sticker->tube_sticker_motor) && empty($sticker->pack_slip_motor) && empty($sticker->tube_sticker_pump) && empty($sticker->pack_slip_pump) && empty($sticker->tube_sticker_pumpset) && empty($sticker->pack_slip_pumpset) && empty($sticker->panel_box_code)) //filter invalid
+ ->pluck('item.code')
+ ->toArray();
+
+ if (!empty($missPackCodes))
+ {
+ $missingCount = count($missPackCodes);
+
+ $message = $missingCount > 10 ? "'$missingCount' item codes doesn't have valid package type to proceed!" : "The following 'Item Code' doesn't have valid package type:
" . implode(', ', $missPackCodes);
+
+ Notification::make()
+ ->title('Invalid: Item Codes')
+ ->body($message)
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $uniqueMissingSerials = array_unique($missingSerials);
+
+ if (!empty($uniqueMissingSerials)) {
+ Notification::make()
+ ->title('Missing Serial Numbers')
+ ->body("The following item codes doesn't have valid serial number:
" . implode(', ', $uniqueMissingSerials))
+ ->danger()
+ ->seconds(2)
+ ->send();
+
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $uniqueInvalidSerCodes = array_unique($invalidSerCodes);
+
+ if (!empty($uniqueInvalidSerCodes)) {
+ Notification::make()
+ ->title('Invalid Serial Numbers')
+ ->body('The following serial numbers should contain minimum 9 digit alpha numeric values:
' . implode(', ', $uniqueInvalidSerCodes))
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $uniqueDupSerCodes = array_unique($duplicateSerials);
+
+ if (!empty($uniqueDupSerCodes)) {
+ Notification::make()
+ ->title('Duplicate Serial Numbers')
+ ->body('The following serial numbers are already exist in invoice excel:
' . implode(', ', $uniqueDupSerCodes))
+ ->danger()
+ ->seconds(2)
+ ->send();
+
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $oldQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ $newQuan = 0;
+
+ $inserted = 0;
+ foreach ($rows as $index => $row)
+ {
+ if ($index == 0) // Skip header;
+ {
+ SerialValidation::where('invoice_number', $invoiceNumber)
+ ->where(function($query) {
+ $query->whereNull('motor_scanned_status')->orWhere('motor_scanned_status', '');
+ })
+ ->where(function($query) {
+ $query->whereNull('pump_scanned_status')->orWhere('pump_scanned_status', '');
+ })
+ ->where(function($query) {
+ $query->whereNull('capacitor_scanned_status')->orWhere('capacitor_scanned_status', '');
+ })
+ ->where(function($query) {
+ $query->whereNull('scanned_status_set')->orWhere('scanned_status_set', '');
+ })
+ ->where(function($query) {
+ $query->whereNull('scanned_status')->orWhere('scanned_status', '');
+ })
+ ->forceDelete(); //->delete();
+
+ $newQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ continue;
+ }
+
+ $materialCode = trim($row[0]);
+ $serialNumber = trim($row[1]);
+
+ if (empty($materialCode) || empty($serialNumber)) {
+ continue;
+ }
+
+ $sNoExist = SerialValidation::where('serial_number', $serialNumber)->where('plant_id', $plantId)->exists(); //->pluck('serial_number')
+
+ if($sNoExist) { continue; }
+
+ $sticker = StickerMaster::where('plant_id', $plantId)->whereHas('item', function ($query) use ($materialCode) {
+ $query->where('plant_id', $this->plantId)->where('code', $materialCode); //Check if item.code matches Excel's materialCode
+ })->first();
+
+ if ($sticker) {
+ SerialValidation::create([
+ 'sticker_master_id' => $sticker->id,
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => $serialNumber,
+ 'operator_id'=> $operatorName,
+ ]);
+ $inserted++;
+ }
+ }
+
+ if ($inserted > 0 || $oldQuan != $newQuan)
+ {
+ Notification::make()
+ ->title("Serial invoice successfully updated.")
+ ->success()
+ ->seconds(1)
+ ->send();
+
+ Notification::make()
+ ->title("Start the scanning process!")
+ ->body("'$inserted' new serial invoice records were inserted.")
+ ->info()
+ // ->success()
+ ->seconds(1)
+ ->send();
+
+ $this->dispatch('playNotificationSound');
+
+ // Update total quantity in the form
+ $totalQuantity = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ $scannedQuantity = SerialValidation::where('invoice_number', $invoiceNumber)->where('scanned_status', 'Scanned')->where('plant_id', $plantId)->count();
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totalQuantity,
+ 'scanned_quantity'=> $scannedQuantity,
+ ]);
+
+ if ($totalQuantity == $scannedQuantity)
+ {
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+
+ $this->dispatch('refreshCompletedInvoice', invoiceNumber: $invoiceNumber, plantId: $plantId, isSerial: true);
+ }
+ else
+ {
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ // $hasRecords = InvoiceValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->first()->stickerMasterRelation->material_type ?? null;
+ // $this->dispatch( (!empty($hasRecords) && $hasRecords) ? 'refreshMaterialInvoiceData' : 'refreshInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId); //$this->invoiceNumber
+ $this->dispatch('refreshInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId);
+ }
+ }
+ else
+ {
+ Notification::make()
+ ->title("Update Failed: Serial Invoice")
+ ->body("No new records were inserted for Serial Invoice : '$invoiceNumber'.")
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ $totalQuantity = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ $scannedQuantity = SerialValidation::where('invoice_number', $invoiceNumber)->where('scanned_status', 'Scanned')->where('plant_id', $plantId)->count();
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totalQuantity,
+ 'scanned_quantity'=> $scannedQuantity,
+ ]);
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+
+ $this->dispatch('refreshEmptyInvoice', invoiceNumber: $invoiceNumber, plantId: $plantId);
+ return;
+ }
+ }
+ else
+ {
+ Notification::make()
+ ->title('Updated Invoice Not Found')
+ ->body("Import the updated 'Serial Invoice' file to proceed..!")
+ ->danger()
+ ->seconds(2)
+ ->send();
+
+ $this->dispatch('playWarnSound');
+
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => 0,
+ 'scanned_quantity'=> 0,
+ ]);
+ $this->dispatch('refreshEmptyInvoice', invoiceNumber: $invoiceNumber, plantId: $plantId);
+ return;
+ }
+ }
+ }
+ return;
+ }
+ }
+
+ $filename = $invoiceNumber . '.xlsx';
+ $directory = 'uploads/temp';
+ $disk = Storage::disk('local');
+ $filePath = $directory . '/' . $filename;
+ $fullPath = null; //$fullPath = $disk->path($filePath);
+
+ // Check if file exists
+ if ($disk->exists($filePath)) {
+ $fullPath = $disk->path($filePath);
+ //$fullPath = session('uploaded_invoice_path');
+ // Notification::make()
+ // ->title('File exists.')
+ // ->success()
+ // ->seconds(2)
+ // ->send();
+ } else {
+ Notification::make()
+ ->title('Invoice Not Found')
+ ->body("Import the scanned 'Invoice' file to proceed..!")
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => 0,
+ 'scanned_quantity'=> 0,
+ ]);
+ $this->dispatch('refreshEmptyInvoice', invoiceNumber: $invoiceNumber, plantId: $plantId);
+ return;
+ }
+
+ if (!file_exists($fullPath))
+ {
+ Notification::make()
+ ->title('Invoice file doesn\'t exist.')
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+ return;
+
+ }
+
+ // Extract filename without extension (e.g., "3RA0018732")
+ $uploadedFilename = pathinfo($fullPath, PATHINFO_FILENAME);
+
+ // Compare with invoice number
+ if ($uploadedFilename != $invoiceNumber) {
+ Notification::make()
+ ->title("Uploaded file name does not match the invoice number.")
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+ return;
+ }
+
+ if ($fullPath && file_exists($fullPath))
+ {
+ // Now you can read/process the file here
+ $rows = Excel::toArray(null, $fullPath)[0];
+ // $collection = Excel::toCollection(null, $fullPath);
+ // $rows = $collection[0]->toArray();
+
+ // $collection = Excel::toCollection(new ExcelImport, $fullPath);
+ // // Convert the collection to an array
+ // $rows = $collection->toArray();
+
+ // $excelImport = new ExcelImport();
+ // // Import the Excel file
+ // Excel::import($excelImport, $fullPath);
+ // // Get the rows
+ // $rows = $excelImport->getRows();
+
+ if((count($rows) - 1) <= 0)
+ {
+ Notification::make()
+ ->title('Records Not Found')
+ ->body("Import the valid 'Invoice' file to proceed..!")
+ ->danger()
+ ->seconds(2)
+ ->send();
+
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ foreach ($rows as $index => $row)
+ {
+ if ($index == 0) continue;
+
+ $materialCode = trim($row[0]);
+
+ if (!empty($materialCode)) {
+ if(Str::length($materialCode) < 6)
+ {
+ continue;
+ }
+ else
+ {
+ $sticker = StickerMaster::where('plant_id', $plantId)->whereHas('item', function ($query) use ($materialCode) {
+ $query->where('plant_id', $this->plantId)->where('code', $materialCode); //Check if item.code matches Excel's materialCode
+ });
+ if($sticker->exists())
+ {
+ if($sticker->first()->material_type && !empty($sticker->first()->material_type))
+ {
+ $invoiceType = "M";
+ break;
+ }
+ else
+ {
+ $invoiceType = "S";
+ break;
+ }
+ }
+ else
+ {
+ continue;
+ }
+ }
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ if($invoiceType == 'M')
+ {
+ $invalidMatCodes = [];
+ $materialCodes = [];
+ $missingQuantities = [];
+ $invalidMatQuan = [];
+ $validRowsFound = false;
+
+ foreach ($rows as $index => $row)
+ {
+ if ($index == 0) continue; // Skip header
+
+ $materialCode = trim($row[0]);
+ $materialQuantity = trim($row[1]);
+
+ if (empty($materialCode) && empty($materialQuantity)) {
+ continue;
+ }
+
+ if (!empty($materialCode)) {
+ if(Str::length($materialCode) < 6 || !ctype_alnum($materialCode))
+ {
+ $invalidMatCodes[] = $materialCode;
+ }
+ else
+ {
+ if (empty($materialQuantity)) {
+ $missingQuantities[] = $materialCode;
+ }
+ else if(!is_numeric($materialQuantity))
+ {
+ $invalidMatQuan[] = $materialCode;
+ }
+ else if($materialQuantity == 0)
+ {
+ $invalidMatQuan[] = $materialCode;
+ }
+ else
+ {
+ $materialCodes[] = $materialCode;
+ $validRowsFound = true;
+ }
+ }
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ if (!$validRowsFound) {
+ Notification::make()
+ ->title('Invalid Material Invoice')
+ ->danger() // This makes the notification red to indicate an error
+ ->body('Uploaded Excel sheet is empty or
contains no valid data.')
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $uniqueInvalidCodes = array_unique($invalidMatCodes);
+
+ if (!empty($uniqueInvalidCodes)) {
+ Notification::make()
+ ->title('Invalid: Item Codes')
+ ->body('The following item codes should contain minimum 6 digit alpha numeric values:
' . implode(', ', $uniqueInvalidCodes))
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $uniqueMissingQuanCodes = array_unique($missingQuantities);
+
+ if (!empty($uniqueMissingQuanCodes)) {
+ Notification::make()
+ ->title('Missing Material Quantity')
+ ->body("The following item codes doesn't have valid material quantity:
" . implode(', ', $uniqueMissingQuanCodes))
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $uniqueInvalidMatQuan = array_unique($invalidMatQuan);
+
+ if (!empty($uniqueInvalidMatQuan)) {
+ Notification::make()
+ ->title('Invalid Material Quantity')
+ ->body("The following item codes doesn't have valid material quantity:
" . implode(', ', $uniqueInvalidMatQuan))
+ ->danger()
+ ->seconds(2)
+ ->send();
+
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $uniqueCodes = array_unique($materialCodes);
+
+ //itemNotFound
+ $matchedItems = StickerMaster::with('item')
+ ->whereHas('item', function ($query) use ($uniqueCodes) {
+ $query->whereIn('code', $uniqueCodes);
+ })
+ ->get();
+
+ $matchedCodes = $matchedItems->pluck('item.code')->toArray();
+
+ $missingCodes = array_diff($uniqueCodes, $matchedCodes);
+
+ if (!empty($missingCodes))
+ {
+ $missingCount = count($missingCodes);
+
+ $message = $missingCount > 10 ? "'$missingCount' item codes are not found in database." : 'The following item codes are not found in database:
' . implode(', ', $missingCodes);
+
+ Notification::make()
+ ->title('Unknown: Item Codes')
+ ->body($message)
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ //plantNotFound
+ $matchedItems = StickerMaster::with('item')
+ ->whereHas('item', function ($query) use ($uniqueCodes, $plantId) {
+ $query->whereIn('code', $uniqueCodes)->where('plant_id', $plantId);
+ })
+ ->get();
+
+ $matchedCodes = $matchedItems->pluck('item.code')->toArray();
+
+ $missingCodes = array_diff($uniqueCodes, $matchedCodes);
+
+ if (!empty($missingCodes))
+ {
+ $missingCount = count($missingCodes);
+
+ $message = $missingCount > 10 ? "'$missingCount' item codes are not found in database for choosed plant." : 'The following item codes are not found in database for choosed plant:
' . implode(', ', $missingCodes);
+
+ Notification::make()
+ ->title('Unknown: Item Codes')
+ ->body($message)
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $invalidCodes = $matchedItems
+ ->filter(fn ($sticker) => empty($sticker->material_type)) //filter invalid
+ ->pluck('item.code')
+ ->toArray();
+
+ if (!empty($invalidCodes))
+ {
+ $missingCount = count($invalidCodes);
+
+ $message = $missingCount > 10 ? "'$missingCount' Serial Invoice item codes found." : "'Serial Invoice' item codes found:
" . implode(', ', $invalidCodes);
+
+ Notification::make()
+ ->title('Invalid: Item Codes')
+ ->body($message)
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $nonNumericQtyCodes = [];
+ $zeroQtyCodes = [];
+ $notDivisibleCodes = [];
+
+ foreach ($matchedItems as $sticker)
+ {
+ $code = $sticker->item->code;
+ $materialType = $sticker->material_type;
+
+ if ($materialType == 2)
+ {
+ $bundleQty = $sticker->bundle_quantity ?? 0;
+ $totalExcelQty = 0;
+
+ foreach ($rows as $index => $row)
+ {
+ if ($index == 0) continue; // Skip header
+
+ $excelCode = trim($row[0]);
+ $excelMatQty = trim($row[1]);
+
+ if (empty($excelCode) || empty($excelMatQty)) {
+ continue;
+ }
+
+ if ($excelCode == $code && is_numeric($excelMatQty)) {
+ $totalExcelQty += $excelMatQty; // Sum up the quantities
+ }
+ }
+
+ if ($totalExcelQty == 0) {
+ $zeroQtyCodes[] = $code;
+ } elseif (!is_numeric($totalExcelQty)) {
+ $nonNumericQtyCodes[] = $code; // Here you may want to check divisibility condition too
+ } elseif ($bundleQty != 0 && $totalExcelQty % $bundleQty != 0) {
+ $notDivisibleCodes[] = $code;
+ }
+ }
+ }
+
+ $showValidationNotification = function(array $codes, string $message) {
+ if (count($codes) == 0) return;
+
+ $uniqueCodes = array_unique($codes);
+ $codeList = implode(', ', $uniqueCodes);
+
+ Notification::make()
+ ->title('Invalid Bundle Quantity')
+ ->body("$message
$codeList")
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+ };
+
+ $showValidationNotification($nonNumericQtyCodes, "The following item codes contains invalid bundle quantity:");
+ $showValidationNotification($zeroQtyCodes, "The following item codes quantity should be greater than '0':");
+ $showValidationNotification($notDivisibleCodes, "The following item codes quantity is not divisible by bundle quantity.");
+
+
+ if ($nonNumericQtyCodes || $zeroQtyCodes || $notDivisibleCodes) {
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+ else
+ {
+ $inserted = 0;
+ foreach ($matchedItems as $sticker)
+ {
+ $code = $sticker->item->code;
+ $materialType = $sticker->material_type;
+ // $sticker = StickerMaster::where('plant_id', $plantId)->whereHas('item', function ($query) use ($code) { $query->where('plant_id', $this->plantId)->where('code', $code); })->first();
+
+ if ($materialType == 1)
+ {
+ $totalExcelQty = 0;
+
+ foreach ($rows as $index => $row)
+ {
+ if ($index == 0) continue; // Skip header
+
+ $excelCode = trim($row[0]);
+ $excelMatQty = trim($row[1]);
+
+ if (empty($excelCode) || empty($excelMatQty)) {
+ continue;
+ }
+
+ if ($excelCode == $code && is_numeric($excelMatQty)) {
+ $totalExcelQty += $excelMatQty; // Sum up the quantities
+ }
+ }
+
+ for ($i = 0; $i < $totalExcelQty; $i++)
+ {
+ if ($sticker) {
+ SerialValidation::create([
+ 'sticker_master_id' => $sticker->id,
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'quantity' => 1,
+ 'operator_id'=> $operatorName,
+ ]);
+ $inserted++;
+ }
+ }
+ }
+ else if ($materialType == 2)
+ {
+ $bundleQty = $sticker->bundle_quantity;
+ $totalExcelQty = 0;
+
+ foreach ($rows as $index => $row)
+ {
+ if ($index == 0) continue; // Skip header
+
+ $excelCode = trim($row[0]);
+ $excelMatQty = trim($row[1]);
+
+ if (empty($excelCode) || empty($excelMatQty)) {
+ continue;
+ }
+
+ if ($excelCode == $code && is_numeric($excelMatQty)) {
+ $totalExcelQty += $excelMatQty; // Sum up the quantities
+ }
+ }
+
+ for ($i = 0; $i < ($totalExcelQty/$bundleQty); $i++)
+ {
+ if ($sticker) {
+ SerialValidation::create([
+ 'sticker_master_id' => $sticker->id,
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'quantity' => $bundleQty,
+ 'operator_id'=> $operatorName,
+ ]);
+ $inserted++;
+ }
+ }
+ }
+ else if ($materialType == 3)
+ {
+ $totalExcelQty = 0;
+
+ foreach ($rows as $index => $row)
+ {
+ if ($index == 0) continue; // Skip header
+
+ $excelCode = trim($row[0]);
+ $excelMatQty = trim($row[1]);
+
+ if (empty($excelCode) || empty($excelMatQty)) {
+ continue;
+ }
+
+ if ($excelCode == $code && is_numeric($excelMatQty)) {
+ $totalExcelQty += $excelMatQty; // Sum up the quantities
+ }
+ }
+
+ if ($sticker) {
+ SerialValidation::create([
+ 'sticker_master_id' => $sticker->id,
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'quantity' => $totalExcelQty,
+ 'operator_id'=> $operatorName,
+ ]);
+ $inserted++;
+ }
+ }
+ }
+
+ if ($inserted > 0)
+ {
+ Notification::make()
+ ->title("Start the scanning process!")
+ ->body("'$inserted' material invoice records were inserted.")
+ ->info()
+ // ->success()
+ ->seconds(1)
+ ->send();
+
+ // Update total quantity in the form
+ $totalQuantity = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ $scannedQuantity = SerialValidation::where('invoice_number', $invoiceNumber)->whereNotNull('serial_number')->where('serial_number', '!=', '')->where('plant_id', $plantId)->count();
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totalQuantity,
+ 'scanned_quantity'=> $scannedQuantity,
+ ]);
+
+ if ($totalQuantity == $scannedQuantity)
+ {
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+
+ $this->dispatch('refreshCompletedInvoice', invoiceNumber: $invoiceNumber, plantId: $plantId, isSerial: false);
+ }
+ else
+ {
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ // $hasRecords = InvoiceValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->first()->stickerMasterRelation->material_type ?? null;
+ // $this->dispatch( (!empty($hasRecords) && $hasRecords) ? 'refreshMaterialInvoiceData' : 'refreshInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId); //$this->invoiceNumber
+ $this->dispatch('refreshMaterialInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId);
+ }
+ }
+ else
+ {
+ Notification::make()
+ ->title("Import Failed: Material Invoice")
+ ->body("No new records were inserted for Material Invoice: '$invoiceNumber'.")
+ ->danger()
+ ->seconds(2)
+ ->send();
+
+ $totalQuantity = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ $scannedQuantity = SerialValidation::where('invoice_number', $invoiceNumber)->whereNotNull('serial_number')->where('serial_number', '!=', '')->where('plant_id', $plantId)->count();
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totalQuantity,
+ 'scanned_quantity'=> $scannedQuantity,
+ ]);
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+
+ $this->dispatch('refreshEmptyInvoice', invoiceNumber: $invoiceNumber, plantId: $plantId);
+ return;
+ }
+ }
+ }
+ else if($invoiceType == 'S')
+ {
+ $invalidMatCodes = [];
+ $materialCodes = [];
+ $missingSerials = [];
+ $invalidSerCodes = [];
+ $duplicateSerials = [];
+ $serialNumbers = [];
+ $validRowsFound = false;
+
+ foreach ($rows as $index => $row)
+ {
+ if ($index == 0) continue; // Skip header
+
+ $materialCode = trim($row[0]);
+ $serialNumber = trim($row[1]);
+
+ if (empty($materialCode) && empty($serialNumber)) {
+ continue;
+ }
+
+ if (!empty($materialCode)) {
+ if(Str::length($materialCode) < 6 || !ctype_alnum($materialCode))
+ {
+ $invalidMatCodes[] = $materialCode;
+ continue;
+ }
+ else
+ {
+ if(empty($serialNumber)) {
+ $missingSerials[] = $materialCode;
+ }
+ else if(Str::length($serialNumber) < 9 || !ctype_alnum($serialNumber))
+ {
+ $invalidSerCodes[] = $serialNumber;
+ }
+ else
+ {
+ if (in_array($serialNumber, $serialNumbers)) {
+ $duplicateSerials[] = $serialNumber;
+ } else {
+ $serialNumbers[] = $serialNumber;
+ $materialCodes[] = $materialCode;
+ $validRowsFound = true;
+ }
+ }
+ }
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ if (!$validRowsFound) {
+ Notification::make()
+ ->title('Invalid Serial Invoice')
+ ->danger() // This makes the notification red to indicate an error
+ ->body('Uploaded excel sheet is empty or
contains no valid data.')
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $uniqueInvalidCodes = array_unique($invalidMatCodes);
+
+ if (!empty($uniqueInvalidCodes)) {
+ Notification::make()
+ ->title('Invalid: Item Codes')
+ ->body('The following item codes should contain minimum 6 digit alpha numeric values:
' . implode(', ', $uniqueInvalidCodes))
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $uniqueCodes = array_unique($materialCodes);
+
+ //itemNotFound
+ $matchedItems = StickerMaster::with('item')
+ ->whereHas('item', function ($query) use ($uniqueCodes) {
+ $query->whereIn('code', $uniqueCodes);
+ })
+ ->get();
+
+ // // Get all codes that exist in the database for the given plant_id
+ // $existingCodes = StickerMaster::where('plant_id', $plantId)
+ // ->whereHas('item', function ($query) use ($uniqueCodes) {
+ // $query->whereIn('code', $uniqueCodes);
+ // })
+ // ->with('item') // Eager load for performance
+ // ->get()
+ // ->pluck('item.code')
+ // ->toArray();
+
+ $matchedCodes = $matchedItems->pluck('item.code')->toArray();
+
+ $missingCodes = array_diff($uniqueCodes, $matchedCodes);
+
+ if (!empty($missingCodes))
+ {
+ $missingCount = count($missingCodes);
+
+ $message = $missingCount > 10 ? "'$missingCount' item codes are not found in database." : 'The following item codes are not found in database:
' . implode(', ', $missingCodes);
+
+ Notification::make()
+ ->title('Unknown: Item Codes')
+ ->body($message)
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ //plantNotFound
+ $matchedItems = StickerMaster::with('item')
+ ->whereHas('item', function ($query) use ($uniqueCodes, $plantId) {
+ $query->whereIn('code', $uniqueCodes)->where('plant_id', $plantId);
+ })
+ ->get();
+
+ $matchedCodes = $matchedItems->pluck('item.code')->toArray();
+
+ $missingCodes = array_diff($uniqueCodes, $matchedCodes);
+
+ if (!empty($missingCodes))
+ {
+ $missingCount = count($missingCodes);
+
+ $message = $missingCount > 10 ? "'$missingCount' item codes are not found in database for choosed plant." : 'The following item codes are not found in database for choosed plant:
' . implode(', ', $missingCodes);
+
+ Notification::make()
+ ->title('Unknown: Item Codes')
+ ->body($message)
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $invalidCodes = $matchedItems
+ ->filter(fn ($sticker) => !empty($sticker->material_type)) //filter invalid
+ ->pluck('item.code')
+ ->toArray();
+
+ if (!empty($invalidCodes))
+ {
+ $missingCount = count($invalidCodes);
+
+ $message = $missingCount > 10 ? "'$missingCount' Material Invoice item codes found." : "'Material Invoice' item codes found:
" . implode(', ', $invalidCodes);
+
+ Notification::make()
+ ->title('Invalid: Item Codes')
+ ->body($message)
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+
+ // $missPackCodes = $matchedItems
+ // ->filter(fn ($sticker) => empty($sticker->tube_sticker_motor) && empty($sticker->pack_slip_motor) && empty($sticker->tube_sticker_pump) && empty($sticker->pack_slip_pump) && empty($sticker->tube_sticker_pumpset) && empty($sticker->pack_slip_pumpset) && empty($sticker->panel_box_code))
+ // ->pluck('item.code')
+ // ->toArray();
+
+ $missPackCodes = $matchedItems
+ ->filter(fn ($sticker) => empty($sticker->pack_slip_motor) && empty($sticker->pack_slip_pump) && empty($sticker->pack_slip_pumpset) && empty($sticker->panel_box_code))
+ ->pluck('item.code')
+ ->toArray();
+
+ if (!empty($missPackCodes))
+ {
+ $missingCount = count($missPackCodes);
+
+ $message = $missingCount > 10 ? "'$missingCount' item codes doesn't have valid package type to proceed!" : "The following 'Item Code' doesn't have valid package type:
" . implode(', ', $missPackCodes);
+
+ Notification::make()
+ ->title('Invalid: Item Codes')
+ ->body($message)
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $uniqueMissingSerials = array_unique($missingSerials);
+
+ if (!empty($uniqueMissingSerials)) {
+ Notification::make()
+ ->title('Missing Serial Numbers')
+ ->body("The following item codes doesn't have valid serial number:
" . implode(', ', $uniqueMissingSerials))
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $uniqueInvalidSerCodes = array_unique($invalidSerCodes);
+
+ if (!empty($uniqueInvalidSerCodes)) {
+ Notification::make()
+ ->title('Invalid Serial Numbers')
+ ->body('The following serial numbers should contain minimum 9 digit alpha numeric values:
' . implode(', ', $uniqueInvalidSerCodes))
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $uniqueDupSerCodes = array_unique($duplicateSerials);
+
+ if (!empty($uniqueDupSerCodes)) {
+ Notification::make()
+ ->title('Duplicate Serial Numbers')
+ ->body('The following serial numbers are already exist in invoice excel:
' . implode(', ', $uniqueDupSerCodes))
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $existingSerialNumbers = SerialValidation::whereIn('serial_number', $serialNumbers)->where('plant_id', $plantId)->pluck('serial_number')->toArray();
+
+ // If there are duplicates, notify and stop the process
+ if (!empty($existingSerialNumbers)) {
+ Notification::make()
+ ->title('Duplicate Serial Numbers')
+ ->body('The following serial numbers are already exist in database:
' . implode(', ', $existingSerialNumbers))
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+
+ $inserted = 0;
+ foreach ($rows as $index => $row)
+ {
+ if ($index == 0) continue;
+
+ $materialCode = trim($row[0]);
+ $serialNumber = trim($row[1]);
+
+ if (empty($materialCode) || empty($serialNumber)) {
+ continue;
+ }
+
+ $sticker = StickerMaster::where('plant_id', $plantId)->whereHas('item', function ($query) use ($materialCode) {
+ $query->where('plant_id', $this->plantId)->where('code', $materialCode); //Check if item.code matches Excel's materialCode
+ })->first();
+
+ if ($sticker) {
+ SerialValidation::create([
+ 'sticker_master_id' => $sticker->id,
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => $serialNumber,
+ 'operator_id'=> $operatorName,
+ ]);
+ $inserted++;
+ }
+ }
+
+ if ($inserted > 0)
+ {
+ Notification::make()
+ ->title("Start the scanning process!")
+ ->body("'$inserted' serial invoice records were inserted.")
+ ->info()
+ // ->success()
+ ->seconds(1)
+ ->send();
+ $this->dispatch('playNotificationSound');
+
+ // Update total quantity in the form
+ $totalQuantity = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ $scannedQuantity = SerialValidation::where('invoice_number', $invoiceNumber)->where('scanned_status', 'Scanned')->where('plant_id', $plantId)->count();
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totalQuantity,
+ 'scanned_quantity'=> $scannedQuantity,
+ ]);
+
+ if ($totalQuantity == $scannedQuantity)
+ {
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+
+ $this->dispatch('refreshCompletedInvoice', invoiceNumber: $invoiceNumber, plantId: $plantId, isSerial: true);
+ }
+ else
+ {
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ // $hasRecords = InvoiceValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->first()->stickerMasterRelation->material_type ?? null;
+ // $this->dispatch( (!empty($hasRecords) && $hasRecords) ? 'refreshMaterialInvoiceData' : 'refreshInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId); //$this->invoiceNumber
+ $this->dispatch('refreshInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId);
+ }
+ }
+ else
+ {
+ Notification::make()
+ ->title("Import Failed: Serial Invoice")
+ ->body("No new records were inserted for Serial Invoice : '$invoiceNumber'.")
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ $totalQuantity = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ $scannedQuantity = SerialValidation::where('invoice_number', $invoiceNumber)->where('scanned_status', 'Scanned')->where('plant_id', $plantId)->count();
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totalQuantity,
+ 'scanned_quantity'=> $scannedQuantity,
+ ]);
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+
+ $this->dispatch('refreshEmptyInvoice', invoiceNumber: $invoiceNumber, plantId: $plantId);
+ return;
+ }
+ }
+ else
+ {
+ Notification::make()
+ ->title('Invoice Type Not Found')
+ ->body("Import the valid 'Invoice' file to proceed..!")
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ if ($disk->exists($filePath)) {
+ $disk->delete($filePath);
+ }
+ return;
+ }
+ }
+ }
+
+ protected function refreshInvoiceTable()
+ {
+ $this->plantId = $this->form->getState()['plant_id'] ?? '';
+ $this->invoiceNumber = $this->form->getState()['invoice_number'] ?? '';
+
+ if (!empty($this->invoiceNumber)) {
+ $hasInvoice = SerialValidation::where('invoice_number', $this->invoiceNumber)->where('plant_id', $this->plantId)->first();
+
+ if (empty($hasInvoice) || !$hasInvoice)
+ {
+ $this->dispatch('refreshEmptyInvoice', invoiceNumber: $this->invoiceNumber, plantId: $this->plantId);
+ }
+ else
+ {
+ $totalQuantity = SerialValidation::where('invoice_number', $this->invoiceNumber)->where('plant_id', $this->plantId)->count();
+ $scannedQuantity = SerialValidation::where('invoice_number', $this->invoiceNumber)->where('scanned_status', 'Scanned')->where('plant_id', $this->plantId)->count();
+ if ($totalQuantity == $scannedQuantity)
+ {
+ $this->dispatch('refreshCompletedInvoice', invoiceNumber: $this->invoiceNumber, plantId: $this->plantId, isSerial: true);
+ }
+ else
+ {
+ $hasRecords = $hasInvoice->stickerMasterRelation->material_type ?? null;
+ $this->dispatch( (!empty($hasRecords) && $hasRecords) ? 'refreshMaterialInvoiceData' : 'refreshInvoiceData', invoiceNumber: $this->invoiceNumber, plantId: $this->plantId);
+ }
+ }
+ }
+ }
+
+ public function processSerialNumber($serNo)
+ {
+ $serNo = trim($serNo);
+ $user = Filament::auth()->user();
+ $operatorName = $user->name;
+
+ $serialNumber = null;
+ $plantId = $this->form->getState()['plant_id'];
+ $this->plantId = $plantId;
+
+ if (!preg_match('/^([a-zA-Z0-9]{6,})\|([1-9][a-zA-Z0-9]{8,})(?:\/[MmPpCc])?$/', $serNo, $matches))
+ {
+ Notification::make()
+ ->danger()
+ ->title('Invalid Serial QR Format')
+ ->body('Scan valid Serial QR code proceed!
Sample formats are:
123456|1234567890123/M (or)
123456|1234567890123/P (or)
123456|1234567890123/C (or)
123456|1234567890123')
+ ->seconds(2)
+ ->send();
+
+ $this->dispatch('playWarnSound');
+
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => null,
+ 'serial_number' => null,
+ // 'total_quantity' => $totQuan,
+ // 'update_invoice' => false,
+ // 'scanned_quantity'=> $scanSQuan,
+ ]);
+ return;
+ }
+
+ if (preg_match('/^([a-zA-Z0-9]{6,})\|([1-9][a-zA-Z0-9]{8,})(?:\/[MmPpCc])?$/', $serNo, $matches))
+ {
+ $itemCode = $matches[1];
+ $serialNumber = $matches[2];
+
+ // // Check if it ends with /M, /P, /C etc.
+ // $isMarkM = preg_match('/\/[Mm]$/', $serialNumber);
+ // $isMarkP = preg_match('/\/[Pp]$/', $serialNumber);
+ // $isMarkC = preg_match('/\/[Cc]$/', $serialNumber);
+ $isMarkM = preg_match('/^([a-zA-Z0-9]{6,})\|([1-9][a-zA-Z0-9]{8,})\/[Mm]?$/', $serNo) ? true : false;
+ $isMarkP = preg_match('/^([a-zA-Z0-9]{6,})\|([1-9][a-zA-Z0-9]{8,})\/[Pp]?$/', $serNo) ? true : false;
+ $isMarkC = preg_match('/^([a-zA-Z0-9]{6,})\|([1-9][a-zA-Z0-9]{8,})\/[Cc]?$/', $serNo) ? true : false;
+ $isMarkPs = (!$isMarkM && !$isMarkP && !$isMarkC) ? true : false;
+ //dd($serialNumber, $isMarkM, $isMarkP, $isMarkC, $isMarkPs);
+
+ $serialNumber = preg_replace('/\/[MmPpCc]$/', '', $serialNumber);
+
+ $record = SerialValidation::where('serial_number', $serialNumber)->where('plant_id', $plantId)->first();
+
+ if (!$record) {
+ Notification::make()
+ ->title('Serial Number Not Found
Serial \''.$serialNumber.'\' not found in database for choosed plant.')
+ // ->body("Serial '$serialNumber' not found in database for choosed plant.")..........
+ ->danger()
+ ->seconds(2)
+ ->send();
+
+ $this->dispatch('play-warn-sound');
+
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => null,
+ 'serial_number' => null,
+ // 'total_quantity' => $totQuan,
+ // 'update_invoice' => false,
+ // 'scanned_quantity'=> $scanSQuan,
+ ]);
+ return;
+ }
+
+ $invoiceNumber = $record->invoice_number;
+
+ $totQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ $scanSQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('scanned_status', 'Scanned')->where('plant_id', $plantId)->count();
+
+
+ $record = SerialValidation::where('serial_number', $serialNumber)
+ ->where('plant_id', $plantId)
+ ->whereHas('stickerMasterRelation.item', function ($query) use ($itemCode) {
+ $query->where('plant_id', $this->plantId)->where('code', $itemCode);
+ })
+ ->first();
+
+ $totQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ $scanSQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('scanned_status', 'Scanned')->where('plant_id', $plantId)->count();
+
+ if (!$record) {
+ Notification::make()
+ ->title('Unknown: Item Code')
+ ->body("Item code '$itemCode' with serial number '$serialNumber' not found.")
+ ->danger()
+ ->seconds(2)
+ ->send();
+
+ $this->dispatch('playWarnSound');
+
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => null,
+ 'serial_number' => null,
+ 'total_quantity' => $totQuan,
+ 'update_invoice' => false,
+ 'scanned_quantity'=> $scanSQuan,
+ ]);
+ return;
+ }
+
+ // $hasMotorQr = $record->stickerMasterRelation->tube_sticker_motor ?? null;
+ // $hasPumpQr = $record->stickerMasterRelation->tube_sticker_pump ?? null;
+ // $hasPumpSetQr = $record->stickerMasterRelation->tube_sticker_pumpset ?? null;
+
+
+ // if (!$hasMotorQr && !$hasPumpQr && !$hasPumpSetQr && !$hasCapacitorQr)
+ // {
+
+ // }
+
+ $hasMotorQr = $record->stickerMasterRelation->pack_slip_motor ?? null;
+ $hasPumpQr = $record->stickerMasterRelation->pack_slip_pump ?? null;
+ $hasPumpSetQr = $record->stickerMasterRelation->pack_slip_pumpset ?? null;
+ $hasCapacitorQr = $record->stickerMasterRelation->panel_box_code ?? null;
+
+ $hadMotorQr = $record->motor_scanned_status ?? null;
+ $hadPumpQr = $record->pump_scanned_status ?? null;
+ $hadPumpSetQr = $record->scanned_status_set ?? null;
+ $hadCapacitorQr = $record->capacitor_scanned_status ?? null;
+
+ if (!$hasMotorQr && !$hasPumpQr && !$hasPumpSetQr && !$hasCapacitorQr)
+ {
+ Notification::make()
+ ->title('Invalid: Item Code')
+ ->body("Scanned 'Item Code' doesn't have valid package type to proceed!")
+ ->danger()
+ ->seconds(2)
+ ->send();
+
+ $this->dispatch('playWarnSound');
+
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => null,
+ 'serial_number' => null,
+ 'total_quantity' => $totQuan,
+ 'update_invoice' => false,
+ 'scanned_quantity'=> $scanSQuan,
+ ]);
+ return;
+ }
+
+ if ($isMarkM) {
+
+ // $record = SerialValidation::where('serial_number', $serialNumber)
+ // ->where('plant_id', $plantId)
+ // ->first();
+ // $invoiceNumber = $record->invoice_number;
+
+ $totQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ $scanSQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('scanned_status', 'Scanned')->where('plant_id', $plantId)->count();
+
+ if (!$hasMotorQr)
+ {
+ Notification::make()
+ ->title('Unknown: Motor QR')
+ ->body("Scanned 'Item Code' doesn't have 'Motor' QR to proceed!")
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totQuan,
+ 'update_invoice' => false,
+ 'scanned_quantity'=> $scanSQuan,
+ ]);
+
+ $this->dispatch( 'refreshInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId);
+ return;
+ }
+ else if($hadMotorQr == $hasMotorQr)
+ {
+ Notification::make()
+ ->title('Duplicate: Motor QR')
+ ->body("Scanned 'Motor' serial number already completed the scanning process.")
+ ->danger()
+ ->seconds(2)
+ ->send();
+
+ $this->dispatch('playWarnSound');
+
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totQuan,
+ 'update_invoice' => false,
+ 'scanned_quantity'=> $scanSQuan,
+ ]);
+
+ $this->dispatch( 'refreshInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId);
+ return;
+ }
+
+ $packCnt = 1;
+ $scanCnt = 1;
+ $record->motor_scanned_status = 1;
+ //if($hadPumpQr == $hasPumpQr && $hadPumpSetQr == $hasPumpSetQr)
+ if($hasPumpQr || $hasPumpSetQr || $hasCapacitorQr)
+ {
+ $packCnt = $hasPumpQr ? $packCnt + 1 : $packCnt;
+ $packCnt = $hasPumpSetQr ? $packCnt + 1 : $packCnt;
+ $packCnt = $hasCapacitorQr ? $packCnt + 1 : $packCnt;
+
+ $scanCnt = $hadPumpQr ? $scanCnt + 1: $scanCnt;
+ $scanCnt = $hadPumpSetQr ? $scanCnt + 1: $scanCnt;
+ $scanCnt = $hadCapacitorQr ? $scanCnt + 1: $scanCnt;
+
+ if($packCnt == $scanCnt)
+ {
+ $record->scanned_status = 'Scanned';
+ }
+ }
+ else
+ {
+ $record->scanned_status = 'Scanned';
+ }
+ $record->operator_id = $operatorName;
+ $record->save();
+
+ // Notification::make()
+ // ->title('Success: Motor QR')
+ // ->body("'Motor' QR scanned status updated, Scan next QR.")
+ // ->success() // commented
+ // ->seconds(2)
+ // ->send();
+
+ $scannedQuantity = SerialValidation::where('invoice_number', $invoiceNumber)->where('scanned_status', 'Scanned')->where('plant_id', $plantId)->count();
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totQuan,
+ 'update_invoice' => false,
+ 'scanned_quantity'=> $scannedQuantity,
+ ]);
+
+ // $invoiceNumber = $this->form->getState()['invoice_number'];
+ // $this->invoiceNumber = $invoiceNumber;
+
+
+
+ // $totMQuan = SerialValidation::where('invoice_number', $invoiceNumber)->whereNotNull('quantity')->where('plant_id', $plantId)->count(); //->where('quantity', '!=', '')
+ // $scanMQuan = SerialValidation::where('invoice_number', $invoiceNumber)->whereNotNull('serial_number')->where('serial_number', '!=', '')->where('plant_id', $plantId)->count();
+
+ if($totQuan == $scannedQuantity)
+ {
+ Notification::make()
+ ->title('Completed: Serial Invoice')
+ ->body("Serial invoice '$invoiceNumber' completed the scanning process.
Scan the next 'Serial Invoice' to proceed!")
+ ->success()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playNotificationSound');
+
+
+ $filename = $invoiceNumber . '.xlsx';
+ $directory = 'uploads/temp';
+ $disk = Storage::disk('local');
+ $filePath = $directory . '/' . $filename;
+ //$fullPath = null;
+ if ($disk->exists($filePath)) {
+ //$fullPath = $disk->path($filePath);
+ $disk->delete($filePath);
+ }
+ $this->dispatch('refreshCompletedInvoice', invoiceNumber: $invoiceNumber, plantId: $plantId, isSerial: true);
+ }
+ else
+ {
+ $this->dispatch( 'refreshInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId);
+ // $this->refreshInvoiceTable();
+ }
+ return;
+ }
+ else if ($isMarkP) {
+
+ // $record = SerialValidation::where('serial_number', $serialNumber)
+ // ->where('plant_id', $plantId)
+ // ->first();
+ // $invoiceNumber = $record->invoice_number;
+
+ $totQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ $scanSQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('scanned_status', 'Scanned')->where('plant_id', $plantId)->count();
+
+ if (!$hasPumpQr)
+ {
+ Notification::make()
+ ->title('Unknown: Pump QR')
+ ->body("Scanned 'Item Code' doesn't have 'Pump' QR to proceed!")
+ ->danger()
+ ->seconds(2)
+ ->send();
+
+ $this->dispatch('playWarnSound');
+
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totQuan,
+ 'update_invoice' => false,
+ 'scanned_quantity'=> $scanSQuan,
+ ]);
+ return;
+ }
+ else if($hadPumpQr == $hasPumpQr)
+ {
+ Notification::make()
+ ->title('Duplicate: Pump QR')
+ ->body("Scanned 'Pump' serial number already completed the scanning process.")
+ ->danger()
+ ->seconds(2)
+ ->send();
+ $this->dispatch('playWarnSound');
+
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totQuan,
+ 'update_invoice' => false,
+ 'scanned_quantity'=> $scanSQuan,
+ ]);
+ return;
+ }
+
+ $packCnt = 1;
+ $scanCnt = 1;
+ $record->pump_scanned_status = 1;
+ // if($hadMotorQr == $hasMotorQr && $hadPumpSetQr == $hasPumpSetQr && ($hadCapacitorQr == '1' && $hasCapacitorQr))
+ if($hasMotorQr || $hasPumpSetQr || $hasCapacitorQr)
+ {
+ $packCnt = $hasMotorQr ? $packCnt + 1 : $packCnt;
+ $packCnt = $hasPumpSetQr ? $packCnt + 1 : $packCnt;
+ $packCnt = $hasCapacitorQr ? $packCnt + 1 : $packCnt;
+
+ $scanCnt = $hadMotorQr ? $scanCnt + 1: $scanCnt;
+ $scanCnt = $hadPumpSetQr ? $scanCnt + 1: $scanCnt;
+ $scanCnt = $hadCapacitorQr ? $scanCnt + 1: $scanCnt;
+
+ if($packCnt == $scanCnt)
+ {
+ $record->scanned_status = 'Scanned';
+ }
+ }
+ else
+ {
+ $record->scanned_status = 'Scanned';
+ }
+ $record->operator_id = $operatorName;
+ $record->save();
+
+ // Notification::make()
+ // ->title('Success: Pump QR')
+ // ->body("'Pump' QR scanned status updated, Scan next QR.")
+ // ->success() // commented
+ // ->seconds(2)
+ // ->send();
+
+ $scannedQuantity = SerialValidation::where('invoice_number', $invoiceNumber)->where('scanned_status', 'Scanned')->where('plant_id', $plantId)->count();
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totQuan,
+ 'update_invoice' => false,
+ 'scanned_quantity'=> $scannedQuantity,
+ ]);
+
+ if($totQuan == $scannedQuantity)
+ {
+ Notification::make()
+ ->title('Completed: Serial Invoice')
+ ->body("Serial invoice '$invoiceNumber' completed the scanning process.
Scan the next 'Serial Invoice' to proceed!")
+ ->success()
+ ->seconds(2)
+ ->send();
+
+ $this->dispatch('playNotificationSound');
+
+ $filename = $invoiceNumber . '.xlsx';
+ $directory = 'uploads/temp';
+ $disk = Storage::disk('local');
+ $filePath = $directory . '/' . $filename;
+ //$fullPath = null;
+ if ($disk->exists($filePath)) {
+ //$fullPath = $disk->path($filePath);
+ $disk->delete($filePath);
+ }
+ $this->dispatch('refreshCompletedInvoice', invoiceNumber: $invoiceNumber, plantId: $plantId, isSerial: true);
+ }
+ else
+ {
+ $this->dispatch( 'refreshInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId);
+ // $this->refreshInvoiceTable();
+ }
+ return;
+ }
+ elseif ($isMarkC) {
+ // $record = SerialValidation::where('serial_number', $serialNumber)
+ // ->where('plant_id', $plantId)
+ // ->first();
+ // $invoiceNumber = $record->invoice_number;
+
+ $totQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ $scanSQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('scanned_status', 'Scanned')->where('plant_id', $plantId)->count();
+
+ if (!$hasCapacitorQr)
+ {
+ Notification::make()
+ // ->title('Unknown: Capacitor QR')
+ ->title('Missing: Panel Box Code')
+ // ->body("Panel Box Code is not available for Item Code : '$itemCode'.")
+ ->body("Scanned 'Item Code' doesn't have 'Panel Box Code' to proceed!")
+ ->danger()
+ ->seconds(2)
+ ->send();
+
+ $this->dispatch('playWarnSound');
+
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totQuan,
+ 'update_invoice' => false,
+ 'scanned_quantity'=> $scanSQuan,
+ ]);
+
+ $this->dispatch( 'refreshInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId);
+ return;
+ }
+ else if($hadCapacitorQr == '1' && $hasCapacitorQr)
+ {
+ Notification::make()
+ ->title('Duplicate: Capacitor QR')
+ ->body("Scanned 'Capacitor' serial number already completed the scanning process.")
+ ->danger()
+ ->seconds(2)
+ ->send();
+
+ $this->dispatch('playWarnSound');
+
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totQuan,
+ 'update_invoice' => false,
+ 'scanned_quantity'=> $scanSQuan,
+ ]);
+ $this->dispatch( 'refreshInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId);
+ return;
+ }
+
+ //hereToUpdate
+ //$this->dispatch('openCapacitorModal');
+ $this->dispatch('openCapacitorModal', itemCode: $itemCode, serialNumber: $serialNumber, plantId: $plantId);
+
+ $scannedQuantity = SerialValidation::where('invoice_number', $invoiceNumber)->where('scanned_status', 'Scanned')->where('plant_id', $plantId)->count();
+
+ // $invoiceNumber = $this->form->getState()['invoice_number'];
+ // $this->invoiceNumber = $invoiceNumber;
+
+ $totQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ $scanSQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('scanned_status', 'Scanned')->where('plant_id', $plantId)->count();
+ $totMQuan = SerialValidation::where('invoice_number', $invoiceNumber)->whereNotNull('quantity')->where('plant_id', $plantId)->count(); //->where('quantity', '!=', '')
+ $scanMQuan = SerialValidation::where('invoice_number', $invoiceNumber)->whereNotNull('serial_number')->where('serial_number', '!=', '')->where('plant_id', $plantId)->count();
+
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totQuan,
+ 'update_invoice' => false,
+ 'scanned_quantity'=> $scannedQuantity,
+ ]);
+ $this->dispatch( 'refreshInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId);
+ // $this->refreshInvoiceTable();
+ return;
+ }
+ elseif ($isMarkPs)
+ {
+ // $record = SerialValidation::where('serial_number', $serialNumber)
+ // ->where('plant_id', $plantId)
+ // ->first();
+ // $invoiceNumber = $record->invoice_number;
+ $totQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ $scanSQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('scanned_status', 'Scanned')->where('plant_id', $plantId)->count();
+
+ if (!$hasPumpSetQr)
+ {
+ Notification::make()
+ ->title('Unknown: Pump Set QR')
+ ->body("Scanned 'Item Code' doesn't have 'Pump Set' QR to proceed!")
+ ->danger()
+ ->seconds(2)
+ ->send();
+
+ $this->dispatch('playWarnSound');
+
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totQuan,
+ 'update_invoice' => false,
+ 'scanned_quantity'=> $scanSQuan,
+ ]);
+ $this->dispatch('refreshInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId);
+ return;
+ }
+ else if($hadPumpSetQr == $hasPumpSetQr)
+ {
+ Notification::make()
+ ->title('Duplicate: Pump Set QR')
+ ->body("Scanned 'Pump Set' serial number already completed the scanning process.")
+ ->danger()
+ ->seconds(2)
+ ->send();
+
+ $this->dispatch('playWarnSound');
+
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totQuan,
+ 'update_invoice' => false,
+ 'scanned_quantity'=> $scanSQuan,
+ ]);
+ return;
+ }
+
+ // Fill the invoice_number field in the form immediately
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => $serialNumber,
+ 'total_quantity' => $totQuan,
+ 'update_invoice' => false,
+ ]);
+
+ $packCnt = 1;
+ $scanCnt = 1;
+ $record->scanned_status_set = 1;
+ // if($hadMotorQr == $hasMotorQr && $hadPumpQr == $hasPumpQr && ($hadCapacitorQr == '1' && $hasCapacitorQr))
+ if($hasMotorQr || $hasPumpQr || $hasCapacitorQr)
+ {
+ $packCnt = $hasMotorQr ? $packCnt + 1 : $packCnt;
+ $packCnt = $hasPumpQr ? $packCnt + 1 : $packCnt;
+ $packCnt = $hasCapacitorQr ? $packCnt + 1 : $packCnt;
+
+ $scanCnt = $hadMotorQr ? $scanCnt + 1: $scanCnt;
+ $scanCnt = $hadPumpQr ? $scanCnt + 1: $scanCnt;
+ $scanCnt = $hadCapacitorQr ? $scanCnt + 1: $scanCnt;
+
+ if($packCnt == $scanCnt)
+ {
+ $record->scanned_status = 'Scanned';
+ }
+ }
+ else
+ {
+ $record->scanned_status = 'Scanned';
+ }
+ $record->operator_id = $operatorName;
+ $record->save();
+
+ // Notification::make()
+ // ->title('Success: Pump Set QR')
+ // ->body("'Pump Set' QR scanned status updated, Scan next QR.")
+ // ->success() // commented
+ // ->seconds(2)
+ // ->send();
+
+
+ $scannedQuantity = SerialValidation::where('invoice_number', $invoiceNumber)->where('scanned_status', 'Scanned')->where('plant_id', $plantId)->count();
+ $this->form->fill([
+ 'plant_id' => $plantId,
+ 'invoice_number' => $invoiceNumber,
+ 'serial_number' => null,
+ 'total_quantity' => $totQuan,
+ 'update_invoice' => false,
+ 'scanned_quantity'=> $scannedQuantity,
+ ]);
+ // $invoiceNumber = $this->form->getState()['invoice_number'];
+ // $this->invoiceNumber = $invoiceNumber;
+
+ $scanSQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('scanned_status', 'Scanned')->where('plant_id', $plantId)->count();
+ $totMQuan = SerialValidation::where('invoice_number', $invoiceNumber)->whereNotNull('quantity')->where('plant_id', $plantId)->count(); //->where('quantity', '!=', '')
+ $scanMQuan = SerialValidation::where('invoice_number', $invoiceNumber)->whereNotNull('serial_number')->where('serial_number', '!=', '')->where('plant_id', $plantId)->count();
+
+ if($totQuan == $scannedQuantity)
+ {
+ Notification::make()
+ ->title('Completed: Serial Invoice')
+ ->body("Serial invoice '$invoiceNumber' completed the scanning process.
Scan the next 'Serial Invoice' to proceed!")
+ ->success()
+ ->seconds(2)
+ ->send();
+
+ $this->dispatch('playNotificationSound');
+
+ $filename = $invoiceNumber . '.xlsx';
+ $directory = 'uploads/temp';
+ $disk = Storage::disk('local');
+ $filePath = $directory . '/' . $filename;
+ //$fullPath = null;
+ if ($disk->exists($filePath)) {
+ //$fullPath = $disk->path($filePath);
+ $disk->delete($filePath);
+ }
+ $this->dispatch('refreshCompletedInvoice', invoiceNumber: $invoiceNumber, plantId: $plantId, isSerial: true);
+ }
+ else
+ {
+ $this->dispatch( 'refreshInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId);
+ // $this->refreshInvoiceTable();
+ }
+ return;
+ }
+ }
+
+ // $invoiceNumber = $this->form->getState()['invoice_number'];
+ // $this->invoiceNumber = $invoiceNumber;
+
+ // $totQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->count();
+ // $scanSQuan = SerialValidation::where('invoice_number', $invoiceNumber)->where('scanned_status', 'Scanned')->where('plant_id', $plantId)->count();
+ // $totMQuan = SerialValidation::where('invoice_number', $invoiceNumber)->whereNotNull('quantity')->where('plant_id', $plantId)->count(); //->where('quantity', '!=', '')
+ // $scanMQuan = SerialValidation::where('invoice_number', $invoiceNumber)->whereNotNull('serial_number')->where('serial_number', '!=', '')->where('plant_id', $plantId)->count();
+
+ //..
+
+
+ }
+
+ public function getHeading(): string
+ {
+ return 'Scan Serial Validation';
+ }
+}
diff --git a/app/Filament/Resources/SerialValidationResource/Pages/EditSerialValidation.php b/app/Filament/Resources/SerialValidationResource/Pages/EditSerialValidation.php
new file mode 100644
index 0000000..5de6c51
--- /dev/null
+++ b/app/Filament/Resources/SerialValidationResource/Pages/EditSerialValidation.php
@@ -0,0 +1,22 @@
+