diff --git a/app/Filament/Resources/ProductionLineStopResource.php b/app/Filament/Resources/ProductionLineStopResource.php index 73ed566..0301077 100644 --- a/app/Filament/Resources/ProductionLineStopResource.php +++ b/app/Filament/Resources/ProductionLineStopResource.php @@ -226,6 +226,7 @@ class ProductionLineStopResource extends Resource Forms\Components\DateTimePicker::make('to_datetime') ->label('To DateTime') ->required() + ->after('from_datetime') ->reactive() ->afterStateUpdated(fn ($state, callable $set, callable $get) => self::updateStopDuration($get, $set) //self means it calling the function within the class @@ -260,11 +261,21 @@ class ProductionLineStopResource extends Resource if ($fromTime->lt($toTime)) { $diffInMinutes = $fromTime->diffInMinutes($toTime); - $set('stop_hour', floor($diffInMinutes / 60)); - $set('stop_min', $diffInMinutes % 60); + // $set('stop_hour', floor($diffInMinutes / 60)); + // $set('stop_min', $diffInMinutes % 60); + if((floor($diffInMinutes / 60) === 0.0) && ($diffInMinutes % 60 === 0)) + { + $set('stop_hour', null); + $set('stop_min', null); + } + else + { + $set('stop_hour', floor($diffInMinutes / 60)); + $set('stop_min', $diffInMinutes % 60); + } } else { - $set('stop_hour', 0); - $set('stop_min', 0); + $set('stop_hour', null); + $set('stop_min', null); } } } diff --git a/app/Filament/Resources/ProductionPlanResource.php b/app/Filament/Resources/ProductionPlanResource.php index 9bda270..93cf25d 100644 --- a/app/Filament/Resources/ProductionPlanResource.php +++ b/app/Filament/Resources/ProductionPlanResource.php @@ -15,6 +15,7 @@ use Filament\Tables\Table; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\SoftDeletingScope; use Filament\Forms\Components\Section; +use Illuminate\Support\Facades\Request; class ProductionPlanResource extends Resource { @@ -147,6 +148,25 @@ class ProductionPlanResource extends Resource } else { + //SELECT COUNT(*) FROM plant_quantity_details WHERE DATE(created_at) = '{DateTime.Now.ToString("yyyy-MM-dd")}' AND shift_id = '{userShiftId}' AND plant_id = '{userPlantId}' AND line_id = '{userLineId}' + //Day shift 'Plant Production Quantity' already updated into database + + // $currentPath = url()->current(); + // $currentPath = $_SERVER['REQUEST_URI']; + // dd($currentPath); + $exists = ProductionPlan::where('plant_id', $get('plant_id')) + ->where('shift_id', $get('shift_id')) + ->where('line_id', $get('line_id')) + ->whereDate('created_at', today()) + ->exists(); + + if ($exists) + { + $set('line_id', null); + $set('ppLineError', $get('shift_id.name').' Production Plan already updated.'); + return; + } + $set('ppLineError', null); } }) diff --git a/app/Filament/Resources/ProductionQuantityResource.php b/app/Filament/Resources/ProductionQuantityResource.php index 1d706ce..91f52af 100644 --- a/app/Filament/Resources/ProductionQuantityResource.php +++ b/app/Filament/Resources/ProductionQuantityResource.php @@ -143,20 +143,24 @@ class ProductionQuantityResource extends Resource ->reactive() ->afterStateUpdated(function ($state, callable $set, callable $get) { $lineId = $get('line_id'); + $set('item_code', null); if (!$lineId) { - $set('ppLineError', 'Please select a line first.'); + $set('pqLineError', 'Please select a line first.'); return; } else { $set('validationError', null); - $set('ppLineError', null); + $set('pqLineError', null); + $set('item_id', null); + $set('item_description', null); + $set('serial_number', null); } }) ->extraAttributes(fn ($get) => [ - 'class' => $get('ppLineError') ? 'border-red-500' : '', + 'class' => $get('pqLineError') ? 'border-red-500' : '', ]) - ->hint(fn ($get) => $get('ppLineError') ? $get('ppLineError') : null) + ->hint(fn ($get) => $get('pqLineError') ? $get('pqLineError') : null) ->hintColor('danger'), // Forms\Components\Select::make('item_id') // ->label('Item Code') @@ -214,62 +218,128 @@ class ProductionQuantityResource extends Resource $set('validationError', 'Please select a line first.'); return; } + + $exists = \App\Models\ProductionPlan::where('plant_id', $get('plant_id')) + ->where('shift_id', $get('shift_id')) + ->where('line_id', $get('line_id')) + ->whereDate('created_at', today()) + ->exists(); + + if (!$exists) + { + $set('item_code', null); + $set('item_id', null); + $set('item_description', null); + $set('serial_number', null); + $set('validationError', 'Please set production plan first.'); + return; + } + $set('validationError', null); } - if (!preg_match('/^[a-zA-Z0-9]+\|[a-zA-Z0-9]+(\|)?$/', $state)) { + if (!preg_match('/^[a-zA-Z0-9]{6,}+\|[1-9][a-zA-Z0-9]{8,}+(\|)?$/', $state)) { + if (strpos($state, '|') === false) { + $set('validationError', 'Scan valid QR code. (Ex: Item_Code|Serial_Number )'); + $set('item_id', null); + $set('item_description', null); + $set('serial_number', null); + return; + } + else + { + $splits = explode('|', $state); + $iCode = trim($splits[0]); + $sNumber = isset($splits[1]) ? trim($splits[1]) : null; + + if (!ctype_alnum($iCode)) { + $set('validationError', 'Item code must contain alpha-numeric values.'); + $set('item_id', null); + $set('item_description', null); + $set('serial_number', null); + return; + } + else if (strlen($iCode) < 6) { + $set('validationError', 'Item code must be at least 6 digits.'); + $set('item_id', null); + $set('item_description', null); + $set('serial_number', null); + return; + } + else if (!ctype_alnum($sNumber)) { + $set('validationError', 'Serial Number must contain alpha-numeric values.'); + $set('item_id', null); + $set('item_description', null); + $set('serial_number', null); + return; + } + else if (strlen($sNumber) < 9) { + $set('validationError', 'Serial Number must be at least 9 digits.'); + $set('item_id', null); + $set('item_description', null); + $set('serial_number', null); + return; + } + } + $set('validationError', 'Scan valid QR code. (Ex: Item_Code|Serial_Number )'); $set('item_id', null); $set('item_description', null); $set('serial_number', null); return; } - - // Only search when all parent IDs are selected - $parts = explode('|', $state); - - $itemCode = trim($parts[0]); // Extract item code // 123456|123456789 - - $serialNumber = isset($parts[1]) ? trim($parts[1]) : null; - - if (strlen($itemCode) < 6) { - $set('validationError', 'Item code must be at least 6 digits.'); - $set('item_id', null); - $set('item_description', null); - $set('serial_number', null); - return; - } - else if (!ctype_alnum($itemCode)) { - $set('validationError', 'Item code should contain alpha-numeric values.'); - $set('item_id', null); - $set('item_description', null); - $set('serial_number', null); - return; - } - else if ($serialNumber === '') { - $set('validationError', 'Waiting for full QR scan...'); - $set('item_description', null); - $set('serial_number', null); - return; // Do not clear item_id, just wait for full input - } - else if (strlen($serialNumber) < 9) { - $set('validationError', 'Serial Number must be at least 9 digits.'); - $set('item_description', null); - $set('serial_number', null); - return; - } - else if (!ctype_alnum($serialNumber)) { - $set('validationError', 'Serial Number should contain alpha-numeric values.'); - $set('item_id', null); - $set('item_description', null); - $set('serial_number', null); - return; - } else { $set('validationError', null); + $set('item_id', null); + $set('item_description', null); + $set('serial_number', null); } + // Only search when all parent IDs are selected + $parts = explode('|', $state); + $itemCode = trim($parts[0]); + $serialNumber = isset($parts[1]) ? trim($parts[1]) : null; + + // if (strlen($itemCode) < 6) { + // $set('validationError', 'Item code must be at least 6 digits.'); + // $set('item_id', null); + // $set('item_description', null); + // $set('serial_number', null); + // return; + // } + // else if (!ctype_alnum($itemCode)) { + // $set('validationError', 'Item code must contain alpha-numeric values.'); + // $set('item_id', null); + // $set('item_description', null); + // $set('serial_number', null); + // return; + // } + // else if ($serialNumber === '') { + // $set('validationError', 'Waiting for full QR scan...'); + // $set('item_id', null); + // $set('item_description', null); + // $set('serial_number', null); + // return; // Do not clear item_id, just wait for full input + // } + // else if (strlen($serialNumber) < 9) { + // $set('validationError', 'Serial Number must be at least 9 digits.'); + // $set('item_description', null); + // $set('serial_number', null); + // return; + // } + // else if (!ctype_alnum($serialNumber)) { + // $set('validationError', 'Serial Number must contain alpha-numeric values.'); + // $set('item_id', null); + // $set('item_description', null); + // $set('serial_number', null); + // return; + // } + // else + // { + // $set('validationError', null); + // } + // Fetch item using item code and plant_id $item = \App\Models\Item::where('code', $itemCode) ->where('plant_id', $get('plant_id')) @@ -284,7 +354,7 @@ class ProductionQuantityResource extends Resource { $set('serial_number', $serialNumber); $set('item_id', $item->id); - $set('item_code', $itemCode); //$itemCode + $set('item_code', $itemCode); $set('item_description', $item->description); } else diff --git a/app/Filament/Resources/QualityValidationResource.php b/app/Filament/Resources/QualityValidationResource.php index 871e436..a5d780b 100644 --- a/app/Filament/Resources/QualityValidationResource.php +++ b/app/Filament/Resources/QualityValidationResource.php @@ -7,12 +7,19 @@ use App\Filament\Resources\QualityValidationResource\RelationManagers; use App\Models\QualityValidation; use Closure; use Filament\Forms; +use Filament\Forms\Components\DatePicker; +use Filament\Forms\Components\DateTimePicker; +use Filament\Forms\Components\TextInput; use Filament\Forms\Form; use Filament\Resources\Resource; use Filament\Tables; +use Filament\Tables\Filters\SelectFilter; use Filament\Tables\Table; use Illuminate\Database\Eloquent\Builder; +use Illuminate\Database\Eloquent\Factories\Relationship; use Illuminate\Database\Eloquent\SoftDeletingScope; +use Filament\Tables\Filters\Filter; + class QualityValidationResource extends Resource @@ -73,29 +80,70 @@ class QualityValidationResource extends Resource } // Proceed with validation logic for new scanned QR code - if (!$state) { + if (!$state || trim($state) === '') { + $set('validationError', null); return; } - if (strpos($state, '|') === false) - { + // Check if QR format contains '|' + if (strpos($state, '|') === false) { + $set('validationError', 'Scan valid QR code. (Ex: Item_Code|Serial_Number )'); return; } + if (!preg_match('/^[a-zA-Z0-9]{6,}+\|[1-9][a-zA-Z0-9]{8,}+(\|)?$/', $state)) { + if (strpos($state, '|') === false) { + $set('validationError', 'Scan valid QR code. (Ex: Item_Code|Serial_Number )'); + $set('item_id', null); + $set('item_description', null); + $set('serial_number', null); + return; + } + else + { + $splits = explode('|', $state); + $iCode = trim($splits[0]); + $sNumber = isset($splits[1]) ? trim($splits[1]) : null; + + if (!ctype_alnum($iCode)) { + $set('validationError', 'Item code must contain alpha-numeric values.'); + return; + } + else if (strlen($iCode) < 6) { + $set('validationError', 'Item code must be at least 6 digits.'); + return; + } + else if (!ctype_alnum($sNumber)) { + $set('validationError', 'Serial Number must contain alpha-numeric values.'); + return; + } + else if (strlen($sNumber) < 9) { + $set('validationError', 'Serial Number must be at least 9 digits.'); + return; + } + } + + $set('validationError', 'Scan valid QR code. (Ex: Item_Code|Serial_Number )'); + return; + } + else + { + $set('validationError', null); + } + $parts = explode('|', $state); $itemCode = trim($parts[0]); // Extract item code // 123456|123456789 $serialNumber = trim($parts[1]); - // Store serial number before resetting fields + // Store serial number before resetting fields $previousSerialNumber = $serialNumber; $previousItemCode = $itemCode; if (strlen($itemCode) < 6) { $set('validationError', 'Item code must be at least 6 digits.'); - $set('item_id', null); return; } else if (!ctype_alnum($itemCode)) { @@ -121,13 +169,6 @@ class QualityValidationResource extends Resource $set('validationError', null); } - if (!preg_match('/^[a-zA-Z0-9]+\|[a-zA-Z0-9]+(\|)?$/', $state)) { - $set('validationError', 'Invalid QR code format. Expected: Item_Code|Serial_Number.'); - return; - } - - //$set('validationError', null); - $plantId = $get('plant_id'); // Get selected plant if (!$plantId) { @@ -144,7 +185,7 @@ class QualityValidationResource extends Resource if (!$stickerMaster) { - $set('validationError', 'Scanned item code does not exist for the selected plant.'); + $set('validationError', 'Item code does not exist in master data.'); $set('sticker_master_id', null); return; } @@ -168,18 +209,18 @@ class QualityValidationResource extends Resource } } - $serialExists = QualityValidation::where('sticker_master_id', $stickerMaster->id) - ->where(function ($query) use ($serialNumber, $serialFields) { - foreach ($serialFields as $column) { - $query->orWhere($column, $serialNumber); - } - })->exists(); + // $serialExists = QualityValidation::where('sticker_master_id', $stickerMaster->id) + // ->where(function ($query) use ($serialNumber, $serialFields) { + // foreach ($serialFields as $column) { + // $query->orWhere($column, $serialNumber); + // } + // })->exists(); - if ($serialExists) { - $set('validationError', 'Already scanning process completed.'); - $set('item_id', "$previousItemCode|$previousSerialNumber"); // Restore original QR code - return; - } + // if ($serialExists) { + // $set('validationError', 'Already scanning process completed.'); + // $set('item_id', "$previousItemCode|$previousSerialNumber"); // Restore original QR code + // return; + // } // Check if the serial number exists in any column of any row $serialExists = QualityValidation::where(function ($query) use ($serialNumber, $serialFields) { @@ -507,17 +548,56 @@ class QualityValidationResource extends Resource public static function table(Table $table): Table { return $table + ->searchable() ->columns([ Tables\Columns\TextColumn::make('id') ->label('ID') ->numeric() ->sortable(), Tables\Columns\TextColumn::make('plant.name') - ->numeric() ->sortable(), - Tables\Columns\TextColumn::make('stickerMaster.id') - ->numeric() + Tables\Columns\TextColumn::make('stickerMaster.item.code') + ->label('Item Code') ->sortable(), + Tables\Columns\TextColumn::make('production_order') + ->label('Production Order') + ->sortable(), + Tables\Columns\TextColumn::make('serial_number_motor') + ->sortable(), + Tables\Columns\TextColumn::make('serial_number_pump') + ->sortable(), + Tables\Columns\TextColumn::make('serial_number_pumpset') + ->sortable(), + Tables\Columns\TextColumn::make('pack_slip_motor') + ->sortable(), + Tables\Columns\TextColumn::make('pack_slip_pump') + ->sortable(), + Tables\Columns\TextColumn::make('pack_slip_pumpset') + ->sortable(), + Tables\Columns\TextColumn::make('name_plate_motor') + ->sortable(), + Tables\Columns\TextColumn::make('name_plate_pump') + ->sortable(), + Tables\Columns\TextColumn::make('name_plate_pumpset') + ->sortable(), + Tables\Columns\TextColumn::make('tube_sticker_motor') + ->sortable(), + Tables\Columns\TextColumn::make('tube_sticker_pump') + ->sortable(), + Tables\Columns\TextColumn::make('tube_sticker_pumpset') + ->sortable(), + Tables\Columns\TextColumn::make('warranty_card') + ->sortable(), + Tables\Columns\TextColumn::make('part_validation1') + ->sortable(), + Tables\Columns\TextColumn::make('part_validation2') + ->sortable(), + Tables\Columns\TextColumn::make('part_validation3') + ->sortable(), + Tables\Columns\TextColumn::make('part_validation4') + ->sortable(), + Tables\Columns\TextColumn::make('part_validation5') + ->sortable(), Tables\Columns\TextColumn::make('created_at') ->dateTime() ->sortable() @@ -532,12 +612,73 @@ class QualityValidationResource extends Resource ->toggleable(isToggledHiddenByDefault: true), ]) ->filters([ + Tables\Filters\TrashedFilter::make(), + SelectFilter::make('item_code') + ->relationship('stickerMaster.item', 'code') + ->label('Filter by item code') + ->searchable(), + + Filter::make('production_order') + ->label('Filter by Production Order') + ->form([ + TextInput::make('production_order') + ->placeholder('Enter Production Order'), + + ]) + ->query(function ($query, array $data) { + return $query + ->when( + $data['production_order'] ?? null, + fn ($q) => $q->where('production_order', 'like', '%' . $data['production_order'] . '%') + ); + }) + + // This function adds indicators to show applied filters in the UI. + // It helps users see what filters are currently active. + + ->indicateUsing(function (array $data) { + return empty($data['production_order']) ? [] : ['Production Order: ' . $data['production_order']]; + }), + + // Created Date Range Filter + Filter::make('created_at') + ->form([ + DateTimePicker::make('created_from') + ->label('Created From') + ->native(false), // Optional: Use a nice date picker UI + + DateTimePicker::make('created_to') + ->label('Created To') + ->native(false), + ]) + ->query(function ($query, array $data) { + return $query + ->when( + $data['created_from'] ?? null, + fn ($q) => $q->where('created_at', '>=', $data['created_from']) + ) + ->when( + $data['created_to'] ?? null, + fn ($q) => $q->where('created_at', '<=', $data['created_to']) + ); + }) + ->indicateUsing(function (array $data) { + $indicators = []; + if (!empty($data['created_from'])) { + $indicators[] = 'From: ' . $data['created_from']; + } + if (!empty($data['created_to'])) { + $indicators[] = 'To: ' . $data['created_to']; + } + return $indicators; + }), ]) ->actions([ Tables\Actions\ViewAction::make(), Tables\Actions\EditAction::make(), ]) + ->bulkActions([ Tables\Actions\BulkActionGroup::make([ Tables\Actions\DeleteBulkAction::make(), @@ -545,6 +686,7 @@ class QualityValidationResource extends Resource Tables\Actions\RestoreBulkAction::make(), ]), ]); + } public static function getRelations(): array diff --git a/app/Filament/Resources/StickerMasterResource.php b/app/Filament/Resources/StickerMasterResource.php index 3ea6ac2..4d07871 100644 --- a/app/Filament/Resources/StickerMasterResource.php +++ b/app/Filament/Resources/StickerMasterResource.php @@ -187,6 +187,7 @@ class StickerMasterResource extends Resource public static function table(Table $table): Table { return $table + ->searchable() ->columns([ Tables\Columns\TextColumn::make('id') ->label('ID') diff --git a/app/Filament/Widgets/ItemOverview.php b/app/Filament/Widgets/ItemOverview.php index 6123d05..d05bbcf 100644 --- a/app/Filament/Widgets/ItemOverview.php +++ b/app/Filament/Widgets/ItemOverview.php @@ -12,72 +12,169 @@ class ItemOverview extends ChartWidget //protected $listeners = ['filtersUpdated' => '$refresh']; // Listen for filter updates - protected function getData(): array - { - $activeFilter = $this->filter; - // Get filter values from session - $selectedPlant = session('selected_plant'); - $selectedLine = session('selected_line'); + // protected function getData(): array + // { + // $activeFilter = $this->filter; + // // Get filter values from session + // $selectedPlant = session('selected_plant'); + // $selectedLine = session('selected_line'); - $query = \DB::table('production_quantities') - ->join('plants', 'production_quantities.plant_id', '=', 'plants.id') // Join plants table - ->join('lines', 'production_quantities.line_id', '=', 'lines.id') // Join lines table - ->selectRaw('EXTRACT(HOUR FROM production_quantities.created_at) AS hour, count(*) AS total_quantity') - ->whereBetween('production_quantities.created_at', [now()->startOfDay(), now()->endOfDay()]) + // $query = \DB::table('production_quantities') + // ->join('plants', 'production_quantities.plant_id', '=', 'plants.id') // Join plants table + // ->join('lines', 'production_quantities.line_id', '=', 'lines.id') // Join lines table + // ->selectRaw('EXTRACT(HOUR FROM production_quantities.created_at) AS hour, count(*) AS total_quantity') + // ->whereBetween('production_quantities.created_at', [now()->startOfDay(), now()->endOfDay()]) + // ->when($selectedPlant, function ($q) use ($selectedPlant) { + // return $q->where('plants.id', $selectedPlant); + // }) + // ->when($selectedLine, function ($q) use ($selectedLine) { + // return $q->where('lines.id', $selectedLine); + // }) + // ->groupByRaw('EXTRACT(HOUR FROM production_quantities.created_at)') + // ->orderByRaw('EXTRACT(HOUR FROM production_quantities.created_at)') + // ->pluck('total_quantity', 'hour') + // ->toArray(); + + // $allHours = array_fill(0, 24, 0); + // $data = array_replace($allHours, $query); + + // $shiftedKeys = range(8, 23); // 8 AM to 11 PM + // $shiftedKeys = array_merge($shiftedKeys, range(0, 8)); + + // $orderedData = array_map(fn($hour) => $data[$hour], $shiftedKeys); + + // return [ + // 'datasets' => [ + // [ + // 'label' => 'Hourly Production', + // 'data' => array_values($orderedData), + // 'borderColor' => 'rgba(75, 192, 192, 1)', + // 'backgroundColor' => 'rgba(75, 192, 192, 0.2)', + // 'fill' => false, + // 'tension' => 0.3, + // ], + // ], + // // Correct label sequence from 8 AM to 7 AM + // 'labels' => array_map(fn ($hour) => date("g A", strtotime("$hour:00")), $shiftedKeys), + // ]; + + // } + protected function getData(): array +{ + $activeFilter = $this->filter; + $selectedPlant = session('selected_plant'); + $selectedLine = session('selected_line'); + + if ($activeFilter === 'yesterday') { + $startDate = now()->subDay()->startOfDay(); + $endDate = now()->subDay()->endOfDay(); + $groupBy = 'EXTRACT(HOUR FROM production_quantities.created_at)'; + } + else if ($activeFilter === 'this_week') { + $startDate = now()->startOfWeek(); // Monday 12:00 AM + $endDate = now()->endOfWeek(); // Sunday 11:59 PM + $groupBy = 'EXTRACT(DOW FROM production_quantities.created_at)'; // Group by day of week + } + else if ($activeFilter === 'this_month') { + $startDate = now()->startOfMonth(); + $endDate = now()->endOfMonth(); + + // Group records into weeks + $groupBy = "FLOOR((EXTRACT(DAY FROM production_quantities.created_at) - 1) / 7) + 1"; + } + else + { + $startDate = now()->startOfDay(); + $endDate = now()->endOfDay(); + $groupBy = 'EXTRACT(HOUR FROM production_quantities.created_at)'; + } + + $query = \DB::table('production_quantities') + ->join('plants', 'production_quantities.plant_id', '=', 'plants.id') + ->join('lines', 'production_quantities.line_id', '=', 'lines.id') + ->selectRaw("$groupBy AS time_unit, count(*) AS total_quantity") + ->whereBetween('production_quantities.created_at', [$startDate, $endDate]) ->when($selectedPlant, function ($q) use ($selectedPlant) { return $q->where('plants.id', $selectedPlant); }) ->when($selectedLine, function ($q) use ($selectedLine) { return $q->where('lines.id', $selectedLine); }) - ->groupByRaw('EXTRACT(HOUR FROM production_quantities.created_at)') - ->orderByRaw('EXTRACT(HOUR FROM production_quantities.created_at)') - ->pluck('total_quantity', 'hour') + + ->groupByRaw($groupBy) + ->orderByRaw($groupBy) + ->pluck('total_quantity', 'time_unit') ->toArray(); + if ($activeFilter === 'this_month') { + $weeksCount = ceil($endDate->day / 7); // Calculate total weeks dynamically + $allWeeks = array_fill(1, $weeksCount, 0); // Initialize all weeks with 0 + $data = array_replace($allWeeks, $query); // Fill missing weeks with 0 - // // Ensure all 24 hours are covered, filling missing ones with zero - // $data = array_replace(array_fill(8, 24, 0), $query); + // Generate dynamic week labels + $labels = []; + for ($i = 1; $i <= $weeksCount; $i++) { + $weekStart = $startDate->copy()->addDays(($i - 1) * 7)->format('d M'); + $weekEnd = $startDate->copy()->addDays($i * 7 - 1)->min($endDate)->format('d M'); + $labels[] = "Week $i ($weekStart - $weekEnd)"; + } - // return [ - // 'datasets' => [ - // [ - // 'label' => 'Hourly Production', - // 'data' => array_values($data), - // 'borderColor' => 'rgba(75, 192, 192, 1)', - // 'backgroundColor' => 'rgba(75, 192, 192, 0.2)', - // 'fill' => false, - // 'tension' => 0.3, - // ], - // ], - // // 'labels' => array_map(fn ($hour) => ($hour == 0 ? '12 AM' : ($hour == 12 ? '12 PM' : ($hour < 12 ? "{$hour} AM" : ($hour - 12) . " PM"))), array_keys($data)), - // // Labels in 24-hour format - // 'labels' => array_map(fn ($hour) => date("g A", strtotime("$hour:00")), array_keys($data)), // Improved hour formatting - // ]; + $orderedData = array_values($data); + } + else if ($activeFilter === 'this_week') { + // Correct week labels: ['Mon', 'Tue', ..., 'Sun'] + $labels = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']; - $allHours = array_fill(0, 24, 0); - $data = array_replace($allHours, $query); + // Initialize default data for all 7 days + $data = array_fill(0, 7, 0); - $shiftedKeys = range(8, 23); // 8 AM to 11 PM - $shiftedKeys = array_merge($shiftedKeys, range(0, 8)); + // Fill in data from query results + foreach ($query as $dow => $count) { + $data[$dow] = $count; + } - $orderedData = array_map(fn($hour) => $data[$hour], $shiftedKeys); + // Ensure days are ordered from Monday to Sunday + $orderedData = [ + $data[1] ?? 0, // Monday + $data[2] ?? 0, // Tuesday + $data[3] ?? 0, // Wednesday + $data[4] ?? 0, // Thursday + $data[5] ?? 0, // Friday + $data[6] ?? 0, // Saturday + $data[0] ?? 0, // Sunday (move to last) + ]; + + } else { + // Hourly data (same as before) + $allHours = array_fill(0, 24, 0); + $data = array_replace($allHours, $query); + + // Shift hours for proper display (8 AM to 7 AM) + $shiftedKeys = array_merge(range(8, 23), range(0, 8)); + $orderedData = array_map(fn($hour) => $data[$hour], $shiftedKeys); + + // Labels: ["8 AM", "9 AM", ..., "7 AM"] + $labels = array_map(fn ($hour) => date("g A", strtotime("$hour:00")), $shiftedKeys); + } return [ 'datasets' => [ [ - 'label' => 'Hourly Production', - 'data' => array_values($orderedData), + 'label' => match ($activeFilter) { + 'this_week' => "Daily Production This Week", + 'this_month' => "Weekly Production This Month", // Updated Label + 'yesterday' => "Yesterday's Hourly Production", + default => "Today's Hourly Production", + }, + 'data' => $orderedData, 'borderColor' => 'rgba(75, 192, 192, 1)', 'backgroundColor' => 'rgba(75, 192, 192, 0.2)', 'fill' => false, 'tension' => 0.3, ], ], - // Correct label sequence from 8 AM to 7 AM - 'labels' => array_map(fn ($hour) => date("g A", strtotime("$hour:00")), $shiftedKeys), + 'labels' => $labels, ]; - - } +} protected function getType(): string { @@ -102,6 +199,9 @@ class ItemOverview extends ChartWidget { return [ 'today' => 'Today', + 'yesterday' => 'Yesterday', + 'this_week'=> 'This Week', + 'this_month'=> 'This Month', ]; } diff --git a/app/Models/ProductionQuantity.php b/app/Models/ProductionQuantity.php index 954220f..da87d57 100644 --- a/app/Models/ProductionQuantity.php +++ b/app/Models/ProductionQuantity.php @@ -37,4 +37,23 @@ class ProductionQuantity extends Model { return $this->belongsTo(Item::class); } + + protected static function booted() + { + static::created(function ($productionQuantity) { + $productionPlan = ProductionPlan::where('plant_id', $productionQuantity->plant_id) + ->where('shift_id', $productionQuantity->shift_id) + ->where('line_id', $productionQuantity->line_id) + ->whereDate('created_at',today()) + // ->where('plan_quantity', $productionQuantity->plan_quantity) + ->first(); + + if ($productionPlan) { + $productionPlan->update([ + 'production_quantity' => $productionPlan->production_quantity + 1, + 'updated_at' => now(), + ]); + } + }); + } }