refactor: [performance] N+1 쿼리 3건 배치 조회로 최적화
- WorkOrderService.getMaterials(): 기존 BOM 루프 내 find() x2 제거 → 루프 전 bomItemsMap/bomChildItemsMap 일괄 사전 로드 - OrderService.createWorkOrderFromOrder(): 루프 내 DB 쿼리 x2 제거 → item_code→id, process_items 사전 배치 조회 - OrderService.checkBendingStockForOrder(): 루프 내 StockService 호출 제거 → Stock 배치 조회 후 맵 참조
This commit is contained in:
@@ -1486,6 +1486,35 @@ public function getMaterials(int $workOrderId): array
|
||||
->keyBy('id');
|
||||
}
|
||||
|
||||
// ── Step 1.5: 기존 BOM용 item_id 일괄 사전 로드 (N+1 방지) ──
|
||||
$bomParentItemIds = $workOrder->items->pluck('item_id')->filter()->unique()->values()->all();
|
||||
$bomItemsMap = collect();
|
||||
$bomChildItemsMap = collect();
|
||||
if (! empty($bomParentItemIds)) {
|
||||
$bomItemsMap = \App\Models\Items\Item::where('tenant_id', $tenantId)
|
||||
->whereIn('id', $bomParentItemIds)
|
||||
->get()
|
||||
->keyBy('id');
|
||||
|
||||
// BOM 자식 item_id 수집 및 배치 조회
|
||||
$allChildIds = [];
|
||||
foreach ($bomItemsMap as $parentItem) {
|
||||
if (! empty($parentItem->bom)) {
|
||||
foreach ($parentItem->bom as $bomEntry) {
|
||||
if (! empty($bomEntry['child_item_id'])) {
|
||||
$allChildIds[] = $bomEntry['child_item_id'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (! empty($allChildIds)) {
|
||||
$bomChildItemsMap = \App\Models\Items\Item::where('tenant_id', $tenantId)
|
||||
->whereIn('id', array_unique($allChildIds))
|
||||
->get()
|
||||
->keyBy('id');
|
||||
}
|
||||
}
|
||||
|
||||
// ── Step 2: 유니크 자재 목록 수집 ──
|
||||
// 키: dynamic_bom → "{item_id}_{woItem_id}", 기존 BOM → "{item_id}"
|
||||
$uniqueMaterials = [];
|
||||
@@ -1527,12 +1556,11 @@ public function getMaterials(int $workOrderId): array
|
||||
continue; // dynamic_bom이 있으면 기존 BOM fallback 건너뜀
|
||||
}
|
||||
|
||||
// 기존 BOM 로직 (하위 호환)
|
||||
// 기존 BOM 로직 (하위 호환) — 사전 로드된 맵 사용
|
||||
$materialItems = [];
|
||||
|
||||
if ($woItem->item_id) {
|
||||
$item = \App\Models\Items\Item::where('tenant_id', $tenantId)
|
||||
->find($woItem->item_id);
|
||||
$item = $bomItemsMap[$woItem->item_id] ?? null;
|
||||
|
||||
if ($item && ! empty($item->bom)) {
|
||||
foreach ($item->bom as $bomItem) {
|
||||
@@ -1543,8 +1571,7 @@ public function getMaterials(int $workOrderId): array
|
||||
continue;
|
||||
}
|
||||
|
||||
$childItem = \App\Models\Items\Item::where('tenant_id', $tenantId)
|
||||
->find($childItemId);
|
||||
$childItem = $bomChildItemsMap[$childItemId] ?? null;
|
||||
|
||||
if (! $childItem) {
|
||||
continue;
|
||||
|
||||
Reference in New Issue
Block a user