8 Commits

8 changed files with 496 additions and 176 deletions

View File

@@ -0,0 +1,53 @@
<?php
namespace App\Filament\Exports;
use App\Models\Line;
use Filament\Actions\Exports\ExportColumn;
use Filament\Actions\Exports\Exporter;
use Filament\Actions\Exports\Models\Export;
class LineExporter extends Exporter
{
protected static ?string $model = Line::class;
public static function getColumns(): array
{
static $rowNumber = 0;
return [
// ExportColumn::make('id')
// ->label('ID'),
ExportColumn::make('no')
->label('NO')
->state(function ($record) use (&$rowNumber) {
// Increment and return the row number
return ++$rowNumber;
}),
ExportColumn::make('plant.name')
->label('PLANT'),
ExportColumn::make('name')
->label('NAME'),
ExportColumn::make('type')
->label('TYPE'),
ExportColumn::make('created_at')
->label('CREATED AT'),
ExportColumn::make('updated_at')
->label('UPDATED AT'),
ExportColumn::make('deleted_at')
->enabledByDefault(false)
->label('DELETED AT'),
];
}
public static function getCompletedNotificationBody(Export $export): string
{
$body = 'Your line export has completed and ' . number_format($export->successful_rows) . ' ' . str('row')->plural($export->successful_rows) . ' exported.';
if ($failedRowsCount = $export->getFailedRowsCount()) {
$body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to export.';
}
return $body;
}
}

View File

