Quality Validation - Dashboard - Production Quantity Validation and Plan Quantity Updation

This commit is contained in:
dhanabalan
2025-03-31 19:10:13 +05:30
parent a93fe806bb
commit 29687b109c
7 changed files with 483 additions and 120 deletions

View File

@@ -226,6 +226,7 @@ class ProductionLineStopResource extends Resource
Forms\Components\DateTimePicker::make('to_datetime')
->label('To DateTime')
->required()
->after('from_datetime')
->reactive()
->afterStateUpdated(fn ($state, callable $set, callable $get) =>
self::updateStopDuration($get, $set) //self means it calling the function within the class
@@ -260,11 +261,21 @@ class ProductionLineStopResource extends Resource
if ($fromTime->lt($toTime)) {
$diffInMinutes = $fromTime->diffInMinutes($toTime);
$set('stop_hour', floor($diffInMinutes / 60));
$set('stop_min', $diffInMinutes % 60);
// $set('stop_hour', floor($diffInMinutes / 60));
// $set('stop_min', $diffInMinutes % 60);
if((floor($diffInMinutes / 60) === 0.0) && ($diffInMinutes % 60 === 0))
{
$set('stop_hour', null);
$set('stop_min', null);
}
else
{
$set('stop_hour', floor($diffInMinutes / 60));
$set('stop_min', $diffInMinutes % 60);
}
} else {
$set('stop_hour', 0);
$set('stop_min', 0);
$set('stop_hour', null);
$set('stop_min', null);
}
}
}

View File

@@ -15,6 +15,7 @@ use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Filament\Forms\Components\Section;
use Illuminate\Support\Facades\Request;
class ProductionPlanResource extends Resource
{
@@ -147,6 +148,25 @@ class ProductionPlanResource extends Resource
}
else
{
//SELECT COUNT(*) FROM plant_quantity_details WHERE DATE(created_at) = '{DateTime.Now.ToString("yyyy-MM-dd")}' AND shift_id = '{userShiftId}' AND plant_id = '{userPlantId}' AND line_id = '{userLineId}'
//Day shift 'Plant Production Quantity' already updated into database
// $currentPath = url()->current();
// $currentPath = $_SERVER['REQUEST_URI'];
// dd($currentPath);
$exists = ProductionPlan::where('plant_id', $get('plant_id'))
->where('shift_id', $get('shift_id'))
->where('line_id', $get('line_id'))
->whereDate('created_at', today())
->exists();
if ($exists)
{
$set('line_id', null);
$set('ppLineError', $get('shift_id.name').' Production Plan already updated.');
return;
}
$set('ppLineError', null);
}
})

View File

