fix: [production] 절곡 검사 데이터 전체 item 복제 + bending EAV 변환
- storeItemInspection: bending/bending_wip 시 동일 작업지시 모든 item에 복제 저장 - transformBendingProductsToRecords: products 배열 → bending EAV 레코드 변환 - getMaterialInputLots: 품목코드별 그룹핑으로 변경 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1837,25 +1837,25 @@ public function getMaterialInputLots(int $workOrderId): array
|
||||
->orderBy('created_at')
|
||||
->get(['id', 'lot_no', 'item_code', 'item_name', 'qty', 'stock_lot_id', 'created_at']);
|
||||
|
||||
// LOT 번호별 그룹핑 (동일 LOT에서 여러번 투입 가능)
|
||||
$lotMap = [];
|
||||
// 품목코드별 그룹핑 (작업일지에서 item_code → lot_no 매핑에 사용)
|
||||
$itemMap = [];
|
||||
foreach ($transactions as $tx) {
|
||||
$lotNo = $tx->lot_no;
|
||||
if (! isset($lotMap[$lotNo])) {
|
||||
$lotMap[$lotNo] = [
|
||||
'lot_no' => $lotNo,
|
||||
'item_code' => $tx->item_code,
|
||||
$itemCode = $tx->item_code;
|
||||
if (! isset($itemMap[$itemCode])) {
|
||||
$itemMap[$itemCode] = [
|
||||
'item_code' => $itemCode,
|
||||
'lot_no' => $tx->lot_no,
|
||||
'item_name' => $tx->item_name,
|
||||
'total_qty' => 0,
|
||||
'input_count' => 0,
|
||||
'first_input_at' => $tx->created_at,
|
||||
];
|
||||
}
|
||||
$lotMap[$lotNo]['total_qty'] += abs((float) $tx->qty);
|
||||
$lotMap[$lotNo]['input_count']++;
|
||||
$itemMap[$itemCode]['total_qty'] += abs((float) $tx->qty);
|
||||
$itemMap[$itemCode]['input_count']++;
|
||||
}
|
||||
|
||||
return array_values($lotMap);
|
||||
return array_values($itemMap);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
@@ -1890,6 +1890,16 @@ public function storeItemInspection(int $workOrderId, int $itemId, array $data):
|
||||
$item->setInspectionData($inspectionData);
|
||||
$item->save();
|
||||
|
||||
// 절곡 공정: 수주 단위 검사 → 동일 작업지시의 모든 item에 검사 데이터 복제
|
||||
$processType = $data['process_type'] ?? '';
|
||||
if (in_array($processType, ['bending', 'bending_wip'])) {
|
||||
$otherItems = $workOrder->items()->where('id', '!=', $itemId)->get();
|
||||
foreach ($otherItems as $otherItem) {
|
||||
$otherItem->setInspectionData($inspectionData);
|
||||
$otherItem->save();
|
||||
}
|
||||
}
|
||||
|
||||
// 감사 로그
|
||||
$this->auditLogger->log(
|
||||
$tenantId,
|
||||
@@ -2492,10 +2502,107 @@ private function transformInspectionDataToDocumentRecords(array $rawItems, int $
|
||||
], $rawItems);
|
||||
}
|
||||
|
||||
// 절곡 products 배열 감지 → bending 전용 EAV 레코드 생성
|
||||
$productsItem = collect($rawItems)->first(fn ($item) => isset($item['products']) && is_array($item['products']));
|
||||
if ($productsItem) {
|
||||
return $this->transformBendingProductsToRecords($productsItem, $templateId);
|
||||
}
|
||||
|
||||
// 레거시 형식: templateValues/values 기반 → 정규화 변환
|
||||
return $this->normalizeOldFormatRecords($rawItems, $templateId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 절곡 products 배열 → bending 전용 EAV 레코드 변환
|
||||
*
|
||||
* InspectionInputModal이 저장하는 products 형식:
|
||||
* [{ id, bendingStatus: '양호'|'불량', lengthMeasured, widthMeasured, gapPoints: [{point, designValue, measured}] }]
|
||||
*
|
||||
* 프론트엔드 TemplateInspectionContent가 기대하는 EAV field_key 형식:
|
||||
* b{productIdx}_ok / b{productIdx}_ng, b{productIdx}_n1, b{productIdx}_p{pointIdx}_n1
|
||||
*/
|
||||
private function transformBendingProductsToRecords(array $item, int $templateId): array
|
||||
{
|
||||
$template = DocumentTemplate::with(['columns'])->find($templateId);
|
||||
if (! $template) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// 컬럼 식별 (column_type + sort_order 기반)
|
||||
$checkCol = $template->columns->firstWhere('column_type', 'check');
|
||||
$complexCols = $template->columns->where('column_type', 'complex')->sortBy('sort_order')->values();
|
||||
// complex 컬럼 순서: 길이(0), 너비(1), 간격(2)
|
||||
$lengthCol = $complexCols->get(0);
|
||||
$widthCol = $complexCols->get(1);
|
||||
$gapCol = $complexCols->get(2);
|
||||
|
||||
$records = [];
|
||||
$products = $item['products'];
|
||||
|
||||
foreach ($products as $productIdx => $product) {
|
||||
// 절곡상태 → check column
|
||||
if ($checkCol) {
|
||||
if (($product['bendingStatus'] ?? null) === '양호') {
|
||||
$records[] = [
|
||||
'section_id' => null, 'column_id' => $checkCol->id,
|
||||
'row_index' => $productIdx, 'field_key' => "b{$productIdx}_ok", 'field_value' => 'OK',
|
||||
];
|
||||
} elseif (($product['bendingStatus'] ?? null) === '불량') {
|
||||
$records[] = [
|
||||
'section_id' => null, 'column_id' => $checkCol->id,
|
||||
'row_index' => $productIdx, 'field_key' => "b{$productIdx}_ng", 'field_value' => 'NG',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// 길이 → first complex column
|
||||
if ($lengthCol && ! empty($product['lengthMeasured'])) {
|
||||
$records[] = [
|
||||
'section_id' => null, 'column_id' => $lengthCol->id,
|
||||
'row_index' => $productIdx, 'field_key' => "b{$productIdx}_n1", 'field_value' => (string) $product['lengthMeasured'],
|
||||
];
|
||||
}
|
||||
|
||||
// 너비 → second complex column
|
||||
if ($widthCol && ! empty($product['widthMeasured'])) {
|
||||
$records[] = [
|
||||
'section_id' => null, 'column_id' => $widthCol->id,
|
||||
'row_index' => $productIdx, 'field_key' => "b{$productIdx}_n1", 'field_value' => (string) $product['widthMeasured'],
|
||||
];
|
||||
}
|
||||
|
||||
// 간격 포인트 → third complex column (gap)
|
||||
if ($gapCol && ! empty($product['gapPoints'])) {
|
||||
foreach ($product['gapPoints'] as $pointIdx => $gp) {
|
||||
if (! empty($gp['measured'])) {
|
||||
$records[] = [
|
||||
'section_id' => null, 'column_id' => $gapCol->id,
|
||||
'row_index' => $productIdx, 'field_key' => "b{$productIdx}_p{$pointIdx}_n1", 'field_value' => (string) $gp['measured'],
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 전체 판정
|
||||
if (isset($item['judgment'])) {
|
||||
$records[] = [
|
||||
'section_id' => null, 'column_id' => null,
|
||||
'row_index' => 0, 'field_key' => 'overall_result', 'field_value' => (string) $item['judgment'],
|
||||
];
|
||||
}
|
||||
|
||||
// 부적합 내용
|
||||
if (! empty($item['nonConformingContent'])) {
|
||||
$records[] = [
|
||||
'section_id' => null, 'column_id' => null,
|
||||
'row_index' => 0, 'field_key' => 'remark', 'field_value' => (string) $item['nonConformingContent'],
|
||||
];
|
||||
}
|
||||
|
||||
return $records;
|
||||
}
|
||||
|
||||
/**
|
||||
* 레거시 형식(section_X_item_Y 키)을 정규화 레코드로 변환
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user