Commit Graph

197 Commits

Author SHA1 Message Date
6dec1e3ca6 fix(ops): add missing env_file to celery-beat and quiet Stripe log spam
Some checks failed
CI / pytest (push) Has been cancelled
CI / ruff (push) Successful in 11s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
celery-beat was missing env_file and DATABASE_URL, so it had no access
to app config (Stripe keys, etc.). Also downgrade "Stripe API key not
configured" from warning to debug to stop log spam when Stripe is not
yet set up.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 22:33:54 +01:00
b5b73559b5 refactor(platform): make base template fully CMS-driven and platform-aware
Some checks failed
CI / ruff (push) Successful in 10s
CI / pytest (push) Has been cancelled
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
Remove all hardcoded OMS-specific content from platform base template:
nav links, contact info, brand name, and footer columns. Everything is
now dynamic via platform model and CMS page queries. Wire up legal_pages
context (privacy/terms) from database instead of hardcoded fallback.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 17:41:24 +01:00
28dca65a06 fix(cms): filter pricing tiers by platform_id on homepage
Some checks failed
CI / ruff (push) Successful in 11s
CI / validate (push) Successful in 25s
CI / pytest (push) Failing after 54m28s
CI / dependency-scanning (push) Successful in 30s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
_get_tiers_data() was querying all active tiers across all platforms.
Now accepts platform_id parameter to scope tiers to the current platform.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 13:09:34 +01:00
adbecd360b feat(cms): CMS-driven homepages, products section, placeholder resolution
Some checks failed
CI / ruff (push) Successful in 11s
CI / pytest (push) Failing after 51m41s
CI / validate (push) Successful in 26s
CI / dependency-scanning (push) Successful in 32s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
- Add ProductCard/ProductsSection schema and _products.html section macro
- Rewrite seed script with 3-platform homepage sections (wizard, OMS, loyalty),
  platform marketing pages, and store defaults with {{store_name}} placeholders
- Add resolve_placeholders() to ContentPageService for store default pages
- Fix SQLAlchemy filter bugs: replace Python `is None` with `.is_(None)` across
  all ContentPageService query methods (was silently breaking all platform page lookups)
- Remove hardcoded orion fallback and delete homepage-orion.html
- Add placeholder hint box with click-to-copy in admin content page editor
- Export ProductCard/ProductsSection from cms schemas __init__

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 12:12:20 +01:00
ef9ea29643 feat: module-driven onboarding system + simplified 3-step signup
Add OnboardingProviderProtocol so modules declare their own post-signup
onboarding steps. The core OnboardingAggregator discovers enabled
providers and exposes a dashboard API (GET /dashboard/onboarding).
A session-scoped banner on the store dashboard shows a checklist that
guides merchants through setup without blocking signup.

Signup is simplified from 4 steps to 3 (Plan → Account → Payment):
store creation is merged into account creation, store language is
captured from the user's browsing language, and platform-specific
template branching is removed.

Includes 47 unit and integration tests covering all new providers,
the aggregator, the API endpoint, and the signup service changes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 23:39:42 +01:00
f8a2394da5 fix: replace missing 'envelope' icon with 'mail' across modules
Some checks failed
CI / pytest (push) Failing after 47m44s
CI / validate (push) Successful in 23s
CI / dependency-scanning (push) Successful in 28s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
CI / ruff (push) Successful in 10s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 21:53:40 +01:00
4d07418f44 fix(prospecting): replace missing icons with available registry icons
Some checks failed
CI / ruff (push) Successful in 9s
CI / pytest (push) Failing after 47m22s
CI / validate (push) Successful in 24s
CI / dependency-scanning (push) Successful in 29s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
map-pin→location-marker, target→cursor-click, device-mobile→phone, radar→globe-alt

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 19:23:02 +01:00
9684747d08 feat(billing): end-to-end Stripe subscription signup with platform enforcement
Move core signup service from marketplace to billing module, add
automatic Stripe product/price sync for tiers, create loyalty-specific
signup wizard, and enforce that platform is always explicitly known
(no silent defaulting to primary/hardcoded ID).

