1
0
forked from poc/pds

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') Forms\Components\DateTimePicker::make('to_datetime')
->label('To DateTime') ->label('To DateTime')
->required() ->required()
->after('from_datetime')
->reactive() ->reactive()
->afterStateUpdated(fn ($state, callable $set, callable $get) => ->afterStateUpdated(fn ($state, callable $set, callable $get) =>
self::updateStopDuration($get, $set) //self means it calling the function within the class 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)) { if ($fromTime->lt($toTime)) {
$diffInMinutes = $fromTime->diffInMinutes($toTime); $diffInMinutes = $fromTime->diffInMinutes($toTime);
$set('stop_hour', floor($diffInMinutes / 60)); // $set('stop_hour', floor($diffInMinutes / 60));
$set('stop_min', $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 { } else {
$set('stop_hour', 0); $set('stop_hour', null);
$set('stop_min', 0); $set('stop_min', null);
} }
} }
} }

View File

@@ -15,6 +15,7 @@ use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope; use Illuminate\Database\Eloquent\SoftDeletingScope;
use Filament\Forms\Components\Section; use Filament\Forms\Components\Section;
use Illuminate\Support\Facades\Request;
class ProductionPlanResource extends Resource class ProductionPlanResource extends Resource
{ {
@@ -147,6 +148,25 @@ class ProductionPlanResource extends Resource
} }
else 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); $set('ppLineError', null);
} }
}) })

View File

