Files
orion/docs/architecture/company-vendor-management.md
Samir Boulahtit 945ddd3852 docs: update company-vendor management documentation
- 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>
2025-12-02 19:40:00 +01:00

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_id to get the owner
  • Use vendor.company.owner to 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 account
  • get_company_by_id() - Get company with vendors loaded
  • get_companies() - Paginated list with filtering
  • update_company() - Update company fields
  • toggle_verification() - Verify/unverify company
  • toggle_active() - Activate/deactivate company
  • transfer_ownership() - Transfer to new owner
  • delete_company() - Delete company (requires no vendors)

AdminService (app/services/admin_service.py)

Admin-specific vendor operations:

  • create_vendor() - Create vendor under existing company
  • get_all_vendors() - Paginated list with company relationship
  • update_vendor() - Update vendor fields
  • verify_vendor() - Toggle verification
  • toggle_vendor_status() - Toggle active status
  • delete_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 control
  • get_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:

  1. Admin initiates transfer via /api/v1/admin/companies/{id}/transfer-ownership
  2. Company owner changes - Company.owner_user_id updated
  3. All vendors affected - Vendors inherit new owner via company relationship
  4. 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:

  1. Run the migration: alembic upgrade head
  2. This will drop the owner_user_id column from vendors table
  3. Ownership is now determined via vendor.company.owner_user_id

If migrating from an older vendor-centric model:

  1. Create companies for existing vendors (group by owner)
  2. Assign vendors to companies via company_id
  3. Copy contact info from vendors to companies
  4. Run the migration to drop the old owner_user_id column