diff --git a/docs/implementation/feature-gating-system.md b/docs/implementation/feature-gating-system.md new file mode 100644 index 00000000..1737e20b --- /dev/null +++ b/docs/implementation/feature-gating-system.md @@ -0,0 +1,377 @@ +# Feature Gating System + +## Overview + +The feature gating system provides tier-based access control for platform features. It allows restricting functionality based on vendor subscription tiers (Essential, Professional, Business, Enterprise) with contextual upgrade prompts when features are locked. + +**Implemented:** December 31, 2025 + +## Architecture + +### Database Models + +Located in `models/database/feature.py`: + +| Model | Purpose | +|-------|---------| +| `Feature` | Feature definitions with tier requirements | +| `VendorFeatureOverride` | Per-vendor feature overrides (enable/disable) | + +### Feature Model Structure + +```python +class Feature(Base): + __tablename__ = "features" + + id: int # Primary key + code: str # Unique feature code (e.g., "analytics_dashboard") + name: str # Display name + description: str # User-facing description + category: str # Feature category + minimum_tier_code: str # Minimum tier required (essential/professional/business/enterprise) + minimum_tier_order: int # Tier order for comparison (1-4) + is_active: bool # Whether feature is available + created_at: datetime + updated_at: datetime +``` + +### Tier Ordering + +| Tier | Order | Code | +|------|-------|------| +| Essential | 1 | `essential` | +| Professional | 2 | `professional` | +| Business | 3 | `business` | +| Enterprise | 4 | `enterprise` | + +## Feature Categories + +30 features organized into 8 categories: + +### 1. Analytics +| Feature Code | Name | Min Tier | +|-------------|------|----------| +| `basic_analytics` | Basic Analytics | Essential | +| `analytics_dashboard` | Analytics Dashboard | Professional | +| `advanced_analytics` | Advanced Analytics | Business | +| `custom_reports` | Custom Reports | Enterprise | + +### 2. Product Management +| Feature Code | Name | Min Tier | +|-------------|------|----------| +| `basic_products` | Product Management | Essential | +| `bulk_product_edit` | Bulk Product Edit | Professional | +| `product_variants` | Product Variants | Professional | +| `product_bundles` | Product Bundles | Business | +| `inventory_alerts` | Inventory Alerts | Professional | + +### 3. Order Management +| Feature Code | Name | Min Tier | +|-------------|------|----------| +| `basic_orders` | Order Management | Essential | +| `order_automation` | Order Automation | Professional | +| `advanced_fulfillment` | Advanced Fulfillment | Business | +| `multi_warehouse` | Multi-Warehouse | Enterprise | + +### 4. Marketing +| Feature Code | Name | Min Tier | +|-------------|------|----------| +| `discount_codes` | Discount Codes | Professional | +| `abandoned_cart` | Abandoned Cart Recovery | Business | +| `email_marketing` | Email Marketing | Business | +| `loyalty_program` | Loyalty Program | Enterprise | + +### 5. Support +| Feature Code | Name | Min Tier | +|-------------|------|----------| +| `basic_support` | Email Support | Essential | +| `priority_support` | Priority Support | Professional | +| `phone_support` | Phone Support | Business | +| `dedicated_manager` | Dedicated Account Manager | Enterprise | + +### 6. Integration +| Feature Code | Name | Min Tier | +|-------------|------|----------| +| `basic_api` | Basic API Access | Professional | +| `advanced_api` | Advanced API Access | Business | +| `webhooks` | Webhooks | Business | +| `custom_integrations` | Custom Integrations | Enterprise | + +### 7. Branding +| Feature Code | Name | Min Tier | +|-------------|------|----------| +| `basic_theme` | Theme Customization | Essential | +| `custom_domain` | Custom Domain | Professional | +| `white_label` | White Label | Enterprise | +| `custom_checkout` | Custom Checkout | Enterprise | + +### 8. Team +| Feature Code | Name | Min Tier | +|-------------|------|----------| +| `team_management` | Team Management | Professional | +| `role_permissions` | Role Permissions | Business | +| `audit_logs` | Audit Logs | Business | + +## Services + +### FeatureService + +Located in `app/services/feature_service.py`: + +```python +class FeatureService: + """Service for managing tier-based feature access.""" + + # In-memory caching (refreshed every 5 minutes) + _feature_cache: dict[str, Feature] = {} + _cache_timestamp: datetime | None = None + CACHE_TTL_SECONDS = 300 + + def has_feature(self, db: Session, vendor_id: int, feature_code: str) -> bool: + """Check if vendor has access to a feature.""" + + def get_available_features(self, db: Session, vendor_id: int) -> list[str]: + """Get list of feature codes available to vendor.""" + + def get_all_features_with_status(self, db: Session, vendor_id: int) -> list[dict]: + """Get all features with availability status for vendor.""" + + def get_feature_info(self, db: Session, feature_code: str) -> dict | None: + """Get full feature information including tier requirements.""" +``` + +### UsageService + +Located in `app/services/usage_service.py`: + +```python +class UsageService: + """Service for tracking and managing vendor usage against tier limits.""" + + def get_usage_summary(self, db: Session, vendor_id: int) -> dict: + """Get comprehensive usage summary with limits and upgrade info.""" + + def check_limit(self, db: Session, vendor_id: int, limit_type: str) -> dict: + """Check specific limit with detailed info.""" + + def get_upgrade_info(self, db: Session, vendor_id: int) -> dict: + """Get upgrade recommendations based on current usage.""" +``` + +## Backend Enforcement + +### Decorator Pattern + +```python +from app.core.feature_gate import require_feature + +@router.get("/analytics/advanced") +@require_feature("advanced_analytics") +async def get_advanced_analytics( + db: Session = Depends(get_db), + vendor_id: int = Depends(get_current_vendor_id) +): + # Only accessible if vendor has advanced_analytics feature + pass +``` + +### Dependency Pattern + +```python +from app.core.feature_gate import RequireFeature + +@router.get("/marketing/loyalty") +async def get_loyalty_program( + db: Session = Depends(get_db), + _: None = Depends(RequireFeature("loyalty_program")) +): + # Only accessible if vendor has loyalty_program feature + pass +``` + +### Exception Handling + +When a feature is not available, `FeatureNotAvailableException` is raised: + +```python +class FeatureNotAvailableException(Exception): + def __init__(self, feature_code: str, required_tier: str): + self.feature_code = feature_code + self.required_tier = required_tier + super().__init__(f"Feature '{feature_code}' requires {required_tier} tier") +``` + +HTTP Response (403): +```json +{ + "detail": "Feature 'advanced_analytics' requires Professional tier or higher", + "feature_code": "advanced_analytics", + "required_tier": "Professional", + "upgrade_url": "/vendor/wizamart/billing" +} +``` + +## API Endpoints + +### Vendor Features API + +Base: `/api/v1/vendor/features` + +| Endpoint | Method | Description | +|----------|--------|-------------| +| `/features/available` | GET | List available feature codes | +| `/features` | GET | All features with availability status | +| `/features/{code}` | GET | Single feature info | +| `/features/{code}/check` | GET | Quick availability check | + +### Vendor Usage API + +Base: `/api/v1/vendor/usage` + +| Endpoint | Method | Description | +|----------|--------|-------------| +| `/usage` | GET | Full usage summary with limits | +| `/usage/check/{limit_type}` | GET | Check specific limit (orders/products/team_members) | +| `/usage/upgrade-info` | GET | Upgrade recommendations | + +### Admin Features API + +Base: `/api/v1/admin/features` + +| Endpoint | Method | Description | +|----------|--------|-------------| +| `/features` | GET | List all features | +| `/features/{id}` | GET | Get feature details | +| `/features/{id}` | PUT | Update feature | +| `/features/{id}/toggle` | POST | Toggle feature active status | +| `/features/vendors/{vendor_id}/overrides` | GET | Get vendor overrides | +| `/features/vendors/{vendor_id}/overrides` | POST | Create override | + +## Frontend Integration + +### Alpine.js Feature Store + +Located in `static/shared/js/feature-store.js`: + +```javascript +// Usage in templates +$store.features.has('analytics_dashboard') // Check feature +$store.features.loaded // Loading state +$store.features.getFeature('advanced_api') // Get feature details +``` + +### Alpine.js Upgrade Store + +Located in `static/shared/js/upgrade-prompts.js`: + +```javascript +// Usage in templates +$store.upgrade.shouldShowLimitWarning('orders') +$store.upgrade.getUsageString('products') +$store.upgrade.hasUpgradeRecommendation +``` + +### Jinja2 Macros + +Located in `app/templates/shared/macros/feature_gate.html`: + +#### Feature Gate Container +```jinja2 +{% from "shared/macros/feature_gate.html" import feature_gate %} + +{% call feature_gate("analytics_dashboard") %} +
Analytics content here - only visible if feature available
+{% endcall %} +``` + +#### Feature Locked Card +```jinja2 +{% from "shared/macros/feature_gate.html" import feature_locked %} + +{{ feature_locked("advanced_analytics", "Advanced Analytics", "Get deeper insights") }} +``` + +#### Upgrade Banner +```jinja2 +{% from "shared/macros/feature_gate.html" import upgrade_banner %} + +{{ upgrade_banner("custom_domain") }} +``` + +#### Usage Limit Warning +```jinja2 +{% from "shared/macros/feature_gate.html" import limit_warning %} + +{{ limit_warning("orders") }} {# Shows warning when approaching limit #} +``` + +#### Usage Progress Bar +```jinja2 +{% from "shared/macros/feature_gate.html" import usage_bar %} + +{{ usage_bar("products", "Products") }} +``` + +#### Tier Badge +```jinja2 +{% from "shared/macros/feature_gate.html" import tier_badge %} + +{{ tier_badge() }} {# Shows current tier as colored badge #} +``` + +## Vendor Dashboard Integration + +The vendor dashboard (`/vendor/{code}/dashboard`) now includes: + +1. **Tier Badge**: Shows current subscription tier in header +2. **Usage Bars**: Visual progress bars for orders, products, team members +3. **Upgrade Prompts**: Contextual upgrade recommendations when approaching limits +4. **Feature Gates**: Locked sections for premium features + +## Admin Features Page + +Located at `/admin/features`: + +- View all 30 features in categorized table +- Toggle features on/off globally +- Filter by category +- Search by name/code +- View tier requirements + +## Migration + +The features are seeded via Alembic migration: + +``` +alembic/versions/n2c3d4e5f6a7_add_features_table.py +``` + +This creates: +- `features` table with 30 default features +- `vendor_feature_overrides` table for per-vendor exceptions + +## Testing + +Unit tests located in: +- `tests/unit/services/test_feature_service.py` +- `tests/unit/services/test_usage_service.py` + +Run tests: +```bash +pytest tests/unit/services/test_feature_service.py -v +pytest tests/unit/services/test_usage_service.py -v +``` + +## Architecture Compliance + +All JavaScript files follow architecture rules: +- JS-003: Alpine components use `vendor*` naming convention +- JS-005: Init guards prevent duplicate initialization +- JS-006: Async operations have try/catch error handling +- JS-008: API calls use `apiClient` (not raw `fetch()`) +- JS-009: Notifications use `Utils.showToast()` + +## Related Documentation + +- [Subscription Billing](../features/subscription-billing.md) - Core subscription system +- [Subscription Workflow Plan](./subscription-workflow-plan.md) - Implementation roadmap diff --git a/docs/implementation/subscription-workflow-plan.md b/docs/implementation/subscription-workflow-plan.md index d14f507d..7010087a 100644 --- a/docs/implementation/subscription-workflow-plan.md +++ b/docs/implementation/subscription-workflow-plan.md @@ -294,61 +294,114 @@ class VendorAddOn(Base): ## 5. Implementation Phases -### Phase 1: Database & Core (Day 1-2) -- [ ] Add `tier_id` FK to VendorSubscription -- [ ] Create migration with data backfill -- [ ] Update subscription service to use tier relationship -- [ ] Update admin subscription endpoints +**Last Updated:** December 31, 2025 -### Phase 2: Admin Vendor Page (Day 2-3) -- [ ] Add subscription card to vendor detail page -- [ ] Show usage meters (orders, products, team) +### Phase 1: Database & Core (COMPLETED) +- [x] Add `tier_id` FK to VendorSubscription +- [x] Create migration with data backfill +- [x] Update subscription service to use tier relationship +- [x] Update admin subscription endpoints +- [x] **NEW:** Add Feature model with 30 features across 8 categories +- [x] **NEW:** Create FeatureService with caching for tier-based feature checking +- [x] **NEW:** Add UsageService for limit tracking and upgrade recommendations + +### Phase 2: Admin Vendor Page (PARTIALLY COMPLETE) +- [x] Add subscription card to vendor detail page +- [x] Show usage meters (orders, products, team) - [ ] Add "Edit Subscription" modal - [ ] Implement tier change API (admin) +- [x] **NEW:** Add Admin Features page (`/admin/features`) +- [x] **NEW:** Admin features API (list, update, toggle) -### Phase 3: Vendor Billing Page (Day 3-4) -- [ ] Create `/vendor/{code}/billing` page -- [ ] Show current plan and usage -- [ ] Add tier comparison/change UI -- [ ] Implement tier change API (vendor) -- [ ] Add Stripe checkout integration for upgrades +### Phase 3: Vendor Billing Page (COMPLETED) +- [x] Create `/vendor/{code}/billing` page +- [x] Show current plan and usage +- [x] Add tier comparison/change UI +- [x] Implement tier change API (vendor) +- [x] Add Stripe checkout integration for upgrades +- [x] **NEW:** Add feature gate macros for templates +- [x] **NEW:** Add Alpine.js feature store +- [x] **NEW:** Add Alpine.js upgrade prompts store +- [x] **FIX:** Resolved 89 JS architecture violations (JS-005 through JS-009) -### Phase 4: Add-ons (Day 4-5) -- [ ] Seed add-on products in database -- [ ] Add "Available Add-ons" section to billing page -- [ ] Implement add-on purchase flow -- [ ] Create VendorAddOn management -- [ ] Add contextual upsell prompts +### Phase 4: Add-ons (COMPLETED) +- [x] Seed add-on products in database +- [x] Add "Available Add-ons" section to billing page +- [x] Implement add-on purchase flow +- [x] Create VendorAddOn management (via billing page) +- [x] Add contextual upsell prompts +- [x] **FIX:** Fix Stripe webhook to create VendorAddOn records -### Phase 5: Polish & Testing (Day 5-6) +### Phase 5: Polish & Testing (IN PROGRESS) - [ ] Email notifications for tier changes -- [ ] Webhook handling for Stripe events -- [ ] Usage limit enforcement updates -- [ ] End-to-end testing -- [ ] Documentation +- [x] Webhook handling for Stripe events +- [x] Usage limit enforcement updates +- [ ] End-to-end testing (manual testing required) +- [x] Documentation (feature-gating-system.md created) + +### Phase 6: Remaining Work (NEW) +- [ ] Admin tier change modal (upgrade/downgrade vendors) +- [ ] Admin subscription override UI (custom limits for enterprise) +- [ ] Trial extension from admin panel +- [ ] Email notifications for tier changes +- [ ] Email notifications for approaching limits +- [ ] Grace period handling for failed payments +- [ ] Integration tests for full billing workflow +- [ ] Stripe test mode checkout verification --- -## 6. Files to Create/Modify +## 6. Files Created/Modified -### New Files -| File | Purpose | -|------|---------| -| `app/templates/vendor/billing.html` | Vendor billing page | -| `static/vendor/js/billing.js` | Billing page JS | -| `app/api/v1/vendor/billing.py` | Vendor billing endpoints | -| `app/services/addon_service.py` | Add-on management | +**Last Updated:** December 31, 2025 + +### New Files (Created) +| File | Purpose | Status | +|------|---------|--------| +| `app/templates/vendor/billing.html` | Vendor billing page | DONE | +| `static/vendor/js/billing.js` | Billing page JS | DONE | +| `app/api/v1/vendor/billing.py` | Vendor billing endpoints | DONE | +| `models/database/feature.py` | Feature & VendorFeatureOverride models | DONE | +| `app/services/feature_service.py` | Feature access control service | DONE | +| `app/services/usage_service.py` | Usage tracking & limits service | DONE | +| `app/core/feature_gate.py` | @require_feature decorator & dependency | DONE | +| `app/api/v1/vendor/features.py` | Vendor features API | DONE | +| `app/api/v1/vendor/usage.py` | Vendor usage API | DONE | +| `app/api/v1/admin/features.py` | Admin features API | DONE | +| `app/templates/admin/features.html` | Admin features management page | DONE | +| `app/templates/shared/macros/feature_gate.html` | Jinja2 feature gate macros | DONE | +| `static/shared/js/feature-store.js` | Alpine.js feature store | DONE | +| `static/shared/js/upgrade-prompts.js` | Alpine.js upgrade prompts | DONE | +| `alembic/versions/n2c3d4e5f6a7_add_features_table.py` | Features migration | DONE | +| `docs/implementation/feature-gating-system.md` | Feature gating documentation | DONE | ### Modified Files -| File | Changes | -|------|---------| -| `models/database/subscription.py` | Add tier_id FK | -| `app/templates/admin/vendor-detail.html` | Add subscription card | -| `static/admin/js/vendor-detail.js` | Load subscription data | -| `app/api/v1/admin/vendors.py` | Include subscription in response | -| `app/api/v1/admin/subscriptions.py` | Add tier change endpoint | -| `app/services/subscription_service.py` | Tier change logic | -| `app/templates/vendor/partials/sidebar.html` | Add Billing link | +| File | Changes | Status | +|------|---------|--------| +| `models/database/subscription.py` | Add tier_id FK | DONE | +| `models/database/__init__.py` | Export Feature models | DONE | +| `app/templates/admin/vendor-detail.html` | Add subscription card | DONE | +| `static/admin/js/vendor-detail.js` | Load subscription data | DONE | +| `app/api/v1/admin/vendors.py` | Include subscription in response | DONE | +| `app/api/v1/admin/__init__.py` | Register features router | DONE | +| `app/api/v1/vendor/__init__.py` | Register features/usage routers | DONE | +| `app/services/subscription_service.py` | Tier change logic | DONE | +| `app/templates/vendor/partials/sidebar.html` | Add Billing link | DONE | +| `app/templates/vendor/base.html` | Load feature/upgrade stores | DONE | +| `app/templates/vendor/dashboard.html` | Add tier badge & usage bars | DONE | +| `app/handlers/stripe_webhook.py` | Create VendorAddOn on purchase | DONE | +| `app/routes/admin_pages.py` | Add features page route | DONE | +| `static/shared/js/api-client.js` | Add postFormData() & getBlob() | DONE | + +### Architecture Fixes (48 files) +| Rule | Files Fixed | Description | +|------|-------------|-------------| +| JS-003 | billing.js | Rename billingData→vendorBilling | +| JS-005 | 15 files | Add init guards | +| JS-006 | 39 files | Add try/catch to async init | +| JS-008 | 5 files | Use apiClient not fetch | +| JS-009 | 30 files | Use Utils.showToast | +| TPL-009 | validate_architecture.py | Check vendor templates too | --- diff --git a/mkdocs.yml b/mkdocs.yml index 75691c83..2e84912c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -161,6 +161,7 @@ nav: - Order Item Exceptions: implementation/order-item-exceptions.md - Product Suppliers Table: implementation/product-suppliers-table.md - Subscription Workflow: implementation/subscription-workflow-plan.md + - Feature Gating System: implementation/feature-gating-system.md - Platform Marketing Homepage: implementation/platform-marketing-homepage.md - Unified Order View: implementation/unified-order-view.md - VAT Invoice Feature: implementation/vat-invoice-feature.md