25 Commits

Author SHA1 Message Date
dhanabalan
9a2a6bdd9b Add device master policy file 2025-07-31 16:21:14 +05:30
dhanabalan
0a414a6804 Added device master resource file 2025-07-31 16:18:25 +05:30
dhanabalan
f4bb7a7a78 Added device master model file 2025-07-31 16:17:35 +05:30
dhanabalan
8aad6cf1e6 Add device master migration file 2025-07-31 16:14:47 +05:30
dhanabalan
3b18411141 Added logic for invoice report for daily report 2025-07-31 15:00:03 +05:30
dhanabalan
162eaa0c9c added unwanted line 2025-07-31 13:59:14 +05:30
dhanabalan
d5f55fbf98 added commented line for git checking 2025-07-31 13:58:18 +05:30
dhanabalan
cf5cfac555 Removed unwanted lines for production send report 2025-07-31 13:53:41 +05:30
dhanabalan
7bf2e8182b Updated QR validation functionality to allow with and without item code 2025-07-31 12:26:16 +05:30
dhanabalan
216b62f8bf Added notification for missing invoice type in filter options 2025-07-31 12:22:23 +05:30
dhanabalan
cad7f19ab5 Added invoice_type radio filter and scanned_status select filter to Invoice Validation 2025-07-31 08:53:40 +05:30
dhanabalan
ca9695c922 Added operator_id and scanned_status filter fields to Invoice validaitons resources and Alignment changed in filter option for Production Quantity / Quality Validation 2025-07-30 15:18:26 +05:30
dhanabalan
d1f9a3176f Added operator_id field to ProductionQuantity and QualityValidation in report filter 2025-07-30 12:32:17 +05:30
dhanabalan
0b9d0f9995 modified size of the qr code of scan pallet 2025-07-29 18:02:42 +05:30
dhanabalan
897aa77217 Modified qr code size for pallet 2025-07-29 15:52:44 +05:30
dhanabalan
000533ef7c Added scan pallet print pdf 2025-07-29 15:36:29 +05:30
dhanabalan
a78cb75bdd Added reprint for scan pallet 2025-07-29 13:56:30 +05:30
dhanabalan
ab769d2287 Added 2 copies of pallet number print for scan pallet 2025-07-29 13:26:13 +05:30
dhanabalan
0bde54cf1a removed logic against the production order 2025-07-29 11:47:26 +05:30
dhanabalan
48942307e1 modified sticker reprint controller logic 2025-07-29 11:46:44 +05:30
dhanabalan
8c5f2b5b39 commented production order text input box as mandatory 2025-07-29 11:35:13 +05:30
dhanabalan
b1df9f8b87 Added production sticker reprint page 2025-07-29 11:33:28 +05:30
dhanabalan
c0d13db2f3 Added created_at, updated_at, email while data response with roles 2025-07-28 18:33:15 +05:30
dhanabalan
b4bf170c89 Added kiosk for scan pallet 2025-07-28 18:10:54 +05:30
dhanabalan
b0d2132e25 Refactor QR code PDF generation to improve layout and add automatic print functionality 2025-07-28 18:01:50 +05:30
20 changed files with 2894 additions and 471 deletions

View File

