diff --git a/app/Services/Admin/Manage/PurchaseService.php b/app/Services/Admin/Manage/PurchaseService.php index c5bebe2..63a2c7b 100644 --- a/app/Services/Admin/Manage/PurchaseService.php +++ b/app/Services/Admin/Manage/PurchaseService.php @@ -27,6 +27,7 @@ public function paginated(int $perPage = 25, string $search = '', string $sort = { $itemCountQuery = '(SELECT COUNT(*) FROM purchase_items WHERE purchase_items.purchase_id = purchases.id AND purchase_items.deleted_at IS NULL)'; $totalQtyQuery = '(SELECT IFNULL(SUM(quantity), 0) FROM purchase_items WHERE purchase_items.purchase_id = purchases.id AND purchase_items.deleted_at IS NULL)'; + $materialsCountQuery = '(SELECT COUNT(DISTINCT raw_materials.id) FROM purchase_items JOIN raw_material_prices ON raw_material_prices.id = purchase_items.raw_material_price_id JOIN raw_materials ON raw_materials.id = raw_material_prices.raw_material_id WHERE purchase_items.purchase_id = purchases.id AND purchase_items.deleted_at IS NULL)'; $materialNameQuery = '(SELECT raw_materials.name FROM purchase_items JOIN raw_material_prices ON raw_material_prices.id = purchase_items.raw_material_price_id JOIN raw_materials ON raw_materials.id = raw_material_prices.raw_material_id WHERE purchase_items.purchase_id = purchases.id AND purchase_items.deleted_at IS NULL LIMIT 1)'; $unitQuery = '(SELECT raw_materials.unit FROM purchase_items JOIN raw_material_prices ON raw_material_prices.id = purchase_items.raw_material_price_id JOIN raw_materials ON raw_materials.id = raw_material_prices.raw_material_id WHERE purchase_items.purchase_id = purchases.id AND purchase_items.deleted_at IS NULL LIMIT 1)'; @@ -39,6 +40,7 @@ public function paginated(int $perPage = 25, string $search = '', string $sort = ]) ->selectRaw("{$itemCountQuery} as variants_count") ->selectRaw("{$totalQtyQuery} as total_qty") + ->selectRaw("{$materialsCountQuery} as materials_count") ->selectRaw("{$materialNameQuery} as material_name") ->selectRaw("{$unitQuery} as unit") ->when($highlight, fn ($q) => $q->where('id', $highlight)) diff --git a/resources/js/pages/admin/manage/purchase/columns.tsx b/resources/js/pages/admin/manage/purchase/columns.tsx index b8d3c15..2cac03e 100644 --- a/resources/js/pages/admin/manage/purchase/columns.tsx +++ b/resources/js/pages/admin/manage/purchase/columns.tsx @@ -20,6 +20,7 @@ export type Purchase = { photo_conversion_urls: string[]; created_at: string; variants_count: number; + materials_count: number; total_qty: number; material_name: string | null; unit: string | null; diff --git a/resources/js/pages/admin/manage/purchase/purchase-card.tsx b/resources/js/pages/admin/manage/purchase/purchase-card.tsx index 6193b4b..b33a6bb 100644 --- a/resources/js/pages/admin/manage/purchase/purchase-card.tsx +++ b/resources/js/pages/admin/manage/purchase/purchase-card.tsx @@ -28,6 +28,7 @@ export function PurchaseCardRow({ const { can } = useCan(); const variantCount = purchase.variants_count ?? 0; const totalQty = purchase.total_qty ?? 0; + const materialsCount = purchase.materials_count ?? 0; const rawMaterialName = purchase.material_name ?? '-'; const unit = purchase.unit ?? ''; @@ -58,7 +59,11 @@ export function PurchaseCardRow({
- {rawMaterialName} + {materialsCount > 1 ? ( + {materialsCount} bahan baku + ) : ( + {rawMaterialName} + )} {variantCount > 0 && ( ({variantCount} varian) diff --git a/resources/js/pages/admin/manage/purchase/purchase-sub-row.tsx b/resources/js/pages/admin/manage/purchase/purchase-sub-row.tsx index f3bf1e8..03e542e 100644 --- a/resources/js/pages/admin/manage/purchase/purchase-sub-row.tsx +++ b/resources/js/pages/admin/manage/purchase/purchase-sub-row.tsx @@ -9,6 +9,7 @@ import { } from '@/components/ui/table'; import { formatNumber } from '@/lib/format'; import { formatCurrency } from '@/lib/utils'; +import { Fragment } from 'react'; import type { Purchase, PurchaseItemDetail } from './columns'; export function PurchaseItemSubRow({ @@ -20,10 +21,31 @@ export function PurchaseItemSubRow({ items: PurchaseItemDetail[]; isLoading: boolean; }) { - const unit = purchase.unit ?? ''; + const items = loadedItems ?? []; + + const groupedByMaterial = items.reduce( + (acc, item) => { + const materialName = item.raw_material_price?.raw_material?.name ?? '-'; + const unit = item.raw_material_price?.raw_material?.unit ?? ''; + + if (!acc[materialName]) { + acc[materialName] = { unit, items: [] }; + } + + acc[materialName].items.push(item); + + return acc; + }, + {} as Record, + ); + + const materialEntries = Object.entries(groupedByMaterial); + const isMultiMaterial = materialEntries.length > 1; + + let counter = 0; return ( -
+
@@ -47,7 +69,7 @@ export function PurchaseItemSubRow({ Memuat item... - ) : loadedItems.length === 0 ? ( + ) : items.length === 0 ? ( ) : ( - loadedItems.map((item, index) => ( - - - {index + 1} - - - {item.raw_material_price?.photo_url ? ( - - ) : ( -
- N/A -
- )} -
- - {item.raw_material_price?.variant ?? '-'} - - - {formatCurrency(item.unit_price)} - - - {formatNumber(item.quantity)} {unit} - - - {formatCurrency(item.subtotal)} - -
- )) + <> + {materialEntries.map(([materialName, group]) => { + const totalQty = group.items.reduce( + (sum, item) => sum + item.quantity, + 0, + ); + const totalSubtotal = group.items.reduce( + (sum, item) => sum + item.subtotal, + 0, + ); + + return ( + + {isMultiMaterial && ( + + + {materialName} + + + {formatNumber(totalQty)}{' '} + {group.unit} + + + {formatCurrency(totalSubtotal)} + + + )} + {group.items.map((item) => { + counter++; + + return ( + + + {counter} + + + {item.raw_material_price?.photo_url ? ( + + ) : ( +
+ N/A +
+ )} +
+ + {item.raw_material_price?.variant ?? '-'} + + + {formatCurrency(item.unit_price)} + + + {formatNumber(item.quantity)}{' '} + {group.unit} + + + {formatCurrency(item.subtotal)} + +
+ ); + })} +
+ ); + })} + )}