b17d7b063d
G11 수주 결재상신(905d5c09)과 동일 패턴을 견적관리에 확장. target_type='CONTRACT_ESTIMATE',
target_objid=estimate_template.objid(최신 차수), formId='1162' (수주 1161과 별도 양식).
- 백엔드: salesEstimateService.startEstimateApproval + POST /sales/estimate/:id/amaranth-approval
- 견적 list SQL: LEFT JOIN amaranth_approval(CONTRACT_ESTIMATE) + APPR_STATUS 4단계 한글 라벨 + approval_required='N' fallback (wace contractMgmt.xml:513~522 1:1)
- 프론트: 견적관리 placeholder 토스트 → handleAmaranthApproval 핸들러 + sky-600 Send 버튼 (수주 페이지와 통일)
- docker-compose 3개: AMARANTH_OUT_PROCESS_CODE_CONTRACT_ESTIMATE + AMARANTH_FORM_ID_CONTRACT_ESTIMATE=1162 추가
- 가드: 행 미선택 / est_objid 없음(견적서 미작성) / inProcess+complete / notRequired+approval_required='N'
- 사전판정(checkApprovalRequired)은 G4 영역으로 분리 — 이번 PR은 단순 SSO 흐름만
검증: BEGIN/ROLLBACK으로 26C-0712(est_objid=-452406811) 4단계 상태(create→inProcess→complete→reject)
+ amaranth row 삭제 시 approval_required='N' fallback 모두 한글 라벨 정상. 문서 08-estimate-approval-verify.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
176 lines
6.1 KiB
YAML
176 lines
6.1 KiB
YAML
# Vexplor 온프레미스(공장) 배포용 Docker Compose
|
|
# 사용법: docker compose up -d
|
|
|
|
services:
|
|
# ============================================
|
|
# 1. 데이터베이스 (PostgreSQL)
|
|
# ============================================
|
|
database:
|
|
image: postgres:15-alpine
|
|
container_name: vexplor-db
|
|
environment:
|
|
POSTGRES_USER: ${DB_USER:-vexplor}
|
|
POSTGRES_PASSWORD: ${DB_PASSWORD:?DB_PASSWORD is required}
|
|
POSTGRES_DB: ${DB_NAME:-vexplor}
|
|
TZ: Asia/Seoul
|
|
volumes:
|
|
- postgres_data:/var/lib/postgresql/data
|
|
- ./init-db:/docker-entrypoint-initdb.d # 초기화 스크립트 (선택)
|
|
ports:
|
|
- "${DB_PORT:-5432}:5432"
|
|
restart: always
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-vexplor}"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
networks:
|
|
- vexplor-network
|
|
|
|
# ============================================
|
|
# 2. 백엔드 API (Node.js)
|
|
# ============================================
|
|
backend:
|
|
image: harbor.wace.me/speefox_vexplor/vexplor-backend:${IMAGE_TAG:-latest}
|
|
container_name: vexplor-backend
|
|
environment:
|
|
NODE_ENV: production
|
|
PORT: 3001
|
|
HOST: 0.0.0.0
|
|
TZ: Asia/Seoul
|
|
# DB 연결
|
|
DB_HOST: database
|
|
DB_PORT: 5432
|
|
DB_USER: ${DB_USER:-vexplor}
|
|
DB_PASSWORD: ${DB_PASSWORD}
|
|
DB_NAME: ${DB_NAME:-vexplor}
|
|
# JWT
|
|
JWT_SECRET: ${JWT_SECRET:?JWT_SECRET is required}
|
|
JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-24h}
|
|
# 암호화 키 (메일 등 민감정보 암호화용)
|
|
ENCRYPTION_KEY: ${ENCRYPTION_KEY:-vexplor-encryption-key-32characters-secure}
|
|
# 회사 코드 (온프레미스는 단일 회사)
|
|
DEFAULT_COMPANY_CODE: ${COMPANY_CODE:-SPIFOX}
|
|
# 로깅
|
|
LOG_LEVEL: ${LOG_LEVEL:-info}
|
|
# SMTP (견적서/발주서 등 메일 발송) — 호스트 .env에서 실값 주입
|
|
SMTP_HOST: ${SMTP_HOST:-erp.rps-korea.com}
|
|
SMTP_PORT: ${SMTP_PORT:-25}
|
|
SMTP_TLS: ${SMTP_TLS:-false}
|
|
SMTP_SEND_SWITCH: ${SMTP_SEND_SWITCH:-Y}
|
|
SMTP_USER_ERP: ${SMTP_USER_ERP:-}
|
|
SMTP_PW_ERP: ${SMTP_PW_ERP:-}
|
|
SMTP_USER_SALES: ${SMTP_USER_SALES:-}
|
|
SMTP_PW_SALES: ${SMTP_PW_SALES:-}
|
|
SMTP_USER_PURCHASE: ${SMTP_USER_PURCHASE:-}
|
|
SMTP_PW_PURCHASE: ${SMTP_PW_PURCHASE:-}
|
|
# Amaranth 전자결재 (수주/견적 등) — 호스트 .env에서 실값 주입
|
|
# OUT_PROCESS_CODE: wace Constants.AMARANTH_OUT_PROCESS_CODE='RPSPLM_00001' 1:1
|
|
# 도메인별 fallback: AMARANTH_OUT_PROCESS_CODE_CONTRACT_ORDER → AMARANTH_OUT_PROCESS_CODE
|
|
AMARANTH_OUT_PROCESS_CODE: ${AMARANTH_OUT_PROCESS_CODE:-RPSPLM_00001}
|
|
AMARANTH_OUT_PROCESS_CODE_CONTRACT_ORDER: ${AMARANTH_OUT_PROCESS_CODE_CONTRACT_ORDER:-}
|
|
AMARANTH_OUT_PROCESS_CODE_CONTRACT_ESTIMATE: ${AMARANTH_OUT_PROCESS_CODE_CONTRACT_ESTIMATE:-}
|
|
AMARANTH_FORM_ID_CONTRACT_ORDER: ${AMARANTH_FORM_ID_CONTRACT_ORDER:-1161}
|
|
AMARANTH_FORM_ID_CONTRACT_ESTIMATE: ${AMARANTH_FORM_ID_CONTRACT_ESTIMATE:-1162}
|
|
AMARANTH_COMP_SEQ: ${AMARANTH_COMP_SEQ:-1000}
|
|
volumes:
|
|
- backend_uploads:/app/uploads
|
|
- backend_data:/app/data
|
|
- backend_logs:/app/logs
|
|
ports:
|
|
- "${BACKEND_PORT:-3001}:3001"
|
|
depends_on:
|
|
database:
|
|
condition: service_healthy
|
|
restart: always
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:3001/health"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 40s
|
|
networks:
|
|
- vexplor-network
|
|
labels:
|
|
- "com.centurylinklabs.watchtower.enable=true"
|
|
|
|
# ============================================
|
|
# 3. 프론트엔드 (Next.js)
|
|
# ============================================
|
|
frontend:
|
|
image: harbor.wace.me/speefox_vexplor/vexplor-frontend:${IMAGE_TAG:-latest}
|
|
container_name: vexplor-frontend
|
|
environment:
|
|
NODE_ENV: production
|
|
PORT: 3000
|
|
HOSTNAME: 0.0.0.0
|
|
TZ: Asia/Seoul
|
|
# 백엔드 API URL (내부 통신)
|
|
NEXT_PUBLIC_API_URL: http://${SERVER_IP:-localhost}:${BACKEND_PORT:-3001}/api
|
|
ports:
|
|
- "${FRONTEND_PORT:-80}:3000"
|
|
depends_on:
|
|
- backend
|
|
restart: always
|
|
healthcheck:
|
|
test: ["CMD", "curl", "-f", "http://localhost:3000"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 30s
|
|
networks:
|
|
- vexplor-network
|
|
labels:
|
|
- "com.centurylinklabs.watchtower.enable=true"
|
|
|
|
# ============================================
|
|
# 4. Watchtower (자동 업데이트)
|
|
# ============================================
|
|
watchtower:
|
|
image: containrrr/watchtower:latest
|
|
container_name: vexplor-watchtower
|
|
environment:
|
|
TZ: Asia/Seoul
|
|
DOCKER_API_VERSION: "1.44"
|
|
# Harbor 레지스트리 인증
|
|
REPO_USER: ${HARBOR_USER}
|
|
REPO_PASS: ${HARBOR_PASSWORD}
|
|
# 업데이트 설정
|
|
# WATCHTOWER_POLL_INTERVAL: ${UPDATE_INTERVAL:-300} # 간격 기반 (비활성화)
|
|
WATCHTOWER_SCHEDULE: "0 0 * * * *" # 매시 정각에 실행 (cron 형식)
|
|
WATCHTOWER_CLEANUP: "true" # 이전 이미지 자동 삭제
|
|
WATCHTOWER_INCLUDE_STOPPED: "true" # 중지된 컨테이너도 업데이트
|
|
WATCHTOWER_ROLLING_RESTART: "true" # 순차 재시작 (다운타임 최소화)
|
|
WATCHTOWER_LABEL_ENABLE: "true" # 라벨이 있는 컨테이너만 업데이트
|
|
# 알림 설정 (선택)
|
|
# WATCHTOWER_NOTIFICATIONS: slack
|
|
# WATCHTOWER_NOTIFICATION_SLACK_HOOK_URL: ${SLACK_WEBHOOK_URL}
|
|
volumes:
|
|
- /var/run/docker.sock:/var/run/docker.sock
|
|
# Harbor 인증 정보 (docker login 후 생성됨)
|
|
- ~/.docker/config.json:/config.json:ro
|
|
restart: always
|
|
networks:
|
|
- vexplor-network
|
|
|
|
# ============================================
|
|
# 볼륨 정의
|
|
# ============================================
|
|
volumes:
|
|
postgres_data:
|
|
driver: local
|
|
backend_uploads:
|
|
driver: local
|
|
backend_data:
|
|
driver: local
|
|
backend_logs:
|
|
driver: local
|
|
|
|
# ============================================
|
|
# 네트워크 정의
|
|
# ============================================
|
|
networks:
|
|
vexplor-network:
|
|
driver: bridge
|
|
|