@@ -143,20 +143,24 @@ class ProductionQuantityResource extends Resource
->reactive() ->reactive()
->afterStateUpdated(function ($state, callable $set, callable $get) { ->afterStateUpdated(function ($state, callable $set, callable $get) {
$lineId = $get('line_id'); $lineId = $get('line_id');
$set('item_code', null);
if (!$lineId) { if (!$lineId) {
$set('ppLineError', 'Please select a line first.'); $set('pqLineError', 'Please select a line first.');
return; return;
} }
else else
{ {
$set('validationError', null); $set('validationError', null);
$set('ppLineError', null); $set('pqLineError', null);
$set('item_id', null);
$set('item_description', null);
$set('serial_number', null);
} }
}) })
->extraAttributes(fn ($get) => [ ->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'), ->hintColor('danger'),
// Forms\Components\Select::make('item_id') // Forms\Components\Select::make('item_id')
// ->label('Item Code') // ->label('Item Code')
@@ -214,62 +218,128 @@ class ProductionQuantityResource extends Resource
$set('validationError', 'Please select a line first.'); $set('validationError', 'Please select a line first.');
return; 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); $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('validationError', 'Scan valid QR code. (Ex: Item_Code|Serial_Number )');
$set('item_id', null); $set('item_id', null);
$set('item_description', null); $set('item_description', null);
$set('serial_number', null); $set('serial_number', null);
return; 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 else
{ {
$set('validationError', null); $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 // Fetch item using item code and plant_id
$item = \App\Models\Item::where('code', $itemCode) $item = \App\Models\Item::where('code', $itemCode)
->where('plant_id', $get('plant_id')) ->where('plant_id', $get('plant_id'))
@@ -284,7 +354,7 @@ class ProductionQuantityResource extends Resource
{ {
$set('serial_number', $serialNumber); $set('serial_number', $serialNumber);
$set('item_id', $item->id); $set('item_id', $item->id);
$set('item_code', $itemCode); //$itemCode $set('item_code', $itemCode);
$set('item_description', $item->description); $set('item_description', $item->description);
} }
else else

View File

@@ -7,12 +7,19 @@ use App\Filament\Resources\QualityValidationResource\RelationManagers;
use App\Models\QualityValidation; use App\Models\QualityValidation;
use Closure; use Closure;
use Filament\Forms; use Filament\Forms;
use Filament\Forms\Components\DatePicker;
use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Form; use Filament\Forms\Form;
use Filament\Resources\Resource; use Filament\Resources\Resource;
use Filament\Tables; use Filament\Tables;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table; use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\Relationship;
use Illuminate\Database\Eloquent\SoftDeletingScope; use Illuminate\Database\Eloquent\SoftDeletingScope;
use Filament\Tables\Filters\Filter;
class QualityValidationResource extends Resource class QualityValidationResource extends Resource
@@ -73,29 +80,70 @@ class QualityValidationResource extends Resource
} }
// Proceed with validation logic for new scanned QR code // Proceed with validation logic for new scanned QR code
if (!$state) { if (!$state || trim($state) === '') {
$set('validationError', null);
return; 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; 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); $parts = explode('|', $state);
$itemCode = trim($parts[0]); // Extract item code // 123456|123456789 $itemCode = trim($parts[0]); // Extract item code // 123456|123456789
$serialNumber = trim($parts[1]); $serialNumber = trim($parts[1]);
// Store serial number before resetting fields // Store serial number before resetting fields
$previousSerialNumber = $serialNumber; $previousSerialNumber = $serialNumber;
$previousItemCode = $itemCode; $previousItemCode = $itemCode;
if (strlen($itemCode) < 6) { if (strlen($itemCode) < 6) {
$set('validationError', 'Item code must be at least 6 digits.'); $set('validationError', 'Item code must be at least 6 digits.');
$set('item_id', null);
return; return;
} }
else if (!ctype_alnum($itemCode)) { else if (!ctype_alnum($itemCode)) {
@@ -121,13 +169,6 @@ class QualityValidationResource extends Resource
$set('validationError', null); $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 $plantId = $get('plant_id'); // Get selected plant
if (!$plantId) { if (!$plantId) {
@@ -144,7 +185,7 @@ class QualityValidationResource extends Resource
if (!$stickerMaster) { 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); $set('sticker_master_id', null);
return; return;
} }
@@ -168,18 +209,18 @@ class QualityValidationResource extends Resource
} }
} }
$serialExists = QualityValidation::where('sticker_master_id', $stickerMaster->id) // $serialExists = QualityValidation::where('sticker_master_id', $stickerMaster->id)
->where(function ($query) use ($serialNumber, $serialFields) { // ->where(function ($query) use ($serialNumber, $serialFields) {
foreach ($serialFields as $column) { // foreach ($serialFields as $column) {
$query->orWhere($column, $serialNumber); // $query->orWhere($column, $serialNumber);
} // }
})->exists(); // })->exists();
if ($serialExists) { // if ($serialExists) {
$set('validationError', 'Already scanning process completed.'); // $set('validationError', 'Already scanning process completed.');
$set('item_id', "$previousItemCode|$previousSerialNumber"); // Restore original QR code // $set('item_id', "$previousItemCode|$previousSerialNumber"); // Restore original QR code
return; // return;
} // }
// Check if the serial number exists in any column of any row // Check if the serial number exists in any column of any row
$serialExists = QualityValidation::where(function ($query) use ($serialNumber, $serialFields) { $serialExists = QualityValidation::where(function ($query) use ($serialNumber, $serialFields) {
@@ -507,17 +548,56 @@ class QualityValidationResource extends Resource
public static function table(Table $table): Table public static function table(Table $table): Table
{ {
return $table return $table
->searchable()
->columns([ ->columns([
Tables\Columns\TextColumn::make('id') Tables\Columns\TextColumn::make('id')
->label('ID') ->label('ID')
->numeric() ->numeric()
->sortable(), ->sortable(),
Tables\Columns\TextColumn::make('plant.name') Tables\Columns\TextColumn::make('plant.name')
->numeric()
->sortable(), ->sortable(),
Tables\Columns\TextColumn::make('stickerMaster.id') Tables\Columns\TextColumn::make('stickerMaster.item.code')
->numeric() ->label('Item Code')
->sortable(), ->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') Tables\Columns\TextColumn::make('created_at')
->dateTime() ->dateTime()
->sortable() ->sortable()
@@ -532,12 +612,73 @@ class QualityValidationResource extends Resource
->toggleable(isToggledHiddenByDefault: true), ->toggleable(isToggledHiddenByDefault: true),
]) ])
->filters([ ->filters([
Tables\Filters\TrashedFilter::make(), 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([ ->actions([
Tables\Actions\ViewAction::make(), Tables\Actions\ViewAction::make(),
Tables\Actions\EditAction::make(), Tables\Actions\EditAction::make(),
]) ])
->bulkActions([ ->bulkActions([
Tables\Actions\BulkActionGroup::make([ Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(), Tables\Actions\DeleteBulkAction::make(),
@@ -545,6 +686,7 @@ class QualityValidationResource extends Resource
Tables\Actions\RestoreBulkAction::make(), Tables\Actions\RestoreBulkAction::make(),
]), ]),
]); ]);
} }
public static function getRelations(): array public static function getRelations(): array

View File

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

View File

@@ -12,72 +12,169 @@ class ItemOverview extends ChartWidget
//protected $listeners = ['filtersUpdated' => '$refresh']; // Listen for filter updates //protected $listeners = ['filtersUpdated' => '$refresh']; // Listen for filter updates
protected function getData(): array // protected function getData(): array
{ // {
$activeFilter = $this->filter; // $activeFilter = $this->filter;
// Get filter values from session // // Get filter values from session
$selectedPlant = session('selected_plant'); // $selectedPlant = session('selected_plant');
$selectedLine = session('selected_line'); // $selectedLine = session('selected_line');
$query = \DB::table('production_quantities') // $query = \DB::table('production_quantities')
->join('plants', 'production_quantities.plant_id', '=', 'plants.id') // Join plants table // ->join('plants', 'production_quantities.plant_id', '=', 'plants.id') // Join plants table
->join('lines', 'production_quantities.line_id', '=', 'lines.id') // Join lines 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') // ->selectRaw('EXTRACT(HOUR FROM production_quantities.created_at) AS hour, count(*) AS total_quantity')
->whereBetween('production_quantities.created_at', [now()->startOfDay(), now()->endOfDay()]) // ->whereBetween('production_quantities.created_at', [now()->startOfDay(), now()->endOfDay()])
// ->when($selectedPlant, function ($q) use ($selectedPlant) {
// return $q->where('plants.id', $selectedPlant);
// })
// ->when($selectedLine, function ($q) use ($selectedLine) {
// return $q->where('lines.id', $selectedLine);
// })
// ->groupByRaw('EXTRACT(HOUR FROM production_quantities.created_at)')
// ->orderByRaw('EXTRACT(HOUR FROM production_quantities.created_at)')
// ->pluck('total_quantity', 'hour')
// ->toArray();
// $allHours = array_fill(0, 24, 0);
// $data = array_replace($allHours, $query);
// $shiftedKeys = range(8, 23); // 8 AM to 11 PM
// $shiftedKeys = array_merge($shiftedKeys, range(0, 8));
// $orderedData = array_map(fn($hour) => $data[$hour], $shiftedKeys);
// return [
// 'datasets' => [
// [
// 'label' => 'Hourly Production',
// 'data' => array_values($orderedData),
// 'borderColor' => 'rgba(75, 192, 192, 1)',
// 'backgroundColor' => 'rgba(75, 192, 192, 0.2)',
// 'fill' => false,
// 'tension' => 0.3,
// ],
// ],
// // Correct label sequence from 8 AM to 7 AM
// 'labels' => array_map(fn ($hour) => date("g A", strtotime("$hour:00")), $shiftedKeys),
// ];
// }
protected function getData(): array
{
$activeFilter = $this->filter;
$selectedPlant = session('selected_plant');
$selectedLine = session('selected_line');
if ($activeFilter === 'yesterday') {
$startDate = now()->subDay()->startOfDay();
$endDate = now()->subDay()->endOfDay();
$groupBy = 'EXTRACT(HOUR FROM production_quantities.created_at)';
}
else if ($activeFilter === 'this_week') {
$startDate = now()->startOfWeek(); // Monday 12:00 AM
$endDate = now()->endOfWeek(); // Sunday 11:59 PM
$groupBy = 'EXTRACT(DOW FROM production_quantities.created_at)'; // Group by day of week
}
else if ($activeFilter === 'this_month') {
$startDate = now()->startOfMonth();
$endDate = now()->endOfMonth();
// Group records into weeks
$groupBy = "FLOOR((EXTRACT(DAY FROM production_quantities.created_at) - 1) / 7) + 1";
}
else
{
$startDate = now()->startOfDay();
$endDate = now()->endOfDay();
$groupBy = 'EXTRACT(HOUR FROM production_quantities.created_at)';
}
$query = \DB::table('production_quantities')
->join('plants', 'production_quantities.plant_id', '=', 'plants.id')
->join('lines', 'production_quantities.line_id', '=', 'lines.id')
->selectRaw("$groupBy AS time_unit, count(*) AS total_quantity")
->whereBetween('production_quantities.created_at', [$startDate, $endDate])
->when($selectedPlant, function ($q) use ($selectedPlant) { ->when($selectedPlant, function ($q) use ($selectedPlant) {
return $q->where('plants.id', $selectedPlant); return $q->where('plants.id', $selectedPlant);
}) })
->when($selectedLine, function ($q) use ($selectedLine) { ->when($selectedLine, function ($q) use ($selectedLine) {
return $q->where('lines.id', $selectedLine); return $q->where('lines.id', $selectedLine);
}) })
->groupByRaw('EXTRACT(HOUR FROM production_quantities.created_at)')
->orderByRaw('EXTRACT(HOUR FROM production_quantities.created_at)') ->groupByRaw($groupBy)
->pluck('total_quantity', 'hour') ->orderByRaw($groupBy)
->pluck('total_quantity', 'time_unit')
->toArray(); ->toArray();
if ($activeFilter === 'this_month') {
$weeksCount = ceil($endDate->day / 7); // Calculate total weeks dynamically
$allWeeks = array_fill(1, $weeksCount, 0); // Initialize all weeks with 0
$data = array_replace($allWeeks, $query); // Fill missing weeks with 0
// // Ensure all 24 hours are covered, filling missing ones with zero // Generate dynamic week labels
// $data = array_replace(array_fill(8, 24, 0), $query); $labels = [];
for ($i = 1; $i <= $weeksCount; $i++) {
$weekStart = $startDate->copy()->addDays(($i - 1) * 7)->format('d M');
$weekEnd = $startDate->copy()->addDays($i * 7 - 1)->min($endDate)->format('d M');
$labels[] = "Week $i ($weekStart - $weekEnd)";
}
// return [ $orderedData = array_values($data);
// 'datasets' => [ }
// [ else if ($activeFilter === 'this_week') {
// 'label' => 'Hourly Production', // Correct week labels: ['Mon', 'Tue', ..., 'Sun']
// 'data' => array_values($data), $labels = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
// '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); // Initialize default data for all 7 days
$data = array_replace($allHours, $query); $data = array_fill(0, 7, 0);
$shiftedKeys = range(8, 23); // 8 AM to 11 PM // Fill in data from query results
$shiftedKeys = array_merge($shiftedKeys, range(0, 8)); foreach ($query as $dow => $count) {
$data[$dow] = $count;
}
$orderedData = array_map(fn($hour) => $data[$hour], $shiftedKeys); // Ensure days are ordered from Monday to Sunday
$orderedData = [
$data[1] ?? 0, // Monday
$data[2] ?? 0, // Tuesday
$data[3] ?? 0, // Wednesday
$data[4] ?? 0, // Thursday
$data[5] ?? 0, // Friday
$data[6] ?? 0, // Saturday
$data[0] ?? 0, // Sunday (move to last)
];
} else {
// Hourly data (same as before)
$allHours = array_fill(0, 24, 0);
$data = array_replace($allHours, $query);
// Shift hours for proper display (8 AM to 7 AM)
$shiftedKeys = array_merge(range(8, 23), range(0, 8));
$orderedData = array_map(fn($hour) => $data[$hour], $shiftedKeys);
// Labels: ["8 AM", "9 AM", ..., "7 AM"]
$labels = array_map(fn ($hour) => date("g A", strtotime("$hour:00")), $shiftedKeys);
}
return [ return [
'datasets' => [ 'datasets' => [
[ [
'label' => 'Hourly Production', 'label' => match ($activeFilter) {
'data' => array_values($orderedData), 'this_week' => "Daily Production This Week",
'this_month' => "Weekly Production This Month", // Updated Label
'yesterday' => "Yesterday's Hourly Production",
default => "Today's Hourly Production",
},
'data' => $orderedData,
'borderColor' => 'rgba(75, 192, 192, 1)', 'borderColor' => 'rgba(75, 192, 192, 1)',
'backgroundColor' => 'rgba(75, 192, 192, 0.2)', 'backgroundColor' => 'rgba(75, 192, 192, 0.2)',
'fill' => false, 'fill' => false,
'tension' => 0.3, 'tension' => 0.3,
], ],
], ],
// Correct label sequence from 8 AM to 7 AM 'labels' => $labels,
'labels' => array_map(fn ($hour) => date("g A", strtotime("$hour:00")), $shiftedKeys),
]; ];
}
}
protected function getType(): string protected function getType(): string
{ {
@@ -102,6 +199,9 @@ class ItemOverview extends ChartWidget
{ {
return [ return [
'today' => 'Today', 'today' => 'Today',
'yesterday' => 'Yesterday',
'this_week'=> 'This Week',
'this_month'=> 'This Month',
]; ];
} }

View File

@@ -37,4 +37,23 @@ class ProductionQuantity extends Model
{ {
return $this->belongsTo(Item::class); return $this->belongsTo(Item::class);
} }
protected static function booted()
{
static::created(function ($productionQuantity) {
$productionPlan = ProductionPlan::where('plant_id', $productionQuantity->plant_id)
->where('shift_id', $productionQuantity->shift_id)
->where('line_id', $productionQuantity->line_id)
->whereDate('created_at',today())
// ->where('plan_quantity', $productionQuantity->plan_quantity)
->first();
if ($productionPlan) {
$productionPlan->update([
'production_quantity' => $productionPlan->production_quantity + 1,
'updated_at' => now(),
]);
}
});
}
} }