diff --git a/apps/api/src/services/payment/addon.service.ts b/apps/api/src/services/payment/addon.service.ts index 10e184b..c867eab 100644 --- a/apps/api/src/services/payment/addon.service.ts +++ b/apps/api/src/services/payment/addon.service.ts @@ -201,18 +201,27 @@ export async function handleAddonPayment(addonId: string, mpPaymentId: string, s // ──────────────────────────────────────────────────────────────── // Overage automático: Business Control y Enterprise (business_cloud) incluyen -// 100 contribuyentes; cada uno adicional cuesta $45/mes. Se modela como un -// único `SubscriptionAddon` con `codename = 'contribuyente_extra_business_cloud'` -// (codename heredado por compat con suscripciones existentes; nombre display ya -// es genérico), `contribuyenteId = null` (tenant-level) y -// `quantity = activeCount − 100`. El cobro MP usa un preapproval propio; cuando -// `quantity` cambia, se actualiza vía `updatePreapprovalAmount` (sin -// re-autorización del usuario). +// 100 contribuyentes; cada RFC adicional cuesta: +// - Business Control: $25/mes +// - Enterprise: $60/mes +// Se modela como un único `SubscriptionAddon` con +// `codename = 'contribuyente_extra_business_cloud'` (codename heredado por +// compat con suscripciones existentes; nombre display ya es genérico), +// `contribuyenteId = null` (tenant-level) y `quantity = activeCount − 100`. +// El cobro MP usa un preapproval propio; cuando `quantity` cambia, se actualiza +// vía `updatePreapprovalAmount` (sin re-autorización del usuario). // ──────────────────────────────────────────────────────────────── const DESPACHO_INCLUDED_RFCS = 100; const OVERAGE_ADDON_CODENAME = 'contribuyente_extra_business_cloud'; +function getOverageUnitPrice(plan: string): number { + if (plan === 'business_control') return 25; + if (plan === 'business_cloud') return 60; + // Fallback por si en el futuro se agrega otro plan con overage + return 45; +} + export type OverageAction = 'none' | 'created' | 'updated' | 'cancelled' | 'skipped'; export interface OverageAdjustResult { @@ -228,9 +237,9 @@ export interface OverageAdjustResult { /** * Ajusta el add-on de overage para el tenant según el número actual de * contribuyentes activos. Aplica a planes Business Control y Enterprise - * (business_cloud) — ambos incluyen 100 contribuyentes y cobran $45/mes por - * cada adicional. Idempotente: llamar varias veces con el mismo `activeCount` - * no tiene efecto. + * (business_cloud) — ambos incluyen 100 contribuyentes y cobran $25/mes + * (Business Control) o $60/mes (Enterprise) por cada adicional. Idempotente: + * llamar varias veces con el mismo `activeCount` no tiene efecto. * * Casos: * - Plan no permite overage (mi_empresa, mi_empresa_plus, trial, etc.) → 'skipped' @@ -291,7 +300,7 @@ export async function adjustDespachoOverage( } // Hay overage → crear o actualizar addon - const price = Number(catalogo.precio); + const price = getOverageUnitPrice(sub.plan); const newAmount = price * overage; if (!existing) { diff --git a/apps/api/src/services/payment/mercadopago.service.ts b/apps/api/src/services/payment/mercadopago.service.ts index e11a127..552c5f0 100644 --- a/apps/api/src/services/payment/mercadopago.service.ts +++ b/apps/api/src/services/payment/mercadopago.service.ts @@ -221,6 +221,9 @@ export async function createProrationPreference(params: { pending: `${backUrlBase()}/configuracion/suscripcion?upgrade=pending`, }, auto_return: 'approved', + payment_methods: { + installments: 12, + }, }, }); @@ -266,6 +269,9 @@ export async function createSubscriptionPreference(params: { pending: `${backUrlBase()}/configuracion/suscripcion?subscription=pending`, }, auto_return: 'approved', + payment_methods: { + installments: 12, + }, }, }); diff --git a/docs/CAMBIOS-2026-05-04.md b/docs/CAMBIOS-2026-05-04.md index 0d5212d..dd06b52 100644 --- a/docs/CAMBIOS-2026-05-04.md +++ b/docs/CAMBIOS-2026-05-04.md @@ -616,7 +616,65 @@ Se reescribió el scraper de CSF para soportar los múltiples flujos del portal |---|---| | `apps/api/src/services/sat/sat-csf-scraper.ts` | Reescritura del scraper | -## Deploy +## 29. Actualización de precios: Business Control, Enterprise, RFCs adicionales y MSI + +**Fecha:** 2026-06-25 + +### Cambio +Se actualizaron los precios de los planes anuales de despacho y la política de cobro por RFC adicional. + +### Planes anuales + +| Plan | Precio anterior | Nuevo precio (primer año / renovación) | +|---|---|---| +| **Business Control** (`business_control`) | $25,850 | **$30,850** | +| **Enterprise** (`business_cloud`) | $43,000 | **$68,850** | + +Los cambios se aplican en la tabla `despacho_plan_prices` y afectan **nuevas suscripciones** y **renovaciones futuras** generadas por el sistema. + +### RFCs adicionales (overage) + +El precio mensual por cada contribuyente extra (más allá de los 100 incluidos) ahora depende del plan: + +| Plan | Precio por RFC adicional | +|---|---| +| **Business Control** | $25/mes | +| **Enterprise** | $60/mes | + +Se modificó `adjustDespachoOverage` para leer el precio desde el plan de la suscripción activa en lugar de usar un valor único de catálogo. + +### Meses sin intereses (MSI) + +Se habilitó el pago a **hasta 12 meses** en el checkout de MercadoPago para: +- Pago anual de Business Control / Enterprise (`createSubscriptionPreference`). +- Prorrateos de upgrade entre planes anuales (`createProrationPreference`). + +> **Nota:** para que las cuotas aparezcan **sin intereses**, es necesario contar con promociones MSI activas en la cuenta de vendedor de MercadoPago. Sin promociones, el checkout mostrará meses con intereses. + +### Archivos modificados + +| Archivo | Cambio | +|---|---| +| `apps/api/src/services/payment/addon.service.ts` | Precio de overage por plan ($25 / $60) | +| `apps/api/src/services/payment/mercadopago.service.ts` | `payment_methods.installments: 12` en preferences anuales y prorrateos | +| `apps/api/prisma/seed` (implícito) | Valores actualizados en `despacho_plan_prices` vía SQL | + +### Deploy + +Build y reload de API para limpiar el cache de `despacho_plan_prices`: + +```bash +cd /root/HoruxDespachosNuevo +pnpm --filter api build +pm2 reload horux-api +pm2 reload horux-web +``` + +**Estado:** ✅ Exitoso + +--- + +## Deploy histórico ### Preparación