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>
This commit is contained in:
2026-02-24 14:28:37 +01:00
parent 3de69e55a1
commit 53dfe018c2
13 changed files with 148 additions and 19 deletions

View File

@@ -24,6 +24,16 @@ class CardEnrollRequest(BaseModel):
None,
description="Customer email (for public enrollment without customer_id)",
)
# Self-enrollment fields (used to create customer if not found)
customer_name: str | None = Field(
None, description="Full name for self-enrollment"
)
customer_phone: str | None = Field(
None, description="Phone number for self-enrollment"
)
customer_birthday: str | None = Field(
None, description="Birthday (YYYY-MM-DD) for self-enrollment"
)
class CardResponse(BaseModel):
@@ -38,6 +48,10 @@ class CardResponse(BaseModel):
program_id: int
enrolled_at_store_id: int | None = None
# Customer info (for list views)
customer_name: str | None = None
customer_email: str | None = None
# Stamps
stamp_count: int
stamps_target: int # From program