Enhance invoice out validation table with searchable 'updated_by' column and improved duplicate handling logic on import
This commit is contained in:
@@ -104,8 +104,14 @@ class InvoiceOutValidationResource extends Resource
|
||||
->sortable(),
|
||||
Tables\Columns\TextColumn::make('updated_at')
|
||||
->dateTime()
|
||||
->sortable()
|
||||
->toggleable(isToggledHiddenByDefault: true),
|
||||
->searchable()
|
||||
->sortable(),
|
||||
// ->toggleable(isToggledHiddenByDefault: true),
|
||||
Tables\Columns\TextColumn::make('updated_by')
|
||||
->label('Updated By')
|
||||
->searchable()
|
||||
->alignCenter()
|
||||
->sortable(),
|
||||
Tables\Columns\TextColumn::make('deleted_at')
|
||||
->dateTime()
|
||||
->sortable()
|
||||
@@ -186,7 +192,7 @@ class InvoiceOutValidationResource extends Resource
|
||||
$userNotFound = [];
|
||||
$seenPlantQr = [];
|
||||
$duplicateQrExcel = [];
|
||||
$duplicateQrDb = [];
|
||||
//$duplicateQrDb = [];
|
||||
|
||||
foreach ($rows as $index => $row)
|
||||
{
|
||||
@@ -217,18 +223,18 @@ class InvoiceOutValidationResource extends Resource
|
||||
$uniqueKey = $plantCode . '_' . $qrCode;
|
||||
|
||||
if (in_array($uniqueKey, $seenPlantQr)) {
|
||||
$duplicateQrExcel[] = "Duplicate in file at Row {$index}: Document Numbers '{$qrCode}' already exists for Plant Code {$plant->name}";
|
||||
$duplicateQrExcel[] = "Duplicate in file at Row {$index}: Document Numbers '{$qrCode}' already exists for Plant Code '{$plant->name}'";
|
||||
}
|
||||
|
||||
$seenPlantQr[] = $uniqueKey;
|
||||
|
||||
$existsInDb = InvoiceOutValidation::where('plant_id', $plantId)
|
||||
->where('qr_code', $qrCode)
|
||||
->first();
|
||||
// $existsInDb = InvoiceOutValidation::where('plant_id', $plantId)
|
||||
// ->where('qr_code', $qrCode)
|
||||
// ->first();
|
||||
|
||||
if ($existsInDb) {
|
||||
$duplicateQrDb[] = "Document Numbers '{$qrCode}' already exists in DB for Plant Code {$plant->name}";
|
||||
}
|
||||
// if ($existsInDb) {
|
||||
// $duplicateQrDb[] = "Document Numbers '{$qrCode}' already exists in DB for Plant Code {$plant->name}";
|
||||
// }
|
||||
}
|
||||
|
||||
if (!empty($invalidqrCode) || !empty($invalidScannedAt) || !empty($invalidScannedBy) || !empty($invalidUser))
|
||||
@@ -263,6 +269,7 @@ class InvoiceOutValidationResource extends Resource
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($invalidPlaCoFound)) {
|
||||
$invalidPlaCoFound = array_unique($invalidPlaCoFound);
|
||||
Notification::make()
|
||||
@@ -275,6 +282,7 @@ class InvoiceOutValidationResource extends Resource
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($userNotFound)) {
|
||||
$userNotFound = array_unique($userNotFound);
|
||||
Notification::make()
|
||||
@@ -287,12 +295,13 @@ class InvoiceOutValidationResource extends Resource
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!empty($duplicateQrExcel))
|
||||
{
|
||||
$duplicateGroupedByPlantQr = [];
|
||||
|
||||
foreach ($duplicateQrExcel as $message) {
|
||||
if (preg_match("/Document Numbers '([^']+)' already exists for Plant Code (\S+)/", $message, $matches)) {
|
||||
foreach ($duplicateQrExcel as $message) {//"/Document Numbers '([^']+)' already exists for Plant Code (\S+)/"
|
||||
if (preg_match("/Document Numbers '([^']+)' already exists for Plant Code '([^']+)'/", $message, $matches)) {
|
||||
$qrCode = $matches[1];
|
||||
$plantCode = $matches[2];
|
||||
$duplicateGroupedByPlantQr[$plantCode][] = $qrCode;
|
||||
@@ -306,11 +315,11 @@ class InvoiceOutValidationResource extends Resource
|
||||
$count = count($uniqueQrCodes);
|
||||
|
||||
if ($count > 10) {
|
||||
$errorMsg .= "Duplicate Document Numbers for Plant <b>{$plantCode}</b>: {$count} Document Numbers already exist in uploaded file<br>";
|
||||
$errorMsg .= "Duplicate Document Numbers for Plant <b>{$plantCode}</b> : {$count} Document Numbers already exist in uploaded file<br>";
|
||||
} else {
|
||||
$errorMsg .= "Duplicate Document Numbers for Plant <b>{$plantCode}</b>: "
|
||||
$errorMsg .= "Duplicate Document Numbers for Plant <b>{$plantCode}</b> : '"
|
||||
. implode(', ', $uniqueQrCodes)
|
||||
. " already exist<br>";
|
||||
. "' already exist in uploaded file<br>";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,46 +335,45 @@ class InvoiceOutValidationResource extends Resource
|
||||
|
||||
return;
|
||||
}
|
||||
if (!empty($duplicateQrDb)) {
|
||||
$duplicateGroupedByPlantDb = [];
|
||||
|
||||
foreach ($duplicateQrDb as $message) {
|
||||
if (preg_match("/Document Numbers '([^']+)' already exists in DB for Plant Code (\S+)/", $message, $matches)) {
|
||||
$qrCode = $matches[1];
|
||||
$plantCode = $matches[2];
|
||||
$duplicateGroupedByPlantDb[$plantCode][] = $qrCode;
|
||||
}
|
||||
}
|
||||
// if (!empty($duplicateQrDb)) {
|
||||
// $duplicateGroupedByPlantDb = [];
|
||||
|
||||
$errorMsg = 'Duplicate Document Numbers found in Database:<br>';
|
||||
// foreach ($duplicateQrDb as $message) {
|
||||
// if (preg_match("/Document Numbers '([^']+)' already exists in DB for Plant Code (\S+)/", $message, $matches)) {
|
||||
// $qrCode = $matches[1];
|
||||
// $plantCode = $matches[2];
|
||||
// $duplicateGroupedByPlantDb[$plantCode][] = $qrCode;
|
||||
// }
|
||||
// }
|
||||
|
||||
foreach ($duplicateGroupedByPlantDb as $plantCode => $qrCodes) {
|
||||
$uniqueQrCodes = array_unique($qrCodes);
|
||||
$count = count($uniqueQrCodes);
|
||||
// $errorMsg = 'Duplicate Document Numbers found in Database:<br>';
|
||||
|
||||
if ($count > 10) {
|
||||
$errorMsg .= "Duplicate Document Numbers for Plant <b>{$plantCode}</b>: {$count} Document Numbers already exist in DB<br>";
|
||||
} else {
|
||||
$errorMsg .= "Duplicate Document Numbers for Plant <b>{$plantCode}</b>: "
|
||||
. implode(', ', $uniqueQrCodes)
|
||||
. " already exist in DB<br>";
|
||||
}
|
||||
}
|
||||
// foreach ($duplicateGroupedByPlantDb as $plantCode => $qrCodes) {
|
||||
// $uniqueQrCodes = array_unique($qrCodes);
|
||||
// $count = count($uniqueQrCodes);
|
||||
|
||||
Notification::make()
|
||||
// ->title('Duplicate Document Numbers in Database')
|
||||
->body($errorMsg)
|
||||
->danger()
|
||||
->send();
|
||||
// if ($count > 10) {
|
||||
// $errorMsg .= "Duplicate Document Numbers for Plant <b>{$plantCode}</b>: {$count} Document Numbers already exist in DB<br>";
|
||||
// } else {
|
||||
// $errorMsg .= "Duplicate Document Numbers for Plant <b>{$plantCode}</b>: "
|
||||
// . implode(', ', $uniqueQrCodes)
|
||||
// . " already exist in DB<br>";
|
||||
// }
|
||||
// }
|
||||
|
||||
if ($disk->exists($path)) {
|
||||
$disk->delete($path);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
// Notification::make()
|
||||
// // ->title('Duplicate Document Numbers in Database')
|
||||
// ->body($errorMsg)
|
||||
// ->danger()
|
||||
// ->send();
|
||||
|
||||
// if ($disk->exists($path)) {
|
||||
// $disk->delete($path);
|
||||
// }
|
||||
|
||||
// return;
|
||||
// }
|
||||
|
||||
$successCount = 0;
|
||||
$failedRecords = [];
|
||||
@@ -412,16 +420,39 @@ class InvoiceOutValidationResource extends Resource
|
||||
}
|
||||
}
|
||||
|
||||
$inserted = InvoiceOutValidation::create([
|
||||
'plant_id' => $plant->id,
|
||||
'qr_code' => $qrcode,
|
||||
'scanned_at' => $formattedDate,
|
||||
'scanned_by' => $scannedBy,
|
||||
'created_by' => $operatorName,
|
||||
]);
|
||||
$record = InvoiceOutValidation::where('plant_id', $plant->id)
|
||||
->where('qr_code', $qrcode)
|
||||
->first();
|
||||
|
||||
$curStat = $record ? 'Updation' : 'Insertion';
|
||||
|
||||
if ($record) {
|
||||
$record->update([
|
||||
'scanned_at' => $formattedDate,
|
||||
'scanned_by' => $scannedBy,
|
||||
'updated_by' => $operatorName
|
||||
]);
|
||||
$inserted = $record;
|
||||
} else {
|
||||
// Record does not exist, create with 'created_by'
|
||||
$inserted = InvoiceOutValidation::create([
|
||||
'plant_id' => $plant->id,
|
||||
'qr_code' => $qrcode,
|
||||
'scanned_at' => $formattedDate,
|
||||
'scanned_by' => $scannedBy,
|
||||
'created_by' => $operatorName
|
||||
]);
|
||||
}
|
||||
// $inserted = InvoiceOutValidation::create([
|
||||
// 'plant_id' => $plant->id,
|
||||
// 'qr_code' => $qrcode,
|
||||
// 'scanned_at' => $formattedDate,
|
||||
// 'scanned_by' => $scannedBy,
|
||||
// 'created_by' => $operatorName
|
||||
// ]);
|
||||
|
||||
if (!$inserted) {
|
||||
throw new \Exception("Insert failed for QR: {$qrcode}");
|
||||
throw new \Exception("{$curStat} failed for QR : {$qrcode}");
|
||||
}
|
||||
|
||||
$successCount++;
|
||||
@@ -439,30 +470,29 @@ class InvoiceOutValidationResource extends Resource
|
||||
|
||||
if (count($failedRecords) > 0) {
|
||||
$failedSummary = collect($failedRecords)
|
||||
->map(fn($f) => "Row {$f['row']} ({$f['qrcode']}): {$f['error']}")
|
||||
->map(fn($f) => "Row {$f['row']} ({$f['qrcode']}) : {$f['error']}")
|
||||
->take(5) // limit preview to first 5 errors
|
||||
->implode("\n");
|
||||
|
||||
Notification::make()
|
||||
->title('Partial Import Warning')
|
||||
->body("{$successCount} records inserted. " . count($failedRecords) . " failed.\n\n{$failedSummary}")
|
||||
->body("'{$successCount}' records inserted. " . count($failedRecords) . " failed.\n\n{$failedSummary}")
|
||||
->warning()
|
||||
->send();
|
||||
} else {
|
||||
Notification::make()
|
||||
->title('Import Success')
|
||||
->body("Successfully inserted: {$successCount} records")
|
||||
->body("Successfully imported '{$successCount}' records")
|
||||
->success()
|
||||
->send();
|
||||
}
|
||||
|
||||
}
|
||||
catch (\Exception $e)
|
||||
{
|
||||
DB::rollBack();
|
||||
Notification::make()
|
||||
->title('Import Failed')
|
||||
->body("No records were inserted. Error: {$e->getMessage()}")
|
||||
->body("No records were inserted. Error : {$e->getMessage()}")
|
||||
->danger()
|
||||
->send();
|
||||
}
|
||||
@@ -471,7 +501,7 @@ class InvoiceOutValidationResource extends Resource
|
||||
->visible(function() {
|
||||
return Filament::auth()->user()->can('view import invoice out validation');
|
||||
}),
|
||||
ExportAction::make()
|
||||
ExportAction::make()
|
||||
->exporter(InvoiceOutValidationExporter::class)
|
||||
->visible(function() {
|
||||
return Filament::auth()->user()->can('view export invoice out validation');
|
||||
|
||||
Reference in New Issue
Block a user