requiredMapping() ->label('Plant Code') ->exampleHeader('Plant Code') ->example('1000') ->relationship(resolveUsing: 'code') ->rules(['required']), ImportColumn::make('serial_number') ->requiredMapping() ->label('Serial Number') ->exampleHeader('Serial Number') ->example('12345678901234') ->rules(['required']), ImportColumn::make('pallet_number') ->requiredMapping() ->label('Pallet Number') ->exampleHeader('Pallet Number') ->example('EP-2507001'), ImportColumn::make('pallet_status') ->requiredMapping() ->label('Pallet Status') ->exampleHeader('Pallet Status') ->example('Completed'), ImportColumn::make('locator_number') ->requiredMapping() ->label('Locator Number') ->exampleHeader('Locator Number') ->example('W05-D1B'), ImportColumn::make('locator_quantity') ->requiredMapping() ->label('Locator Quantity') ->exampleHeader('Locator Quantity') ->example(1) ->rules(['required']), ImportColumn::make('created_at') ->requiredMapping() ->label('Created At') ->exampleHeader('Created At') ->example('01-01-2025 08:00:00') ->rules(['required']), ImportColumn::make('scanned_at') ->requiredMapping() ->label('Scanned At') ->exampleHeader('Scanned At') ->example('01-01-2025 08:00:00') ->rules(['required']), ImportColumn::make('updated_at') ->requiredMapping() ->label('Updated At') ->exampleHeader('Updated At') ->example('01-01-2025 08:00:00') ->rules(['required']), ImportColumn::make('created_by') ->requiredMapping() ->label('Created By') ->exampleHeader('Created By') ->example('Admin') ->rules(['required']), ImportColumn::make('scanned_by') ->requiredMapping() ->label('Scanned By') ->exampleHeader('Scanned By') ->example('Admin') ->rules(['required']), ImportColumn::make('updated_by') ->requiredMapping() ->label('Updated By') ->exampleHeader('Updated By') ->example('Admin'), ]; } public function resolveRecord(): ?PalletValidation { $warnMsg = []; $plantCod = $this->data['plant']; $plant = null; $serialNo = $this->data['serial_number']; $palletNo = $this->data['pallet_number']; $palletStat = $this->data['pallet_status']; $locatorNo = $this->data['locator_number']; $locatorQty = $this->data['locator_quantity']; $createdAt = $this->data['created_at']; $scannedAt = $this->data['scanned_at']; $updatedAt = $this->data['updated_at']; $cDateTime = null; $sDateTime = null; $uDateTime = null; $createdBy = $this->data['created_by']; $scannedBy = $this->data['scanned_by']; $updatedBy = $this->data['updated_by']; if (Str::length($plantCod) < 4 || ! is_numeric($plantCod) || ! preg_match('/^[1-9]\d{3,}$/', $plantCod)) { $warnMsg[] = 'Invalid plant code found'; } else { $plant = Plant::where('code', $plantCod)->first(); if (! $plant) { $warnMsg[] = 'Plant not found'; } else { if (Str::length($serialNo) < 9 || Str::length($serialNo) > 20 || ! ctype_alnum($serialNo)) { $warnMsg[] = 'Invalid serial number found'; } if (Str::length($palletNo) > 0 && Str::length($palletNo) < 10) { $warnMsg[] = 'Invalid pallet number found'; } if (Str::length($palletStat) > 0 && $palletStat != 'Completed') { $warnMsg[] = 'Invalid pallet status found'; } if (Str::length($locatorNo) > 0 && Str::length($locatorNo) < 7) { $warnMsg[] = 'Invalid locator number found'; } if (Str::length($palletNo) <= 0 && Str::length($locatorNo) <= 0) { $warnMsg[] = 'Pallet and locator number found'; } if (Str::length($locatorQty) < 0 || ! is_numeric($locatorQty) || $locatorQty < 0 || $locatorQty > 2) { $warnMsg[] = 'Invalid locator quantity found'; } $created = User::where('name', $createdBy)->first(); if (! $created) { $warnMsg[] = 'Created by not found'; } $scanned = User::where('name', $scannedBy)->first(); if (! $scanned) { $warnMsg[] = 'Scanned by not found'; } $updated = User::where('name', $updatedBy)->first(); if (! $updated) { $warnMsg[] = 'Updated by not found'; } $formats = ['d-m-Y H:i', 'd-m-Y H:i:s']; // '07-05-2025 08:00' or '07-05-2025 08:00:00' foreach ($formats as $format) { try { $cDateTime = Carbon::createFromFormat($format, $createdAt); break; } catch (\Exception $e) { // Optionally collect warning messages // $warnMsg[] = "Date format mismatch with format: $format"; } } if (! isset($cDateTime)) { // throw new \Exception('Invalid date time format'); $warnMsg[] = "Invalid 'Created DateTime' format. Expected DD-MM-YYYY HH:MM:SS"; } foreach ($formats as $format) { try { $sDateTime = Carbon::createFromFormat($format, $scannedAt); break; } catch (\Exception $e) { // Optionally collect warning messages // $warnMsg[] = "Date format mismatch with format: $format"; } } if (! isset($sDateTime)) { $warnMsg[] = "Invalid 'Scanned DateTime' format. Expected DD-MM-YYYY HH:MM:SS"; } foreach ($formats as $format) { try { $uDateTime = Carbon::createFromFormat($format, $updatedAt); break; } catch (\Exception $e) { // Optionally collect warning messages // $warnMsg[] = "Date format mismatch with format: $format"; } } if (! isset($uDateTime)) { $warnMsg[] = "Invalid 'Updated DateTime' format. Expected DD-MM-YYYY HH:MM:SS"; } else { if (isset($cDateTime) && isset($uDateTime)) { if ($cDateTime->greaterThan($uDateTime)) { $warnMsg[] = "'Created DataTime' is greater than 'Updated DateTime'."; } } } } } // if (!is_numeric($locatorQuantity) || $locatorQuantity < 0 || $locatorQuantity > 2) { // $warnMsg[] = "Invalid locator quantity found"; // } if (! empty($warnMsg)) { throw new RowImportFailedException(implode(', ', $warnMsg)); } PalletValidation::updateOrCreate( [ 'plant_id' => $plant->id, 'serial_number' => $serialNo, ], [ 'pallet_number' => $palletNo, 'pallet_status' => $palletStat, 'locator_number' => $locatorNo, 'locator_quantity' => $locatorQty, 'created_at' => $cDateTime->format('Y-m-d H:i:s'), 'scanned_at' => $sDateTime->format('Y-m-d H:i:s'), 'updated_at' => $uDateTime->format('Y-m-d H:i:s'), 'created_by' => $createdBy, 'scanned_by' => $scannedBy, 'updated_by' => $updatedBy, ] ); return null; // // return PalletValidation::firstOrNew([ // // // Update existing records, matching them by `$this->data['column_name']` // // 'email' => $this->data['email'], // // ]); // return new PalletValidation(); } public static function getCompletedNotificationBody(Import $import): string { $body = 'Your pallet validation import has completed and '.number_format($import->successful_rows).' '.str('row')->plural($import->successful_rows).' imported.'; if ($failedRowsCount = $import->getFailedRowsCount()) { $body .= ' '.number_format($failedRowsCount).' '.str('row')->plural($failedRowsCount).' failed to import.'; } return $body; } }