/** * Subscription Service - Mirror backend subscription endpoints */ import { apiClient } from '../client'; import { SubscriptionLimits, FeatureCheckRequest, FeatureCheckResponse, UsageCheckRequest, UsageCheckResponse, UsageSummary, AvailablePlans, PlanUpgradeValidation, PlanUpgradeResult } from '../types/subscription'; export class SubscriptionService { private readonly baseUrl = '/subscriptions'; async getSubscriptionLimits(tenantId: string): Promise { return apiClient.get(`${this.baseUrl}/${tenantId}/limits`); } async checkFeatureAccess( tenantId: string, featureName: string ): Promise { return apiClient.get( `${this.baseUrl}/${tenantId}/features/${featureName}/check` ); } async checkUsageLimit( tenantId: string, resourceType: 'users' | 'sales_records' | 'inventory_items' | 'api_requests', requestedAmount?: number ): Promise { const queryParams = new URLSearchParams(); if (requestedAmount !== undefined) { queryParams.append('requested_amount', requestedAmount.toString()); } const url = queryParams.toString() ? `${this.baseUrl}/${tenantId}/usage/${resourceType}/check?${queryParams.toString()}` : `${this.baseUrl}/${tenantId}/usage/${resourceType}/check`; return apiClient.get(url); } async recordUsage( tenantId: string, resourceType: 'users' | 'sales_records' | 'inventory_items' | 'api_requests', amount: number = 1 ): Promise<{ success: boolean; message: string }> { return apiClient.post<{ success: boolean; message: string }>( `${this.baseUrl}/${tenantId}/usage/${resourceType}/record`, { amount } ); } async getCurrentUsage(tenantId: string): Promise<{ users: number; sales_records: number; inventory_items: number; api_requests_this_hour: number; }> { return apiClient.get(`${this.baseUrl}/${tenantId}/usage/current`); } async getUsageSummary(tenantId: string): Promise { try { return await apiClient.get(`${this.baseUrl}/${tenantId}/summary`); } catch (error) { // Return mock data if backend endpoint doesn't exist yet console.warn('Using mock subscription data - backend endpoint not implemented yet'); return this.getMockUsageSummary(); } } async getAvailablePlans(): Promise { try { return await apiClient.get(`${this.baseUrl}/plans`); } catch (error) { // Return mock data if backend endpoint doesn't exist yet console.warn('Using mock plans data - backend endpoint not implemented yet'); return this.getMockAvailablePlans(); } } async validatePlanUpgrade(tenantId: string, planKey: string): Promise { try { return await apiClient.post(`${this.baseUrl}/${tenantId}/validate-upgrade`, { plan: planKey }); } catch (error) { console.warn('Using mock validation - backend endpoint not implemented yet'); return { can_upgrade: true }; } } async upgradePlan(tenantId: string, planKey: string): Promise { try { return await apiClient.post(`${this.baseUrl}/${tenantId}/upgrade`, { plan: planKey }); } catch (error) { console.warn('Using mock upgrade - backend endpoint not implemented yet'); return { success: true, message: 'Plan actualizado correctamente (modo demo)' }; } } formatPrice(amount: number): string { return new Intl.NumberFormat('es-ES', { style: 'currency', currency: 'EUR', minimumFractionDigits: 0, maximumFractionDigits: 2 }).format(amount); } getPlanDisplayInfo(planKey: string): { name: string; color: string } { const planInfo = { starter: { name: 'Starter', color: 'blue' }, professional: { name: 'Professional', color: 'purple' }, enterprise: { name: 'Enterprise', color: 'amber' } }; return planInfo[planKey as keyof typeof planInfo] || { name: 'Desconocido', color: 'gray' }; } private getMockUsageSummary(): UsageSummary { return { plan: 'professional', status: 'active', monthly_price: 49.99, next_billing_date: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(), usage: { users: { current: 3, limit: 10, unlimited: false, usage_percentage: 30 }, locations: { current: 1, limit: 3, unlimited: false, usage_percentage: 33 }, products: { current: 45, limit: -1, unlimited: true, usage_percentage: 0 } } }; } private getMockAvailablePlans(): AvailablePlans { return { plans: { starter: { name: 'Starter', description: 'Perfecto para panaderías pequeñas', monthly_price: 29.99, max_users: 3, max_locations: 1, max_products: 50, popular: false }, professional: { name: 'Professional', description: 'Para panaderías en crecimiento', monthly_price: 49.99, max_users: 10, max_locations: 3, max_products: -1, popular: true }, enterprise: { name: 'Enterprise', description: 'Para grandes operaciones', monthly_price: 99.99, max_users: -1, max_locations: -1, max_products: -1, contact_sales: true } } }; } } export const subscriptionService = new SubscriptionService();