@@ -13,11 +13,21 @@ class QualityValidationExporter extends Exporter
public static function getColumns(): array
{
static $rowNumber = 0;
return [
ExportColumn::make('id')
->label('ID'),
// ExportColumn::make('id')
// ->label('ID'),
ExportColumn::make('no')
->label('NO')
->state(function ($record) use (&$rowNumber) {
// Increment and return the row number
return ++$rowNumber;
}),
ExportColumn::make('plant.name')
->label('PLANT'),
ExportColumn::make('line.name')
->label('LINE'),
ExportColumn::make('production_order')
->label('PRODUCTION ORDER'),
ExportColumn::make('serial_number')

View File

@@ -3,6 +3,7 @@
namespace App\Filament\Imports;
use App\Models\Item;
use App\Models\Line;
use App\Models\Plant;
use App\Models\QualityValidation;
use App\Models\StickerMaster;
@@ -36,21 +37,28 @@ class QualityValidationImporter extends Importer
->label('Plant Name')
->relationship(resolveUsing:'name')
->rules(['required']),
ImportColumn::make('sticker_master_id') // stickerMaster.item
ImportColumn::make('line')
->requiredMapping()
->exampleHeader('Line Name')
->example('4 inch pump line')
->label('Line Name')
->relationship(resolveUsing:'name')
->rules(['required']),
ImportColumn::make('sticker_master_id_code') // stickerMaster.item
->requiredMapping()
->exampleHeader('Item Code')
->example('123456')
->label('Item Code')
->relationship(
name: 'stickerMaster',
resolveUsing: function ($state) {
$state = trim($state);
$item = Item::where('code', $state)->first();
return $item
? StickerMaster::where('item_id', $item->id)->value('id')
: null;
}
),
->label('Item Code'),
// ->relationship(
// name: 'stickerMaster',
// resolveUsing: function ($state) {
// $state = trim($state);
// $item = Item::where('code', $state)->first();
// return $item
// ? StickerMaster::where('item_id', $item->id)->value('id')
// : null;
// }
// ),
ImportColumn::make('production_order')
->requiredMapping()
->exampleHeader('Production Order')
@@ -176,16 +184,24 @@ class QualityValidationImporter extends Importer
{
$warnMsg = [];
$plant = Plant::where('name', $this->data['plant'])->first();
$line = null;
$stickMaster = null;
if (!$plant) {
$warnMsg[] = "Plant not found";
}
$uniqueCode = trim($this->data['sticker_master_id']);// stickerMaster.item
$stickMaster = StickerMaster::select('id')->with('item')
else {
$line = Line::where('name', $this->data['line'])->where('plant_id', $plant->id)->first();
$uniqueCode = trim($this->data['sticker_master_id_code']);// stickerMaster.item
$stickMaster = StickerMaster::select('id')->with('item')
->whereHas('item', function ($query) use ($uniqueCode, $plant) {
$query->where('code', $uniqueCode)->where('plant_id', $plant->id);
})->value('id');
}
if (!$line) {
$warnMsg[] = "Line not found";
}
if (!$stickMaster) {
$warnMsg[] = "Sticker item code not found";
}
@@ -197,6 +213,7 @@ class QualityValidationImporter extends Importer
if (!ctype_alnum($this->data['serial_number']) || Str::length($this->data['serial_number']) < 9) {
$warnMsg[] = "Invalid serial number found";
}
// dd($stickMaster);
// if (Str::length($this->data['uom']) < 1) {
// $warnMsg[] = "Invalid unit of measure found";
@@ -261,8 +278,10 @@ class QualityValidationImporter extends Importer
if (!empty($warnMsg)) {
throw new RowImportFailedException(implode(', ', $warnMsg));
}
return QualityValidation::updateOrCreate([
QualityValidation::updateOrCreate([
'plant_id' => $plant->id,
'line_id' => $line->id,
'sticker_master_id' => $stickMaster,//->id
'uom' => $this->data['uom'],
'production_order' => $this->data['production_order'],
@@ -289,6 +308,8 @@ class QualityValidationImporter extends Importer
'updated_at' => $tdateTime->format('Y-m-d H:i:s'),//$this->data['updated_at'],
'operator_id' => $this->data['operator_id'],
]);
return null;
// return QualityValidation::firstOrNew([
// // Update existing records, matching them by `$this->data['column_name']`
// 'email' => $this->data['email'],

View File

@@ -2,10 +2,12 @@
namespace App\Filament\Resources;
use App\Filament\Exports\LineExporter;
use App\Filament\Imports\LineImporter;
use App\Filament\Resources\LineResource\Pages;
use App\Filament\Resources\LineResource\RelationManagers;
use App\Models\Line;
use Filament\Facades\Filament;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Forms\Get;
@@ -16,6 +18,7 @@ use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Filament\Forms\Components\Section;
use Filament\Tables\Actions\ExportAction;
use Illuminate\Validation\Rule;
use Illuminate\Validation\Rules\Unique;
@@ -115,9 +118,44 @@ class LineResource extends Resource
->where('plant_id', $get('plant_id'))
->ignore($get('id')); // Ignore current record during updates
}),
Forms\Components\TextInput::make('type')
// 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'),
Forms\Components\Select::make('type')
->label('Type')
->required()
->placeholder('Scan the valid type')
->options([
'Sub Assembly Serial' => 'Sub Assembly Serial',
'Sub Assembly Lot' => 'Sub Assembly Lot',
'Base FG Line' => 'Base FG Line',
'SFG Line' => 'SFG Line',
'FG Line' => 'FG Line',
'Machining Cell' => 'Machining Cell',
'Blanking Cell' => 'Blanking Cell',
'Forming Cell' => 'Forming Cell',
'Welding Cell' => 'Welding Cell',
'Die-Casting Cell' => 'Die-Casting Cell',
'Brazzing Cell' => 'Brazzing Cell',
])
->searchable()
->reactive()
->afterStateUpdated(function ($state, callable $set, callable $get) {
$lineTyp = $get('type');
@@ -148,29 +186,48 @@ class LineResource extends Resource
{
return $table
->columns([
Tables\Columns\TextColumn::make('id')
->label('ID')
->numeric()
->sortable(),
// Tables\Columns\TextColumn::make('id')
// ->label('ID')
// ->numeric()
// ->sortable(),
Tables\Columns\TextColumn::make('No.')
->label('No.')
->getStateUsing(function ($record, $livewire, $column, $rowLoop) {
$paginator = $livewire->getTableRecords();
$perPage = method_exists($paginator, 'perPage') ? $paginator->perPage() : 10;
$currentPage = method_exists($paginator, 'currentPage') ? $paginator->currentPage() : 1;
return ($currentPage - 1) * $perPage + $rowLoop->iteration;
}),
Tables\Columns\TextColumn::make('name')
->label('Line')
->alignCenter()
->sortable()
->searchable(),
Tables\Columns\TextColumn::make('type')
->label('Type')
->alignCenter()
->sortable()
->searchable(),
Tables\Columns\TextColumn::make('plant.name')
->label('Plant')
->alignCenter()
->sortable()
->searchable(),
Tables\Columns\TextColumn::make('created_at')
->label('Created At')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('updated_at')
->label('Updated At')
->dateTime()
->alignCenter()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('deleted_at')
->label('Deleted At')
->dateTime()
->alignCenter()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
@@ -190,7 +247,15 @@ class LineResource extends Resource
])
->headerActions([
ImportAction::make()
->importer(LineImporter::class),
->importer(LineImporter::class)
->visible(function() {
return Filament::auth()->user()->can('view import line');
}),
ExportAction::make()
->exporter(LineExporter::class)
->visible(function() {
return Filament::auth()->user()->can('view export line');
}),
]);
}

View File

@@ -7,6 +7,7 @@ use App\Filament\Imports\QualityValidationImporter;
use App\Filament\Resources\QualityValidationResource\Pages;
use App\Filament\Resources\QualityValidationResource\RelationManagers;
use App\Models\Item;
use App\Models\Line;
use App\Models\Plant;
use App\Models\QualityValidation;
use App\Models\StickerMaster;
@@ -50,12 +51,62 @@ class QualityValidationResource extends Resource
Forms\Components\Select::make('plant_id')
->relationship('plant', 'name')
->reactive()
->afterStateUpdated(fn (callable $set) => [
$set('item_id', null),
$set('validationError', null),
])
->afterStateUpdated(function (callable $set, callable $get) {
$set('item_id', null);
$set('line_id', null);
$set('production_order', null);
$pId = $get('plant_id');
if (!$pId) {
$set('pqPlantError', 'Please select a plant first.');
} else {
$set('pqPlantError', null);
}
$pId = $get('line_id');
if (!$pId) {
$set('pqLineError', null);
}
})
->required()
->default(fn () => request()->query('plant_id')),
->default(fn () => request()->query('plant_id'))
->extraAttributes(fn ($get) => [
'class' => $get('pqPlantError') ? 'border-red-500' : '',
])
->hint(fn ($get) => $get('pqPlantError') ? $get('pqPlantError') : null)
->hintColor('danger'),
Forms\Components\Select::make('line_id')
->relationship('line', titleAttribute: 'name')
->reactive()
->required()
->options(function (callable $get) {
$plantId = $get('plant_id');
if (!$plantId)
{
return [];
}
return Line::where('plant_id', $plantId)
->where('type', 'FG Line') // Filter by type
->pluck('name', 'id')
->toArray();
})
->afterStateUpdated(function (callable $set, callable $get) {
$set('item_id', null);
$set('production_order', null);
$pId = $get('line_id');
if (!$pId) {
$set('pqLineError', 'Please select a line.');
} else {
$set('pqLineError', null);
}
})
->extraAttributes(fn ($get) => [
'class' => $get('pqLineError') ? 'border-red-500' : '',
])
->hint(fn ($get) => $get('pqLineError') ? $get('pqLineError') : null)
->hintColor('danger'),
Forms\Components\Hidden::make('sticker_master_id')
// ->relationship('stickerMaster', 'id')
->required(),
@@ -111,6 +162,23 @@ class QualityValidationResource extends Resource
->live()
->afterStateUpdated(function (callable $set, callable $get, ?string $state) {
$pId = $get('line_id');
if (!$pId) {
$set('pqLineError', 'Please select a line.');
} else {
$set('pqLineError', null);
}
$pOrder = $get('production_order');
if (!$pOrder)
{
$set('productionError', 'Production Order cant be empty.');
}
else
{
$set('productionError', null);
}
$serialFields = [
'serial_number_motor_qr', 'serial_number_pump_qr', 'serial_number_pumpset_qr', 'pack_slip_motor_qr', 'pack_slip_pump_qr', 'pack_slip_pumpset_qr', 'name_plate_motor_qr', 'name_plate_pump_qr', 'name_plate_pumpset_qr', 'tube_sticker_motor_qr', 'tube_sticker_pump_qr', 'tube_sticker_pumpset_qr', 'warranty_card_qr'
];
@@ -1894,21 +1962,37 @@ class QualityValidationResource extends Resource
return $table
->query(QualityValidation::query())
->columns([
Tables\Columns\TextColumn::make('id')
->label('ID')
->numeric()
->sortable(),
// Tables\Columns\TextColumn::make('id')
// ->label('ID')
// ->numeric()
// ->sortable(),
Tables\Columns\TextColumn::make('No.')
->label('No.')
->getStateUsing(function ($record, $livewire, $column, $rowLoop) {
$paginator = $livewire->getTableRecords();
$perPage = method_exists($paginator, 'perPage') ? $paginator->perPage() : 10;
$currentPage = method_exists($paginator, 'currentPage') ? $paginator->currentPage() : 1;
return ($currentPage - 1) * $perPage + $rowLoop->iteration;
}),
Tables\Columns\TextColumn::make('plant.name')
->label('Plant')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('line.name')
->label('Line')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('production_order')
->label('Production Order')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('serial_number')
->label('Serial Number')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('stickerMaster.item.code')
->label('Item Code')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('uom')
->label('Unit of Measure')
@@ -1992,20 +2076,23 @@ class QualityValidationResource extends Resource
->sortable(),
Tables\Columns\TextColumn::make('sap_msg_description')
->label('SAP Message Description')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('created_at')
->label('Created At')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('updated_at')
->label('Updated At')
->dateTime()
->alignCenter()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('deleted_at')
->label('Deleted At')
->dateTime()
->alignCenter()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
@@ -2027,6 +2114,26 @@ class QualityValidationResource extends Resource
$set('sticker_master_id', null);
$set('sap_msg_status', null);
}),
Select::make('Line')
->label('Select Line')
->nullable()
->options(function (callable $get) {
$plantId = $get('Plant');
if (!$plantId)
{
return [];
}
return Line::where('plant_id', $plantId)
->where('type', 'FG Line') // Filter by type
->pluck('name', 'id')
->toArray();
})
->reactive()
->afterStateUpdated(function ($state, callable $set, callable $get) {
$set('sticker_master_id', null);
$set('sap_msg_status', null);
}),
TextInput::make('production_order')
->label('Production Order')
->placeholder('Enter Production Order'),
@@ -2083,6 +2190,10 @@ class QualityValidationResource extends Resource
$query->where('plant_id', $data['Plant']);
}
if (!empty($data['Line'])) {
$query->where('line_id', $data['Line']);
}
if (!empty($data['production_order'])) {
$query->where('production_order', 'like', '%' . $data['production_order'] . '%');
}
@@ -2120,6 +2231,10 @@ class QualityValidationResource extends Resource
$indicators[] = 'Plant: ' . Plant::where('id', $data['Plant'])->value('name');
}
if (!empty($data['Line'])) {
$indicators[] = 'Line: ' . Line::where('id', $data['Line'])->value('name');
}
if (!empty($data['production_order'])) {
$indicators[] = 'Production Order: ' . $data['production_order'];
}

View File

@@ -3,6 +3,8 @@
namespace App\Filament\Widgets;
use App\Models\Line;
use App\Models\ProductionQuantity;
use App\Models\QualityValidation;
use Filament\Widgets\ChartWidget;
class CumulativeChart extends ChartWidget
@@ -15,13 +17,77 @@ class CumulativeChart extends ChartWidget
protected int|string|array $columnSpan = 12;
// protected function getData(): array
// {
// $selectedPlant = session('selected_plant');
// $activeFilter = $this->filter;
// // Define date range based on filter
// switch ($activeFilter) {
// case 'yesterday':
// $startDate = now()->subDay()->startOfDay();
// $endDate = now()->subDay()->endOfDay();
// break;
// case 'this_week':
// $startDate = now()->startOfWeek();
// $endDate = now()->endOfWeek();
// break;
// case 'this_month':
// $startDate = now()->startOfMonth();
// $endDate = now()->endOfMonth();
// break;
// default: // today
// $startDate = now()->startOfDay();
// $endDate = now()->endOfDay();
// break;
// }
// // Get all lines for selected plant
// $lines = Line::where('plant_id', $selectedPlant)
// ->pluck('name', 'id')
// ->toArray();
// // Get total production per line in the date range
// $production = \DB::table('production_quantities')
// ->select('line_id', \DB::raw('COUNT(*) as total_quantity'))
// ->whereBetween('created_at', [$startDate, $endDate])
// ->whereIn('line_id', array_keys($lines))
// ->groupBy('line_id')
// ->pluck('total_quantity', 'line_id')
// ->toArray();
// // Match quantities with lines (fill 0 if missing)
// $labels = [];
// $data = [];
// foreach ($lines as $lineId => $lineName) {
// $labels[] = $lineName;
// $data[] = $production[$lineId] ?? 0;
// }
// return [
// 'labels' => $labels,
// 'datasets' => [
// [
// 'label' => match ($activeFilter) {
// 'yesterday' => "Production Quantity (Yesterday)",
// 'this_week' => "Daily Production This Week",
// 'this_month' => "Weekly Production This Month",
// default => "Today's Production",
// },
// 'data' => $data,
// ],
// ],
// ];
// }
protected function getData(): array
{
$selectedPlant = session('selected_plant');
$activeFilter = $this->filter;
// Define date range based on filter
switch ($activeFilter) {
// Define date range
switch ($activeFilter)
{
case 'yesterday':
$startDate = now()->subDay()->startOfDay();
$endDate = now()->subDay()->endOfDay();
@@ -40,46 +106,90 @@ class CumulativeChart extends ChartWidget
break;
}
// Get all lines for selected plant
$lines = Line::where('plant_id', $selectedPlant)
->pluck('name', 'id')
->toArray();
// Get lines with names and types
$lines = Line::where('plant_id', $selectedPlant)->get(['id', 'name', 'type']);
// Get total production per line in the date range
$production = \DB::table('production_quantities')
->select('line_id', \DB::raw('COUNT(*) as total_quantity'))
$lineNames = [];
$fgLineIds = [];
$nonFgLineIds = [];
foreach ($lines as $line)
{
$lineNames[$line->id] = $line->name;
if ($line->type == 'FG Line')
{
$fgLineIds[] = $line->id;
}
else
{
$nonFgLineIds[] = $line->id;
}
}
//FG production from quality_validations
$fgProduction = QualityValidation::select('line_id', \DB::raw('COUNT(*) as total_quantity'))
->whereBetween('created_at', [$startDate, $endDate])
->whereIn('line_id', array_keys($lines))
->whereIn('line_id', $fgLineIds)
->groupBy('line_id')
->pluck('total_quantity', 'line_id')
->toArray();
// Match quantities with lines (fill 0 if missing)
$labels = [];
$data = [];
//Non-FG production from production_quantities
$nonFgProduction = ProductionQuantity::select('line_id', \DB::raw('COUNT(*) as total_quantity'))
->whereBetween('created_at', [$startDate, $endDate])
->whereIn('line_id', $nonFgLineIds)
->groupBy('line_id')
->pluck('total_quantity', 'line_id')
->toArray();
foreach ($lines as $lineId => $lineName) {
//Separate FG and non-FG into different datasets
$labels = [];
$fgData = [];
$nonFgData = [];
foreach ($lineNames as $lineId => $lineName) {
$labels[] = $lineName;
$data[] = $production[$lineId] ?? 0;
if (in_array($lineId, $fgLineIds))
{
$fgData[] = $fgProduction[$lineId] ?? 0;
$nonFgData[] = null;
}
else
{
$nonFgData[] = $nonFgProduction[$lineId] ?? 0;
$fgData[] = null;
}
}
return [
'labels' => $labels,
'datasets' => [
'datasets' => array_filter([
[
'label' => match ($activeFilter) {
'yesterday' => "Production Quantity (Yesterday)",
'this_week' => "Daily Production This Week",
'this_month' => "Weekly Production This Month",
default => "Today's Production",
},
'data' => $data,
},
'data' => $nonFgData,
//'backgroundColor' => '#3b82f6', // Blue for non-FG
],
],
[
'label' => match ($activeFilter) {
'yesterday' => "FG Count (Yesterday)",
'this_week' => "FG Count This Week",
'this_month' => "FG Count This Month",
default => "Today's FG Count",
},
'data' => $fgData,
// 'backgroundColor' => '#ef4444', // Red for FG
],
]),
];
}
protected function getType(): string
{
return 'bar';
@@ -106,7 +216,6 @@ class CumulativeChart extends ChartWidget
],
],
],
];
}

View File

@@ -34,129 +34,96 @@ class ItemOverview extends ChartWidget
];
}
if ($activeFilter === 'yesterday') {
$startDate = now()->subDay()->setTime(8, 0, 0); // Yesterday 8:00 AM
$endDate = now()->setTime(8, 0, 0); // Today 8:00 AM
$groupBy = 'EXTRACT(HOUR FROM production_quantities.created_at)';
}
// Determine if line is FG Line
$line = \App\Models\Line::find($selectedLine);
$isFgLine = $line?->type == 'FG Line';
else if ($activeFilter === 'this_week') {
// Monday 8:00 AM of the current week
// Set date range and groupBy logic
if ($activeFilter == 'yesterday')
{
$startDate = now()->subDay()->setTime(8, 0, 0);
$endDate = now()->setTime(8, 0, 0);
$groupBy = 'EXTRACT(HOUR FROM created_at)';
}
elseif ($activeFilter == 'this_week')
{
$startDate = now()->startOfWeek()->setTime(8, 0, 0);
$endDate = now()->endOfWeek()->addDay()->setTime(8, 0, 0);
$groupBy = 'EXTRACT(DOW FROM production_quantities.created_at)'; // Group by day of week
$groupBy = 'EXTRACT(DOW FROM created_at)';
}
else if ($activeFilter === 'this_month') {
elseif ($activeFilter == 'this_month')
{
$startDate = now()->startOfMonth();
$endDate = now()->endOfMonth();
$groupBy = "FLOOR((EXTRACT(DAY FROM production_quantities.created_at) - 1) / 7) + 1";
$groupBy = "FLOOR((EXTRACT(DAY FROM created_at) - 1) / 7) + 1";
}
else
{
$startDate = now()->setTime(8, 0, 0); // today at 8:00 AM
$endDate = now()->copy()->addDay()->setTime(8, 0, 0); // tomorrow at 8:00 AM
$groupBy = 'EXTRACT(HOUR FROM production_quantities.created_at)';
$startDate = now()->setTime(8, 0, 0);
$endDate = now()->copy()->addDay()->setTime(8, 0, 0);
$groupBy = 'EXTRACT(HOUR FROM created_at)';
}
$query = \DB::table('production_quantities')
->join('plants', 'production_quantities.plant_id', '=', 'plants.id') //inner join
->join('lines', 'production_quantities.line_id', '=', 'lines.id')
->selectRaw("$groupBy AS time_unit, count(*) AS total_quantity")
//->whereBetween('production_quantities.created_at', [$startDate, $endDate])
->where('production_quantities.created_at', '>=', $startDate) // $startDate should be >=
->where('production_quantities.created_at', '<', $endDate) // $endDate should be <
->when($selectedPlant, function ($q) use ($selectedPlant) {
return $q->where('plants.id', $selectedPlant);
})
->when($selectedLine, function ($q) use ($selectedLine) {
return $q->where('lines.id', $selectedLine);
})
$baseTable = $isFgLine ? 'quality_validations' : 'production_quantities';
->groupByRaw($groupBy)
->orderByRaw($groupBy)
->pluck('total_quantity', 'time_unit')
->toArray();
$query = \DB::table($baseTable)
->selectRaw("$groupBy AS time_unit, COUNT(*) AS total_quantity")
->where('created_at', '>=', $startDate)
->where('created_at', '<', $endDate)
->where('plant_id', $selectedPlant)
->where('line_id', $selectedLine)
->groupByRaw($groupBy)
->orderByRaw($groupBy)
->pluck('total_quantity', 'time_unit')
->toArray();
if ($activeFilter == 'this_month')
{
$weeksCount = ceil($endDate->day / 7);
$allWeeks = array_fill(1, $weeksCount, 0);
$data = array_replace($allWeeks, $query);
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
// Generate dynamic week labels
$labels = [];
for ($i = 1; $i <= $weeksCount; $i++) {
$weekStart = $startDate->copy()->addDays(($i - 1) * 7)->format('d M');
$weekEnd = $startDate->copy()->addDays($i * 7 - 1)->min($endDate)->format('d M');
$labels[] = "Week $i ($weekStart - $weekEnd)";
}
$orderedData = array_values($data);
$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)";
}
else if ($activeFilter === 'this_week') {
// Correct week labels: ['Mon', 'Tue', ..., 'Sun']
$labels = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
// Initialize default data for all 7 days
$data = array_fill(0, 7, 0);
// Fill in data from query results
foreach ($query as $dow => $count) {
$data[$dow] = $count;
}
// 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)
];
$orderedData = array_values($data);
}
elseif ($activeFilter == 'this_week')
{
$labels = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
$data = array_fill(0, 7, 0);
foreach ($query as $dow => $count) {
$data[$dow] = $count;
}
else if($activeFilter === 'yesterday')
{
// 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, 7));
$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);
$orderedData = [
$data[1] ?? 0, $data[2] ?? 0, $data[3] ?? 0,
$data[4] ?? 0, $data[5] ?? 0, $data[6] ?? 0,
$data[0] ?? 0,
];
}
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, 7));
$orderedData = array_map(fn($hour) => $data[$hour], $shiftedKeys);
// Labels: ["8 AM", "9 AM", ..., "7 AM"]
$labels = array_map(fn ($hour) => date("g A", strtotime("$hour:00")), $shiftedKeys);
}
return [
'datasets' => [
[
'label' => match ($activeFilter) {
'this_week' => "Daily Production This Week",
'this_month' => "Weekly Production This Month", // Updated Label
'yesterday' => "Yesterday's Hourly Production",
default => "Today's Hourly Production",
'this_week' => $isFgLine ? 'Daily FG Count This Week' : 'Daily Production This Week',
'this_month' => $isFgLine ? 'Weekly FG Count This Month' : 'Weekly Production This Month',
'yesterday' => $isFgLine ? "Yesterday's FG Count" : "Yesterday's Hourly Production",
default => $isFgLine ? "Today's FG Count" : "Today's Hourly Production",
},
'data' => $orderedData,
'interaction' => [
@@ -195,32 +162,6 @@ class ItemOverview extends ChartWidget
}
// protected function getOptions(): array
// {
// return [
// 'plugins' => [
// 'datalabels' => [
// 'color' => '#3490dc',
// 'font' => [
// 'weight' => 'bold',
// 'size' => 14,
// ],
// 'backgroundColor' => 'rgba(255,255,255,0.8)',
// 'borderRadius' => 4,
// 'formatter' => \Illuminate\Support\Js::from(
// new Js('function(value, context) {
// if (Number(value) === 0) {
// return null;
// }
// return "Count: " + value;
// }')
// ),
// ]
// ]
// ];
// }
protected function getFilters(): ?array
{
return [

View File

@@ -13,6 +13,7 @@ class QualityValidation extends Model
protected $fillable = [
'sticker_master_id',
'plant_id',
'line_id',
'production_order',
'serial_number_motor',
'serial_number_pump',
@@ -48,4 +49,9 @@ class QualityValidation extends Model
{
return $this->belongsTo(Plant::class);
}
public function line(): BelongsTo
{
return $this->belongsTo(Line::class);
}
}