- 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>
10 KiB
Company-Vendor Management Architecture
Overview
The Wizamart platform implements a hierarchical multi-tenant architecture where Companies are the primary business entities and Vendors are storefronts/brands that operate under companies.
Company (Business Entity)
├── Owner (User)
├── Contact Information
├── Business Details
└── Vendors (Storefronts/Brands)
├── Vendor 1
├── Vendor 2
└── Vendor N
Key Concepts
Company
A Company represents a business entity on the platform. It contains:
- Owner: A user account that has full control over the company
- Contact Information: Business email, phone, website
- Business Details: Address, tax number
- Status: Active/Inactive, Verified/Pending
Vendor
A Vendor (also called storefront or brand) represents a specific storefront operating under a company. A company can have multiple vendors.
- Unique Identity: Vendor code and subdomain
- Marketplace Integration: CSV URLs for product feeds (FR, EN, DE)
- Status: Active/Inactive, Verified/Pending
- Products: Each vendor has its own product catalog
Data Model
Company Model
class Company:
id: int
name: str
description: str | None
# Owner (at company level)
owner_user_id: int # FK to User
# Contact Information
contact_email: str
contact_phone: str | None
website: str | None
# Business Details
business_address: str | None
tax_number: str | None
# Status
is_active: bool
is_verified: bool
# Timestamps
created_at: datetime
updated_at: datetime
# Relationships
owner: User # Company owner
vendors: list[Vendor] # Storefronts under this company
Vendor Model
class Vendor:
id: int
company_id: int # FK to Company
vendor_code: str # Unique identifier (e.g., "TECHSTORE")
subdomain: str # URL subdomain (e.g., "tech-store")
name: str
description: str | None
# Marketplace URLs (brand-specific)
letzshop_csv_url_fr: str | None
letzshop_csv_url_en: str | None
letzshop_csv_url_de: str | None
# Status
is_active: bool
is_verified: bool
# Timestamps
created_at: datetime
updated_at: datetime
# Relationships
company: Company # Parent company (owner is accessed via company.owner)
Key Design Decisions
1. Owner at Company Level Only
Previously, each vendor had its own owner_user_id. This has been refactored:
- Before:
Vendor.owner_user_id- each vendor had a separate owner - After:
Company.owner_user_id- ownership is at company level
Rationale: A business entity (company) should have a single owner who can manage all storefronts. This simplifies:
- User management
- Permission handling
- Ownership transfer operations
2. Contact Information at Company Level
Business contact information (email, phone, website, address, tax number) is now stored at the company level:
- Before: Vendors had contact fields
- After: Contact info on Company model, vendors reference parent company
Rationale: Business details are typically the same across all storefronts of a company.
3. Clean Architecture
The Vendor.owner_user_id field has been completely removed:
- Ownership is determined solely via the company relationship
- Use
vendor.company.owner_user_idto get the owner - Use
vendor.company.ownerto get the owner User object
API Endpoints
Company Management (Admin)
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/admin/companies |
Create company with owner |
| GET | /api/v1/admin/companies |
List all companies |
| GET | /api/v1/admin/companies/{id} |
Get company details |
| PUT | /api/v1/admin/companies/{id} |
Update company |
| PUT | /api/v1/admin/companies/{id}/verification |
Toggle verification |
| PUT | /api/v1/admin/companies/{id}/status |
Toggle active status |
| POST | /api/v1/admin/companies/{id}/transfer-ownership |
Transfer ownership |
| DELETE | /api/v1/admin/companies/{id} |
Delete company |
Vendor Management (Admin)
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/admin/vendors |
Create vendor under company |
| GET | /api/v1/admin/vendors |
List all vendors |
| GET | /api/v1/admin/vendors/{id} |
Get vendor details |
| PUT | /api/v1/admin/vendors/{id} |
Update vendor |
| PUT | /api/v1/admin/vendors/{id}/verification |
Toggle verification |
| PUT | /api/v1/admin/vendors/{id}/status |
Toggle active status |
| DELETE | /api/v1/admin/vendors/{id} |
Delete vendor |
User Management (Admin)
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/admin/users |
List all users |
| GET | /api/v1/admin/users/search?q={query} |
Search users by name/email |
| PUT | /api/v1/admin/users/{id}/status |
Toggle user status |
| GET | /api/v1/admin/users/stats |
Get user statistics |
Service Layer
CompanyService (app/services/company_service.py)
Primary service for company operations:
create_company_with_owner()- Creates company and owner user accountget_company_by_id()- Get company with vendors loadedget_companies()- Paginated list with filteringupdate_company()- Update company fieldstoggle_verification()- Verify/unverify companytoggle_active()- Activate/deactivate companytransfer_ownership()- Transfer to new ownerdelete_company()- Delete company (requires no vendors)
AdminService (app/services/admin_service.py)
Admin-specific vendor operations:
create_vendor()- Create vendor under existing companyget_all_vendors()- Paginated list with company relationshipupdate_vendor()- Update vendor fieldsverify_vendor()- Toggle verificationtoggle_vendor_status()- Toggle active statusdelete_vendor()- Delete vendor
VendorService (app/services/vendor_service.py)
Self-service vendor operations (for company owners):
create_vendor()- Create vendor (requires company_id, validates ownership)get_vendors()- Get vendors with access controlget_vendor_by_code()- Get single vendor
Creating a New Company with Vendors
Via Admin API
# 1. Create company with owner
POST /api/v1/admin/companies
{
"name": "Tech Solutions Ltd",
"owner_email": "owner@techsolutions.com",
"contact_email": "info@techsolutions.com",
"contact_phone": "+352 123 456",
"website": "https://techsolutions.com",
"business_address": "123 Tech Street, Luxembourg",
"tax_number": "LU12345678"
}
# Response includes temporary password for owner
# 2. Create vendor under company
POST /api/v1/admin/vendors
{
"company_id": 1,
"vendor_code": "TECHSTORE",
"subdomain": "tech-store",
"name": "Tech Store",
"description": "Consumer electronics storefront"
}
Ownership Transfer
Ownership transfer is a critical operation available at the company level:
- Admin initiates transfer via
/api/v1/admin/companies/{id}/transfer-ownership - Company owner changes -
Company.owner_user_idupdated - All vendors affected - Vendors inherit new owner via company relationship
- Audit trail - Transfer reason logged
POST /api/v1/admin/companies/1/transfer-ownership
{
"new_owner_user_id": 42,
"confirm_transfer": true,
"transfer_reason": "Business acquisition"
}
Admin UI Pages
Company List Page (/admin/companies)
- Lists all companies with owner, vendor count, and status
- Actions: View, Edit, Delete (disabled if company has vendors)
- Stats cards showing total, verified, active companies
Company Detail Page (/admin/companies/{id})
- Quick Actions - Edit Company, Delete Company
- Status Cards - Verification, Active status, Vendor count, Created date
- Information Sections - Basic info, Contact info, Business details, Owner info
- Vendors Table - Lists all vendors under this company with links
- More Actions - Create Vendor button
Company Edit Page (/admin/companies/{id}/edit)
- Quick Actions - Verify/Unverify, Activate/Deactivate
- Edit Form - Company details, contact info, business details
- Statistics - Vendor counts (readonly)
- More Actions - Transfer Ownership, Delete Company
Vendor Detail Page (/admin/vendors/{code})
- Quick Actions - Edit Vendor, Delete Vendor
- Status Cards - Verification, Active status, Created/Updated dates
- Information Sections - Basic info, Contact info, Business details, Owner info
- More Actions - View Parent Company link, Customize Theme
Transfer Ownership Modal
A modal dialog for transferring company ownership:
- User Search - Autocomplete search by username or email
- Selected User Display - Shows selected user with option to clear
- Transfer Reason - Optional field for audit trail
- Confirmation Checkbox - Required before transfer
- Validation - Inline error messages for missing fields
Best Practices
Creating Vendors
Always use company_id when creating vendors:
# Correct
vendor_data = VendorCreate(
company_id=company.id,
vendor_code="MYSTORE",
subdomain="my-store",
name="My Store"
)
# Incorrect (old pattern - don't use)
vendor_data = VendorCreate(
owner_email="owner@example.com", # No longer supported
...
)
Accessing Owner Information
Use the company relationship:
# Get owner User object
owner = vendor.company.owner
# Get owner details
owner_email = vendor.company.owner.email
owner_id = vendor.company.owner_user_id
Checking Permissions
For vendor operations, check company ownership:
def can_manage_vendor(user, vendor):
if user.role == "admin":
return True
return vendor.company.owner_user_id == user.id
Migration Notes
The Vendor.owner_user_id column has been removed. If you have an existing database:
- Run the migration:
alembic upgrade head - This will drop the
owner_user_idcolumn from vendors table - Ownership is now determined via
vendor.company.owner_user_id
If migrating from an older vendor-centric model:
- Create companies for existing vendors (group by owner)
- Assign vendors to companies via
company_id - Copy contact info from vendors to companies
- Run the migration to drop the old owner_user_id column