- Add office-building, lock-open, switch-horizontal, x icons
- Remove owner_user_id from vendor creation in seed script
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add "View Parent Company" button in More Actions section
- Show parent company name in info text
- Add deleteVendor function to vendor-edit.js
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add company-detail.html with status cards, info sections, vendors list
- Add company-edit.html with transfer ownership modal
- Add company-detail.js and company-edit.js
- Add user search autocomplete for transfer ownership
- Add inline validation errors for transfer form
- Add View button to companies list page
- Add route for /admin/companies/{id} detail page
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add transfer-ownership endpoint to companies API
- Add user search endpoint for autocomplete (/admin/users/search)
- Update company detail endpoint to include owner info and vendors list
- Update vendor endpoints to use company relationship for ownership
- Update deps.py vendor access check to use company.owner_user_id
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update VendorResponse to use company_id instead of owner fields
- Add VendorDetailResponse with company info (name, email, phone, website)
- Update VendorCreate to require company_id
- Add owner_email, owner_username, vendors list to CompanyDetailResponse
- Remove obsolete VendorTransferOwnership schemas
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Remove owner_user_id column and owner relationship from Vendor model
- Update User model ownership checks to use company relationship
- Add migration to drop owner_user_id column from vendors table
Ownership is now determined solely via vendor.company.owner_user_id
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
SQLAlchemy Error Fix:
- Add .unique() when using joinedload(Company.vendors)
- When eagerly loading collection relationships with joinedload, SQLAlchemy can return duplicate rows
- The unique() method deduplicates results and is required for joined collection loads
Error was:
InvalidRequestError: The unique() method must be invoked on this Result, as it contains results that include joined eager loads against collections
This is a standard SQLAlchemy pattern for handling one-to-many relationships with eager loading.
- Document 221 remaining violations (down from 239)
- Explain intentional transaction control at API layer
- Categorize violations by priority and impact
- Create refactoring roadmap for legacy code
- Establish architecture validation philosophy
Categories:
1. Transaction control (intentional, documented)
2. Raw dict responses (legacy, low priority)
3. Service patterns (legacy, medium priority)
4. Simple queries in endpoints (case-by-case)
5. Template inline styles (accepted)
Result: Codebase in good architectural health with clear improvement path
JavaScript Logging (18 violations fixed):
- Replace console.log with centralized logger in marketplace.js
- Replace console.log with centralized logger in vendor-themes.js
- Replace console.log with centralized logger in settings.js
- Replace console.log with centralized logger in imports.js
API Layer Transaction Control (documented):
- Add comments to db.commit() calls in companies.py
- Document that commits at API level are intentional for transaction boundary control
- Service layer handles business logic, API layer controls transactions
Remaining Violations (221):
- API-002: Database commits in endpoints (intentional for transaction control)
- API-001: Raw dict responses (legacy code, will refactor incrementally)
- Service layer patterns (legacy code, will refactor incrementally)
Architecture Decision:
Following standard pattern where:
- Service Layer: Contains business logic
- API Layer: Controls transaction boundaries (commit/rollback)
This is a common and acceptable pattern in FastAPI applications.
- Create comprehensive seed scripts audit document
- Inventory of all seed/create scripts
- Analysis of current vs intended workflow
- Identification of duplicates and orphaned scripts
- Refactoring recommendations
- Create Makefile refactoring completion document
- Summary of architecture decisions
- Before/after comparison
- Updated workflows for production and development
- Script classification (production, demo, utility, test)
- New developer onboarding workflow
- Production deployment workflow
Documentation provides clear guidance on:
- Which scripts to run in production vs development
- How init-prod differs from seed-demo
- When to use utility commands
- Proper setup workflow for new developers
Seed Script Updates:
- Add create_demo_companies() function to seed 3 demo companies with owners
- Update create_demo_vendors() to link vendors to companies (not create owners)
- Fix VendorTheme to use JSON colors format (not individual columns)
- Fix VendorDomain to use 'domain' field (not 'domain_name')
- Update seed summary to show company information
- Update credentials output to show company owners instead of vendor owners
Makefile Refactoring:
- Separate production initialization from demo data seeding
- Update init-prod to run 4 steps:
1. Create admin user + alerts (init_production.py)
2. Initialize log settings (init_log_settings.py)
3. Create CMS defaults (create_default_content_pages.py)
4. Create platform pages (create_platform_pages.py)
- Update db-setup workflow: migrate-up + init-prod + seed-demo
- Update db-reset workflow: migrate-down + migrate-up + init-prod + seed-demo-reset
- Add utility commands: create-cms-defaults, create-platform-pages, init-logging
- Enhance help documentation with clear production vs demo distinction
Architecture:
- init-prod: Production-safe platform initialization (run in prod + dev)
- seed-demo: Demo data only (NEVER run in production)
- Clear separation of concerns for production deployment
- Create companies list page with stats (total, verified, active, vendor count)
- Add company creation form with owner account generation
- Implement companies.js with full CRUD operations (list, create, edit, delete)
- Add Companies menu item to admin sidebar (desktop + mobile)
- Create company admin page routes (/admin/companies, /admin/companies/create)
- Register companies API router in admin __init__.py
Features:
- List all companies with pagination
- Create company with automatic owner user creation
- Display temporary password for new owner accounts
- Edit company information
- Delete company (only if no vendors)
- Toggle active/verified status
- Show vendor count per company
UI Components:
- Stats cards (total companies, verified, active, total vendors)
- Company table with status badges
- Create form with validation
- Success/error messaging
- Responsive design with dark mode support
- Add database migration to make vendor.owner_user_id nullable
- Update Vendor model to support company-based ownership (DEPRECATED vendor.owner_user_id)
- Implement company_service with singleton pattern (consistent with vendor_service)
- Create Company model with proper relationships to vendors and users
- Add company exception classes for proper error handling
- Refactor companies API to use singleton service pattern
Architecture Change:
- OLD: Each vendor has its own owner (vendor.owner_user_id)
- NEW: Vendors belong to a company, company has one owner (company.owner_user_id)
- This allows one company owner to manage multiple vendor brands
Technical Details:
- Company service uses singleton pattern (not factory)
- Company service accepts db: Session as parameter (follows SVC-003)
- Uses AuthManager for password hashing (consistent with admin_service)
- Added _generate_temp_password() helper method
Problem:
- Accessing /admin/code-quality/violations/{id} returned 500 error
- TemplateNotFound: 'admin/code-quality-violation-detail.html'
- Route existed but template file was missing
Solution:
Created complete violation detail template with:
Features:
- Displays violation details (severity, status, rule, file, line)
- Shows code context and suggestions
- Status management (open, assigned, resolved, ignored)
- Assignment to users
- Comment system for collaboration
- Alpine.js component for API integration
- Loading and error states
- Proper dark mode support
Template Structure:
- Extends admin/base.html
- Uses codeQualityViolationDetail(violationId) Alpine component
- Loads violation data via API on init
- Interactive status updates and comments
- Breadcrumb navigation back to violations list
API Endpoints Used:
- GET /api/v1/admin/code-quality/violations/{id}
- PATCH /api/v1/admin/code-quality/violations/{id}/status
- PATCH /api/v1/admin/code-quality/violations/{id}/assign
- POST /api/v1/admin/code-quality/violations/{id}/comments
Now violation detail page loads successfully.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Problem:
- GET /api/v1/admin/code-quality/stats returned 500 error
- Pydantic validation error: "last_scan Field required"
- When no scan data exists, service returned dict without last_scan field
- DashboardStatsResponse model required last_scan field
Solution:
1. Added last_scan: None to empty state return dictionary
2. Made last_scan field explicitly optional with default value (= None)
3. Ensures field is always present in response
Changes:
- app/services/code_quality_service.py: Added "last_scan": None
- app/api/v1/admin/code_quality.py: Changed to last_scan: str | None = None
This fixes the 500 error when accessing /admin/code-quality page
with no architecture scan data in the database.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Problem:
- Ruff removed 'from app.core.database import Base' from models/database/base.py
- Import appeared "unused" (F401) but was actually a critical re-export
- Caused ImportError: cannot import name 'Base' at runtime
- Re-export pattern: import in one file to export from package
Solution:
1. Added F401 ignore for models/database/base.py in pyproject.toml
2. Created scripts/verify_critical_imports.py verification script
3. Integrated verification into make check and CI pipeline
4. Updated documentation with explanation
New Verification Script:
- Checks all critical re-export imports exist
- Detects import variations (parentheses, 'as' clauses)
- Handles SQLAlchemy declarative_base alternatives
- Runs as part of make check automatically
Protected Files:
- models/database/base.py - Re-exports Base for all models
- models/__init__.py - Exports Base for Alembic
- models/database/__init__.py - Exports Base from package
- All __init__.py files (already protected)
Makefile Changes:
- make verify-imports - Run import verification
- make check - Now includes verify-imports
- make ci - Includes verify-imports in pipeline
Documentation Updated:
- Code quality guide explains re-export protection
- Pre-commit workflow includes verification
- Examples of why re-exports matter
This prevents future issues where linters remove seemingly
"unused" imports that are actually critical for application structure.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed broken conditional logic in JavaScript validation that was causing
false positives on every single line of JS files.
Problem:
- Malformed ternary expression with 'if' inside condition
- 'else True' caused every line WITHOUT 'window.apiClient' to trigger
- Result: 3,144 violations (mostly false positives)
Solution:
- Simplified conditional to check if 'window.apiClient' exists first
- Then check if it's not in a comment
- Clearer, more maintainable logic
Results:
- Before: 3,144 total violations (3,000+ false JS-001 violations)
- After: 184 total violations (all legitimate)
- JS-001 violations: 0 (correct - no actual window.apiClient usage)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update .architecture-rules.yaml to ignore venv/.venv directories
- Improve _should_ignore_file() method to handle venv path exclusions
- Add explicit checks for .venv/ and venv/ in file paths
This prevents the architecture validator from scanning thousands of
files in virtual environment directories, reducing validation time
from scanning all dependency files to just project files.
Before: Scanned venv files (thousands of violations in dependencies)
After: Only scans project files (123 files checked)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add detailed Code Quality guide covering Ruff, mypy, and pytest
- Add Contributing Guide with workflow, standards, and best practices
- Update mkdocs.yml navigation to include new documentation
- Successfully build documentation without errors
New Documentation:
- docs/development/code-quality.md - Complete guide to code quality tools
- docs/development/contributing.md - Contributing guidelines and workflow
- Added Code Quality Dashboard implementation to navigation
Documentation includes:
- Ruff usage and configuration
- mypy type checking
- pytest testing guidelines
- Makefile command reference
- Pre-commit workflow
- IDE integration instructions
- Migration guide from old tools
- Best practices and common issues
Documentation builds cleanly with mkdocs build.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Replace black, isort, and flake8 with Ruff (all-in-one linter and formatter)
- Add comprehensive pyproject.toml configuration
- Simplify Makefile code quality targets
- Configure exclusions for venv/.venv in pyproject.toml
- Auto-fix 1,359 linting issues across codebase
Benefits:
- Much faster builds (Ruff is written in Rust)
- Single tool replaces multiple tools
- More comprehensive rule set (UP, B, C4, SIM, PIE, RET, Q)
- All configuration centralized in pyproject.toml
- Better import sorting and formatting consistency
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Standardize quote style (single to double quotes)
- Reorder and group imports alphabetically
- Fix line breaks and indentation for consistency
- Apply PEP 8 formatting standards
Also updated Makefile to exclude both venv and .venv from code quality checks.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fix multiple JavaScript errors on code quality dashboard pages:
Issues Fixed:
1. ReferenceError: getAccessToken is not defined
- Changed to use apiClient.get() and apiClient.post() from api-client.js
- Properly uses existing authentication infrastructure
2. ReferenceError: dark/isSideMenuOpen/currentPage is not defined
- Extended base data() function using spread operator
- Inherits all base Alpine.js state from init-alpine.js
3. RegExp validation error
- Not directly addressed but likely resolved by proper Alpine initialization
Changes:
- static/admin/js/code-quality-dashboard.js:
* Spread ...data() to inherit base Alpine.js state
* Set currentPage: 'code-quality' for navigation highlighting
* Use apiClient.get('/admin/code-quality/stats') for API calls
* Use apiClient.post('/admin/code-quality/scan') for scan triggers
* Simplified error handling with apiClient error messages
- static/admin/js/code-quality-violations.js:
* Spread ...data() to inherit base Alpine.js state
* Set currentPage: 'code-quality' for navigation highlighting
* Use apiClient.get('/admin/code-quality/violations', params) for API calls
* Simplified query parameter building using object instead of URLSearchParams
Testing:
- Dashboard should now load without JavaScript errors
- API calls should work with proper authentication
- Dark mode toggle and sidebar menu should function correctly
- Navigation highlighting should work properly
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement comprehensive code quality dashboard (Phase 2-4) to track and manage
architecture violations found by the validation script.
Backend Implementation:
- Add JSON output support to validate_architecture.py script
- Create CodeQualityService with scan management, violation tracking, and statistics
- Implement REST API endpoints for code quality management:
* POST /admin/code-quality/scan - trigger new architecture scan
* GET /admin/code-quality/scans - list scan history
* GET /admin/code-quality/violations - list violations with filtering/pagination
* GET /admin/code-quality/violations/{id} - get violation details
* POST /admin/code-quality/violations/{id}/assign - assign to developer
* POST /admin/code-quality/violations/{id}/resolve - mark as resolved
* POST /admin/code-quality/violations/{id}/ignore - mark as ignored
* POST /admin/code-quality/violations/{id}/comments - add comments
* GET /admin/code-quality/stats - dashboard statistics
- Fix architecture_scan model imports to use app.core.database
Frontend Implementation:
- Create code quality dashboard page (code-quality-dashboard.html)
* Summary cards for total violations, errors, warnings, health score
* Status breakdown (open, assigned, resolved, ignored)
* Trend visualization for last 7 scans
* Top violating files list
* Violations by rule and module
* Quick action links
- Create violations list page (code-quality-violations.html)
* Filterable table by severity, status, rule ID, file path
* Pagination support
* Violation detail view links
- Add Alpine.js components (code-quality-dashboard.js, code-quality-violations.js)
* Dashboard state management and scan triggering
* Violations list with filtering and pagination
* API integration with authentication
- Add "Code Quality" navigation link in admin sidebar (Developer Tools section)
Routes:
- GET /admin/code-quality - dashboard page
- GET /admin/code-quality/violations - violations list
- GET /admin/code-quality/violations/{id} - violation details
Features:
- Real-time scan execution from UI
- Technical debt score calculation (0-100 scale)
- Violation workflow: open → assigned → resolved/ignored
- Trend tracking across multiple scans
- File and module-level insights
- Assignment system with priorities and due dates
- Collaborative comments on violations
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Created detailed implementation guide for remaining phases (2-4):
Phase 2 - Service Layer:
- CodeQualityService class specification
- Scan management methods
- Violation CRUD operations
- Statistics and metrics calculation
- Integration with validator script
Phase 3 - API Endpoints:
- REST API specification for code quality
- Pydantic request/response models
- Endpoint documentation (/admin/code-quality/*)
Phase 4 - Frontend:
- Dashboard layout and components
- Alpine.js component structure
- Violations table with filtering
- Charts and visualizations
- Navigation integration
Implementation Details:
- Database schema documentation
- JSON output format for validator
- Testing checklist
- Priority order for next session
- Time estimates (3-4 hours)
Additional Features:
- Background job support considerations
- Email notifications
- GitHub/GitLab PR integration
- Historical trend analysis
This document serves as a complete blueprint for completing
the code quality dashboard in the next development session.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented database models and migration for tracking architecture violations
in the admin dashboard. This is the foundation for the code quality UI.
Database Models Added (app/models/architecture_scan.py):
- ArchitectureScan: Tracks validator runs with statistics
- ArchitectureViolation: Individual violations with status tracking
- ArchitectureRule: Rule configuration with enable/disable support
- ViolationAssignment: Assign violations to developers
- ViolationComment: Collaboration on violations
Schema Features:
- Full violation history tracking
- Status workflow (open → assigned → resolved/ignored/technical_debt)
- Assignment and due date tracking
- Comments for collaboration
- Rule management (enable/disable, severity override)
- Scan statistics (errors, warnings, duration)
Migration:
- Created 5 tables with proper indexes and foreign keys
- SQLite-compatible datetime defaults
- Supports relationships between scans, violations, users
Next Steps (Remaining Phases):
- Phase 2: Service layer (code_quality_service.py)
- Phase 3: API endpoints (/admin/code-quality/*)
- Phase 4: Frontend dashboard and UI
Benefits:
- Track technical debt over time
- Assign violations to developers
- Prioritize fixes by severity
- Measure code quality improvements
- Collaborative violation resolution
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented automated architecture validation to enforce design decisions:
Architecture Validation System:
- Created .architecture-rules.yaml with comprehensive rule definitions
- Implemented validate_architecture.py script with AST-based validation
- Added pre-commit hook configuration for automatic validation
- Comprehensive documentation in docs/architecture/architecture-patterns.md
Key Design Rules Enforced:
- API-001 to API-004: API endpoint patterns (Pydantic models, no business logic, exception handling, auth)
- SVC-001 to SVC-004: Service layer patterns (domain exceptions, db session params, no HTTP concerns)
- MDL-001 to MDL-002: Model separation (SQLAlchemy vs Pydantic)
- EXC-001 to EXC-002: Exception handling (custom exceptions, no bare except)
- JS-001 to JS-003: JavaScript patterns (apiClient, logger, Alpine components)
- TPL-001: Template patterns (extend base.html)
Features:
- Validates separation of concerns (routes vs services vs models)
- Enforces proper exception handling (domain exceptions in services, HTTP in routes)
- Checks database session patterns and Pydantic model usage
- JavaScript and template validation
- Detailed error reporting with suggestions
- Integration with pre-commit hooks and CI/CD
UI Fix:
- Fixed icon names in content-pages.html (pencil→edit, trash→delete)
Documentation:
- Added architecture patterns guide with examples
- Created scripts/README.md for validator usage
- Updated mkdocs.yml with architecture documentation
- Built and verified documentation successfully
Usage:
python scripts/validate_architecture.py # Validate all
python scripts/validate_architecture.py --verbose # With details
python scripts/validate_architecture.py --errors-only # Errors only
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add self-hosted Inter font files to ensure application works offline
and reduce dependency on external CDN (Google Fonts).
Problem:
- Google Fonts (fonts.googleapis.com) fails when no internet connection
- Application shows NS_ERROR_UNKNOWN_HOST errors
- Font rendering falls back to system fonts, breaking design consistency
Solution:
- Download Inter font files (weights 400, 500, 600, 700, 800) from Google Fonts
- Host locally in static/shared/fonts/inter/
- Create inter.css with @font-face declarations
- Update all templates to load local fonts FIRST, then Google Fonts as fallback
Files Added:
- static/shared/fonts/inter.css (font-face declarations)
- static/shared/fonts/inter/inter-400.ttf (318KB - Regular)
- static/shared/fonts/inter/inter-500.ttf (318KB - Medium)
- static/shared/fonts/inter/inter-600.ttf (319KB - Semi-bold)
- static/shared/fonts/inter/inter-700.ttf (319KB - Bold)
- static/shared/fonts/inter/inter-800.ttf (320KB - Extra-bold)
Templates Updated (7 files):
- app/templates/admin/base.html
- app/templates/admin/login.html
- app/templates/vendor/base.html
- app/templates/vendor/login.html
- app/templates/shop/account/login.html
- app/templates/shop/account/register.html
- app/templates/shop/account/forgot-password.html
Font Loading Strategy:
1. Load local fonts first (always available, fast)
2. Load Google Fonts second (better quality when online)
3. Browser uses first available source
Example change:
Before:
<link href="https://fonts.googleapis.com/css2?family=Inter..." />
After:
<link href="/static/shared/fonts/inter.css" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css2?family=Inter..." />
Benefits:
- ✅ Works offline without font loading errors
- ✅ Faster initial load (local fonts, no DNS lookup)
- ✅ Reduced external dependencies
- ✅ Consistent typography even when CDN is down
- ✅ Still uses Google Fonts when available (higher quality)
- ✅ Total size: ~1.6MB (reasonable for 5 font weights)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fix error page links not respecting vendor context in path-based routing
by aligning with the pattern used throughout the codebase.
Problem:
- Error pages showed links like /shop/ instead of /vendors/wizamart/shop/
- error_renderer.py was checking request.state.access_method (never set)
- This meant access_method was always None, so base_url defaulted to "/"
- Links ignored vendor context and broke multi-access routing
Root Cause:
- Inconsistent pattern: error_renderer.py used wrong attribute
- Rest of codebase (6 locations) correctly uses vendor_context.get('detection_method')
- No code ever sets request.state.access_method anywhere
Solution:
- Change from: access_method = getattr(request.state, "access_method", None)
- Change to: access_method = vendor_context.get('detection_method', 'unknown')
- Aligns with pattern used in:
* app/exceptions/handler.py:384 (login redirect)
* main.py:336 (root redirect)
* app/routes/shop_pages.py:85, 391 (shop pages)
* app/api/v1/shop/auth.py:159, 223 (auth endpoints)
Changes:
- Line 263-264: Get vendor_context first, then extract detection_method from it
- Line 266: Now correctly detects path-based access method
- base_url now properly set to /vendors/wizamart/ for path-based routing
Impact:
- ✅ Path-based routing: /vendors/wizamart/shop123 → links to /vendors/wizamart/shop/
- ✅ Direct shop access: /shop/test → links to /shop/ (unchanged)
- ✅ No breaking changes (access_method was never used before)
- ✅ Consistent with entire codebase pattern
Testing:
- curl http://localhost:8000/vendors/wizamart/shop123
Before: href="/shop/" (wrong)
After: href="/vendors/wizamart/shop/" (correct)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fix broken links in shop error pages that were not respecting the base_url
for multi-access routing (domain, subdomain, and path-based vendor access).
Problem:
- Links used `{{ base_url or '/' }}` pattern which incorrectly fell back to '/'
- This broke navigation when accessing via path-based routing (e.g., /vendor/vendor1/)
- Links like "Continue Shopping" and "View All Products" went to wrong URLs
Solution:
- Remove `or '/'` fallback since base_url is always provided by error_renderer.py
- Add proper path prefixes (shop/, shop/products, shop/account/login, etc.)
- Ensure all links use `{{ base_url }}shop/...` pattern
Files Updated (10 templates):
- base.html: Fixed default action buttons and contact links
- 404.html: Fixed "Continue Shopping" and "View All Products" links
- 401.html: Fixed login and register links to use shop/account/* paths
- 403.html: Fixed login and home links
- 400.html: Fixed home and contact links
- 422.html: Fixed home and contact links
- 429.html: Fixed home and contact links
- 500.html: Fixed home and contact links
- 502.html: Fixed home and contact links
- generic.html: Fixed home and contact links
Example fix:
Before: href="{{ base_url or '/' }}shop/products"
After: href="{{ base_url }}shop/products"
Result for path-based access (/vendor/vendor1/):
Before: /shop/products (wrong - ignores vendor context)
After: /vendor/vendor1/shop/products (correct)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implement secure customer authentication system with dedicated JWT tokens,
separate from admin/vendor authentication.
Backend Changes:
- Add customer JWT token support in deps.py
- New get_current_customer_from_cookie_or_header dependency
- Validates customer-specific tokens with type checking
- Returns Customer object instead of User for shop routes
- Extend AuthService with customer token support
- Add verify_password() method
- Add create_access_token_with_data() for custom token payloads
- Update CustomerService authentication
- Generate customer-specific JWT tokens with type="customer"
- Use vendor-scoped customer lookup
- Enhance exception handler
- Sanitize validation errors to prevent password leaks in logs
- Fix shop login redirect to support multi-access routing
- Improve vendor context detection from Referer header
- Consistent "path" detection method for cookie path logic
Schema Changes:
- Rename UserLogin.username to email_or_username for flexibility
- Update field validators accordingly
API Changes:
- Update admin/vendor auth endpoints to use email_or_username
- Customer auth already uses email field correctly
Route Changes:
- Update shop account routes to use Customer dependency
- Add /account redirect (without trailing slash)
- Change parameter names from current_user to current_customer
Frontend Changes:
- Update login forms to use email_or_username in API calls
- Change button text from "Log in" to "Sign in" for consistency
- Improve loading spinner layout with flexbox
Security Improvements:
- Customer tokens scoped to vendor_id
- Token type validation prevents cross-context token usage
- Password inputs redacted from validation error logs
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed two critical issues preventing cart from working:
1. Product Name Attribute Error:
- Product model doesn't have 'name' attribute directly
- Product name comes from marketplace_product.title relationship
- Updated all references in cart_service.py:
* get_cart() - product display in cart
* add_to_cart() - logging and exception messages
* update_cart_item() - exception messages
- Also updated image_url to use marketplace_product.image_link
2. Products Page Not Calling API:
- products.html had stub addToCart() with TODO comment
- Implemented actual API call:
* POST to /api/v1/shop/cart/{sessionId}/items
* Sends product_id and quantity
* Updates cartCount on success
* Shows error toast on failure
* Proper error handling with try/catch
Testing Results:
- API endpoint now works correctly (tested with curl)
- Cart items are properly saved to database
- Product names display correctly from marketplace_product relationship
- Frontend can successfully add items to cart
Related Models:
- Product has relationship to MarketplaceProduct
- Product.marketplace_product.title contains the product name
- Product.marketplace_product.image_link contains the image URL
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated API reference, error handling, and architecture docs to reflect
the new persistent cart system with database storage.
API Reference Updates (shop-api-reference.md):
- Updated last modified date to 2025-11-23
- Updated cart response schemas to match CartResponse/CartItemResponse models
- Added detailed schema tables for all cart endpoints
- Documented all cart exceptions with examples (CART_ITEM_NOT_FOUND, INSUFFICIENT_INVENTORY_FOR_CART, etc.)
- Added implementation notes about cart persistence and duplicate prevention
- Updated all endpoint documentation with proper request/response schemas
- Added CartOperationResponse and ClearCartResponse documentation
Error Handling Updates (error-handling.md):
- Added Shopping Cart Exceptions section with 6 cart-specific exceptions
- Added Product Exceptions section
- Added Inventory Exceptions section
- Updated error response format to show structured WizamartException format
- Added examples with error_code, message, status_code, and details fields
- Documented the difference between structured and generic error formats
Architecture Updates (overview.md):
- Added cart_items table to database schema diagram
- Documented session-based shopping cart in data model hierarchy
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Implemented a complete shopping cart system with database persistence,
replacing the previous stub implementation. The cart now properly stores
items across sessions and follows the project's architecture patterns.
Database Changes:
- Add cart_items table with vendor_id, session_id, product_id, quantity, price_at_add
- Create unique constraint to prevent duplicate items per session
- Add indexes for session lookups and old cart cleanup
- Run migration a2064e1dfcd4 to create cart_items table
New Models & Schemas:
- models/database/cart.py: CartItem SQLAlchemy model with relationships
- models/schema/cart.py: Pydantic schemas for requests/responses
* AddToCartRequest, UpdateCartItemRequest
* CartResponse, CartItemResponse, CartOperationResponse, ClearCartResponse
Exception Handling:
- app/exceptions/cart.py: Cart-specific exceptions following project patterns
* CartItemNotFoundException - item not found in cart
* InsufficientInventoryForCartException - not enough inventory for cart operation
* InvalidCartQuantityException - invalid quantity validation
* CartValidationException - general cart validation
* EmptyCartException - operations on empty cart
* ProductNotAvailableForCartException - product unavailable
- Updated app/exceptions/__init__.py to export cart exceptions
Service Layer:
- Implement cart_service.get_cart() - fetch cart from database with totals
- Implement cart_service.add_to_cart() - create or update cart items with inventory checks
- Implement cart_service.update_cart_item() - update quantity with validation
- Implement cart_service.remove_from_cart() - delete cart item
- Implement cart_service.clear_cart() - remove all items for session
- Replace generic exceptions with cart-specific ones
- Fix InsufficientInventoryException usage (was using wrong parameters)
API Layer:
- Update app/api/v1/shop/cart.py to use Pydantic schemas
- Add response_model declarations to all endpoints
- Add return type hints for type safety
- Convert service dict responses to Pydantic models
Features:
- Cart items persist in database across server restarts
- Inventory validation before adding/updating items
- Price captured at time of adding to cart
- Duplicate items update quantity instead of creating new entries
- Full CRUD operations with proper error handling
- Type-safe API with auto-generated OpenAPI documentation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added three new documentation pages to mkdocs.yml navigation:
- Features → Vendor Landing Pages (features/vendor-landing-pages.md)
- Frontend Development → Shop Frontend → Navigation Flow (frontend/shop/navigation-flow.md)
- Troubleshooting → Shop Frontend (troubleshooting/shop-frontend.md)
This fixes the MkDocs build warnings about orphaned pages not in navigation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated documentation to cover all work completed today:
## Database Setup (docs/getting-started/database-setup.md)
- Added data seeding section with all three scripts
- Documented inventory creation requirement
- Added complete setup workflow
- Included common issues and solutions
- Added database reset instructions
## New Troubleshooting Guide (docs/troubleshooting/shop-frontend.md)
Comprehensive troubleshooting for:
### Cart and Product Issues
- Products cannot be added to cart (inventory = 0)
- Cart is empty after adding products (session ID issue)
- Root causes and solutions with code examples
### Styling and Layout Issues
- Pages with no styling (not extending base template)
- Images not loading (placeholder SVG implementation)
- Detailed before/after examples
### Navigation and Routing Issues
- Product detail 404 (duplicate /shop prefix)
- Missing /shop/ in links
- Breadcrumb navigation patterns
### Landing Page Issues
- Vendor root 404 (no landing page)
- Breadcrumb home link configuration
- Auto-redirect behavior
### Alpine.js Issues
- Component data not available (parent init not called)
- Product ID undefined (window globals solution)
- Debugging tips and console commands
All issues encountered today are now documented with:
- Clear symptoms
- Root cause explanation
- How the system works
- Step-by-step solutions
- Code examples
- Verification steps
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Created script to populate inventory table for products that have 0 inventory.
Issue:
- Products had 0 available_inventory because inventory table was empty
- available_inventory is calculated from inventory_entries relationship
- Empty inventory table = 0 inventory for all products
- Add to cart fails when inventory is 0
Solution:
- Create inventory entries for all products
- Each product gets 100 units in 'Main Warehouse'
- Script can be run multiple times (only creates missing entries)
Usage:
python scripts/create_inventory.py
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added comprehensive console logging to track:
- Cart eligibility checks
- API request URL and payload
- Response status and data
- Error details
This will help identify why items aren't being added to cart.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Issue:
- sessionId was undefined when cart/product pages loaded
- Parent shopLayoutData init() was being overridden, not called
- Session ID setup in parent wasn't running
Solution:
- Store reference to baseData before spreading
- Explicitly call baseData.init() in child component init
- This ensures sessionId is initialized before cart/product logic runs
- Add session ID logging for debugging
Now the session ID is properly initialized and cart functionality works.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Issue:
- Cart was empty after adding products
- Product and cart pages reference this.sessionId but it wasn't defined
- Session ID was being created separately in each page component
Solution:
- Add sessionId property to shopLayoutData base component
- Add getOrCreateSessionId() method to manage session across all pages
- Initialize sessionId in init() so it's available to all child components
- Session ID stored in localStorage as 'cart_session_id'
Now the cart session is shared across all shop pages and cart items
persist correctly.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Issue:
- Cart page was standalone HTML without proper styling
- Referenced non-existent CSS files (/static/css/shared/base.css, /static/css/vendor/vendor.css)
- Missing header, footer, and navigation
- Not integrated with shop layout system
Changes:
- Extend shop/base.html for consistent styling and layout
- Remove hardcoded CSS references (now inherited from base)
- Add proper breadcrumbs with landing page navigation
- Integrate with shopLayoutData() for cart and toast functionality
- Use Tailwind classes consistent with other shop pages
- Add @error handler for broken product images
- Update all URLs to use {{ base_url }} for multi-tenant support
- Modernize layout with responsive grid system
The cart page now has proper styling, navigation, and integrates
seamlessly with the rest of the shop frontend.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>