Key changes:
- New billing SignupService with separated account/store creation steps
- Stripe auto-sync on tier create/update (new prices, archive old)
- Loyalty signup template (Plan → Account → Store → Payment)
- platform_code is now required throughout the signup flow
- Pricing/signup pages return 404 if platform not detected
- OMS-specific logic (Letzshop claiming) stays in marketplace module
- Bootstrap script: scripts/seed/sync_stripe_products.py

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 19:16:14 +01:00
2078ce35b2 fix(prospecting): resolve all architecture validator warnings
Some checks failed
CI / validate (push) Successful in 24s
CI / dependency-scanning (push) Successful in 29s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
CI / ruff (push) Successful in 10s
CI / pytest (push) Failing after 46m55s
- MDL-003: use Pydantic v2 ConfigDict in PerformanceProfileResponse
- EXC-003: suppress broad except in enrichment_service (external HTTP scanning)
- FE-004: suppress inline modal warnings in templates with noqa comments
- FE-008: suppress score filter number input warning in leads.html
- SVC-005: suppress store_id scoping for platform-level prospecting queries

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 16:49:47 +01:00
22ae63b414 refactor(prospecting): migrate SVC-006 transaction control to endpoint level
Some checks failed
CI / validate (push) Has been cancelled
CI / ruff (push) Successful in 10s
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has started running
Move db.commit() from services to API endpoints and Celery tasks.
Services now use db.flush() only; endpoints own the transaction.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 16:40:09 +01:00
6d6eba75bf feat(prospecting): add complete prospecting module for lead discovery and scoring
Some checks failed
CI / pytest (push) Failing after 48m31s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
CI / ruff (push) Successful in 11s
CI / validate (push) Successful in 23s
CI / dependency-scanning (push) Successful in 28s
Migrates scanning pipeline from marketing-.lu-domains app into Orion module.
Supports digital (domain scan) and offline (manual capture) lead channels
with enrichment, scoring, campaign management, and interaction tracking.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-28 00:59:47 +01:00
35d1559162 feat(monitoring): add Redis exporter + Sentry docs to deployment guide
Some checks failed
CI / ruff (push) Successful in 10s
CI / pytest (push) Failing after 47m30s
CI / validate (push) Successful in 24s
CI / dependency-scanning (push) Successful in 29s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
- Add redis-exporter container to docker-compose (oliver006/redis_exporter, 32MB)
- Add Redis scrape target to Prometheus config
- Add 4 Redis alert rules: RedisDown, HighMemory, HighConnections, RejectedConnections
- Document Step 19b (Sentry Error Tracking) in Hetzner deployment guide
- Document Step 19c (Redis Monitoring) in Hetzner deployment guide
- Update resource budget and port reference tables

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 23:30:18 +01:00
ce822af883 feat: production launch — email audit, team invites, security headers, router fixes
Some checks failed
CI / ruff (push) Successful in 9s
CI / pytest (push) Failing after 47m32s
CI / validate (push) Successful in 23s
CI / dependency-scanning (push) Successful in 29s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
- Fix loyalty & monitoring router bugs (_get_router → named routers)
- Implement team invitation email with send_template + seed templates (en/fr/de)
- Add SecurityHeadersMiddleware (nosniff, HSTS, referrer-policy, permissions-policy)
- Build email audit admin page: service, schemas, API, page route, menu, i18n, HTML, JS
- Clean stale TODO in platform-menu-config.js
- Add 67 tests (unit + integration) covering all new functionality

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 18:24:30 +01:00
4ebd419987 fix: admin sidebar missing on /admin/my-menu page
Some checks failed
CI / ruff (push) Successful in 9s
CI / pytest (push) Failing after 46m46s
CI / validate (push) Successful in 23s
CI / dependency-scanning (push) Successful in 29s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
Rename loadMenuConfig() → loadUserMenuConfig() in adminMyMenuConfig()
to avoid shadowing the sidebar's loadMenuConfig() inherited from data()
via the spread operator. The name collision caused the sidebar to never
populate its menuData, showing only the fallback "Dashboard" link.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 12:40:46 +01:00
30c4593e0f refactor(P6): standardize route variable naming to router
Some checks failed
CI / ruff (push) Successful in 9s
CI / pytest (push) Has been cancelled
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
All route files (admin.py, store.py) now export `router` instead of
`admin_router`/`store_router`. Consumer code (definition.py, __init__.py)
imports as `router as admin_router` where distinction is needed.
ModuleDefinition fields remain admin_router/store_router.

