refactor(demo): Standardize demo account type names across codebase

Standardize demo account type naming from inconsistent variants to clean names:
- individual_bakery, professional_bakery → professional
- central_baker, enterprise_chain → enterprise

This eliminates naming confusion that was causing bugs in the demo session
initialization, particularly for enterprise demo tenants where different
parts of the system used different names for the same concept.

Changes:
- Updated source of truth in demo_session config
- Updated all backend services (middleware, cloning, orchestration)
- Updated frontend types, pages, and stores
- Updated demo session models and schemas
- Removed all backward compatibility code as requested

Related to: Enterprise demo session access fix

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Urtzi Alfaro
2025-11-30 08:48:56 +01:00
parent 2d9fc01515
commit fd657dea02
13 changed files with 2186 additions and 650 deletions

View File

@@ -20,7 +20,7 @@
* Backend: services/demo_session/app/api/schemas.py:10-15 (DemoSessionCreate)
*/
export interface DemoSessionCreate {
demo_account_type: string; // individual_bakery or central_baker
demo_account_type: string; // professional or enterprise
user_id?: string | null; // Optional authenticated user ID
ip_address?: string | null;
user_agent?: string | null;

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,43 @@ import { useEffect } from 'react';
import { useIsAuthenticated } from './auth.store';
import { useTenantActions, useAvailableTenants, useCurrentTenant } from './tenant.store';
import { useIsDemoMode, useDemoSessionId, useDemoAccountType } from '../hooks/useAccessControl';
import { SUBSCRIPTION_TIERS, SubscriptionTier } from '../api/types/subscription';
/**
* Defines the appropriate subscription tier based on demo account type
*/
const getDemoTierForAccountType = (accountType: string | null): SubscriptionTier => {
switch (accountType) {
case 'enterprise':
return SUBSCRIPTION_TIERS.ENTERPRISE;
case 'professional':
default:
return SUBSCRIPTION_TIERS.PROFESSIONAL;
}
};
/**
* Defines appropriate tenant characteristics based on account type
*/
const getTenantDetailsForAccountType = (accountType: string | null) => {
const details = {
professional: {
name: 'Panadería Profesional - Demo',
business_type: 'bakery',
business_model: 'professional',
description: 'Demostración de panadería profesional'
},
enterprise: {
name: 'Red de Panaderías - Demo',
business_type: 'bakery',
business_model: 'enterprise',
description: 'Demostración de cadena de panaderías enterprise'
}
};
const defaultDetails = details.professional;
return details[accountType as keyof typeof details] || defaultDetails;
};
/**
* Hook to automatically initialize tenant data when user is authenticated or in demo mode
@@ -23,60 +60,74 @@ export const useTenantInitializer = () => {
}
}, [isAuthenticated, availableTenants, loadUserTenants]);
// Set up mock tenant for demo mode
// Set up mock tenant for demo mode with appropriate subscription tier
useEffect(() => {
if (isDemoMode && demoSessionId) {
const demoTenantId = localStorage.getItem('demo_tenant_id') || 'demo-tenant-id';
const virtualTenantId = localStorage.getItem('virtual_tenant_id');
const storedTier = localStorage.getItem('subscription_tier');
console.log('🔍 [TenantInitializer] Demo mode detected:', {
isDemoMode,
demoSessionId,
demoTenantId,
virtualTenantId,
demoAccountType,
storedTier,
currentTenant: currentTenant?.id
});
// Guard: If no virtual_tenant_id is available, skip tenant setup
if (!virtualTenantId) {
console.warn('⚠️ [TenantInitializer] No virtual_tenant_id found in localStorage');
return;
}
// Check if current tenant is the demo tenant and is properly set
const isValidDemoTenant = currentTenant &&
typeof currentTenant === 'object' &&
currentTenant.id === demoTenantId;
currentTenant.id === virtualTenantId;
if (!isValidDemoTenant) {
console.log('🔧 [TenantInitializer] Setting up demo tenant...');
const accountTypeName = demoAccountType === 'individual_bakery'
? 'Panadería San Pablo - Demo'
: 'Panadería La Espiga - Demo';
// Determine the appropriate subscription tier based on stored value or account type
const subscriptionTier = storedTier as SubscriptionTier || getDemoTierForAccountType(demoAccountType);
// Get appropriate tenant details based on account type
const tenantDetails = getTenantDetailsForAccountType(demoAccountType);
// Create a complete tenant object matching TenantResponse structure
const mockTenant = {
id: demoTenantId,
name: accountTypeName,
id: virtualTenantId,
name: tenantDetails.name,
subdomain: `demo-${demoSessionId.slice(0, 8)}`,
business_type: demoAccountType === 'individual_bakery' ? 'bakery' : 'central_baker',
business_model: demoAccountType,
business_type: tenantDetails.business_type,
business_model: tenantDetails.business_model,
description: tenantDetails.description,
address: 'Demo Address',
city: 'Madrid',
postal_code: '28001',
phone: null,
is_active: true,
subscription_tier: 'demo',
subscription_plan: subscriptionTier, // New field name
subscription_tier: subscriptionTier, // Deprecated but kept for backward compatibility
ml_model_trained: false,
last_training_date: null,
owner_id: 'demo-user',
created_at: new Date().toISOString(),
};
console.log(`✅ [TenantInitializer] Setting up tenant with tier: ${subscriptionTier}`);
// Set the demo tenant as current
setCurrentTenant(mockTenant);
// **CRITICAL: Also set tenant ID in API client**
// This ensures API requests include the tenant ID header
import('../api/client').then(({ apiClient }) => {
apiClient.setTenantId(demoTenantId);
console.log('✅ [TenantInitializer] Set API client tenant ID:', demoTenantId);
apiClient.setTenantId(virtualTenantId);
console.log('✅ [TenantInitializer] Set API client tenant ID:', virtualTenantId);
});
}
}
}, [isDemoMode, demoSessionId, demoAccountType, currentTenant, setCurrentTenant]);
};
};;