Internal Django app for tracking chama contributions, parsing payment SMS messages, and sending automated reminder/report emails.
- Member management (active/inactive members)
- Contribution tracking by month (one contribution per member per month)
- SMS parsing for:
- M-Pesa confirmation messages
- M-Pesa App payment messages
- Cytonn deposit confirmations
- Dashboard with monthly status and charts
- Member-level and year-level reports
- Automated email jobs with Celery:
- Reminder window (3rd-15th)
- End-of-month reminder (28th)
- Monthly report (1st of month)
- Python 3.11
- Django 5
- Celery + Redis
- PostgreSQL (production) / SQLite (development)
- Django Anymail (Brevo)
- Docker + Docker Compose
bbc_chama/Django project config (settings/dev.py,settings/prod.py,celery.py)chama/main app (models, views, parser, tasks, templates)docker-compose.ymllocal/dev multi-service stackdocker-compose.prod.ymlproduction stacknginx/nginx.confreverse proxy config for production
Main variables used by this project:
DJANGO_ENV(devorprod)SECRET_KEYALLOWED_HOSTSCSRF_TRUSTED_ORIGINSDATABASE_URLPOSTGRES_HOSTPOSTGRES_PORTPOSTGRES_DBPOSTGRES_USERPOSTGRES_PASSWORDCELERY_BROKER_URLBREVO_API_KEYDEFAULT_FROM_EMAILADMIN_EMAIL
Notes:
devsettings use SQLite and console email backend.prodsettings useDATABASE_URLand Brevo email backend.DJANGO_ENVdefaults todevif not set.
- Create and activate a virtual environment.
- Install dependencies:
pip install -r requirements.txt- Set environment:
export DJANGO_ENV=dev
export SECRET_KEY="change-me"- Run migrations:
python manage.py migrate- Create admin user:
python manage.py createsuperuser- (Optional) Seed initial members:
python manage.py seed_members \
--email-ndolo ndolo@example.com \
--email-njau njau@example.com \
--email-patrick patrick@example.com \
--email-timothy timothy@example.com \
--target 5000- Start server:
python manage.py runserverOpen:
- App:
http://127.0.0.1:8000/ - Admin:
http://127.0.0.1:8000/admin/
Start Redis, then run worker and beat in separate terminals:
celery -A bbc_chama worker -l info
celery -A bbc_chama beat -l infoScheduled tasks are defined in bbc_chama/celery.py.
Ensure a .env file exists with the variables listed above, then:
Bring up all services:
docker compose up -dRun migrations:
docker compose exec web python manage.py migrateCreate superuser:
docker compose exec web python manage.py createsuperuserThe default compose stack starts:
web(Django)db(PostgreSQL)redisworker(Celery worker)beat(Celery beat)
Open: http://127.0.0.1:8001/
- Use
DJANGO_ENV=prod. - Set
DATABASE_URLto PostgreSQL. - Configure Brevo via
BREVO_API_KEY. - Ensure
ALLOWED_HOSTSandCSRF_TRUSTED_ORIGINSare correct. - Static files are collected at container startup (
entrypoint.sh).
- Each member can have at most one contribution per month.
- Contribution month is inferred as the month before the transaction date in parsed SMS flows.
- Monthly target comes from
MonthlyTargetrecords, falling back toCHAMA_MONTHLY_TARGETin settings.
GitHub Actions (.github/workflows/ci-cd.yml) runs:
- Lint + Django system checks on PRs/pushes to
main - Docker image build and push to GHCR on
main - VPS deploy via SSH on successful main-branch build