Replace persisted event statuses with publication and cancellation flags, and compute public lifecycle labels from event timing and registration capacity. Keep filters, registration checks, and profile responses aligned with the derived status.
Guilan ACE Backend
Stack
- Django 5 with Ninja API routers
- PostgreSQL, Redis, Celery, Gunicorn
- Prometheus instrumentation through
django-prometheus
Layout
guilan-ace-backend/
apps/
users/
blog/
gallery/
events/
communications/
payments/
certificates/
core/
config/
static/
templates/
manage.py
Local development on Windows (no Compose)
The backend, frontend, Celery worker, and Celery beat run as separate processes. PostgreSQL must listen on 127.0.0.1:5432 and Redis on 127.0.0.1:6379. Redis can be a standalone container with its port published; no other service needs Docker.
Use Python 3.13 for the pinned dependencies. From this directory in PowerShell:
py -3.13 -m venv .venv
python -m pip install -r requirements.txt
Copy-Item .env.development.example .env
Fill in SECRET_KEY, JWT_SECRET_KEY, DB_PASSWORD, SMS_APIKEY, the SMS template IDs you use, and ZARINPAL_MERCHANT_ID in the ignored .env. Leave ZARINPAL_USE_SANDBOX=True. The frontend's .env should contain NEXT_PUBLIC_API_BASE_URL=http://127.0.0.1:8000 and NEXT_PUBLIC_SITE_URL=http://localhost:8080. Copy its .env.sample if needed.
Create the local database once, then apply migrations. Use the PostgreSQL createdb.exe from your installation if it is not on PATH:
$env:PGPASSWORD = '<your local PostgreSQL password>'
createdb -h 127.0.0.1 -p 5432 -U postgres guilan_ace_local
python manage.py migrate
Open four PowerShell terminals. Run the first three in this backend directory:
python manage.py runserver 127.0.0.1:8000
celery -A config.services.celery worker --pool=solo --loglevel=INFO
New-Item -ItemType Directory -Force (Join-Path $env:TEMP 'guilan-ace-local') | Out-Null
celery -A config.services.celery beat --loglevel=INFO --schedule (Join-Path $env:TEMP 'guilan-ace-local\celerybeat-schedule')
Run the frontend in the sibling guilan-ace-frontend directory:
npm.cmd ci
npm.cmd run dev
Open http://localhost:8080 for the site and http://127.0.0.1:8000/api/docs for the API. Django serves local media under /media/. The first Next.js page request may take a while to compile.
The June 12, 2026 server backup was restored locally into guilan_ace_local and this repository's ignored media/ directory. The backup also supplied the local SMS.ir OTP credentials. Its other SMS template IDs were empty. The local .env points at localhost and Zarinpal's sandbox; never replace it directly with the backup's production environment file. The previous local .env is saved as ignored .env.bak.
Tests
Install test dependencies, then run the two pytest suites:
python -m pip install -r requirements-test.txt
python -m pytest -m unit
python -m pytest -m integration
CI uses PostgreSQL for integration tests and combines branch coverage from both suites. The same coverage gate can be run locally after configuring the test database:
python -m coverage run -m pytest -m unit
python -m coverage run --append -m pytest -m integration
python -m coverage json -o coverage.json
python scripts/check_coverage.py coverage.json --minimum 80
Coverage includes executable modules in apps, core, and config. The fixed exclusions are migrations, tests, __init__.py, apps.py, config/settings, ASGI/WSGI entrypoints, and constant-only service config modules (location, notifications, and zarinpal). Every included module must reach 80% combined statement and branch coverage.
Notes
- Domain routers live under
apps/<domain>/api. - Shared auth helpers live in
core/authentication.py. - Shared base models, admin helpers, choices, and template tags live under
core/.
Project-local skills
Backend implementation guidance is vendored in .agents/skills/: api-and-interface-design, deprecation-and-migration, and test-driven-development. Shared team guidance is also included: grill-me, grilling, planning-and-task-breakdown, documentation-and-adrs, and git-workflow-and-versioning. These directories are part of this repository so they are available after cloning it.