From 945ddd3852a3441a2b4b5499b749356c26716120 Mon Sep 17 00:00:00 2001 From: Samir Boulahtit Date: Tue, 2 Dec 2025 19:40:00 +0100 Subject: [PATCH] docs: update company-vendor management documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- .../architecture/company-vendor-management.md | 331 ++++++++++++++++++ docs/frontend/overview.md | 2 +- docs/guides/marketplace-integration.md | Bin 17775 -> 17791 bytes mkdocs.yml | 3 + 4 files changed, 335 insertions(+), 1 deletion(-) create mode 100644 docs/architecture/company-vendor-management.md diff --git a/docs/architecture/company-vendor-management.md b/docs/architecture/company-vendor-management.md new file mode 100644 index 00000000..5032eaa9 --- /dev/null +++ b/docs/architecture/company-vendor-management.md @@ -0,0 +1,331 @@ +# 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 +```python +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 +```python +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 +```python +# 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 + +```python +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: +```python +# 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: +```python +# 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: +```python +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 + +## Related Documentation + +- [Multi-Tenant Architecture](multi-tenant.md) +- [Authentication & RBAC](auth-rbac.md) +- [Models Structure](models-structure.md) +- [Admin Integration Guide](../backend/admin-integration-guide.md) diff --git a/docs/frontend/overview.md b/docs/frontend/overview.md index abb99813..dabbc81f 100644 --- a/docs/frontend/overview.md +++ b/docs/frontend/overview.md @@ -163,7 +163,7 @@ All three frontends share the same core technologies: | Backend | FastAPI | REST API + routing | | Templates | Jinja2 | Server-side rendering | | Interactivity | Alpine.js 3.x | Client-side reactivity | -| Styling | Tailwind CSS 2.x | Utility-first CSS (CDN + fallback) | +| Styling | Tailwind CSS 2.2.x | Utility-first CSS (CDN + fallback) - [Build Guide](tailwind-css.md) | | Icons | Heroicons | SVG icon system | | HTTP Client | Fetch API | API requests | | State Management | Alpine.js reactive | No external state lib | diff --git a/docs/guides/marketplace-integration.md b/docs/guides/marketplace-integration.md index 7c3720bf66e64801e3c1efa7f3b3798f3434282c..d15a5984bc66bbba726d168f7180d1b8bd4c661c 100644 GIT binary patch delta 210 zcmaFg#rVIAaf65%pSnUpQGRl2adBo|x`O&$k zNr^>ZT{edoOqR5e6*|01AuKg7CBLW`YS^U7{pR98!(uILm=1SMo@F5?ez;q~Gq)hW ts6@dlKdD#&3Jy&^YoRN7xJALSpdcqRIk6-&KTp9YKOJiIWTFc%eipx}~NoRO5DSd_vg z!@!_m`)qQixx?gD=9)a06oM0TQj57nfWng>nrn!CRB%km&CF8>&P+*7N-P4aw|OvG z(Lz?>l|oo*UP^vZF~pEdlLIWoCudmLFrJ#c%tB7|w1Q`DL4Hw*f>(Z0u>urKzHOl^ deni2spdcqRIk6-&KTp9YKOJJ