64 files changed across all modules. Architecture rules, docs, and
migration plan updated. Added noqa:API001 support to validator for
pre-existing raw dict endpoints now visible with standardized router name.
All 1114 tests pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 11:05:34 +01:00
8c0967e215 fix(arch): resolve all 14 architecture validation warnings
Some checks failed
CI / ruff (push) Successful in 11s
CI / pytest (push) Failing after 44m18s
CI / validate (push) Successful in 23s
CI / dependency-scanning (push) Successful in 28s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
- Add missing module dependency declarations (IMPORT-002): analytics
  requires catalog/inventory/marketplace/orders, orders requires
  marketplace, inventory requires orders
- Replace broad except Exception with specific types (EXC-003):
  StoreNotFoundException in auth_service, PlatformNotFoundException in
  admin_subscription_service, SQLAlchemyError in customer_service
- Use number_stepper macro in loyalty program-edit template (FE-008)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 06:24:57 +01:00
86e85a98b8 refactor(arch): eliminate all cross-module model imports in service layer
Some checks failed
CI / ruff (push) Successful in 9s
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / pytest (push) Has been cancelled
Enforce MOD-025/MOD-026 rules: zero top-level cross-module model imports
remain in any service file. All 66 files migrated using deferred import
patterns (method-body, _get_model() helpers, instance-cached self._Model)
and new cross-module service methods in tenancy. Documentation updated
with Pattern 6 (deferred imports), migration plan marked complete, and
violations status reflects 84→0 service-layer violations.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 06:13:15 +01:00
4aa6f76e46 refactor(arch): move auth schemas to tenancy module and add cross-module service methods
Some checks failed
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled
CI / ruff (push) Successful in 10s
Move all auth schemas (UserContext, UserLogin, LoginResponse, etc.) from
legacy models/schema/auth.py to app/modules/tenancy/schemas/auth.py per
MOD-019. Update 84 import sites across 14 modules. Legacy file now
re-exports for backwards compatibility.

Add missing tenancy service methods for cross-module consumers:
- merchant_service.get_merchant_by_owner_id()
- merchant_service.get_merchant_count_for_owner()
- admin_service.get_user_by_id() (public, was private-only)
- platform_service.get_active_store_count()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 23:57:04 +01:00
f95db7c0b1 feat(roles): add admin store roles page, permission i18n, and menu integration
Some checks failed
CI / ruff (push) Successful in 9s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has started running
- Add admin store roles page with merchant→store cascading for superadmin
  and store-only selection for platform admin
- Add permission catalog API with translated labels/descriptions (en/fr/de/lb)
- Add permission translations to all 15 module locale files (60 files total)
- Add info icon tooltips for permission descriptions in role editor
- Add store roles menu item and admin menu item in module definition
- Fix store-selector.js URL construction bug when apiEndpoint has query params
- Add admin store roles API (CRUD + platform scoping)
- Add integration tests for admin store roles and permission catalog

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 23:31:27 +01:00
2b55e7458b fix: use window.LogConfig pattern for storeRoles logger
Some checks failed
CI / ruff (push) Successful in 11s
CI / deploy (push) Has been skipped
CI / pytest (push) Failing after 45m57s
CI / validate (push) Successful in 22s
CI / dependency-scanning (push) Successful in 29s
CI / docs (push) Has been skipped
createModuleLogger is not available in store context. Use the same
window.LogConfig.createLogger pattern as team.js.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 19:24:13 +01:00
c82210795f fix: move storeRoles() to external JS with base layout inheritance
Some checks failed
CI / ruff (push) Successful in 10s
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has started running
CI / validate (push) Has been cancelled
The inline storeRoles() was missing ...data() spread, causing Alpine
errors for dark mode, sidebar, storeCode etc. Follow the same pattern
as team.js: external JS file with ...data() and parent init() call.
Uses apiClient and Utils.showToast per architecture rules.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 19:15:19 +01:00
cb3bc3c118 feat: implement complete RBAC access control with tests
Some checks failed
CI / pytest (push) Failing after 45m29s
CI / validate (push) Successful in 24s
CI / dependency-scanning (push) Successful in 28s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
CI / ruff (push) Successful in 9s
Add 4-layer access control stack (subscription → module → menu → permissions):
- P1: Wire requires_permission into menu sidebar filtering
- P2: Expose window.USER_PERMISSIONS for Alpine.js client-side gating
- P3: Add page-level permission guards on store routes
- P4: Role CRUD API endpoints and role editor UI
- P5: Audit trail for all role/permission changes

