콘텐츠로 이동

공사관리ERP_설계서_v0.1

1|# 🏗️ 공사관리 ERP — 설계서 v0.1 2| 3|> 작성: 분홍 (Hermes Agent) 4|> 기획: 분홍아빠 5|> 일자: 2026-04-20 6|> 상태: 초안 (논의 기반 자동 구상, 제작 시 수정/추가 예정) 7| 8|--- 9| 10|## 1. 프로젝트 개요 11| 12|### 1.1 목표 13|- 모든 공사유형(건축, 토목, 통신 등)에 범용 가능한 웹 어플리케이션 제작 14|- 판매 모델 적용 — 회사당 독립 VM 환경 제공 15|- 기존 레드마인 변형 시스템(현재 폐지)을 대체하는 신규 구축 16| 17|### 1.2 기존 시스템 아쉬웠던 점 → 개선 방향 18|| 아쉬웠던 점 | 개선 | 19||------------|------| 20|| 플러그인 추가 불가 | 직접 개발 → 자유로운 기능 추가 | 21|| 유료 플러그인 연간 비용 | 비용 없음 | 22|| 자재관리 없었고 유료는 커스텀 불가 | 자재관리 기본 탑재 + 자유 커스텀 | 23| 24|### 1.3 프로젝트 범위 25| 26|포함: 27|- 공사 파이프라인 관리 (8단계) 28|- 역할/권한 관리 (5그룹) 29|- 자재관리 (입력 → 반영 → 불용 → 재고 자동계산) 30|- 공가신청/해지 (플러그인) 31|- OCR 자료 반영 (업로드 → 분석 → 확인) 32|- 공사유형별 파이프라인 템플릿 (관리자 커스터마이징) 33|- 플러그인 시스템 (공사유형별 on/off) 34| 35|제외: 36|- 설계서류, 준공서류, 작업계획서 등 Excel 서류 (너무 방대) 37|- 선번조사툴 (독립 웹프로그램, ERP 내부에 넣으면 무거움) 38| 39|--- 40| 41|## 2. 역할 & 권한 42| 43|### 2.1 역할 정의 44| 45|| 역할 | 권한 | 비고 | 46||------|------|------| 47|| 관리자 | 웹서버 관리, 최고권한 | 공사유형 템플릿 커스텀, 감시인 권한 조절 | 48|| 공사감독 | 거의 뷰어 | 외부 자체프로그램 사용, 실제 로그인 안 함, 감시인 | 49|| 현장대리 | 각 공사의 진행 관리 | 공사당 1명 (교체 가능), 공사감독 승인 대리 입력 | 50|| 현장팀 | 각 공사의 부분 처리 | 공사당 여러 명, 모바일 간편 입력 | 51|| 공무팀 | 공사 완료 시 서류 작성 | 준공 단계 서류 | 52| 53|### 2.2 감시인 체계 54|- 공사감독 + 회사대표 = 감시인 55|- 감시인은 기본적으로 조회만 가능 56|- 관리자가 페이지별로 조회 권한 개별 조절 가능 57|- 예: 공사목록 O, 자재현황 O, 재무정보 X 58| 59|### 2.3 현장팀 모바일 특성 60|- 회원가입 간편 (최소 정보) 61|- 로그인 간편 62|- 내용 입력 위주의 가벼운 인터페이스 63| 64|### 2.4 공사감독 승인 처리 65|- 공사감독은 외부 자체 프로그램 사용 → 이 시스템에 직접 접속 안 함 66|- 현장대리가 공사감독의 승인 결과를 대신 입력/수정 67|- 승인 상태: 승인 / 취소 / 보류 68| 69|--- 70| 71|## 3. 공사 진행 파이프라인 72| 73|### 3.1 기본 8단계 74| 75| 76|발생(접수) → 실사 → 설계 → 검토(승인) → 진행 → 현장완료 → 준공 → 완료 77| 78| 79|검토(승인) 단계 세부 상태: 80|| 상태 | 의미 | 이후 동작 | 81||------|------|----------| 82|| 승인 | 공사감독이 승인 | 다음 단계(진행)로 이동 | 83|| 취소 | 공사감독이 취소 | 이전 단계로 복귀 또는 대기 | 84|| 보류 | 공사감독이 검토 보류 | 현재 단계 유지, 재검토 대기 | 85| 86|### 3.2 진행 단계 — 공사유형별 상이 87| 88|통신선로공사 기준: 89| 90|| 단계 | 담당 | 91||------|------| 92|| 공가사전검토 | 공무팀 | 93|| 선로포설 | 현장(외선)팀 | 94|| 선번조사 | 현장(접속)팀 | 95|| 작업계획서 | 현장대리 | 96|| 절체 | 현장(접속)팀 | 97|| 선로철거 | 현장(외선)팀 | 98| 99|> - 관리자가 공사유형 템플릿에서 진행 단계를 직접 커스터마이징 100|> - 각 단계별 담당자 지정 가능 101|> - 모든 단계가 필요한 경우도 있고, 일부 단계가 생략되는 경우도 있음 (공사별 선택) 102| 103|### 3.3 준공 단계 104| 105|서류작성 → 공가신청 → 서류접수 106| 107| 108|> 공가신청은 통신공사 전용 → 플러그인으로 관리 (해당 공사유형에만 표시) 109| 110|### 3.4 검토(승인) 단계 111|- 현장대리가 승인/취소/보류 입력 112|- 승인 → 다음 단계 진행 113|- 취소 → 이전 단계로 복귀 또는 대기 114|- 보류 → 현재 단계 유지, 재검토 대기 115| 116|--- 117| 118|## 4. 자재관리 119| 120|### 4.1 흐름 121| 122| 123|최초 자재 데이터 입력 (관리자/현장대리, 사급/지입 지정) 124| ↓ 125|사용자재 입력 → 현장(외선)팀 126| ↓ 127|반영자재 재입력 → 현장(접속)팀 128| ↓ 129|불용자재 = 사용자재 - 반영자재 (자동계산) 130| ↓ 131|재고 = 최초입력 - 사용자재(반영+불용) (자동계산) 132| 133| 134|### 4.2 재고 분류 135|- 사급: 원청에서 지급한 자재 136|- 지입: 직접 구매한 자재 137|- 반납 없음 — 반영자재 + 불용자재 기준 138| 139|### 4.3 계산 예시 140| 141| 142|최초 입력: 100개 (사급) 143|사용자재: 80개 (외선 팀 입력) 144|반영자재: 60개 (접속 팀 재입력) 145|불용자재: 20개 (자동계산: 80-60) 146|재고: 20개 (자동계산: 100-80) 147| 148| 149|### 4.4 입력 주체 150| 151|| 입력 유형 | 입력자 | team_type | 152||----------|--------|-----------| 153|| 최초 | 관리자/현장대리 | 관리자 | 154|| 사용 | 현장(외선)팀 | 외선 | 155|| 반영 | 현장(접속)팀 | 접속 | 156| 157|--- 158| 159|## 5. 플러그인 시스템 160| 161|### 5.1 개념 162|- 공사유형에 따라 표시 여부가 다른 기능을 플러그인으로 관리 163|- 관리자가 회사별로 플러그인 on/off 164|- 공사유형별로도 플러그인 on/off 165| 166|### 5.2 플러그인 목록 (초안) 167| 168|| plugin_key | 설명 | 기본 | 169||-----------|------|------| 170|| 공가신청 | 공가신청/해지 기능 | OFF (통신공사만 ON) | 171|| 선번조사결과 | 선번조사 결과 반영 (OCR) | OFF | 172|| 자재관리 | 자재 입력/추적 | ON | 173| 174|> 향후 플러그인 계속 추가 가능 175| 176|### 5.3 플러그인 연동 구조 177| 178|Plugin (회사별 on/off) 179| └── ProjectTypePlugin (공사유형별 on/off) 180| └── UI에 표시/숨김 181| 182| 183|--- 184| 185|## 6. 배포 아키텍처 186| 187|### 6.1 인프라 구성 188| 189| 190|서버컴 (Proxmox) 191|├── 가상헤놀로지 (회사 NAS) 192|├── 공사관리ERP VM #1 (A회사용, 독립도메인) 193|├── 공사관리ERP VM #2 (B회사용, 독립도메인) 194|└── ... 195| 196| 197|### 6.2 VM 당 Docker 구성 198| 199| 200|Docker Compose 201|├── 프론트엔드 (Vue 3 + Vuetify) — 관리자 UI에 강함 202|├── 백엔드 (FastAPI) — 가볍고 빠름, OCR 연동 유리 203|├── PostgreSQL — 데이터베이스 204|├── Redis — 세션/캐시 205|├── OCR 서비스 — Tesseract / 클라우드 OCR 206|└── Nginx — 리버스프록시 + SSL 207| 208| 209|### 6.3 배포 흐름 210| 211|신규 회사 추가 시: 212|1. Proxmox에서 VM 생성 (또는 템플릿 복제) 213|2. Docker Compose 배포 214|3. 도메인 설정 + SSL 인증서 215|4. 관리자 계정 생성 216|5. 회사별 초기 설정 (공사유형, 자재, 플러그인) 217| 218| 219|### 6.4 백업 전략 220|- VM 스냅샷 (Proxmox) 221|- PostgreSQL 정기 백업 (pg_dump) 222|- 백업 파일 NAS 저장 223|- 세부 스케줄: 미정 (구현 시 결정) 224| 225|--- 226| 227|## 7. DB 설계 228| 229|### 7.1 Company (회사 — VM당 1개) 230| 231|| 컬럼 | 타입 | 설명 | 232||------|------|------| 233|| id | UUID PK | | 234|| name | VARCHAR(100) | 회사명 | 235|| business_number | VARCHAR(20) | 사업자등록번호 | 236|| domain | VARCHAR(100) | 전용 도메인 | 237|| address | TEXT | 회사 주소 | 238|| phone | VARCHAR(20) | 대표 전화 | 239|| email | VARCHAR(100) | 대표 이메일 | 240|| logo_url | VARCHAR(500) | 회사 로고 | 241|| settings | JSONB | 회사별 설정 | 242|| subscription | ENUM(무료/기본/프리미엄) | 구독 플랜 | 243|| subscription_expires | TIMESTAMP | 구독 만료일 | 244|| is_active | BOOLEAN | DEFAULT TRUE | 245|| created_at | TIMESTAMP | | 246|| updated_at | TIMESTAMP | | 247| 248|settings JSONB 예시: 249|json 250|{ 251| "default_lang": "ko", 252| "timezone": "Asia/Seoul", 253| "max_projects": 100, 254| "max_users": 50, 255| "features": { 256| "공가신청": true, 257| "자재관리": true, 258| "OCR": false 259| } 260|} 261| 262| 263|--- 264| 265|### 7.2 User (사용자) 266| 267|| 컬럼 | 타입 | 설명 | 268||------|------|------| 269|| id | UUID PK | | 270|| company_id | UUID FK → Company | | 271|| name | VARCHAR(50) | 이름 | 272|| email | VARCHAR(100) | 로그인ID | 273|| password_hash | VARCHAR(255) | 비밀번호 (현장팀은 간단히) | 274|| phone | VARCHAR(20) | 연락처 | 275|| role | ENUM(관리자/공사감독/현장대리/현장팀/공무팀) | 역할 | 276|| team_type | ENUM(외선/접속/기타) | 현장팀만, 나머지 NULL | 277|| is_active | BOOLEAN | DEFAULT TRUE | 278|| last_login_at | TIMESTAMP | | 279|| created_at | TIMESTAMP | | 280|| updated_at | TIMESTAMP | | 281| 282|--- 283| 284|### 7.3 ViewerPermission (감시인 페이지 권한) 285| 286|| 컬럼 | 타입 | 설명 | 287||------|------|------| 288|| id | UUID PK | | 289|| user_id | UUID FK → User | 감시인 | 290|| page_key | VARCHAR(50) | 예: 공사목록/자재현황/진행상태 | 291|| can_view | BOOLEAN | DEFAULT TRUE | 292|| granted_by | UUID FK → User | 권한 부여한 관리자 | 293| 294|--- 295| 296|### 7.4 ProjectType (공사유형 템플릿) 297| 298|| 컬럼 | 타입 | 설명 | 299||------|------|------| 300|| id | UUID PK | | 301|| company_id | UUID FK → Company | | 302|| name | VARCHAR(100) | 예: 통신선로공사, 건축공사 | 303|| description | TEXT | 설명 | 304|| is_active | BOOLEAN | DEFAULT TRUE | 305|| created_at | TIMESTAMP | | 306|| updated_at | TIMESTAMP | | 307| 308|--- 309| 310|### 7.5 ProjectTypeStage (유형별 파이프라인 단계) 311| 312|| 컬럼 | 타입 | 설명 | 313||------|------|------| 314|| id | UUID PK | | 315|| project_type_id | UUID FK → ProjectType | | 316|| stage_group | ENUM(발생/실사/설계/검토/진행/현장완료/준공/완료) | 대분류 | 317|| stage_name | VARCHAR(100) | 예: 공가사전검토 | 318|| stage_order | INT | 정렬순서 | 319|| assigned_role | ENUM(관리자/공사감독/현장대리/현장팀/공무팀) | 담당 역할 | 320|| assigned_team_type | ENUM(외선/접속/기타) | 현장팀인 경우 세분류 | 321|| is_required | BOOLEAN | DEFAULT TRUE, 필수단계 여부 | 322|| created_at | TIMESTAMP | | 323|| updated_at | TIMESTAMP | | 324| 325|예시 — 통신선로공사: 326| 327|| stage_group | stage_name | order | assigned_role | assigned_team_type | is_required | 328||-------------|-----------|-------|---------------|---------------------|-------------| 329|| 발생 | 접수 | 1 | 현장대리 | - | TRUE | 330|| 실사 | 실사 | 2 | 현장대리 | - | TRUE | 331|| 설계 | 설계 | 3 | 현장대리 | - | TRUE | 332|| 검토 | 검토(승인) | 4 | 현장대리 | - | TRUE | 333|| 진행 | 공가사전검토 | 5 | 공무팀 | - | FALSE | 334|| 진행 | 선로포설 | 6 | 현장팀 | 외선 | TRUE | 335|| 진행 | 선번조사 | 7 | 현장팀 | 접속 | TRUE | 336|| 진행 | 작업계획서 | 8 | 현장대리 | - | FALSE | 337|| 진행 | 절체 | 9 | 현장팀 | 접속 | TRUE | 338|| 진행 | 선로철거 | 10 | 현장팀 | 외선 | TRUE | 339|| 현장완료 | 현장완료 | 11 | 현장대리 | - | TRUE | 340|| 준공 | 서류작성 | 12 | 공무팀 | - | TRUE | 341|| 준공 | 공가신청 | 13 | 공무팀 | - | FALSE | 342|| 준공 | 서류접수 | 14 | 공무팀 | - | TRUE | 343|| 완료 | 완료 | 15 | 현장대리 | - | TRUE | 344| 345|--- 346| 347|### 7.6 Project (공사) 348| 349|| 컬럼 | 타입 | 설명 | 350||------|------|------| 351|| id | UUID PK | | 352|| company_id | UUID FK → Company | | 353|| project_type_id | UUID FK → ProjectType | 공사유형 | 354|| title | VARCHAR(200) | 공사명 | 355|| description | TEXT | 공사 설명 | 356|| location | TEXT | 공사 위치 | 357|| current_stage | ENUM(발생/실사/설계/검토/진행/현장완료/준공/완료) | 현재 대분류 | 358|| current_step | VARCHAR(100) | 현재 진행단계명 | 359|| approval_status | ENUM(대기/승인/취소/보류) | DEFAULT 대기 | 360|| agent_id | UUID FK → User | 현장대리 (1명, 교체가능) | 361|| started_at | TIMESTAMP | | 362|| completed_at | TIMESTAMP | | 363|| created_at | TIMESTAMP | | 364|| updated_at | TIMESTAMP | | 365| 366|--- 367| 368|### 7.7 ProjectTeam (현장팀 배정) 369| 370|| 컬럼 | 타입 | 설명 | 371||------|------|------| 372|| id | UUID PK | | 373|| project_id | UUID FK → Project | | 374|| user_id | UUID FK → User | | 375|| team_type | ENUM(외선/접속/기타) | | 376|| assigned_at | TIMESTAMP | | 377|| removed_at | TIMESTAMP | 팀에서 빠질 때 | 378| 379|--- 380| 381|### 7.8 ProjectStageLog (공사 단계 진행 이력) 382| 383|| 컬럼 | 타입 | 설명 | 384||------|------|------| 385|| id | UUID PK | | 386|| project_id | UUID FK → Project | | 387|| stage_group | ENUM(발생/실사/설계/검토/진행/현장완료/준공/완료) | | 388|| stage_name | VARCHAR(100) | | 389|| status | ENUM(시작/완료/취소) | | 390|| note | TEXT | 비고 | 391|| updated_by | UUID FK → User | | 392|| started_at | TIMESTAMP | | 393|| completed_at | TIMESTAMP | | 394|| created_at | TIMESTAMP | | 395| 396|--- 397| 398|### 7.9 Material (자재 마스터) 399| 400|| 컬럼 | 타입 | 설명 | 401||------|------|------| 402|| id | UUID PK | | 403|| company_id | UUID FK → Company | | 404|| name | VARCHAR(100) | 자재명 | 405|| code | VARCHAR(50) | 자재코드 | 406|| unit | VARCHAR(20) | 단위 (개/m/등) | 407|| supply_type | ENUM(사급/지입) | | 408|| unit_price | DECIMAL(12,2) | 단가 (지입만 해당) | 409|| is_active | BOOLEAN | DEFAULT TRUE | 410|| created_at | TIMESTAMP | | 411|| updated_at | TIMESTAMP | | 412| 413|--- 414| 415|### 7.10 MaterialInput (자재 입력 — 공사별) 416| 417|| 컬럼 | 타입 | 설명 | 418||------|------|------| 419|| id | UUID PK | | 420|| project_id | UUID FK → Project | | 421|| material_id | UUID FK → Material | | 422|| input_type | ENUM(최초/사용/반영) | | 423|| quantity | INT | | 424|| input_by | UUID FK → User | | 425|| team_type | ENUM(외선/접속/관리자) | | 426|| input_at | TIMESTAMP | | 427|| created_at | TIMESTAMP | | 428| 429|자동 계산 로직: 430| 431|불용자재 = SUM(사용.quantity) - SUM(반영.quantity) -- 같은 project_id + material_id 432|재고 = SUM(최초.quantity) - SUM(사용.quantity) -- 같은 project_id + material_id 433| 434| 435|--- 436| 437|### 7.11 Plugin (플러그인 관리) 438| 439|| 컬럼 | 타입 | 설명 | 440||------|------|------| 441|| id | UUID PK | | 442|| company_id | UUID FK → Company | | 443|| plugin_key | VARCHAR(50) | 예: 공가신청/선번조사결과 | 444|| name | VARCHAR(100) | 표시명 | 445|| enabled | BOOLEAN | DEFAULT FALSE | 446|| config | JSONB | 플러그인별 설정 | 447|| created_at | TIMESTAMP | | 448|| updated_at | TIMESTAMP | | 449| 450|--- 451| 452|### 7.12 ProjectTypePlugin (공사유형별 플러그인 연결) 453| 454|| 컬럼 | 타입 | 설명 | 455||------|------|------| 456|| id | UUID PK | | 457|| project_type_id | UUID FK → ProjectType | | 458|| plugin_id | UUID FK → Plugin | | 459|| enabled | BOOLEAN | DEFAULT TRUE | 460| 461|--- 462| 463|### 7.13 Document (공가신청/해지 — 플러그인 전용) 464| 465|| 컬럼 | 타입 | 설명 | 466||------|------|------| 467|| id | UUID PK | | 468|| project_id | UUID FK → Project | | 469|| doc_type | ENUM(공가신청/공가해지) | 플러그인 활성화 시만 | 470|| status | ENUM(작성중/신청/접수/완료) | | 471|| content | JSONB | 서류 내용 | 472|| created_by | UUID FK → User | | 473|| created_at | TIMESTAMP | | 474|| updated_at | TIMESTAMP | | 475| 476|--- 477| 478|### 7.14 OCRUpload (OCR 자료 반영) 479| 480|| 컬럼 | 타입 | 설명 | 481||------|------|------| 482|| id | UUID PK | | 483|| project_id | UUID FK → Project | | 484|| uploaded_by | UUID FK → User | 현장(접속)팀 | 485|| file_path | VARCHAR(500) | | 486|| ocr_result | JSONB | OCR 분석 결과 | 487|| reviewed_by | UUID FK → User | 현장대리 | 488|| review_status | ENUM(대기/확인/수정) | | 489|| uploaded_at | TIMESTAMP | | 490|| reviewed_at | TIMESTAMP | | 491| 492|--- 493| 494|### 7.15 ER 관계도 495| 496| 497|Company ──── User ──── ViewerPermission 498| │ 499| ├──── ProjectType ── ProjectTypeStage 500| │ │ 501| │ └──── ProjectTypePlugin ── Plugin 502| │ 503| ├──── Material 504| │ 505| └──── Project ── ProjectTeam 506| │ 507| ├──── ProjectStageLog 508| ├──── MaterialInput (→ Material) 509| ├──── Document (플러그인) 510| └──── OCRUpload 511| 512| 513|--- 514| 515|

