Components
Inside Express, each module owns its tables and exposes functions to the others. HTTP handlers are thin: they validate input, call a module, and map the result to JSON. Cross-module writes that must succeed or fail together run in one Prisma transaction.
Module map
| Module | Tables | Called by |
|---|---|---|
| Authentication | users, user_credentials, refresh_tokens, account_setup_tokens, password_reset_tokens, user_mfa_factors | Every private route |
| Catalog | services, service_packages | Orders |
| Bookings | bookings | Orders, galleries, rewards |
| Orders | orders, order_items, idempotency_keys | Payments, rewards |
| Payments | payments, payment_webhook_events | Bookings, rewards, notifications |
| Galleries | galleries, gallery_access_reviews, photos, photo_ratings | Notifications |
| Rewards | referral_codes, referrals, reward_policies, referral_rewards, reward_ledger, reward_redemptions | Orders, payments |
| Notifications | notifications, notification_deliveries, background_jobs | Bookings, galleries, rewards |
| Audit | audit_logs | Authentication, bookings, galleries, rewards |
Request path for a paid booking
- The catalog module loads the active package and returns
price_cents. - The orders module inserts the order and item snapshot. The bookings module inserts the booking. A referral code, if present and valid, inserts an attribution in the same transaction.
- The payments module creates a Stripe checkout for
total_centsandUSD. - The webhook handler verifies the signature, inserts
payment_webhook_events, and only then marks the order paid and the bookingPENDING_APPROVAL. - The rewards module may attach the qualifying order and insert a
PENDINGreward. It does not post a ledger credit yet. - The notifications module queues photographer email and an in-app notification.
The photographer decision is a later call. Approval confirms the booking and posts the reward credit if the order is still paid. Rejection enqueues a refund and withholds the credit.
Background jobs
| Job type | Purpose |
|---|---|
email.deliver | Send one notification delivery and update notification_deliveries. |
image.thumbnail | Read the original from private storage, write a thumbnail, and set the photo to READY. |
payment.refund | Call Stripe for a refund that was committed with a rejection or cancellation. |
payment.reconcile | Read a stuck payment from the provider when a webhook was missed. |
reward.expire | Post an expiration ledger entry for an available reward past expires_at. |
Jobs are claimed with a row lock on background_jobs where status is pending and available_at is due. A failure increments attempt_count, stores last_error, and sets a later available_at.
Documentation container
Docusaurus is a separate static site. It holds the pages in this project and the OpenAPI document. It does not read PostgreSQL.