@@ -280,8 +280,8 @@ class SendInvoiceReport extends Command
$mailRules = \App\Models\AlertMailRule::where('module', 'InvoiceValidation')->get()->groupBy('rule_name'); $mailRules = \App\Models\AlertMailRule::where('module', 'InvoiceValidation')->get()->groupBy('rule_name');
$startDate = now()->setTime(8, 0, 0); // $startDate = now()->setTime(8, 0, 0);
$endDate = now()->copy()->addDay()->setTime(8, 0, 0); // $endDate = now()->copy()->addDay()->setTime(8, 0, 0);
$serialTableData = []; $serialTableData = [];
$materialTableData = []; $materialTableData = [];
@@ -293,6 +293,16 @@ class SendInvoiceReport extends Command
: [$plantIdArg]; : [$plantIdArg];
$no = 1; $no = 1;
if (strtolower($schedule) == 'daily')
{
$startDate = now()->subDay()->setTime(8, 0, 0);
$endDate = now()->setTime(8, 0, 0);
}
else
{
$startDate = now()->setTime(8, 0, 0);
$endDate = now()->copy()->addDay()->setTime(8, 0, 0);
}
foreach ($plantIds as $plantId) { foreach ($plantIds as $plantId) {
$plant = Plant::find($plantId); $plant = Plant::find($plantId);
$plantName = $plant ? $plant->name : $plantId; $plantName = $plant ? $plant->name : $plantId;

View File

@@ -193,6 +193,9 @@ class SendProductionReport extends Command
// ]; // ];
// } // }
// } // }
//..
//.
foreach ($plants as $plant) foreach ($plants as $plant)
{ {
@@ -204,7 +207,7 @@ class SendProductionReport extends Command
->whereBetween('created_at', [$PlanstartDate, $planendDate]) ->whereBetween('created_at', [$PlanstartDate, $planendDate])
->sum('plan_quantity'); ->sum('plan_quantity');
if (strtolower($line->type) === 'fg line') { if (strtolower($line->type) == 'fg line') {
$productionQuantity = \App\Models\QualityValidation::where('plant_id', $plant->id) $productionQuantity = \App\Models\QualityValidation::where('plant_id', $plant->id)
->where('line_id', $line->id) ->where('line_id', $line->id)
->whereBetween('created_at', [$startDate, $endDate]) ->whereBetween('created_at', [$startDate, $endDate])

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,131 @@
<?php
namespace App\Filament\Resources;
use App\Filament\Resources\DeviceMasterResource\Pages;
use App\Filament\Resources\DeviceMasterResource\RelationManagers;
use App\Models\DeviceMaster;
use Filament\Facades\Filament;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Filament\Forms\Components\Section;
class DeviceMasterResource extends Resource
{
protected static ?string $model = DeviceMaster::class;
protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
protected static ?string $navigationGroup = 'Power House';
public static function form(Form $form): Form
{
return $form
->schema([
Section::make('')
->schema([
Forms\Components\Select::make('plant_id')
->label('Plant')
->relationship('plant', 'name')
->required(),
Forms\Components\TextInput::make('name')
->label('Device Name')
->required(),
Forms\Components\TextInput::make('mac_address')
->label('MAC Address'),
Forms\Components\TextInput::make('ip_address')
->label('IP Address'),
Forms\Components\Hidden::make('created_by')
->default(Filament::auth()->user()?->name),
])
->columns(4),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('id')
->label('ID')
->numeric()
->sortable(),
Tables\Columns\TextColumn::make('plant.name')
->label('Plant')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('name')
->label('Device Name')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('mac_address')
->label('MAC Address')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('ip_address')
->label('IP Address')
->alignCenter()
->sortable(),
Tables\Columns\TextColumn::make('created_at')
->label('Created At')
->alignCenter()
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('updated_at')
->label('Updated At')
->alignCenter()
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('deleted_at')
->dateTime()
->alignCenter()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
Tables\Filters\TrashedFilter::make(),
])
->actions([
Tables\Actions\ViewAction::make(),
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
Tables\Actions\ForceDeleteBulkAction::make(),
Tables\Actions\RestoreBulkAction::make(),
]),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListDeviceMasters::route('/'),
'create' => Pages\CreateDeviceMaster::route('/create'),
'view' => Pages\ViewDeviceMaster::route('/{record}'),
'edit' => Pages\EditDeviceMaster::route('/{record}/edit'),
];
}
public static function getEloquentQuery(): Builder
{
return parent::getEloquentQuery()
->withoutGlobalScopes([
SoftDeletingScope::class,
]);
}
}

View File

@@ -0,0 +1,12 @@
<?php
namespace App\Filament\Resources\DeviceMasterResource\Pages;
use App\Filament\Resources\DeviceMasterResource;
use Filament\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateDeviceMaster extends CreateRecord
{
protected static string $resource = DeviceMasterResource::class;
}

View File

@@ -0,0 +1,22 @@
<?php
namespace App\Filament\Resources\DeviceMasterResource\Pages;
use App\Filament\Resources\DeviceMasterResource;
use Filament\Actions;
use Filament\Resources\Pages\EditRecord;
class EditDeviceMaster extends EditRecord
{
protected static string $resource = DeviceMasterResource::class;
protected function getHeaderActions(): array
{
return [
Actions\ViewAction::make(),
Actions\DeleteAction::make(),
Actions\ForceDeleteAction::make(),
Actions\RestoreAction::make(),
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\DeviceMasterResource\Pages;
use App\Filament\Resources\DeviceMasterResource;
use Filament\Actions;
use Filament\Resources\Pages\ListRecords;
class ListDeviceMasters extends ListRecords
{
protected static string $resource = DeviceMasterResource::class;
protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),
];
}
}

View File

@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\DeviceMasterResource\Pages;
use App\Filament\Resources\DeviceMasterResource;
use Filament\Actions;
use Filament\Resources\Pages\ViewRecord;
class ViewDeviceMaster extends ViewRecord
{
protected static string $resource = DeviceMasterResource::class;
protected function getHeaderActions(): array
{
return [
Actions\EditAction::make(),
];
}
}

View File

@@ -17,6 +17,7 @@ use Filament\Forms;
use Filament\Forms\Components\Actions\Action as ActionsAction; use Filament\Forms\Components\Actions\Action as ActionsAction;
use Filament\Forms\Components\DateTimePicker; use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\FileUpload; use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\Radio;
use Filament\Forms\Components\Section; use Filament\Forms\Components\Section;
use Filament\Forms\Components\Select; use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput; use Filament\Forms\Components\TextInput;
@@ -929,6 +930,16 @@ class InvoiceValidationResource extends Resource
Filter::make('advanced_filters') Filter::make('advanced_filters')
->label('Advanced Filters') ->label('Advanced Filters')
->form([ ->form([
Radio::make('invoice_type')
->label('Type ?')
->boolean()
->options([
'Serial' => 'Serial',
'Material' => 'Material'
])
->default('Serial')
->inlineLabel(false)
->inline(),
Select::make('Plant') Select::make('Plant')
->label('Select Plant') ->label('Select Plant')
->nullable() ->nullable()
@@ -938,6 +949,7 @@ class InvoiceValidationResource extends Resource
->reactive() ->reactive()
->afterStateUpdated(function ($state, callable $set, callable $get): void { ->afterStateUpdated(function ($state, callable $set, callable $get): void {
$set('sticker_master_id', null); $set('sticker_master_id', null);
$set('operator_id', null);
}), }),
TextInput::make('invoice_number') TextInput::make('invoice_number')
->label('Invoice Number') ->label('Invoice Number')
@@ -962,6 +974,31 @@ class InvoiceValidationResource extends Resource
}) })
->searchable() ->searchable()
->reactive(), ->reactive(),
Select::make('scanned_status')
->label('Scanned Status')
->nullable()
->options([
'Scanned' => 'Scanned',
'Pending' => 'Pending',
])
->searchable()
->reactive(),
Select::make('operator_id')
->label('Created By')
->nullable()
->options(function (callable $get) {
$plantId = $get('Plant');
if (!$plantId)
{
return InvoiceValidation::whereNotNull('operator_id')->select('operator_id')->distinct()->pluck('operator_id', 'operator_id');
}
else
{
return InvoiceValidation::where('plant_id', $plantId)->whereNotNull('operator_id')->select('operator_id')->distinct()->pluck('operator_id', 'operator_id');
}
})
->searchable()
->reactive(),
DateTimePicker::make(name: 'created_from') DateTimePicker::make(name: 'created_from')
->label('Created From') ->label('Created From')
->placeholder(placeholder: 'Select From DateTime') ->placeholder(placeholder: 'Select From DateTime')
@@ -975,10 +1012,46 @@ class InvoiceValidationResource extends Resource
]) ])
->query(function ($query, array $data) { ->query(function ($query, array $data) {
// Hide all records initially if no filters are applied // Hide all records initially if no filters are applied
if (empty($data['Plant']) && empty($data['invoice_number']) && empty($data['serial_number']) && empty($data['created_from']) && empty($data['created_to']) && empty($data['sticker_master_id'])) { if (empty($data['invoice_type']) || (empty($data['Plant']) && empty($data['invoice_number']) && empty($data['serial_number']) && empty($data['created_from']) && empty($data['created_to']) && empty($data['operator_id']) && empty($data['scanned_status']) && empty($data['sticker_master_id']))) {
if(empty($data['invoice_type']))
{
Notification::make()
->title('Please, choose invoice type to filter.')
->danger()
->send();
}
return $query->whereRaw('1 = 0'); return $query->whereRaw('1 = 0');
} }
if ($data['invoice_type'] == 'Serial') {
$query->whereNull('quantity');
if (!empty($data['scanned_status'])) {
if ($data['scanned_status'] == 'Scanned') {
$query->whereNotNull('scanned_status')->where('scanned_status', '!=', '');
} elseif ($data['scanned_status'] == 'Pending') {
//$query->whereNull('scanned_status')->orWhere('scanned_status', '');
$query->where(function ($query) use ($data) {
// if (empty($data['scanned_status']) || $data['scanned_status'] == 'Pending') {
$query->whereNull('scanned_status')->orWhere('scanned_status', '!=', 'Scanned');
// }
});
}
}
} elseif ($data['invoice_type'] == 'Material') {
$query->whereNotNull('quantity');//->where('quantity', '>', 0)
if (!empty($data['scanned_status'])) {
if ($data['scanned_status'] == 'Scanned') {
$query->whereNotNull('serial_number')->where('serial_number', '!=', '');
} elseif ($data['scanned_status'] == 'Pending') {
$query->where(function ($query) use ($data) {
$query->whereNull('serial_number')->orWhere('serial_number', '=', '');
});
}
}
}
if (!empty($data['Plant'])) { //$plant = $data['Plant'] ?? null if (!empty($data['Plant'])) { //$plant = $data['Plant'] ?? null
$query->where('plant_id', $data['Plant']); $query->where('plant_id', $data['Plant']);
} }
@@ -999,6 +1072,10 @@ class InvoiceValidationResource extends Resource
$query->where('created_at', '<=', $data['created_to']); $query->where('created_at', '<=', $data['created_to']);
} }
if (!empty($data['operator_id'])) {
$query->where('operator_id', $data['operator_id']);
}
if (!empty($data['sticker_master_id'])) { if (!empty($data['sticker_master_id'])) {
$stickerMasterIds = StickerMaster::where('item_id', $data['sticker_master_id']) $stickerMasterIds = StickerMaster::where('item_id', $data['sticker_master_id'])
->pluck('id') ->pluck('id')
@@ -1024,6 +1101,15 @@ class InvoiceValidationResource extends Resource
$indicators[] = 'Serial Number: ' . $data['serial_number']; $indicators[] = 'Serial Number: ' . $data['serial_number'];
} }
if (!empty($data['sticker_master_id'])) {
$itemCode = Item::find($data['sticker_master_id'])->code ?? 'Unknown';
$indicators[] = 'Item Code: ' . $itemCode;
}
if (!empty($data['operator_id'])) {
$indicators[] = 'Created By: ' . $data['operator_id'];
}
if (!empty($data['created_from'])) { if (!empty($data['created_from'])) {
$indicators[] = 'From: ' . $data['created_from']; $indicators[] = 'From: ' . $data['created_from'];
} }
@@ -1032,9 +1118,8 @@ class InvoiceValidationResource extends Resource
$indicators[] = 'To: ' . $data['created_to']; $indicators[] = 'To: ' . $data['created_to'];
} }
if (!empty($data['sticker_master_id'])) { if (!empty($data['scanned_status'])) {
$itemCode = Item::find($data['sticker_master_id'])->code ?? 'Unknown'; $indicators[] = 'Scanned Status: ' . $data['scanned_status'];
$indicators[] = 'Item Code: ' . $itemCode;
} }
return $indicators; return $indicators;