섹션 제목: “1|# 🏗️ 공사관리 ERP — 설계서 v0.1 2| 3|> 작성: 분홍 (Hermes Agent) 4|> 기획: 분홍아빠 5|> 일자: 2026-04-20 6|> 상태: 초안 (논의 기반 자동 구상, 제작 시 수정/추가 예정) 7| 8|--- 9| 10|## 1. 프로젝트 개요 11| 12|### 1.1 목표 13|- 모든 공사유형(건축, 토목, 통신 등)에 범용 가능한 웹 어플리케이션 제작 14|- 판매 모델 적용 — 회사당 독립 VM 환경 제공 15|- 기존 레드마인 변형 시스템(현재 폐지)을 대체하는 신규 구축 16| 17|### 1.2 기존 시스템 아쉬웠던 점 → 개선 방향 18|| 아쉬웠던 점 | 개선 | 19||------------|------| 20|| 플러그인 추가 불가 | 직접 개발 → 자유로운 기능 추가 | 21|| 유료 플러그인 연간 비용 | 비용 없음 | 22|| 자재관리 없었고 유료는 커스텀 불가 | 자재관리 기본 탑재 + 자유 커스텀 | 23| 24|### 1.3 프로젝트 범위 25| 26|포함: 27|- 공사 파이프라인 관리 (8단계) 28|- 역할/권한 관리 (5그룹) 29|- 자재관리 (입력 → 반영 → 불용 → 재고 자동계산) 30|- 공가신청/해지 (플러그인) 31|- OCR 자료 반영 (업로드 → 분석 → 확인) 32|- 공사유형별 파이프라인 템플릿 (관리자 커스터마이징) 33|- 플러그인 시스템 (공사유형별 on/off) 34| 35|제외: 36|- 설계서류, 준공서류, 작업계획서 등 Excel 서류 (너무 방대) 37|- 선번조사툴 (독립 웹프로그램, ERP 내부에 넣으면 무거움) 38| 39|--- 40| 41|## 2. 역할 & 권한 42| 43|### 2.1 역할 정의 44| 45|| 역할 | 권한 | 비고 | 46||------|------|------| 47|| 관리자 | 웹서버 관리, 최고권한 | 공사유형 템플릿 커스텀, 감시인 권한 조절 | 48|| 공사감독 | 거의 뷰어 | 외부 자체프로그램 사용, 실제 로그인 안 함, 감시인 | 49|| 현장대리 | 각 공사의 진행 관리 | 공사당 1명 (교체 가능), 공사감독 승인 대리 입력 | 50|| 현장팀 | 각 공사의 부분 처리 | 공사당 여러 명, 모바일 간편 입력 | 51|| 공무팀 | 공사 완료 시 서류 작성 | 준공 단계 서류 | 52| 53|### 2.2 감시인 체계 54|- 공사감독 + 회사대표 = 감시인 55|- 감시인은 기본적으로 조회만 가능 56|- 관리자가 페이지별로 조회 권한 개별 조절 가능 57|- 예: 공사목록 O, 자재현황 O, 재무정보 X 58| 59|### 2.3 현장팀 모바일 특성 60|- 회원가입 간편 (최소 정보) 61|- 로그인 간편 62|- 내용 입력 위주의 가벼운 인터페이스 63| 64|### 2.4 공사감독 승인 처리 65|- 공사감독은 외부 자체 프로그램 사용 → 이 시스템에 직접 접속 안 함 66|- 현장대리가 공사감독의 승인 결과를 대신 입력/수정 67|- 승인 상태: 승인 / 취소 / 보류 68| 69|--- 70| 71|## 3. 공사 진행 파이프라인 72| 73|### 3.1 기본 8단계 74| 75| 76|발생(접수) → 실사 → 설계 → 검토(승인) → 진행 → 현장완료 → 준공 → 완료 77| 78| 79|검토(승인) 단계 세부 상태: 80|| 상태 | 의미 | 이후 동작 | 81||------|------|----------| 82|| 승인 | 공사감독이 승인 | 다음 단계(진행)로 이동 | 83|| 취소 | 공사감독이 취소 | 이전 단계로 복귀 또는 대기 | 84|| 보류 | 공사감독이 검토 보류 | 현재 단계 유지, 재검토 대기 | 85| 86|### 3.2 진행 단계 — 공사유형별 상이 87| 88|통신선로공사 기준: 89| 90|| 단계 | 담당 | 91||------|------| 92|| 공가사전검토 | 공무팀 | 93|| 선로포설 | 현장(외선)팀 | 94|| 선번조사 | 현장(접속)팀 | 95|| 작업계획서 | 현장대리 | 96|| 절체 | 현장(접속)팀 | 97|| 선로철거 | 현장(외선)팀 | 98| 99|> - 관리자가 공사유형 템플릿에서 진행 단계를 직접 커스터마이징 100|> - 각 단계별 담당자 지정 가능 101|> - 모든 단계가 필요한 경우도 있고, 일부 단계가 생략되는 경우도 있음 (공사별 선택) 102| 103|### 3.3 준공 단계 104| 105|서류작성 → 공가신청 → 서류접수 106| 107| 108|> 공가신청은 통신공사 전용 → 플러그인으로 관리 (해당 공사유형에만 표시) 109| 110|### 3.4 검토(승인) 단계 111|- 현장대리가 승인/취소/보류 입력 112|- 승인 → 다음 단계 진행 113|- 취소 → 이전 단계로 복귀 또는 대기 114|- 보류 → 현재 단계 유지, 재검토 대기 115| 116|--- 117| 118|## 4. 자재관리 119| 120|### 4.1 흐름 121| 122| 123|최초 자재 데이터 입력 (관리자/현장대리, 사급/지입 지정) 124| ↓ 125|사용자재 입력 → 현장(외선)팀 126| ↓ 127|반영자재 재입력 → 현장(접속)팀 128| ↓ 129|불용자재 = 사용자재 - 반영자재 (자동계산) 130| ↓ 131|재고 = 최초입력 - 사용자재(반영+불용) (자동계산) 132| 133| 134|### 4.2 재고 분류 135|- 사급: 원청에서 지급한 자재 136|- 지입: 직접 구매한 자재 137|- 반납 없음 — 반영자재 + 불용자재 기준 138| 139|### 4.3 계산 예시 140| 141| 142|최초 입력: 100개 (사급) 143|사용자재: 80개 (외선 팀 입력) 144|반영자재: 60개 (접속 팀 재입력) 145|불용자재: 20개 (자동계산: 80-60) 146|재고: 20개 (자동계산: 100-80) 147| 148| 149|### 4.4 입력 주체 150| 151|| 입력 유형 | 입력자 | team_type | 152||----------|--------|-----------| 153|| 최초 | 관리자/현장대리 | 관리자 | 154|| 사용 | 현장(외선)팀 | 외선 | 155|| 반영 | 현장(접속)팀 | 접속 | 156| 157|--- 158| 159|## 5. 플러그인 시스템 160| 161|### 5.1 개념 162|- 공사유형에 따라 표시 여부가 다른 기능을 플러그인으로 관리 163|- 관리자가 회사별로 플러그인 on/off 164|- 공사유형별로도 플러그인 on/off 165| 166|### 5.2 플러그인 목록 (초안) 167| 168|| plugin_key | 설명 | 기본 | 169||-----------|------|------| 170|| 공가신청 | 공가신청/해지 기능 | OFF (통신공사만 ON) | 171|| 선번조사결과 | 선번조사 결과 반영 (OCR) | OFF | 172|| 자재관리 | 자재 입력/추적 | ON | 173| 174|> 향후 플러그인 계속 추가 가능 175| 176|### 5.3 플러그인 연동 구조 177| 178|Plugin (회사별 on/off) 179| └── ProjectTypePlugin (공사유형별 on/off) 180| └── UI에 표시/숨김 181| 182| 183|--- 184| 185|## 6. 배포 아키텍처 186| 187|### 6.1 인프라 구성 188| 189| 190|서버컴 (Proxmox) 191|├── 가상헤놀로지 (회사 NAS) 192|├── 공사관리ERP VM #1 (A회사용, 독립도메인) 193|├── 공사관리ERP VM #2 (B회사용, 독립도메인) 194|└── ... 195| 196| 197|### 6.2 VM 당 Docker 구성 198| 199| 200|Docker Compose 201|├── 프론트엔드 (Vue 3 + Vuetify) — 관리자 UI에 강함 202|├── 백엔드 (FastAPI) — 가볍고 빠름, OCR 연동 유리 203|├── PostgreSQL — 데이터베이스 204|├── Redis — 세션/캐시 205|├── OCR 서비스 — Tesseract / 클라우드 OCR 206|└── Nginx — 리버스프록시 + SSL 207| 208| 209|### 6.3 배포 흐름 210| 211|신규 회사 추가 시: 212|1. Proxmox에서 VM 생성 (또는 템플릿 복제) 213|2. Docker Compose 배포 214|3. 도메인 설정 + SSL 인증서 215|4. 관리자 계정 생성 216|5. 회사별 초기 설정 (공사유형, 자재, 플러그인) 217| 218| 219|### 6.4 백업 전략 220|- VM 스냅샷 (Proxmox) 221|- PostgreSQL 정기 백업 (pg_dump) 222|- 백업 파일 NAS 저장 223|- 세부 스케줄: 미정 (구현 시 결정) 224| 225|--- 226| 227|## 7. DB 설계 228| 229|### 7.1 Company (회사 — VM당 1개) 230| 231|| 컬럼 | 타입 | 설명 | 232||------|------|------| 233|| id | UUID PK | | 234|| name | VARCHAR(100) | 회사명 | 235|| business_number | VARCHAR(20) | 사업자등록번호 | 236|| domain | VARCHAR(100) | 전용 도메인 | 237|| address | TEXT | 회사 주소 | 238|| phone | VARCHAR(20) | 대표 전화 | 239|| email | VARCHAR(100) | 대표 이메일 | 240|| logo_url | VARCHAR(500) | 회사 로고 | 241|| settings | JSONB | 회사별 설정 | 242|| subscription | ENUM(무료/기본/프리미엄) | 구독 플랜 | 243|| subscription_expires | TIMESTAMP | 구독 만료일 | 244|| is_active | BOOLEAN | DEFAULT TRUE | 245|| created_at | TIMESTAMP | | 246|| updated_at | TIMESTAMP | | 247| 248|settings JSONB 예시: 249|json 250|{ 251| "default_lang": "ko", 252| "timezone": "Asia/Seoul", 253| "max_projects": 100, 254| "max_users": 50, 255| "features": { 256| "공가신청": true, 257| "자재관리": true, 258| "OCR": false 259| } 260|} 261| 262| 263|--- 264| 265|### 7.2 User (사용자) 266| 267|| 컬럼 | 타입 | 설명 | 268||------|------|------| 269|| id | UUID PK | | 270|| company_id | UUID FK → Company | | 271|| name | VARCHAR(50) | 이름 | 272|| email | VARCHAR(100) | 로그인ID | 273|| password_hash | VARCHAR(255) | 비밀번호 (현장팀은 간단히) | 274|| phone | VARCHAR(20) | 연락처 | 275|| role | ENUM(관리자/공사감독/현장대리/현장팀/공무팀) | 역할 | 276|| team_type | ENUM(외선/접속/기타) | 현장팀만, 나머지 NULL | 277|| is_active | BOOLEAN | DEFAULT TRUE | 278|| last_login_at | TIMESTAMP | | 279|| created_at | TIMESTAMP | | 280|| updated_at | TIMESTAMP | | 281| 282|--- 283| 284|### 7.3 ViewerPermission (감시인 페이지 권한) 285| 286|| 컬럼 | 타입 | 설명 | 287||------|------|------| 288|| id | UUID PK | | 289|| user_id | UUID FK → User | 감시인 | 290|| page_key | VARCHAR(50) | 예: 공사목록/자재현황/진행상태 | 291|| can_view | BOOLEAN | DEFAULT TRUE | 292|| granted_by | UUID FK → User | 권한 부여한 관리자 | 293| 294|--- 295| 296|### 7.4 ProjectType (공사유형 템플릿) 297| 298|| 컬럼 | 타입 | 설명 | 299||------|------|------| 300|| id | UUID PK | | 301|| company_id | UUID FK → Company | | 302|| name | VARCHAR(100) | 예: 통신선로공사, 건축공사 | 303|| description | TEXT | 설명 | 304|| is_active | BOOLEAN | DEFAULT TRUE | 305|| created_at | TIMESTAMP | | 306|| updated_at | TIMESTAMP | | 307| 308|--- 309| 310|### 7.5 ProjectTypeStage (유형별 파이프라인 단계) 311| 312|| 컬럼 | 타입 | 설명 | 313||------|------|------| 314|| id | UUID PK | | 315|| project_type_id | UUID FK → ProjectType | | 316|| stage_group | ENUM(발생/실사/설계/검토/진행/현장완료/준공/완료) | 대분류 | 317|| stage_name | VARCHAR(100) | 예: 공가사전검토 | 318|| stage_order | INT | 정렬순서 | 319|| assigned_role | ENUM(관리자/공사감독/현장대리/현장팀/공무팀) | 담당 역할 | 320|| assigned_team_type | ENUM(외선/접속/기타) | 현장팀인 경우 세분류 | 321|| is_required | BOOLEAN | DEFAULT TRUE, 필수단계 여부 | 322|| created_at | TIMESTAMP | | 323|| updated_at | TIMESTAMP | | 324| 325|예시 — 통신선로공사: 326| 327|| stage_group | stage_name | order | assigned_role | assigned_team_type | is_required | 328||-------------|-----------|-------|---------------|---------------------|-------------| 329|| 발생 | 접수 | 1 | 현장대리 | - | TRUE | 330|| 실사 | 실사 | 2 | 현장대리 | - | TRUE | 331|| 설계 | 설계 | 3 | 현장대리 | - | TRUE | 332|| 검토 | 검토(승인) | 4 | 현장대리 | - | TRUE | 333|| 진행 | 공가사전검토 | 5 | 공무팀 | - | FALSE | 334|| 진행 | 선로포설 | 6 | 현장팀 | 외선 | TRUE | 335|| 진행 | 선번조사 | 7 | 현장팀 | 접속 | TRUE | 336|| 진행 | 작업계획서 | 8 | 현장대리 | - | FALSE | 337|| 진행 | 절체 | 9 | 현장팀 | 접속 | TRUE | 338|| 진행 | 선로철거 | 10 | 현장팀 | 외선 | TRUE | 339|| 현장완료 | 현장완료 | 11 | 현장대리 | - | TRUE | 340|| 준공 | 서류작성 | 12 | 공무팀 | - | TRUE | 341|| 준공 | 공가신청 | 13 | 공무팀 | - | FALSE | 342|| 준공 | 서류접수 | 14 | 공무팀 | - | TRUE | 343|| 완료 | 완료 | 15 | 현장대리 | - | TRUE | 344| 345|--- 346| 347|### 7.6 Project (공사) 348| 349|| 컬럼 | 타입 | 설명 | 350||------|------|------| 351|| id | UUID PK | | 352|| company_id | UUID FK → Company | | 353|| project_type_id | UUID FK → ProjectType | 공사유형 | 354|| title | VARCHAR(200) | 공사명 | 355|| description | TEXT | 공사 설명 | 356|| location | TEXT | 공사 위치 | 357|| current_stage | ENUM(발생/실사/설계/검토/진행/현장완료/준공/완료) | 현재 대분류 | 358|| current_step | VARCHAR(100) | 현재 진행단계명 | 359|| approval_status | ENUM(대기/승인/취소/보류) | DEFAULT 대기 | 360|| agent_id | UUID FK → User | 현장대리 (1명, 교체가능) | 361|| started_at | TIMESTAMP | | 362|| completed_at | TIMESTAMP | | 363|| created_at | TIMESTAMP | | 364|| updated_at | TIMESTAMP | | 365| 366|--- 367| 368|### 7.7 ProjectTeam (현장팀 배정) 369| 370|| 컬럼 | 타입 | 설명 | 371||------|------|------| 372|| id | UUID PK | | 373|| project_id | UUID FK → Project | | 374|| user_id | UUID FK → User | | 375|| team_type | ENUM(외선/접속/기타) | | 376|| assigned_at | TIMESTAMP | | 377|| removed_at | TIMESTAMP | 팀에서 빠질 때 | 378| 379|--- 380| 381|### 7.8 ProjectStageLog (공사 단계 진행 이력) 382| 383|| 컬럼 | 타입 | 설명 | 384||------|------|------| 385|| id | UUID PK | | 386|| project_id | UUID FK → Project | | 387|| stage_group | ENUM(발생/실사/설계/검토/진행/현장완료/준공/완료) | | 388|| stage_name | VARCHAR(100) | | 389|| status | ENUM(시작/완료/취소) | | 390|| note | TEXT | 비고 | 391|| updated_by | UUID FK → User | | 392|| started_at | TIMESTAMP | | 393|| completed_at | TIMESTAMP | | 394|| created_at | TIMESTAMP | | 395| 396|--- 397| 398|### 7.9 Material (자재 마스터) 399| 400|| 컬럼 | 타입 | 설명 | 401||------|------|------| 402|| id | UUID PK | | 403|| company_id | UUID FK → Company | | 404|| name | VARCHAR(100) | 자재명 | 405|| code | VARCHAR(50) | 자재코드 | 406|| unit | VARCHAR(20) | 단위 (개/m/등) | 407|| supply_type | ENUM(사급/지입) | | 408|| unit_price | DECIMAL(12,2) | 단가 (지입만 해당) | 409|| is_active | BOOLEAN | DEFAULT TRUE | 410|| created_at | TIMESTAMP | | 411|| updated_at | TIMESTAMP | | 412| 413|--- 414| 415|### 7.10 MaterialInput (자재 입력 — 공사별) 416| 417|| 컬럼 | 타입 | 설명 | 418||------|------|------| 419|| id | UUID PK | | 420|| project_id | UUID FK → Project | | 421|| material_id | UUID FK → Material | | 422|| input_type | ENUM(최초/사용/반영) | | 423|| quantity | INT | | 424|| input_by | UUID FK → User | | 425|| team_type | ENUM(외선/접속/관리자) | | 426|| input_at | TIMESTAMP | | 427|| created_at | TIMESTAMP | | 428| 429|자동 계산 로직: 430| 431|불용자재 = SUM(사용.quantity) - SUM(반영.quantity) -- 같은 project_id + material_id 432|재고 = SUM(최초.quantity) - SUM(사용.quantity) -- 같은 project_id + material_id 433| 434| 435|--- 436| 437|### 7.11 Plugin (플러그인 관리) 438| 439|| 컬럼 | 타입 | 설명 | 440||------|------|------| 441|| id | UUID PK | | 442|| company_id | UUID FK → Company | | 443|| plugin_key | VARCHAR(50) | 예: 공가신청/선번조사결과 | 444|| name | VARCHAR(100) | 표시명 | 445|| enabled | BOOLEAN | DEFAULT FALSE | 446|| config | JSONB | 플러그인별 설정 | 447|| created_at | TIMESTAMP | | 448|| updated_at | TIMESTAMP | | 449| 450|--- 451| 452|### 7.12 ProjectTypePlugin (공사유형별 플러그인 연결) 453| 454|| 컬럼 | 타입 | 설명 | 455||------|------|------| 456|| id | UUID PK | | 457|| project_type_id | UUID FK → ProjectType | | 458|| plugin_id | UUID FK → Plugin | | 459|| enabled | BOOLEAN | DEFAULT TRUE | 460| 461|--- 462| 463|### 7.13 Document (공가신청/해지 — 플러그인 전용) 464| 465|| 컬럼 | 타입 | 설명 | 466||------|------|------| 467|| id | UUID PK | | 468|| project_id | UUID FK → Project | | 469|| doc_type | ENUM(공가신청/공가해지) | 플러그인 활성화 시만 | 470|| status | ENUM(작성중/신청/접수/완료) | | 471|| content | JSONB | 서류 내용 | 472|| created_by | UUID FK → User | | 473|| created_at | TIMESTAMP | | 474|| updated_at | TIMESTAMP | | 475| 476|--- 477| 478|### 7.14 OCRUpload (OCR 자료 반영) 479| 480|| 컬럼 | 타입 | 설명 | 481||------|------|------| 482|| id | UUID PK | | 483|| project_id | UUID FK → Project | | 484|| uploaded_by | UUID FK → User | 현장(접속)팀 | 485|| file_path | VARCHAR(500) | | 486|| ocr_result | JSONB | OCR 분석 결과 | 487|| reviewed_by | UUID FK → User | 현장대리 | 488|| review_status | ENUM(대기/확인/수정) | | 489|| uploaded_at | TIMESTAMP | | 490|| reviewed_at | TIMESTAMP | | 491| 492|--- 493| 494|### 7.15 ER 관계도 495| 496| 497|Company ──── User ──── ViewerPermission 498| │ 499| ├──── ProjectType ── ProjectTypeStage 500| │ │ 501| │ └──── ProjectTypePlugin ── Plugin 502| │ 503| ├──── Material 504| │ 505| └──── Project ── ProjectTeam 506| │ 507| ├──── ProjectStageLog 508| ├──── MaterialInput (→ Material) 509| ├──── Document (플러그인) 510| └──── OCRUpload 511| 512| 513|--- 514| 515|”

