From e46f290fd11f83aaabbda799237fb1b01a788d07 Mon Sep 17 00:00:00 2001 From: dhanabalan Date: Fri, 28 Mar 2025 16:52:40 +0530 Subject: [PATCH] Import Fun Completed and Sticker Master --- app/Filament/Imports/BlockImporter.php | 2 +- app/Filament/Imports/ItemImporter.php | 12 - app/Filament/Imports/LineImporter.php | 12 - app/Filament/Imports/LineStopImporter.php | 18 -- .../Imports/ProductionLineStopImporter.php | 14 +- .../Imports/ProductionPlanImporter.php | 10 + .../Imports/ProductionQuantityImporter.php | 6 - app/Filament/Imports/ShiftImporter.php | 2 +- app/Filament/Pages/Dashboard.php | 63 ++-- .../Pages/SubmitNameLabel.php | 12 + app/Filament/Resources/BlockResource.php | 5 +- app/Filament/Resources/CompanyResource.php | 2 +- app/Filament/Resources/ItemResource.php | 40 +-- app/Filament/Resources/LineResource.php | 17 +- app/Filament/Resources/LineStopResource.php | 15 - .../Resources/ProductionLineStopResource.php | 157 ++++++++-- .../Resources/ProductionPlanResource.php | 63 +++- .../Resources/ProductionQuantityResource.php | 134 ++++++-- .../Resources/QualityValidationResource.php | 126 ++++++++ .../Pages/CreateQualityValidation.php | 12 + .../Pages/EditQualityValidation.php | 22 ++ .../Pages/ListQualityValidations.php | 19 ++ .../Pages/ViewQualityValidation.php | 19 ++ app/Filament/Resources/ShiftResource.php | 79 ++++- .../Resources/StickerMasterResource.php | 291 ++++++++++++++++++ .../Pages/CreateStickerMaster.php | 12 + .../Pages/EditStickerMaster.php | 22 ++ .../Pages/ListStickerMasters.php | 19 ++ .../Pages/ViewStickerMaster.php | 19 ++ app/Filament/Widgets/ItemOverview.php | 96 +++--- app/Models/Item.php | 12 - app/Models/Line.php | 18 -- app/Models/LineStop.php | 19 -- app/Models/Plant.php | 5 + app/Models/ProductionLineStop.php | 8 +- app/Models/ProductionQuantity.php | 6 - app/Models/QualityValidation.php | 51 +++ app/Models/StickerMaster.php | 46 +++ app/Providers/AppServiceProvider.php | 4 + app/Providers/Filament/AdminPanelProvider.php | 1 + .../2025_03_21_090347_create_lines_table.php | 6 +- .../2025_03_21_090348_create_items_table.php | 6 +- ...5_03_22_184847_create_line_stops_table.php | 13 +- ...259_create_production_line_stops_table.php | 6 +- ...155_create_production_quantities_table.php | 2 - ...28_092047_create_sticker_masters_table.php | 62 ++++ ...62455_create_quality_validations_table.php | 67 ++++ 47 files changed, 1317 insertions(+), 335 deletions(-) create mode 100644 app/Filament/Resources/AppFilamentResourcesStickerMasterResource/Pages/SubmitNameLabel.php create mode 100644 app/Filament/Resources/QualityValidationResource.php create mode 100644 app/Filament/Resources/QualityValidationResource/Pages/CreateQualityValidation.php create mode 100644 app/Filament/Resources/QualityValidationResource/Pages/EditQualityValidation.php create mode 100644 app/Filament/Resources/QualityValidationResource/Pages/ListQualityValidations.php create mode 100644 app/Filament/Resources/QualityValidationResource/Pages/ViewQualityValidation.php create mode 100644 app/Filament/Resources/StickerMasterResource.php create mode 100644 app/Filament/Resources/StickerMasterResource/Pages/CreateStickerMaster.php create mode 100644 app/Filament/Resources/StickerMasterResource/Pages/EditStickerMaster.php create mode 100644 app/Filament/Resources/StickerMasterResource/Pages/ListStickerMasters.php create mode 100644 app/Filament/Resources/StickerMasterResource/Pages/ViewStickerMaster.php create mode 100644 app/Models/QualityValidation.php create mode 100644 app/Models/StickerMaster.php create mode 100644 database/migrations/2025_03_28_092047_create_sticker_masters_table.php create mode 100644 database/migrations/2025_03_28_162455_create_quality_validations_table.php diff --git a/app/Filament/Imports/BlockImporter.php b/app/Filament/Imports/BlockImporter.php index 7236a5d4c..17df22bad 100644 --- a/app/Filament/Imports/BlockImporter.php +++ b/app/Filament/Imports/BlockImporter.php @@ -23,7 +23,7 @@ class BlockImporter extends Importer ->requiredMapping() ->exampleHeader('Plant Name') ->label('Plant Name') - ->relationship(resolveUsing:'name') + ->relationship(resolveUsing:'Name') ->rules(['required']), ]; } diff --git a/app/Filament/Imports/ItemImporter.php b/app/Filament/Imports/ItemImporter.php index ebee437cd..d8263b28a 100644 --- a/app/Filament/Imports/ItemImporter.php +++ b/app/Filament/Imports/ItemImporter.php @@ -30,18 +30,6 @@ class ItemImporter extends Importer ->label('Hourly Quantity') ->numeric() ->rules(['required', 'integer']), - ImportColumn::make('line') - ->requiredMapping() - ->exampleHeader('Line Name') - ->label('Line Name') - ->relationship(resolveUsing:'name') - ->rules(['required']), - ImportColumn::make('block') - ->requiredMapping() - ->exampleHeader('Block Name') - ->label('Block Name') - ->relationship(resolveUsing:'name') - ->rules(['required']), ImportColumn::make('plant') ->requiredMapping() ->exampleHeader('Plant Name') diff --git a/app/Filament/Imports/LineImporter.php b/app/Filament/Imports/LineImporter.php index 8174485d5..a98824145 100644 --- a/app/Filament/Imports/LineImporter.php +++ b/app/Filament/Imports/LineImporter.php @@ -24,18 +24,6 @@ class LineImporter extends Importer ->exampleHeader('Line Type') ->label('Line Type') ->rules(['required']), - ImportColumn::make('shift') - ->requiredMapping() - ->exampleHeader('Shift Name') - ->label('Shift Name') - ->relationship(resolveUsing:'name') - ->rules(['required']), - ImportColumn::make('block') - ->requiredMapping() - ->exampleHeader('Block Name') - ->label('Block Name') - ->relationship(resolveUsing:'name') - ->rules(['required']), ImportColumn::make('plant') ->requiredMapping() ->exampleHeader('Plant Name') diff --git a/app/Filament/Imports/LineStopImporter.php b/app/Filament/Imports/LineStopImporter.php index c531ff233..75e41b348 100644 --- a/app/Filament/Imports/LineStopImporter.php +++ b/app/Filament/Imports/LineStopImporter.php @@ -24,24 +24,6 @@ class LineStopImporter extends Importer ->exampleHeader('Line Stop Reason') ->label('Line Stop Reason') ->rules(['required']), - ImportColumn::make('shift') - ->requiredMapping() - ->exampleHeader('Shift Name') - ->label('Shift Name') - ->relationship(resolveUsing:'name') - ->rules(['required']), - ImportColumn::make('block') - ->requiredMapping() - ->exampleHeader('Block Name') - ->label('Block Name') - ->relationship(resolveUsing:'name') - ->rules(['required']), - ImportColumn::make('plant') - ->requiredMapping() - ->exampleHeader('Plant Name') - ->label('Plant Name') - ->relationship(resolveUsing:'name') - ->rules(['required']), ]; } diff --git a/app/Filament/Imports/ProductionLineStopImporter.php b/app/Filament/Imports/ProductionLineStopImporter.php index 18fb04601..edfb0da7c 100644 --- a/app/Filament/Imports/ProductionLineStopImporter.php +++ b/app/Filament/Imports/ProductionLineStopImporter.php @@ -16,16 +16,24 @@ class ProductionLineStopImporter extends Importer return [ ImportColumn::make('from_datetime') ->requiredMapping() + ->exampleHeader('From DateTime') + ->label('From DateTime') ->rules(['required', 'datetime']), ImportColumn::make('to_datetime') ->requiredMapping() + ->exampleHeader('To DateTime') + ->label('To DateTime') ->rules(['required', 'datetime']), ImportColumn::make('stop_hour') ->requiredMapping() + ->exampleHeader('Stop Hour') + ->label('Stop Hour') ->numeric() ->rules(['required', 'integer']), ImportColumn::make('stop_min') ->requiredMapping() + ->exampleHeader('Stop Min') + ->label('Stop Min') ->numeric() ->rules(['required', 'integer']), ImportColumn::make('linestop') @@ -46,12 +54,6 @@ class ProductionLineStopImporter extends Importer ->label('Shift Name') ->relationship(resolveUsing:'name') ->rules(['required']), - ImportColumn::make('block') - ->requiredMapping() - ->exampleHeader('Block Name') - ->label('Block Name') - ->relationship(resolveUsing:'name') - ->rules(['required']), ImportColumn::make('plant') ->requiredMapping() ->exampleHeader('Plant Name') diff --git a/app/Filament/Imports/ProductionPlanImporter.php b/app/Filament/Imports/ProductionPlanImporter.php index ef2f36b5c..81f22feb5 100644 --- a/app/Filament/Imports/ProductionPlanImporter.php +++ b/app/Filament/Imports/ProductionPlanImporter.php @@ -14,6 +14,11 @@ class ProductionPlanImporter extends Importer public static function getColumns(): array { return [ + ImportColumn::make('created_at') + ->requiredMapping() + ->exampleHeader('Created DateTime') + ->label('Created DateTime') + ->rules(['required']), ImportColumn::make('plan_quantity') ->requiredMapping() ->exampleHeader('Plan Quantity') @@ -44,6 +49,11 @@ class ProductionPlanImporter extends Importer ->label('Plant Name') ->relationship(resolveUsing:'name') ->rules(['required']), + ImportColumn::make('updated_at') + ->requiredMapping() + ->exampleHeader('Updated DateTime') + ->label('Updated DateTime') + ->rules(['required']), ]; } diff --git a/app/Filament/Imports/ProductionQuantityImporter.php b/app/Filament/Imports/ProductionQuantityImporter.php index 118fc021e..928cf1468 100644 --- a/app/Filament/Imports/ProductionQuantityImporter.php +++ b/app/Filament/Imports/ProductionQuantityImporter.php @@ -48,12 +48,6 @@ class ProductionQuantityImporter extends Importer ->label('Shift Name') ->relationship(resolveUsing:'name') ->rules(['required']), - ImportColumn::make('block') - ->requiredMapping() - ->exampleHeader('Block Name') - ->label('Block Name') - ->relationship(resolveUsing:'name') - ->rules(['required']), ImportColumn::make('plant') ->requiredMapping() ->exampleHeader('Plant Name') diff --git a/app/Filament/Imports/ShiftImporter.php b/app/Filament/Imports/ShiftImporter.php index 47346bd38..a4bf6d764 100644 --- a/app/Filament/Imports/ShiftImporter.php +++ b/app/Filament/Imports/ShiftImporter.php @@ -41,7 +41,7 @@ class ShiftImporter extends Importer ->numeric() ->exampleHeader('Shift Duration') ->label('Shift Duration') - ->rules(['required', 'integer']), + ->rules(['required']), ImportColumn::make('end_time') ->requiredMapping() ->exampleHeader('End Time') diff --git a/app/Filament/Pages/Dashboard.php b/app/Filament/Pages/Dashboard.php index 8f9e5e382..1de959ce3 100644 --- a/app/Filament/Pages/Dashboard.php +++ b/app/Filament/Pages/Dashboard.php @@ -1,33 +1,50 @@ schema([ - // Select::make('plant_id') - // ->relationship('plant', 'name') - // ->required() - // ->reactive(), + public function filtersForm(Form $form): Form + { + $selectedPlant = session('selected_plant', request()->input('filters.Plant')); + return $form->schema([ + // Plant Filter + Select::make('Plant') + ->options(Plant::pluck('name', 'id')) // Fetch plant names with their IDs + ->label('Select Plant') + ->reactive() + ->afterStateUpdated(function ($state, callable $set) use ($selectedPlant) { + // Update only in memory and not in the URL + session(['selected_plant' => $state]); // Store in session + session()->forget('selected_line'); // Reset line filter + $set('Plant', $state); + $set('Line', null); + $this->dispatch('filtersUpdated'); // Notify chart to refresh + }), + + // Line Filter + Select::make('Line') + ->options(function ($get) { + $plantId = $get('Plant'); + return $plantId ? Plant::find($plantId)->getLineNames()->pluck('name', 'id') : []; + }) + ->label('Select Line') + ->reactive() + ->afterStateUpdated(function ($state) { + session(['selected_line' => $state]); // Store in session + $this->dispatch('filtersUpdated'); // Notify chart to refresh + }), + ]); + } - // Select::make('line_id') - // ->relationship('line', 'name') - // ->required() - // ->options(fn (callable $get) => - // Line::where('plant_id', $get('plant_id'))->pluck('name', 'id') - // ) - // ->reactive() - // ->afterStateUpdated(fn ($set) => $set('line_id', null)), - ]); - } } diff --git a/app/Filament/Resources/AppFilamentResourcesStickerMasterResource/Pages/SubmitNameLabel.php b/app/Filament/Resources/AppFilamentResourcesStickerMasterResource/Pages/SubmitNameLabel.php new file mode 100644 index 000000000..730dba076 --- /dev/null +++ b/app/Filament/Resources/AppFilamentResourcesStickerMasterResource/Pages/SubmitNameLabel.php @@ -0,0 +1,12 @@ +schema([ Forms\Components\TextInput::make('name') - ->required() - ->unique(ignoreRecord: true), + ->required(), + // ->unique(ignoreRecord: true), // ->columnSpanFull(), Forms\Components\Select::make('plant_id') ->relationship('plant', 'name') + // ->unique(ignoreRecord: true) ->required(), ]); } diff --git a/app/Filament/Resources/CompanyResource.php b/app/Filament/Resources/CompanyResource.php index d90577fb6..131b7d84e 100644 --- a/app/Filament/Resources/CompanyResource.php +++ b/app/Filament/Resources/CompanyResource.php @@ -31,7 +31,7 @@ class CompanyResource extends Resource Forms\Components\TextInput::make('name') ->required() //->citext('name') - ->unique() + ->unique(ignoreRecord: true) ->columnSpanFull(), ]); } diff --git a/app/Filament/Resources/ItemResource.php b/app/Filament/Resources/ItemResource.php index 48d3db2ab..02c290e10 100644 --- a/app/Filament/Resources/ItemResource.php +++ b/app/Filament/Resources/ItemResource.php @@ -28,6 +28,10 @@ class ItemResource extends Resource { return $form ->schema([ + Forms\Components\Select::make('plant_id') + ->relationship('plant', 'name') + ->required(), + // ->nullable(), Forms\Components\TextInput::make('code') ->required() ->unique(ignoreRecord: true) @@ -38,38 +42,8 @@ class ItemResource extends Resource ->numeric() ->minValue(1), Forms\Components\Textarea::make('description') - ->required() - ->columnSpanFull(), - Forms\Components\Select::make('plant_id') - ->relationship('plant', 'name') - ->required() - ->reactive() - ->afterStateUpdated(fn ($set) => $set('block_id', null)), // Reset block_id when plant changes - - Forms\Components\Select::make('block_id') - ->relationship('block', 'name') - ->required() - ->options(fn (callable $get) => - \App\Models\Block::where('plant_id', $get('plant_id')) - ->pluck('name', 'id') - ->toArray() // Convert collection to array - ) - ->reactive(), // Ensures the dropdown updates when plant_id changes - // Forms\Components\Select::make('plant_id') - // ->relationship('plant', 'name') - // ->required() - // ->reactive(), - // Forms\Components\Select::make('block_id') - // ->relationship('block', 'name') - // ->required() - // ->options(fn (callable $get) => - // \App\Models\Block::where('plant_id', $get('plant_id'))->pluck('name', 'id') - // ) - // ->reactive() // Updates dynamically when plant_id changes - // ->afterStateUpdated(fn ($set) => $set('block_id', null)), // Reset block_id when plant_id changes - Forms\Components\Select::make('line_id') - ->relationship('line', 'name') ->required(), + // ->columnSpanFull(), ]); } @@ -88,10 +62,6 @@ class ItemResource extends Resource ->sortable(), Tables\Columns\TextColumn::make('description') ->sortable(), - Tables\Columns\TextColumn::make('line.name') - ->sortable(), - Tables\Columns\TextColumn::make('block.name') - ->sortable(), Tables\Columns\TextColumn::make('plant.name') ->sortable(), Tables\Columns\TextColumn::make('created_at') diff --git a/app/Filament/Resources/LineResource.php b/app/Filament/Resources/LineResource.php index 32180e23b..994842784 100644 --- a/app/Filament/Resources/LineResource.php +++ b/app/Filament/Resources/LineResource.php @@ -27,21 +27,16 @@ class LineResource extends Resource { return $form ->schema([ + Forms\Components\Select::make('plant_id') + ->relationship('plant', 'name') + ->required(), + // ->nullable(), Forms\Components\Textarea::make('name') ->required(), // ->columnSpanFull(), Forms\Components\Textarea::make('type') ->required(), //->columnSpanFull(), - Forms\Components\Select::make('plant_id') - ->relationship('plant', 'name') - ->required(), - Forms\Components\Select::make('block_id') - ->relationship('block', 'name') - ->required(), - Forms\Components\Select::make('shift_id') - ->relationship('shift', 'name') - ->required(), ]); } @@ -57,10 +52,6 @@ class LineResource extends Resource ->sortable(), Tables\Columns\TextColumn::make('type') ->sortable(), - Tables\Columns\TextColumn::make('shift.name') - ->sortable(), - Tables\Columns\TextColumn::make('block.name') - ->sortable(), Tables\Columns\TextColumn::make('plant.name') ->sortable(), Tables\Columns\TextColumn::make('created_at') diff --git a/app/Filament/Resources/LineStopResource.php b/app/Filament/Resources/LineStopResource.php index 2f50931db..c40563910 100644 --- a/app/Filament/Resources/LineStopResource.php +++ b/app/Filament/Resources/LineStopResource.php @@ -33,15 +33,6 @@ class LineStopResource extends Resource Forms\Components\Textarea::make('reason') ->required(), //->columnSpanFull(), - Forms\Components\Select::make('plant_id') - ->relationship('plant', 'name') - ->required(), - Forms\Components\Select::make('block_id') - ->relationship('block', 'name') - ->required(), - Forms\Components\Select::make('shift_id') - ->relationship('shift', 'name') - ->required(), ]); } @@ -57,12 +48,6 @@ class LineStopResource extends Resource ->sortable(), Tables\Columns\TextColumn::make('reason') ->sortable(), - Tables\Columns\TextColumn::make('shift.name') - ->sortable(), - Tables\Columns\TextColumn::make('block.name') - ->sortable(), - Tables\Columns\TextColumn::make('plant.name') - ->sortable(), Tables\Columns\TextColumn::make('created_at') ->dateTime() ->sortable() diff --git a/app/Filament/Resources/ProductionLineStopResource.php b/app/Filament/Resources/ProductionLineStopResource.php index 46f112a61..e5aa71931 100644 --- a/app/Filament/Resources/ProductionLineStopResource.php +++ b/app/Filament/Resources/ProductionLineStopResource.php @@ -14,6 +14,8 @@ use Filament\Tables\Actions\ImportAction; use Filament\Tables\Table; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\SoftDeletingScope; +use Carbon\Carbon; + class ProductionLineStopResource extends Resource { @@ -21,43 +23,154 @@ class ProductionLineStopResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack'; - protected static ?string $navigationGroup = 'Master Entries'; + // protected static ?string $navigationParentItem = 'Display Transactions'; + + protected static ?string $navigationGroup = 'Production'; public static function form(Form $form): Form { + return $form ->schema([ - Forms\Components\Select::make('lineStop_id') - ->relationship('linestop', 'code') - ->required(), - Forms\Components\Select::make('lineStop_id') - ->relationship('linestop', 'reason') - ->required(), + Forms\Components\Select::make('plant_id') + ->relationship('plant', 'name') + ->required() + ->nullable() + ->reactive(), + Forms\Components\Select::make('block_name') + ->required() + ->nullable() + ->reactive() + ->afterStateUpdated(fn ($set) => $set('shift_id', null)), + Forms\Components\Select::make('shift_id') + ->relationship('shift', 'name') + ->required() + ->nullable() + // ->options(fn (callable $get) => + // \App\Models\Shift::where('plant_id', $get('plant_id')) + // ->pluck('name', 'id') + // ->toArray() // Convert collection to array + // ) + ->options(function (callable $get) { + if (!$get('plant_id')) { + return []; + } + + return \App\Models\Shift::where('plant_id', $get('plant_id')) + ->pluck('name', 'id') + ->toArray(); + }) + ->reactive() + ->afterStateUpdated(fn ($set) => $set('line_id', null)), + Forms\Components\Select::make('line_id') + ->relationship('line', 'name') + ->required() + ->nullable() + // ->options(fn (callable $get) => + // \App\Models\Line::where('plant_id', $get('plant_id')) + // ->pluck('name', 'id') + // ->toArray() // Convert collection to array + // ) + ->options(function (callable $get) { + if (!$get('plant_id')) { + return []; + } + + return \App\Models\Line::where('plant_id', $get('plant_id')) + ->pluck('name', 'id') + ->toArray(); + }) + ->reactive(), + // Forms\Components\Select::make('linestop_id') + // ->label('Line Stop Code') + // ->relationship('linestop', 'code') + // ->searchable() + // ->required() + // ->nullable() + // ->reactive(), + Forms\Components\Select::make('linestop_id') + ->label('Line Stop Code') + // ->options(fn (callable $get) => + // \App\Models\LineStop::where('id', $get('linestop_id')) + // ->pluck('code', 'id') + // ) + ->options(fn () => \App\Models\LineStop::pluck('code', 'id')) + ->required() + ->nullable() + // ->reactive() + ->searchable() + ->live(debounce: 500) // Enable live updates + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $lineStopId = $get('linestop_id'); // Get entered linestop_id + + // Ensure `linestop_id` is not cleared + if (!$lineStopId) { + $set('lineStop_reason', null); + return; + } + + // Check if item exists for the selected plant + $lineStop = \App\Models\LineStop::where('id', $lineStopId) + ->where('id', $lineStopId) + ->first(); + + $set('lineStop_reason', $lineStop?->reason ?? null); + + }), + Forms\Components\TextInput::make('lineStop_reason') + ->label('Line Stop Reason') + ->required() + ->reactive() + ->readOnly(true), Forms\Components\DateTimePicker::make('from_datetime') - ->required(), + ->label('From DateTime') + ->required() + ->reactive() + ->afterStateUpdated(fn ($state, callable $set, callable $get) => + self::updateStopDuration($get, $set) + ), Forms\Components\DateTimePicker::make('to_datetime') - ->required(), + ->label('To DateTime') + ->required() + ->reactive() + ->afterStateUpdated(fn ($state, callable $set, callable $get) => + self::updateStopDuration($get, $set) //self means it calling the function within the class + ), Forms\Components\TextInput::make('stop_hour') ->required() + // ->dehydrated(false) // Don't send to backend + ->readOnly(true) ->numeric(), Forms\Components\TextInput::make('stop_min') ->required() + // ->dehydrated(false) + ->readOnly(true) ->numeric(), - Forms\Components\Select::make('plant_id') - ->relationship('plant', 'name') - ->required(), - Forms\Components\Select::make('block_id') - ->relationship('block', 'name') - ->required(), - Forms\Components\Select::make('shift_id') - ->relationship('shift', 'name') - ->required(), - Forms\Components\Select::make('line_id') - ->relationship('line', 'name') - ->required(), ]); } + public static function updateStopDuration(callable $get, callable $set) + { + $from = $get('from_datetime'); + $to = $get('to_datetime'); + + // Carbon is a PHP date and time library. + + if ($from && $to) { + $fromTime = Carbon::parse($from); //Carbon::parse($from) converts the from datetime string into a Carbon objec + $toTime = Carbon::parse($to); + + if ($fromTime->lt($toTime)) { + $diffInMinutes = $fromTime->diffInMinutes($toTime); + $set('stop_hour', floor($diffInMinutes / 60)); + $set('stop_min', $diffInMinutes % 60); + } else { + $set('stop_hour', 0); + $set('stop_min', 0); + } + } + } + public static function table(Table $table): Table { return $table @@ -86,8 +199,6 @@ class ProductionLineStopResource extends Resource ->sortable(), Tables\Columns\TextColumn::make('shift.name') ->sortable(), - Tables\Columns\TextColumn::make('block.name') - ->sortable(), Tables\Columns\TextColumn::make('plant.name') ->sortable(), Tables\Columns\TextColumn::make('created_at') diff --git a/app/Filament/Resources/ProductionPlanResource.php b/app/Filament/Resources/ProductionPlanResource.php index e15972868..893f4e129 100644 --- a/app/Filament/Resources/ProductionPlanResource.php +++ b/app/Filament/Resources/ProductionPlanResource.php @@ -21,12 +21,63 @@ class ProductionPlanResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack'; - protected static ?string $navigationGroup = 'Master Entries'; + // protected static ?string $navigationParentItem = 'Production Line Stops'; + + protected static ?string $navigationGroup = 'Production'; public static function form(Form $form): Form { return $form ->schema([ + Forms\Components\Select::make('plant_id') + ->relationship('plant', 'name') + ->required() + ->nullable() + ->reactive(), + Forms\Components\Select::make('block_name') + ->required() + ->nullable() + ->reactive() + ->afterStateUpdated(fn ($set) => $set('shift_id', null)), + Forms\Components\Select::make('shift_id') + ->relationship('shift', 'name') + ->required() + ->nullable() + // ->options(fn (callable $get) => + // \App\Models\Shift::where('plant_id', $get('plant_id')) + // ->pluck('name', 'id') + // ->toArray() // Convert collection to array + // ) + ->options(function (callable $get) { + if (!$get('plant_id')) { + return []; + } + + return \App\Models\Shift::where('plant_id', $get('plant_id')) + ->pluck('name', 'id') + ->toArray(); + }) + ->reactive() + ->afterStateUpdated(fn ($set) => $set('line_id', null)), + Forms\Components\Select::make('line_id') + ->relationship('line', 'name') + ->required() + ->nullable() + // ->options(fn (callable $get) => + // \App\Models\Line::where('plant_id', $get('plant_id')) + // ->pluck('name', 'id') + // ->toArray() // Convert collection to array + // ) + ->options(function (callable $get) { + if (!$get('plant_id')) { + return []; + } + + return \App\Models\Line::where('plant_id', $get('plant_id')) + ->pluck('name', 'id') + ->toArray(); + }) + ->reactive(), Forms\Components\TextInput::make('plan_quantity') ->required() ->numeric() @@ -36,15 +87,7 @@ class ProductionPlanResource extends Resource ->numeric() ->readOnly() ->default(0), - Forms\Components\Select::make('plant_id') - ->relationship('plant', 'name') - ->required(), - Forms\Components\Select::make('shift_id') - ->relationship('shift', 'name') - ->required(), - Forms\Components\Select::make('line_id') - ->relationship('line', 'name') - ->required(), + ]); } diff --git a/app/Filament/Resources/ProductionQuantityResource.php b/app/Filament/Resources/ProductionQuantityResource.php index 09ed47919..7c077b6d7 100644 --- a/app/Filament/Resources/ProductionQuantityResource.php +++ b/app/Filament/Resources/ProductionQuantityResource.php @@ -21,35 +21,121 @@ class ProductionQuantityResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack'; - protected static ?string $navigationGroup = 'Master Entries'; + // protected static ?string $navigationParentItem = 'Display Transactions'; + + protected static ?string $navigationGroup = 'Production'; public static function form(Form $form): Form { return $form ->schema([ - Forms\Components\Select::make('item_id') - ->relationship('item', 'code') + Forms\Components\Select::make('plant_id') + ->relationship('plant', 'name') + ->required() + ->nullable() + ->reactive(), + Forms\Components\Select::make('block_name') + ->required() + ->nullable() + ->reactive() + ->afterStateUpdated(fn ($set) => $set('shift_id', null)), + Forms\Components\Select::make('shift_id') + ->relationship('shift', 'name') + ->required() + ->nullable() + // ->options(fn (callable $get) => + // \App\Models\Shift::where('plant_id', $get('plant_id')) + // ->pluck('name', 'id') + // ->toArray() // Convert collection to array + // ) + ->options(function (callable $get) { + if (!$get('plant_id')) { + return []; + } + + return \App\Models\Shift::where('plant_id', $get('plant_id')) + ->pluck('name', 'id') + ->toArray(); + }) + ->reactive() + ->afterStateUpdated(fn ($set) => $set('line_id', null)), + Forms\Components\Select::make('line_id') + ->relationship('line', 'name') + ->required() + ->nullable() + // ->options(fn (callable $get) => + // \App\Models\Line::where('plant_id', $get('plant_id')) + // ->pluck('name', 'id') + // ->toArray() // Convert collection to array + // ) + ->options(function (callable $get) { + if (!$get('plant_id')) { + return []; + } + + return \App\Models\Line::where('plant_id', $get('plant_id')) + ->pluck('name', 'id') + ->toArray(); + }) + ->reactive(), + // Forms\Components\Select::make('item_id') + // ->label('Item Code') + // ->relationship('item', 'code') + // ->required(), + // // Forms\Components\TextInput::make('item_code') + // // ->required() + // // ->autocapitalize('item_code'), + // // //->columnSpanFull(), + // Virtual field for code input (not stored in DB) + Forms\Components\TextInput::make('item_code') + ->label('Item Code') + ->required() + ->reactive() + ->afterStateUpdated(function ($state, callable $get, callable $set) { + // Only search when all parent IDs are selected + if ($get('plant_id') && $get('line_id')) { + $item = \App\Models\Item::where('code', $state) + ->where('plant_id', $get('plant_id')) + ->where('line_id', $get('line_id')) + ->first(); + + if ($item) { + $set('item_id', $item->id); // Set actual foreign key + } else { + $set('item_id', null); // Clear item_id if not found + } + } + }) + ->rules([ + function ($get) { + return function ($attribute, $value, $fail) use ($get) { + // Check if item exists with the given code and foreign keys + $exists = \App\Models\Item::where('code', $value) + ->where('plant_id', $get('plant_id')) + ->where('line_id', $get('line_id')) + ->exists(); + + if (!$exists) { + // Custom error message + $fail("The item code '{$value}' does not exist for the selected Plant/Block/Line."); + } + }; + }, + ]), + + Forms\Components\Hidden::make('item_id') ->required(), - // Forms\Components\TextInput::make('item_code') - // ->required() - // ->autocapitalize('item_code'), - // //->columnSpanFull(), + Forms\Components\TextInput::make('item_description') + ->label('Description') + ->required(), + // Forms\Components\Select::make('item_id') + // ->label('Description') + // ->relationship('item', 'description') + // ->required(), Forms\Components\TextInput::make('serial_number') ->required() ->autocapitalize('serial_number'), //->columnSpanFull(), - Forms\Components\Select::make('plant_id') - ->relationship('plant', 'name') - ->required(), - Forms\Components\Select::make('block_id') - ->relationship('block', 'name') - ->required(), - Forms\Components\Select::make('shift_id') - ->relationship('shift', 'name') - ->required(), - Forms\Components\Select::make('line_id') - ->relationship('line', 'name') - ->required(), ]); } @@ -61,13 +147,7 @@ class ProductionQuantityResource extends Resource ->label('ID') ->numeric() ->sortable(), - Tables\Columns\TextColumn::make('plan_quantity') - ->numeric() - ->sortable(), - Tables\Columns\TextColumn::make('hourly_quantity') - ->numeric() - ->sortable(), - Tables\Columns\TextColumn::make('item_code') + Tables\Columns\TextColumn::make('item.code') ->sortable(), Tables\Columns\TextColumn::make('serial_number') ->sortable(), @@ -75,8 +155,6 @@ class ProductionQuantityResource extends Resource ->sortable(), Tables\Columns\TextColumn::make('shift.name') ->sortable(), - Tables\Columns\TextColumn::make('block.name') - ->sortable(), Tables\Columns\TextColumn::make('plant.name') ->sortable(), Tables\Columns\TextColumn::make('created_at') diff --git a/app/Filament/Resources/QualityValidationResource.php b/app/Filament/Resources/QualityValidationResource.php new file mode 100644 index 000000000..f766b377c --- /dev/null +++ b/app/Filament/Resources/QualityValidationResource.php @@ -0,0 +1,126 @@ +schema([ + Forms\Components\Select::make('plant_id') + ->relationship('plant', 'name') + ->required(), + Forms\Components\Select::make('item_id') + ->relationship('item', 'code') + ->searchable() + ->required(), + Forms\Components\Select::make('stickermaster_id') + ->relationship('stickermaster', 'id') + ->required(), + Forms\Components\TextInput::make('scan_qr') + ->label('Scan QR Code') + ->required(), + Forms\Components\TextInput::make('production_order') + ->required(), + Forms\Components\TextInput::make('part_validation1'), + + Forms\Components\TextInput::make('part_validation2'), + + Forms\Components\TextInput::make('part_validation3'), + + Forms\Components\TextInput::make('part_validation4'), + + Forms\Components\TextInput::make('part_validation5'), + + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('id') + ->label('ID') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('item.id') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('plant.name') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('stickermaster.id') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('created_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('updated_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('deleted_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + ]) + ->filters([ + Tables\Filters\TrashedFilter::make(), + ]) + ->actions([ + Tables\Actions\ViewAction::make(), + Tables\Actions\EditAction::make(), + ]) + ->bulkActions([ + Tables\Actions\BulkActionGroup::make([ + Tables\Actions\DeleteBulkAction::make(), + Tables\Actions\ForceDeleteBulkAction::make(), + Tables\Actions\RestoreBulkAction::make(), + ]), + ]); + } + + public static function getRelations(): array + { + return [ + // + ]; + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListQualityValidations::route('/'), + 'create' => Pages\CreateQualityValidation::route('/create'), + 'view' => Pages\ViewQualityValidation::route('/{record}'), + 'edit' => Pages\EditQualityValidation::route('/{record}/edit'), + ]; + } + + public static function getEloquentQuery(): Builder + { + return parent::getEloquentQuery() + ->withoutGlobalScopes([ + SoftDeletingScope::class, + ]); + } +} diff --git a/app/Filament/Resources/QualityValidationResource/Pages/CreateQualityValidation.php b/app/Filament/Resources/QualityValidationResource/Pages/CreateQualityValidation.php new file mode 100644 index 000000000..5a6c5914d --- /dev/null +++ b/app/Filament/Resources/QualityValidationResource/Pages/CreateQualityValidation.php @@ -0,0 +1,12 @@ +schema([ Forms\Components\Select::make('plant_id') ->relationship('plant', 'name') - ->required(), + ->required() + ->nullable() + ->reactive() + ->afterStateUpdated(fn ($set) => $set('block_id', null)), // Reset block_id when plant changes Forms\Components\Select::make('block_id') ->relationship('block', 'name') - ->required(), + ->required() + ->nullable() + // ->options(fn (callable $get) => + // \App\Models\Block::where('plant_id', $get('plant_id')) + // ->pluck('name', 'id') + // ->toArray() // Convert collection to array + // ) + ->options(function (callable $get) { + if (!$get('plant_id')) { + return []; + } + + return \App\Models\Block::where('plant_id', $get('plant_id')) + ->pluck('name', 'id') + ->toArray(); + }) + ->reactive(), Forms\Components\TextInput::make('name') ->required(), Forms\Components\TimePicker::make('start_time') - ->required(), - // ->native(false), + ->required() + ->live() + ->afterStateUpdated(fn (callable $set, callable $get, $state) => + $set('end_time', self::calculateEndTime($state, $get('duration'))) + ), + Forms\Components\TextInput::make('duration') ->required() ->inputMode('decimal') - ->minValue(1), + ->minValue(0.01) // Minimum valid duration + ->lazy() + ->afterStateUpdated(fn (callable $set, callable $get, $state) => + $set('end_time', self::calculateEndTime($get('start_time'), $state)) + ), + Forms\Components\TimePicker::make('end_time') ->required(), // ->native(false), ]); + + } public static function table(Table $table): Table @@ -90,6 +123,10 @@ class ShiftResource extends Resource Tables\Actions\ForceDeleteBulkAction::make(), Tables\Actions\RestoreBulkAction::make(), ]), + ]) + ->headerActions([ + ImportAction::make() + ->importer(ShiftImporter::class), ]); } @@ -117,4 +154,36 @@ class ShiftResource extends Resource SoftDeletingScope::class, ]); } + + protected static function calculateEndTime(?string $startTime, ?string $duration): ?string +{ + if (!$startTime || !$duration) { + return null; + } + + try { + // Convert start_time to Carbon instance + $startTimeCarbon = Carbon::createFromFormat('H:i:s', $startTime); + + // Ensure duration is in a valid numeric format + $duration = str_replace(',', '.', $duration); // Handle decimal formats + if (!is_numeric($duration)) { + return null; // Invalid duration format + } + + // Extract hours and minutes correctly + [$hours, $decimalMinutes] = explode('.', $duration) + [0, 0]; // Ensure two parts + $hours = (int) $hours; // Convert to integer hours + $minutes = (int) $decimalMinutes; // Directly use decimal part as minutes + + // Calculate end time + $endTimeCarbon = $startTimeCarbon->addHours($hours)->addMinutes($minutes); + + return $endTimeCarbon->format('H:i:s'); // Return formatted end time + } catch (\Exception $e) { + return null; + } +} + + } diff --git a/app/Filament/Resources/StickerMasterResource.php b/app/Filament/Resources/StickerMasterResource.php new file mode 100644 index 000000000..055ac5dd8 --- /dev/null +++ b/app/Filament/Resources/StickerMasterResource.php @@ -0,0 +1,291 @@ +schema([ + Forms\Components\Select::make('plant_id') + ->relationship('plant', 'name') + ->reactive() + ->afterStateUpdated(fn (callable $set) => $set('item_id', null)) + ->required(), + + Forms\Components\Select::make('item_id') + ->label('Item Code') + ->options(fn (callable $get) => + \App\Models\Item::where('plant_id', $get('plant_id')) + ->pluck('code', 'id') + ) + ->required() + ->searchable() + ->live(debounce: 500) // Enable live updates + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $plantId = $get('plant_id'); // Get selected plant_id + $itemId = $get('item_id'); // Get entered item_id + + // Ensure `item_id` is not cleared + if (!$plantId || !$itemId) { + $set('item_description', null); + return; + } + + // Check if item exists for the selected plant + $item = \App\Models\Item::where('plant_id', $plantId) + ->where('id', $itemId) + ->first(); + + if ($item) { + $set('item_description', $item->description); + } else { + $set('item_description', null); + } + + }), + // ->validationAttribute('Item Code') + // ->rule('required') + // ->extraAttributes(fn ($get) => [ + // 'class' => $get('validationError') ? 'border-red-500' : '', + // ]) + // ->hint(fn ($get) => $get('validationError') ? $get('validationError') : null) + // ->hintColor('danger'), // Show error in red under the input field + + Forms\Components\TextInput::make('item_description') + ->label('Description') + ->required() + ->reactive() + ->readOnly(true), + + //Forms\Components\Textarea::make('serial_number_motor'), + + Forms\Components\TextInput::make('part_validation1') + ->nullable(), + + Forms\Components\TextInput::make('part_validation2') + ->nullable(), + + Forms\Components\TextInput::make('part_validation3') + ->nullable(), + + Forms\Components\TextInput::make('part_validation4') + ->nullable(), + + Forms\Components\TextInput::make('part_validation5') + ->nullable(), + + Forms\Components\Checkbox::make('serial_number_motor') + ->nullable() + ->dehydrateStateUsing(fn ($state) => $state ? $state : null), + + //Forms\Components\Textarea::make('serial_number_pump') + + Forms\Components\Checkbox::make('serial_number_pump') + ->nullable() + ->dehydrateStateUsing(fn ($state) => $state ? $state : null), + + //Forms\Components\TextInput::make('serial_number_pumpset'), + + Forms\Components\Checkbox::make('serial_number_pumpset') + ->nullable() + ->dehydrateStateUsing(fn ($state) => $state ? $state : null), + + //Forms\Components\TextInput::make('pack_slip_motor'), + + Forms\Components\Checkbox::make('pack_slip_motor') + ->nullable() + ->dehydrateStateUsing(fn ($state) => $state ? $state : null), + + //Forms\Components\TextInput::make('pack_slip_pump'), + + Forms\Components\Checkbox::make('pack_slip_pump') + ->nullable() + ->dehydrateStateUsing(fn ($state) => $state ? $state : null), + + //Forms\Components\TextInput::make('pack_slip_pumpset'), + + Forms\Components\Checkbox::make('pack_slip_pumpset') + ->nullable() + ->dehydrateStateUsing(fn ($state) => $state ? $state : null), + + //Forms\Components\TextInput::make('name_plate_motor'), + + Forms\Components\Checkbox::make('name_plate_motor') + ->nullable() + ->dehydrateStateUsing(fn ($state) => $state ? $state : null), + + //Forms\Components\TextInput::make('name_plate_pump'), + + Forms\Components\Checkbox::make('name_plate_pump') + ->nullable() + ->dehydrateStateUsing(fn ($state) => $state ? $state : null), + + //Forms\Components\TextInput::make('name_plate_pumpset'), + + Forms\Components\Checkbox::make('name_plate_pumpset') + ->nullable() + ->dehydrateStateUsing(fn ($state) => $state ? $state : null), + + //Forms\Components\TextInput::make('tube_sticker_motor'), + + Forms\Components\Checkbox::make('tube_sticker_motor') + ->nullable() + ->dehydrateStateUsing(fn ($state) => $state ? $state : null), + + //Forms\Components\TextInput::make('tube_sticker_pump'), + + Forms\Components\Checkbox::make('tube_sticker_pump') + ->nullable() + ->dehydrateStateUsing(fn ($state) => $state ? $state : null), + + //Forms\Components\TextInput::make('tube_sticker_pumpset'), + + Forms\Components\Checkbox::make('tube_sticker_pumpset') + ->nullable() + ->dehydrateStateUsing(fn ($state) => $state ? $state : null), + + //Forms\Components\TextInput::make('warranty_card'), + + Forms\Components\Checkbox::make('warranty_card') + ->nullable() + ->dehydrateStateUsing(fn ($state) => $state ? $state : null), + + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('id') + ->label('ID') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('item.id') + ->numeric() + ->sortable(), + Tables\Columns\TextColumn::make('plant.name') + ->numeric() + ->sortable(), + Tables\Columns\CheckboxColumn::make('serial_number_motor') + ->disabled(true) + ->sortable(), + Tables\Columns\CheckboxColumn::make('serial_number_pump') + ->disabled(true) + ->sortable(), + Tables\Columns\CheckboxColumn::make('serial_number_pumpset') + ->disabled(true) + ->sortable(), + Tables\Columns\CheckboxColumn::make('pack_slip_motor') + ->disabled(true) + ->sortable(), + Tables\Columns\CheckboxColumn::make('pack_slip_pump') + ->disabled(true) + ->sortable(), + Tables\Columns\CheckboxColumn::make('pack_slip_pumpset') + ->disabled(true) + ->sortable(), + Tables\Columns\CheckboxColumn::make('name_plate_motor') + ->disabled(true) + ->sortable(), + Tables\Columns\CheckboxColumn::make('name_plate_pump') + ->disabled(true) + ->sortable(), + Tables\Columns\CheckboxColumn::make('name_plate_pumpset') + ->disabled(true) + ->sortable(), + Tables\Columns\CheckboxColumn::make('tube_sticker_motor') + ->disabled(true) + ->sortable(), + Tables\Columns\CheckboxColumn::make('tube_sticker_pump') + ->disabled(true) + ->sortable(), + Tables\Columns\CheckboxColumn::make('tube_sticker_pumpset') + ->disabled(true) + ->sortable(), + Tables\Columns\CheckboxColumn::make('warranty_card') + ->disabled(true) + ->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() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('updated_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + Tables\Columns\TextColumn::make('deleted_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + ]) + ->filters([ + Tables\Filters\TrashedFilter::make(), + ]) + ->actions([ + Tables\Actions\ViewAction::make(), + Tables\Actions\EditAction::make(), + ]) + ->bulkActions([ + Tables\Actions\BulkActionGroup::make([ + Tables\Actions\DeleteBulkAction::make(), + Tables\Actions\ForceDeleteBulkAction::make(), + Tables\Actions\RestoreBulkAction::make(), + ]), + ]); + } + + public static function getRelations(): array + { + return [ + // + ]; + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListStickerMasters::route('/'), + 'create' => Pages\CreateStickerMaster::route('/create'), + 'view' => Pages\ViewStickerMaster::route('/{record}'), + 'edit' => Pages\EditStickerMaster::route('/{record}/edit'), + ]; + } + + public static function getEloquentQuery(): Builder + { + return parent::getEloquentQuery() + ->withoutGlobalScopes([ + SoftDeletingScope::class, + ]); + } +} diff --git a/app/Filament/Resources/StickerMasterResource/Pages/CreateStickerMaster.php b/app/Filament/Resources/StickerMasterResource/Pages/CreateStickerMaster.php new file mode 100644 index 000000000..00d8b1bd7 --- /dev/null +++ b/app/Filament/Resources/StickerMasterResource/Pages/CreateStickerMaster.php @@ -0,0 +1,12 @@ + '$refresh']; // Listen for filter updates + protected function getData(): array { $activeFilter = $this->filter; - - // Get selected values from the plant and line filter form inputs - $selectedPlant = request()->input('plant'); // Assuming form input name is 'plant' - $selectedLine = request()->input('line'); // Assuming form input name is 'line' + // Get filter values from session + $selectedPlant = session('selected_plant'); + $selectedLine = session('selected_line'); $query = \DB::table('production_quantities') - ->selectRaw('EXTRACT(HOUR FROM created_at) AS hour, COUNT(*) AS total_quantity') - ->whereBetween('created_at', [now()->startOfDay(), now()->endOfDay()]); - - // Apply filters only if values are selected - if (!empty($selectedPlant)) { - $query->where('plant', $selectedPlant); - } - - if (!empty($selectedLine)) { - $query->where('line', $selectedLine); - } - - $query = $query->groupByRaw('EXTRACT(HOUR FROM created_at)') - ->orderByRaw('EXTRACT(HOUR FROM created_at)') + ->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(); - $data = array_fill(8, 12, 0); + // // Ensure all 24 hours are covered, filling missing ones with zero + // $data = array_replace(array_fill(8, 24, 0), $query); - // Populate actual values - // foreach ($query as $record) { - // $hour = (int) $record->hour; - // if ($hour >= 8 && $hour <= 19) { - // $data[$hour] = $record->total_quantity; // Assign only the hourly production - // } - // } + // 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 + // ]; + + $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); - // Convert data to chart format return [ 'datasets' => [ [ 'label' => 'Hourly Production', - 'data' => array_values($data), // Values only + 'data' => array_values($orderedData), 'borderColor' => 'rgba(75, 192, 192, 1)', 'backgroundColor' => 'rgba(75, 192, 192, 0.2)', - 'fill' => false, // No area fill, just the line - 'tension' => 0.3, // Smooth curve + 'fill' => false, + 'tension' => 0.3, ], ], - 'labels' => array_map(fn($h) => ($h <= 11 ? "$h AM" : ($h == 12 ? "12 PM" : ($h - 12) . " PM")), array_keys($data)), + // Correct label sequence from 8 AM to 7 AM + 'labels' => array_map(fn ($hour) => date("g A", strtotime("$hour:00")), $shiftedKeys), ]; } @@ -69,13 +84,24 @@ class ItemOverview extends ChartWidget return 'line'; } + protected function getOptions(): array + { + return [ + 'scales' => [ + 'y' => [ + 'beginAtZero' => true, //Start Y-axis from 0 + 'ticks' => [ + 'stepSize' => 0.5, + ], + ], + ], + ]; + } + protected function getFilters(): ?array { return [ 'today' => 'Today', - 'week' => 'Last week', - 'month' => 'Last month', - 'year' => 'This year', ]; } diff --git a/app/Models/Item.php b/app/Models/Item.php index eb0f485be..be85049d2 100644 --- a/app/Models/Item.php +++ b/app/Models/Item.php @@ -12,8 +12,6 @@ class Item extends Model protected $fillable = [ "plant_id", - "block_id", - "line_id", 'code', 'description', 'hourly_quantity', @@ -23,14 +21,4 @@ class Item extends Model { return $this->belongsTo(Plant::class); } - - public function block(): BelongsTo - { - return $this->belongsTo(Block::class); - } - - public function line(): BelongsTo - { - return $this->belongsTo(Line::class); - } } diff --git a/app/Models/Line.php b/app/Models/Line.php index da234c3be..58c9b16bb 100644 --- a/app/Models/Line.php +++ b/app/Models/Line.php @@ -13,30 +13,12 @@ class Line extends Model protected $fillable = [ "plant_id", - "block_id", - "shift_id", "name", "type", ]; - public function plant(): BelongsTo { return $this->belongsTo(Plant::class); } - - public function block(): BelongsTo - { - return $this->belongsTo(Block::class); - } - - public function shift(): BelongsTo - { - return $this->belongsTo(Shift::class); - } - - public function line_stops(): HasMany - { - return $this->hasMany(LineStop::class); - } } diff --git a/app/Models/LineStop.php b/app/Models/LineStop.php index 41a57931f..807a6e47a 100644 --- a/app/Models/LineStop.php +++ b/app/Models/LineStop.php @@ -11,26 +11,7 @@ class LineStop extends Model use SoftDeletes; protected $fillable = [ - "plant_id", - "block_id", - "shift_id", "code", "reason", ]; - - - public function plant(): BelongsTo - { - return $this->belongsTo(Plant::class); - } - - public function block(): BelongsTo - { - return $this->belongsTo(Block::class); - } - - public function shift(): BelongsTo - { - return $this->belongsTo(Shift::class); - } } diff --git a/app/Models/Plant.php b/app/Models/Plant.php index bbc2515dd..6685a97e4 100644 --- a/app/Models/Plant.php +++ b/app/Models/Plant.php @@ -32,4 +32,9 @@ class Plant extends Model { return $this->hasMany(Line::class); } + + public function getLineNames() + { + return $this->hasMany(Line::class, 'plant_id', 'id'); // Ensure 'plant_id' is the foreign key in 'lines' table + } } diff --git a/app/Models/ProductionLineStop.php b/app/Models/ProductionLineStop.php index f4b01eafd..242fd7809 100644 --- a/app/Models/ProductionLineStop.php +++ b/app/Models/ProductionLineStop.php @@ -12,10 +12,9 @@ class ProductionLineStop extends Model protected $fillable = [ "plant_id", - "block_id", "shift_id", "line_id", - "lineStop_id", + "linestop_id", "from_datetime", "to_datetime", "stop_hour", @@ -27,11 +26,6 @@ class ProductionLineStop extends Model return $this->belongsTo(Plant::class); } - public function block(): BelongsTo - { - return $this->belongsTo(Block::class); - } - public function shift(): BelongsTo { return $this->belongsTo(Shift::class); diff --git a/app/Models/ProductionQuantity.php b/app/Models/ProductionQuantity.php index 6d5e7df24..954220f3d 100644 --- a/app/Models/ProductionQuantity.php +++ b/app/Models/ProductionQuantity.php @@ -12,7 +12,6 @@ class ProductionQuantity extends Model protected $fillable = [ "plant_id", - "block_id", "shift_id", "line_id", "item_id", @@ -24,11 +23,6 @@ class ProductionQuantity extends Model return $this->belongsTo(Plant::class); } - public function block(): BelongsTo - { - return $this->belongsTo(Block::class); - } - public function shift(): BelongsTo { return $this->belongsTo(Shift::class); diff --git a/app/Models/QualityValidation.php b/app/Models/QualityValidation.php new file mode 100644 index 000000000..86c87aabb --- /dev/null +++ b/app/Models/QualityValidation.php @@ -0,0 +1,51 @@ +belongsTo(Item::class); + } + + public function plant(): BelongsTo + { + return $this->belongsTo(Plant::class); + } + + public function stickermaster(): BelongsTo + { + return $this->belongsTo(StickerMaster::class); + } +} diff --git a/app/Models/StickerMaster.php b/app/Models/StickerMaster.php new file mode 100644 index 000000000..49df73fe3 --- /dev/null +++ b/app/Models/StickerMaster.php @@ -0,0 +1,46 @@ +belongsTo(Item::class); + } + + public function plant(): BelongsTo + { + return $this->belongsTo(Plant::class); + } + +} diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index d82cd88df..896ecfb23 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -4,6 +4,8 @@ namespace App\Providers; use Illuminate\Support\Facades\Gate; use Illuminate\Support\ServiceProvider; +use URL; + // use Doctrine\DBAL\Types\Type; class AppServiceProvider extends ServiceProvider @@ -25,6 +27,8 @@ class AppServiceProvider extends ServiceProvider return $user->hasRole('Super Admin') ? true : null; }); + // URL::forceScheme('https'); + // if (!Type::hasType('citext')) { // Type::addType('citext', \Doctrine\DBAL\Platforms\PostgreSqlPlatform::class); // } diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php index a474fea7f..106478c96 100644 --- a/app/Providers/Filament/AdminPanelProvider.php +++ b/app/Providers/Filament/AdminPanelProvider.php @@ -7,6 +7,7 @@ use Filament\Http\Middleware\Authenticate; use Filament\Http\Middleware\AuthenticateSession; use Filament\Http\Middleware\DisableBladeIconComponents; use Filament\Http\Middleware\DispatchServingFilamentEvent; +use Filament\Navigation\NavigationGroup; use Filament\Pages; use Filament\Panel; use Filament\PanelProvider; diff --git a/database/migrations/2025_03_21_090347_create_lines_table.php b/database/migrations/2025_03_21_090347_create_lines_table.php index 9a058ee74..5824f4672 100644 --- a/database/migrations/2025_03_21_090347_create_lines_table.php +++ b/database/migrations/2025_03_21_090347_create_lines_table.php @@ -14,8 +14,6 @@ return new class extends Migration CREATE TABLE lines ( id BIGINT GENERATED always AS IDENTITY PRIMARY KEY, - shift_id BIGINT NOT NULL, - block_id BIGINT NOT NULL, plant_id BIGINT NOT NULL, name TEXT NOT NULL, @@ -25,9 +23,7 @@ return new class extends Migration updated_at TIMESTAMP NOT NULL DEFAULT NOW(), deleted_at TIMESTAMP, - UNIQUE (name, shift_id, block_id, plant_id), - FOREIGN KEY (shift_id) REFERENCES shifts (id), - FOREIGN KEY (block_id) REFERENCES blocks (id), + UNIQUE (name, plant_id), FOREIGN KEY (plant_id) REFERENCES plants (id) ); SQL; diff --git a/database/migrations/2025_03_21_090348_create_items_table.php b/database/migrations/2025_03_21_090348_create_items_table.php index 5db2ad43a..8fafd65ee 100644 --- a/database/migrations/2025_03_21_090348_create_items_table.php +++ b/database/migrations/2025_03_21_090348_create_items_table.php @@ -14,8 +14,6 @@ return new class extends Migration CREATE TABLE items ( id BIGINT GENERATED always AS IDENTITY PRIMARY KEY, - line_id BIGINT NOT NULL, - block_id BIGINT NOT NULL, plant_id BIGINT NOT NULL, code TEXT NOT NULL CHECK (LENGTH(code) >= 6), @@ -27,9 +25,7 @@ return new class extends Migration updated_at TIMESTAMP NOT NULL DEFAULT NOW(), deleted_at TIMESTAMP, - UNIQUE (code, line_id, block_id, plant_id), - FOREIGN KEY (line_id) REFERENCES lines (id), - FOREIGN KEY (block_id) REFERENCES blocks (id), + UNIQUE (code, plant_id), FOREIGN KEY (plant_id) REFERENCES plants (id) ); SQL; diff --git a/database/migrations/2025_03_22_184847_create_line_stops_table.php b/database/migrations/2025_03_22_184847_create_line_stops_table.php index 01e53483c..d7bf613cb 100644 --- a/database/migrations/2025_03_22_184847_create_line_stops_table.php +++ b/database/migrations/2025_03_22_184847_create_line_stops_table.php @@ -15,21 +15,12 @@ return new class extends Migration CREATE TABLE line_stops ( id BIGINT GENERATED always AS IDENTITY PRIMARY KEY, - shift_id BIGINT NOT NULL, - block_id BIGINT NOT NULL, - plant_id BIGINT NOT NULL, - - code TEXT NOT NULL, + code TEXT NOT NULL UNIQUE, reason TEXT NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT NOW(), updated_at TIMESTAMP NOT NULL DEFAULT NOW(), - deleted_at TIMESTAMP, - - UNIQUE (code, shift_id, block_id, plant_id), - FOREIGN KEY (shift_id) REFERENCES shifts (id), - FOREIGN KEY (block_id) REFERENCES blocks (id), - FOREIGN KEY (plant_id) REFERENCES plants (id) + deleted_at TIMESTAMP ); SQL; diff --git a/database/migrations/2025_03_23_163259_create_production_line_stops_table.php b/database/migrations/2025_03_23_163259_create_production_line_stops_table.php index 23f2071cc..fa7e155c2 100644 --- a/database/migrations/2025_03_23_163259_create_production_line_stops_table.php +++ b/database/migrations/2025_03_23_163259_create_production_line_stops_table.php @@ -16,9 +16,8 @@ return new class extends Migration line_id BIGINT NOT NULL, shift_id BIGINT NOT NULL, - block_id BIGINT NOT NULL, plant_id BIGINT NOT NULL, - lineStop_id BIGINT NOT NULL, + linestop_id BIGINT NOT NULL, from_datetime TIMESTAMP NOT NULL, to_datetime TIMESTAMP NOT NULL, @@ -31,9 +30,8 @@ return new class extends Migration FOREIGN KEY (line_id) REFERENCES lines (id), FOREIGN KEY (shift_id) REFERENCES shifts (id), - FOREIGN KEY (block_id) REFERENCES blocks (id), FOREIGN KEY (plant_id) REFERENCES plants (id), - FOREIGN KEY (lineStop_id) REFERENCES line_stops (id) + FOREIGN KEY (linestop_id) REFERENCES line_stops (id) ); SQL; diff --git a/database/migrations/2025_03_23_170155_create_production_quantities_table.php b/database/migrations/2025_03_23_170155_create_production_quantities_table.php index e174ce175..62019e9a3 100644 --- a/database/migrations/2025_03_23_170155_create_production_quantities_table.php +++ b/database/migrations/2025_03_23_170155_create_production_quantities_table.php @@ -17,7 +17,6 @@ return new class extends Migration line_id BIGINT NOT NULL, shift_id BIGINT NOT NULL, - block_id BIGINT NOT NULL, plant_id BIGINT NOT NULL, item_id BIGINT NOT NULL, @@ -31,7 +30,6 @@ return new class extends Migration FOREIGN KEY (item_id) REFERENCES items (id), FOREIGN KEY (line_id) REFERENCES lines (id), FOREIGN KEY (shift_id) REFERENCES shifts (id), - FOREIGN KEY (block_id) REFERENCES blocks (id), FOREIGN KEY (plant_id) REFERENCES plants (id) ); SQL; diff --git a/database/migrations/2025_03_28_092047_create_sticker_masters_table.php b/database/migrations/2025_03_28_092047_create_sticker_masters_table.php new file mode 100644 index 000000000..5563ef326 --- /dev/null +++ b/database/migrations/2025_03_28_092047_create_sticker_masters_table.php @@ -0,0 +1,62 @@ +