05/07 Phase 3: initial codes

This commit is contained in:
2026-05-07 12:17:19 -04:00
parent 6e5518c103
commit ce462c57b2
107 changed files with 6365 additions and 208 deletions
+45 -3
View File
@@ -682,8 +682,37 @@ WantedBy=multi-user.target
- [x] `tests/test_admin_phase2.py` — full test suite for all 7 modules
- [x] Demo account creation deferred — available via `POST /tenants/new` with `is_demo=1`
### Phase 3 — Multi-Location & Tenant Core Modules
- [ ] Location management (CRUD, primary flag, per-location settings)
### Phase 3 — Multi-Location & Tenant Core Modules ✅ COMPLETE
- [x] Location management (CRUD, primary flag, switch, plan limit check)
- [x] Location switcher UI + tenant_staff location restriction enforcement
- [x] Staff management (profiles, job type, location assignment, passcode set/reset)
- [x] Staff passcode management (validate_passcode helper in security.py)
- [x] Dashboard (Phase 3 KPIs: revenue, appointments, staff on shift, queue count, upcoming)
- [x] Customers (search, CRUD, visit history, no-show count, soft-delete)
- [x] Services & products (tenant-wide catalogue, soft-delete)
- [x] Promotions management (create, activate/deactivate, applies_to, target_ids_json)
- [x] Promotion engine: get_active_promotion() + apply_promotion_to_price() in app/tenant/utils.py
- [x] Appointments (calendar by day, create, edit, status workflow, no-show counter, cancellation)
- [x] Customer check-in kiosk (/checkin/<slug>; auto-profile creation; queue entry; rate-limited; CSRF-exempt)
- [x] Queue polling API: GET /api/v1/checkin/queue + POST /api/v1/checkin/queue/<id>/acknowledge
- [x] Online booking (/book/<slug>; no auth; availability check; confirmation email; tenant_feature_required)
- [x] Waitlist (add, notify via email, set booked/expired; tenant_feature_required)
- [x] Staff Portal (clock in/out, today's appointments, schedule, commission, profile)
- [x] POS/Checkout (services + products, auto-apply promotions, tip, gift card redemption, payment method)
- [x] Rebook at checkout (creates pending appointment + 24h reminder; linked to transaction)
- [x] Gift cards (unique code gen, issuance, balance lookup, POS redemption, deactivate)
- [x] Transaction void (reason required; gift card balance reversed)
- [x] End-of-day reconciliation (close day, cash count, variance, history)
- [x] Reviews dashboard (avg rating, distribution chart, list)
- [x] Settings (managed key/value pairs for booking, reviews, receipt)
- [x] Phase 4 stubs (inventory, marketing, reports) registered with feature_unavailable page
- [x] app/tenant/utils.py — log_tenant_action, plan_limit_check, get_active_promotion, apply_promotion_to_price
- [x] All 17 Phase 3 blueprints registered in create_tenant_app()
- [x] All nav links in tenant/layouts/base.html wired to Phase 3 routes
- [x] Both template trees (templates/ and app/templates/) in sync: 67 files each
- [x] All 46 render_template references verified against disk
### Phase 3 Location management (CRUD, primary flag, per-location settings)
- [ ] Location switcher UI + `tenant_staff` location restriction enforcement
- [ ] Staff ↔ location assignment (many-to-many)
- [ ] Staff passcode management (set at creation, reset by admin/manager, never stored in plaintext)
@@ -953,6 +982,16 @@ Both portal apps set `template_folder` to the project-root `templates/` director
- Admin templates: `"admin/auth/login.html"`, `{% extends "admin/layouts/base.html" %}`
- Tenant templates: `"tenant/auth/login.html"`, `{% extends "tenant/layouts/base.html" %}`
### Template Authoring Checklist
Every new template must satisfy all of the following before delivery:
1. File lives in `templates/` (project root) — not `app/templates/`
2. First line is `{% extends "admin/layouts/base.html" %}` (admin) or `{% extends "tenant/layouts/base.html" %}` (tenant)
3. Every `url_for('blueprint.endpoint')` call references a route that is actually registered (not a stub). Stubs use `'#'`
4. No bare `{{ expression }}` outside an HTML tag
5. No `{{ csrf_token() }}` rendered as standalone text — only inside `value="..."` of a hidden input
### Phase 2 Blueprint Stubs
All Phase 2+ blueprints are registered as stubs (blueprint object only, no routes) so the app boots cleanly. The admin portal base template references to `url_for('tenants.index')`, `url_for('system_users.index')` etc. are replaced with `#` until Phase 2 routes are implemented.
@@ -988,4 +1027,7 @@ All Phase 2+ blueprints are registered as stubs (blueprint object only, no route
| 24 | Admin login URL | Admin auth blueprint uses `url_prefix=""`. Login page is at `posadmin.ngodanguyen.tech/login`. Root `/` redirects to `/login` (unauthenticated) or `/dashboard` (authenticated). |
| 25 | JWT blocklist table location | `jwt_blocklist` defined in `platform.py` (not `salon.py`) — it is a platform-level concern shared across all tenants. DB-persisted (not in-memory) to survive Gunicorn worker restarts. |
| 26 | Template path convention | `template_folder` points to project-root `templates/`. All `render_template()` calls and `{% extends %}` use full paths: `"admin/auth/login.html"`, `"admin/layouts/base.html"`, `"tenant/auth/login.html"`, etc. |
| 27 | Production domains | Admin portal: `posadmin.ngodanguyen.tech`. Tenant portal: `pos.ngodanguyen.tech`. Updated in `.env`, `nginx.conf`, and all documentation. |
| 27 | Production domains | Admin portal: `posadmin.ngodanguyen.tech`. Tenant portal: `pos.ngodanguyen.tech`. Updated in `.env`, `nginx.conf`, and all documentation. |
| 28 | Authoritative template tree | `templates/` (project root) is the **only** authoritative template tree. The app factories use `os.path.abspath(__file__)` to resolve this path absolutely. `app/templates/` exists as a mirror for legacy compatibility but `templates/` is the source of truth. All new templates go in `templates/` only. |
| 29 | Template extends convention | All admin templates extend `"admin/layouts/base.html"`. All tenant templates extend `"tenant/layouts/base.html"`. These paths are relative to the `templates/` root. Any other extends path (`"layouts/base.html"`, `"tenant/base.html"`, `"admin/base.html"`) is wrong and will produce a 500. |
| 30 | Phase 3+ nav links in base template | All Phase 3+ `url_for()` calls in `templates/tenant/layouts/base.html` are replaced with `'#'` until those blueprints are implemented. Leaving live `url_for()` calls pointing at stub-only blueprints causes `BuildError` 500s on every authenticated page load. |