Includes unit tests (menu permission filtering, role CRUD service) and
integration tests (role API endpoints). All 404 core+tenancy tests pass.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 18:26:59 +01:00
e7f8e61717 feat: add unique constraints for custom subdomain and domain per platform
Some checks failed
CI / ruff (push) Successful in 10s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled
Add UNIQUE(custom_subdomain, platform_id) on store_platforms to prevent
two stores from claiming the same subdomain on the same platform.
Add UNIQUE(store_id, platform_id) on store_domains to enforce one custom
domain per store per platform.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 12:05:17 +01:00
ce5b54f27b feat: production routing support for subdomain and custom domain modes
Some checks failed
CI / ruff (push) Successful in 10s
CI / pytest (push) Failing after 45m18s
CI / validate (push) Successful in 24s
CI / dependency-scanning (push) Successful in 30s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
Double-mount store routes at /store/* and /store/{store_code}/* so the
same handlers work in dev path-based, prod path-based, prod subdomain,
and prod custom-domain modes.  Wire StorePlatform.custom_subdomain into
StoreContextMiddleware for per-platform subdomain overrides.  Add admin
custom-domain management UI, fix stale /shop/ reset link, add
/merchants/ to reserved paths, and server-render window.STORE_CODE for
JS that previously parsed the URL.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 00:15:06 +01:00
6a82d7c12d refactor(loyalty): replace inline modals with shared modal macros
Some checks failed
CI / ruff (push) Successful in 11s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled
Replace hand-written inline modal HTML in programs.html,
merchant-detail.html, and program-edit.html with the project's
confirm_modal, confirm_modal_dynamic, and modal macros from
shared/macros/modals.html. Resolves all 4 FE-004 architecture warnings.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 23:29:48 +01:00
f1e7baaa6c feat(loyalty): add dedicated program edit page with full CRUD and tests
Some checks failed
CI / ruff (push) Successful in 9s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has started running
Add /admin/loyalty/merchants/{id}/program route for program configuration
with a dedicated Alpine.js edit page supporting create/edit/delete flows.
Restructure programs dashboard with create modal (merchant search +
duplicate detection) and delete confirmation. Rename "Loyalty Settings"
to "Admin Policy" for clearer separation of concerns.

Add integration tests for all admin page routes (12 tests) and program
list search/filter/pagination endpoints (9 tests).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 23:25:22 +01:00
6b46a78e72 feat(loyalty): restructure program CRUD by interface
Some checks failed
CI / ruff (push) Successful in 10s
CI / pytest (push) Failing after 45m49s
CI / validate (push) Successful in 23s
CI / dependency-scanning (push) Successful in 29s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
Move program CRUD from store to merchant/admin interfaces.
Store becomes view-only for program config while merchant gets
full CRUD and admin gets override capabilities.

Merchant portal:
- New API endpoints (GET/POST/PATCH/DELETE /program)
- New settings page with create/edit/delete form
- Overview page now has Create/Edit Program buttons
- Settings menu item added to sidebar

Admin portal:
- New CRUD endpoints (create for merchant, update, delete)
- New activate/deactivate program endpoints
- Programs list has edit and toggle buttons per row
- Merchant detail has create/delete/toggle program actions

Store portal:
- Removed POST/PATCH /program endpoints (now read-only)
- Removed settings page route and template
- Terminal, cards, stats, enroll unchanged

Tests: 112 passed (58 new) covering merchant API, admin CRUD,
store endpoint removal, and program service unit tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 13:32:20 +01:00
3df75e2e78 test: add loyalty module tests for today's bug fixes
Some checks failed
CI / ruff (push) Successful in 11s
CI / dependency-scanning (push) Successful in 28s
CI / docs (push) Has been skipped
CI / pytest (push) Failing after 46m26s
CI / validate (push) Successful in 23s
CI / deploy (push) Has been skipped
Covers card lookup route ordering, func.replace normalization, customer
name in transactions, self-enrollment creation, and earn points endpoint.
54 tests total (was 1).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 23:28:22 +01:00
92a434530f refactor: rename points earn endpoint to /points/earn for clarity
Some checks failed
CI / ruff (push) Successful in 10s
CI / validate (push) Successful in 23s
CI / dependency-scanning (push) Successful in 29s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
CI / pytest (push) Failing after 45m37s
Use /points/earn and /points/redeem consistently for explicit intent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 23:04:01 +01:00
01146d5c97 fix: correct earn points API path on loyalty terminal
Some checks failed
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled
CI / ruff (push) Successful in 10s
JS called /store/loyalty/points/earn but endpoint is POST /store/loyalty/points.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 23:00:18 +01:00
d0d5aadaf7 fix: show proper transaction type labels on loyalty terminal
Some checks failed
CI / ruff (push) Successful in 10s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled
Replace naive points_delta > 0 check with actual transaction_type
labels. Previously card_created showed as "Redeemed" because
points_delta was 0. Now uses a label map matching all TransactionType
enum values with appropriate color coding.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 22:56:06 +01:00
56afb9192b fix(loyalty): fix wallet service test fixtures and mock paths
Some checks failed
CI / ruff (push) Successful in 10s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled
- Add customer_id to card fixtures (NOT NULL constraint)
- Use test_customer shared fixture instead of inline Customer creation
- Fix mock path to target source module for lazy imports

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 22:50:16 +01:00
a4519035df fix(loyalty): read Google Wallet config from core settings instead of module config
Module config only reads from os.environ (not .env), so wallet settings
were always None. Core Settings already loads these via env_file=".env".
Also adds comprehensive wallet creation tests with mocked Google API.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 22:29:27 +01:00
c9b2ecbdff fix: use SQL func.replace instead of Python str.replace on column
Some checks failed
CI / ruff (push) Successful in 10s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has started running
LoyaltyCard.card_number is a SQLAlchemy column, not a string —
cannot call .replace() on it. Use func.replace() for the SQL query.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 22:12:49 +01:00
1194731f33 fix: card lookup 422 caused by route ordering conflict
Some checks failed
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled
CI / ruff (push) Successful in 11s
Move /cards/lookup (GET and POST) before /cards/{card_id} so FastAPI
matches the literal path before the parameterized one. Previously,
"lookup" was parsed as card_id (int), causing a 422 validation error.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 22:10:10 +01:00
12c1c3c511 fix: loyalty sidebar menu label and active state highlighting
Some checks failed
CI / ruff (push) Successful in 10s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has started running
- Rename menu item IDs to match URL last segments (terminal, cards,
  stats) so the sidebar active state comparison works correctly
- Change "Dashboard" label to "Terminal" for the loyalty terminal page
- Point menu route directly to /loyalty/terminal (skip redirect)
- Add "terminal" translation key in all locale files (en, de, fr, lb)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 22:04:16 +01:00
81cf84ed28 fix: correct billing feature-store API paths and loyalty config
Some checks failed
CI / ruff (push) Successful in 9s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled
Fix feature-store.js calling /store/features/available instead of
/store/billing/features/available (missing module prefix caused 404).
Also handle platform-prefixed URLs in getStoreCode().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 22:01:03 +01:00
a6e6d9be8e refactor: rename shopLayoutData to storefrontLayoutData
Some checks failed
CI / ruff (push) Successful in 11s
CI / pytest (push) Failing after 46m49s
CI / validate (push) Successful in 23s
CI / dependency-scanning (push) Successful in 30s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
Align Alpine.js base component naming with storefront terminology.
Updated across all storefront JS, templates, and documentation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 19:06:45 +01:00
ec888f2e94 fix: add card detail and store transactions endpoints for loyalty terminal
Some checks failed
CI / ruff (push) Successful in 10s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled
- Fix GET /cards/{card_id} 500 error (program_type → loyalty_type)
- Add GET /transactions endpoint for store-wide recent transactions
- Add get_store_transactions service method (merchant-scoped, store-filterable)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 19:01:48 +01:00
53dfe018c2 fix: loyalty storefront and store card detail — enrollment, context, and Alpine.js
Some checks failed
CI / ruff (push) Successful in 10s
CI / pytest (push) Failing after 46m41s
CI / validate (push) Successful in 23s
CI / dependency-scanning (push) Successful in 30s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
- Fix storefront enabled_modules always empty (page_context overwrote computed
  set with empty default via extra_context)
- Fix storefront loyalty JS using store's data() instead of shopLayoutData()
- Remove defer from storefront loyalty scripts to prevent Alpine race condition
- Fix enrollment field name mismatch (customer_email → email) in both store
  and storefront JS
- Add self-enrollment customer creation (resolve_customer_id with
  create_if_missing) including hashed_password and customer_number
- Fix card list showing "Unknown" — add customer_name/email to CardResponse
- Add GET /cards/{card_id} detail endpoint for store card detail page
- Fix enroll-success.html using data() instead of shopLayoutData()
- Fix enrollment redirect reading response.card_number instead of
  response.card.card_number

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 14:28:37 +01:00
3de69e55a1 fix: add GET /cards/lookup endpoint for loyalty terminal customer search
Some checks failed
CI / ruff (push) Successful in 11s
CI / pytest (push) Failing after 47m33s
CI / validate (push) Successful in 24s
CI / dependency-scanning (push) Successful in 29s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
The terminal JS uses GET with a free-text ?q= parameter, but only a POST
endpoint existed with typed params (card_id, qr_code, card_number).

- Add search_card_for_store service method (tries card number then email)
- Add GET /cards/lookup route using the service method
- Extract _build_card_lookup_response helper to DRY up POST and GET endpoints

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 13:55:11 +01:00
cfce6c0ca4 fix: loyalty module end-to-end — merchant route, store menus, sidebar, API error handling
Some checks failed
CI / ruff (push) Successful in 10s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled
- Add merchant loyalty overview route and template (was 404)
- Fix store loyalty route paths to match menu URLs (/{store_code}/loyalty/...)
- Add loyalty rewards card to storefront account dashboard
- Fix merchant overview to resolve merchant via get_merchant_for_current_user_page
- Fix store login to use store's primary platform for JWT token (interim fix)
- Fix apiClient to attach status/errorCode to thrown errors (fixes error.status
  checks in 12+ JS files — loyalty settings, terminal, email templates, etc.)
- Hide "Add Product" sidebar button when catalog module is not enabled
- Add proposal doc for proper platform detection in store login flow

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 13:52:11 +01:00
2833ff1476 fix(billing): use tier_id instead of tier_code for feature limit endpoints
Some checks failed
CI / ruff (push) Successful in 10s
CI / validate (push) Has been cancelled
CI / dependency-scanning (push) Has been cancelled
CI / docs (push) Has been cancelled
CI / deploy (push) Has been cancelled
CI / pytest (push) Has been cancelled
Tier codes are not unique across platforms (e.g., "essential" exists for
OMS, marketplace, and loyalty). Using tier_code caused feature limits to
be saved to the wrong tier. Switched to tier_id (unique PK) in routes,
service, and frontend JS. Added comprehensive unit and integration tests
including cross-platform isolation regression tests.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 13:06:18 +01:00
f47c680cb8 fix: storefront login 403, cookie path, double-storefront URLs, and auth redirects
Some checks failed
CI / ruff (push) Successful in 9s
CI / pytest (push) Failing after 46m52s
CI / validate (push) Successful in 23s
CI / dependency-scanning (push) Successful in 30s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
- Extract store/platform context from Referer header for storefront API requests
  (StoreContextMiddleware and PlatformContextMiddleware) so login POST works in
  dev mode where API paths lack /platforms/{code}/ prefix
- Set customer token cookie path to "/" for cross-route compatibility
- Fix double storefront in URLs: replace {{ base_url }}storefront/ with {{ base_url }}
  across all 24 storefront templates
- Fix auth error redirect to include platform prefix and use store_code
- Update seed script to output correct storefront login URLs
- Add 20 new unit tests covering all fixes; fix 9 pre-existing test failures

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 12:29:52 +01:00
32e4aa6564 feat: wire Google Wallet into loyalty enrollment, stamps, and points flows
Connect the fully-implemented Google Wallet service to the loyalty module:
- Create wallet class/object on customer enrollment
- Sync wallet passes on stamp and points operations
- Expose wallet URLs in storefront API responses
- Add conditional "Add to Google Wallet" buttons on dashboard and enroll-success pages
- Use platform-wide env var config (not per-merchant DB column)
- Add Google service account patterns to .gitignore
- Add LOYALTY_GOOGLE_* fields to app Settings
- Update deployment docs and add local testing guide

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 10:38:46 +01:00
6c78827c7f feat: add language switching to admin and merchant frontends
Some checks failed
CI / ruff (push) Successful in 10s
CI / pytest (push) Failing after 46m27s
CI / validate (push) Successful in 23s
CI / dependency-scanning (push) Successful in 29s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
- Add cookie to ADMIN resolution chain (cookie → user_pref → "en")
- Add explicit MERCHANT resolution (cookie → user_pref → "fr")
- Add language selector dropdown to admin and merchant headers
- Add languageSelector() function to merchant init-alpine.js
- Add flag-icons CSS and i18n.js setup to merchant base template
- Add compact flag-based language selector to both login pages
- Make lang attribute dynamic on all base and login templates
- Pass current_language to login route template context
- Update architecture doc with ADMIN/MERCHANT resolution priorities

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 10:26:57 +01:00
cd935988c4 fix: store login crash and dashboard misrouted as storefront
Some checks failed
CI / ruff (push) Successful in 10s
CI / pytest (push) Failing after 44m20s
CI / validate (push) Successful in 22s
CI / dependency-scanning (push) Successful in 27s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped
- Seed default RBAC roles per store and assign role_id to StoreUser
  records (was never implemented after RBAC Phase 1 cleanup)
- Handle nullable role in auth_service find_user_store and
  get_user_store_role to prevent NoneType crash on login
- Use platform_clean_path instead of clean_path in FrontendTypeMiddleware
  so /store/X/dashboard is detected as STORE, not STOREFRONT

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 01:19:22 +01:00
32acc76b49 feat: platform-aware storefront routing and billing improvements
Overhaul storefront URL routing to be platform-aware:
- Dev: /platforms/{code}/storefront/{store_code}/
- Prod: subdomain.platform.lu/ (internally rewritten to /storefront/)
- Add subdomain detection in PlatformContextMiddleware
- Add /storefront/ path rewrite for prod mode (subdomain/custom domain)
- Remove all silent platform fallbacks (platform_id=1)
- Add require_platform dependency for clean endpoint validation
- Update route registration, templates, module definitions, base_url calc
- Update StoreContextMiddleware for /storefront/ path detection
- Remove /stores/ from FrontendDetector STOREFRONT_PATH_PREFIXES

Billing service improvements:
- Add store_platform_sync_service to keep store_platforms in sync
- Make tier lookups platform-aware across billing services
- Add tiers for all platforms in seed data
- Add demo subscriptions to seed

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 23:42:41 +01:00
2fc157d7b2 fix: store menu 404, logger crash, platform detection, and sidebar UX
All checks were successful
CI / ruff (push) Successful in 12s
CI / pytest (push) Successful in 46m12s
CI / validate (push) Successful in 24s
CI / dependency-scanning (push) Successful in 29s
CI / docs (push) Successful in 38s
CI / deploy (push) Successful in 50s
- Fix store menu API URL (/store/menu/render/store, not /store/core/...)
- Fix storeLog/merchantLog fallback to console object instead of console.log
- Embed platform_id/platform_code in store JWT from URL context at login
- Use token_platform_id in store menu endpoint with DB fallback for old tokens
- Add "Menu unavailable" warning in sidebar fallback for all three frontends
- Standardize admin section default to all-open (consistent with store/merchant)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 13:53:31 +01:00
506171503d feat: complete dynamic menu system across all frontends
All checks were successful
CI / ruff (push) Successful in 11s
CI / pytest (push) Successful in 44m40s
CI / validate (push) Successful in 22s
CI / dependency-scanning (push) Successful in 28s
CI / docs (push) Successful in 39s
CI / deploy (push) Successful in 49s
- Add "Merchant Frontend" tab to admin menu-config page
- Merchant render endpoint now respects AdminMenuConfig visibility
  via get_merchant_primary_platform_id() platform resolution
- New store menu render endpoint (GET /store/core/menu/render/store)
  with platform-scoped visibility and store_code interpolation
- Store sidebar migrated from hardcoded Jinja2 macros to dynamic
  Alpine.js x-for rendering with loading skeleton and fallback
- Store init-alpine.js: add loadMenuConfig(), expandSectionForCurrentPage()
- Include store page route fixes, login template updates, and tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 02:14:42 +01:00