feat:문서관리 Phase 1.3~2.1 구현 (시드데이터, 복제, 문서생성)
- Phase 1.3: EGI/SUS 수입검사 시드 데이터 생성 (IncomingInspectionTemplateSeeder) - Phase 1.5: 양식 복제 기능 (duplicate API, 테이블 버튼, JS) - Phase 2.1: 문서 생성 보완 - 문서번호 카테고리별 prefix (IQC/PRD/SLS/PUR-YYMMDD-순번) - 결재라인 초기화 (template.approvalLines → document_approvals) - 기본필드 뷰 속성 수정 (field_type, Str::slug field_key) - store()에 DB 트랜잭션 추가 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,9 +4,12 @@
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Documents\Document;
|
||||
use App\Models\Documents\DocumentApproval;
|
||||
use App\Models\Documents\DocumentData;
|
||||
use App\Models\DocumentTemplate;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class DocumentApiController extends Controller
|
||||
{
|
||||
@@ -86,37 +89,66 @@ public function store(Request $request): JsonResponse
|
||||
'data.*.field_value' => 'nullable|string',
|
||||
]);
|
||||
|
||||
// 문서 번호 생성
|
||||
$documentNo = $this->generateDocumentNo($tenantId, $request->template_id);
|
||||
try {
|
||||
DB::beginTransaction();
|
||||
|
||||
$document = Document::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'template_id' => $request->template_id,
|
||||
'document_no' => $documentNo,
|
||||
'title' => $request->title,
|
||||
'status' => Document::STATUS_DRAFT,
|
||||
'created_by' => $userId,
|
||||
'updated_by' => $userId,
|
||||
]);
|
||||
// 문서 번호 생성
|
||||
$documentNo = $this->generateDocumentNo($tenantId, $request->template_id);
|
||||
|
||||
// 문서 데이터 저장
|
||||
if ($request->filled('data')) {
|
||||
foreach ($request->data as $item) {
|
||||
if (! empty($item['field_value'])) {
|
||||
DocumentData::create([
|
||||
$document = Document::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'template_id' => $request->template_id,
|
||||
'document_no' => $documentNo,
|
||||
'title' => $request->title,
|
||||
'status' => Document::STATUS_DRAFT,
|
||||
'created_by' => $userId,
|
||||
'updated_by' => $userId,
|
||||
]);
|
||||
|
||||
// 결재라인 초기화 (템플릿의 approvalLines 기반)
|
||||
$template = DocumentTemplate::with('approvalLines')->find($request->template_id);
|
||||
if ($template && $template->approvalLines->isNotEmpty()) {
|
||||
foreach ($template->approvalLines as $line) {
|
||||
DocumentApproval::create([
|
||||
'document_id' => $document->id,
|
||||
'field_key' => $item['field_key'],
|
||||
'field_value' => $item['field_value'],
|
||||
'user_id' => $userId,
|
||||
'step' => $line->sort_order + 1,
|
||||
'role' => $line->role ?? $line->name,
|
||||
'status' => DocumentApproval::STATUS_PENDING,
|
||||
'created_by' => $userId,
|
||||
'updated_by' => $userId,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => '문서가 저장되었습니다.',
|
||||
'data' => $document->fresh(['template', 'data']),
|
||||
], 201);
|
||||
// 문서 데이터 저장
|
||||
if ($request->filled('data')) {
|
||||
foreach ($request->data as $item) {
|
||||
if (! empty($item['field_value'])) {
|
||||
DocumentData::create([
|
||||
'document_id' => $document->id,
|
||||
'field_key' => $item['field_key'],
|
||||
'field_value' => $item['field_value'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DB::commit();
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => '문서가 저장되었습니다.',
|
||||
'data' => $document->fresh(['template', 'data', 'approvals']),
|
||||
], 201);
|
||||
} catch (\Exception $e) {
|
||||
DB::rollBack();
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => '문서 생성 중 오류가 발생했습니다: '.$e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -200,27 +232,50 @@ public function destroy(int $id): JsonResponse
|
||||
|
||||
/**
|
||||
* 문서 번호 생성
|
||||
* 형식: {카테고리prefix}-{YYMMDD}-{순번}
|
||||
* 예: IQC-260131-01, PRD-260131-01
|
||||
*/
|
||||
private function generateDocumentNo(int $tenantId, int $templateId): string
|
||||
{
|
||||
$prefix = 'DOC';
|
||||
$date = now()->format('Ymd');
|
||||
$template = DocumentTemplate::find($templateId);
|
||||
$prefix = $this->getCategoryPrefix($template?->category);
|
||||
$date = now()->format('ymd');
|
||||
|
||||
$lastDocument = Document::where('tenant_id', $tenantId)
|
||||
->where('template_id', $templateId)
|
||||
->whereDate('created_at', now()->toDateString())
|
||||
->where('document_no', 'like', "{$prefix}-{$date}-%")
|
||||
->orderBy('id', 'desc')
|
||||
->first();
|
||||
|
||||
$sequence = 1;
|
||||
if ($lastDocument) {
|
||||
// 마지막 문서 번호에서 시퀀스 추출
|
||||
$parts = explode('-', $lastDocument->document_no);
|
||||
if (count($parts) >= 3) {
|
||||
$sequence = (int) end($parts) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
return sprintf('%s-%s-%04d', $prefix, $date, $sequence);
|
||||
return sprintf('%s-%s-%02d', $prefix, $date, $sequence);
|
||||
}
|
||||
|
||||
/**
|
||||
* 카테고리별 문서번호 prefix
|
||||
* 카테고리가 '품질/수입검사' 등 슬래시 포함 시 상위 카테고리 기준
|
||||
*/
|
||||
private function getCategoryPrefix(?string $category): string
|
||||
{
|
||||
if (! $category) {
|
||||
return 'DOC';
|
||||
}
|
||||
|
||||
// 상위 카테고리 추출 (슬래시 포함 시)
|
||||
$mainCategory = str_contains($category, '/') ? explode('/', $category)[0] : $category;
|
||||
|
||||
return match ($mainCategory) {
|
||||
'품질' => 'IQC',
|
||||
'생산' => 'PRD',
|
||||
'영업' => 'SLS',
|
||||
'구매' => 'PUR',
|
||||
default => 'DOC',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user