feat: add SQL query tool, platform debug, loyalty settings, and multi-module improvements
Some checks failed
CI / ruff (push) Successful in 14s
CI / pytest (push) Failing after 50m12s
CI / validate (push) Successful in 25s
CI / dependency-scanning (push) Successful in 32s
CI / docs (push) Has been skipped
CI / deploy (push) Has been skipped

- Add admin SQL query tool with saved queries, schema explorer presets,
  and collapsible category sections (dev_tools module)
- Add platform debug tool for admin diagnostics
- Add loyalty settings page with owner-only access control
- Fix loyalty settings owner check (use currentUser instead of window.__userData)
- Replace HTTPException with AuthorizationException in loyalty routes
- Expand loyalty module with PIN service, Apple Wallet, program management
- Improve store login with platform detection and multi-platform support
- Update billing feature gates and subscription services
- Add store platform sync improvements and remove is_primary column
- Add unit tests for loyalty (PIN, points, stamps, program services)
- Update i18n translations across dev_tools locales

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-10 20:08:07 +01:00
parent a77a8a3a98
commit 319900623a
77 changed files with 5341 additions and 401 deletions

View File

@@ -941,7 +941,6 @@ def create_demo_stores(
store_id=store.id,
platform_id=platform_id,
is_active=True,
is_primary=(i == 0),
custom_subdomain=custom_sub,
)
db.add(sp)
@@ -1280,10 +1279,12 @@ def create_demo_store_content_pages(db: Session, stores: list[Store]) -> int:
store_primary_platform: dict[int, int] = {}
sp_rows = db.execute(
select(StorePlatform.store_id, StorePlatform.platform_id)
.where(StorePlatform.is_primary == True) # noqa: E712
.where(StorePlatform.is_active == True) # noqa: E712
.order_by(StorePlatform.joined_at)
).all()
for store_id, platform_id in sp_rows:
store_primary_platform[store_id] = platform_id
if store_id not in store_primary_platform:
store_primary_platform[store_id] = platform_id
# Fallback: OMS platform ID
oms_platform = db.execute(
@@ -1544,7 +1545,7 @@ def print_summary(db: Session):
select(StorePlatform.store_id, Platform.code).join(
Platform, Platform.id == StorePlatform.platform_id
).where(StorePlatform.is_active == True).order_by( # noqa: E712
StorePlatform.store_id, StorePlatform.is_primary.desc()
StorePlatform.store_id, StorePlatform.joined_at
)
).all()
store_platform_map: dict[int, list[str]] = {}
@@ -1563,7 +1564,7 @@ def print_summary(db: Session):
StorePlatform.custom_subdomain,
).join(Platform, Platform.id == StorePlatform.platform_id)
.where(StorePlatform.is_active == True) # noqa: E712
.order_by(StorePlatform.store_id, StorePlatform.is_primary.desc())
.order_by(StorePlatform.store_id, StorePlatform.joined_at)
).all()
for store_id, pcode, pdomain, custom_sub in sp_detail_rows:
store_platform_details.setdefault(store_id, []).append({

View File

@@ -74,7 +74,7 @@ def get_store_platform_map(db):
"FROM store_platforms sp "
"JOIN platforms p ON p.id = sp.platform_id "
"WHERE sp.is_active = true "
"ORDER BY sp.store_id, sp.is_primary DESC"
"ORDER BY sp.store_id, sp.joined_at"
)
).fetchall()