requiredMapping() ->exampleHeader('Created DateTime') ->example(['01-01-2025 08:00:00', '01-01-2025 19:30:00']) ->label('Created DateTime') ->rules(['required']), ImportColumn::make('production_order') ->requiredMapping() ->exampleHeader('Production Order') ->example(['1234567', '1234567']) ->label('Production Order') ->numeric(), ImportColumn::make('item') ->requiredMapping() ->exampleHeader('Item Code') ->example(['123456', '123456']) ->label('Item Code') ->relationship(resolveUsing: 'code') ->rules(['required']), ImportColumn::make('serial_number') ->requiredMapping() ->exampleHeader('Serial Number') ->example(['12345678901234', '12345678902234']) ->label('Serial Number') ->rules(['required']), ImportColumn::make('line') ->requiredMapping() ->exampleHeader('Line Name') ->example(['4 inch pump line', '4 inch pump line']) ->label('Line Name') ->relationship(resolveUsing: 'name') ->rules(['required']), ImportColumn::make('block_reference') ->requiredMapping() // Or optionalMapping() if not always present ->exampleHeader('Block Name') ->example(['Block A', 'Block A']) ->label('Block Name') ->rules(['required']), // Or remove if not required ImportColumn::make('shift') ->requiredMapping() ->exampleHeader('Shift Name') ->example(['Day', 'Night']) ->label('Shift Name') ->relationship(resolveUsing: 'name') ->rules(['required']), ImportColumn::make('plant') ->requiredMapping() ->exampleHeader('Plant Code') ->example(['1000', '1000']) ->label('Plant Code') ->relationship(resolveUsing: 'code') ->rules(['required']), ImportColumn::make('updated_at') ->requiredMapping() ->exampleHeader('Updated DateTime') ->example(['01-01-2025 08:00:00', '01-01-2025 19:30:00']) ->label('Updated DateTime') ->rules(['required']), ImportColumn::make('operator_id') ->requiredMapping() ->exampleHeader('Operator ID') ->example([Filament::auth()->user()->name, Filament::auth()->user()->name]) ->label('Operator ID') ->rules(['required']), ]; } public function resolveRecord(): ?ProductionQuantity { $warnMsg = []; $plantCod = $this->data['plant']; $plant = null; $line = null; $block = null; $shift = null; 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 { $line = Line::where('name', $this->data['line'])->where('plant_id', $plant->id)->first(); // block_reference $block = Block::where('name', $this->data['block_reference'])->where('plant_id', $plant->id)->first(); } if (! $line) { $warnMsg[] = 'Line not found'; } if (! $block) { $warnMsg[] = 'Block not found'; } elseif ($plant) { $shift = Shift::where('name', $this->data['shift'])->where('plant_id', $plant->id)->where('block_id', $block->id)->first(); } // $shift = Shift::where('id', $this->data['shift'])->where('plant_id', $plant->id)->first(); if (! $shift) { $warnMsg[] = 'Shift not found'; } $item = null; if ($plant) { $item = Item::where('code', $this->data['item'])->where('plant_id', $plant->id)->first(); } if (! $item) { $warnMsg[] = 'Item not found'; } if (Str::length($this->data['serial_number']) < 9 || ! ctype_alnum($this->data['serial_number'])) { $warnMsg[] = 'Invalid serial number found'; } if (Str::length($this->data['production_order']) > 0 && (Str::length($this->data['production_order']) < 7 || Str::length($this->data['production_order']) > 14 || ! is_numeric($this->data['production_order']))) { $warnMsg[] = 'Invalid production order found'; } $fromDate = $this->data['created_at']; $toDate = $this->data['updated_at']; $formats = ['d-m-Y H:i', 'd-m-Y H:i:s']; // '07-05-2025 08:00' or '07-05-2025 08:00:00' $fdateTime = null; $tdateTime = null; // Try parsing with multiple formats foreach ($formats as $format) { try { $fdateTime = Carbon::createFromFormat($format, $fromDate); break; } catch (\Exception $e) { // Optionally collect warning messages // $warnMsg[] = "Date format mismatch with format: $format"; } } foreach ($formats as $format) { try { $tdateTime = Carbon::createFromFormat($format, $toDate); break; } catch (\Exception $e) { // Optionally collect warning messages // $warnMsg[] = "Date format mismatch with format: $format"; } } // $fDateOnly = ''; if (! isset($fdateTime)) { // throw new \Exception('Invalid date time format'); $warnMsg[] = "Invalid 'Created DateTime' format. Expected DD-MM-YYYY HH:MM:SS"; } // else { // $fDateOnly = $fdateTime->toDateString(); // } if (! isset($tdateTime)) { $warnMsg[] = "Invalid 'Updated DateTime' format. Expected DD-MM-YYYY HH:MM:SS"; } if (isset($fdateTime) && isset($tdateTime)) { if ($fdateTime->greaterThan($tdateTime)) { $warnMsg[] = "'Created DataTime' is greater than 'Updated DateTime'."; } } // if (!$fromDate) { // $warnMsg[] = "Invalid 'Created DateTime' format. Expected DD-MM-YYYY HH:MM:SS"; // } // else if (!$toDate) { // $warnMsg[] = "Invalid 'Updated DateTime' format. Expected DD-MM-YYYY HH:MM:SS"; // } $user = User::where('name', $this->data['operator_id'])->first(); if (! $user) { $warnMsg[] = 'Operator ID not found'; } if (! empty($warnMsg)) { throw new RowImportFailedException(implode(', ', $warnMsg)); } else { // if (empty($warnMsg)) $productionQuan = ProductionQuantity::where('plant_id', $plant->id) ->where('serial_number', $this->data['serial_number']) ->latest() ->first(); if ($productionQuan) { throw new RowImportFailedException('Serial number already exist!'); } } ProductionQuantity::updateOrCreate([ 'serial_number' => $this->data['serial_number'], 'plant_id' => $plant->id, 'shift_id' => $shift->id, 'line_id' => $line->id, 'item_id' => $item->id, 'production_order' => $this->data['production_order'] ?? null, 'created_at' => $fdateTime->format('Y-m-d H:i:s'), // $this->data['created_at'], 'updated_at' => $tdateTime->format('Y-m-d H:i:s'), // $this->data['updated_at'], 'operator_id' => $this->data['operator_id'], ]); // ProductionQuantity::updateOrCreate([ // 'serial_number' => $this->data['serial_number'], // 'plant_id' => $plant->id, // ], // [ // 'shift_id' => $shift->id, // 'line_id' => $line->id, // 'item_id' => $item->id, // 'production_order' => $this->data['production_order'] ?? null, // 'created_at' => $fdateTime->format('Y-m-d H:i:s'),//$this->data['created_at'], // 'updated_at' => $tdateTime->format('Y-m-d H:i:s'),//$this->data['updated_at'], // 'operator_id' => $this->data['operator_id'], // ]); return null; // return new ProductionQuantity(); } public static function getCompletedNotificationBody(Import $import): string { $body = 'Your production quantity 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; } public function processRow(array $row): Model { // Activate import flag ProductionQuantity::$importing = true; try { // Create record with relationships $productionQuantity = ProductionQuantity::create([ 'created_at' => $row['created_at'], 'item_id' => $this->resolveItemId($row['item']), 'serial_number' => $row['serial_number'], 'line_id' => $this->resolveLineId($row['line']), 'shift_id' => $this->resolveShiftId($row['shift']), 'plant_id' => $this->resolvePlantId($row['plant']), 'updated_at' => $row['updated_at'], ]); } finally { // Always disable flag even if errors occur ProductionQuantity::$importing = false; } return $productionQuantity; } // Relationship resolvers private function resolveItemId(string $code): int { return Item::where('code', $code)->first()->id; } private function resolveLineId(string $name): int { return Line::where('name', $name)->first()->id; } private function resolveShiftId(string $name): int { return Shift::where('name', $name)->first()->id; } private function resolvePlantId(string $name): int { return Plant::where('name', $name)->first()->id; } }