콘텐츠로 이동

공사상세페이지 7단계 조건렌더링 재설계

공사상세페이지 7단계 조건렌더링 재설계

섹션 제목: “공사상세페이지 7단계 조건렌더링 재설계”

[!note] 수정이력 | 2025-05-04, 분홍 (hermes)

  • 상단 7단계 스텝퍼 구현 완료
  • 하단을 단계별 조건렌더링으로 재설계 필요 (분홍아빠 요청)
  • “다음단계” 버튼은 현재 단계 필수 조건 충족 시만 활성화
접수(발생) → 실사 → 설계 → 검토 → 진행 → 준공 → 완료
테이블용도상태
projects공사 기본정보, current_stage✅ 유지
project_stage_logs단계변경 이력✅ 유지
works작업관리 (진행단계용)✅ 유지
documents공가신청/해지✅ 유지
ocr_uploadsOCR 자료반영✅ 유지
material_inputs자재투입✅ 유지

2. 단계별 데이터 모델 설계 (신규)

섹션 제목: “2. 단계별 데이터 모델 설계 (신규)”

2.1 실사단계: inspection_photos 테이블

섹션 제목: “2.1 실사단계: inspection_photos 테이블”
CREATE TABLE inspection_photos (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
photo_type VARCHAR(20) NOT NULL, -- 'before', 'after', 'panorama', 'detail'
file_path VARCHAR(500) NOT NULL,
file_name VARCHAR(255),
description TEXT,
taken_at TIMESTAMP,
uploaded_by UUID NOT NULL REFERENCES users(id),
created_at TIMESTAMP DEFAULT NOW()
);

필수조건: photo_type=‘before’ 최소 1장 + photo_type=‘after’ 최소 1장

2.2 설계단계: design_documents 테이블

섹션 제목: “2.2 설계단계: design_documents 테이블”
CREATE TABLE design_documents (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
doc_category VARCHAR(30) NOT NULL, -- 'plan', 'drawing', 'calculation', 'approval'
file_path VARCHAR(500),
file_name VARCHAR(255),
description TEXT,
created_by UUID NOT NULL REFERENCES users(id),
created_at TIMESTAMP DEFAULT NOW()
);

필수조건: doc_category=‘plan’ 최소 1개

2.3 검토단계: project_approvals 테이블

섹션 제목: “2.3 검토단계: project_approvals 테이블”
CREATE TABLE project_approvals (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
approval_date DATE NOT NULL,
request_number VARCHAR(50), -- 공사요청번호
construction_number VARCHAR(50), -- 공사번호
approved_by UUID REFERENCES users(id),
approval_note TEXT,
created_at TIMESTAMP DEFAULT NOW()
);

필수조건: approval_date + (request_number OR construction_number)

2.4 준공단계: completion_reports 테이블

섹션 제목: “2.4 준공단계: completion_reports 테이블”
CREATE TABLE completion_reports (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
report_type VARCHAR(30) NOT NULL, -- 'photo', 'document', 'checklist'
file_path VARCHAR(500),
file_name VARCHAR(255),
description TEXT,
created_by UUID NOT NULL REFERENCES users(id),
created_at TIMESTAMP DEFAULT NOW()
);

필수조건: 작업관리(works) 상태 ‘완료’ ≥ 1개

현재단계다음단계필수 조건실패 시 메시지
접수실사공사기본정보 완료 (title, location)“공사명과 위치를 입력하세요”
실사설계실사사진 ≥ 2장 (before+after)“실사 사진을 등록하세요 (현장전/후)“
설계검토설계자료 ≥ 1개”설계 계획서를 등록하세요”
검토진행승인일자 + 공사번호 입력”승인 정보를 입력하세요”
진행준공작업완료 ≥ 1개”완료된 작업이 없습니다”
준공완료준공자료 ≥ 1개”준공 자료를 등록하세요”
완료-(마감)-
[검토자료 입력] → [승인] or [반려]
→ 승인: 다음단계(진행) 버튼 활성화
→ 반려: 설계단계로 롤백 + 반려사유 기록
단계공사정보실사자료설계자료검토자료작업관리준공자료자재요약
접수✅편집❌숨김❌숨김❌숨김❌숨김❌숨김❌숨김
실사🔒읽기✅편집❌숨김❌숨김❌숨김❌숨김❌숨김
설계🔒읽기🔒읽기✅편집❌숨김❌숨김❌숨김❌숨김
검토🔒읽기🔒읽기🔒읽기✅편집❌숨김❌숨김❌숨김
진행🔒읽기🔒읽기🔒읽기🔒읽기✅편집❌숨김❌숨김
준공🔒읽기🔒읽기🔒읽기🔒읽기🔒읽기✅편집❌숨김
완료🔒읽기🔒읽기🔒읽기🔒읽기🔒읽기🔒읽기✅표시
ProjectDetailView.vue
<template>
<div v-if="project">
<!-- 상단: 공사정보 + 스텝퍼 (모든 단계 공통) -->
<ProjectHeader :project="project" />
<StageStepper :current="project.current_stage" />
<!-- 현재 단계의 활성 컴포넌트 -->
<component :is="currentStageComponent" :project="project" />
<!-- 하단: 다음단계 버튼 -->
<StageTransitionButton
:current="project.current_stage"
:validation="stageValidation"
@advance="advanceStage"
/>
</div>
</template>
컴포넌트단계설명
StageInfoEdit접수공사정보 편집 (제목, 위치, 기간)
StageInspection실사사진등록 (before/after/panorama)
StageDesign설계설계파일 업로드 + 설계정보
StageReview검토승인일자/공사번호 + 승인/반려 버튼
StageProgress진행작업관리 (기존 works 재활용)
StageCompletion준공준공자료 + 작업완료 검토
StageDone완료전체요약 + 자재요약 + 마감
const canAdvance = computed(() => {
switch (project.current_stage) {
case '접수': return !!project.title && !!project.location;
case '실사': return inspectionPhotos.value.length >= 2;
case '설계': return designDocs.value.length >= 1;
case '검토': return !!approval.approval_date && (!!approval.request_number || !!approval.construction_number);
case '진행': return completedWorks.value.length >= 1;
case '준공': return completionReports.value.length >= 1;
case '완료': return false; // 마지막 단계
default: return false;
}
});

