Rewrite README for post-decoupling architecture
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 44s

Document all 12 blueprints, all 6 models with table, submodules,
cross-app integration via glue services, and migration ownership.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
giles
2026-02-14 19:29:09 +00:00
parent 88347222d8
commit ddbd04b67f

View File

@@ -1,48 +1,89 @@
# Events App
Calendar and event booking service for the Rose Ash cooperative platform.
Calendar and event booking service for the Rose Ash cooperative platform. Manages calendars, time slots, calendar entries (bookings), tickets, and ticket types.
## Overview
## Architecture
The events app provides calendar-based event booking with flexible slot management.
It runs as a standalone Quart microservice, part of the multi-app coop architecture.
One of four Quart microservices sharing a single PostgreSQL database:
| App | Port | Domain |
|-----|------|--------|
| blog (coop) | 8000 | Auth, blog, admin, menus, snippets |
| market | 8001 | Product browsing, Suma scraping |
| cart | 8002 | Shopping cart, checkout, orders |
| **events** | 8003 | Calendars, bookings, tickets |
## Structure
```
app.py # Application factory and entry point
events_api.py # Internal JSON API (server-to-server, CSRF-exempt)
bp/ # Blueprints
calendars/ # Calendar listing
calendar/ # Single calendar view and admin
calendar_entries/ # Calendar entries listing
calendar_entry/ # Single entry view and admin
day/ # Day view and admin
slots/ # Slot listing
slot/ # Single slot management
ticket_types/ # Ticket type listing
ticket_type/ # Single ticket type management
templates/ # Jinja2 templates
_types/ # Feature-specific templates
app.py # Application factory (create_base_app + blueprints)
path_setup.py # Adds project root + app dir to sys.path
config/app-config.yaml # App URLs, feature flags
events_api.py # Internal API (/internal/events/*)
models/ # Events-domain models
calendars.py # Calendar, CalendarEntry, CalendarSlot,
# TicketType, Ticket, CalendarEntryPost
bp/ # Blueprints
calendars/ # Calendar listing
calendar/ # Single calendar view and admin
calendar_entries/ # Calendar entries listing
calendar_entry/ # Single entry view and admin
day/ # Day view and admin
slots/ # Slot listing
slot/ # Single slot management
ticket_types/ # Ticket type listing
ticket_type/ # Single ticket type management
tickets/ # Ticket listing
ticket_admin/ # Ticket administration
markets/ # Page-scoped marketplace views
payments/ # Payment-related views
templates/ # Jinja2 templates
entrypoint.sh # Docker entrypoint
Dockerfile
shared/ # Submodule → git.rose-ash.com/coop/shared.git
glue/ # Submodule → git.rose-ash.com/coop/glue.git
```
## Models
All events-domain models live in `models/calendars.py`:
| Model | Description |
|-------|-------------|
| **Calendar** | Container for entries, scoped to a page via `container_type + container_id` |
| **CalendarEntry** | A bookable event/time slot. Has `state` (pending/ordered/provisional), `cost`, ownership (`user_id`/`session_id`), and `order_id` (plain integer, no FK) |
| **CalendarSlot** | Recurring time bands (day-of-week + time range) within a calendar |
| **TicketType** | Named ticket categories with price and count |
| **Ticket** | Individual ticket with unique code, state, and `order_id` (plain integer, no FK) |
| **CalendarEntryPost** | Junction linking entries to content via `content_type + content_id` |
`order_id` on CalendarEntry and Ticket is a plain integer column — no FK constraint to the orders table. The cart app writes these values via glue services (`order_lifecycle.py`), not directly.
## Cross-App Integration
- **Cart checkout:** The cart app marks entries as "ordered" and sets `order_id` via `glue/services/order_lifecycle.py`.
- **Payment confirmation:** Cart app marks entries as "provisional" via the same glue service.
- **Login adoption:** Anonymous entries are adopted to the logged-in user via `glue/services/cart_adoption.py`.
- **Internal API:** `/internal/events/` endpoints serve calendar data to other apps.
- **Cart widget:** Context processor fetches cart summary via internal API.
## Migrations
This app does **not** run Alembic migrations on startup. Migrations are managed in the `shared/` submodule and run from the blog app's entrypoint. The events app's `entrypoint.sh` skips the migration step.
## Running
```bash
# Set required environment variables (see .env.example)
export APP_MODULE=app:app
hypercorn app:app --bind 0.0.0.0:8000
export DATABASE_URL_ASYNC=postgresql+asyncpg://user:pass@localhost/coop
export REDIS_URL=redis://localhost:6379/0
export SECRET_KEY=your-secret-key
hypercorn app:app --bind 0.0.0.0:8003
```
## Docker
```bash
docker build -t events .
docker run -p 8000:8000 --env-file .env events
docker run -p 8003:8000 --env-file .env events
```
## Notes
- This app does **not** run Alembic migrations. Database schema is managed by the blog app.
- Internal API endpoints under `/internal/events/` are used by the cart app for cross-service communication.
- Depends on shared packages (`shared/`, `models/`, `config/`) from the main coop monorepo.