View File

@@ -521,7 +521,7 @@ class PalletValidationResource extends Resource
]) ])
->action(function (array $data) { ->action(function (array $data) {
$selectedPalletNumber = $data['pallet_list']; $selectedPalletNumber = $data['pallet_list'];
return redirect()->route('download-qr-pdf', ['palletNo' => $selectedPalletNumber]); return redirect()->route('download-reprint-qr-pdf', ['palletNo' => $selectedPalletNumber]);
}) })
->visible(function() { ->visible(function() {

View File

@@ -1035,6 +1035,7 @@ class ProductionQuantityResource extends Resource
$set('Shift', null); $set('Shift', null);
$set('Item', null); $set('Item', null);
$set('sap_msg_status', null); $set('sap_msg_status', null);
$set('operator_id', null);
}), }),
//line //line
@@ -1050,7 +1051,10 @@ class ProductionQuantityResource extends Resource
return Line::where('plant_id', $plantId) return Line::where('plant_id', $plantId)
->pluck('name', 'id'); ->pluck('name', 'id');
}) })
->reactive(), ->reactive()
->afterStateUpdated(function ($state, callable $set, callable $get) {
$set('operator_id', null);
}),
//block //block
Select::make('Block') Select::make('Block')
@@ -1067,6 +1071,7 @@ class ProductionQuantityResource extends Resource
->reactive() ->reactive()
->afterStateUpdated(function ($state, callable $set, callable $get) { ->afterStateUpdated(function ($state, callable $set, callable $get) {
$set('Shift', null); $set('Shift', null);
$set('operator_id', null);
}), }),
//shift //shift
@@ -1085,7 +1090,10 @@ class ProductionQuantityResource extends Resource
->where('block_id', $blockId) ->where('block_id', $blockId)
->pluck('name', 'id'); ->pluck('name', 'id');
}) })
->reactive(), ->reactive()
->afterStateUpdated(function ($state, callable $set, callable $get) {
$set('operator_id', null);
}),
TextInput::make('production_order') TextInput::make('production_order')
->label('Production Order') ->label('Production Order')
@@ -1133,6 +1141,37 @@ class ProductionQuantityResource extends Resource
// ->options(QualityValidation::whereNotNull('sap_msg_status')->select('sap_msg_status')->distinct()->pluck('sap_msg_status', 'sap_msg_status')) // ->options(QualityValidation::whereNotNull('sap_msg_status')->select('sap_msg_status')->distinct()->pluck('sap_msg_status', 'sap_msg_status'))
->reactive(), ->reactive(),
Select::make('operator_id')
->label('Created By')
->nullable()
->options(function (callable $get) {
$plantId = $get('Plant');
$lineId = $get('Line');
$shiftId = $get('Shift');
if (!$plantId && !$lineId && !$shiftId)
{
return ProductionQuantity::whereNotNull('operator_id')->select('operator_id')->distinct()->pluck('operator_id', 'operator_id');
}
else if ($plantId && !$lineId && !$shiftId)
{
return ProductionQuantity::where('plant_id', $plantId)->whereNotNull('operator_id')->select('operator_id')->distinct()->pluck('operator_id', 'operator_id');
}
else if ($plantId && $lineId && !$shiftId)
{
return ProductionQuantity::where('plant_id', $plantId)->where('line_id', $lineId)->whereNotNull('operator_id')->select('operator_id')->distinct()->pluck('operator_id', 'operator_id');
}
else if ($plantId && !$lineId && $shiftId)
{
return ProductionQuantity::where('plant_id', $plantId)->where('shift_id', $shiftId)->whereNotNull('operator_id')->select('operator_id')->distinct()->pluck('operator_id', 'operator_id');
}
else// if ($plantId && $lineId && $shiftId)
{
return ProductionQuantity::where('plant_id', $plantId)->where('line_id', $lineId)->where('shift_id', $shiftId)->whereNotNull('operator_id')->select('operator_id')->distinct()->pluck('operator_id', 'operator_id');
}
})
->searchable()
->reactive(),
DateTimePicker::make(name: 'created_from') DateTimePicker::make(name: 'created_from')
->label('Created From') ->label('Created From')
->placeholder(placeholder: 'Select From DateTime') ->placeholder(placeholder: 'Select From DateTime')
@@ -1146,7 +1185,7 @@ class ProductionQuantityResource extends Resource
->native(false), ->native(false),
]) ])
->query(function ($query, array $data) { ->query(function ($query, array $data) {
if (empty($data['Plant']) && empty($data['Shift']) && empty($data['Line']) && empty($data['production_order']) && empty($data['serial_number']) && empty($data['Item']) && empty($data['sap_msg_status']) && empty($data['created_from']) && empty($data['created_to'])) { if (empty($data['Plant']) && empty($data['Shift']) && empty($data['Line']) && empty($data['production_order']) && empty($data['serial_number']) && empty($data['Item']) && empty($data['operator_id']) && empty($data['sap_msg_status']) && empty($data['created_from']) && empty($data['created_to'])) {
return $query->whereRaw('1 = 0'); return $query->whereRaw('1 = 0');
} }
@@ -1178,6 +1217,10 @@ class ProductionQuantityResource extends Resource
$query->where('sap_msg_status', $data['sap_msg_status']); $query->where('sap_msg_status', $data['sap_msg_status']);
} }
if (!empty($data['operator_id'])) {
$query->where('operator_id', $data['operator_id']);
}
if ($from = $data['created_from'] ?? null) { if ($from = $data['created_from'] ?? null) {
$query->where('created_at', '>=', $from); $query->where('created_at', '>=', $from);
} }
@@ -1185,6 +1228,7 @@ class ProductionQuantityResource extends Resource
if ($to = $data['created_to'] ?? null) { if ($to = $data['created_to'] ?? null) {
$query->where('created_at', '<=', $to); $query->where('created_at', '<=', $to);
} }
// return $query; // return $query;
}) })
->indicateUsing(function (array $data) { ->indicateUsing(function (array $data) {
@@ -1218,6 +1262,10 @@ class ProductionQuantityResource extends Resource
$indicators[] = 'SAP Message Status: ' . $data['sap_msg_status']; $indicators[] = 'SAP Message Status: ' . $data['sap_msg_status'];
} }
if (!empty($data['operator_id'])) {
$indicators[] = 'Created By: ' . $data['operator_id'];
}
if (!empty($data['created_from'])) { if (!empty($data['created_from'])) {
$indicators[] = 'From: ' . $data['created_from']; $indicators[] = 'From: ' . $data['created_from'];
} }

File diff suppressed because it is too large Load Diff

View File

@@ -17,23 +17,23 @@ class PalletController extends Controller
// //
} }
public function downloadQrPdf($palletNo) public function downloadReprintQrPdf($palletNo)
{ {
$qrCode = new QrCode($palletNo); $qrCode = new QrCode($palletNo);
$output = new Output\Png(); $output = new Output\Png();
$qrBinary = $output->output($qrCode, 100); $qrBinary = $output->output($qrCode, 100);
$qrBase64 = base64_encode($qrBinary); $qrBase64 = base64_encode($qrBinary);
$html = ' return '
<html> <html>
<head> <head>
<style> <style>
body { margin: 0; padding: 0; width: 60mm; height: 14mm; font-size: 10pt; font-family: DejaVu Sans, sans-serif; } body { margin: 0; padding: 0; width: 60mm; height: auto; font-size: 10pt; font-family: DejaVu Sans, sans-serif; }
.sticker-table { width: 60mm; height: 14mm; border-collapse: collapse; } .sticker-table { width: 60mm; height: 14mm; border-collapse: collapse; page-break-after: always; }
.qr-cell { width: 14mm; text-align: left; vertical-align: middle; padding-left: 6mm; padding-top: 2mm; } .qr-cell { width: 14mm; text-align: right; vertical-align: bottom; padding-left: 0mm; padding-top: 0mm; }
.text-cell { text-align: left; vertical-align: middle; font-size: 15pt; padding-left: 4mm; padding-top: 2mm; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: bold; } .text-cell { text-align: left; vertical-align: middle; font-size: 20pt; padding-left: 1mm; padding-top: 2mm; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: bold; }
img.qr { width: 18mm; height: 18mm; display: block; } img.qr { width: 19mm; height: 19mm; display: block; }
</style> </style>
</head> </head>
<body> <body>
<table class="sticker-table"> <table class="sticker-table">
@@ -46,23 +46,89 @@ class PalletController extends Controller
</td> </td>
</tr> </tr>
</table> </table>
<script>
window.onload = function () {
window.print();
setTimeout(function () {
window.close();
}, 500); // Wait 0.5 seconds before closing
};
</script>
</body> </body>
</html> </html>
'; ';
$mpdf = new Mpdf([ // $mpdf = new Mpdf([
'mode' => 'utf-8', // 'mode' => 'utf-8',
'format' => [60, 14], // 'format' => [60, 14],
'margin_left' => 0, // 'margin_left' => 0,
'margin_right' => 0, // 'margin_right' => 0,
'margin_top' => 0, // 'margin_top' => 0,
'margin_bottom' => 0, // 'margin_bottom' => 0,
'tempDir' => '/var/www/storage/mpdf-tmp', // // 'tempDir' => '/var/www/storage/mpdf-tmp',
]); // ]);
$mpdf->WriteHTML($html); // $mpdf->WriteHTML($html);
$mpdf->Output('qr-label.pdf', 'I'); // // Output PDF to browser for printing
exit; // $mpdf->Output('qr-label.pdf', 'I');
}
public function downloadQrPdf($palletNo)
{
$qrCode = new QrCode($palletNo);
$output = new Output\Png();
$qrBinary = $output->output($qrCode, 100);
$qrBase64 = base64_encode($qrBinary);
$htmlBlock = '
<table class="sticker-table">
<tr>
<td class="qr-cell">
<img class="qr" src="data:image/png;base64,' . $qrBase64 . '" alt="QR" />
</td>
<td class="text-cell">
' . htmlspecialchars($palletNo) . '
</td>
</tr>
</table>';
return '
<html>
<head>
<style>
body { margin: 0; padding: 0; width: 60mm; height: auto; font-size: 10pt; font-family: DejaVu Sans, sans-serif; }
.sticker-table { width: 60mm; height: 14mm; border-collapse: collapse; page-break-after: always; }
.qr-cell { width: 14mm; text-align: right; vertical-align: bottom; padding-left: -8mm; padding-top: 0mm; }
.text-cell { text-align: left; vertical-align: middle; font-size: 22pt; padding-left: 1mm; padding-top: 2mm; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-weight: bold; }
img.qr { width: 19mm; height: 19mm; display: block; }
</style>
</head>
<body>
' . $htmlBlock . $htmlBlock . '
<script>
window.onload = function () {
window.print();
setTimeout(function () {
window.close();
}, 1000); // Wait 1 second before closing
};
</script>
</body>
</html>';
// $mpdf = new Mpdf([
// 'mode' => 'utf-8',
// 'format' => [60, 14],
// 'margin_left' => 0,
// 'margin_right' => 0,
// 'margin_top' => 0,
// 'margin_bottom' => 0,
// // 'tempDir' => '/var/www/storage/mpdf-tmp',
// ]);
// $mpdf->WriteHTML($html);
// // Output PDF to browser for printing
// $mpdf->Output('qr-label.pdf', 'I');
} }
/** /**

View File

@@ -0,0 +1,240 @@
<?php
namespace App\Http\Controllers;
use App\Models\Item;
use App\Models\ProductionQuantity;
use App\Models\StickerMaster;
use Illuminate\Http\Request;
use Mpdf\Mpdf;
use Mpdf\QrCode\Output;
use Mpdf\QrCode\QrCode;
class ProductionStickerReprintController extends Controller
{
/**
* Display a listing of the resource.
*/
public function index()
{
//
}
public function downloadQrPdf($palletNo)
{
$parts = explode('|', $palletNo);
$itemCode = trim($parts[0]);
$serial = isset($parts[1]) ? trim($parts[1]) : null;
// Retrieve the item record by item code
$item = Item::where('code', $itemCode)->first();
if (!$item) {
abort(404, "Item with code {$itemCode} not found.");
}
$itemId = $item->id;
$production = ProductionQuantity::where('item_id', $itemId)
->where('serial_number', $serial)
->first();
if (!$production) {
abort(404, "Production data for item code '{$itemCode}' with serial '{$serial}' not found.");
}
$productionOrder = $production->production_order;
$qrCode = new QrCode($palletNo);
$output = new Output\Png();
$qrBinary = $output->output($qrCode, 100);
$qrBase64 = base64_encode($qrBinary);
$sticker = StickerMaster::where('item_id', $itemId)->first();
// Decide number of copies
$copies = 1;
if ($sticker) {
if ($sticker->serial_number_pump == 1) {
// If pump is selected (regardless of motor), 2 copies
$copies = 2;
} elseif ($sticker->serial_number_motor == 1) {
// Only motor selected, 1 copy
$copies = 1;
}
}
return '
<html>
<head>
<style>
body {
margin: 0;
padding: 0;
width: 60mm;
height: 14mm;
font-size: 10pt;
font-family: Arial Narrow, Arial, sans-serif;
}
.sticker-table {
width: 60mm;
height: 14mm;
border-collapse: collapse;
}
.text-cell {
text-align: left;
vertical-align: middle;
font-size: 10pt;
padding: 2mm 2mm 0 0;
white-space: normal;
font-weight: normal;
line-height: 0.3;
}
.text-row {
align-items: center;
width: 100%;
font-weight: bold;
font-size: 9pt;
}
.serial {
text-align: left;
}
.po-number {
text-align: right;
white-space: nowrap;
width: 1%;
}
.desc-row {
font-weight: normal;
font-size: 7pt;
}
.qr-cell {
width: 14mm;
text-align: left;
vertical-align: middle;
padding-left: 1mm;
padding-top: 0mm;
}
img.qr {
width: 13mm;
height: 13mm;
display: block;
}
</style>
</head>
<body>
<div id="print-container"></div>
<script>
const copies = ' . $copies . ';
const htmlBlock = `
<table class="sticker-table">
<tr>
<td class="qr-cell">
<img class="qr" src="data:image/png;base64,' . $qrBase64 . '" alt="QR" />
</td>
<td class="text-cell">
<div class="text-row">
<pre><span class="serial">' . htmlspecialchars($serial) . '</span> <span class="po-number">' . htmlspecialchars($productionOrder) . '</span></pre>
</div>
<div class="desc-row">
' . htmlspecialchars($item->description) . '
</div>
</td>
</tr>
</table>
`;
const container = document.getElementById("print-container");
for (let i = 0; i < copies; i++) {
container.insertAdjacentHTML("beforeend", htmlBlock);
}
window.onload = function () {
window.print();
setTimeout(function () {
window.close();
}, 500);
};
</script>
</body>
</html>
';
// //Get sticker master data
// $sticker = StickerMaster::where('item_id', $itemId)->first();
// //Decide number of copies
// $copies = 1; // default
// if ($sticker) {
// if ($sticker->serial_number_motor == 1) {
// $copies = 1;
// } elseif (is_null($sticker->serial_number_motor) && $sticker->serial_number_pump == 1) {
// $copies = 2;
// }
// }
// $mpdf = new Mpdf([
// 'mode' => 'utf-8',
// 'format' => [60, 14],
// 'margin_left' => 0,
// 'margin_right' => 0,
// 'margin_top' => 0,
// 'margin_bottom' => 0,
// ]);
// for ($i = 0; $i < $copies; $i++) {
// $mpdf->WriteHTML($html);
// if ($i < $copies - 1) {
// $mpdf->AddPage();
// }
// }
// $mpdf->Output('qr-label.pdf', 'I');
// exit;
}
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
/**
* Update the specified resource in storage.
*/
public function update(Request $request, string $id)
{
//
}
/**
* Remove the specified resource from storage.
*/
public function destroy(string $id)
{
//
}
}