분홍아빠 실무 피드백 반영: 공사 ≠ 작업 분리, 포맷(템플릿), 설계서 버전 관리

WorkTemplate (작업 포맷/템플릿 — 관리자가 정의)

섹션 제목: “WorkTemplate (작업 포맷/템플릿 — 관리자가 정의)”
컬럼타입설명
idUUID PK
company_idUUID FK → Company
project_type_idUUID FK → ProjectType공사유형별 (통신선로용 등)
nameVARCHAR(100)포맷명 예: “1번 전체”
format_codeVARCHAR(20)1번/2번 등 or 커스텀 코드
descriptionTEXT설명
stagesJSONB포함 작업 목록 [{"stage":"포설","assign":"외선팀","required":true}, ...]
is_activeBOOLEANDEFAULT TRUE
created_atTIMESTAMP
updated_atTIMESTAMP

stages JSONB 예시 (1번 전체 포맷):

[
{"stage_group":"진행","stage_name":"포설","assign_role":"현장팀","assign_team_type":"외선","required":true,"order":1},
{"stage_group":"진행","stage_name":"선번조사","assign_role":"현장팀","assign_team_type":"접속","required":true,"order":2},
{"stage_group":"진행","stage_name":"준비작업","assign_role":"현장대리","assign_team_type":null,"required":true,"order":3},
{"stage_group":"진행","stage_name":"코아구성","assign_role":"현장팀","assign_team_type":"접속","required":true,"order":4},
{"stage_group":"진행","stage_name":"절체작업","assign_role":"현장팀","assign_team_type":"접속","required":true,"order":5},
{"stage_group":"진행","stage_name":"밴딩작업","assign_role":"현장팀","assign_team_type":"접속","required":false,"order":6},
{"stage_group":"진행","stage_name":"선로철거","assign_role":"현장팀","assign_team_type":"외선","required":true,"order":7}
]

