Initial commit: PESCO NCR system
Complete Non-Conformance Report system replacing the PowerApps/SharePoint prototype: FastAPI + SQLAlchemy 2 (async) + Alembic + MySQL 8 backend, React 18 + Vite + TypeScript + MUI frontend, Entra ID auth (MSAL / JWKS, group-gated), Microsoft Graph delegated Mail.Send notifications (OBO), six-stage workflow state machine with server-side enforcement, atomic NCR-YYYY-NNNN numbering, attachments with camera capture, immutable field-level audit trail, admin reopen, reports + CSV export, WeasyPrint PDF traveler, Power BI reporting views + read-only DB user, documented VISUAL ERP job-lookup stub, pytest suite (26 tests), docker-compose deployment. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
87
docker-compose.yml
Normal file
87
docker-compose.yml
Normal file
@@ -0,0 +1,87 @@
|
||||
name: pesco-ncr
|
||||
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:8.4
|
||||
command:
|
||||
- --character-set-server=utf8mb4
|
||||
- --collation-server=utf8mb4_unicode_ci
|
||||
environment:
|
||||
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
|
||||
MYSQL_DATABASE: ${MYSQL_DATABASE:-pesco_ncr}
|
||||
MYSQL_USER: ${MYSQL_USER:-ncr_app}
|
||||
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
|
||||
POWERBI_RO_PASSWORD: ${POWERBI_RO_PASSWORD}
|
||||
ports:
|
||||
# Published so the on-prem Power BI gateway can reach the reporting views.
|
||||
# Remove or firewall this mapping if external reporting access is not needed.
|
||||
- "${MYSQL_PUBLISHED_PORT:-3306}:3306"
|
||||
volumes:
|
||||
- mysql_data:/var/lib/mysql
|
||||
- ./db/init:/docker-entrypoint-initdb.d:ro
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -u root -p$$MYSQL_ROOT_PASSWORD --silent"]
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 30
|
||||
start_period: 40s
|
||||
restart: unless-stopped
|
||||
|
||||
api:
|
||||
build: ./backend
|
||||
environment:
|
||||
APP_BASE_URL: ${APP_BASE_URL:-http://localhost:8080}
|
||||
LOG_LEVEL: ${LOG_LEVEL:-INFO}
|
||||
AUTH_MODE: ${AUTH_MODE:-entra}
|
||||
ENTRA_TENANT_ID: ${ENTRA_TENANT_ID:-}
|
||||
ENTRA_CLIENT_ID: ${ENTRA_CLIENT_ID:-}
|
||||
ENTRA_CLIENT_SECRET: ${ENTRA_CLIENT_SECRET:-}
|
||||
ENTRA_ALLOWED_GROUP_ID: ${ENTRA_ALLOWED_GROUP_ID:-}
|
||||
ENTRA_API_AUDIENCE: ${ENTRA_API_AUDIENCE:-}
|
||||
INITIAL_ADMIN_EMAILS: ${INITIAL_ADMIN_EMAILS:-}
|
||||
MYSQL_HOST: mysql
|
||||
MYSQL_PORT: 3306
|
||||
MYSQL_DATABASE: ${MYSQL_DATABASE:-pesco_ncr}
|
||||
MYSQL_USER: ${MYSQL_USER:-ncr_app}
|
||||
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
|
||||
ATTACHMENTS_DIR: ${ATTACHMENTS_DIR:-/data/attachments}
|
||||
MAX_UPLOAD_MB: ${MAX_UPLOAD_MB:-25}
|
||||
NOTIFICATIONS_ENABLED_DEFAULT: ${NOTIFICATIONS_ENABLED_DEFAULT:-true}
|
||||
JOB_LOOKUP_PROVIDER: ${JOB_LOOKUP_PROVIDER:-null}
|
||||
VISUAL_DB_HOST: ${VISUAL_DB_HOST:-}
|
||||
VISUAL_DB_PORT: ${VISUAL_DB_PORT:-1433}
|
||||
VISUAL_DB_NAME: ${VISUAL_DB_NAME:-}
|
||||
VISUAL_DB_USER: ${VISUAL_DB_USER:-}
|
||||
VISUAL_DB_PASSWORD: ${VISUAL_DB_PASSWORD:-}
|
||||
VISUAL_SITE_ID: ${VISUAL_SITE_ID:-}
|
||||
SEED_DEMO_DATA: ${SEED_DEMO_DATA:-false}
|
||||
volumes:
|
||||
- attachments_data:/data/attachments
|
||||
depends_on:
|
||||
mysql:
|
||||
condition: service_healthy
|
||||
healthcheck:
|
||||
test: ["CMD", "curl", "-fsS", "http://localhost:8000/api/health"]
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 12
|
||||
start_period: 30s
|
||||
restart: unless-stopped
|
||||
|
||||
frontend:
|
||||
build: ./frontend
|
||||
ports:
|
||||
- "${HTTP_PORT:-8080}:80"
|
||||
environment:
|
||||
AUTH_MODE: ${AUTH_MODE:-entra}
|
||||
ENTRA_TENANT_ID: ${ENTRA_TENANT_ID:-}
|
||||
ENTRA_CLIENT_ID: ${ENTRA_CLIENT_ID:-}
|
||||
ENTRA_API_SCOPE: ${ENTRA_API_SCOPE:-}
|
||||
depends_on:
|
||||
api:
|
||||
condition: service_healthy
|
||||
restart: unless-stopped
|
||||
|
||||
volumes:
|
||||
mysql_data:
|
||||
attachments_data:
|
||||
Reference in New Issue
Block a user