4.5 이전단계 데이터 읽기 전용 표시

섹션 제목: “4.5 이전단계 데이터 읽기 전용 표시”
<!-- 실사단계일 때 -->
<StageInfoReadonly :project="project" /> <!-- 접수단계 데이터 읽기 -->
<StageInspectionEdit :project="project" /> <!-- 현재 활성 -->
# 실사자료
GET /api/projects/{id}/inspection-photos
POST /api/projects/{id}/inspection-photos
DELETE /api/projects/{id}/inspection-photos/{photo_id}
# 설계자료
GET /api/projects/{id}/design-documents
POST /api/projects/{id}/design-documents
DELETE /api/projects/{id}/design-documents/{doc_id}
# 검토승인
GET /api/projects/{id}/approvals
POST /api/projects/{id}/approvals
PATCH /api/projects/{id}/approvals/{approval_id}
# 준공자료
GET /api/projects/{id}/completion-reports
POST /api/projects/{id}/completion-reports
DELETE /api/projects/{id}/completion-reports/{report_id}
# 단계전이
POST /api/projects/{id}/advance-stage
BODY: { "target_stage": "설계", "note": "실사 완료" }
RESPONSE: { "success": true, "current_stage": "설계", "validation_passed": true }
@router.post("/projects/{id}/advance-stage")
async def advance_stage(project_id: UUID, req: AdvanceRequest, db: Session):
project = get_project(project_id)
# 1. 현재 단계 확인
current = project.current_stage
# 2. 다음 단계 결정
target = get_next_stage(current) # 단계 흐름 정의
# 3. 필수조건 검증
validator = StageValidator(db, project)
result = validator.validate_transition(current, target)
if not result.passed:
raise HTTPException(400, detail=result.error_message)
# 4. 단계 전이 실행
project.current_stage = target
db.add(ProjectStageLog(...))
db.commit()
return {"success": True, "stage": target}

Phase 1: 프론트엔드 UI 구조 (빠른 프로토타입)

섹션 제목: “Phase 1: 프론트엔드 UI 구조 (빠른 프로토타입)”
  • 단계별 컴포넌트 7개 생성 (StageInfoEdit, StageInspection…)
  • 조건렌더링 매트릭스 구현
  • “다음단계” 버튼 + 검증 UI (mock 검증)
  • 이전단계 읽기전용 표시

Phase 2: 백엔드 API + DB 마이그레이션

섹션 제목: “Phase 2: 백엔드 API + DB 마이그레이션”
  • Alembic 마이그레이션 (inspection_photos, design_documents, project_approvals, completion_reports)
  • CRUD API 구현
  • advance-stage API + 검증 로직
  • 프론트엔드 ↔ 백엔드 API 연동
  • 단계전이 end-to-end 테스트
  • 에러 케이스 테스트 (조건 미충족 시)
  • 자재투입 데이터 집계
  • 완료단계 마감 UI
  • 승인 → 진행단계 이동
  • 반려 → 설계단계 롤백 + 사유 필수 입력
  • 보류 → 현재 단계 유지
  • NAS WebDAV 경로에 저장 (/mnt/y/공사{project_id}/)
  • DB에는 파일 경로만 저장 (file_path)
  • 각 단계별 담당팀/역할이 다름 (ProjectTypeStage.assigned_role 참조)
  • 현재 단계의 담당자만 편집 가능, 다른 역할은 읽기만