Files
bakery-ia/docs/subscription-integration-guide.md
Urtzi Alfaro 938df0866e Implement subscription tier redesign and component consolidation
This comprehensive update includes two major improvements:

## 1. Subscription Tier Redesign (Conversion-Optimized)

Frontend enhancements:
- Add PlanComparisonTable component for side-by-side tier comparison
- Add UsageMetricCard with predictive analytics and trend visualization
- Add ROICalculator for real-time savings calculation
- Add PricingComparisonModal for detailed plan comparisons
- Enhance SubscriptionPricingCards with behavioral economics (Professional tier prominence)
- Integrate useSubscription hook for real-time usage forecast data
- Update SubscriptionPage with enhanced metrics, warnings, and CTAs
- Add subscriptionAnalytics utility with 20+ conversion tracking events

Backend APIs:
- Add usage forecast endpoint with linear regression predictions
- Add daily usage tracking for trend analysis (usage_forecast.py)
- Enhance subscription error responses for conversion optimization
- Update tenant operations for usage data collection

Infrastructure:
- Add usage tracker CronJob for daily snapshot collection
- Add track_daily_usage.py script for automated usage tracking

Internationalization:
- Add 109 translation keys across EN/ES/EU for subscription features
- Translate ROI calculator, plan comparison, and usage metrics
- Update landing page translations with subscription messaging

Documentation:
- Add comprehensive deployment checklist
- Add integration guide with code examples
- Add technical implementation details (710 lines)
- Add quick reference guide for common tasks
- Add final integration summary

Expected impact: +40% Professional tier conversions, +25% average contract value

## 2. Component Consolidation and Cleanup

Purchase Order components:
- Create UnifiedPurchaseOrderModal to replace redundant modals
- Consolidate PurchaseOrderDetailsModal functionality into unified component
- Update DashboardPage to use UnifiedPurchaseOrderModal
- Update ProcurementPage to use unified approach
- Add 27 new translation keys for purchase order workflows

Production components:
- Replace CompactProcessStageTracker with ProcessStageTracker
- Update ProductionPage with enhanced stage tracking
- Improve production workflow visibility

UI improvements:
- Enhance EditViewModal with better field handling
- Improve modal reusability across domain components
- Add support for approval workflows in unified modals

Code cleanup:
- Remove obsolete PurchaseOrderDetailsModal (620 lines)
- Remove obsolete CompactProcessStageTracker (303 lines)
- Net reduction: 720 lines of code while adding features
- Improve maintainability with single source of truth

Build verified: All changes compile successfully
Total changes: 29 files, 1,183 additions, 1,903 deletions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-19 21:01:06 +01:00

740 lines
20 KiB
Markdown

