Files
bakery-ia/SUBSCRIPTION_ARCHITECTURE_REDESIGN.md
2026-01-16 15:19:34 +01:00

15 KiB

Subscription System Architecture Redesign - IMPLEMENTED

Overview

This document outlines the completed implementation of the comprehensive subscription system architecture redesign. The implementation improves organization, maintainability, and separation of concerns while respecting the existing service-based client architecture.

Current State - FULLY IMPLEMENTED

Issues Resolved

  1. Mixed Concerns: Subscription endpoints are now properly separated from tenant management
  2. Inconsistent URL Patterns: All endpoints now use consistent /tenants/{tenant_id}/subscription/* structure
  3. Poor Organization: Subscription operations are now centralized in one API file
  4. Middleware Dependencies: All middleware now uses updated URL patterns
  5. Client Layer Confusion: Tenant client contains only tenant-specific methods, subscription methods use proper patterns

New Architecture Design - FULLY IMPLEMENTED

API Structure & URL Patterns

Public Endpoints (No Authentication) - IMPLEMENTED

GET    /api/v1/plans                          - Get all available plans
GET    /api/v1/plans/{tier}                  - Get specific plan details
GET    /api/v1/plans/{tier}/features         - Get plan features
GET    /api/v1/plans/{tier}/limits           - Get plan limits
GET    /api/v1/plans/compare                 - Compare all plans

Registration Flow (No Tenant Context) - IMPLEMENTED

POST   /api/v1/registration/payment-setup    - Start registration with payment
POST   /api/v1/registration/complete         - Complete registration after 3DS
GET    /api/v1/registration/state/{state_id} - Check registration state

Tenant-Dependent Subscription Endpoints - IMPLEMENTED

GET    /api/v1/tenants/{tenant_id}/subscription/status         - Get subscription status
GET    /api/v1/tenants/{tenant_id}/subscription/details        - Get full subscription details
GET    /api/v1/tenants/{tenant_id}/subscription/tier           - Get subscription tier (cached)
GET    /api/v1/tenants/{tenant_id}/subscription/limits         - Get subscription limits
GET    /api/v1/tenants/{tenant_id}/subscription/usage          - Get usage summary
GET    /api/v1/tenants/{tenant_id}/subscription/features/{feature} - Check feature access

# Subscription Management
POST   /api/v1/tenants/{tenant_id}/subscription/cancel         - Cancel subscription
POST   /api/v1/tenants/{tenant_id}/subscription/reactivate     - Reactivate subscription
GET    /api/v1/tenants/{tenant_id}/subscription/validate-upgrade/{new_plan} - Validate upgrade
POST   /api/v1/tenants/{tenant_id}/subscription/upgrade        - Upgrade subscription

# Quota & Limit Checks
GET    /api/v1/tenants/{tenant_id}/subscription/limits/locations - Check location limits
GET    /api/v1/tenants/{tenant_id}/subscription/limits/products  - Check product limits
GET    /api/v1/tenants/{tenant_id}/subscription/limits/users     - Check user limits
GET    /api/v1/tenants/{tenant_id}/subscription/limits/recipes   - Check recipe limits
GET    /api/v1/tenants/{tenant_id}/subscription/limits/suppliers - Check supplier limits

# Payment Management
GET    /api/v1/tenants/{tenant_id}/subscription/payment-method  - Get payment method
POST   /api/v1/tenants/{tenant_id}/subscription/payment-method - Update payment method
GET    /api/v1/tenants/{tenant_id}/subscription/invoices        - Get invoices

Service Layer Organization - IMPLEMENTED

subscription.py - All subscription-related endpoints

  • Registration flow endpoints
  • Tenant-dependent subscription endpoints
  • Subscription management endpoints
  • Quota and limit checks
  • Payment management endpoints

tenant_operations.py - Only tenant-centric operations

  • Tenant creation/management
  • Tenant hierarchy operations
  • Tenant settings management
  • Tenant location management

plans.py - Public plan information (unchanged)

Implementation Status - COMPLETE

Phase 1: Backend API Reorganization - COMPLETED

Step 1: Move Subscription Endpoints - DONE

  • Moved all subscription endpoints from tenant_operations.py to subscription.py
  • Implemented new URL patterns with consistent structure
  • Updated all endpoint implementations to use new paths

Files Modified:

  • services/tenant/app/api/subscription.py - All subscription endpoints added
  • services/tenant/app/api/tenant_operations.py - Subscription endpoints removed

Step 2: Update Tenant Service Main.py - DONE

  • Ensured proper router inclusion for new subscription endpoints
  • Removed old subscription endpoints from tenant operations router

Files Modified:

  • services/tenant/app/main.py - Router inclusion updated

Phase 2: Update Tenant Client - COMPLETED

Step 3: Update Tenant Client URL Patterns - DONE

All subscription-related methods in shared/clients/tenant_client.py updated:

# ✅ All methods already updated with new URL patterns
async def get_subscription_status(self, tenant_id: str) -> Optional[Dict[str, Any]]:
    result = await self.get(f"tenants/{tenant_id}/subscription/status")
    return result

async def get_subscription_details(self, tenant_id: str) -> Optional[Dict[str, Any]]:
    result = await self.get(f"tenants/{tenant_id}/subscription/details")
    return result

# ✅ All other subscription methods similarly updated

Files Modified:

  • shared/clients/tenant_client.py - All subscription methods updated

Phase 3: Gateway Updates - COMPLETED

Step 4: Update Gateway Routes - DONE

# ✅ All gateway routes updated with new patterns
@router.get("/plans")
@router.get("/plans/{tier}")
@router.get("/plans/{tier}/features")
@router.get("/plans/{tier}/limits")
@router.get("/plans/compare")

# ✅ Registration flow
@router.post("/registration/payment-setup")
@router.post("/registration/complete")
@router.get("/registration/state/{state_id}")

# ✅ Tenant subscription endpoints
@router.get("/tenants/{tenant_id}/subscription/status")
@router.get("/tenants/{tenant_id}/subscription/details")
@router.get("/tenants/{tenant_id}/subscription/tier")
@router.get("/tenants/{tenant_id}/subscription/limits")
@router.get("/tenants/{tenant_id}/subscription/usage")
@router.get("/tenants/{tenant_id}/subscription/features/{feature}")
@router.post("/tenants/{tenant_id}/subscription/cancel")
@router.post("/tenants/{tenant_id}/subscription/reactivate")
@router.get("/tenants/{tenant_id}/subscription/validate-upgrade/{new_plan}")
@router.post("/tenants/{tenant_id}/subscription/upgrade")
@router.get("/tenants/{tenant_id}/subscription/limits/locations")
@router.get("/tenants/{tenant_id}/subscription/limits/products")
@router.get("/tenants/{tenant_id}/subscription/limits/users")
@router.get("/tenants/{tenant_id}/subscription/limits/recipes")
@router.get("/tenants/{tenant_id}/subscription/limits/suppliers")
@router.get("/tenants/{tenant_id}/subscription/payment-method")
@router.post("/tenants/{tenant_id}/subscription/payment-method")
@router.get("/tenants/{tenant_id}/subscription/invoices")

Files Modified:

  • gateway/app/routes/subscription.py - All gateway routes updated

Step 5: Update Middleware URL Patterns - DONE

# ✅ In gateway/app/middleware/auth.py
async def _get_tenant_subscription_tier(self, tenant_id: str, request: Request) -> Optional[str]:
    response = await self._make_request(
        "GET",
        f"{settings.TENANT_SERVICE_URL}/api/v1/tenants/{tenant_id}/subscription/tier"
    )
# ✅ In gateway/app/middleware/read_only_mode.py
async def check_subscription_status(self, tenant_id: str, authorization: str) -> dict:
    response = await self._make_request(
        "GET",
        f"{settings.TENANT_SERVICE_URL}/api/v1/tenants/{tenant_id}/subscription/status"
    )

Files Modified:

  • gateway/app/middleware/subscription.py - URL patterns updated
  • gateway/app/middleware/auth.py - Subscription tier lookup URL updated
  • gateway/app/middleware/read_only_mode.py - Subscription status check URL updated
  • gateway/app/middleware/rate_limiting.py - Subscription tier URL fixed
  • gateway/app/routes/tenant.py - Removed conflicting wildcard route

Phase 4: Frontend Updates - COMPLETED

Step 6: Update Frontend Subscription Service - DONE

// ✅ In frontend/src/api/services/subscription.ts
export class SubscriptionService {
  // ✅ All methods updated to use new URL patterns

  async getSubscriptionStatus(tenantId: string): Promise<UsageSummary> {
    return apiClient.get<UsageSummary>(`/tenants/${tenantId}/subscription/status`);
  }

  async getSubscriptionDetails(tenantId: string): Promise<any> {
    return apiClient.get(`/tenants/${tenantId}/subscription/details`);
  }

  async getSubscriptionTier(tenantId: string): Promise<string> {
    return apiClient.get(`/tenants/${tenantId}/subscription/tier`);
  }

  async getUsageSummary(tenantId: string): Promise<UsageSummary> {
    return apiClient.get<UsageSummary>(`/tenants/${tenantId}/subscription/usage`);
  }

  async checkFeatureAccess(tenantId: string, featureName: string): Promise<FeatureCheckResponse> {
    return apiClient.get<FeatureCheckResponse>(`/tenants/${tenantId}/subscription/features/${featureName}`);
  }

  async cancelSubscription(tenantId: string, reason?: string): Promise<any> {
    return apiClient.post(`/tenants/${tenantId}/subscription/cancel`, { reason });
  }

  async reactivateSubscription(tenantId: string, plan: string = 'starter'): Promise<any> {
    return apiClient.post(`/tenants/${tenantId}/subscription/reactivate`, { plan });
  }

  async validatePlanUpgrade(tenantId: string, newPlan: string): Promise<PlanUpgradeValidation> {
    return apiClient.get<PlanUpgradeValidation>(`/tenants/${tenantId}/subscription/validate-upgrade/${newPlan}`);
  }

  async upgradePlan(tenantId: string, newPlan: string): Promise<PlanUpgradeResult> {
    return apiClient.post<PlanUpgradeResult>(`/tenants/${tenantId}/subscription/upgrade`, { new_plan: newPlan });
  }

  async canAddLocation(tenantId: string): Promise<any> {
    return apiClient.get(`/tenants/${tenantId}/subscription/limits/locations`);
  }

  async canAddProduct(tenantId: string): Promise<any> {
    return apiClient.get(`/tenants/${tenantId}/subscription/limits/products`);
  }

  async canAddUser(tenantId: string): Promise<any> {
    return apiClient.get(`/tenants/${tenantId}/subscription/limits/users`);
  }

  async canAddRecipe(tenantId: string): Promise<any> {
    return apiClient.get(`/tenants/${tenantId}/subscription/limits/recipes`);
  }

  async canAddSupplier(tenantId: string): Promise<any> {
    return apiClient.get(`/tenants/${tenantId}/subscription/limits/suppliers`);
  }

  async getPaymentMethod(tenantId: string): Promise<any> {
    return apiClient.get(`/tenants/${tenantId}/subscription/payment-method`);
  }

  async updatePaymentMethod(tenantId: string, paymentMethodId: string): Promise<any> {
    return apiClient.post(`/tenants/${tenantId}/subscription/payment-method`, { payment_method_id: paymentMethodId });
  }

  async getInvoices(tenantId: string): Promise<any[]> {
    return apiClient.get(`/tenants/${tenantId}/subscription/invoices`);
  }

  // ✅ Registration flow methods
  async startRegistrationPaymentSetup(userData: any): Promise<any> {
    return apiClient.post('/registration/payment-setup', userData);
  }

  async completeRegistration(setupIntentId: string, userData: any): Promise<any> {
    return apiClient.post('/registration/complete', {
      setup_intent_id: setupIntentId,
      user_data: userData
    });
  }
}

Files Modified:

  • frontend/src/api/services/subscription.ts - All URL patterns updated
  • frontend/src/api/services/tenant.ts - Fixed subscription linking endpoint

Additional Fixes - COMPLETED

Service Integration Updates

Files Modified:

  • services/auth/app/utils/subscription_fetcher.py - Fixed subscription details URLs
  • services/auth/app/api/account_deletion.py - Fixed subscription status URL
  • services/inventory/app/api/ingredients.py - Fixed quota check URLs
  • services/tenant/tests/integration/test_subscription_creation_flow.py - Fixed test URLs

Benefits Achieved

  1. Clear Separation of Concerns: Subscription operations are properly separated from tenant management operations
  2. Consistent URL Patterns: All subscription endpoints follow a logical, standardized structure
  3. Better Organization: Easier to find and maintain subscription-related code
  4. Service-Based Architecture: Maintains the constraint of using tenant client only
  5. Improved Maintainability: Changes to subscription logic are localized to one API file
  6. Better Performance: Clear caching strategies for subscription data
  7. Easier Scaling: Subscription endpoints can be scaled independently if needed
  8. Cleaner Codebase: No mixed concerns between tenant and subscription operations

Implementation Summary - COMPLETE

Files Modified

Backend Services:

  • services/tenant/app/api/subscription.py - Add all subscription endpoints
  • services/tenant/app/api/tenant_operations.py - Remove subscription endpoints
  • services/tenant/app/main.py - Update router inclusion

Shared Client Layer:

  • shared/clients/tenant_client.py - Update all subscription methods with new URL patterns

Gateway Layer:

  • gateway/app/routes/subscription.py - Update all gateway routes with new patterns
  • gateway/app/routes/tenant.py - Remove conflicting wildcard route
  • gateway/app/middleware/subscription.py - Update URL patterns
  • gateway/app/middleware/auth.py - Update subscription tier lookup URL
  • gateway/app/middleware/read_only_mode.py - Update subscription status check URL
  • gateway/app/middleware/rate_limiting.py - Fix subscription tier URL

Frontend Layer:

  • frontend/src/api/services/subscription.ts - Update all URL patterns
  • frontend/src/api/services/tenant.ts - Fix subscription linking endpoint

Service Integration:

  • services/auth/app/utils/subscription_fetcher.py - Fix subscription details URLs
  • services/auth/app/api/account_deletion.py - Fix subscription status URL
  • services/inventory/app/api/ingredients.py - Fix quota check URLs
  • services/tenant/tests/integration/test_subscription_creation_flow.py - Fix test URLs

Implementation Order

  1. Backend API Reorganization (Phase 1) - COMPLETED
  2. Update Tenant Client (Phase 2) - COMPLETED
  3. Gateway Updates (Phase 3) - COMPLETED
  4. Frontend Updates (Phase 4) - COMPLETED
  5. Service Integration Fixes - COMPLETED

Verification Status

  • All backend endpoints implemented and tested
  • All client methods updated and verified
  • All gateway routes updated and verified
  • All frontend services updated and verified
  • All middleware updated and verified
  • All service integrations updated and verified
  • No remaining old URL patterns in production code
  • All tests updated to use new patterns

Migration Complete

The subscription system architecture redesign has been fully implemented and is ready for production use. All components are using the new, consistent URL patterns as specified in the architecture redesign. The system maintains proper separation of concerns while respecting the existing service-based client architecture constraint.

Status: PRODUCTION READY 🚀