Implement database-driven feature gating with contextual upgrade prompts:
- Add Feature model with 30 features across 8 categories
- Create FeatureService with caching for tier-based feature checking
- Add @require_feature decorator and RequireFeature dependency for backend enforcement
- Create vendor features API (6 endpoints) and admin features API
- Add Alpine.js feature store and upgrade prompts store for frontend
- Create Jinja macros: feature_gate, feature_locked, limit_warning, usage_bar
- Add usage API for tracking orders/products/team limits with upgrade info
- Fix Stripe webhook to create VendorAddOn records on addon purchase
- Integrate upgrade prompts into vendor dashboard with tier badge and usage bars
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add third placement category for content pages that appear in the
bottom bar alongside the copyright notice (Privacy Policy, Terms, etc.):
Model changes:
- Add show_in_legal boolean field to ContentPage model
- Add to to_dict() serialization
Service changes:
- Add legal_only filter to list_pages_for_vendor()
Platform changes:
- Fetch legal_pages in get_platform_context()
- Update base.html to render legal_pages dynamically
- Fallback to hardcoded links if no CMS pages configured
Migration:
- Add column with default=False
- Auto-set show_in_legal=True for privacy and terms pages
Categories:
- show_in_header: Top navigation
- show_in_footer: Quick Links column
- show_in_legal: Bottom bar with copyright (NEW)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement 4-step onboarding flow for new vendors after signup:
- Step 1: Company profile setup
- Step 2: Letzshop API configuration with connection testing
- Step 3: Product & order import CSV URL configuration
- Step 4: Historical order sync with progress bar
Key features:
- Blocks dashboard access until completed
- Step indicators with visual progress
- Resume capability (progress persisted in DB)
- Admin skip capability for support cases
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements a comprehensive email system with:
- Multi-provider support (SMTP, SendGrid, Mailgun, Amazon SES)
- Database-stored templates with i18n (EN, FR, DE, LB)
- Jinja2 template rendering with variable interpolation
- Email logging for debugging and compliance
- Debug mode for development (logs instead of sending)
- Welcome email integration in signup flow
New files:
- models/database/email.py: EmailTemplate and EmailLog models
- app/services/email_service.py: Provider abstraction and service
- scripts/seed_email_templates.py: Template seeding script
- tests/unit/services/test_email_service.py: 28 unit tests
- docs/features/email-system.md: Complete documentation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement complete marketing homepage for Wizamart targeting Letzshop
vendors in Luxembourg. Includes:
- Marketing homepage with hero, pricing tiers, and add-ons
- 4-step signup wizard with Stripe card collection (30-day trial)
- Letzshop vendor lookup for shop claiming
- Platform API endpoints for pricing, vendors, and signup
- Stripe SetupIntent integration for trial with card upfront
- Database fields for Letzshop vendor identity tracking
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 6 - Database-driven tiers:
- Update subscription_service to query database first with legacy fallback
- Add get_tier_info() db parameter and _get_tier_from_legacy() method
Phase 7 - Platform health integration:
- Add get_subscription_capacity() for theoretical vs actual capacity
- Include subscription capacity in full health report
Phase 8 - Background subscription tasks:
- Add reset_period_counters() for billing period resets
- Add check_trial_expirations() for trial management
- Add sync_stripe_status() for Stripe synchronization
- Add cleanup_stale_subscriptions() for maintenance
- Add capture_capacity_snapshot() for daily metrics
Phase 10 - Capacity planning & forecasting:
- Add CapacitySnapshot model for historical tracking
- Create capacity_forecast_service with growth trends
- Add /subscription-capacity, /trends, /recommendations endpoints
- Add /snapshot endpoint for manual captures
Also includes billing API enhancements from phase 4:
- Add upcoming-invoice, change-tier, addon purchase/cancel endpoints
- Add UsageSummary schema for billing page
- Enhance billing.js with addon management functions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add tier_id column with FK to subscription_tiers table
- Add tier_obj relationship to VendorSubscription model
- Update tier_limits property to use database tier when available
- Create migration with SQLite batch mode support
- Backfill tier_id from existing tier code values
This enables proper database relationship between vendors and their
subscription tier, instead of just storing the tier code string.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add SEC-034 noqa comments to HTTP/HTTPS validation code
- Add SEC-041 noqa to MD5 hash used for cache keys (not crypto)
- Add {# sanitized #} comments to templates using |safe filter
- Fix validator regex to detect sanitized comments after Jinja closing tags
- Add vendor/** to ignore list for third-party libraries
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add translations support with language tabs (EN, FR, DE, LU)
- Add product identifiers: vendor SKU with auto-generate, brand, GTIN, GTIN type
- Add pricing fields: price (incl. VAT), sale price, currency, VAT rate
- Add primary image field with preview
- Add product status (active, featured) checkboxes
- Add optional supplier info section
- Pre-populate form with existing product data from API
- Add form validation (isFormValid method)
- Make is_digital read-only (derived from marketplace product)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add warehouse and bin_location columns to Inventory model
- Create inventory_import_service for bulk TSV/CSV import
- Add POST /api/v1/admin/inventory/import endpoint
- Add Import button and modal to inventory admin page
- Support both single-unit rows and explicit QUANTITY column
File format: BIN, EAN, PRODUCT (optional), QUANTITY (optional)
Products matched by GTIN/EAN, unmatched items reported.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add "Create Product" button in header
- Update actions column to View, Edit, Delete
- Add create/edit pages with forms and vendor selector
- Add POST/PATCH API endpoints for vendor products
- Add create_product and update_product service methods
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Change Product/ProductTranslation from "override/inheritance" pattern
(NULL = inherit from marketplace) to "independent copy" pattern
(all fields populated at creation).
Key changes:
- Remove OVERRIDABLE_FIELDS, effective_* properties, reset_* methods
- Rename get_override_info() → get_source_comparison_info()
- Update copy_to_vendor_catalog() to copy ALL fields + translations
- Replace effective_* with direct field access in services
- Remove *_overridden fields from schema, keep *_source for comparison
- Add migration to populate NULL fields from marketplace products
The marketplace_product_id FK is kept for "view original source" feature.
Rollback tag: v1.0.0-pre-product-independence
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add invoice exceptions module with proper exception hierarchy
- Replace HTTPException with service-layer exceptions in invoice API
- Add InvoicePDFGeneratedResponse and InvoiceStatsResponse Pydantic models
- Replace db.commit() with db.flush() in services for proper transaction control
- Update invoice service to use exceptions from app/exceptions/invoice.py
All 14 errors and 14 warnings are now resolved. Validation passes with
only INFO-level findings.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 1 OMS implementation:
Invoicing:
- Add Invoice and VendorInvoiceSettings database models
- Full EU VAT support (27 countries, OSS, B2B reverse charge)
- Invoice PDF generation with WeasyPrint + Jinja2 templates
- Vendor invoice API endpoints for settings, creation, PDF download
Subscription Tiers:
- Add VendorSubscription model with 4 tiers (Essential/Professional/Business/Enterprise)
- Tier limit enforcement for orders, products, team members
- Feature gating based on subscription tier
- Automatic trial subscription creation for new vendors
- Integrate limit checks into order creation (direct and Letzshop sync)
Marketing:
- Update pricing documentation with 4-tier structure
- Revise back-office positioning strategy
- Update homepage with Veeqo-inspired Letzshop-focused messaging
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add validator_type field to scans and violations (architecture,
security, performance)
- Create security validator with SEC-xxx rules
- Create performance validator with PERF-xxx rules
- Add base validator class for shared functionality
- Add validate_all.py script to run all validators
- Update code quality service with validator type filtering
- Add validator type tabs to dashboard UI
- Add validator type filter to violations list
- Update stats response with per-validator breakdown
- Add security and performance rules documentation
- Add chat-bubble icons to icon library
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add status fields to ArchitectureScan model (status, started_at,
completed_at, error_message, progress_message)
- Create database migration for new status fields
- Create background task function execute_code_quality_scan()
- Update API to return 202 with job IDs and support polling
- Add code quality scans to unified BackgroundTasksService
- Integrate scans into background tasks API and page
- Implement frontend polling with 3-second interval
- Add progress banner showing scan status
- Users can navigate away while scans run in background
- Document the implementation in architecture docs
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add job cancellation and retry functionality
- Improve jobs table with better status display
- Add background task improvements
- Update Letzshop order service
- Update documentation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add admin customers API endpoints
- Add AdminCustomerService for customer operations
- Enhance customers.html template with management features
- Add customers.js Alpine component
- Add customer list schemas
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add API-002 architecture rule preventing Pydantic imports in API endpoints
- Move inline Pydantic models from vendor_products.py to models/schema/vendor_product.py
- Update vendor_products.py to import schemas from proper location
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Follows architecture rule: Pydantic schemas belong in models/schema/
- Moved LetzshopExportRequest to models/schema/vendor.py
- Added LetzshopExportFileInfo and LetzshopExportResponse schemas
- Updated API endpoint to use proper response_model
- Removed inline BaseModel import from API file
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Money Handling Architecture:
- Store all monetary values as integer cents (€105.91 = 10591)
- Add app/utils/money.py with Money class and conversion helpers
- Add static/shared/js/money.js for frontend formatting
- Update all database models to use _cents columns (Product, Order, etc.)
- Update CSV processor to convert prices to cents on import
- Add Alembic migration for Float to Integer conversion
- Create .architecture-rules/money.yaml with 7 validation rules
- Add docs/architecture/money-handling.md documentation
Order Details Page Fixes:
- Fix customer name showing 'undefined undefined' - use flat field names
- Fix vendor info empty - add vendor_name/vendor_code to OrderDetailResponse
- Fix shipping address using wrong nested object structure
- Enrich order detail API response with vendor info
Vendor Filter Persistence Fixes:
- Fix orders.js: restoreSavedVendor now sets selectedVendor and filters
- Fix orders.js: init() only loads orders if no saved vendor to restore
- Fix marketplace-letzshop.js: restoreSavedVendor calls selectVendor()
- Fix marketplace-letzshop.js: clearVendorSelection clears TomSelect dropdown
- Align vendor selector placeholder text between pages
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Historical import jobs were not appearing in the recent jobs list because
list_letzshop_jobs() only queried marketplace_import_jobs and letzshop_sync_logs.
Changes:
- Add LetzshopHistoricalImportJob query to list_letzshop_jobs()
- Add current_phase and error_message fields to LetzshopJobItem schema
- Fixed stuck job 8 (marked as failed)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replaces the "fail on missing product" behavior with graceful handling:
- Orders import even when products aren't found by GTIN
- Unmatched items link to a per-vendor placeholder product
- Exceptions tracked in order_item_exceptions table for QC resolution
- Order confirmation blocked until exceptions are resolved
- Auto-matching when products are imported via catalog sync
New files:
- OrderItemException model and migration
- OrderItemExceptionService with CRUD and resolution logic
- Admin and vendor API endpoints for exception management
- Domain exceptions for error handling
Modified:
- OrderItem: added needs_product_match flag and exception relationship
- OrderService: graceful handling with placeholder products
- MarketplaceProductService: auto-match on product import
- Letzshop confirm endpoints: blocking check for unresolved exceptions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update API endpoints and schemas to use the unified Order model:
- Update Letzshop order schemas with OrderItem support
- Update API responses to use new field names (external_*, status, etc.)
- Update confirm/reject endpoints to use OrderItem.external_item_id
- Update Letzshop order service for unified Order model queries
- Update documentation to reflect completed implementation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add AddressSnapshot and CustomerSnapshot schemas
- Update OrderItemResponse with gtin fields and item_state
- Update OrderResponse with all snapshot fields
- Add OrderListItem for simplified list views
- Add Letzshop-specific schemas (LetzshopOrderImport, LetzshopShippingInfo)
- Update AdminOrderItem with new fields
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Update Order model with customer/address snapshot fields
- Add external marketplace references (external_order_id, external_shipment_id)
- Add tracking_provider field for shipping carriers
- Add order_date, confirmed_at timestamps
- Update OrderItem with gtin/gtin_type, external_item_id, item_state
- Remove LetzshopOrder model (orders now go to unified table)
- Update LetzshopFulfillmentQueue to reference orders.id
Design decision: Single orders table for all channels with snapshotted
data preserved at order time for historical accuracy.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add admin API endpoints for order management
- Add orders page with vendor selector and filtering
- Add order schemas for admin operations
- Support order status tracking and management
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add admin API endpoints for inventory management
- Add inventory page with vendor selector and filtering
- Add admin schemas for cross-vendor inventory operations
- Support digital products with unlimited inventory
- Add integration tests for admin inventory API
- Add inventory management guide documentation
Mirrors vendor inventory functionality with admin-level access.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add historical order import with pagination support
- Add customer_locale, shipping_country_iso, billing_country_iso columns
- Add gtin/gtin_type columns to Product table for EAN matching
- Fix order stats to count all orders server-side (not just visible page)
- Add GraphQL introspection script with tracking workaround tests
- Enrich inventory units with EAN, MPN, SKU, product name
- Add LetzshopOrderStats schema for proper status counts
Migrations:
- a9a86cef6cca: Add locale and country fields to letzshop_orders
- cb88bc9b5f86: Add gtin columns to products table
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add new Marketplace section in admin sidebar with Letzshop sub-item
- Remove old Import and Letzshop Orders items from Product Catalog
- Create unified Letzshop management page with 3 tabs:
- Products tab: Import/Export functionality
- Orders tab: Order management with confirm/reject/tracking
- Settings tab: API credentials and CSV URLs
- Add unified jobs table showing imports, exports, and order syncs
- Implement vendor autocomplete using Tom Select library (CDN + fallback)
- Add /vendors/{vendor_id}/jobs API endpoint for unified job listing
- Move database queries to service layer (LetzshopOrderService)
- Add LetzshopJobItem and LetzshopJobsListResponse schemas
- Include Tom Select CSS/JS assets as local fallback
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove |safe from |tojson in HTML attributes (x-data) - quotes must
become " for browsers to parse correctly
- Update LANG-002 and LANG-003 architecture rules to document correct
|tojson usage patterns:
- HTML attributes: |tojson (no |safe)
- Script blocks: |tojson|safe
- Fix validator to warn when |tojson|safe is used in x-data (breaks
HTML attribute parsing)
- Improve code quality across services, APIs, and tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add database fields for language preferences:
- Vendor: dashboard_language, storefront_language, storefront_languages
- User: preferred_language
- Customer: preferred_language
- Add language middleware for request-level language detection:
- Cookie-based persistence
- Browser Accept-Language fallback
- Vendor storefront language constraints
- Add language API endpoints (/api/v1/language/*):
- POST /set - Set language preference
- GET /current - Get current language info
- GET /list - List available languages
- DELETE /clear - Clear preference
- Add i18n utilities (app/utils/i18n.py):
- JSON-based translation loading
- Jinja2 template integration
- Language resolution helpers
- Add reusable language selector macros for templates
- Add languageSelector() Alpine.js component
- Add translation files (en, fr, de, lb) in static/locales/
- Add architecture rules documentation for language implementation
- Update marketplace-product-detail.js to use native language names
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add Optional type annotations to nullable parameters in service methods
to fix architecture validation warnings.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Bug: Language selector worked on UI but import always used 'en'
Root causes:
1. Frontend: startImport() was not including language in API payload
2. Backend: language was not stored in import job database record
3. Backend: language was not returned in API response models
Fixes:
- Add language to payload in marketplace.js startImport()
- Add language column to MarketplaceImportJob model
- Store language when creating import job in service
- Include language in both response model converters
- Add database migration for language column
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Import Error Tracking:
- Add MarketplaceImportError model to store detailed error information
- Store row number, identifier, error type, message, and row data for each error
- Add API endpoint GET /admin/marketplace-import-jobs/{job_id}/errors
- Add UI to view and browse import errors in job details modal
- Support pagination and error type filtering
Translation Tabs:
- Replace flat translation list with tabbed interface on product detail page
- Add language tabs with full language names
- Add copy-to-clipboard functionality for translation content
- Improved UX with better visual separation of translations
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add a new Testing Dashboard page that replaces the old Testing Hub with
pytest integration:
- Database models for test runs, results, and collections (TestRun,
TestResult, TestCollection)
- Test runner service that executes pytest with JSON reporting and
stores results in the database
- REST API endpoints for running tests, viewing history, and statistics
- Dashboard UI showing pass rates, trends, tests by category, and top
failing tests
- Alembic migration for the new test_* tables
The dashboard allows admins to:
- Run pytest directly from the UI
- View test run history with pass/fail statistics
- See trend data across recent runs
- Identify frequently failing tests
- Collect test information without running
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add language parameter to import endpoints and background tasks
- Extract translation fields (title, description, short_description)
- Create/update MarketplaceProductTranslation records during import
- Add MarketplaceProductTranslationSchema for API responses
- Map product_type column to product_type_raw to avoid enum conflict
- Parse prices to numeric format (price_numeric, sale_price_numeric)
- Update marketplace product service for translation-based lookups
- Update CSV export to retrieve titles from translations
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove unused register_user() method and helper methods
- Remove legacy UserRegister schema (customer registration uses CustomerService)
- Remove wrapper methods that just delegated to auth_manager
- Simplify auth_service to focus on login and vendor access control
- Clean up tests to match simplified service
The only registration path is now /api/v1/shop/auth/register for customers,
which uses CustomerService.register_customer().
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Move database queries to service layer and use proper Pydantic responses:
Schema changes (models/schema/marketplace_import_job.py):
- Add AdminMarketplaceImportJobResponse with extra fields (id, error_details,
created_by_name)
- Add AdminMarketplaceImportJobListResponse with items/total/page/limit format
Service changes (app/services/marketplace_import_job_service.py):
- Add convert_to_admin_response_model() for admin-specific response
- Add get_all_import_jobs_paginated() for admin listing
- Add get_import_job_by_id_admin() without access control
API changes (app/api/v1/admin/marketplace.py):
- Use service methods instead of direct DB queries
- Use proper Pydantic response models instead of dicts
- All business logic now in service layer
Cleanup:
- Remove duplicate methods from admin_service.py
Architecture validation now passes with 0 violations.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add POST /api/v1/admin/marketplace-import-jobs endpoint to allow
admins to create import jobs for any vendor.
Changes:
- Add AdminMarketplaceImportJobRequest schema with vendor_id field
- Add create_marketplace_import_job endpoint in admin/marketplace.py
- Make vendor_code and vendor_name optional in response model
to handle edge cases where vendor relationship may not be loaded
This fixes the 405 Method Not Allowed error when trying to import
products from the admin marketplace page.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>