@@ -143,20 +143,24 @@ class ProductionQuantityResource extends Resource
->reactive()
->afterStateUpdated(function ($state, callable $set, callable $get) {
$lineId = $get('line_id');
$set('item_code', null);
if (!$lineId) {
$set('ppLineError', 'Please select a line first.');
$set('pqLineError', 'Please select a line first.');
return;
}
else
{
$set('validationError', null);
$set('ppLineError', null);
$set('pqLineError', null);
$set('item_id', null);
$set('item_description', null);
$set('serial_number', null);
}
})
->extraAttributes(fn ($get) => [
'class' => $get('ppLineError') ? 'border-red-500' : '',
'class' => $get('pqLineError') ? 'border-red-500' : '',
])
->hint(fn ($get) => $get('ppLineError') ? $get('ppLineError') : null)
->hint(fn ($get) => $get('pqLineError') ? $get('pqLineError') : null)
->hintColor('danger'),
// Forms\Components\Select::make('item_id')
// ->label('Item Code')
@@ -214,62 +218,128 @@ class ProductionQuantityResource extends Resource
$set('validationError', 'Please select a line first.');
return;
}
$exists = \App\Models\ProductionPlan::where('plant_id', $get('plant_id'))
->where('shift_id', $get('shift_id'))
->where('line_id', $get('line_id'))
->whereDate('created_at', today())
->exists();
if (!$exists)
{
$set('item_code', null);
$set('item_id', null);
$set('item_description', null);
$set('serial_number', null);
$set('validationError', 'Please set production plan first.');
return;
}
$set('validationError', null);
}
if (!preg_match('/^[a-zA-Z0-9]+\|[a-zA-Z0-9]+(\|)?$/', $state)) {
if (!preg_match('/^[a-zA-Z0-9]{6,}+\|[1-9][a-zA-Z0-9]{8,}+(\|)?$/', $state)) {
if (strpos($state, '|') === false) {
$set('validationError', 'Scan valid QR code. (Ex: Item_Code|Serial_Number )');
$set('item_id', null);
$set('item_description', null);
$set('serial_number', null);
return;
}
else
{
$splits = explode('|', $state);
$iCode = trim($splits[0]);
$sNumber = isset($splits[1]) ? trim($splits[1]) : null;
if (!ctype_alnum($iCode)) {
$set('validationError', 'Item code must contain alpha-numeric values.');
$set('item_id', null);
$set('item_description', null);
$set('serial_number', null);
return;
}
else if (strlen($iCode) < 6) {
$set('validationError', 'Item code must be at least 6 digits.');
$set('item_id', null);
$set('item_description', null);
$set('serial_number', null);
return;
}
else if (!ctype_alnum($sNumber)) {
$set('validationError', 'Serial Number must contain alpha-numeric values.');
$set('item_id', null);
$set('item_description', null);
$set('serial_number', null);
return;
}
else if (strlen($sNumber) < 9) {
$set('validationError', 'Serial Number must be at least 9 digits.');
$set('item_id', null);
$set('item_description', null);
$set('serial_number', null);
return;
}
}
$set('validationError', 'Scan valid QR code. (Ex: Item_Code|Serial_Number )');
$set('item_id', null);
$set('item_description', null);
$set('serial_number', null);
return;
}
// Only search when all parent IDs are selected
$parts = explode('|', $state);
$itemCode = trim($parts[0]); // Extract item code // 123456|123456789
$serialNumber = isset($parts[1]) ? trim($parts[1]) : null;
if (strlen($itemCode) < 6) {
$set('validationError', 'Item code must be at least 6 digits.');
$set('item_id', null);
$set('item_description', null);
$set('serial_number', null);
return;
}
else if (!ctype_alnum($itemCode)) {
$set('validationError', 'Item code should contain alpha-numeric values.');
$set('item_id', null);
$set('item_description', null);
$set('serial_number', null);
return;
}
else if ($serialNumber === '') {
$set('validationError', 'Waiting for full QR scan...');
$set('item_description', null);
$set('serial_number', null);
return; // Do not clear item_id, just wait for full input
}
else if (strlen($serialNumber) < 9) {
$set('validationError', 'Serial Number must be at least 9 digits.');
$set('item_description', null);
$set('serial_number', null);
return;
}
else if (!ctype_alnum($serialNumber)) {
$set('validationError', 'Serial Number should contain alpha-numeric values.');
$set('item_id', null);
$set('item_description', null);
$set('serial_number', null);
return;
}
else
{
$set('validationError', null);
$set('item_id', null);
$set('item_description', null);
$set('serial_number', null);
}
// Only search when all parent IDs are selected
$parts = explode('|', $state);
$itemCode = trim($parts[0]);
$serialNumber = isset($parts[1]) ? trim($parts[1]) : null;
// if (strlen($itemCode) < 6) {
// $set('validationError', 'Item code must be at least 6 digits.');
// $set('item_id', null);
// $set('item_description', null);
// $set('serial_number', null);
// return;
// }
// else if (!ctype_alnum($itemCode)) {
// $set('validationError', 'Item code must contain alpha-numeric values.');
// $set('item_id', null);
// $set('item_description', null);
// $set('serial_number', null);
// return;
// }
// else if ($serialNumber === '') {
// $set('validationError', 'Waiting for full QR scan...');
// $set('item_id', null);
// $set('item_description', null);
// $set('serial_number', null);
// return; // Do not clear item_id, just wait for full input
// }
// else if (strlen($serialNumber) < 9) {
// $set('validationError', 'Serial Number must be at least 9 digits.');
// $set('item_description', null);
// $set('serial_number', null);
// return;
// }
// else if (!ctype_alnum($serialNumber)) {
// $set('validationError', 'Serial Number must contain alpha-numeric values.');
// $set('item_id', null);
// $set('item_description', null);
// $set('serial_number', null);
// return;
// }
// else
// {
// $set('validationError', null);
// }
// Fetch item using item code and plant_id
$item = \App\Models\Item::where('code', $itemCode)
->where('plant_id', $get('plant_id'))
@@ -284,7 +354,7 @@ class ProductionQuantityResource extends Resource
{
$set('serial_number', $serialNumber);
$set('item_id', $item->id);
$set('item_code', $itemCode); //$itemCode
$set('item_code', $itemCode);
$set('item_description', $item->description);
}
else

View File

@@ -7,12 +7,19 @@ use App\Filament\Resources\QualityValidationResource\RelationManagers;
use App\Models\QualityValidation;
use Closure;
use Filament\Forms;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\Relationship;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Filament\Tables\Filters\Filter;
class QualityValidationResource extends Resource
@@ -73,29 +80,70 @@ class QualityValidationResource extends Resource
}
// Proceed with validation logic for new scanned QR code
if (!$state) {
if (!$state || trim($state) === '') {
$set('validationError', null);
return;
}
if (strpos($state, '|') === false)
{
// Check if QR format contains '|'
if (strpos($state, '|') === false) {
$set('validationError', 'Scan valid QR code. (Ex: Item_Code|Serial_Number )');
return;
}
if (!preg_match('/^[a-zA-Z0-9]{6,}+\|[1-9][a-zA-Z0-9]{8,}+(\|)?$/', $state)) {
if (strpos($state, '|') === false) {
$set('validationError', 'Scan valid QR code. (Ex: Item_Code|Serial_Number )');
$set('item_id', null);
$set('item_description', null);
$set('serial_number', null);
return;
}
else
{
$splits = explode('|', $state);
$iCode = trim($splits[0]);
$sNumber = isset($splits[1]) ? trim($splits[1]) : null;
if (!ctype_alnum($iCode)) {
$set('validationError', 'Item code must contain alpha-numeric values.');
return;
}
else if (strlen($iCode) < 6) {
$set('validationError', 'Item code must be at least 6 digits.');
return;
}
else if (!ctype_alnum($sNumber)) {
$set('validationError', 'Serial Number must contain alpha-numeric values.');
return;
}
else if (strlen($sNumber) < 9) {
$set('validationError', 'Serial Number must be at least 9 digits.');
return;
}
}
$set('validationError', 'Scan valid QR code. (Ex: Item_Code|Serial_Number )');
return;
}
else
{
$set('validationError', null);
}
$parts = explode('|', $state);
$itemCode = trim($parts[0]); // Extract item code // 123456|123456789
$serialNumber = trim($parts[1]);
// Store serial number before resetting fields
// Store serial number before resetting fields
$previousSerialNumber = $serialNumber;
$previousItemCode = $itemCode;
if (strlen($itemCode) < 6) {
$set('validationError', 'Item code must be at least 6 digits.');
$set('item_id', null);
return;
}
else if (!ctype_alnum($itemCode)) {
@@ -121,13 +169,6 @@ class QualityValidationResource extends Resource
$set('validationError', null);
}
if (!preg_match('/^[a-zA-Z0-9]+\|[a-zA-Z0-9]+(\|)?$/', $state)) {
$set('validationError', 'Invalid QR code format. Expected: Item_Code|Serial_Number.');
return;
}
//$set('validationError', null);
$plantId = $get('plant_id'); // Get selected plant
if (!$plantId) {
@@ -144,7 +185,7 @@ class QualityValidationResource extends Resource
if (!$stickerMaster) {
$set('validationError', 'Scanned item code does not exist for the selected plant.');
$set('validationError', 'Item code does not exist in master data.');
$set('sticker_master_id', null);
return;
}
@@ -168,18 +209,18 @@ class QualityValidationResource extends Resource
}
}
$serialExists = QualityValidation::where('sticker_master_id', $stickerMaster->id)
->where(function ($query) use ($serialNumber, $serialFields) {
foreach ($serialFields as $column) {
$query->orWhere($column, $serialNumber);
}
})->exists();
// $serialExists = QualityValidation::where('sticker_master_id', $stickerMaster->id)
// ->where(function ($query) use ($serialNumber, $serialFields) {
// foreach ($serialFields as $column) {
// $query->orWhere($column, $serialNumber);
// }
// })->exists();
if ($serialExists) {
$set('validationError', 'Already scanning process completed.');
$set('item_id', "$previousItemCode|$previousSerialNumber"); // Restore original QR code
return;
}
// if ($serialExists) {
// $set('validationError', 'Already scanning process completed.');
// $set('item_id', "$previousItemCode|$previousSerialNumber"); // Restore original QR code
// return;
// }
// Check if the serial number exists in any column of any row
$serialExists = QualityValidation::where(function ($query) use ($serialNumber, $serialFields) {
@@ -507,17 +548,56 @@ class QualityValidationResource extends Resource
public static function table(Table $table): Table
{
return $table
->searchable()
->columns([
Tables\Columns\TextColumn::make('id')
->label('ID')
->numeric()
->sortable(),
Tables\Columns\TextColumn::make('plant.name')
->numeric()
->sortable(),
Tables\Columns\TextColumn::make('stickerMaster.id')
->numeric()
Tables\Columns\TextColumn::make('stickerMaster.item.code')
->label('Item Code')
->sortable(),
Tables\Columns\TextColumn::make('production_order')
->label('Production Order')
->sortable(),
Tables\Columns\TextColumn::make('serial_number_motor')
->sortable(),
Tables\Columns\TextColumn::make('serial_number_pump')
->sortable(),
Tables\Columns\TextColumn::make('serial_number_pumpset')
->sortable(),
Tables\Columns\TextColumn::make('pack_slip_motor')
->sortable(),
Tables\Columns\TextColumn::make('pack_slip_pump')
->sortable(),
Tables\Columns\TextColumn::make('pack_slip_pumpset')
->sortable(),
Tables\Columns\TextColumn::make('name_plate_motor')
->sortable(),
Tables\Columns\TextColumn::make('name_plate_pump')
->sortable(),
Tables\Columns\TextColumn::make('name_plate_pumpset')
->sortable(),
Tables\Columns\TextColumn::make('tube_sticker_motor')
->sortable(),
Tables\Columns\TextColumn::make('tube_sticker_pump')
->sortable(),
Tables\Columns\TextColumn::make('tube_sticker_pumpset')
->sortable(),
Tables\Columns\TextColumn::make('warranty_card')
->sortable(),
Tables\Columns\TextColumn::make('part_validation1')
->sortable(),
Tables\Columns\TextColumn::make('part_validation2')
->sortable(),
Tables\Columns\TextColumn::make('part_validation3')
->sortable(),
Tables\Columns\TextColumn::make('part_validation4')
->sortable(),
Tables\Columns\TextColumn::make('part_validation5')
->sortable(),
Tables\Columns\TextColumn::make('created_at')
->dateTime()
->sortable()
@@ -532,12 +612,73 @@ class QualityValidationResource extends Resource
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
Tables\Filters\TrashedFilter::make(),
SelectFilter::make('item_code')
->relationship('stickerMaster.item', 'code')
->label('Filter by item code')
->searchable(),
Filter::make('production_order')
->label('Filter by Production Order')
->form([
TextInput::make('production_order')
->placeholder('Enter Production Order'),
])
->query(function ($query, array $data) {
return $query
->when(
$data['production_order'] ?? null,
fn ($q) => $q->where('production_order', 'like', '%' . $data['production_order'] . '%')
);
})
// This function adds indicators to show applied filters in the UI.
// It helps users see what filters are currently active.
->indicateUsing(function (array $data) {
return empty($data['production_order']) ? [] : ['Production Order: ' . $data['production_order']];
}),
// Created Date Range Filter
Filter::make('created_at')
->form([
DateTimePicker::make('created_from')
->label('Created From')
->native(false), // Optional: Use a nice date picker UI
DateTimePicker::make('created_to')
->label('Created To')
->native(false),
])
->query(function ($query, array $data) {
return $query
->when(
$data['created_from'] ?? null,
fn ($q) => $q->where('created_at', '>=', $data['created_from'])
)
->when(
$data['created_to'] ?? null,
fn ($q) => $q->where('created_at', '<=', $data['created_to'])
);
})
->indicateUsing(function (array $data) {
$indicators = [];
if (!empty($data['created_from'])) {
$indicators[] = 'From: ' . $data['created_from'];
}
if (!empty($data['created_to'])) {
$indicators[] = 'To: ' . $data['created_to'];
}
return $indicators;
}),
])
->actions([
Tables\Actions\ViewAction::make(),
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
@@ -545,6 +686,7 @@ class QualityValidationResource extends Resource
Tables\Actions\RestoreBulkAction::make(),
]),
]);
}
public static function getRelations(): array

View File

@@ -187,6 +187,7 @@ class StickerMasterResource extends Resource
public static function table(Table $table): Table
{
return $table
->searchable()
->columns([
Tables\Columns\TextColumn::make('id')
->label('ID')