fix(API): 견적 관리 필드 저장/조회 개선

- QuoteStoreRequest/UpdateRequest: manager, contact, remarks 필드 추가
- QuoteController: store에서 validated 데이터 로깅 추가 (디버깅용)
- QuoteService: manager, contact, remarks 필드 저장/조회 로직 추가
- FormulaEvaluatorService: BOM 계산 서비스 개선

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-06 20:57:51 +09:00
parent 494bdd19da
commit d6783b4a15
5 changed files with 282 additions and 23 deletions

View File

@@ -101,7 +101,11 @@ public function show(int $id): Quote
}
/**
* 저장된 calculation_inputs를 기반으로 BOM 자재 목록 계산
* 저장된 calculation_inputs를 기반으로 BOM 자재(leaf nodes) 목록 조회
*
* 세부산출내역과 달리, BOM 트리에서 실제 원자재만 추출합니다:
* - 세부산출내역: BOM 계산 결과 (수식 기반 산출 품목)
* - 소요자재내역: BOM 트리 leaf nodes (실제 구매 필요한 원자재)
*/
private function calculateBomMaterials(Quote $quote): array
{
@@ -112,6 +116,7 @@ private function calculateBomMaterials(Quote $quote): array
return [];
}
$tenantId = $this->tenantId();
$inputItems = $calculationInputs['items'];
$allMaterials = [];
@@ -122,11 +127,14 @@ private function calculateBomMaterials(Quote $quote): array
continue;
}
// 주문 수량
$orderQuantity = (float) ($input['quantity'] ?? 1);
// BOM 계산을 위한 입력 변수 구성
$bomInputs = [
$variables = [
'W0' => (float) ($input['openWidth'] ?? 0),
'H0' => (float) ($input['openHeight'] ?? 0),
'QTY' => (float) ($input['quantity'] ?? 1),
'QTY' => $orderQuantity,
'PC' => $input['productCategory'] ?? 'SCREEN',
'GT' => $input['guideRailType'] ?? 'wall',
'MP' => $input['motorPower'] ?? 'single',
@@ -136,27 +144,33 @@ private function calculateBomMaterials(Quote $quote): array
];
try {
$result = $this->calculationService->calculateBom($finishedGoodsCode, $bomInputs, false);
// BOM 트리에서 원자재(leaf nodes)만 추출
$leafMaterials = $this->calculationService->formulaEvaluator->getBomLeafMaterials(
$finishedGoodsCode,
$orderQuantity,
$variables,
$tenantId
);
if (($result['success'] ?? false) && ! empty($result['items'])) {
// 각 자재 항목에 인덱스 정보 추가
foreach ($result['items'] as $material) {
$allMaterials[] = [
'item_index' => $index,
'finished_goods_code' => $finishedGoodsCode,
'item_code' => $material['item_code'] ?? '',
'item_name' => $material['item_name'] ?? '',
'specification' => $material['specification'] ?? '',
'unit' => $material['unit'] ?? 'EA',
'quantity' => $material['quantity'] ?? 0,
'unit_price' => $material['unit_price'] ?? 0,
'total_price' => $material['total_price'] ?? 0,
'formula_category' => $material['formula_category'] ?? '',
];
}
// 각 자재 항목에 인덱스 정보 추가
foreach ($leafMaterials as $material) {
$allMaterials[] = [
'item_index' => $index,
'finished_goods_code' => $finishedGoodsCode,
'item_code' => $material['item_code'] ?? '',
'item_name' => $material['item_name'] ?? '',
'item_type' => $material['item_type'] ?? '',
'item_category' => $material['item_category'] ?? '',
'specification' => $material['specification'] ?? '',
'unit' => $material['unit'] ?? 'EA',
'quantity' => $material['quantity'] ?? 0,
'unit_price' => $material['unit_price'] ?? 0,
'total_price' => $material['total_price'] ?? 0,
'process_type' => $material['process_type'] ?? '',
];
}
} catch (\Throwable) {
// BOM 계산 실패 시 해당 품목은 스킵
// BOM 조회 실패 시 해당 품목은 스킵
continue;
}
}