컬럼타입설명
idUUID PK
project_idUUID FK → Project상위 공사
template_stage_idVARCHAR(50)참조 템플릿 단계 (nullable)
work_codeVARCHAR(50)작업코드 예: WKS… (원청 부여, nullable)
stage_groupENUM(발생/실사/설계/검토/진행/현장완료/준공/완료)단계
stage_nameVARCHAR(100)작업명: 포설, 선번조사, 코아구성 등
descriptionTEXT작업 설명/비고
statusENUM(대기/진행중/완료/보류)DEFAULT 대기
assigned_roleENUM(…)배정된 역할
assigned_team_typeENUM(외선/접속/기타)배정된 팀
assigned_user_idUUID FK → User특정 담당자 지정 (선번조사 등, nullable)
created_byUUID FK → User현장대리 (생성자)
started_atTIMESTAMP
completed_atTIMESTAMP
created_atTIMESTAMP
updated_atTIMESTAMP

Work ↔ WorkTemplate 관계:

  • 공사 등록 시 WorkTemplate.stages 기반으로 Work 행 자동 생성 (현장대리가 템플릿 선택 후)
  • 현장대리가 각 Work 개별으로 생성/삭제/수정 가능 (필요 시)
  • 원청 작업번호(work_code)는 수동 등록 가능

