chore: actualiza precios Business Control y Enterprise; overage por plan; MSI en checkout
This commit is contained in:
@@ -201,18 +201,27 @@ export async function handleAddonPayment(addonId: string, mpPaymentId: string, s
|
|||||||
|
|
||||||
// ────────────────────────────────────────────────────────────────
|
// ────────────────────────────────────────────────────────────────
|
||||||
// Overage automático: Business Control y Enterprise (business_cloud) incluyen
|
// Overage automático: Business Control y Enterprise (business_cloud) incluyen
|
||||||
// 100 contribuyentes; cada uno adicional cuesta $45/mes. Se modela como un
|
// 100 contribuyentes; cada RFC adicional cuesta:
|
||||||
// único `SubscriptionAddon` con `codename = 'contribuyente_extra_business_cloud'`
|
// - Business Control: $25/mes
|
||||||
// (codename heredado por compat con suscripciones existentes; nombre display ya
|
// - Enterprise: $60/mes
|
||||||
// es genérico), `contribuyenteId = null` (tenant-level) y
|
// Se modela como un único `SubscriptionAddon` con
|
||||||
// `quantity = activeCount − 100`. El cobro MP usa un preapproval propio; cuando
|
// `codename = 'contribuyente_extra_business_cloud'` (codename heredado por
|
||||||
// `quantity` cambia, se actualiza vía `updatePreapprovalAmount` (sin
|
// compat con suscripciones existentes; nombre display ya es genérico),
|
||||||
// re-autorización del usuario).
|
// `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 DESPACHO_INCLUDED_RFCS = 100;
|
||||||
const OVERAGE_ADDON_CODENAME = 'contribuyente_extra_business_cloud';
|
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 type OverageAction = 'none' | 'created' | 'updated' | 'cancelled' | 'skipped';
|
||||||
|
|
||||||
export interface OverageAdjustResult {
|
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
|
* 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
|
* contribuyentes activos. Aplica a planes Business Control y Enterprise
|
||||||
* (business_cloud) — ambos incluyen 100 contribuyentes y cobran $45/mes por
|
* (business_cloud) — ambos incluyen 100 contribuyentes y cobran $25/mes
|
||||||
* cada adicional. Idempotente: llamar varias veces con el mismo `activeCount`
|
* (Business Control) o $60/mes (Enterprise) por cada adicional. Idempotente:
|
||||||
* no tiene efecto.
|
* llamar varias veces con el mismo `activeCount` no tiene efecto.
|
||||||
*
|
*
|
||||||
* Casos:
|
* Casos:
|
||||||
* - Plan no permite overage (mi_empresa, mi_empresa_plus, trial, etc.) → 'skipped'
|
* - 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
|
// Hay overage → crear o actualizar addon
|
||||||
const price = Number(catalogo.precio);
|
const price = getOverageUnitPrice(sub.plan);
|
||||||
const newAmount = price * overage;
|
const newAmount = price * overage;
|
||||||
|
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
|
|||||||
@@ -221,6 +221,9 @@ export async function createProrationPreference(params: {
|
|||||||
pending: `${backUrlBase()}/configuracion/suscripcion?upgrade=pending`,
|
pending: `${backUrlBase()}/configuracion/suscripcion?upgrade=pending`,
|
||||||
},
|
},
|
||||||
auto_return: 'approved',
|
auto_return: 'approved',
|
||||||
|
payment_methods: {
|
||||||
|
installments: 12,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -266,6 +269,9 @@ export async function createSubscriptionPreference(params: {
|
|||||||
pending: `${backUrlBase()}/configuracion/suscripcion?subscription=pending`,
|
pending: `${backUrlBase()}/configuracion/suscripcion?subscription=pending`,
|
||||||
},
|
},
|
||||||
auto_return: 'approved',
|
auto_return: 'approved',
|
||||||
|
payment_methods: {
|
||||||
|
installments: 12,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -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 |
|
| `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
|
### Preparación
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user