Merge pull request 'Added meter pattern in invoice validation' (#1031) from ranjith-dev into master
All checks were successful
Scan for leaked secrets using Kingfisher / kingfisher-secrets-scan (push) Successful in 13s

Reviewed-on: #1031
This commit was merged in pull request #1031.
This commit is contained in:
2026-09-14 10:41:31 +00:00

View File

@@ -6,6 +6,7 @@ use App\Filament\Resources\InvoiceValidationResource;
use App\Imports\ExcelImport;
use App\Mail\InvalidSerialMail;
use App\Models\AlertMailRule;
use App\Models\CoilPacking;
use App\Models\InvoiceValidation;
use App\Models\Item;
use App\Models\Plant;
@@ -2551,19 +2552,90 @@ class CreateInvoiceValidation extends CreateRecord
$this->dispatch('refreshMaterialInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId);
}
$pattern6 = '/^(?<item_code>[^|]+)\|(?<batch_number>[^|]+)\|(?<batch_id>[^|]+)\|(?<batch_count>[^|]+)\|(?<batch_quantity>[^|]+)$/i';
$pattern0 = '/^(?<item_code>[^|]+)\|(?<batch_id>[^|]+)\|(?<batch_count>[^|]+)\|(?<batch_quantity>[0-9]+(?:\.[0-9]+)?)\s?kg$/i';
$pattern1 = '/^(?<item_code>[^|]+)\|(?<batch_number>[^|]+)\|(?<batch_id>[^|]+)\|(?<batch_count>[^|]+)\/(?<batch_quantity>.+)$/i';
$pattern2 = '/^(?<item_code>[^|]+)\|(?<batch_number>[^|]+)\|(?<batch_id>[^|]+)\|(?<batch_count>.+)$/i';
$pattern3 = '/^(?<item_code>[^|]+)\|(?<batch_id>[^|]+)-(?<batch_count>.+)$/i';
$pattern4 = '/^MP-(?<code>.+)$/i';
$pattern5 = '/^CP-(?<code>.+)$/i';
$itemCode = '';
$batchNumber = '';
$curScanQty = '';
$wirePallet = '';
$coilPallet = '';
$curMaterialQty = '';
$curMaterialSer = '';
if (preg_match($pattern0, $serNo, $matches)) {
if (preg_match($pattern6, $serNo, $matches) && substr_count($serNo, '|') == 4) {
$itemCode = $matches['item_code'];
$this->currentItemCode = $itemCode;
$batchNumber = $matches['batch_number'];
$curScanQty = trim($matches['batch_quantity']);
$serialNumber = $matches['batch_id'].'-'.$matches['batch_count'];
$serNo = null;
if (empty($matches['batch_number']) || ! $matches['batch_number']) {
Notification::make()
->danger()
->title('Invalid Material QR Format')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1 (or) <br>657204|26091200|200000266831|001|650.000')
->seconds(2)
->send();
$this->dispatch('playWarnSound');
$this->form->fill([
'plant_id' => $plantId,
'invoice_number' => $invoiceNumber,
'serial_number' => null,
'total_quantity' => $totMatQuan,
'update_invoice' => false,
'scanned_quantity' => $scanMatQuan,
]);
return;
} elseif (empty($matches['batch_id']) || ! $matches['batch_id']) {
Notification::make()
->danger()
->title('Invalid Material QR Format')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1 (or) <br>657204|26091200|200000266831|001|650.000')
->seconds(2)
->send();
$this->dispatch('playWarnSound');
$this->form->fill([
'plant_id' => $plantId,
'invoice_number' => $invoiceNumber,
'serial_number' => null,
'total_quantity' => $totMatQuan,
'update_invoice' => false,
'scanned_quantity' => $scanMatQuan,
]);
return;
}
elseif (empty($matches['batch_count']) || ! $matches['batch_count']) {
Notification::make()
->danger()
->title('Invalid Material QR Format')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1 (or) <br>657204|26091200|200000266831|001|650.000')
->seconds(2)
->send();
$this->dispatch('playWarnSound');
$this->form->fill([
'plant_id' => $plantId,
'invoice_number' => $invoiceNumber,
'serial_number' => null,
'total_quantity' => $totMatQuan,
'update_invoice' => false,
'scanned_quantity' => $scanMatQuan,
]);
return;
}
} elseif (preg_match($pattern0, $serNo, $matches)) {
$itemCode = $matches['item_code'];
$this->currentItemCode = $itemCode;
$curScanQty = trim($matches['batch_quantity']);
@@ -2574,8 +2646,7 @@ class CreateInvoiceValidation extends CreateRecord
Notification::make()
->danger()
->title('Invalid Material QR Format')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1')
->seconds(2)
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1 (or) <br>657204|26091200|200000266831|001|650.000')
->send();
$this->dispatch('playWarnSound');
@@ -2593,7 +2664,7 @@ class CreateInvoiceValidation extends CreateRecord
Notification::make()
->danger()
->title('Invalid Material QR Format')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1 (or) <br>657204|26091200|200000266831|001|650.000')
->seconds(2)
->send();
$this->dispatch('playWarnSound');
@@ -2621,7 +2692,7 @@ class CreateInvoiceValidation extends CreateRecord
Notification::make()
->danger()
->title('Invalid Material QR Format')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1 (or) <br>657204|26091200|200000266831|001|650.000')
->seconds(2)
->send();
$this->dispatch('playWarnSound');
@@ -2655,7 +2726,7 @@ class CreateInvoiceValidation extends CreateRecord
Notification::make()
->danger()
->title('Invalid Material QR Format')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1 (or) <br>657204|26091200|200000266831|001|650.000')
->seconds(2)
->send();
$this->dispatch('playWarnSound');
@@ -2689,7 +2760,7 @@ class CreateInvoiceValidation extends CreateRecord
Notification::make()
->danger()
->title('Invalid Material QR Format')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1 (or) <br>657204|26091200|200000266831|001|650.000')
->seconds(2)
->send();
$this->dispatch('playWarnSound');
@@ -2734,7 +2805,7 @@ class CreateInvoiceValidation extends CreateRecord
Notification::make()
->danger()
->title('Invalid Material QR Format')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1 (or) <br>657204|26091200|200000266831|001|650.000')
->seconds(2)
->send();
$this->dispatch('playWarnSound');
@@ -2767,7 +2838,7 @@ class CreateInvoiceValidation extends CreateRecord
Notification::make()
->danger()
->title('Invalid Material QR Format')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1 (or) <br>657204|26091200|200000266831|001|650.000')
->seconds(2)
->send();
$this->dispatch('playWarnSound');
@@ -2800,7 +2871,7 @@ class CreateInvoiceValidation extends CreateRecord
Notification::make()
->danger()
->title('Invalid Material QR Format')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1 (or) <br>657204|26091200|200000266831|001|650.000')
->seconds(2)
->send();
$this->dispatch('playWarnSound');
@@ -2840,7 +2911,7 @@ class CreateInvoiceValidation extends CreateRecord
Notification::make()
->danger()
->title('Invalid Material QR Format')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1 (or) <br>657204|26091200|200000266831|001|650.000')
->seconds(2)
->send();
$this->dispatch('playWarnSound');
@@ -2874,7 +2945,7 @@ class CreateInvoiceValidation extends CreateRecord
Notification::make()
->danger()
->title('Invalid Material QR Format')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1 (or) <br>657204|26091200|200000266831|001|650.000')
->seconds(2)
->send();
$this->dispatch('playWarnSound');
@@ -3197,7 +3268,305 @@ class CreateInvoiceValidation extends CreateRecord
]);
return;
} else {
} elseif (preg_match($pattern5, $serNo, $matches)) {
$coilPallet = 'CP-'.$matches['code'];
$coilPattern = '/^CP-(?<code>\d+)$/i';
if (! preg_match($coilPattern, $serNo, $matches)) {
Notification::make()
->title('Invalid Coil Packing QR Format')
->body("Scan valid Coil Packing QR code proceed!<br>Sample format : 'CP-2601001'")
->danger()
->seconds(1)
->send();
return;
}
$coilMaster = CoilPacking::where('plant_id', $plantId)->where('coil_packing_number', $coilPallet)->first();
if (! $coilMaster) {
Notification::make()
->title('Master Pallet Not Found')
->body("No record found for this Master Packing QR $coilPallet")
->danger()
->seconds(2)
->send();
return;
}
$coilItemCodes = CoilPacking::join('items', 'items.id', '=', 'coil_packings.item_id')
->where('coil_packings.plant_id', $plantId)
->where('coil_packings.coil_packing_number', $wirePallet)
->pluck('items.code')
->unique()
->toArray();
$invoiceItemCodes = InvoiceValidation::join(
'sticker_masters',
'sticker_masters.id',
'=',
'invoice_validations.sticker_master_id'
)
->join(
'items',
'items.id',
'=',
'sticker_masters.item_id'
)
->where('invoice_validations.plant_id', $plantId)
->where('invoice_validations.invoice_number', $this->invoiceNumber)
->pluck('items.code')
->unique()
->toArray();
$missedCodes = array_diff($coilItemCodes, $invoiceItemCodes);
if (! empty($missedCodes)) {
Notification::make()
->title('Items Missing in Invoice')
->body('Item codes are missing in invoice: '.implode(', ', $missedCodes))
->danger()
->seconds(3)
->send();
return;
}
$duplicateSerial = [];
$weightExceeded = [];
$invalidMaterialItems = [];
$coilItems1 = CoilPacking::join('items', 'items.id', '=', 'coil_packings.item_id')
->where('coil_packings.plant_id', $plantId)
->where('coil_packings.coil_packing_number', $wirePallet)
->select(
'items.code as item_code',
'coil_packings.process_order',
DB::raw('COUNT(*) as pallet_weight')
)
->groupBy('items.code', 'coil_packings.process_order')
->get();
foreach ($coilItems1 as $coilItem) {
$processOrder = $coilItem->process_order;
$palletWeight = $coilItem->pallet_weight;
$itemCode = $coilItem->item_code;
$duplicate = InvoiceValidation::where('plant_id', $this->plantId)
->where('invoice_number', $this->invoiceNumber)
->where('serial_number', $processOrder)
->exists();
if ($duplicate) {
$duplicateSerial[] = $processOrder;
continue;
}
$materialType = StickerMaster::where('item_id', function ($q) use ($itemCode) {
$q->select('id')->from('items')->where('code', $itemCode);
})->value('material_type');
if ($materialType != 3) {
if (! in_array($itemCode, $invalidMaterialItems)) {
$invalidMaterialItems[] = $itemCode;
}
}
$scannedQty = InvoiceValidation::join('sticker_masters', 'sticker_masters.id', '=', 'invoice_validations.sticker_master_id')
->join('items', 'items.id', '=', 'sticker_masters.item_id')
->where('invoice_validations.plant_id', $plantId)
->where('invoice_validations.invoice_number', $this->invoiceNumber)
->where('items.code', $itemCode)
->sum(DB::raw('invoice_validations.quantity::numeric'));
if ($palletWeight > $scannedQty) {
$weightExceeded[] = $itemCode;
}
}
if (! empty($invalidMaterialItems)) {
$uniqueInvalidItems = array_unique($invalidMaterialItems);
Notification::make()
->title('Invalid Material Type')
->body(implode(', ', $uniqueInvalidItems)."<br>Invalid material type found for the invoice '$invoiceNumber'.")
->danger()
->seconds(4)
->send();
return;
} elseif (! empty($weightExceeded)) {
Notification::make()
->title('Item Code Limit')
->body(implode(', ', $weightExceeded)."<br>Master pallet weight exceeds the remaining quantity in invoice '$invoiceNumber'.")
->danger()
->seconds(4)
->send();
return;
} elseif (! empty($duplicateSerial)) {
Notification::make()
->title('Duplicate Serial Number')
->body(implode(', ', $duplicateSerial)."<br>Duplicate Serial numbers found for the invoice '$invoiceNumber'.")
->danger()
->seconds(4)
->send();
return;
}
$itemExceeded = [];
$invoiceRows = InvoiceValidation::where('plant_id', $plantId)
->where('invoice_number', $invoiceNumber)
->whereNull('serial_number')
->get();
$palletItems = CoilPacking::where('coil_packings.plant_id', $plantId)
->where('coil_packings.coil_packing_number', $coilPallet)
->join('items', 'items.id', '=', 'coil_packings.item_id')
->select(
'items.code as item_code',
DB::raw('COUNT(*) as pallet_weight')
)
->groupBy('items.code')
->get();
foreach ($invoiceRows as $row) {
$itemCode = $row->stickerMaster->item->code ?? null;
if (! $itemCode) {
continue;
}
$pallet = $palletItems->firstWhere('item_code', $itemCode);
$palletWeight = $pallet->pallet_weight ?? 0;
$remainingQty = $row->quantity;
if ($palletWeight > $remainingQty) {
$itemExceeded[] = $itemCode;
}
}
$items = implode(', ', $itemExceeded);
if (! empty($itemExceeded)) {
Notification::make()
->title('Item Code Limit')
->body("Pallet coil count exceeds remaining quantity for invoice number '$invoiceNumber'for below item codes <br>$items")
->danger()
->seconds(5)
->send();
return;
}
$wireItems = CoilPacking::join('items', 'items.id', '=', 'coil_packings.item_id')
->where('coil_packings.coil_packing_number', $coilPallet)
->select(
'items.code as item_code',
'coil_packings.process_order',
DB::raw('COUNT(*) as pallet_weight')
)
->groupBy(
'items.code',
'coil_packings.process_order'
)
->get();
foreach ($wireItems as $wireItem) {
$itemCode = $wireItem->item_code;
$palletWeight = $wireItem->pallet_weight;
$processOrder = $wireItem->process_order;
if (! $processOrder || $palletWeight <= 0) {
continue;
}
$records = InvoiceValidation::join('sticker_masters', 'sticker_masters.id', '=', 'invoice_validations.sticker_master_id')
->join('items', 'items.id', '=', 'sticker_masters.item_id')
->where('invoice_validations.invoice_number', $invoiceNumber)
->where('invoice_validations.plant_id', $plantId)
->where('items.code', $itemCode)
->whereNull('invoice_validations.serial_number')
->where('invoice_validations.quantity', '>', 0)
->orderBy('invoice_validations.created_at')
->select('invoice_validations.*')
->get();
if ($records->isEmpty()) {
continue;
}
foreach ($records as $record) {
if ($palletWeight <= 0) {
break;
}
$usedQty = min($record->quantity, $palletWeight);
$record->quantity -= $usedQty;
if ($usedQty == $record->quantity + $usedQty) {
$record->serial_number = $processOrder;
$record->quantity = $palletWeight;
$record->save();
} else {
$record->save();
InvoiceValidation::create([
'sticker_master_id' => $record->sticker_master_id,
'plant_id' => $plantId,
'invoice_number' => $invoiceNumber,
'serial_number' => $processOrder,
'quantity' => $usedQty,
'operator_id' => $operatorName,
'created_by' => $operatorName,
'updated_by' => $operatorName,
]);
}
$palletWeight -= $usedQty;
// if ($record->quantity <= 0) {
// $records->forget($key);
// }
}
}
$this->dispatch('refreshMaterialInvoiceData', invoiceNumber: $invoiceNumber, plantId: $plantId);
$totQuan = InvoiceValidation::where('plant_id', $plantId)->where('invoice_number', $invoiceNumber)->count();
$scanMQuan = InvoiceValidation::where('invoice_number', $invoiceNumber)->whereNotNull('serial_number')->where('serial_number', '!=', '')->where('plant_id', $plantId)->count();
$checkMat = InvoiceValidation::where('invoice_number', $invoiceNumber)->where('plant_id', $plantId)->latest('updated_at')->first(); // ->where('quantity', '!=', '')
if (($checkMat?->stickerMaster->material_type ?? 0) == 3) {
$totMatQuan = InvoiceValidation::where('invoice_number', $invoiceNumber)->whereNull('serial_number')->where('plant_id', $plantId)->latest('updated_at')->first()?->invoice_quantity ?? 0;
$scanMatQuan = number_format($totMatQuan - (InvoiceValidation::where('invoice_number', $invoiceNumber)->whereNull('serial_number')->where('plant_id', $plantId)->latest('updated_at')->first()?->quantity ?? 0), 3, '.', ''); // ('updated_at', 'desc')
} else {
$totMatQuan = $totQuan;
$scanMatQuan = $scanMQuan;
}
$this->form->fill([
'plant_id' => $plantId,
'invoice_number' => $invoiceNumber,
'serial_number' => null,
'total_quantity' => $totMatQuan,
'update_invoice' => false,
'scanned_quantity' => $scanMatQuan,
]);
return;
}
else {
$itemCode = null;
$this->currentItemCode = '';
$batchNumber = null;
@@ -3207,7 +3576,7 @@ class CreateInvoiceValidation extends CreateRecord
Notification::make()
->danger()
->title('Invalid Material QR Format')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1')
->body('Scan valid Material QR code to proceed!<br>Sample formats are:<br>123456|123456789|001|5kg (or)<br>123456|12345|12345678|1/1 (or)<br>123456|12345|12345678|1 (or)<br>123456|12345678-1 (or) <br>657204|26091200|200000266831|001|650.000')
->seconds(1)
->send();