From a4dcbcd7715f778a6378c5606a58e6e0ee01d251 Mon Sep 17 00:00:00 2001 From: dhanabalan Date: Tue, 1 Sep 2026 12:26:02 +0530 Subject: [PATCH] Added sale order master importer and exporter --- .../Exports/SaleOrderMasterExporter.php | 58 +++++++ .../Imports/SaleOrderMasterImporter.php | 153 ++++++++++++++++++ 2 files changed, 211 insertions(+) create mode 100644 app/Filament/Exports/SaleOrderMasterExporter.php create mode 100644 app/Filament/Imports/SaleOrderMasterImporter.php diff --git a/app/Filament/Exports/SaleOrderMasterExporter.php b/app/Filament/Exports/SaleOrderMasterExporter.php new file mode 100644 index 0000000..0e0f6a7 --- /dev/null +++ b/app/Filament/Exports/SaleOrderMasterExporter.php @@ -0,0 +1,58 @@ +label('NO') + ->state(function ($record) use (&$rowNumber) { + // Increment and return the row number + return ++$rowNumber; + }), + ExportColumn::make('plant.code') + ->label('PLANT CODE'), + ExportColumn::make('item.code') + ->label('ITEM CODE'), + ExportColumn::make('sale_order_number') + ->label('SALE ORDER NUMBER'), + ExportColumn::make('supplier_name') + ->label('SUPPLIER NAME'), + ExportColumn::make('quantity') + ->label('QUANTITY'), + ExportColumn::make('created_at') + ->label('CREATED AT'), + ExportColumn::make('updated_at') + ->label('UPDATED AT'), + ExportColumn::make('created_by') + ->label('CREATED BY'), + ExportColumn::make('updated_by') + ->label('UPDATED BY'), + ExportColumn::make('deleted_at') + ->label('DELETED AT') + ->enabledByDefault(false), + ]; + } + + public static function getCompletedNotificationBody(Export $export): string + { + $body = 'Your sale order master 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; + } +} diff --git a/app/Filament/Imports/SaleOrderMasterImporter.php b/app/Filament/Imports/SaleOrderMasterImporter.php new file mode 100644 index 0000000..b2e1356 --- /dev/null +++ b/app/Filament/Imports/SaleOrderMasterImporter.php @@ -0,0 +1,153 @@ +requiredMapping() + ->exampleHeader('Plant Code') + ->example('1000') + ->label('Plant Code') + ->relationship(resolveUsing: 'code') + ->rules(['required']), + ImportColumn::make('item') + ->requiredMapping() + ->exampleHeader('Item Code') + ->example('630214') + ->label('Item Code') + ->relationship(resolveUsing: 'code') + ->rules(['required']), + ImportColumn::make('sale_order_number') + ->requiredMapping() + ->exampleHeader('Sale Order Number') + ->example('1JA0029512') + ->label('Sale Order Number') + ->rules(['required']), + ImportColumn::make('supplier_name') + ->exampleHeader('Supplier Name') + ->example('ABC Supplier') + ->label('Supplier Name'), + ImportColumn::make('quantity') + ->exampleHeader('Quantity') + ->example('100') + ->label('Quantity'), + ]; + } + + public function resolveRecord(): ?SaleOrderMaster + { + $warnMsg = []; + $plantCod = $this->data['plant']; + $plant = null; + $item = null; + $saleOrder = trim($this->data['sale_order_number']); + $supplierName = trim($this->data['supplier_name']); + + if (Str::length($plantCod) < 4 || ! is_numeric($plantCod) || ! preg_match('/^[1-9]\d{3,}$/', $plantCod)) { + $warnMsg[] = 'Invalid plant code found'; + } else { + $plant = Plant::where('code', $plantCod)->first(); + if (! $plant) { + $warnMsg[] = 'Plant not found'; + } else { + $item = Item::where('code', $this->data['item'])->where('plant_id', $plant->id)->first(); + } + if (! $item) { + $warnMsg[] = 'Item not found'; + } + } + + if (Str::length($this->data['sale_order_number']) < 9) { + $warnMsg[] = 'Invalid Sale Order number found'; + } + + if (empty($this->data['sale_order_number'])) { + $warnMsg[] = 'Sale Order Number cannot be empty.'; + } + + if (empty($this->data['supplier_name'])) { + $warnMsg[] = 'Supplier Name cannot be empty.'; + } + + if (empty($this->data['quantity'])) { + $warnMsg[] = 'Quantity cannot be empty.'; + } + + if (! is_numeric($this->data['quantity'])) { + $warnMsg[] = 'Quantity must be a number.'; + } + + if (isset($this->importedSaleOrders[$saleOrder])) { + + if (strtolower(trim($this->importedSaleOrders[$saleOrder])) != strtolower($supplierName)){ + $warnMsg[] = "Sale Order '{$saleOrder}' has multiple supplier names in the import file."; + } + } + else { + $this->importedSaleOrders[$saleOrder] = $supplierName; + } + + $existingPo = SaleOrderMaster::where('plant_id', $plant->id)->where('sale_order_number', $this->data['sale_order_number'])->first(); + + if ($existingPo && trim(strtolower($existingPo->supplier_name)) != trim(strtolower($this->data['supplier_name']))) + { + $warnMsg[] = "Sale Order '{$this->data['sale_order_number']}' is already mapped to supplier '{$existingPo->supplier_name}'."; + } + + $existingPoItem = SaleOrderMaster::where('plant_id', $plant->id)->where('item_id', $item->id)->where('sale_order_number', $this->data['sale_order_number'])->where('supplier_name', $this->data['supplier_name'])->first(); + + if ($existingPoItem) + { + $warnMsg[] = "Sale Order '{$this->data['sale_order_number']}' is already exist with item code '{$this->data['item']}' and supplier name '{$this->data['supplier_name']}'."; + } + + $user = Filament::auth()->user(); + + $operatorName = $user->name; + + if (! empty($warnMsg)) { + throw new RowImportFailedException(implode(', ', $warnMsg)); + } + + SaleOrderMaster::updateOrCreate([ + 'plant_id' => $plant->id, + 'item_id' => $item->id, + 'sale_order_number' => $this->data['sale_order_number'], + 'supplier_name' => $this->data['supplier_name'], + 'quantity' => $this->data['quantity'] ?? null, + 'created_by' => $operatorName, + 'updated_by' => $operatorName, + ]); + + return null; + } + + public static function getCompletedNotificationBody(Import $import): string + { + $body = 'Your sale order master import has completed and ' . number_format($import->successful_rows) . ' ' . str('row')->plural($import->successful_rows) . ' imported.'; + + if ($failedRowsCount = $import->getFailedRowsCount()) { + $body .= ' ' . number_format($failedRowsCount) . ' ' . str('row')->plural($failedRowsCount) . ' failed to import.'; + } + + return $body; + } +}