diff --git a/README.md b/README.md index 55794cb..f1ff9b3 100644 --- a/README.md +++ b/README.md @@ -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.