feat(API): 중간검사 문서 템플릿 동적 연동 - process_steps ↔ document_templates 연결
- process_steps 테이블에 document_template_id FK 추가 (migration) - ProcessStep 모델에 documentTemplate BelongsTo 관계 추가 - ProcessStepService에서 documentTemplate eager loading - StoreProcessStepRequest/UpdateProcessStepRequest에 document_template_id 유효성 검증 - WorkOrderService에 getInspectionTemplate(), createInspectionDocument() 메서드 추가 - WorkOrderController에 inspection-template/inspection-document 엔드포인트 추가 - DocumentService.formatTemplateForReact() 접근자 public으로 변경 - i18n 메시지 키 추가 (inspection_document_created, no_inspection_template) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Models\Documents\DocumentTemplate;
|
||||
use App\Models\Orders\Order;
|
||||
use App\Models\Production\WorkOrder;
|
||||
use App\Models\Production\WorkOrderAssignee;
|
||||
@@ -1621,6 +1622,159 @@ public function getInspectionData(int $workOrderId, array $params = []): array
|
||||
];
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
// 검사 문서 템플릿 연동
|
||||
// ──────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* 작업지시의 검사용 문서 템플릿 조회
|
||||
*
|
||||
* work_order → process → steps(needs_inspection=true) → documentTemplate 로드
|
||||
*/
|
||||
public function getInspectionTemplate(int $workOrderId): array
|
||||
{
|
||||
$tenantId = $this->tenantId();
|
||||
|
||||
$workOrder = WorkOrder::where('tenant_id', $tenantId)
|
||||
->with([
|
||||
'process.steps' => fn ($q) => $q->where('is_active', true)
|
||||
->where('needs_inspection', true)
|
||||
->whereNotNull('document_template_id')
|
||||
->orderBy('sort_order'),
|
||||
'process.steps.documentTemplate' => fn ($q) => $q->with([
|
||||
'approvalLines',
|
||||
'basicFields',
|
||||
'sections.items',
|
||||
'columns',
|
||||
'sectionFields',
|
||||
]),
|
||||
'salesOrder:id,order_no,client_name,site_name',
|
||||
'items:id,work_order_id,item_name,specification,quantity,unit,sort_order',
|
||||
])
|
||||
->find($workOrderId);
|
||||
|
||||
if (! $workOrder) {
|
||||
throw new NotFoundHttpException(__('error.not_found'));
|
||||
}
|
||||
|
||||
$inspectionSteps = $workOrder->process?->steps ?? collect();
|
||||
if ($inspectionSteps->isEmpty()) {
|
||||
return [
|
||||
'work_order_id' => $workOrderId,
|
||||
'has_template' => false,
|
||||
'template' => null,
|
||||
'work_order_info' => $this->buildWorkOrderInfo($workOrder),
|
||||
];
|
||||
}
|
||||
|
||||
// 첫 번째 검사 단계의 템플릿 사용 (향후 다중 검사 단계 지원 가능)
|
||||
$inspectionStep = $inspectionSteps->first();
|
||||
$template = $inspectionStep->documentTemplate;
|
||||
|
||||
if (! $template) {
|
||||
return [
|
||||
'work_order_id' => $workOrderId,
|
||||
'has_template' => false,
|
||||
'template' => null,
|
||||
'work_order_info' => $this->buildWorkOrderInfo($workOrder),
|
||||
];
|
||||
}
|
||||
|
||||
// DocumentService의 formatTemplateForReact와 동일한 포맷
|
||||
$documentService = app(DocumentService::class);
|
||||
$formattedTemplate = $documentService->formatTemplateForReact($template);
|
||||
|
||||
return [
|
||||
'work_order_id' => $workOrderId,
|
||||
'has_template' => true,
|
||||
'template' => $formattedTemplate,
|
||||
'work_order_info' => $this->buildWorkOrderInfo($workOrder),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 검사 완료 시 Document + DocumentData 생성
|
||||
*/
|
||||
public function createInspectionDocument(int $workOrderId, array $inspectionData): array
|
||||
{
|
||||
$tenantId = $this->tenantId();
|
||||
$userId = $this->apiUserId();
|
||||
|
||||
$workOrder = WorkOrder::where('tenant_id', $tenantId)
|
||||
->with([
|
||||
'process.steps' => fn ($q) => $q->where('is_active', true)
|
||||
->where('needs_inspection', true)
|
||||
->whereNotNull('document_template_id')
|
||||
->orderBy('sort_order'),
|
||||
])
|
||||
->find($workOrderId);
|
||||
|
||||
if (! $workOrder) {
|
||||
throw new NotFoundHttpException(__('error.not_found'));
|
||||
}
|
||||
|
||||
$inspectionStep = $workOrder->process?->steps?->first();
|
||||
if (! $inspectionStep || ! $inspectionStep->document_template_id) {
|
||||
throw new BadRequestHttpException(__('error.work_order.no_inspection_template'));
|
||||
}
|
||||
|
||||
$documentService = app(DocumentService::class);
|
||||
|
||||
// DocumentService::create() 재사용
|
||||
$documentData = [
|
||||
'template_id' => $inspectionStep->document_template_id,
|
||||
'title' => $inspectionData['title'] ?? "중간검사성적서 - {$workOrder->work_order_no}",
|
||||
'linkable_type' => 'work_order',
|
||||
'linkable_id' => $workOrderId,
|
||||
'data' => $inspectionData['data'] ?? [],
|
||||
'approvers' => $inspectionData['approvers'] ?? [],
|
||||
];
|
||||
|
||||
$document = $documentService->create($documentData);
|
||||
|
||||
// 감사 로그
|
||||
$this->auditLogger->log(
|
||||
$tenantId,
|
||||
self::AUDIT_TARGET,
|
||||
$workOrderId,
|
||||
'inspection_document_created',
|
||||
null,
|
||||
['document_id' => $document->id, 'document_no' => $document->document_no]
|
||||
);
|
||||
|
||||
return [
|
||||
'document_id' => $document->id,
|
||||
'document_no' => $document->document_no,
|
||||
'status' => $document->status,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 작업지시 기본정보 빌드 (검사 문서 렌더링용)
|
||||
*/
|
||||
private function buildWorkOrderInfo(WorkOrder $workOrder): array
|
||||
{
|
||||
return [
|
||||
'id' => $workOrder->id,
|
||||
'work_order_no' => $workOrder->work_order_no,
|
||||
'project_name' => $workOrder->project_name,
|
||||
'status' => $workOrder->status,
|
||||
'scheduled_date' => $workOrder->scheduled_date,
|
||||
'sales_order' => $workOrder->salesOrder ? [
|
||||
'order_no' => $workOrder->salesOrder->order_no,
|
||||
'client_name' => $workOrder->salesOrder->client_name,
|
||||
'site_name' => $workOrder->salesOrder->site_name,
|
||||
] : null,
|
||||
'items' => $workOrder->items?->map(fn ($item) => [
|
||||
'id' => $item->id,
|
||||
'item_name' => $item->item_name,
|
||||
'specification' => $item->specification,
|
||||
'quantity' => $item->quantity,
|
||||
'unit' => $item->unit,
|
||||
])->toArray() ?? [],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 작업지시 검사 성적서용 데이터 조회 (전체 품목 + 검사 데이터 + 주문 정보)
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user