diff --git a/app/Filament/Pages/ProductionTarget.php b/app/Filament/Pages/ProductionTarget.php new file mode 100644 index 0000000..0d301bc --- /dev/null +++ b/app/Filament/Pages/ProductionTarget.php @@ -0,0 +1,173 @@ +statePath('filters') + ->schema([ + Section::make('') + ->schema([ + Select::make('plant_id') + ->label('Plant') + ->reactive() + ->options(function (callable $get) { + $userHas = Filament::auth()->user()->plant_id; + return ($userHas && strlen($userHas) > 0) ? Plant::where('id', $userHas)->pluck('name', 'id')->toArray() : Plant::pluck('name', 'id')->toArray(); + }) + ->required() + ->afterStateUpdated(function ($state, callable $get, $set) { + $set('line_id', null); + $set('year', null); + $set('month', null); + $this->dispatch('loadData',$state, '', '', ''); + }), + Select::make('line_id') + ->label('Line') + ->required() + ->columnSpan(1) + ->options(function (callable $get) { + if (!$get('plant_id')) { + return []; + } + + return \App\Models\Line::where('plant_id', $get('plant_id')) + ->pluck('name', 'id') + ->toArray(); + }) + ->reactive() + ->afterStateUpdated(function ($state, callable $get, $set) { + $plantId = $get('plant_id'); + $set('year', null); + $set('month', null); + $this->dispatch('loadData',$plantId, $state, '', ''); + }), + Select::make('year') + ->label('Year') + ->reactive() + ->options([ + '2026' => '2026', + '2027' => '2027', + '2028' => '2028', + '2029' => '2029', + '2030' => '2030', + '2031' => '2031', + '2032' => '2032', + '2033' => '2033', + '2034' => '2034', + '2035' => '2035', + '2036' => '2036', + '2037' => '2037', + '2038' => '2038', + '2039' => '2039', + '2040' => '2040', + ]) + ->required() + ->afterStateUpdated(function ($state, callable $get, $set) { + $set('month', null); + $plantId = $get('plant_id'); + $lineId = $get('line_id'); + $this->dispatch('loadData',$plantId, $lineId, $state, ''); + }), + + Select::make('month') + ->label('Month') + ->reactive() + ->options([ + '01' => 'January', + '02' => 'February', + '03' => 'March', + '04' => 'April', + '05' => 'May', + '06' => 'June', + '07' => 'July', + '08' => 'August', + '09' => 'September', + '10' => 'October', + '11' => 'November', + '12' => 'December', + ]) + ->required() + ->afterStateUpdated(function ($state, callable $get) { + + $plantId = $get('plant_id'); + $lineId = $get('line_id'); + // $month = $get('month'); + $year = $get('year'); + + $month = (int) $get('month'); + + if (!$month) { + return; + } + $this->dispatch('loadData', $plantId, $lineId, $month, $year); + }), + + ]) + ->columns(4) + ]); + } + + public function export(){ + + $plantId = $this->filters['plant_id'] ?? null; + $lineId = $this->filters['line_id'] ?? null; + $year = $this->filters['year'] ?? null; + $month = $this->filters['month'] ?? null; + + if (! $plantId) { + Notification::make() + ->title('Plant') + ->body("please select plant to export data..!") + ->danger() + ->send(); + return; + } + else if (! $lineId) { + Notification::make() + ->title('Line') + ->body("please select line to export data..!") + ->danger() + ->send(); + return; + } + else if (! $year) { + Notification::make() + ->title('Year') + ->body("please select year to export data..!") + ->danger() + ->send(); + return; + } + else if (! $month) { + Notification::make() + ->title('Month') + ->body("please select month to export data..!") + ->danger() + ->send(); + return; + } + + $this->dispatch('loadData1' ,$plantId, $lineId, $year, $month); + } +} diff --git a/app/Livewire/ProductionTargetPlan.php b/app/Livewire/ProductionTargetPlan.php new file mode 100644 index 0000000..960885f --- /dev/null +++ b/app/Livewire/ProductionTargetPlan.php @@ -0,0 +1,236 @@ + 'loadProductionData', + 'loadData1' => 'exportProductionData', + ]; + + public function getMonthDates($month, $year) + { + $start = Carbon::createFromDate($year, $month, 1); + $days = $start->daysInMonth; + + $dates = []; + + for ($i = 1; $i <= $days; $i++) { + $dates[] = Carbon::createFromDate($year, $month, $i) + ->format('Y-m-d'); + } + + return $dates; + } + + public function loadProductionData($plantId, $lineId, $month, $year){ + + if (!$plantId || !$lineId || !$month || !$year) { + $this->records = []; + $this->dates = []; + $this->leaveDates = []; + return; + } + + $this->dates = $this->getMonthDates($month, $year); + + $data = ProductionPlan::query() + ->join('items', 'items.id', '=', 'production_plans.item_id') + ->join('lines', 'lines.id', '=', 'production_plans.line_id') + ->join('plants', 'plants.id', '=', 'production_plans.plant_id') + ->where('production_plans.plant_id', $plantId) + ->where('production_plans.line_id', $lineId) + ->whereMonth('production_plans.created_at', $month) + ->whereYear('production_plans.created_at', $year) + ->select( + 'production_plans.created_at', + 'production_plans.operator_id', + 'plants.name as plant', + 'items.code as item_code', + 'items.description as item_description', + 'lines.name as line_name', + 'production_plans.leave_dates' + ) + ->first(); + + if ($data && $data->leave_dates) { + $this->leaveDates = array_map('trim', explode(',', $data->leave_dates)); + } + + $producedData = ProductionQuantity::selectRaw(" + plant_id, + line_id, + item_id, + DATE(created_at) as prod_date, + COUNT(*) as total_qty + ") + ->where('plant_id', $plantId) + ->where('line_id', $lineId) + ->whereMonth('created_at', $month) + ->whereYear('created_at', $year) + ->groupBy('plant_id', 'line_id', 'item_id', DB::raw('DATE(created_at)')) + ->get() + ->groupBy(function ($row) { + return $row->plant_id . '_' . $row->line_id . '_' . $row->item_id; + }) + ->map(function ($group) { + return $group->keyBy('prod_date'); + }); + + $this->records = ProductionPlan::query() + ->join('items', 'items.id', '=', 'production_plans.item_id') + ->join('lines', 'lines.id', '=', 'production_plans.line_id') + ->join('plants', 'plants.id', '=', 'production_plans.plant_id') + ->where('production_plans.plant_id', $plantId) + ->where('production_plans.line_id', $lineId) + ->whereMonth('production_plans.created_at', $month) + ->whereYear('production_plans.created_at', $year) + ->select( + 'production_plans.item_id', + 'production_plans.plant_id', + 'production_plans.line_id', + 'production_plans.plan_quantity', + 'production_plans.working_days', + 'items.code as item_code', + 'items.description as item_description', + 'lines.name as line_name', + 'plants.name as plant_name' + ) + ->get() + // ->map(function ($row) use ($producedData) { + // $row = $row->toArray(); + + // $row['daily_target'] = ($row['working_days'] > 0) + // ? round($row['plan_quantity'] / $row['working_days'], 2) + // : 0; + + // // $key = $row['plant_id'].'_'.$row['line_id'].'_'.$row['item_id']; + + // // foreach ($this->dates as $date) { + // // $found = $producedData[$key][$date] ?? null; + // // $row['produced_quantity'][$date] = $found->total_qty ?? 0; + // // } + + // $remainingDays = $row['working_days']; + // $pendingQty = 0; + + // $row['daily_target_dynamic'] = []; + // $row['produced_quantity'] = []; + + // $key = $row['plant_id'].'_'.$row['line_id'].'_'.$row['item_id']; + + // foreach ($this->dates as $date) { + + // $found = $producedData[$key][$date] ?? null; + // $producedQty = $found->total_qty ?? 0; + + // // today's adjusted target + // $todayTarget = $baseDailyTarget; + + // if ($remainingDays > 1 && $pendingQty > 0) { + // $todayTarget += $pendingQty / $remainingDays; + // } + + // $row['daily_target_dynamic'][$date] = round($todayTarget, 2); + // $row['produced_quantity'][$date] = $producedQty; + + // // calculate today's shortfall + // $pendingQty += ($todayTarget - $producedQty); + + // if ($pendingQty < 0) { + // $pendingQty = 0; + // } + + // $remainingDays--; + // } + + // return $row; + // }) + ->map(function ($row) use ($producedData) { + + $row = $row->toArray(); + + $remainingQty = $row['plan_quantity']; + $remainingDays = $row['working_days']; + + $row['daily_target_dynamic'] = []; + $row['produced_quantity'] = []; + + $key = $row['plant_id'].'_'.$row['line_id'].'_'.$row['item_id']; + + foreach ($this->dates as $date) { + + // Skip leave dates + if (in_array($date, $this->leaveDates)) { + $row['daily_target_dynamic'][$date] = '-'; + $row['produced_quantity'][$date] = '-'; + continue; + } + + $todayTarget = $remainingDays > 0 + ? round($remainingQty / $remainingDays, 2) + : 0; + + //$todayTarget = $remainingDays > 0 + // ? $remainingQty / $remainingDays + // : 0; + + $producedQty = isset($producedData[$key][$date]) + ? $producedData[$key][$date]->total_qty + : 0; + + $row['daily_target_dynamic'][$date] = $todayTarget; + $row['produced_quantity'][$date] = $producedQty; + + // Carry forward pending + $remainingQty -= $producedQty; + if ($remainingQty < 0) { + $remainingQty = 0; + } + + $remainingDays--; + } + + return $row; + }) + ->toArray(); + } + + public function exportProductionData() + { + return Excel::download( + new ProductionPlanExport($this->records, $this->dates), + 'production_plan_data.xlsx' + ); + } + + public function render() + { + // return view('livewire.production-target-plan'); + return view('livewire.production-target-plan', [ + 'records' => $this->records, + 'dates' => $this->dates, + ]); + } +} diff --git a/resources/views/filament/pages/production-target.blade.php b/resources/views/filament/pages/production-target.blade.php new file mode 100644 index 0000000..242dbbb --- /dev/null +++ b/resources/views/filament/pages/production-target.blade.php @@ -0,0 +1,19 @@ + +
+ + {{-- Render the Select form fields --}} +
+ {{ $this->form }} +
+ + Export + +
+ +
+
+
diff --git a/resources/views/livewire/production-target-plan.blade.php b/resources/views/livewire/production-target-plan.blade.php new file mode 100644 index 0000000..fee20f1 --- /dev/null +++ b/resources/views/livewire/production-target-plan.blade.php @@ -0,0 +1,85 @@ +
+

+ PRODUCTION PLAN TABLE: +

+
+ + {{-- + + + + + + + + + + --}} + + + + + + + + + + + @foreach($dates as $date) + + @endforeach + + + @foreach($dates as $date) + + + @endforeach + + + + + @forelse ($records as $index => $record) + + + + + + + {{-- @foreach($dates as $date) + + + @endforeach --}} + + @foreach($dates as $date) + @if(in_array($date, $leaveDates)) + + + @else + {{-- --}} + + + {{-- --}} + @endif + @endforeach + + @empty + + + + @endforelse + +
NoCreated DatetimeCreated ByPlantLineItem CodeProduction Plan Dates
NoPlantLineItem Code + Production Plan Dates +
+ {{ $date }} +
Target PlanProduced Quantity
{{ $index + 1 }}{{ $record['plant_name'] }}{{ $record['line_name'] }}{{ $record['item_code'] }}{{ $record['target_plan'][$date] ?? '-' }}{{ $record['production_plan'][$date] ?? '-' }}--{{ $record['daily_target'] ?? '-' }} + {{ $record['daily_target_dynamic'][$date] ?? '-' }} + + {{ $record['produced_quantity'][$date] ?? '-' }} + {{ $record['produced_quantity'] ?? '-' }}
+ No production plan data found. +
+
+
+ +