requiredMapping() // ->exampleHeader('Created DateTime') // ->example(['01-01-2025 08:00:00', '01-01-2025 19:30:00']) // ->label('Created DateTime') // ->rules(['required']), ImportColumn::make('plant') ->requiredMapping() ->exampleHeader('Plant Code') ->example(['1000']) ->label('Plant Code') ->relationship(resolveUsing: 'code') ->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('item') ->requiredMapping() ->exampleHeader('Item Code') ->example(['123456']) ->label('Item Code') ->relationship(resolveUsing: 'code') ->rules(['required']), // ImportColumn::make('plan_quantity') // ->requiredMapping() // ->exampleHeader('Plan Quantity') // ->example(['500', '450']) // ->label('Plan Quantity') // ->numeric() // ->rules(['required', 'integer']), ImportColumn::make('week_1') ->requiredMapping() ->exampleHeader('Week 1') ->label('Week 1'), ImportColumn::make('week_2') ->requiredMapping() ->exampleHeader('Week 2') ->label('Week 2'), ImportColumn::make('week_3') ->requiredMapping() ->exampleHeader('Week 3') ->label('Week 3'), ImportColumn::make('week_4') ->requiredMapping() ->exampleHeader('Week 4') ->label('Week 4'), ImportColumn::make('week_5') ->requiredMapping() ->exampleHeader('Week 5') ->label('Week 5'), // ImportColumn::make('production_quantity') // ->requiredMapping() // ->exampleHeader('Production Quantity') // ->example(['0', '0']) // ->label('Production Quantity') // ->numeric() // ->rules(['required', 'integer']), // 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') // ID // ->example(['Day', 'Night']) // '2', '7' // ->label('Shift Name') // ID // ->relationship(resolveUsing: 'name') // ->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(): ?ProductionPlan { $warnMsg = []; $plantCod = $this->data['plant']; $itemCod = $this->data['item']; $plant = null; $line = null; $block = 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'; } if (Str::length($itemCod) < 6 || ! is_numeric($itemCod)) { $warnMsg[] = 'Invalid item code found'; } else { $item = Item::where('code', $itemCod)->first(); } if (! $item) { $warnMsg[] = 'Item not found'; } $plantId = $plant->id; $itemAgaPlant = Item::where('plant_id', $plantId)->where('code', $itemCod)->first(); if(!$itemAgaPlant){ $warnMsg[] = 'Item not found against plant code'; } else { $line = $itemAgaPlant->line_id; if (!$line) { $warnMsg[] = 'Line not mapped for that item code'; } } $user = Filament::auth()->user(); $operatorName = $user->name; if (!empty($this->data['plan_quantity'])) { if (Str::length($this->data['plan_quantity']) < 0 || ! is_numeric($this->data['plan_quantity']) || $this->data['plan_quantity'] <= 0) { $warnMsg[] = 'Invalid plan quantity found'; } } foreach (['week_1', 'week_2', 'week_3', 'week_4'] as $week) { $value = $this->data[$week] ?? null; if (filled($value) && (! is_numeric($value) || $value < 0)) { $warnMsg[] = "Invalid {$week} value found"; } } $week5 = $this->data['week_5'] ?? null; if ( filled($week5) && (! is_numeric($week5) || $week5 < 0) ) { $warnMsg[] = 'Invalid week_5 value found'; } $recordDate = now(); $month = $recordDate->month; $year = $recordDate->year; $previousRecord = ProductionCalendar::where('plant_id', $plant->id) ->whereMonth('created_at', $month) ->whereYear('created_at', $year) ->first(); if(!$previousRecord){ $warnMsg[] = 'Update this month production calendar'; } if (! empty($warnMsg)) { throw new RowImportFailedException(implode(', ', $warnMsg)); } $recordDate = now(); $month = $recordDate->month; $year = $recordDate->year; $totalDays = $recordDate->daysInMonth; $previousRecord = ProductionCalendar::where('plant_id', $plant->id) ->whereMonth('created_at', $month) ->whereYear('created_at', $year) ->first(); $workingDays = $previousRecord?->working_days ?? null; // Get leave dates $leaveDates = array_filter( array_map( 'trim', explode(',', (string) ($previousRecord?->leave_dates ?? '')) ) ); // Convert leave dates into day numbers $leaveDayNumbers = []; foreach ($leaveDates as $leaveDate) { try { $date = Carbon::parse($leaveDate); if ($date->format('Y-m') === $recordDate->format('Y-m')) { $leaveDayNumbers[] = (int) $date->format('d'); } } catch (\Throwable $e) { // Ignore invalid leave dates } } // Get existing production plan for this item $productionPlan1 = ProductionPlan::where('plant_id', $plant->id) ->where('item_id', $itemAgaPlant->id) ->whereYear('created_at', $year) ->whereMonth('created_at', $month) ->first(); // Initialize daily data $dailyData = []; for ($day = 1; $day <= 31; $day++) { if ($day <= $totalDays) { $dailyData['day_' . $day] = (int) ($productionPlan1->{'day_' . $day} ?? 0); } else { // Invalid dates must always remain zero $dailyData['day_' . $day] = 0; } } // Weekly ranges $weekRanges = [ 'week_1' => [1, min(7, $totalDays)], 'week_2' => [8, min(14, $totalDays)], 'week_3' => [15, min(21, $totalDays)], 'week_4' => [22, min(28, $totalDays)], 'week_5' => [29, min(31, $totalDays)], ]; // Process weekly values foreach ($weekRanges as $week => [$start, $end]) { if ($start > $totalDays) { continue; } $weeklyValue = $this->data[$week] ?? null; // Empty Excel value: retain existing daily values if ($weeklyValue === null || $weeklyValue === '') { continue; } // Get working days excluding leave dates $remainingDays = []; for ($day = $start; $day <= $end; $day++) { if (! in_array($day, $leaveDayNumbers, true)) { $remainingDays[] = $day; } else { $dailyData['day_' . $day] = 0; } } $daysCount = count($remainingDays); if ($daysCount === 0) { continue; } // Replace existing weekly quantity with Excel quantity $weeklyTotal = (int) round((float) $weeklyValue); $dailyValue = intdiv($weeklyTotal, $daysCount); $remainder = $weeklyTotal % $daysCount; foreach ($remainingDays as $index => $day) { $dailyData['day_' . $day] = $dailyValue + ($index < $remainder ? 1 : 0); } } // Calculate final monthly plan quantity $planQuantity = array_sum($dailyData); // Prepare plan data $planData = array_merge([ 'line_id' => $line, 'plan_quantity' => $planQuantity, 'working_days' => $workingDays, 'operator_id' => $operatorName, 'updated_at' => now(), ], $dailyData); // Update or create production plan if ($productionPlan1) { $productionPlan1->update($planData); } else { ProductionPlan::create(array_merge($planData, [ 'plant_id' => $plant->id, 'item_id' => $itemAgaPlant->id, 'created_at' => now(), ])); } //..Working Logic // $recordDate = now(); // $month = $recordDate->month; // $year = $recordDate->year; // $previousRecord = ProductionPlan::where('plant_id', $plant->id) // ->whereMonth('created_at', $month) // ->whereYear('created_at', $year) // ->first(); // $workingDays = $previousRecord?->working_days ?? null; // // Get leave dates from the existing production plan // $leaveDates = array_filter( // array_map('trim', explode(',', (string) ($previousRecord?->leave_dates ?? ''))) // ); // // Convert leave dates into day numbers for the current month // $leaveDayNumbers = []; // foreach ($leaveDates as $leaveDate) { // $date = Carbon::parse($leaveDate); // if ($date->format('Y-m') === $recordDate->format('Y-m')) { // $leaveDayNumbers[] = (int) $date->format('d'); // } // } // $totalDays = $recordDate->daysInMonth; // $dailyData = []; // for ($day = 1; $day <= 31; $day++) { // $dailyData['day_' . $day] = 0; // } // $planQuantity = 0; // foreach (['week_1', 'week_2', 'week_3', 'week_4', 'week_5'] as $week) { // $planQuantity += (float) ($this->data[$week] ?? 0); // } // $planQuantity = (int) $planQuantity; // // Dynamic weekly ranges // $weekRanges = [ // 'week_1' => [1, min(7, $totalDays)], // 'week_2' => [8, min(14, $totalDays)], // 'week_3' => [15, min(21, $totalDays)], // 'week_4' => [22, min(28, $totalDays)], // 'week_5' => [29, min(31, $totalDays)], // ]; // foreach ($weekRanges as $week => [$start, $end]) { // if ($start > $totalDays) { // continue; // } // $weeklyValue = $this->data[$week] ?? null; // if ($weeklyValue === null || $weeklyValue === '') { // continue; // } // $remainingDays = []; // for ($day = $start; $day <= $end; $day++) { // if (! in_array($day, $leaveDayNumbers)) { // $remainingDays[] = $day; // } // } // $daysCount = count($remainingDays); // if ($daysCount === 0) { // continue; // } // $weeklyTotal = (int) round((float) $weeklyValue); // $dailyValue = intdiv($weeklyTotal, $daysCount); // $remainder = $weeklyTotal % $daysCount; // foreach ($remainingDays as $index => $day) { // $dailyData['day_' . $day] = // $dailyValue + ($index < $remainder ? 1 : 0); // } // } // $dailyTotal = array_sum($dailyData); // $productionPlan1 = ProductionPlan::where('plant_id', $plant->id) // ->where('item_id', $itemAgaPlant->id) // ->whereYear('created_at', $recordDate->year) // ->whereMonth('created_at', $recordDate->month) // ->first(); // $planData = array_merge([ // 'line_id' => $line, // 'plan_quantity' => $planQuantity, // 'working_days' => $workingDays, // 'operator_id' => $operatorName, // 'updated_at' => now(), // ], $dailyData); // if ($productionPlan1) { // $productionPlan1->update($planData); // } else { // ProductionPlan::create(array_merge($planData, [ // 'plant_id' => $plant->id, // 'item_id' => $itemAgaPlant->id, // 'created_at' => now(), // ])); // } //..Old Logic // $productionPlan1 = ProductionPlan::where('plant_id', $plant->id) // ->where('item_id', $itemAgaPlant->id) // ->whereYear('created_at', $recordDate->year) // ->whereMonth('created_at', $recordDate->month) // ->first(); // if ($productionPlan1) { // $productionPlan1->update([ // 'line_id' => $line, // 'plan_quantity' => $this->data['plan_quantity'], // 'working_days' => $workingDays, // 'operator_id' => $operatorName, // 'updated_at' => now(), // ]); // } else { // ProductionPlan::create([ // 'plant_id' => $plant->id, // 'line_id' => $line, // 'item_id' => $itemAgaPlant->id, // 'plan_quantity' => $this->data['plan_quantity'], // 'working_days' => $workingDays, // 'operator_id' => $operatorName, // 'created_at' => now(), // 'updated_at' => now(), // ]); // } return null; } public static function getCompletedNotificationBody(Import $import): string { $body = 'Your production plan 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; } }