From 6e44b690f1ebcda39f1e07280e4b42c8522df669 Mon Sep 17 00:00:00 2001 From: dhanabalan Date: Sun, 30 Mar 2025 23:04:29 +0530 Subject: [PATCH] After Production Quantity and Overall Validation --- app/Filament/Imports/ItemImporter.php | 2 +- app/Filament/Resources/BlockResource.php | 59 ++- app/Filament/Resources/CompanyResource.php | 36 +- app/Filament/Resources/ItemResource.php | 113 ++++- app/Filament/Resources/LineResource.php | 109 ++++- app/Filament/Resources/LineStopResource.php | 69 ++- app/Filament/Resources/PlantResource.php | 97 +++- .../Resources/ProductionLineStopResource.php | 316 +++++++----- .../Resources/ProductionPlanResource.php | 210 +++++--- .../Resources/ProductionQuantityResource.php | 403 ++++++++++++---- .../Resources/QualityValidationResource.php | 453 +++++++++++++++++- app/Filament/Resources/ShiftResource.php | 216 +++++++-- .../Resources/StickerMasterResource.php | 26 +- app/Models/QualityValidation.php | 15 +- app/Providers/Filament/AdminPanelProvider.php | 2 + ...1732_create_quality_validations_table.php} | 7 +- 16 files changed, 1726 insertions(+), 407 deletions(-) rename database/migrations/{2025_03_28_162455_create_quality_validations_table.php => 2025_03_30_091732_create_quality_validations_table.php} (88%) diff --git a/app/Filament/Imports/ItemImporter.php b/app/Filament/Imports/ItemImporter.php index d8263b2..d4f180b 100644 --- a/app/Filament/Imports/ItemImporter.php +++ b/app/Filament/Imports/ItemImporter.php @@ -34,7 +34,7 @@ class ItemImporter extends Importer ->requiredMapping() ->exampleHeader('Plant Name') ->label('Plant Name') - ->relationship(resolveUsing:'name') + ->relationship(resolveUsing: 'name') ->rules(['required']), ]; } diff --git a/app/Filament/Resources/BlockResource.php b/app/Filament/Resources/BlockResource.php index bbcc251..113923f 100644 --- a/app/Filament/Resources/BlockResource.php +++ b/app/Filament/Resources/BlockResource.php @@ -13,6 +13,7 @@ use Filament\Tables\Actions\ImportAction; use Filament\Tables\Table; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\SoftDeletingScope; +use Filament\Forms\Components\Section; class BlockResource extends Resource { @@ -22,18 +23,60 @@ class BlockResource extends Resource protected static ?string $navigationGroup = 'Master Entries'; + protected static ?int $navigationSort = 3; + public static function form(Form $form): Form { return $form ->schema([ - Forms\Components\TextInput::make('name') - ->required(), - // ->unique(ignoreRecord: true), - // ->columnSpanFull(), - Forms\Components\Select::make('plant_id') - ->relationship('plant', 'name') - // ->unique(ignoreRecord: true) - ->required(), + Section::make('') + ->schema([ + Forms\Components\TextInput::make('name') + ->required() + ->unique(ignoreRecord: true) + ->placeholder('Scan the valid name') + ->reactive() + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $nameId = $get('name'); + // Ensure `linestop_id` is not cleared + if (!$nameId) { + $set('bNameError', 'Scan the valid name.'); + return; + } + else + { + $set('bNameError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('bNameError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('bNameError') ? $get('bNameError') : null) + ->hintColor('danger'), + Forms\Components\Select::make('plant_id') + ->relationship('plant', 'name') + // ->unique(ignoreRecord: true) + ->required() + ->reactive() + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $nameId = $get('plant_id'); + // Ensure `linestop_id` is not cleared + if (!$nameId) { + $set('bPlantError', 'Please select a plant first.'); + return; + } + else + { + $set('bPlantError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('bPlantError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('bPlantError') ? $get('bPlantError') : null) + ->hintColor('danger'), + ]) + ->columns(2), ]); } diff --git a/app/Filament/Resources/CompanyResource.php b/app/Filament/Resources/CompanyResource.php index 131b7d8..102c6df 100644 --- a/app/Filament/Resources/CompanyResource.php +++ b/app/Filament/Resources/CompanyResource.php @@ -15,6 +15,7 @@ use Filament\Tables\Actions\ImportAction; use Filament\Tables\Table; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\SoftDeletingScope; +use Filament\Forms\Components\Section; class CompanyResource extends Resource { @@ -24,15 +25,40 @@ class CompanyResource extends Resource protected static ?string $navigationGroup = 'Master Entries'; + protected static ?int $navigationSort = 1; + public static function form(Form $form): Form { return $form ->schema([ - Forms\Components\TextInput::make('name') - ->required() - //->citext('name') - ->unique(ignoreRecord: true) - ->columnSpanFull(), + Section::make('') + ->schema([ + Forms\Components\TextInput::make('name') + ->required() + //->citext('name') + ->placeholder('Scan the valid name') + ->unique(ignoreRecord: true) + ->columnSpanFull() + ->reactive() + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $companyId = $get('name'); + // Ensure `linestop_id` is not cleared + if (!$companyId) { + $set('cNameError', 'Scan the valid name first.'); + return; + } + else + { + $set('cNameError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('cNameError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('cNameError') ? $get('cNameError') : null) + ->hintColor('danger'), + ]) + ->columns(2), ]); } diff --git a/app/Filament/Resources/ItemResource.php b/app/Filament/Resources/ItemResource.php index 02c290e..a860b4a 100644 --- a/app/Filament/Resources/ItemResource.php +++ b/app/Filament/Resources/ItemResource.php @@ -15,6 +15,7 @@ use Filament\Tables\Actions\ImportAction; use Filament\Tables\Table; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\SoftDeletingScope; +use Filament\Forms\Components\Section; class ItemResource extends Resource { @@ -24,26 +25,106 @@ class ItemResource extends Resource protected static ?string $navigationGroup = 'Master Entries'; + protected static ?int $navigationSort = 5; + public static function form(Form $form): Form { return $form ->schema([ - Forms\Components\Select::make('plant_id') - ->relationship('plant', 'name') - ->required(), - // ->nullable(), - Forms\Components\TextInput::make('code') - ->required() - ->unique(ignoreRecord: true) - ->minLength(6) - ->autocapitalize('code'), - Forms\Components\TextInput::make('hourly_quantity') - ->required() - ->numeric() - ->minValue(1), - Forms\Components\Textarea::make('description') - ->required(), - // ->columnSpanFull(), + Section::make('') + ->schema([ + Forms\Components\Select::make('plant_id') + ->relationship('plant', 'name') + ->required() + // ->nullable(), + ->reactive() + // ->afterStateUpdated(fn ($set) => $set('block_id', null) & $set('name', null) & $set('start_time', null) & $set('duration', null) & $set('end_time', null)) + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $plantId = $get('plant_id'); + // Ensure `linestop_id` is not cleared + if (!$plantId) { + $set('iPlantError', 'Please select a plant first.'); + return; + } + else + { + $set('iPlantError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('iPlantError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('iPlantError') ? $get('iPlantError') : null) + ->hintColor('danger'), + Forms\Components\TextInput::make('code') + ->required() + ->placeholder('Scan the valid code') + ->unique(ignoreRecord: true) + ->alphaNum() + ->minLength(6) + // ->autocapitalize('characters') + ->reactive() + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $code = $get('code'); + // Ensure `linestop_id` is not cleared + if (!$code) { + $set('iCodeError', 'Scan the valid code.'); + return; + } + else + { + if (strlen($code) < 6) { + $set('iCodeError', 'Item code must be at least 6 digits.'); + return; + } + else if (!preg_match('/^[a-zA-Z0-9]{6,}$/', $code)) { + $set('code',null); + $set('iCodeError', 'Item code must contain only alpha-numeric characters.'); + return; + } + $set('iCodeError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('iCodeError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('iCodeError') ? $get('iCodeError') : null) + ->hintColor('danger'), + Forms\Components\TextInput::make('hourly_quantity') + ->required() + ->label('Hourly Quantity') + ->placeholder('Scan the valid quantity') + ->integer() + ->minValue(1) + ->reactive() + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $hourQuan = $get('hourly_quantity'); + // Ensure `linestop_id` is not cleared + if (!$hourQuan) { + $set('iHourQuanError', 'Scan the valid hourly quantity.'); + return; + } + else + { + if (!preg_match('/^[0-9]{1,}$/', $hourQuan)) { + $set('hourly_quantity',null); + $set('iHourQuanError', 'Quantity must be integer value.'); + return; + } + $set('iHourQuanError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('iHourQuanError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('iHourQuanError') ? $get('iHourQuanError') : null) + ->hintColor('danger'), + Forms\Components\Textarea::make('description') + ->required() + ->placeholder('Scan the valid description'), + // ->columnSpanFull(), + ]) + ->columns(2), ]); } diff --git a/app/Filament/Resources/LineResource.php b/app/Filament/Resources/LineResource.php index 9948427..a881f3c 100644 --- a/app/Filament/Resources/LineResource.php +++ b/app/Filament/Resources/LineResource.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 Filament\Forms\Components\Section; +use Illuminate\Validation\Rules\Unique; class LineResource extends Resource { @@ -22,21 +24,108 @@ class LineResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack'; protected static ?string $navigationGroup = 'Master Entries'; + protected static ?int $navigationSort = 6; public static function form(Form $form): Form { 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(), + Section::make('') + ->schema([ + Forms\Components\Select::make('plant_id') + ->relationship('plant', 'name') + ->required() + // ->nullable(), + ->reactive() + // ->afterStateUpdated(fn ($set) => $set('block_id', null) & $set('name', null) & $set('start_time', null) & $set('duration', null) & $set('end_time', null)) + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $plantId = $get('plant_id'); + // Ensure `linestop_id` is not cleared + if (!$plantId) { + $set('lPlantError', 'Please select a plant first.'); + return; + } + else + { + $set('lPlantError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('lPlantError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('lPlantError') ? $get('lPlantError') : null) + ->hintColor('danger'), + Forms\Components\TextInput::make('name') + ->required() + ->placeholder('Scan the valid name') + // ->unique( + // ignoreRecord: true, + // modifyRuleUsing: function (Unique $rule) { + // return $rule->where('plant_id', $this->data['plant_id']); + // } + // ) + // ->rule(function () { + // return function ($attribute, $value, $fail) { + // $exists = Line::where('name', $value) + // ->where('plant_id', request()->input('plant_id')) + // ->exists(); + + // if ($exists) { + // $fail('The combination of name and plant ID must be unique.'); + // } + // }; + // }) + ->reactive() + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $lineNam = $get('name'); + // Ensure `linestop_id` is not cleared + if (!$lineNam) { + $set('lNameError', 'Scan the valid name.'); + return; + } + else + { + $exists = Line::where('name', $lineNam) + ->where('plant_id', $get('plant_id')) + ->exists(); + + if ($exists) { + $set('name', null); + $set('lNameError', 'The name has already been taken.'); + // $set('lNameError', 'The combination of name and plant ID must be unique.'); + return; + } + $set('lNameError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('lNameError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('lNameError') ? $get('lNameError') : null) + ->hintColor('danger'), + Forms\Components\TextInput::make('type') + ->required() + ->placeholder('Scan the valid type') + ->reactive() + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $lineTyp = $get('type'); + // Ensure `linestop_id` is not cleared + if (!$lineTyp) { + $set('lTypeError', 'Scan the valid type.'); + return; + } + else + { + $set('lTypeError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('lTypeError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('lTypeError') ? $get('lTypeError') : null) + ->hintColor('danger'), + ]) + ->columns(2), ]); } diff --git a/app/Filament/Resources/LineStopResource.php b/app/Filament/Resources/LineStopResource.php index c405639..7c6389e 100644 --- a/app/Filament/Resources/LineStopResource.php +++ b/app/Filament/Resources/LineStopResource.php @@ -6,6 +6,7 @@ use App\Filament\Imports\LineStopImporter; use App\Filament\Resources\LineStopResource\Pages; use App\Filament\Resources\LineStopResource\RelationManagers; use App\Models\LineStop; +use Doctrine\DBAL\Exception\InvalidColumnType\ColumnPrecisionRequired; use Filament\Forms; use Filament\Forms\Form; use Filament\Resources\Resource; @@ -14,6 +15,7 @@ use Filament\Tables\Actions\ImportAction; use Filament\Tables\Table; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\SoftDeletingScope; +use Filament\Forms\Components\Section; class LineStopResource extends Resource { @@ -23,16 +25,71 @@ class LineStopResource extends Resource protected static ?string $navigationGroup = 'Master Entries'; + protected static ?int $navigationSort = 7; + public static function form(Form $form): Form { return $form ->schema([ - Forms\Components\TextInput::make('code') - ->required() - ->autocapitalize(autocapitalize: 'code'), - Forms\Components\Textarea::make('reason') - ->required(), - //->columnSpanFull(), + Section::make('') + ->schema([ + Forms\Components\TextInput::make('code') + ->required() + ->alphaNum() + ->unique(ignoreRecord: true) + ->minLength(3) + ->placeholder('Scan the valid code') + ->autocapitalize(autocapitalize: 'characters') + ->columnSpan(1) + ->reactive() + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $code = $get('code'); + if (!$code) { + $set('lsCodeError', 'Scan the valid code.'); + return; + } + else + { + if (strlen($code) < 3) { + $set('lsCodeError', 'Code must be at least 3 digits.'); + return; + } + else if (!preg_match('/^[a-zA-Z0-9]{3,}$/', $code)) { + $set('code',null); + $set('lsCodeError', 'Alpha-numeric only allowed.'); + return; + } + $set('lsCodeError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('lsCodeError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('lsCodeError') ? $get('lsCodeError') : null) + ->hintColor('danger'), + Forms\Components\TextInput::make('reason') + ->required() + ->placeholder('Scan the valid reason') + ->reactive() + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $reason = $get('reason'); + if (!$reason) { + $set('lsReasonError', 'Scan the valid reason.'); + return; + } + else + { + $set('lsReasonError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('lsReasonError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('lsReasonError') ? $get('lsReasonError') : null) + ->hintColor('danger') + ->columnSpan(['default' => 1, 'sm' => 2]), + ]) + ->columns(['default' => 1, 'sm' => 3]), ]); } diff --git a/app/Filament/Resources/PlantResource.php b/app/Filament/Resources/PlantResource.php index cbd6cbc..3508085 100644 --- a/app/Filament/Resources/PlantResource.php +++ b/app/Filament/Resources/PlantResource.php @@ -23,6 +23,8 @@ class PlantResource extends Resource protected static ?string $navigationGroup = 'Master Entries'; + protected static ?int $navigationSort = 2; + public static function form(Form $form): Form { return $form @@ -32,19 +34,104 @@ class PlantResource extends Resource Forms\Components\TextInput::make('code') ->required() ->unique(ignoreRecord: true) - ->numeric() - ->minValue(1000), + ->integer() + ->reactive() + ->placeholder('Scan the valid code') + ->minValue(1000) + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $codeId = $get('code'); + // Ensure `linestop_id` is not cleared + if (!$codeId) { + $set('pCodeError', 'Scan the valid code.'); + return; + } + else + { + if (strlen($codeId) < 4) { + $set('pCodeError', 'Code must be at least 4 digits.'); + return; + } + // if (!preg_match('/^[1-9][0-9]{3,}$/', $codeId)) { + // $set('code',null); + // $set('pCodeError', 'Code should not begin with zero and must contain 4 digit number.'); + // return; + // } + $set('pCodeError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('pCodeError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('pCodeError') ? $get('pCodeError') : null) + ->hintColor('danger'), Forms\Components\Select::make('company_id') + // ->placeholder('Choose the valid company name') ->relationship('company', 'name') - ->required(), + ->required() + ->reactive() + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $companyId = $get('company_id'); + // Ensure `linestop_id` is not cleared + if (!$companyId) { + $set('pCompanyError', 'Please select a company first.'); + return; + } + else + { + $set('pCompanyError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('pCompanyError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('pCompanyError') ? $get('pCompanyError') : null) + ->hintColor('danger'), Forms\Components\TextInput::make('name') ->required() + ->placeholder('Scan the valid name') ->unique(ignoreRecord: true) - ->columnSpanFull(), + ->columnSpanFull() + ->reactive() + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $nameId = $get('name'); + // Ensure `linestop_id` is not cleared + if (!$nameId) { + $set('pNameError', 'Scan the valid name.'); + return; + } + else + { + $set('pNameError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('pNameError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('pNameError') ? $get('pNameError') : null) + ->hintColor('danger'), Forms\Components\Textarea::make('address') ->required() + ->placeholder('Scan the valid address') ->unique(ignoreRecord: true) - ->columnSpanFull(), + ->columnSpanFull() + ->reactive() + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $nameId = $get('address'); + // Ensure `linestop_id` is not cleared + if (!$nameId) { + $set('pAddressError', 'Scan the valid address.'); + return; + } + else + { + $set('pAddressError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('pAddressError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('pAddressError') ? $get('pAddressError') : null) + ->hintColor('danger'), ]) ->columns(2), ]); diff --git a/app/Filament/Resources/ProductionLineStopResource.php b/app/Filament/Resources/ProductionLineStopResource.php index e5aa719..73ed566 100644 --- a/app/Filament/Resources/ProductionLineStopResource.php +++ b/app/Filament/Resources/ProductionLineStopResource.php @@ -15,7 +15,7 @@ use Filament\Tables\Table; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\SoftDeletingScope; use Carbon\Carbon; - +use Filament\Forms\Components\Section; class ProductionLineStopResource extends Resource { @@ -32,120 +32,218 @@ class ProductionLineStopResource extends Resource 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 []; - } + Section::make('') + ->schema([ + Forms\Components\Select::make('plant_id') + ->relationship('plant', 'name') + ->required() + // ->nullable() + ->reactive() + // ->afterStateUpdated(fn ($set) => $set('block_name', null)) + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $plantId = $get('plant_id'); + $set('block_name', null); + if (!$plantId) { + $set('plsPlantError', 'Please select a plant first.'); + return; + } + else + { + $set('plsPlantError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('plsPlantError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('plsPlantError') ? $get('plsPlantError') : null) + ->hintColor('danger'), + Forms\Components\Select::make('block_name') + ->required() + // ->nullable() + ->label('Block') + ->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\Block::where('plant_id', $get('plant_id')) + ->pluck('name', 'id') + ->toArray(); + }) + ->reactive() + // ->afterStateUpdated(fn ($set) => $set('shift_id', null)) + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $blockId = $get('block_name'); + $set('shift_id', null); + if (!$blockId) { + $set('plsBlockError', 'Please select a block first.'); + return; + } + else + { + $set('plsBlockError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('plsBlockError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('plsBlockError') ? $get('plsBlockError') : null) + ->hintColor('danger'), + 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') || !$get('block_name')) { + 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 + // // Get the block ID based on plant_id and block_name + // $block = \App\Models\Block::where('plant_id', $get('plant_id')) + // ->where('name', $get('block_name')) + // ->first(); - // Ensure `linestop_id` is not cleared - if (!$lineStopId) { - $set('lineStop_reason', null); - return; - } + // if (!$block) { + // return []; + // } - // Check if item exists for the selected plant - $lineStop = \App\Models\LineStop::where('id', $lineStopId) - ->where('id', $lineStopId) - ->first(); + // return \App\Models\Shift::where('plant_id', $get('plant_id')) + // ->pluck('name', 'id') + // ->toArray(); + return \App\Models\Shift::where('plant_id', $get('plant_id')) + ->where('block_id', $get('block_name')) + ->pluck('name', 'id') + ->toArray(); + }) + ->reactive() + // ->afterStateUpdated(fn ($set) => $set('line_id', null)) + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $shiftId = $get('shift_id'); + $set('line_id', null); + if (!$shiftId) { + $set('plsShiftError', 'Please select a shift first.'); + return; + } + else + { + $set('plsShiftError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('plsShiftError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('plsShiftError') ? $get('plsShiftError') : null) + ->hintColor('danger'), + 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') || !$get('block_name') || !$get('shift_id')) { + return []; + } - $set('lineStop_reason', $lineStop?->reason ?? null); + return \App\Models\Line::where('plant_id', $get('plant_id')) + ->pluck('name', 'id') + ->toArray(); + }) + ->reactive() + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $lineId = $get('line_id'); + if (!$lineId) { + $set('plsLineError', 'Please select a line first.'); + return; + } + else + { + $set('plsLineError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('plsLineError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('plsLineError') ? $get('plsLineError') : null) + ->hintColor('danger'), + // 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') + // ) + ->placeholder('Scan the valid code') + ->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 - }), - Forms\Components\TextInput::make('lineStop_reason') - ->label('Line Stop Reason') - ->required() - ->reactive() - ->readOnly(true), - Forms\Components\DateTimePicker::make('from_datetime') - ->label('From DateTime') - ->required() - ->reactive() - ->afterStateUpdated(fn ($state, callable $set, callable $get) => - self::updateStopDuration($get, $set) - ), - Forms\Components\DateTimePicker::make('to_datetime') - ->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(), + // 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') + ->label('From DateTime') + ->required() + ->reactive() + ->afterStateUpdated(fn ($state, callable $set, callable $get) => + self::updateStopDuration($get, $set) + ), + Forms\Components\DateTimePicker::make('to_datetime') + ->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() + ->label( 'Stop Hour') + // ->dehydrated(false) // Don't send to backend + ->readOnly(true) + ->numeric(), + Forms\Components\TextInput::make('stop_min') + ->required() + ->label('Stop Minute') + // ->dehydrated(false) + ->readOnly(true) + ->numeric(), + ]) + ->columns(2), ]); } diff --git a/app/Filament/Resources/ProductionPlanResource.php b/app/Filament/Resources/ProductionPlanResource.php index 893f4e1..9bda270 100644 --- a/app/Filament/Resources/ProductionPlanResource.php +++ b/app/Filament/Resources/ProductionPlanResource.php @@ -14,6 +14,7 @@ use Filament\Tables\Actions\ImportAction; use Filament\Tables\Table; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\SoftDeletingScope; +use Filament\Forms\Components\Section; class ProductionPlanResource extends Resource { @@ -29,65 +30,162 @@ class ProductionPlanResource extends Resource { 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 []; - } + Section::make('') + ->schema([ + Forms\Components\Select::make('plant_id') + ->relationship('plant', 'name') + ->required() + // ->nullable() + ->reactive() + // ->afterStateUpdated(fn ($set) => $set('block_name', null)) + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $plantId = $get('plant_id'); + $set('block_name', null); + if (!$plantId) { + $set('ppPlantError', 'Please select a plant first.'); + return; + } + else + { + $set('ppPlantError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('ppPlantError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('ppPlantError') ? $get('ppPlantError') : null) + ->hintColor('danger'), + Forms\Components\Select::make('block_name') + ->required() + // ->nullable() + ->label('Block') + ->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\Block::where('plant_id', $get('plant_id')) + ->pluck('name', 'id') + ->toArray(); + }) + ->reactive() + //->afterStateUpdated(fn ($set) => $set('shift_id', null)) + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $blockId = $get('block_name'); + $set('shift_id', null); + if (!$blockId) { + $set('ppBlockError', 'Please select a block first.'); + return; + } + else + { + $set('ppBlockError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('ppBlockError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('ppBlockError') ? $get('ppBlockError') : null) + ->hintColor('danger'), + Forms\Components\Select::make('shift_id') + ->relationship('shift', 'name') + ->required() + // ->nullable() + ->options(function (callable $get) { + if (!$get('plant_id') || !$get('block_name')) { + return []; + } - return \App\Models\Line::where('plant_id', $get('plant_id')) - ->pluck('name', 'id') - ->toArray(); - }) - ->reactive(), - Forms\Components\TextInput::make('plan_quantity') - ->required() - ->numeric() - ->minValue(1), - Forms\Components\TextInput::make('production_quantity') - ->required() - ->numeric() - ->readOnly() - ->default(0), + return \App\Models\Shift::where('plant_id', $get('plant_id')) + ->where('block_id', $get('block_name')) + ->pluck('name', 'id') + ->toArray(); + }) + ->reactive() + // ->afterStateUpdated(fn ($set) => $set('line_id', null)) + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $shiftId = $get('shift_id'); + $set('line_id', null); + if (!$shiftId) { + $set('ppShiftError', 'Please select a shift first.'); + return; + } + else + { + $set('ppShiftError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('ppShiftError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('ppShiftError') ? $get('ppShiftError') : null) + ->hintColor('danger'), + 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') || !$get('block_name') || !$get('shift_id')) { + return []; + } + return \App\Models\Line::where('plant_id', $get('plant_id')) + ->pluck('name', 'id') + ->toArray(); + }) + ->reactive() + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $lineId = $get('line_id'); + if (!$lineId) { + $set('ppLineError', 'Please select a line first.'); + return; + } + else + { + $set('ppLineError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('ppLineError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('ppLineError') ? $get('ppLineError') : null) + ->hintColor('danger'), + Forms\Components\TextInput::make('plan_quantity') + ->required() + ->integer() + ->label('Plan Quantity') + ->placeholder('Scan the valid quantity') + ->minValue(1) + ->reactive() + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $planQuan = $get('plan_quantity'); + if (!$planQuan) { + $set('ppPlanQuanError', 'Scan the valid plan quantity.'); + return; + } + else + { + $set('ppPlanQuanError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('ppPlanQuanError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('ppPlanQuanError') ? $get('ppPlanQuanError') : null) + ->hintColor('danger'), + Forms\Components\TextInput::make('production_quantity') + ->required() + ->integer() + ->label('Production Quantity') + ->readOnly() + ->default(0), + ]) + ->columns(2), ]); } diff --git a/app/Filament/Resources/ProductionQuantityResource.php b/app/Filament/Resources/ProductionQuantityResource.php index 7c077b6..1d706ce 100644 --- a/app/Filament/Resources/ProductionQuantityResource.php +++ b/app/Filament/Resources/ProductionQuantityResource.php @@ -14,6 +14,7 @@ use Filament\Tables\Actions\ImportAction; use Filament\Tables\Table; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\SoftDeletingScope; +use Filament\Forms\Components\Section; class ProductionQuantityResource extends Resource { @@ -29,113 +30,305 @@ class ProductionQuantityResource extends Resource { 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\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."); + Section::make('') + ->schema([ + Forms\Components\Select::make('plant_id') + ->relationship('plant', 'name') + ->required() + // ->nullable() + ->reactive() + // ->afterStateUpdated(fn ($set) => $set('block_name', null)) + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $plantId = $get('plant_id'); + $set('block_name', null); + if (!$plantId) { + $set('pqPlantError', 'Please select a plant first.'); + return; + } + else + { + $set('validationError', null); + $set('pqPlantError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('pqPlantError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('pqPlantError') ? $get('pqPlantError') : null) + ->hintColor('danger'), + Forms\Components\Select::make('block_name') + ->required() + // ->nullable() + ->options(function (callable $get) { + if (!$get('plant_id')) { + return []; } - }; - }, - ]), - Forms\Components\Hidden::make('item_id') - ->required(), - 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(), + return \App\Models\Block::where('plant_id', $get('plant_id')) + ->pluck('name', 'id') + ->toArray(); + }) + ->reactive() + // ->afterStateUpdated(fn ($set) => $set('shift_id', null)) + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $blockId = $get('block_name'); + $set('shift_id', null); + if (!$blockId) { + $set('pqBlockError', 'Please select a block first.'); + return; + } + else + { + $set('validationError', null); + $set('pqBlockError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('pqBlockError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('pqBlockError') ? $get('pqBlockError') : null) + ->hintColor('danger'), + Forms\Components\Select::make('shift_id') + ->relationship('shift', 'name') + ->required() + // ->nullable() + ->options(function (callable $get) { + if (!$get('plant_id') || !$get('block_name')) { + return []; + } + + return \App\Models\Shift::where('plant_id', $get('plant_id')) + ->where('block_id', $get('block_name')) + ->pluck('name', 'id') + ->toArray(); + }) + ->reactive() + ->afterStateUpdated(fn ($set) => $set('line_id', null)) + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $shiftId = $get('shift_id'); + $set('line_id', null); + if (!$shiftId) { + $set('pqShiftError', 'Please select a shift first.'); + return; + } + else + { + $set('validationError', null); + $set('pqShiftError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('pqShiftError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('pqShiftError') ? $get('pqShiftError') : null) + ->hintColor('danger'), + 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') || !$get('block_name') || !$get('shift_id')) { + return []; + } + + return \App\Models\Line::where('plant_id', $get('plant_id')) + ->pluck('name', 'id') + ->toArray(); + }) + ->reactive() + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $lineId = $get('line_id'); + if (!$lineId) { + $set('ppLineError', 'Please select a line first.'); + return; + } + else + { + $set('validationError', null); + $set('ppLineError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('ppLineError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('ppLineError') ? $get('ppLineError') : null) + ->hintColor('danger'), + // 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) { + // **Check if input is empty before processing** + if (empty($state)) { + $set('item_id', null); + $set('item_description', null); + $set('serial_number', null); + $set('validationError', null); + return; + } + else + { + if (!$get('plant_id')) { + $set('item_code', null); + $set('item_id', null); + $set('item_description', null); + $set('serial_number', null); + $set('validationError', 'Please select a plant first.'); + return; + } + else if (!$get('block_name')) { + $set('item_code', null); + $set('item_id', null); + $set('item_description', null); + $set('serial_number', null); + $set('validationError', 'Please select a block first.'); + return; + } + else if (!$get('shift_id')) { + $set('item_code', null); + $set('item_id', null); + $set('item_description', null); + $set('serial_number', null); + $set('validationError', 'Please select a shift first.'); + return; + } + else if (!$get('line_id')) { + $set('item_code', null); + $set('item_id', null); + $set('item_description', null); + $set('serial_number', null); + $set('validationError', 'Please select a line first.'); + return; + } + $set('validationError', null); + } + + if (!preg_match('/^[a-zA-Z0-9]+\|[a-zA-Z0-9]+(\|)?$/', $state)) { + $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); + } + + // Fetch item using item code and plant_id + $item = \App\Models\Item::where('code', $itemCode) + ->where('plant_id', $get('plant_id')) + ->first(); + + if ($item) + { + $sNo = ProductionQuantity::where('serial_number', $serialNumber) + // ->where('plant_id', $get('plant_id')) + ->exists(); + if (!$sNo) + { + $set('serial_number', $serialNumber); + $set('item_id', $item->id); + $set('item_code', $itemCode); //$itemCode + $set('item_description', $item->description); + } + else + { + $set('validationError', 'Serial number already exist in database.'); + $set('item_id', null); + $set('item_description', null); + $set('serial_number', null); + return; + } + } + else + { + $set('validationError', 'Item code does not exist in master data.'); + $set('item_id', null); + $set('item_description', null); + $set('serial_number', null); + return; + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('validationError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('validationError') ? $get('validationError') : null) + ->hintColor('danger'), + Forms\Components\Hidden::make('item_id') + ->required(), + Forms\Components\TextInput::make('item_description') + ->label('Description') + ->reactive() + ->readOnly(true) + ->required(), + // Forms\Components\Select::make('item_id') + // ->label('Description') + // ->relationship('item', 'description') + // ->required(), + Forms\Components\TextInput::make('serial_number') + ->required() + ->unique(ignoreRecord: true) + ->readOnly(true) + ->autocapitalize('serial_number'), + //->columnSpanFull(), + ]) + ->columns(2), ]); } diff --git a/app/Filament/Resources/QualityValidationResource.php b/app/Filament/Resources/QualityValidationResource.php index f766b37..18528d5 100644 --- a/app/Filament/Resources/QualityValidationResource.php +++ b/app/Filament/Resources/QualityValidationResource.php @@ -5,6 +5,7 @@ namespace App\Filament\Resources; use App\Filament\Resources\QualityValidationResource\Pages; use App\Filament\Resources\QualityValidationResource\RelationManagers; use App\Models\QualityValidation; +use Closure; use Filament\Forms; use Filament\Forms\Form; use Filament\Resources\Resource; @@ -20,36 +21,453 @@ class QualityValidationResource extends Resource protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack'; protected static ?string $navigationGroup = 'Display'; + public $isSubmitted = false; public static function form(Form $form): Form { return $form ->schema([ Forms\Components\Select::make('plant_id') - ->relationship('plant', 'name') - ->required(), - Forms\Components\Select::make('item_id') - ->relationship('item', 'code') - ->searchable() + ->relationship('plant', 'name') + ->reactive() + ->afterStateUpdated(fn (callable $set) => [ + $set('item_id', null), + $set('validationError', null), + ]) ->required(), - Forms\Components\Select::make('stickermaster_id') - ->relationship('stickermaster', 'id') - ->required(), - Forms\Components\TextInput::make('scan_qr') - ->label('Scan QR Code') + Forms\Components\Hidden::make('sticker_master_id') + // ->relationship('stickerMaster', 'id') ->required(), Forms\Components\TextInput::make('production_order') ->required(), - Forms\Components\TextInput::make('part_validation1'), + Forms\Components\TextInput::make('item_id') + ->label('Item Code') + ->placeholder('Scan the valid QR code') + ->reactive() + ->required() + ->afterStateUpdated(function (callable $set, callable $get, ?string $state) { - Forms\Components\TextInput::make('part_validation2'), + // Reset visibility of all serial and part validation fields + $serialFields = [ + 'serial_number_motor', 'serial_number_pump', 'serial_number_pumpset', + 'pack_slip_motor', 'pack_slip_pump', 'pack_slip_pumpset', + 'name_plate_motor', 'name_plate_pump', 'name_plate_pumpset', + 'tube_sticker_motor', 'tube_sticker_pump', 'tube_sticker_pumpset', + 'warranty_card' + ]; - Forms\Components\TextInput::make('part_validation3'), + $partValidationColumns = [ + 'part_validation1', 'part_validation2', 'part_validation3', + 'part_validation4', 'part_validation5' + ]; - Forms\Components\TextInput::make('part_validation4'), + foreach ($serialFields as $field) { + $set($field . '_visible', false); + $set($field, null); + } - Forms\Components\TextInput::make('part_validation5'), + foreach ($partValidationColumns as $column) { + $set($column . '_visible', false); + $set($column, null); + } + // Proceed with validation logic for new scanned QR code + if (!$state) { + return; + } + + if (strpos($state, '|') === false) + { + return; + } + + $parts = explode('|', $state); + + $itemCode = trim($parts[0]); // Extract item code // 123456|123456789 + + $serialNumber = trim($parts[1]); + + if (strlen($itemCode) < 6) { + $set('validationError', 'Item code must be at least 6 digits.'); + $set('item_id', null); + return; + } + else if (!ctype_alnum($itemCode)) { + $set('validationError', 'Item Code should contain alpha-numeric values.'); + $set('item_id', null); + return; + } + else if ($serialNumber === '') { + $set('validationError', 'Waiting for full QR scan...'); + 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.'); + return; + } + else if (!ctype_alnum($serialNumber)) { + $set('validationError', 'Serial Number should contain alpha-numeric values.'); + $set('item_id', null); + return; + } + else + { + $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) { + $set('validationError', 'Please select a plant first.'); + $set('item_id', null); + $set('sticker_master_id', null); + return; + } + + // Check if the item exists for the selected plant + $stickerMaster = \App\Models\StickerMaster::where('plant_id', $plantId) + ->whereHas('item', function ($query) use ($itemCode) { + $query->where('code', $itemCode); + })->first(); + + + if (!$stickerMaster) { + $set('validationError', 'Scanned item code does not exist for the selected plant.'); + $set('sticker_master_id', null); + return; + } + else + { + $set('sticker_master_id', $stickerMaster->id); + $set('item_id', $itemCode); + } + + + // Check if user input matches the database values + foreach ($partValidationColumns as $field) { + if ($get("{$field}_visible")) { // Only validate visible fields + $userInput = $get($field); // Get user input + $expectedValue = $stickerMaster->$field; // Get expected value from DB + + if ($userInput !== null && $userInput !== $expectedValue) { + $set('validationError', "Invalid input for $field. Expected: $expectedValue"); + return; // Stop execution if any validation fails + } + } + } + + // Clear validation error if all inputs match + $set('validationError', null); + + // Filter columns with value `1` + $visibleColumns = []; + foreach ($serialFields as $column) { + if ($stickerMaster->$column === 1) { + $visibleColumns[] = $column; + } + } + + // Filter part validation columns that are not `null` + $visiblePartValidations = []; + foreach ($partValidationColumns as $column) { + if ($stickerMaster->$column !== null) { + $visiblePartValidations[] = $column; + } + } + + foreach ($serialFields as $column) { + if ($stickerMaster->$column == 1) { + $set($column . '_visible', true); + } else { + $set($column . '_visible', false); + } + } + + foreach ($partValidationColumns as $column) { + if ($stickerMaster->$column !== null) { + $set($column . '_visible', true); // Separate key for visibility + } else { + $set($column . '_visible', false); + } + } + + // Assign serial number to only visible text inputs + foreach ($serialFields as $field) { + if ($get("{$field}_visible")) { + $set($field, $serialNumber); + } + } + + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('validationError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('validationError') ? $get('validationError') : null) + ->hintColor('danger'), + + + Forms\Components\TextInput::make('serial_number_motor') + ->hidden(fn (callable $get) => !$get('serial_number_motor_visible')) // Controls visibility + ->default(''), // Keeps input empty + + Forms\Components\TextInput::make('serial_number_pump') + ->hidden(fn (callable $get) => !$get('serial_number_pump_visible')) + ->default(''), + + Forms\Components\TextInput::make('serial_number_pumpset') + ->hidden(fn (callable $get) => !$get('serial_number_pumpset_visible')) + ->default(''), + + Forms\Components\TextInput::make('pack_slip_motor') + ->hidden(fn (callable $get) => !$get('pack_slip_motor_visible')) + ->default(''), + + Forms\Components\TextInput::make('pack_slip_pump') + ->hidden(fn (callable $get) => !$get('pack_slip_pump_visible')) + ->default(''), + + Forms\Components\TextInput::make('pack_slip_pumpset') + ->hidden(fn (callable $get) => !$get('pack_slip_pumpset_visible')) + ->default(''), + + Forms\Components\TextInput::make('name_plate_motor') + ->hidden(fn (callable $get) => !$get('name_plate_motor_visible')) + ->default(''), + + Forms\Components\TextInput::make('name_plate_pump') + ->hidden(fn (callable $get) => !$get('name_plate_pump_visible')) + ->default(''), + + Forms\Components\TextInput::make('name_plate_pumpset') + ->hidden(fn (callable $get) => !$get('name_plate_pumpset_visible')) + ->default(''), + + Forms\Components\TextInput::make('tube_sticker_motor') + ->hidden(fn (callable $get) => !$get('tube_sticker_motor_visible')) + ->default(''), + + Forms\Components\TextInput::make('tube_sticker_pump') + ->hidden(fn (callable $get) => !$get('tube_sticker_pump_visible')) + ->default(''), + + Forms\Components\TextInput::make('tube_sticker_pumpset') + ->hidden(fn (callable $get) => !$get('tube_sticker_pumpset_visible')) + ->default(''), + + Forms\Components\TextInput::make('warranty_card') + ->hidden(fn (callable $get) => !$get('warranty_card_visible')) + ->default(''), + + Forms\Components\TextInput::make('part_validation1') + ->hidden(fn (callable $get) => !$get('part_validation1_visible')) + ->default('') + ->reactive() + ->required() + ->afterStateUpdated(function (callable $set, callable $get, ?string $state) { + + $stickerMasterId = $get('sticker_master_id'); + if (!$stickerMasterId) { + return; + } + + $stickerMaster = \App\Models\StickerMaster::find($stickerMasterId); + if (!$stickerMaster) { + return; + } + + $expectedValue = $stickerMaster->part_validation1; + + // If input is empty, reset the error + if ($state === null || trim($state) === '') { + $set('part_validation1_error', null); + return; + } + + if ($state === $expectedValue) + { + $set('part_validation1_error', null); + } + else + { + $set('part_validation1_error', "Invalid input for part validation 1."); // Expected: $expectedValue + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('part_validation1_error') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('part_validation1_error')) + ->hintColor('danger'), + + + Forms\Components\TextInput::make('part_validation2') + ->hidden(fn (callable $get) => !$get('part_validation2_visible')) + ->default('') + ->required() + ->afterStateUpdated(function (callable $set, callable $get, ?string $state) { + + $stickerMasterId = $get('sticker_master_id'); + if (!$stickerMasterId) { + return; + } + + $stickerMaster = \App\Models\StickerMaster::find($stickerMasterId); + if (!$stickerMaster) { + return; + } + + $expectedValue = $stickerMaster->part_validation2; + + // If input is empty, reset the error + if ($state === null || trim($state) === '') { + $set('part_validation2_error', null); + return; + } + + // If input is empty, do not show an error + + if ($state === $expectedValue) + { + $set('part_validation2_error', null); + } + else + { + $set('part_validation2_error', "Invalid input for part validation 2."); // Expected: $expectedValue + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('part_validation2_error') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('part_validation2_error')) + ->hintColor('danger'), + + Forms\Components\TextInput::make('part_validation3') + ->hidden(fn (callable $get) => !$get('part_validation3_visible')) + ->default('') + ->required() + ->afterStateUpdated(function (callable $set, callable $get, ?string $state) { + $stickerMasterId = $get('sticker_master_id'); + if (!$stickerMasterId) { + return; + } + + $stickerMaster = \App\Models\StickerMaster::find($stickerMasterId); + if (!$stickerMaster) { + return; + } + + $expectedValue = $stickerMaster->part_validation3; + + // If input is empty, reset the error + if ($state === null || trim($state) === '') { + $set('part_validation3_error', null); + return; + } + + // If input is empty, do not show an error + + if ($state === $expectedValue) + { + $set('part_validation3_error', null); + } + else + { + $set('part_validation3_error', "Invalid input for part validation 3."); // Expected: $expectedValue + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('part_validation3_error') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('part_validation3_error')) + ->hintColor('danger'), + + Forms\Components\TextInput::make('part_validation4') + ->hidden(fn (callable $get) => !$get('part_validation4_visible')) + ->default('') + ->required() + ->afterStateUpdated(function (callable $set, callable $get, ?string $state) { + $stickerMasterId = $get('sticker_master_id'); + if (!$stickerMasterId) { + return; + } + + $stickerMaster = \App\Models\StickerMaster::find($stickerMasterId); + if (!$stickerMaster) { + return; + } + + $expectedValue = $stickerMaster->part_validation4; + + // If input is empty, reset the error + if ($state === null || trim($state) === '') { + $set('part_validation4_error', null); + return; + } + + // If input is empty, do not show an error + + if ($state === $expectedValue) + { + $set('part_validation4_error', null); + } + else + { + $set('part_validation4_error', "Invalid input for part validation 4."); // Expected: $expectedValue + } + + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('part_validation4_error') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('part_validation4_error')) + ->hintColor('danger'), + + Forms\Components\TextInput::make('part_validation5') + ->hidden(fn (callable $get) => !$get('part_validation5_visible')) + ->default('') + ->required() + ->afterStateUpdated(function (callable $set, callable $get, ?string $state) { + $stickerMasterId = $get('sticker_master_id'); + if (!$stickerMasterId) { + return; + } + + $stickerMaster = \App\Models\StickerMaster::find($stickerMasterId); + if (!$stickerMaster) { + return; + } + + $expectedValue = $stickerMaster->part_validation4; + + // If input is empty, reset the error + if ($state === null || trim($state) === '') { + $set('part_validation5_error', null); + return; + } + + // If input is empty, do not show an error + + if ($state === $expectedValue) + { + $set('part_validation5_error', null); + } + else + { + $set('part_validation5_error', "Invalid input for part validation 5."); // Expected: $expectedValue + } + + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('part_validation5_error') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('part_validation5_error')) + ->hintColor('danger'), ]); } @@ -61,13 +479,10 @@ class QualityValidationResource extends Resource ->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') + Tables\Columns\TextColumn::make('stickerMaster.id') ->numeric() ->sortable(), Tables\Columns\TextColumn::make('created_at') diff --git a/app/Filament/Resources/ShiftResource.php b/app/Filament/Resources/ShiftResource.php index f6f818f..95d4d67 100644 --- a/app/Filament/Resources/ShiftResource.php +++ b/app/Filament/Resources/ShiftResource.php @@ -14,6 +14,7 @@ use Filament\Tables\Actions\ImportAction; use Filament\Tables\Table; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\SoftDeletingScope; +use Filament\Forms\Components\Section; class ShiftResource extends Resource { @@ -23,56 +24,181 @@ class ShiftResource extends Resource protected static ?string $navigationGroup = 'Master Entries'; + protected static ?int $navigationSort = 4; + public static function form(Form $form): Form { return $form ->schema([ - Forms\Components\Select::make('plant_id') - ->relationship('plant', 'name') - ->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() - ->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 []; - } + Section::make('') + ->schema([ + Forms\Components\Select::make('plant_id') + ->relationship('plant', 'name') + ->required() + // ->nullable() + ->reactive() + // ->afterStateUpdated(fn ($set) => $set('block_id', null) & $set('name', null) & $set('start_time', null) & $set('duration', null) & $set('end_time', null)) + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $plantId = $get('plant_id'); + $set('block_id', null); + // Ensure `linestop_id` is not cleared + if (!$plantId) { + $set('sPlantError', 'Please select a plant first.'); + return; + } + else + { + $set('sPlantError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('sPlantError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('sPlantError') ? $get('sPlantError') : null) + ->hintColor('danger'), + Forms\Components\Select::make('block_id') + ->relationship('block', 'name') + ->required() + // ->nullable() + ->reactive() + // ->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() - ->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(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), + return \App\Models\Block::where('plant_id', $get('plant_id')) + ->pluck('name', 'id') + ->toArray(); + }) + // ->afterStateUpdated(fn ($set) => $set('name', null)) + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $blockId = $get('block_id'); + $set('name', null); + // Ensure `linestop_id` is not cleared + if (!$blockId) { + $set('sBlockError', 'Please select a block first.'); + return; + } + else + { + $set('sBlockError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('sBlockError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('sBlockError') ? $get('sBlockError') : null) + ->hintColor('danger'), + Forms\Components\TextInput::make('name') + ->placeholder('Scan the valid name') + ->required() + ->reactive() + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $nameId = $get('name'); + $set('start_time', null); + // Ensure `linestop_id` is not cleared + if (!$nameId) { + $set('sNameError', 'Scan the valid name.'); + return; + } + else + { + $set('sNameError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('sNameError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('sNameError') ? $get('sNameError') : null) + ->hintColor('danger'), + Forms\Components\TimePicker::make('start_time') + ->required() + ->label('Start Time') + ->live() + // ->afterStateUpdated(fn (callable $set, callable $get, $state) => + // $set('end_time', self::calculateEndTime($state, $get('duration'))) + // ) + ->reactive() + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $nameId = $get('start_time'); + // $set('duration', null); + $set('end_time', self::calculateEndTime($state, $get('duration'))); + // Ensure `linestop_id` is not cleared + if (!$nameId) { + $set('sStartTimeError', 'Choose the valid start time.'); + return; + } + else + { + $set('sStartTimeError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('sStartTimeError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('sStartTimeError') ? $get('sStartTimeError') : null) + ->hintColor('danger'), + Forms\Components\TextInput::make('duration') + ->required() + ->placeholder('Scan the valid duration') + ->numeric() + ->inputMode('decimal') + ->minValue(0.01) // Minimum valid duration + ->lazy() + // ->afterStateUpdated(fn (callable $set, callable $get, $state) => + // $set('end_time', self::calculateEndTime($get('start_time'), $state)) + // ) + ->reactive() + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $duration = $get('duration'); + // $set('end_time', null); + $set('end_time', self::calculateEndTime($get('start_time'), $state)); + // Ensure `linestop_id` is not cleared + if (!$duration) { + $set('sDurationError', 'Scan the valid duration.'); + return; + } + else + { + $set('sDurationError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('sDurationError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('sDurationError') ? $get('sDurationError') : null) + ->hintColor('danger'), + Forms\Components\TimePicker::make('end_time') + ->required() + ->label('End Time') + ->readOnly() + // ->native(false), + ->reactive() + ->afterStateUpdated(function ($state, callable $set, callable $get) { + $endTime = $get('end_time'); + $set('end_time', self::calculateEndTime($get('start_time'), $state)); + // Ensure `linestop_id` is not cleared + if (!$endTime) { + $set('sEndTimeError', 'Choose the valid start time & duration.'); + return; + } + else + { + $set('sEndTimeError', null); + } + }) + ->extraAttributes(fn ($get) => [ + 'class' => $get('sEndTimeError') ? 'border-red-500' : '', + ]) + ->hint(fn ($get) => $get('sEndTimeError') ? $get('sEndTimeError') : null) + ->hintColor('danger'), + ]) + ->columns(2), ]); diff --git a/app/Filament/Resources/StickerMasterResource.php b/app/Filament/Resources/StickerMasterResource.php index 055ac5d..3ea6ac2 100644 --- a/app/Filament/Resources/StickerMasterResource.php +++ b/app/Filament/Resources/StickerMasterResource.php @@ -21,6 +21,8 @@ class StickerMasterResource extends Resource protected static ?string $navigationGroup = 'Master Entries'; + protected static ?int $navigationSort = 8; + public static function form(Form $form): Form { return $form @@ -28,17 +30,27 @@ class StickerMasterResource extends Resource Forms\Components\Select::make('plant_id') ->relationship('plant', 'name') ->reactive() - ->afterStateUpdated(fn (callable $set) => $set('item_id', null)) + ->nullable() + ->afterStateUpdated(fn (callable $set) => + $set('item_id', null) & $set('item_description', 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') - ) + ->options(function (callable $get) { + if (!$get('plant_id')) { + return []; + } + + return \App\Models\Item::where('plant_id', $get('plant_id')) + ->pluck('code', 'id') + ->toArray(); + }) ->required() + ->nullable() ->searchable() + ->reactive() ->live(debounce: 500) // Enable live updates ->afterStateUpdated(function ($state, callable $set, callable $get) { $plantId = $get('plant_id'); // Get selected plant_id @@ -180,11 +192,9 @@ class StickerMasterResource extends Resource ->label('ID') ->numeric() ->sortable(), - Tables\Columns\TextColumn::make('item.id') - ->numeric() + Tables\Columns\TextColumn::make('item.code') ->sortable(), Tables\Columns\TextColumn::make('plant.name') - ->numeric() ->sortable(), Tables\Columns\CheckboxColumn::make('serial_number_motor') ->disabled(true) diff --git a/app/Models/QualityValidation.php b/app/Models/QualityValidation.php index 86c87aa..7eabfac 100644 --- a/app/Models/QualityValidation.php +++ b/app/Models/QualityValidation.php @@ -11,9 +11,9 @@ class QualityValidation extends Model use SoftDeletes; protected $fillable = [ - 'item_id', - 'plant_id', - 'stickermaster_id ', + 'sticker_master_id', + 'plant_id', + 'production_order', 'serial_number_motor', 'serial_number_pump', 'serial_number_pumpset', @@ -34,18 +34,13 @@ class QualityValidation extends Model 'part_validation5', ]; - public function item(): BelongsTo + public function stickerMaster(): BelongsTo { - return $this->belongsTo(Item::class); + return $this->belongsTo(StickerMaster::class); } public function plant(): BelongsTo { return $this->belongsTo(Plant::class); } - - public function stickermaster(): BelongsTo - { - return $this->belongsTo(StickerMaster::class); - } } diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php index 106478c..b9f5b43 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\MenuItem; use Filament\Navigation\NavigationGroup; use Filament\Pages; use Filament\Panel; @@ -39,6 +40,7 @@ class AdminPanelProvider extends PanelProvider ->pages([ ]) + ->discoverWidgets(in: app_path('Filament/Widgets'), for: 'App\\Filament\\Widgets') // ->widgets([ // Widgets\AccountWidget::class, diff --git a/database/migrations/2025_03_28_162455_create_quality_validations_table.php b/database/migrations/2025_03_30_091732_create_quality_validations_table.php similarity index 88% rename from database/migrations/2025_03_28_162455_create_quality_validations_table.php rename to database/migrations/2025_03_30_091732_create_quality_validations_table.php index ad54327..4c5d407 100644 --- a/database/migrations/2025_03_28_162455_create_quality_validations_table.php +++ b/database/migrations/2025_03_30_091732_create_quality_validations_table.php @@ -15,9 +15,8 @@ return new class extends Migration CREATE TABLE quality_validations ( id BIGINT GENERATED always AS IDENTITY PRIMARY KEY, - item_id BIGINT NOT NULL, plant_id BIGINT NOT NULL, - stickermaster_id BIGINT NOT NULL, + sticker_master_id BIGINT NOT NULL, production_order TEXT NOT NULL, @@ -48,13 +47,13 @@ return new class extends Migration updated_at TIMESTAMP NOT NULL DEFAULT NOW(), deleted_at TIMESTAMP, - FOREIGN KEY (item_id) REFERENCES items (id), FOREIGN KEY (plant_id) REFERENCES plants (id), - FOREIGN KEY (stickerMaster_id) REFERENCES sticker_masters (id) + FOREIGN KEY (sticker_master_id) REFERENCES sticker_masters (id) ); SQL; DB::statement($sql); + } /**