Add three new NestJS modules following DDD/CQRS architecture: - Industrial: KCN (industrial park) management with PostGIS geo queries, Typesense search, and market statistics - Transfer: Furniture/premises transfer listings with AI-powered price estimation and depreciation modeling - Reports: Async AI report generation via BullMQ with Claude narrative service, PDF generation, and macro data integration Includes Prisma schema models, migrations, seed scripts, and app.module wiring with BullMQ Redis config. Co-Authored-By: Paperclip <noreply@paperclip.ing>
205 lines
7.6 KiB
Plaintext
205 lines
7.6 KiB
Plaintext
# =============================================================================
|
|
# GoodGo Platform — Environment Variables
|
|
# Copy this file to .env and update values for your local environment
|
|
# =============================================================================
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# PostgreSQL + PostGIS
|
|
# -----------------------------------------------------------------------------
|
|
DB_HOST=localhost
|
|
DB_PORT=5432
|
|
DB_NAME=goodgo
|
|
DB_USER=goodgo
|
|
DB_PASSWORD=CHANGE_ME
|
|
DATABASE_URL=postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}?schema=public
|
|
|
|
# Direct connection (bypasses PgBouncer — used for migrations/introspection)
|
|
DATABASE_URL_DIRECT=postgresql://${DB_USER}:${DB_PASSWORD}@${DB_HOST}:${DB_PORT}/${DB_NAME}?schema=public
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# PgBouncer (Connection Pooling — production only)
|
|
# -----------------------------------------------------------------------------
|
|
PGBOUNCER_POOL_SIZE=20
|
|
PGBOUNCER_MAX_CLIENT_CONN=200
|
|
PGBOUNCER_ADMIN_PASSWORD=CHANGE_ME
|
|
PGBOUNCER_STATS_PASSWORD=CHANGE_ME
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Redis
|
|
# -----------------------------------------------------------------------------
|
|
REDIS_HOST=localhost
|
|
REDIS_PORT=6379
|
|
REDIS_PASSWORD=CHANGE_ME_IN_PRODUCTION
|
|
REDIS_URL=redis://:${REDIS_PASSWORD}@${REDIS_HOST}:${REDIS_PORT}
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Typesense
|
|
# -----------------------------------------------------------------------------
|
|
TYPESENSE_HOST=localhost
|
|
TYPESENSE_PORT=8108
|
|
TYPESENSE_PROTOCOL=http
|
|
TYPESENSE_API_KEY=CHANGE_ME
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# MinIO (S3-compatible Object Storage)
|
|
# -----------------------------------------------------------------------------
|
|
MINIO_ENDPOINT=localhost
|
|
MINIO_API_PORT=9000
|
|
MINIO_PORT=9000
|
|
MINIO_CONSOLE_PORT=9001
|
|
MINIO_ACCESS_KEY=CHANGE_ME
|
|
MINIO_SECRET_KEY=CHANGE_ME
|
|
MINIO_BUCKET=goodgo-media
|
|
MINIO_USE_SSL=false
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# NestJS API
|
|
# -----------------------------------------------------------------------------
|
|
API_PORT=3000
|
|
PORT=3001
|
|
NODE_ENV=development
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# CORS — comma-separated allowed origins (REQUIRED in production)
|
|
# -----------------------------------------------------------------------------
|
|
CORS_ORIGINS=http://localhost:3000,http://localhost:3001
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# JWT / Auth (REQUIRED — app will not start without these)
|
|
#
|
|
# SECURITY: Generate strong, random secrets (min 32 characters).
|
|
# openssl rand -base64 48
|
|
#
|
|
# Do NOT use placeholder values like "CHANGE_ME" — the app will reject them.
|
|
# Each secret must be unique and kept out of version control.
|
|
# -----------------------------------------------------------------------------
|
|
JWT_SECRET=<generate with: openssl rand -base64 48>
|
|
JWT_EXPIRES_IN=15m
|
|
JWT_REFRESH_SECRET=<generate with: openssl rand -base64 48>
|
|
JWT_REFRESH_EXPIRES_IN=7d
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# OAuth Providers
|
|
# -----------------------------------------------------------------------------
|
|
GOOGLE_CLIENT_ID=
|
|
GOOGLE_CLIENT_SECRET=
|
|
GOOGLE_CALLBACK_URL=http://localhost:3001/auth/google/callback
|
|
|
|
ZALO_APP_ID=
|
|
ZALO_APP_SECRET=
|
|
ZALO_CALLBACK_URL=http://localhost:3001/auth/zalo/callback
|
|
|
|
FRONTEND_URL=http://localhost:3000
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Next.js Web
|
|
# -----------------------------------------------------------------------------
|
|
NEXT_PUBLIC_API_URL=http://localhost:3000
|
|
WEB_PORT=3001
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# AI Service (Python/FastAPI)
|
|
# -----------------------------------------------------------------------------
|
|
AI_SERVICE_PORT=8000
|
|
AI_SERVICE_URL=http://localhost:8000
|
|
CLAUDE_API_KEY=
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Mapbox
|
|
# -----------------------------------------------------------------------------
|
|
NEXT_PUBLIC_MAPBOX_TOKEN=
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Payment Gateways (VNPay, MoMo, ZaloPay)
|
|
# Leave empty if not using payment features
|
|
# -----------------------------------------------------------------------------
|
|
VNPAY_TMN_CODE=
|
|
VNPAY_HASH_SECRET=
|
|
VNPAY_BASE_URL=https://sandbox.vnpayment.vn/paymentv2/vpcpay.html
|
|
VNPAY_API_URL=https://sandbox.vnpayment.vn/merchant_webapi/api/transaction
|
|
|
|
MOMO_PARTNER_CODE=
|
|
MOMO_ACCESS_KEY=
|
|
MOMO_SECRET_KEY=
|
|
MOMO_ENDPOINT=https://test-payment.momo.vn/v2/gateway/api
|
|
|
|
ZALOPAY_APP_ID=
|
|
ZALOPAY_KEY1=
|
|
ZALOPAY_KEY2=
|
|
ZALOPAY_ENDPOINT=https://sb-openapi.zalopay.vn/v2
|
|
|
|
BANK_TRANSFER_ACCOUNT_NUMBER=
|
|
BANK_TRANSFER_BANK_NAME=
|
|
BANK_TRANSFER_ACCOUNT_HOLDER=
|
|
BANK_TRANSFER_WEBHOOK_SECRET=
|
|
BANK_TRANSFER_INSTRUCTIONS_URL=https://goodgo.vn/thanh-toan/chuyen-khoan
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Email / SMTP
|
|
# -----------------------------------------------------------------------------
|
|
SMTP_HOST=localhost
|
|
SMTP_PORT=1025
|
|
SMTP_USER=
|
|
SMTP_PASS=
|
|
SMTP_FROM=noreply@goodgo.vn
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Stringee SMS (Vietnamese SMS provider — OTP & notifications)
|
|
# -----------------------------------------------------------------------------
|
|
STRINGEE_API_KEY=
|
|
STRINGEE_BRANDNAME=GoodGo
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Firebase Cloud Messaging (optional)
|
|
# -----------------------------------------------------------------------------
|
|
FIREBASE_SERVICE_ACCOUNT=
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Zalo OA Notifications (ZNS — Zalo Notification Service)
|
|
# Obtain from Zalo OA Manager: https://oa.zalo.me/manage
|
|
# -----------------------------------------------------------------------------
|
|
ZALO_OA_ID=
|
|
ZALO_OA_ACCESS_TOKEN=
|
|
|
|
# ZNS Template IDs (registered in Zalo OA Manager console)
|
|
ZALO_ZNS_TEMPLATE_INQUIRY=
|
|
ZALO_ZNS_TEMPLATE_PAYMENT=
|
|
ZALO_ZNS_TEMPLATE_LISTING_APPROVED=
|
|
ZALO_ZNS_TEMPLATE_LISTING_REJECTED=
|
|
ZALO_ZNS_TEMPLATE_LISTING_SOLD=
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Sentry Error Tracking
|
|
# -----------------------------------------------------------------------------
|
|
SENTRY_DSN=
|
|
NEXT_PUBLIC_SENTRY_DSN=
|
|
SENTRY_AUTH_TOKEN=
|
|
SENTRY_ORG=
|
|
SENTRY_PROJECT=
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# KYC Field Encryption (REQUIRED in production)
|
|
#
|
|
# AES-256-GCM key for encrypting sensitive KYC data at rest.
|
|
# Must be exactly 64 hex characters (32 bytes).
|
|
# openssl rand -hex 32
|
|
# -----------------------------------------------------------------------------
|
|
KYC_ENCRYPTION_KEY=<generate with: openssl rand -hex 32>
|
|
KYC_ENCRYPTION_KEY_VERSION=1
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Logging
|
|
# -----------------------------------------------------------------------------
|
|
LOG_LEVEL=info
|
|
|
|
# -----------------------------------------------------------------------------
|
|
# Monitoring & Alerting
|
|
# -----------------------------------------------------------------------------
|
|
GRAFANA_ADMIN_USER=admin
|
|
GRAFANA_ADMIN_PASSWORD=CHANGE_ME
|
|
GRAFANA_PORT=3002
|
|
GRAFANA_ROOT_URL=http://localhost:3002
|
|
|
|
# Slack webhook for alert notifications (Alertmanager + CI/CD)
|
|
SLACK_WEBHOOK_URL=https://hooks.slack.com/services/CHANGE_ME
|