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:
김보곤
2026-03-14 14:40:04 +09:00
parent 877d15420a
commit 926a7c7da6
2 changed files with 77 additions and 32 deletions

View File

@@ -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;