Implement complete metering data management for energy communities: - MeteringData entity with unique constraint (metering_point_id, interval_start, data_type) - Bulk upload via JSON or XLSX (multipart) with validation - XLSX parser using Apache POI with comma-decimal support - Ownership check on GET endpoints (userId must match metering point owner) - Deduplication: existing records overwritten on re-upload - DataSource tracking (EMAIL_XLSX, API, MANUAL) - Query endpoints: by metering point, by type, by upload batch Additional fixes: - MapStruct annotation processor: add to execution-level annotationProcessorPaths (Spring Boot parent POM was overriding plugin-level config) - EnergyCommunityMapper + MeteringDataMapper: componentModel=spring - UserMapper: ignore passwordResetToken/Expiry (unmapped target policy ERROR) - TariffService: add TariffInviteRepository dependency + invitation check - TariffServiceTest: add missing @Mock for TariffInviteRepository - SecurityConfig: permit /actuator/health and /actuator/info - pom.xml: add poi-ooxml, postgresql, spring-boot-starter-actuator - .gitignore: add *.log, survey/, backend.log Tests: 137/137 passing
75 lines
2.1 KiB
YAML
75 lines
2.1 KiB
YAML
services:
|
|
db:
|
|
image: postgres:16-alpine
|
|
container_name: eeg-database
|
|
restart: unless-stopped
|
|
environment:
|
|
- POSTGRES_DB=${POSTGRES_DB:-eegportal}
|
|
- POSTGRES_USER=${POSTGRES_USER:-eeg}
|
|
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}
|
|
volumes:
|
|
- pg-data:/var/lib/postgresql/data
|
|
networks:
|
|
- eeg-network
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-eeg} -d ${POSTGRES_DB:-eegportal}"]
|
|
interval: 10s
|
|
timeout: 5s
|
|
retries: 5
|
|
start_period: 30s
|
|
|
|
backend:
|
|
build:
|
|
context: .
|
|
dockerfile: Dockerfile
|
|
container_name: eeg-backend
|
|
restart: unless-stopped
|
|
depends_on:
|
|
db:
|
|
condition: service_healthy
|
|
environment:
|
|
- SPRING_PROFILES_ACTIVE=prod
|
|
- JWT_SECRET=${JWT_SECRET:?JWT_SECRET must be set}
|
|
- APP_FRONTEND_URL=${APP_FRONTEND_URL:?APP_FRONTEND_URL must be set}
|
|
- APP_BACKEND_URL=${APP_BACKEND_URL:?APP_BACKEND_URL must be set}
|
|
- CORS_ORIGINS=${CORS_ORIGINS:?CORS_ORIGINS must be set}
|
|
- DATABASE_URL=jdbc:postgresql://db:5432/${POSTGRES_DB:-eegportal}
|
|
- DATABASE_DRIVER=org.postgresql.Driver
|
|
- DATABASE_USERNAME=${POSTGRES_USER:-eeg}
|
|
- DATABASE_PASSWORD=${POSTGRES_PASSWORD:?POSTGRES_PASSWORD must be set}
|
|
- MAIL_HOST=${MAIL_HOST:-}
|
|
- MAIL_PORT=${MAIL_PORT:-587}
|
|
- MAIL_USERNAME=${MAIL_USERNAME:-}
|
|
- MAIL_PASSWORD=${MAIL_PASSWORD:-}
|
|
- JAVA_OPTS=${JAVA_OPTS:--Xms256m -Xmx512m}
|
|
networks:
|
|
- eeg-network
|
|
healthcheck:
|
|
test: ["CMD-SHELL", "curl -f http://localhost:8080/actuator/health || exit 1"]
|
|
interval: 30s
|
|
timeout: 5s
|
|
retries: 3
|
|
start_period: 60s
|
|
|
|
frontend:
|
|
image: nginx:alpine
|
|
container_name: eeg-frontend
|
|
restart: unless-stopped
|
|
ports:
|
|
- "${APP_PORT:-80}:80"
|
|
volumes:
|
|
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
|
|
depends_on:
|
|
backend:
|
|
condition: service_healthy
|
|
networks:
|
|
- eeg-network
|
|
|
|
volumes:
|
|
pg-data:
|
|
driver: local
|
|
|
|
networks:
|
|
eeg-network:
|
|
driver: bridge
|