feat: add configurable currency locale and fix vendor JS init
Currency Locale Configuration: - Add platform-level storefront settings (locale, currency) - Create PlatformSettingsService with resolution chain: vendor → AdminSetting → environment → hardcoded fallback - Add storefront_locale nullable field to Vendor model - Update shop routes to resolve and pass locale to templates - Add window.SHOP_CONFIG for frontend JavaScript access - Centralize formatPrice() in shop-layout.js using SHOP_CONFIG - Remove local formatPrice functions from shop templates Vendor JS Bug Fix: - Fix vendorCode being null on all vendor pages - Root cause: page components overriding init() without calling parent - Add parent init call to 14 vendor JS files - Add JS-013 architecture rule to prevent future regressions - Validator now checks vendor JS files for parent init pattern Files changed: - New: app/services/platform_settings_service.py - New: alembic/versions/s7a8b9c0d1e2_add_storefront_locale_to_vendors.py - Modified: 14 vendor JS files, shop templates, validation scripts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2862,6 +2862,9 @@ class ArchitectureValidator:
|
||||
# JS-012: Check for double /api/v1 prefix in API calls
|
||||
self._check_api_prefix_usage(file_path, content, lines)
|
||||
|
||||
# JS-013: Check that components overriding init() call parent init
|
||||
self._check_parent_init_call(file_path, content, lines)
|
||||
|
||||
def _check_platform_settings_usage(
|
||||
self, file_path: Path, content: str, lines: list[str]
|
||||
):
|
||||
@@ -2995,6 +2998,59 @@ class ArchitectureValidator:
|
||||
suggestion="Change '/api/v1/admin/...' to '/admin/...'",
|
||||
)
|
||||
|
||||
def _check_parent_init_call(
|
||||
self, file_path: Path, content: str, lines: list[str]
|
||||
):
|
||||
"""
|
||||
JS-013: Check that vendor components overriding init() call parent init.
|
||||
|
||||
When a component uses ...data() to inherit base layout functionality AND
|
||||
defines its own init() method, it MUST call the parent init first to set
|
||||
critical properties like vendorCode.
|
||||
|
||||
Note: This only applies to vendor JS files because the vendor data() has
|
||||
an init() method that extracts vendorCode from URL. Admin data() does not.
|
||||
"""
|
||||
# Only check vendor JS files (admin data() doesn't have init())
|
||||
if "/vendor/js/" not in str(file_path):
|
||||
return
|
||||
|
||||
# Skip files that shouldn't have this pattern
|
||||
excluded_files = ["init-alpine.js", "login.js", "onboarding.js"]
|
||||
if file_path.name in excluded_files:
|
||||
return
|
||||
|
||||
# Check if file uses ...data() spread operator
|
||||
uses_data_spread = "...data()" in content
|
||||
|
||||
# Check if file defines its own async init()
|
||||
has_own_init = re.search(r"async\s+init\s*\(\s*\)", content)
|
||||
|
||||
# If both conditions are true, check for parent init call
|
||||
if uses_data_spread and has_own_init:
|
||||
# Check for parent init call patterns
|
||||
calls_parent_init = (
|
||||
"data().init" in content
|
||||
or "parentInit" in content
|
||||
or "parent.init" in content
|
||||
)
|
||||
|
||||
if not calls_parent_init:
|
||||
# Find the line with async init() to report
|
||||
for i, line in enumerate(lines, 1):
|
||||
if re.search(r"async\s+init\s*\(\s*\)", line):
|
||||
self._add_violation(
|
||||
rule_id="JS-013",
|
||||
rule_name="Components overriding init() must call parent init",
|
||||
severity=Severity.ERROR,
|
||||
file_path=file_path,
|
||||
line_number=i,
|
||||
message="Component with ...data() must call parent init() to set vendorCode",
|
||||
context=line.strip()[:80],
|
||||
suggestion="Add: const parentInit = data().init; if (parentInit) { await parentInit.call(this); }",
|
||||
)
|
||||
break
|
||||
|
||||
def _validate_templates(self, target_path: Path):
|
||||
"""Validate template patterns"""
|
||||
print("📄 Validating templates...")
|
||||
|
||||
Reference in New Issue
Block a user