Add subcription feature 6
This commit is contained in:
361
SUBSCRIPTION_ARCHITECTURE_REDESIGN.md
Normal file
361
SUBSCRIPTION_ARCHITECTURE_REDESIGN.md
Normal file
@@ -0,0 +1,361 @@
|
||||
# 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:
|
||||
|
||||
```python
|
||||
# ✅ 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
|
||||
|
||||
```python
|
||||
# ✅ 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
|
||||
|
||||
```python
|
||||
# ✅ 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"
|
||||
)
|
||||
```
|
||||
|
||||
```python
|
||||
# ✅ 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
|
||||
|
||||
```typescript
|
||||
// ✅ 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 🚀**
|
||||
Reference in New Issue
Block a user