westfarn 045e956011
Deploy Beta / unit-tests (push) Successful in 24s
Deploy Beta / docker (push) Successful in 30s
Deploy Beta / deploy-beta (push) Successful in 7m22s
Add PCM carrier-route postcard pick-and-send (#16)
## Summary
Closes #15.
Mirrors westfarn/web_django_template#11.

- Compose can target the postcard mailing list **or** find and select one or two USPS carrier routes by ZIP (optional radius).
- Estimated cost is shown per route and for the selection (PCM design pricing, else `PCM_POSTCARD_PRICE_*` fallback).
- Selected routes order through PCM `POST /order/postcard/with-list-count` — occupant addresses are not imported into Contacts.
- Not official EDDM postage; PCM FirstClass/Standard purchased occupant lists on carrier routes.

## Test plan
- [ ] Campaign compose: mailing-list audience still quotes list size × per-piece cost.
- [ ] Switch to USPS carrier routes, search ZIP 60540 (mocked or live PCM), pick 1–2 routes, confirm household count + estimated cost.
- [ ] Saving without a selection is rejected; saving with a quote creates one contact-less Message and shows the route panel on the report.
- [ ] Send places `/order/postcard/with-list-count` (not per-recipient `/order/postcard`).
- [ ] `uv run python manage.py test messaging.tests.CarrierRoutePostcardTests messaging.tests.PostcardDesignPickTests`

Reviewed-on: #16
2026-09-21 13:29:20 -07:00
2026-07-16 05:48:12 -05:00

monica_site

Django 6 marketing platform for Monica Dhillon / MKDRealtor.com — public site, realtor portal, multi-channel outreach (email + SMS via SMTP2GO, postcards via PCM Integrations), and social scheduling (Facebook / Instagram / LinkedIn) with Ollama-assisted drafting.

Stack

  • Django 6 + uv
  • Postgres (prod/beta); SQLite locally when DATABASE_URL unset
  • dj-queue (Django Tasks backend, Postgres queue, no Redis/Celery)
  • Docker; deploy via server-infra Ansible pipeline

Environments

Env Domain Port (host) Gate
prod mkdrealtor.com 8004 SITE_UNDER_CONSTRUCTION=true (holding page)
beta monica-preview.aimloperations.com 8014 full app (SITE_UNDER_CONSTRUCTION=false)

Local development

uv sync
cd site
uv run python manage.py migrate
uv run python manage.py runserver
# optional: docker compose up   # web + postgres + worker (hot reload)

Docker compose mounts ./site into the container and runs Django runserver when DJANGO_ENV=dev (the default). The worker service polls dispatch_due every 15s so scheduled campaigns and social posts fire without a manual command. Edit Python/templates → auto-reload; no image rebuild. Rebuild only when Dockerfile, entrypoint scripts, or deps (pyproject.toml, uv.lock) change:

docker compose up --build

Local secrets (SMTP2GO, etc.)

Copy .env.example → .env (gitignored). Compose reads .env for email vars.

cp .env.example .env
# fill EMAIL_HOST_USER / EMAIL_HOST_PASSWORD
# for real delivery (not console logs):
# EMAIL_BACKEND=django.core.mail.backends.smtp.EmailBackend
docker compose up

Without EMAIL_BACKEND=…smtp…, mail prints to the web container logs (console backend).

SMTP2GO delivery webhooks

See site/messaging/README.md for SMTP2GO email/SMS webhooks and PCM Integrations postcard designer + webhook setup (Bearer auth, events).

Prod compose (docker-compose.prod.yml) still uses gunicorn with baked-in image code.

Secret env files (control node)

Create on the deploy host:

~/Documents/secrets/monica_site/monica_site_prod.env
~/Documents/secrets/monica_site/monica_site_beta.env

Templates: .env.prod.example (full var list). Validate with:

./scripts/validate-env.sh ~/Documents/secrets/monica_site/monica_site_prod.env

Campaign UTM short links (piha.li) need both sides:

File Vars
monica_site_prod.env SHORTENER_BASE_URL=https://piha.lc · SHORTENER_API_TOKEN=monica:<secret>
monica_site_beta.env SHORTENER_BASE_URL=https://beta.piha.li · distinct SHORTENER_API_TOKEN
url_shortening_service_prod.env SHORTENER_API_TOKENS=monica:<same-secret> · SHORT_ALLOWED_HOSTS includes mkdrealtor.com · PUBLIC_SHORT_URL=https://piha.lc
url_shortening_service_beta.env matching beta token · PUBLIC_SHORT_URL=https://beta.piha.li

Generate the secret with python -c "import secrets; print(secrets.token_urlsafe(32))". Do not put it in git. Mint and redirects share the short host; Bearer is required on /api/.

Deploy

CI on merge to main → tests → server-infra/scripts/deploy.sh --app monica_site --env prod --ref <sha>.

Start the dj-queue worker on exactly one host:

docker compose -f docker-compose.prod.yml --profile worker up -d

Apps

public · accounts · dashboard · leads · contacts · analytics · messaging · social

Social AI drafts: POST /portal/social/api/generate/ → Ollama at OLLAMA_BASE_URL (default http://10.0.0.128:11434).

See docs/monica-site-design.md for architecture.

S
Description
No description provided
Readme
59 MiB
0 Stars 2 Watchers 0 Forks
Languages
HTML 35.9%
SCSS 24.5%
Python 17.2%
PHP 7.7%
Pug 6.2%
Other 8.5%