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>
Add comprehensive section on SQLAlchemy fixture best practices:
- Explain why db.expunge() is an anti-pattern in test fixtures
- Document how test isolation works via the db fixture
- Provide examples of correct vs incorrect fixture patterns
- Show how to use db.refresh() for fresh data instead of expunge
This documents the lessons learned from the fixture refactoring
and helps prevent future issues with DetachedInstanceError.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updates to work with refactored fixtures (no expunge):
- Re-query entities when modifying state in tests
- Remove assertions on expunged object properties
Auth service tests:
- Update to use email_or_username field instead of username
Admin service tests:
- Fix statistics test to use stats_service module
- Remove vendor_name filter test (field removed)
- Update import job assertions
Inventory/Marketplace/Stats/Vendor service tests:
- Refactor to work with attached session objects
- Update assertions for changed response formats
- Improve test isolation and cleanup
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Split the monolithic test_database_models.py into focused test modules:
Database model tests (tests/unit/models/database/):
- test_customer.py: Customer model and authentication tests
- test_inventory.py: Inventory model tests
- test_marketplace_import_job.py: Import job model tests
- test_marketplace_product.py: Marketplace product model tests
- test_order.py: Order and OrderItem model tests
- test_product.py: Product model tests
- test_team.py: Team invitation and membership tests
- test_user.py: User model tests
- test_vendor.py: Vendor model tests
Schema validation tests (tests/unit/models/schema/):
- test_auth.py: Auth schema validation tests
- test_customer.py: Customer schema validation tests
- test_inventory.py: Inventory schema validation tests
- test_marketplace_import_job.py: Import job schema tests
- test_order.py: Order schema validation tests
- test_product.py: Product schema validation tests
This improves test organization and makes it easier to find
and maintain tests for specific models.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Remove db.expunge() calls that were causing DetachedInstanceError
when accessing lazy-loaded relationships in tests.
Changes:
- conftest.py: Add documentation about fixture best practices
- auth_fixtures: Remove expunge, keep objects attached to session
- customer_fixtures: Remove expunge, add proper relationship loading
- vendor_fixtures: Remove expunge, add test_company and other_company
fixtures for proper company-vendor relationship setup
- marketplace_import_job_fixtures: Remove expunge calls
- marketplace_product_fixtures: Remove expunge calls
The db fixture already provides test isolation by dropping/recreating
tables after each test, so expunge is unnecessary and harmful.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Services:
- admin_service: Add source_url to import job response, fix vendor_name
to use vendor.name relationship instead of vendor_name field
- marketplace_product_service: Include reserved_quantity and
available_quantity in InventoryLocationResponse
- vendor_service: Fix _get_product_by_id_or_raise to use database ID
(int) instead of marketplace_product_id (str)
Schema:
- Add InventorySummaryResponse model for marketplace product service
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update architecture rules to be stricter (API-003 now blocks ALL exception
raising in endpoints, not just HTTPException)
- Update get_current_vendor_api dependency to guarantee token_vendor_id presence
- Remove redundant _get_vendor_from_token helpers from all vendor API files
- Move vendor access validation to service layer methods
- Add Pydantic response models for media, notification, and payment endpoints
- Add get_active_vendor_by_code service method for public vendor lookup
- Add get_import_job_for_vendor service method with vendor validation
- Update validation script to detect exception raising patterns in endpoints
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Sidebar sections can now be collapsed/expanded by clicking the header.
State is persisted to localStorage so sections remain open/closed
across page navigation and browser sessions.
Changes:
- init-alpine.js: Added openSections state, toggleSection(),
expandSectionForCurrentPage(), and localStorage helpers
- sidebar.html: Refactored with Jinja2 macros for DRY code,
added collapsible sections with CSS transitions and rotating
chevron icons
Features:
- Click section header to toggle expand/collapse
- Chevron rotates 180 degrees when expanded
- Smooth CSS transitions (no extra Alpine plugins needed)
- State persists in localStorage (admin_sidebar_sections key)
- Default: Platform Administration open, others closed
- Dashboard and Settings always visible (not collapsible)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updated documentation to reflect new sidebar structure:
- Added Platform Administration section
- Added Customers page to navigation
- Updated page mapping table with all current pages
- Updated sidebar organization in page-templates.md
- Added customers logger to pre-configured loggers list
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Contact fields now look consistent with other fields (like Letzshop URLs).
The "(from company)" label still indicates inheritance status.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Added company_business_address and company_tax_number to:
- VendorDetailResponse schema
- API response builder
Template now shows actual company values as placeholders instead of
generic "Using company address/tax number" text.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixed the inheritance UI to be based on formData content rather than
stale server state (vendor._inherited flags):
- "(from company)" shows when formData field is empty
- "Reset" shows when formData field has a value
- Purple border shows when formData field is empty
- formData initialization: empty for inherited, actual value for overrides
This ensures each field's UI is independent and reactive to user input.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add UI for vendor contact field inheritance from company:
- Show "(from company)" indicator for inherited fields
- Add "Reset" button per field to clear override
- Add "Reset All to Company" button for bulk reset
- Purple border styling for inherited fields
- Dynamic placeholder showing company values
JavaScript methods:
- resetFieldToCompany(fieldName): Reset individual field
- resetAllContactToCompany(): Reset all contact fields
- hasAnyContactOverride(): Check if any field is overridden
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Vendors can now override company contact information for specific branding.
Fields are nullable - if null, value is inherited from parent company.
Database changes:
- Add vendor.contact_email, contact_phone, website, business_address, tax_number
- All nullable (null = inherit from company)
- Alembic migration: 28d44d503cac
Model changes:
- Add effective_* properties for resolved values
- Add get_contact_info_with_inheritance() helper
Schema changes:
- VendorCreate: Optional contact fields for override at creation
- VendorUpdate: Contact fields + reset_contact_to_company flag
- VendorDetailResponse: Resolved values + *_inherited flags
API changes:
- GET/PUT vendor endpoints return resolved contact info
- PUT accepts contact overrides (empty string = reset to inherit)
- _build_vendor_detail_response helper for consistent responses
Service changes:
- admin_service.update_vendor handles reset_contact_to_company flag
- Empty strings converted to None for inheritance
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
vendor_service.py:
- Remove 6 db.commit() calls from service methods
- Use db.flush() in create methods to get IDs without committing
- Remove db.rollback() calls (endpoint handles transaction)
- Methods affected: create_vendor, toggle_verification, set_verification,
toggle_status, set_status, add_product_to_catalog
vendors.py (endpoints):
- Add db.commit() after set_verification() call
- Add db.commit() after set_status() call
This follows the industry pattern: one request = one transaction,
with commit controlled at the API endpoint level.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
API-002 updated:
- Remove db.commit() from anti-patterns (allowed at endpoint level)
- Add db.delete() to anti-patterns (business logic)
- Clarify that transaction control != business logic
SVC-006 added (new rule):
- Services should NOT call db.commit()
- Transaction control belongs at endpoint level
- Exception: log_service.py for audit log commits
- Severity: warning (to allow gradual migration)
This aligns with industry standard:
- One request = one transaction
- Services do work, endpoints control commits
- Enables composing multiple service calls in single transaction
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- seed_demo.py: Change company owner role from "user" to "vendor"
- header.html: Update header partial styling/content
- marketplace.js: Minor JS updates
- marketplace.html: Template updates
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Icons added to icons.js:
- user-plus, user-check, user-x: User action icons
- shield: Plain shield icon
- store: E-commerce store icon
Loggers added to log-config.js:
- companies: For company management logging
- marketplace: For marketplace operations logging
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Rewrite pagination.md for server-side pagination approach
- Update quick-start guide with new implementation pattern
- Document shared pattern across Vendors, Companies, Users pages
- Add examples for filters, search, and API integration
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Companies and Vendors pages now use server-side pagination:
- Moved from client-side to server-side pagination
- Added search with debounced input
- Added status and verification filters
- Added pagination state object (page, per_page, total, pages)
- Added pageNumbers computed with ellipsis support
- Updated templates with search bar and filter dropdowns
Benefits:
- Better performance with large datasets
- Consistent UX across all admin list pages
- Reduced initial page load time
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
API endpoints (app/api/v1/admin/users.py):
- GET /users: Paginated list with search and filters
- POST /users: Create new user
- GET /users/{id}: Get user details with related counts
- PUT /users/{id}: Update user information
- PUT /users/{id}/status: Toggle active status
- DELETE /users/{id}: Delete user (with ownership check)
Pydantic schemas (models/schema/auth.py):
- UserCreate: For creating new users
- UserUpdate: For updating user information
- UserDetailResponse: Extended user details with counts
- UserListResponse: Paginated list response
Frontend:
- Updated users.html with server-side pagination and filters
- New user-create.html/js for user creation form
- New user-detail.html/js for viewing user details
- New user-edit.html/js for editing users
Routes added for user create, detail, and edit pages.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
vendor_themes.py:
- Return ThemePresetListResponse instead of raw dict (API-001 fix)
- Add ThemePresetResponse response_model to apply_theme_preset
- Add ThemeDeleteResponse response_model to delete endpoint
vendor_domain.py:
- Remove _get_vendor_by_id helper with direct DB query
- Use vendor_service.get_vendor_by_id() instead (API-002 fix)
models/schema/vendor_theme.py:
- Add ThemeDeleteResponse model for delete endpoint response
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add vendor-create.html template:
- Company dropdown with dynamic loading
- Vendor code and subdomain fields with auto-generation
- Name, description, and optional marketplace CSV URL fields
- Extends admin/base.html with proper layout
Add vendor-create.js:
- Uses centralized logger (vendorCreateLog)
- Alpine.js component for form handling
- Company loading from API
- Subdomain auto-generation from vendor name
- Form submission with validation
Route was already defined in admin_pages.py.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Add new methods to vendor_service.py:
- get_vendor_by_id(): Fetch vendor by ID with proper exception
- get_vendor_by_identifier(): Fetch by ID or code
- toggle_verification/set_verification(): Manage vendor verification
- toggle_status/set_status(): Manage vendor active status
Refactor vendors.py API endpoints:
- Remove _get_vendor_by_identifier helper with direct DB queries
- All endpoints now use vendor_service methods
- Remove direct db.commit() calls from endpoints
This fixes API-002 violations and improves architecture compliance.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Change API-003 from "must catch exceptions" to "must NOT raise HTTPException
directly". This aligns with the architecture where:
- Domain exceptions bubble up to global exception handler
- Endpoints should NOT catch and convert exceptions
- HTTPException should only be used by the global handler
Also adds:
- EXC-004: Domain exceptions must inherit from WizamartException
- EXC-005: Global exception handler must be registered
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Convert direct console.log/error/warn calls to use centralized logger:
- imports.js: 13 violations fixed using adminImportsLog
- vendor-themes.js: 5 violations fixed using vendorThemesLog
- code-quality-dashboard.js: 2 violations fixed using codeQualityLog
- code-quality-violations.js: 1 violation fixed using codeQualityViolationsLog
- settings.js: 1 violation fixed using settingsLog
All files now use window.LogConfig.loggers.* for consistent logging.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add arch-check, arch-check-file, arch-check-object Makefile targets
- Include arch-check in QA target for CI integration
- Update architecture-rules.md with CLI usage examples
- Update code-quality.md with validation commands
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add -f/--file option to validate a single file
- Add -d/--folder option to validate a directory
- Add -o/--object option to validate all files related to an entity
(e.g., company, vendor, user) with automatic singular/plural handling
- Add summary table showing pass/fail status per file with error/warning counts
- Remove deprecated positional path argument
Usage examples:
python scripts/validate_architecture.py -f app/api/v1/vendors.py
python scripts/validate_architecture.py -d app/api/
python scripts/validate_architecture.py -o company
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Document all admin UI pages (list, detail, edit)
- Document transfer ownership modal with user search
- Add user management API endpoints section
- Update ownership transfer description
- Fix encoding issue in marketplace-integration.md
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- 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.