View File

@@ -81,6 +81,9 @@ class UserController extends Controller
//$user = User::where('email', $email)->first(); //$user = User::where('email', $email)->first();
if (Hash::check($header_pass, $existUser->password)) { if (Hash::check($header_pass, $existUser->password)) {
return response()->json([ return response()->json([
'created_at' => $existUser->created_at->format('Y-m-d H:i:s'),
'updated_at' => $existUser->updated_at->format('Y-m-d H:i:s'),
'email' => $existUser->email,
'roles' => $existUser->roles()->pluck('name')->toArray() 'roles' => $existUser->roles()->pluck('name')->toArray()
], 200); ], 200);
} else { } else {

View File

@@ -0,0 +1,27 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
class DeviceMaster extends Model
{
use SoftDeletes;
protected $fillable = [
'plant_id',
'name',
'mac_address',
'ip_address',
'created_at',
'updated_at',
'created_by',
];
public function plant(): BelongsTo
{
return $this->belongsTo(Plant::class);
}
}

View File

@@ -0,0 +1,106 @@
<?php
namespace App\Policies;
use Illuminate\Auth\Access\Response;
use App\Models\DeviceMaster;
use App\Models\User;
class DeviceMasterPolicy
{
/**
* Determine whether the user can view any models.
*/
public function viewAny(User $user): bool
{
return $user->checkPermissionTo('view-any DeviceMaster');
}
/**
* Determine whether the user can view the model.
*/
public function view(User $user, DeviceMaster $devicemaster): bool
{
return $user->checkPermissionTo('view DeviceMaster');
}
/**
* Determine whether the user can create models.
*/
public function create(User $user): bool
{
return $user->checkPermissionTo('create DeviceMaster');
}
/**
* Determine whether the user can update the model.
*/
public function update(User $user, DeviceMaster $devicemaster): bool
{
return $user->checkPermissionTo('update DeviceMaster');
}
/**
* Determine whether the user can delete the model.
*/
public function delete(User $user, DeviceMaster $devicemaster): bool
{
return $user->checkPermissionTo('delete DeviceMaster');
}
/**
* Determine whether the user can delete any models.
*/
public function deleteAny(User $user): bool
{
return $user->checkPermissionTo('delete-any DeviceMaster');
}
/**
* Determine whether the user can restore the model.
*/
public function restore(User $user, DeviceMaster $devicemaster): bool
{
return $user->checkPermissionTo('restore DeviceMaster');
}
/**
* Determine whether the user can restore any models.
*/
public function restoreAny(User $user): bool
{
return $user->checkPermissionTo('restore-any DeviceMaster');
}
/**
* Determine whether the user can replicate the model.
*/
public function replicate(User $user, DeviceMaster $devicemaster): bool
{
return $user->checkPermissionTo('replicate DeviceMaster');
}
/**
* Determine whether the user can reorder the models.
*/
public function reorder(User $user): bool
{
return $user->checkPermissionTo('reorder DeviceMaster');
}
/**
* Determine whether the user can permanently delete the model.
*/
public function forceDelete(User $user, DeviceMaster $devicemaster): bool
{
return $user->checkPermissionTo('force-delete DeviceMaster');
}
/**
* Determine whether the user can permanently delete any models.
*/
public function forceDeleteAny(User $user): bool
{
return $user->checkPermissionTo('force-delete-any DeviceMaster');
}
}

View File

@@ -0,0 +1,45 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
$sql = <<<'SQL'
CREATE TABLE device_masters (
id BIGINT GENERATED always AS IDENTITY PRIMARY KEY,
plant_id BIGINT NOT NULL,
name TEXT NOT NULL,
mac_address TEXT DEFAULT NULL,
ip_address TEXT DEFAULT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
deleted_at TIMESTAMP,
created_by TEXT NULL,
UNIQUE (name, plant_id),
FOREIGN KEY (plant_id) REFERENCES plants (id)
);
SQL;
DB::statement($sql);
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('device_masters');
}
};