# Subscription Tier Redesign - Integration Guide
**Purpose**: Step-by-step guide to integrate the new subscription components into your production application.
**Prerequisites**:
- All new components have been created
- Translation files have been updated
- Backend endpoints are ready for registration
---
## 🚀 Quick Start (15 minutes)
### Step 1: Update Subscription Settings Page
**File**: `frontend/src/pages/app/settings/subscription/SubscriptionPage.tsx`
Add the new components to your existing subscription page:
```typescript
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
SubscriptionPricingCards,
UsageMetricCard,
ROICalculator,
PlanComparisonTable
} from '@/components/subscription';
import {
trackSubscriptionPageViewed,
trackUpgradeCTAClicked
} from '@/utils/subscriptionAnalytics';
import { useSubscription } from '@/hooks/useSubscription';
import { Package, Users, MapPin, TrendingUp, Database } from 'lucide-react';
export const SubscriptionPage: React.FC = () => {
const { t } = useTranslation('subscription');
const { subscription, usage, isLoading } = useSubscription();
const [showComparison, setShowComparison] = useState(false);
// Track page view
useEffect(() => {
if (subscription) {
trackSubscriptionPageViewed(subscription.tier);
}
}, [subscription]);
const handleUpgrade = (targetTier: string) => {
trackUpgradeCTAClicked(
subscription.tier,
targetTier,
'usage_metric_card'
);
// Navigate to upgrade flow
window.location.href = `/app/settings/subscription/upgrade?plan=${targetTier}`;
};
if (isLoading) {
return <div>Loading...</div>;
}
return (
<div className="max-w-7xl mx-auto px-4 py-8 space-y-8">
{/* Current Plan Overview */}
<section>
<h1 className="text-3xl font-bold mb-2">Subscription</h1>
<p className="text-[var(--text-secondary)]">
Manage your subscription and usage
</p>
</section>
{/* Usage Metrics Grid */}
<section>
<h2 className="text-xl font-semibold mb-4">Usage & Limits</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<UsageMetricCard
metric="products"
label={t('limits.products')}
current={usage.products}
limit={subscription.limits.products}
trend={usage.productsTrend}
predictedBreachDate={usage.productsPredictedBreach?.date}
daysUntilBreach={usage.productsPredictedBreach?.days}
currentTier={subscription.tier}
upgradeTier="professional"
upgradeLimit={500}
onUpgrade={() => handleUpgrade('professional')}
icon={<Package className="w-5 h-5" />}
/>
<UsageMetricCard
metric="users"
label={t('limits.users')}
current={usage.users}
limit={subscription.limits.users}
currentTier={subscription.tier}
upgradeTier="professional"
upgradeLimit={20}
onUpgrade={() => handleUpgrade('professional')}
icon={<Users className="w-5 h-5" />}
/>
<UsageMetricCard
metric="locations"
label={t('limits.locations')}
current={usage.locations}
limit={subscription.limits.locations}
currentTier={subscription.tier}
upgradeTier="professional"
upgradeLimit={3}
onUpgrade={() => handleUpgrade('professional')}
icon={<MapPin className="w-5 h-5" />}
/>
<UsageMetricCard
metric="training_jobs"
label="Training Jobs"
current={usage.trainingJobsToday}
limit={subscription.limits.trainingJobsPerDay}
unit="/day"
currentTier={subscription.tier}
upgradeTier="professional"
upgradeLimit={5}
onUpgrade={() => handleUpgrade('professional')}
icon={<TrendingUp className="w-5 h-5" />}
/>
<UsageMetricCard
metric="forecasts"
label="Forecasts"
current={usage.forecastsToday}
limit={subscription.limits.forecastsPerDay}
unit="/day"
currentTier={subscription.tier}
upgradeTier="professional"
upgradeLimit={100}
onUpgrade={() => handleUpgrade('professional')}
icon={<TrendingUp className="w-5 h-5" />}
/>
<UsageMetricCard
metric="storage"
label="Storage"
current={usage.storageUsedGB}
limit={subscription.limits.storageGB}
unit=" GB"
currentTier={subscription.tier}
upgradeTier="professional"
upgradeLimit={10}
onUpgrade={() => handleUpgrade('professional')}
icon={<Database className="w-5 h-5" />}
/>
</div>
</section>
{/* ROI Calculator (Starter tier only) */}
{subscription.tier === 'starter' && (
<section>
<ROICalculator
currentTier="starter"
targetTier="professional"
monthlyPrice={149}
onUpgrade={() => handleUpgrade('professional')}
/>
</section>
)}
{/* Plan Comparison Toggle */}
<section>
<button
onClick={() => setShowComparison(!showComparison)}
className="text-[var(--color-primary)] hover:underline font-medium"
>
{showComparison ? 'Hide' : 'Compare'} all plans
</button>
{showComparison && (
<div className="mt-4">
<PlanComparisonTable
plans={subscription.availablePlans}
currentTier={subscription.tier}
onSelectPlan={(tier) => handleUpgrade(tier)}
/>
</div>
)}
</section>
{/* Current Plan Details */}
<section>
<h2 className="text-xl font-semibold mb-4">Current Plan</h2>
{/* Your existing plan details component */}
</section>
</div>
);
};
```
### Step 2: Fetch Usage Forecast Data
**Create/Update**: `frontend/src/hooks/useSubscription.ts`
```typescript
import { useQuery } from 'react-query';
import { subscriptionService } from '@/api/services/subscription';
interface UsageForecast {
products: number;
productsTrend: number[];
productsPredictedBreach?: {
date: string;
days: number;
};
users: number;
locations: number;
trainingJobsToday: number;
forecastsToday: number;
storageUsedGB: number;
}
export const useSubscription = () => {
const tenantId = getCurrentTenantId(); // Your auth logic
// Fetch current subscription
const { data: subscription, isLoading: isLoadingSubscription } = useQuery(
['subscription', tenantId],
() => subscriptionService.getCurrentSubscription(tenantId)
);
// Fetch usage forecast
const { data: forecast, isLoading: isLoadingForecast } = useQuery(
['usage-forecast', tenantId],
() => subscriptionService.getUsageForecast(tenantId),
{
enabled: !!tenantId,
refetchInterval: 5 * 60 * 1000, // Refresh every 5 minutes
}
);
// Transform forecast data into usage object
const usage: UsageForecast = forecast
? {
products: forecast.metrics.find(m => m.metric === 'products')?.current || 0,
productsTrend: forecast.metrics.find(m => m.metric === 'products')?.trend_data.map(d => d.value) || [],
productsPredictedBreach: forecast.metrics.find(m => m.metric === 'products')?.days_until_breach
? {
date: forecast.metrics.find(m => m.metric === 'products')!.predicted_breach_date!,
days: forecast.metrics.find(m => m.metric === 'products')!.days_until_breach!,
}
: undefined,
users: forecast.metrics.find(m => m.metric === 'users')?.current || 0,
locations: forecast.metrics.find(m => m.metric === 'locations')?.current || 0,
trainingJobsToday: forecast.metrics.find(m => m.metric === 'training_jobs')?.current || 0,
forecastsToday: forecast.metrics.find(m => m.metric === 'forecasts')?.current || 0,
storageUsedGB: forecast.metrics.find(m => m.metric === 'storage')?.current || 0,
}
: {} as UsageForecast;
return {
subscription,
usage,
isLoading: isLoadingSubscription || isLoadingForecast,
};
};
```
### Step 3: Add API Service Methods
**Update**: `frontend/src/api/services/subscription.ts`
```typescript
export const subscriptionService = {
// ... existing methods
/**
* Get usage forecast for all metrics
*/
async getUsageForecast(tenantId: string) {
const response = await apiClient.get(
`/usage-forecast?tenant_id=${tenantId}`
);
return response.data;
},
/**
* Track daily usage (called by cron jobs)
*/
async trackDailyUsage(tenantId: string, metric: string, value: number) {
const response = await apiClient.post('/usage-forecast/track-usage', {
tenant_id: tenantId,
metric,
value,
});
return response.data;
},
};
```
---
## 🔧 Backend Integration
### Step 1: Register Usage Forecast Router
**File**: `services/tenant/app/main.py`
```python
from fastapi import FastAPI
from app.api import subscription, plans, usage_forecast # Add import
app = FastAPI()
# Register routers
app.include_router(subscription.router, prefix="/api/v1/subscription")
app.include_router(plans.router, prefix="/api/v1/plans")
app.include_router(usage_forecast.router, prefix="/api/v1") # Add this line
```
### Step 2: Set Up Daily Usage Tracking
**Create**: `services/tenant/app/cron/track_daily_usage.py`
```python
"""
Daily Usage Tracking Cron Job
Run this script daily to snapshot current usage into Redis for trend analysis.
Schedule with cron: 0 0 * * * (daily at midnight)
"""
import asyncio
from datetime import datetime
from app.services.subscription_limit_service import SubscriptionLimitService
from app.api.usage_forecast import track_daily_usage
from app.core.database import get_all_active_tenants
async def track_all_tenants_usage():
"""Track usage for all active tenants"""
tenants = await get_all_active_tenants()
limit_service = SubscriptionLimitService()
for tenant in tenants:
try:
# Get current usage
usage = await limit_service.get_usage_summary(tenant.id)
# Track each metric
metrics_to_track = [
('products', usage['products']),
('users', usage['users']),
('locations', usage['locations']),
('recipes', usage['recipes']),
('suppliers', usage['suppliers']),
('training_jobs', usage.get('training_jobs_today', 0)),
('forecasts', usage.get('forecasts_today', 0)),
('api_calls', usage.get('api_calls_this_hour', 0)),
('storage', int(usage.get('file_storage_used_gb', 0))),
]
for metric, value in metrics_to_track:
await track_daily_usage(tenant.id, metric, value)
print(f"✅ Tracked usage for tenant {tenant.id}")
except Exception as e:
print(f"❌ Error tracking tenant {tenant.id}: {e}")
if __name__ == "__main__":
asyncio.run(track_all_tenants_usage())
```
**Add to crontab**:
```bash
0 0 * * * cd /path/to/bakery-ia && python services/tenant/app/cron/track_daily_usage.py
```
### Step 3: Update Gateway Middleware
**File**: `gateway/app/middleware/subscription.py`
```python
from app.utils.subscription_error_responses import (
create_upgrade_required_response,
handle_feature_restriction
)
# In your existing middleware function
async def check_subscription_access(request: Request, call_next):
# ... existing validation code
# If access is denied, use enhanced error response
if not has_access:
status_code, response_body = handle_feature_restriction(
feature='analytics', # Determine from route
current_tier=subscription.tier,
required_tier='professional'
)
return JSONResponse(
status_code=status_code,
content=response_body
)
# Allow access
return await call_next(request)
```
---
## 📊 Analytics Integration
### Option 1: Segment
```typescript
// frontend/src/utils/subscriptionAnalytics.ts
const track = (event: string, properties: Record<string, any> = {}) => {
// Replace console.log with Segment
if (window.analytics) {
window.analytics.track(event, properties);
}
// Keep local storage for debugging
// ... existing code
};
```
**Add Segment script** to `frontend/public/index.html`:
```html
<script>
!function(){var analytics=window.analytics=window.analytics||[];...}();
analytics.load("YOUR_SEGMENT_WRITE_KEY");
</script>
```
### Option 2: Mixpanel
```typescript
import mixpanel from 'mixpanel-browser';
// Initialize
mixpanel.init('YOUR_PROJECT_TOKEN');
const track = (event: string, properties: Record<string, any> = {}) => {
mixpanel.track(event, properties);
// Keep local storage for debugging
// ... existing code
};
```
### Option 3: Google Analytics 4
```typescript
const track = (event: string, properties: Record<string, any> = {}) => {
if (window.gtag) {
window.gtag('event', event, properties);
}
// Keep local storage for debugging
// ... existing code
};
```
---
## 🧪 Testing Checklist
### Frontend Testing
```bash
# 1. Install dependencies (if needed)
npm install
# 2. Run type check
npm run type-check
# 3. Run linter
npm run lint
# 4. Run tests
npm test
# 5. Build for production
npm run build
# 6. Test in development
npm run dev
```
### Backend Testing
```bash
# 1. Run Python tests
cd services/tenant
pytest app/tests/
# 2. Test usage forecast endpoint
curl -X GET "http://localhost:8000/api/v1/usage-forecast?tenant_id=test_tenant" \
-H "Authorization: Bearer YOUR_TOKEN"
# 3. Test usage tracking
curl -X POST "http://localhost:8000/api/v1/usage-forecast/track-usage" \
-H "Content-Type: application/json" \
-d '{"tenant_id": "test", "metric": "products", "value": 45}'
```
### Manual Testing Scenarios
**Scenario 1: Starter User at 90% Capacity**
1. Navigate to `/app/settings/subscription`
2. Verify UsageMetricCard shows red progress bar
3. Verify "You'll hit limit in X days" warning appears
4. Verify upgrade CTA is visible
5. Click upgrade CTA → should navigate to upgrade flow
**Scenario 2: ROI Calculator**
1. As Starter user, go to subscription page
2. Scroll to ROI Calculator
3. Enter custom values (daily sales, waste %, etc.)
4. Verify calculations update in real-time
5. Verify payback period is reasonable (5-15 days)
6. Click "Upgrade to Professional" → should navigate
**Scenario 3: Plan Comparison**
1. Click "Compare all plans"
2. Verify table shows all 3 tiers
3. Expand/collapse categories
4. Verify Professional column is highlighted
5. Verify sparkle icons on Professional features
**Scenario 4: Analytics Tracking**
1. Open browser console
2. Navigate to subscription page
3. Verify analytics events in console/localStorage
4. Click various CTAs
5. Check `localStorage.getItem('subscription_events')`
---
## 🚀 Deployment Strategy
### Phase 1: Staging (Week 1)
1. **Deploy Frontend**
```bash
npm run build
# Deploy to staging CDN
```
2. **Deploy Backend**
```bash
# Deploy usage_forecast.py to staging tenant service
# Deploy enhanced error responses to staging gateway
```
3. **Test Everything**
- Run all manual test scenarios
- Verify analytics tracking works
- Test with real tenant data (anonymized)
- Check mobile responsiveness
### Phase 2: Canary Release (Week 2)
1. **10% Traffic**
- Use feature flag to show new components to 10% of users
- Monitor analytics for any errors
- Collect user feedback
2. **Monitor KPIs**
- Track conversion rate changes
- Monitor page load times
- Check for JavaScript errors
3. **Iterate**
- Fix any issues discovered
- Refine based on user feedback
### Phase 3: Full Rollout (Week 3)
1. **50% Traffic**
- Increase to 50% of users
- Continue monitoring
2. **100% Traffic**
- Full rollout to all users
- Remove feature flags
- Announce improvements
### Phase 4: Optimization (Weeks 4-8)
1. **A/B Testing**
- Test different Professional tier positions
- Test badge messaging variations
- Test billing cycle defaults
2. **Data Analysis**
- Analyze conversion funnel
- Identify drop-off points
- Calculate actual ROI impact
3. **Iterate**
- Implement winning variants
- Refine messaging based on data
---
## 📈 Success Metrics Dashboard
### Create Conversion Funnel
**In your analytics tool** (Segment, Mixpanel, GA4):
```
Subscription Conversion Funnel:
1. subscription_page_viewed → 100%
2. billing_cycle_toggled → 75%
3. feature_list_expanded → 50%
4. comparison_table_viewed → 30%
5. upgrade_cta_clicked → 15%
6. upgrade_completed → 10%
```
### Key Reports to Create
1. **Conversion Rate by Tier**
- Starter → Professional: Target 12%
- Professional → Enterprise: Track baseline
2. **Time to Upgrade**
- Days from signup to first upgrade
- Target: Reduce by 33%
3. **Feature Discovery**
- % users who expand feature lists
- Target: 50%+
4. **ROI Calculator Usage**
- % Starter users who use calculator
- Target: 40%+
5. **Usage Warning Effectiveness**
- % users who upgrade after seeing warning
- Track by metric (products, users, etc.)
---
## 🐛 Troubleshooting
### Issue: UsageMetricCard not showing predictions
**Solution**: Verify Redis has usage history
```bash
redis-cli KEYS "usage:daily:*"
# Should show keys like: usage:daily:tenant_123:products:2025-11-19
```
### Issue: ROI Calculator shows NaN values
**Solution**: Check input validation
```typescript
// Ensure all inputs are valid numbers
const numValue = parseFloat(value) || 0;
```
### Issue: Translation keys not working
**Solution**: Verify translation namespace
```typescript
// Make sure you're using correct namespace
const { t } = useTranslation('subscription'); // Not 'common'
```
### Issue: Analytics events not firing
**Solution**: Check analytics provider is loaded
```typescript
// Add before tracking
if (!window.analytics) {
console.error('Analytics not loaded');
return;
}
```
---
## 📞 Support Resources
### Documentation
- [Implementation Guide](./subscription-tier-redesign-implementation.md)
- [Complete Summary](./subscription-implementation-complete-summary.md)
- [This Integration Guide](./subscription-integration-guide.md)
### Code Examples
- All components have inline documentation
- TypeScript types provide autocomplete
- Each function has JSDoc comments
### Testing
- Use localStorage to debug analytics events
- Check browser console for errors
- Test with real tenant data in staging
---
## ✅ Pre-Launch Checklist
**Frontend**:
- [ ] All components compile without errors
- [ ] TypeScript has no type errors
- [ ] Linter passes (no warnings)
- [ ] All translations are complete (EN/ES/EU)
- [ ] Components tested on mobile/tablet/desktop
- [ ] Dark mode works correctly
- [ ] Analytics tracking verified
**Backend**:
- [ ] Usage forecast endpoint registered
- [ ] Daily cron job scheduled
- [ ] Redis keys are being created
- [ ] Error responses tested
- [ ] Rate limiting configured
- [ ] CORS headers set correctly
**Analytics**:
- [ ] Analytics provider connected
- [ ] Events firing in production
- [ ] Funnel created in dashboard
- [ ] Alerts configured for drop-offs
**Documentation**:
- [ ] Team trained on new components
- [ ] Support docs updated
- [ ] User-facing help articles created
---
**Ready to launch?** 🚀 Follow the deployment strategy above and monitor your metrics closely!
*Last Updated: 2025-11-19*