diff --git a/app/Filament/Pages/ProductionPlanTarget.php b/app/Filament/Pages/ProductionPlanTarget.php new file mode 100644 index 00000000..a9ac305d --- /dev/null +++ b/app/Filament/Pages/ProductionPlanTarget.php @@ -0,0 +1,383 @@ +statePath('filters') + ->schema([ + Section::make('') + ->schema([ + Select::make('year') + ->label('Year') + ->reactive() + // ->searchable() + ->options([ + '2025' => '2025', + '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); + $set('plant_id', null); + $set('line_id', null); + $set('category', null); + $plantId = $get('plant_id'); + $lineId = $get('line_id'); + // $this->dispatch('loadData',$plantId, $lineId, $state, ''); + $this->dispatch('loadData',$state, '', '', '', ''); + }), + + Select::make('month') + ->label('Month') + ->reactive() + // ->searchable() + ->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, $set) { + + $set('plant_id', null); + $set('line_id', null); + $set('category', null); + + $year = $get('year'); + + $this->dispatch('loadData',$year, $state, '', '', ''); + + // $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); + }), + Select::make('plant_id') + ->label('Plant') + ->relationship('plant', 'name') + ->reactive() + // ->searchable() + ->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) { + // dd($state); + $set('line_id', null); + $set('category', null); + $this->dispatch('loadData',$state, '', '', '', ''); + }), + Select::make('line_id') + ->label('Line') + ->required() + // ->relationship('line', 'name') + // ->searchable() + ->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) { + $this->dispatch('loadData',$state, '', '', '', ''); + }), + // ->afterStateUpdated(function ($state, callable $get, $set) { + // $plantId = $get('plant_id'); + // $lineId = $state; + // // $month = $get('month'); + // $year = $get('year'); + + // $month = (int) $get('month'); + // $this->dispatch('loadData',$year, $month, $plantId, $lineId, ''); + // }), + + Select::make('week') + ->label('Choose Week') + ->reactive() + // ->searchable() + ->options([ + 'all_weeks' => 'All Weeks', + 'Week_1' => 'Week 1', + 'Week_2' => 'Week 2', + 'Week_3' => 'Week 3', + 'Week_4' => 'Week 4', + 'Week_5' => 'Week 5', + ]) + ->required() + ->afterStateUpdated(function ($state, callable $get, $set) { + $set('category', null); + + $year = $get('year'); + + $this->dispatch('loadData',$year, $state, '', '', ''); + + // $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); + }), + + TextInput::make('category') + ->label('Category') + ->reactive() + ->afterStateUpdated(function ($state, callable $get, $set) { + $plantId = $get('plant_id'); + $lineId = $get('line_id'); + // $month = $get('month'); + $year = $get('year'); + + $month = (int) $get('month'); + $category = $get('category'); + + }), + + ]) + ->columns(6) + ]); + } + + 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); + + // $this->dispatch('loadDataMonthly' ,$plantId, $lineId, $year, $month); + } + + public function importDayPlan($filePath) + { + $plantId = $this->filters['plant_id'] ?? null; + $lineId = $this->filters['line_id'] ?? null; + $year = $this->filters['year'] ?? null; + $month = $this->filters['month'] ?? null; + $week = $this->filters['week'] ?? null; + + if (!$plantId || !$lineId || !$year || !$month || !$week) { + Notification::make() + ->title('Missing Filters') + ->body('Please select Plant, Line, Year, Month and Week.') + ->danger() + ->send(); + + return; + } + + try { + + $fullPath = Storage::disk('local')->path($filePath); + + Excel::import( + new DayPlanTargetImport( + $plantId, + $lineId, + $year, + $month, + $week + ), + $fullPath + ); + + Notification::make() + ->title('Import Successful') + ->body('Selected week daily targets imported successfully.') + ->success() + ->send(); + + $this->dispatch('loadWeekData',$year, $month, $plantId, $lineId, $week); + + } catch (\Throwable $e) { + + Notification::make() + ->title('Import Failed') + ->body($e->getMessage()) + ->danger() + ->persistent() + ->send(); + } + } + + public function downloadSampleFormat() + { + $plantId = $this->filters['plant_id'] ?? null; + $lineId = $this->filters['line_id'] ?? null; + $year = $this->filters['year'] ?? null; + $month = $this->filters['month'] ?? null; + $week = $this->filters['week'] ?? null; + + if (!$plantId || !$lineId || !$year || !$month || !$week) { + + Notification::make() + ->title('Missing Filters') + ->body('Please select Plant, Line, Year, Month and Week.') + ->danger() + ->send(); + + return; + } + + return Excel::download( + new DayPlanSampleExport( + $plantId, + $lineId, + $year, + $month, + $week + ), + "Day_Plan_Sample_{$week}.xlsx" + ); + } + + public function generate(){ + $plantId = $this->filters['plant_id'] ?? null; + $lineId = $this->filters['line_id'] ?? null; + $year = $this->filters['year'] ?? null; + $month = (int) $this->filters['month'] ?? null; + $week = $this->filters['week'] ?? null; + $category = $this->filters['category'] ?? null; + + + if($week != '' && $week != null){ + $this->dispatch('loadWeekData',$year, $month, $plantId, $lineId, $week); + } + else if($category == '' || $category == null){ + $this->dispatch('loadData',$year, $month, $plantId, $lineId, ''); + } + else{ + $this->dispatch('loadDataCategory',$year, $month, $plantId, $lineId, $category); + } + + } + + public function importDayPlanAction(): Action + { + return Action::make('importDayPlan') + ->label('Import') + ->form([ + FileUpload::make('file') + ->label('Choose Excel File') + ->acceptedFileTypes([ + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + ]) + ->required() + ->disk('local') + ->directory('day-plan-imports'), + ]) + ->action(function (array $data) { + $this->importDayPlan($data['file']); + }); + } + + public static function canAccess(): bool + { + return Auth::check() && Auth::user()->can('view production plan target page'); + } +} diff --git a/app/Livewire/ProductionPlanTarget.php b/app/Livewire/ProductionPlanTarget.php new file mode 100644 index 00000000..78f99fdc --- /dev/null +++ b/app/Livewire/ProductionPlanTarget.php @@ -0,0 +1,1003 @@ + 'loadProductionData', + 'loadData1' => 'exportProductionData', + 'loadDataCategory' => 'loadProductionCategoryData', + 'loadWeekData' => 'loadProductionDataWeek' + ]; + + 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; + } + + private function getWeekDates($month, $year, $week) + { + $month = (int) $month; + $year = (int) $year; + + if ($week === 'all_weeks') { + return $this->getMonthDates($month, $year); + } + + $weekRanges = [ + 'week_1' => [1, 7], + 'week_2' => [8, 14], + 'week_3' => [15, 21], + 'week_4' => [22, 28], + 'week_5' => [29, 31], + ]; + + $week = strtolower(trim((string) $week)); + + if (!array_key_exists($week, $weekRanges)) { + return []; + } + + [$startDay, $endDay] = $weekRanges[$week]; + + $daysInMonth = Carbon::create($year, $month, 1)->daysInMonth; + + $endDay = min($endDay, $daysInMonth); + + if ($startDay > $daysInMonth) { + return []; + } + + $dates = []; + + for ($day = $startDay; $day <= $endDay; $day++) { + $dates[] = Carbon::create($year, $month, $day)->format('Y-m-d'); + } + + return $dates; + } + + public function getDailyPlanColumns() + { + return array_map( + fn($day) => "production_plans.day_{$day}", + range(1, 31) + ); + } + + // 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(); + + // $remainingQty = $row['plan_quantity']; + // // $remainingDays = $row['working_days']; + // $remainingDays = (int) ($row['working_days'] ?? 0); + + // $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; + // } + + // if ($remainingDays > 0) { + // $remainingDays--; + // } + + // // $remainingDays--; + // } + + // return $row; + // }) + // ->toArray(); + // } + + + // public function loadProductionData($year, $month, $plantId, $lineId, $category) + // { + // if (!$plantId || !$lineId || !$month || !$year) { + // $this->records = []; + // $this->dates = []; + // $this->leaveDates = []; + // return; + // } + + // $dates = $this->getMonthDates($month, $year); + // $this->dates = $dates; + + // $plans = 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) + // ->when($category, function ($query) use ($category) { + // $query->where('items.category', $category); + // }) + // ->select( + // 'production_plans.item_id', + // 'production_plans.plant_id', + // 'production_plans.line_id', + // 'production_plans.plan_quantity', + // 'production_plans.working_days', + // 'production_plans.leave_dates', + // 'items.code as item_code', + // 'items.category as category', + // 'items.description as item_description', + // 'items.hourly_quantity as hourly_quantity', + // 'lines.name as line_name', + // // 'lines.line_capacity as line_capacity', + // 'plants.name as plant_name' + // ) + // ->get(); + + // $leaveDates = []; + + // if ($plans->isNotEmpty() && $plans[0]->leave_dates) { + // $leaveDates = array_map('trim', explode(',', $plans[0]->leave_dates)); + // } + + // $this->leaveDates = $leaveDates; + + // // $producedData = QualityValidation::selectRaw(" + // // plant_id, + // // line_id, + // // sticker_master_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) + // // ->when($category, function ($query) use ($category) { + // // $query->whereHas('item', function ($q) use ($category) { + // // $q->where('category', $category); + // // }); + // // }) + // // ->groupBy('plant_id', 'line_id', 'sticker_master_id', DB::raw('DATE(created_at)')) + // // ->get() + // // ->groupBy(fn($row) => + // // $row->plant_id . '_' . $row->line_id . '_' . $row->item_id + // // ) + // // ->map(fn($group) => $group->keyBy('prod_date')); + + // $producedData = QualityValidation::selectRaw(" + // quality_validations.plant_id, + // quality_validations.line_id, + // quality_validations.sticker_master_id, + // sticker_masters.item_id, + // DATE(quality_validations.created_at) as prod_date, + // COUNT(*) as total_qty + // ") + // ->join('sticker_masters', 'sticker_masters.id', '=', 'quality_validations.sticker_master_id') + // ->where('quality_validations.plant_id', $plantId) + // ->where('quality_validations.line_id', $lineId) + // ->whereMonth('quality_validations.created_at', $month) + // ->whereYear('quality_validations.created_at', $year) + // ->when($category, function ($query) use ($category) { + // $query->whereHas('item', function ($q) use ($category) { + // $q->where('category', $category); + // }); + // }) + // ->groupBy( + // 'quality_validations.plant_id', + // 'quality_validations.line_id', + // 'quality_validations.sticker_master_id', + // 'sticker_masters.item_id', + // DB::raw('DATE(quality_validations.created_at)') + // ) + // ->get() + // ->groupBy(fn($row) => + // $row->plant_id . '_' . $row->line_id . '_' . $row->item_id + // ) + // ->map(fn($group) => $group->keyBy('prod_date')); + + + // $records = []; + + // foreach ($plans as $plan) { + + // $row = $plan->toArray(); + + // $remainingQty = (float) $row['plan_quantity']; + // $remainingDays = (int) ($row['working_days'] ?? 0); + + // $lineCapacity = (float) ($row['line_capacity'] ?? 0); + // $dailyHourlyQuantity = (float) ($row['hourly_quantity'] ?? 0); + + // $row['category'] = $row['category'] ?? '-'; + // $row['daily_hourly_quantity'] = []; + // $row['daily_target_dynamic'] = []; + // $row['produced_quantity'] = []; + + // $key = $row['plant_id'].'_'.$row['line_id'].'_'.$row['item_id']; + + // foreach ($dates as $date) { + + // // Skip leave dates fast + // if (isset($leaveDates) && in_array($date, $leaveDates)) { + // $row['daily_hourly_quantity'][$date] = '-'; + // $row['daily_target_dynamic'][$date] = '-'; + // $row['produced_quantity'][$date] = '-'; + // continue; + // } + + // $todayTarget = $remainingDays > 0 + // ? round($remainingQty / $remainingDays, 2) + // : 0; + + // $producedQty = $producedData[$key][$date]->total_qty ?? 0; + + // $row['daily_target_dynamic'][$date] = $todayTarget; + // $row['produced_quantity'][$date] = $producedQty; + // $row['daily_hourly_quantity'][$date] = $dailyHourlyQuantity * 22.5; + + // // Carry forward remaining qty + // $remainingQty = max(0, $remainingQty - $producedQty); + + // if ($remainingDays > 0) { + // $remainingDays--; + // } + // } + + // $records[] = $row; + // } + + // $this->records = $records; + // } + + // public function loadProductionDataCategory($year, $month, $plantId, $lineId, $category) + // { + // if (!$plantId || !$lineId || !$month || !$year || !$category) { + // $this->records = []; + // $this->dates = []; + // $this->leaveDates = []; + // return; + // } + + // $dates = $this->getMonthDates($month, $year); + // $this->dates = $dates; + + // $plans = 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', + // 'production_plans.leave_dates', + // 'items.code as item_code', + // 'items.description as item_description', + // 'lines.name as line_name', + // 'lines.line_capacity as line_capacity', + // 'plants.name as plant_name' + // ) + // ->get(); + + // $leaveDates = []; + + // if ($plans->isNotEmpty() && $plans[0]->leave_dates) { + // $leaveDates = array_map('trim', explode(',', $plans[0]->leave_dates)); + // } + + // $this->leaveDates = $leaveDates; + + // $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(fn($row) => + // $row->plant_id . '_' . $row->line_id . '_' . $row->item_id + // ) + // ->map(fn($group) => $group->keyBy('prod_date')); + + + // $records = []; + + // foreach ($plans as $plan) { + + // $row = $plan->toArray(); + + // $remainingQty = (float) $row['plan_quantity']; + // $remainingDays = (int) ($row['working_days'] ?? 0); + + // $lineCapacity = (float) ($row['line_capacity'] ?? 0); + // $dailyLineCapacity = (float) ($row['line_capacity'] ?? 0); + + + // $row['daily_line_capacity'] = []; + // $row['daily_target_dynamic'] = []; + // $row['produced_quantity'] = []; + + // $key = $row['plant_id'].'_'.$row['line_id'].'_'.$row['item_id']; + + // foreach ($dates as $date) { + + // // Skip leave dates fast + // if (isset($leaveDates) && in_array($date, $leaveDates)) { + // $row['daily_line_capacity'][$date] = '-'; + // $row['daily_target_dynamic'][$date] = '-'; + // $row['produced_quantity'][$date] = '-'; + // continue; + // } + + // $todayTarget = $remainingDays > 0 + // ? round($remainingQty / $remainingDays, 2) + // : 0; + + // $producedQty = $producedData[$key][$date]->total_qty ?? 0; + + // $row['daily_target_dynamic'][$date] = $todayTarget; + // $row['produced_quantity'][$date] = $producedQty; + // $row['daily_line_capacity'][$date] = $dailyLineCapacity; + + // // Carry forward remaining qty + // $remainingQty = max(0, $remainingQty - $producedQty); + + // if ($remainingDays > 0) { + // $remainingDays--; + // } + // } + + // $records[] = $row; + // } + + // $this->records = $records; + // } + + + + + public function loadProductionDataWeek($year, $month, $plantId, $lineId, $week) + { + $this->records = []; + $this->monthlyRecords = 0; + $this->monthlyActualQuantity = 0; + $this->efficiency = 0; + $this->dates = []; + $this->leaveDates = []; + + if (!$plantId || !$lineId || !$month || !$year) { + return; + } + + $startDate = Carbon::create($year, $month, 1)->startOfDay(); + + $endDate = $startDate->copy()->addMonth(); + + $dates = $this->getWeekDates($month, $year, $week); + + $this->dates = $dates; + + $plans = 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) + ->where('production_plans.created_at', '>=', $startDate) + ->where('production_plans.created_at', '<', $endDate) + ->select(array_merge( + [ + 'production_plans.item_id', + 'production_plans.plant_id', + 'production_plans.line_id', + 'production_plans.plan_quantity', + 'production_plans.working_days', + 'production_plans.leave_dates', + 'items.code as item_code', + 'items.category as category', + 'items.description as item_description', + 'items.hourly_quantity as hourly_quantity', + 'lines.name as line_name', + 'plants.name as plant_name', + ], + $this->getDailyPlanColumns() + )) + ->get(); + + $leaveDates = []; + + if ($plans->isNotEmpty() && $plans[0]->leave_dates) { + $leaveDates = array_map( + 'trim', + explode(',', $plans[0]->leave_dates) + ); + } + + $this->leaveDates = $leaveDates; + + $leaveDateLookup = array_fill_keys($leaveDates, true); + + $producedData = QualityValidation::selectRaw(" + quality_validations.plant_id, + quality_validations.line_id, + sticker_masters.item_id, + DATE(quality_validations.created_at) as prod_date, + COUNT(*) as total_qty + ") + ->join( + 'sticker_masters', + 'sticker_masters.id', + '=', + 'quality_validations.sticker_master_id' + ) + ->where('quality_validations.plant_id', $plantId) + ->where('quality_validations.line_id', $lineId) + ->where('quality_validations.created_at', '>=', $startDate) + ->where('quality_validations.created_at', '<', $endDate) + ->groupBy( + 'quality_validations.plant_id', + 'quality_validations.line_id', + 'sticker_masters.item_id', + DB::raw('DATE(quality_validations.created_at)') + ) + ->get() + ->groupBy(fn($row) => + $row->plant_id . '_' . + $row->line_id . '_' . + $row->item_id + ) + ->map(fn($group) => $group->keyBy('prod_date')); + + $records = []; + + foreach ($plans as $plan) { + + $row = $plan->toArray(); + + $row['category'] = $row['category'] ?? '-'; + + $row['daily_target_dynamic'] = []; + + $row['produced_quantity'] = []; + + $key = $row['plant_id'] . '_' . + $row['line_id'] . '_' . + $row['item_id']; + + foreach ($dates as $date) { + + if (isset($leaveDateLookup[$date])) { + + $row['daily_target_dynamic'][$date] = '-'; + + $row['produced_quantity'][$date] = '-'; + + continue; + } + + $dayNumber = Carbon::parse($date)->day; + + $dayColumn = 'day_' . $dayNumber; + + $todayTarget = (float) ($row[$dayColumn] ?? 0); + + $producedQty = $producedData[$key][$date]->total_qty ?? 0; + + $row['daily_target_dynamic'][$date] = $todayTarget; + + $row['produced_quantity'][$date] = $producedQty; + } + + $records[] = $row; + } + + $this->records = $records; + + $this->monthlyRecords = ProductionPlan::where('plant_id', $plantId) + ->where('line_id', $lineId) + ->where('created_at', '>=', $startDate) + ->where('created_at', '<', $endDate) + ->sum('plan_quantity'); + + $this->monthlyActualQuantity = QualityValidation::where('plant_id', $plantId) + ->where('line_id', $lineId) + ->where('created_at', '>=', $startDate) + ->where('created_at', '<', $endDate) + ->count(); + + $this->efficiency = $this->monthlyRecords > 0 + ? ($this->monthlyActualQuantity / $this->monthlyRecords) * 100 + : 0; + } + + public function loadProductionData($year, $month, $plantId, $lineId) + { + $this->records = []; + $this->monthlyRecords = 0; + $this->monthlyActualQuantity = 0; + $this->efficiency = 0; + $this->dates = []; + $this->leaveDates = []; + + if (!$plantId || !$lineId || !$month || !$year) { + return; + } + + $startDate = Carbon::create($year, $month, 1)->startOfDay(); + + $endDate = $startDate->copy()->addMonth(); + + $dates = $this->getMonthDates($month, $year); + + $this->dates = $dates; + + $plans = 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) + ->where('production_plans.created_at', '>=', $startDate) + ->where('production_plans.created_at', '<', $endDate) + ->select(array_merge( + [ + 'production_plans.item_id', + 'production_plans.plant_id', + 'production_plans.line_id', + 'production_plans.plan_quantity', + 'production_plans.working_days', + 'production_plans.leave_dates', + 'items.code as item_code', + 'items.category as category', + 'items.description as item_description', + 'items.hourly_quantity as hourly_quantity', + 'lines.name as line_name', + 'plants.name as plant_name', + ], + $this->getDailyPlanColumns() + )) + ->get(); + + $leaveDates = []; + + if ($plans->isNotEmpty() && $plans[0]->leave_dates) { + $leaveDates = array_map( + 'trim', + explode(',', $plans[0]->leave_dates) + ); + } + + $this->leaveDates = $leaveDates; + + $leaveDateLookup = array_fill_keys($leaveDates, true); + + $producedData = QualityValidation::selectRaw(" + quality_validations.plant_id, + quality_validations.line_id, + sticker_masters.item_id, + DATE(quality_validations.created_at) as prod_date, + COUNT(*) as total_qty + ") + ->join( + 'sticker_masters', + 'sticker_masters.id', + '=', + 'quality_validations.sticker_master_id' + ) + ->where('quality_validations.plant_id', $plantId) + ->where('quality_validations.line_id', $lineId) + ->where('quality_validations.created_at', '>=', $startDate) + ->where('quality_validations.created_at', '<', $endDate) + ->groupBy( + 'quality_validations.plant_id', + 'quality_validations.line_id', + 'sticker_masters.item_id', + DB::raw('DATE(quality_validations.created_at)') + ) + ->get() + ->groupBy(fn($row) => + $row->plant_id . '_' . + $row->line_id . '_' . + $row->item_id + ) + ->map(fn($group) => $group->keyBy('prod_date')); + + $records = []; + + foreach ($plans as $plan) { + + $row = $plan->toArray(); + + $row['category'] = $row['category'] ?? '-'; + + $row['daily_target_dynamic'] = []; + + $row['produced_quantity'] = []; + + $key = $row['plant_id'] . '_' . + $row['line_id'] . '_' . + $row['item_id']; + + foreach ($dates as $date) { + + if (isset($leaveDateLookup[$date])) { + + $row['daily_target_dynamic'][$date] = '-'; + + $row['produced_quantity'][$date] = '-'; + + continue; + } + + $dayNumber = Carbon::parse($date)->day; + + $dayColumn = 'day_' . $dayNumber; + + $todayTarget = (float) ($row[$dayColumn] ?? 0); + + $producedQty = $producedData[$key][$date]->total_qty ?? 0; + + $row['daily_target_dynamic'][$date] = $todayTarget; + + $row['produced_quantity'][$date] = $producedQty; + } + + $records[] = $row; + } + + $this->records = $records; + + $this->monthlyRecords = ProductionPlan::where('plant_id', $plantId) + ->where('line_id', $lineId) + ->where('created_at', '>=', $startDate) + ->where('created_at', '<', $endDate) + ->sum('plan_quantity'); + + $this->monthlyActualQuantity = QualityValidation::where('plant_id', $plantId) + ->where('line_id', $lineId) + ->where('created_at', '>=', $startDate) + ->where('created_at', '<', $endDate) + ->count(); + + $this->efficiency = $this->monthlyRecords > 0 + ? ($this->monthlyActualQuantity / $this->monthlyRecords) * 100 + : 0; + } + + public function loadProductionCategoryData($year, $month, $plantId, $lineId, $category) + { + + $this->records = []; + $this->monthlyRecords = 0; + $this->dates = []; + $this->leaveDates = []; + + if (!$plantId || !$lineId || !$month || !$year || !$category) { + return; + } + + $startDate = Carbon::create($year, $month, 1)->startOfDay(); + $endDate = $startDate->copy()->addMonth(); + + $dates = $this->getMonthDates($month, $year); + $this->dates = $dates; + + $plans = 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) + ->where('items.category', $category) + // ->whereMonth('production_plans.created_at', $month) + // ->whereYear('production_plans.created_at', $year) + ->where('production_plans.created_at', '>=', $startDate) + ->where('production_plans.created_at', '<', $endDate) + ->select( + 'production_plans.item_id', + 'production_plans.plant_id', + 'production_plans.line_id', + 'production_plans.plan_quantity', + 'production_plans.working_days', + 'production_plans.leave_dates', + 'items.code as item_code', + 'items.category as category', + 'items.description as item_description', + 'items.hourly_quantity as hourly_quantity', + 'lines.name as line_name', + // 'lines.line_capacity as line_capacity', + 'plants.name as plant_name' + ) + ->get(); + + $leaveDates = []; + + if ($plans->isNotEmpty() && $plans[0]->leave_dates) { + $leaveDates = array_map('trim', explode(',', $plans[0]->leave_dates)); + } + + $this->leaveDates = $leaveDates; + + $producedData = QualityValidation::selectRaw(" + quality_validations.plant_id, + quality_validations.line_id, + sticker_masters.item_id, + DATE(quality_validations.created_at) as prod_date, + COUNT(*) as total_qty + ") + ->join( + 'sticker_masters', + 'sticker_masters.id', + '=', + 'quality_validations.sticker_master_id' + ) + ->join('items', 'items.id', '=', 'sticker_masters.item_id') + ->where('items.category', $category) + ->where('quality_validations.plant_id', $plantId) + ->where('quality_validations.line_id', $lineId) + ->where('quality_validations.created_at', '>=', $startDate) + ->where('quality_validations.created_at', '<', $endDate) + // ->whereMonth('quality_validations.created_at', $month) + // ->whereYear('quality_validations.created_at', $year) + ->groupBy( + 'quality_validations.plant_id', + 'quality_validations.line_id', + 'sticker_masters.item_id', + DB::raw('DATE(quality_validations.created_at)') + ) + ->get() + ->groupBy(fn($row) => + $row->plant_id . '_' . $row->line_id . '_' . $row->item_id + ) + ->map(fn($group) => $group->keyBy('prod_date')); + + $records = []; + + foreach ($plans as $plan) { + + $row = $plan->toArray(); + + $workingDays = (int) ($row['working_days'] ?? 0); + + $normalDailyTarget = $workingDays > 0 + ? round((float) $row['plan_quantity'] / $workingDays, 2) + : 0; + + $pendingQty = 0; + + $lineCapacity = (float) ($row['line_capacity'] ?? 0); + $dailyHourlyQuantity = (float) ($row['hourly_quantity'] ?? 0); + + $row['category'] = $row['category'] ?? '-'; + // $row['daily_hourly_quantity'] = []; + $row['daily_target_dynamic'] = []; + $row['produced_quantity'] = []; + + $key = $row['plant_id'] . '_' . $row['line_id'] . '_' . $row['item_id']; + + foreach ($dates as $date) { + if (in_array($date, $leaveDates)) { + + // $row['daily_hourly_quantity'][$date] = '-'; + $row['daily_target_dynamic'][$date] = '-'; + $row['produced_quantity'][$date] = '-'; + + continue; + } + + $todayTarget = round( + $normalDailyTarget + $pendingQty, + 2 + ); + + $producedQty = $producedData[$key][$date]->total_qty ?? 0; + + $row['daily_target_dynamic'][$date] = $todayTarget; + $row['produced_quantity'][$date] = $producedQty; + // $row['daily_hourly_quantity'][$date] = $dailyHourlyQuantity * 22.5; + + $pendingQty = max( + 0, + $todayTarget - $producedQty + ); + } + + $records[] = $row; + } + + $this->records = $records; + + $this->monthlyRecords = ProductionPlan::where('plant_id', $plantId) + ->where('line_id', $lineId) + ->whereYear('created_at', $year) + ->whereMonth('created_at', $month) + ->sum('plan_quantity'); + + $this->monthlyActualQuantity = QualityValidation::where('plant_id', $plantId) + ->where('line_id', $lineId) + ->where('created_at', '>=', $startDate) + ->where('created_at', '<', $endDate) + // ->whereYear('created_at', $year) + // ->whereMonth('created_at', $month) + ->count(); + + $this->efficiency = $this->monthlyRecords > 0 + ? ($this->monthlyActualQuantity / $this->monthlyRecords) * 100 + : 0; + + //$this->monthlyRecords = $plans->sum('plan_quantity'); + } + + 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-plan-target', [ + 'records' => $this->records, + 'monthlyRecords' => $this->monthlyRecords, + 'monthlyActualRecords' => $this->monthlyActualQuantity, + 'monthlyEfficiency' => $this->efficiency, + 'dates' => $this->dates, + ]); + } +} diff --git a/resources/views/filament/pages/production-plan-target.blade.php b/resources/views/filament/pages/production-plan-target.blade.php new file mode 100644 index 00000000..993640f0 --- /dev/null +++ b/resources/views/filament/pages/production-plan-target.blade.php @@ -0,0 +1,48 @@ + +
+ + {{-- Render the Select form fields --}} +
+ {{ $this->form }} +
+ {{-- + Import + --}} + + + Download Sample Format + + + + Import + + + Export + + + Generate + +
+ +
+
+
diff --git a/resources/views/livewire/production-plan-target.blade.php b/resources/views/livewire/production-plan-target.blade.php new file mode 100644 index 00000000..498c6b3b --- /dev/null +++ b/resources/views/livewire/production-plan-target.blade.php @@ -0,0 +1,161 @@ +
+ +
+

+ MONTHLY PRODUCTION PLAN: +

+ +
+ + + + + + + + + + + + + + + @if (!empty($records)) + + + + + + + + + + + @if(($efficiency ?? 0) > 95) + @php $bgStyle = 'background-color: #22c55e; color: white;' @endphp + @elseif(($efficiency ?? 0) >= 85) + @php $bgStyle = 'background-color: #eab308; color: white;' @endphp + @else + @php $bgStyle = 'background-color: #f87171; color: white;' @endphp + @endif + + + + @else + + + + @endif + + +
NoPlantLine + Monthly Plan Quantity + + Monthly Actual Quantity + + Monthly Efficiency(%) +
+ 1 + + {{ $records[0]['plant_name'] ?? '-' }} + + {{ $records[0]['line_name'] ?? '-' }} + + {{ $monthlyRecords ?? 0 }} + + {{ $monthlyActualQuantity ?? 0 }} + + {{ number_format($efficiency ?? 0, 2) }}% +
+ No monthly production plan data found. +
+
+
+ + {{-- //.. --}} +

+ 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 + +
NoPlantLineItem CodeCategory + Production Plan Dates +
+ {{ $date }} + + {{-- {{ $date }} --}} + {{ \Carbon\Carbon::parse($date)->format('d-m-Y') }} +
Item QuantityPlan Quantity + Actual Quantity + Produced Quantity
{{ $index + 1 }}{{ $record['plant_name'] }}{{ $record['line_name'] }}{{ $record['item_code'] }}{{ $record['category'] }}{{ $record['target_plan'][$date] ?? '-' }}{{ $record['production_plan'][$date] ?? '-' }}---{{ $record['daily_target'] ?? '-' }} + {{ $record['daily_hourly_quantity'][$date] ?? '-' }} + + {{ $record['daily_target_dynamic'][$date] ?? '-' }} + + {{ $record['produced_quantity'][$date] ?? '-' }} + {{ $record['produced_quantity'] ?? '-' }}
+ No production plan data found. +
+
+