fix: [document] document.data null 참조 오류 수정

- DocumentController: resolveAndBackfillBasicFields에서 data null-safe 처리
- show.blade.php: $docData 변수로 일괄 치환 (클로저 포함 전체 12곳)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-04 23:30:41 +09:00
parent 491426fc3e
commit fd017a9e34
2 changed files with 19 additions and 18 deletions

View File

@@ -290,7 +290,7 @@ private function resolveAndBackfillBasicFields(Document $document): void
}
// bf_ 레코드가 하나라도 있으면 이미 저장된 것 → skip
$existingBfCount = $document->data
$existingBfCount = ($document->data ?? collect())
->filter(fn ($d) => str_starts_with($d->field_key, 'bf_'))
->count();
if ($existingBfCount > 0) {

View File

@@ -3,6 +3,7 @@
@section('title', '문서 상세')
@section('content')
@php $docData = $document->data ?? collect(); @endphp
<!-- 헤더 -->
<div class="flex flex-col lg:flex-row lg:justify-between lg:items-center gap-4 mb-6">
<div>
@@ -116,10 +117,10 @@ class="bg-gray-200 hover:bg-gray-300 text-gray-700 px-4 py-2 rounded-lg transiti
@foreach($document->template->basicFields as $field)
@php
$fieldKey = 'bf_' . $field->id;
$fieldData = $document->data->where('field_key', $fieldKey)->first();
$fieldData = $docData->where('field_key', $fieldKey)->first();
// 레거시 호환: bf_{label} 형식으로 저장된 데이터도 조회
if (!$fieldData) {
$fieldData = $document->data->where('field_key', 'bf_' . $field->label)->first();
$fieldData = $docData->where('field_key', 'bf_' . $field->label)->first();
}
$value = $fieldData?->field_value ?? '-';
@endphp
@@ -320,7 +321,7 @@ class="px-2 py-2 text-center text-xs font-medium text-gray-600 border border-gra
{{-- 작업 통계 (document_data에서 stats_ 조회) --}}
@php
$statsData = $document->data->filter(fn($d) => str_starts_with($d->field_key, 'stats_'));
$statsData = $docData->filter(fn($d) => str_starts_with($d->field_key, 'stats_'));
$statsMap = $statsData->pluck('field_value', 'field_key')->toArray();
@endphp
@if(!empty($statsMap))
@@ -384,7 +385,7 @@ class="px-2 py-2 text-center text-xs font-medium text-gray-600 border border-gra
{{-- 비고 (document_data에서 remarks 조회) --}}
@php
$remarksData = $document->data->where('field_key', 'remarks')->first();
$remarksData = $docData->where('field_key', 'remarks')->first();
@endphp
@if($remarksData && $remarksData->field_value)
<div class="bg-white rounded-lg shadow-sm border border-gray-200 p-6">
@@ -413,9 +414,9 @@ class="px-2 py-2 text-center text-xs font-medium text-gray-600 border border-gra
@if($section->items->count() > 0 && $document->template->columns->count() > 0)
@php
// 데이터 조회 헬퍼: 정규화 형식 우선, 레거시 fallback
$getData = function($sectionId, $colId, $rowIdx, $fieldKey) use ($document) {
$getData = function($sectionId, $colId, $rowIdx, $fieldKey) use ($docData) {
// 1차: 정규화 형식 (section_id + column_id + row_index + field_key)
$record = $document->data
$record = $docData
->where('section_id', $sectionId)
->where('column_id', $colId)
->where('row_index', $rowIdx)
@@ -425,9 +426,9 @@ class="px-2 py-2 text-center text-xs font-medium text-gray-600 border border-gra
};
// 레거시 데이터 조회 헬퍼 (수입검사 호환: {itemId}_n{n}, {itemId}_result 등)
$getLegacyData = function($itemId, $fieldKey) use ($document) {
return $document->data->where('field_key', "{$itemId}_{$fieldKey}")->first()?->field_value
?? $document->data->where('field_key', $fieldKey)->first()?->field_value
$getLegacyData = function($itemId, $fieldKey) use ($docData) {
return $docData->where('field_key', "{$itemId}_{$fieldKey}")->first()?->field_value
?? $docData->where('field_key', $fieldKey)->first()?->field_value
?? '';
};
@@ -518,7 +519,7 @@ class="px-2 py-2 text-center text-xs font-medium text-gray-600 uppercase border
// fallback: document_data의 max row_index + 1
$rowCount = $workOrderItems->isNotEmpty()
? $workOrderItems->count()
: max(1, ($document->data->where('section_id', $section->id)->max('row_index') ?? 0) + 1);
: max(1, ($docData->where('section_id', $section->id)->max('row_index') ?? 0) + 1);
@endphp
@for($rowIndex = 0; $rowIndex < $rowCount; $rowIndex++)
<tr class="hover:bg-gray-50">
@@ -620,7 +621,7 @@ class="px-2 py-2 text-center text-xs font-medium text-gray-600 uppercase border
@php
$savedVal = $getData($section->id, $col->id, $rowIndex, 'value');
if (!$savedVal) {
$rowJudgment = $document->data->where('field_key', 'row_judgment')->where('row_index', $rowIndex)->first()?->field_value ?? '';
$rowJudgment = $docData->where('field_key', 'row_judgment')->where('row_index', $rowIndex)->first()?->field_value ?? '';
if (in_array(strtolower($rowJudgment), ['pass', 'ok', '적합'])) $savedVal = 'OK';
elseif (in_array(strtolower($rowJudgment), ['fail', 'ng', '부적합'])) $savedVal = 'NG';
}
@@ -684,7 +685,7 @@ class="px-2 py-2 text-center text-xs font-medium text-gray-600 uppercase border
@php
$savedVal = $getData($section->id, $col->id, $rowIndex, 'value');
if (!$savedVal) {
$rowJudgment = $document->data->where('field_key', 'row_judgment')->where('row_index', $rowIndex)->first()?->field_value ?? '';
$rowJudgment = $docData->where('field_key', 'row_judgment')->where('row_index', $rowIndex)->first()?->field_value ?? '';
if (in_array(strtolower($rowJudgment), ['pass', 'ok', '적합'])) $savedVal = 'OK';
elseif (in_array(strtolower($rowJudgment), ['fail', 'ng', '부적합'])) $savedVal = 'NG';
}
@@ -726,15 +727,15 @@ class="px-2 py-2 text-center text-xs font-medium text-gray-600 uppercase border
@if($loop->last)
@php
// React 형식: overall_result, remark (+ 레거시 호환: footer_judgement, footer_remark)
$remarkVal = $document->data->where('field_key', 'remark')->first()?->field_value
?? $document->data->where('field_key', 'footer_remark')->first()?->field_value
$remarkVal = $docData->where('field_key', 'remark')->first()?->field_value
?? $docData->where('field_key', 'footer_remark')->first()?->field_value
?? '';
$judgementVal = $document->data->where('field_key', 'overall_result')->first()?->field_value
?? $document->data->where('field_key', 'footer_judgement')->first()?->field_value
$judgementVal = $docData->where('field_key', 'overall_result')->first()?->field_value
?? $docData->where('field_key', 'footer_judgement')->first()?->field_value
?? '';
// fallback: overall_result 없으면 row_judgment에서 계산 (전체 행 수 대비 판정)
if (!$judgementVal) {
$rowJudgments = $document->data->where('field_key', 'row_judgment')->pluck('field_value');
$rowJudgments = $docData->where('field_key', 'row_judgment')->pluck('field_value');
if ($rowJudgments->isNotEmpty() && $rowJudgments->count() >= $rowCount) {
$hasFail = $rowJudgments->contains(fn($v) => in_array(strtolower($v), ['fail', '부', '부적합', '불합격']));
$allPass = $rowJudgments->every(fn($v) => in_array(strtolower($v), ['pass', '적', '적합', '합격']));