View File

@@ -0,0 +1,72 @@
<x-filament-panels::page>
<div class="space-y-4">
{{-- Heading label --}}
<h2 class="text-xl font-semibold text-gray-800">
STICKER RE-PRINT
</h2>
{{-- Render the Select form fields --}}
<div class="space-y-4">
{{-- {{ $this->filtersForm($this->form) }} --}}
{{ $this->form }}
</div>
{{-- <input
type="text"
id="qr-scan-input"
class="border border-gray-300 rounded px-4 py-2 text-sm w-full"
placeholder="Scan QR Code & Press Enter"
autocomplete="off"
autofocus
/> --}}
<div class="mb-4">
<label for="qr-scan-input" class="block text-sm font-medium text-gray-700 mb-2">
SCAN QR CODE
</label>
<input
type="text"
id="qr-scan-input"
class="border border-gray-300 rounded px-4 py-2 text-sm w-full"
placeholder="Scan QR Code & Press Enter"
autocomplete="off"
autofocus
/>
</div>
@push('scripts')
<script>
document.addEventListener('DOMContentLoaded', function () {
const scanInput = document.getElementById('qr-scan-input');
if (!scanInput) return;
scanInput.addEventListener('keydown', function (event) {
if (event.key === 'Enter') {
event.preventDefault();
const value = scanInput.value.trim();
if (value !== '') {
Livewire.dispatch('handleQrScan', { value: value });
scanInput.value = '';
}
}
});
window.addEventListener('open-pdf', event => {
const pdfUrl = event.detail.url;
const win = window.open(pdfUrl, '_blank');
if (!win) {
console.warn('Popup blocked. Please allow popups for this site.');
}
});
});
</script>
@endpush
{{-- Render the chart widget below the form --}}
<div class="mt-6">
@livewire(\App\Filament\Widgets\ItemOverview::class)
</div>
</div>
</x-filament-panels::page>

View File

@@ -82,6 +82,8 @@ Route::get('sticker/get-master-type-data', [StickerMasterController::class, 'get
Route::get('/download-qr-pdf/{palletNo}', [PalletController::class, 'downloadQrPdf'])->name('download-qr-pdf'); Route::get('/download-qr-pdf/{palletNo}', [PalletController::class, 'downloadQrPdf'])->name('download-qr-pdf');
Route::get('/download-reprint-qr-pdf/{palletNo}', [PalletController::class, 'downloadReprintQrPdf'])->name('download-reprint-qr-pdf');
Route::get('/download-qr1-pdf/{palletNo}', [ProductionStickerReprintController::class, 'downloadQrPdf'])->name('download-qr1-pdf'); Route::get('/download-qr1-pdf/{palletNo}', [ProductionStickerReprintController::class, 'downloadQrPdf'])->name('download-qr1-pdf');
//Production Dashboard Controller //Production Dashboard Controller