컬럼타입설명
idUUID PK
work_idUUID FK → Work
user_idUUID FK → User배정된 현장팀원
assigned_atTIMESTAMP
removed_atTIMESTAMP팀 교체 시

ProjectDocument (공사 문서 버전 관리 — 설계서, 작업계획서, 서류 등)

섹션 제목: “ProjectDocument (공사 문서 버전 관리 — 설계서, 작업계획서, 서류 등)”
컬럼타입설명
idUUID PK
project_idUUID FK → Project
work_idUUID FK → Work해당 작업 (작업계획서 등, nullable)
doc_typeENUM(설계서/작업계획서/서류작성/공가신청서/기타)
version_nameVARCHAR(20)v0.1, v1.0, v1.1 등
statusENUM(설계중/확정/확정수정/폐기)DEFAULT 설계중
change_summaryTEXT변경사항 요약 (diff 설명)
contentJSONB문서 내용 (템플릿 + 데이터)
previous_version_idUUID FK → ProjectDocumentdiff 계산용 (nullable)
created_byUUID FK → User
approved_byUUID FK → User확정한 관리자/nullable
approved_atTIMESTAMP
created_atTIMESTAMP
updated_atTIMESTAMP

Company ──── User ──── ViewerPermission
├──── ProjectType ── ProjectTypeStage ──── WorkTemplate
│ │ │
│ │ └── stages JSONB
│ │
│ ├──────────────────┘
│ │
│ └────────────────────────────── Project ── ProjectTeam
│ │ │ │
│ │ ├──── ProjectStageLog │
│ │ ├──── MaterialInput (→ Material) │
│ │ ├──── Document (플러그인) │
│ │ ├──── OCRUpload │
│ │ ├──── Work ⭐ │
│ │ │ │ │
│ │ │ ├──── WorkAssignment ── User
│ │ │ │
│ │ │ └──── ProjectDocument ⭐ │
│ │ │ │
│ │ │ └──── previous_version_id → ProjectDocument
│ │ │
│ │ └──── ProjectDocument ⭐ (공사 전체 문서)
│ │
│ └───────────────────── WorkTemplate (포맷 정의)
├──── Material
└──── Plugin ── ProjectTypePlugin

516| 517|- [ ] 감사 로그 (AuditLog) — 누가 뭘 언제 변경했나 518|- [ ] 알림 시스템 — 단계 변경 시 알림 (이메일/카카오톡/문자) 519|- [ ] 파일 첨부 — 공사별 첨부파일 관리 520|- [ ] 통계/리포트 — 관리자 대시보드용 521|- [ ] API 토큰 — 외부 연동용 522|- [ ] 다국어 지원 (판매 모델 확장 시) 523|- [ ] 모바일 앱 (현장팀 전용 PWA) 524| 525|--- 526| 527|## 변경 이력 528| 529|| 버전 | 일자 | 내용 | 530||------|------|------| 531|| v0.1 | 2026-04-20 | 초안 — 기획 + DB 설계 1차 구상 | 532|| v0.1.1 | 2026-04-20 | 검토상태 보류 추가, 진행단계별 담당자 지정, 작업계획서 단계 추가, 단계 선택/생략 가능 명시, DB 테이블 동기화 |