Modal de Cancelación de Pedidos - CancelOrderModal
Documentación completa del componente [CancelOrderModal] que gestiona la experiencia de usuario al cancelar pedidos en la aplicación móvil. El sistema implementa políticas diferenciadas por país (Chile/Argentina/México con CANCELLATION-2-2 vs otros países con sistema anti-fraude), evalúa condiciones de alto valor (HIGH_BASKET_SIZE), y determina qué mensaje mostrar al usuario basado en su historial de cancelaciones, método de pago, y configuraciones de fraude del backend.
Modal de Cancelación de Pedidos - CancelOrderModal
Documentación completa del componente CancelOrderModal que gestiona la experiencia de usuario al cancelar pedidos en la aplicación móvil. El sistema implementa políticas diferenciadas por país (Chile/Argentina con CANCELLATION-2-2 vs otros países con sistema anti-fraude), evalúa condiciones de alto valor (HIGH_BASKET_SIZE), y determina qué mensaje mostrar al usuario basado en su historial de cancelaciones, método de pago, y configuraciones de fraude del backend.
¿Qué es este sistema?
Cuando un usuario intenta cancelar un pedido, la aplicación muestra diferentes mensajes dependiendo de las condiciones técnicas evaluadas por el sistema de fraude y políticas de cancelación.
CHILE Y ARGENTINA ÚNICAMENTE - Política CANCELLATION-2-2
🟢 Mensaje Normal (DefaultMessageChile)
Lo que ve el usuario: "El monto de tu pedido se te devolverá automáticamente en créditos Cheaf"
Cuándo aparece:
- País es Chile (
'CL') o Argentina ('AR') únicamente - Y NO se cumple la condición de
CANCELLATION-2-2
Condición técnica: countryCode === 'CL' || countryCode === 'AR' Y condiciones normales
Devolución de créditos: willRefundCredits = true
Origen de datos: authState.ipDetails.countryCode
🔴 Cancelación con Costo (CancellationChileMessage)
Lo que ve el usuario: "Por tratarse de una cancelación tardía, se te cobrará el monto total del pedido"
Cuándo aparece:
- País es Chile o Argentina únicamente
- Y
policyType === 'CANCELLATION-2-2' - Y
isApplicable === true
Condiciones específicas de la Regla 2-2 (Backend):
- Condiciones Temporales (AMBAS deben cumplirse):
- Faltan menos de 2 horas para el cierre:
now_time_plus_2 > collect_before > now.time() - El pedido fue creado hace más de 1 hora:
created_at < now_time(dondenow_time = now - 1 hora)
- Faltan menos de 2 horas para el cierre:
- Condiciones Adicionales para Penalización:
- Monto alto:
order.total() >= basket_size(≥200 configurado en BASKET_SIZE) - Pago en efectivo:
order.payment_type == "1" - Política aplicable:
is_applicable === true
- Monto alto:
Consecuencias:
- Se genera deuda por el costo total del pedido
- La orden se marca como
STATUS_LATE_CANCELLED - Sin devolución de créditos:
willRefundCredits = false
Condición técnica: countryCode === 'CL' || countryCode === 'AR' Y policyType === 'CANCELLATION-2-2' && isApplicable === true
Origen de datos: orderPolicies.cancellationPolicy (evaluado por el backend según reglas temporales)
TODOS LOS DEMÁS PAÍSES - Sistema Anti-Fraude
🚫 Usuario Baneado (BannedMessage)
Lo que ve el usuario: "Has cancelado muchos pedidos en los últimos 90 días, si cancelas este pedido no recibirás devolución"
Cuándo aparece:
- País NO es Chile ni Argentina
- Y (
isBanned === trueOfraudStatus.details.warningCancellationPolicy === 'inflicts')
Qué significa 'inflicts': El backend asigna este valor cuando:
- Órdenes efectivas ≤ 8 Y cancelaciones = 5, O
- Órdenes efectivas > 8 Y cancelaciones ≥ 5 Y tasa de cancelación ≥ 25%
Condición técnica: !(countryCode === 'CL' || countryCode === 'AR') Y (isBanned || warningCancellationPolicy === 'inflicts')
Devolución de créditos: willRefundCredits = false
Origen de datos:
isBanned:authState.cancellationBannedwarningCancellationPolicy: API/orders/cancel-order/${orderId}/check_for_fraud/
⚠️ Advertencia de Fraude (FraudWarningMessage)
Lo que ve el usuario: "Has cancelado muchos pedidos, no podrás pagar en sucursal. Tus créditos se te devolverán en un periodo de 24 horas"
Cuándo aparece:
- País NO es Chile ni Argentina
- Y
HIGH_BASKET_SIZE === false - Y
fraudStatus.isFraudAttempt === true - Y
usePromos === true(tiene cupones o créditos > 0) - Y
fraudStatus.details.warningCancellationPolicy === 'warning'
Qué significa 'warning': El backend asigna este valor cuando:
- Cancelaciones = 4 (una menos que el límite de 5), O
- inflicts_cancellation_policy = true Y last_opportunity_cancellation_policy = true
Condición técnica: !(countryCode === 'CL' || countryCode === 'AR') Y !HIGH_BASKET_SIZE && isFraudAttempt && usePromos && warningCancellationPolicy === 'warning'
Devolución de créditos: willRefundCredits = true (con retraso de 24h)
Origen de datos: API /orders/cancel-order/${orderId}/check_for_fraud/ + usePromos calculado como coupon || credits > 0
🔍 Fraude Simple (FraudMessage)
Lo que ve el usuario: "Tus créditos o cupones se te devolverán en un periodo de 24 horas"
Cuándo aparece:
- País NO es Chile ni Argentina
- Y
HIGH_BASKET_SIZE === false - Y
fraudStatus.isFraudAttempt === true - Y
usePromos === true - Y
fraudStatus.details.warningCancellationPolicy !== 'warning'
Condición técnica: !(countryCode === 'CL' || countryCode === 'AR') Y !HIGH_BASKET_SIZE && isFraudAttempt && usePromos && warningCancellationPolicy !== 'warning'
Devolución de créditos: willRefundCredits = true (con retraso de 24h)
Origen de datos: API /orders/cancel-order/${orderId}/check_for_fraud/
📦⚠️ Alto Valor + Advertencia (HighBasketWarningMessage)
Lo que ve el usuario: "La tienda ha reservado este pedido para ti. Si decides cancelar [generarás un adeudo/no podremos realizar un reembolso]"
Cuándo aparece:
- País NO es Chile ni Argentina
- Y
fraudStatus.details.userCancelledOrdersCount >= 1 - Y
fraudStatus.details.warningCancellationPolicy === 'not_inflicts' - Y
HIGH_BASKET_SIZE === true
Qué significa 'not_inflicts': El backend asigna este valor cuando el usuario NO cumple las condiciones para 'inflicts' o 'warning' (es decir, está en rango normal pero con algunas cancelaciones)
Condición técnica: !(countryCode === 'CL' || countryCode === 'AR') Y userCancelledOrdersCount >= 1 && warningCancellationPolicy === 'not_inflicts' && HIGH_BASKET_SIZE
Devolución de créditos: willRefundCredits = false
Origen de datos: API /orders/cancel-order/${orderId}/check_for_fraud/ + cálculo HIGH_BASKET_SIZE
⚠️ Primera Advertencia (WarningMessage)
Lo que ve el usuario: "Si tu alta tasa de cancelación persiste perderás la posibilidad de pagar en sucursal"
Cuándo aparece:
- País NO es Chile ni Argentina
- Y
fraudStatus.details.userCancelledOrdersCount >= 1 - Y
fraudStatus.details.warningCancellationPolicy === 'not_inflicts' - Y
HIGH_BASKET_SIZE === false
Condición técnica: !(countryCode === 'CL' || countryCode === 'AR') Y userCancelledOrdersCount >= 1 && warningCancellationPolicy === 'not_inflicts' && !HIGH_BASKET_SIZE
Devolución de créditos: willRefundCredits = true
Origen de datos: API /orders/cancel-order/${orderId}/check_for_fraud/
🚨📦 Pre-Baneo + Alto Valor (HighBasketPreBannedMessage)
Lo que ve el usuario: "Has cancelado muchos pedidos, no podrás pagar en sucursal. Si decides cancelar [generarás un adeudo/no podremos realizar un reembolso]"
Cuándo aparece:
- País NO es Chile ni Argentina
- Y
fraudStatus.details.warningCancellationPolicy === 'warning' - Y
HIGH_BASKET_SIZE === true
Condición técnica: !(countryCode === 'CL' || countryCode === 'AR') Y warningCancellationPolicy === 'warning' && HIGH_BASKET_SIZE
Devolución de créditos: willRefundCredits = false
Origen de datos: API /orders/cancel-order/${orderId}/check_for_fraud/ + cálculo HIGH_BASKET_SIZE
🚨 Pre-Baneo (PreBannedMessage)
Lo que ve el usuario: "Has cancelado muchos pedidos en los últimos 90 días, si cancelas este pedido no podrás pagar en sucursal"
Cuándo aparece:
- País NO es Chile ni Argentina
- Y
fraudStatus.details.warningCancellationPolicy === 'warning' - Y
HIGH_BASKET_SIZE === false
Condición técnica: !(countryCode === 'CL' || countryCode === 'AR') Y warningCancellationPolicy === 'warning' && !HIGH_BASKET_SIZE
Devolución de créditos: willRefundCredits = true
Origen de datos: API /orders/cancel-order/${orderId}/check_for_fraud/
📦 Solo Alto Valor (HighBasketMessage)
Lo que ve el usuario: "La tienda ha reservado este pedido para ti. Si decides cancelar [generarás un adeudo/no podremos realizar un reembolso]"
Cuándo aparece:
- País NO es Chile ni Argentina
- Y
HIGH_BASKET_SIZE === true - Y ninguna de las condiciones anteriores se cumple
Condición técnica: !(countryCode === 'CL' || countryCode === 'AR') Y solo HIGH_BASKET_SIZE === true
Devolución de créditos: willRefundCredits = false
Origen de datos: Cálculo HIGH_BASKET_SIZE en el componente
🟢 Mensaje Normal (DefaultMessage)
Lo que ve el usuario: "Si pagaste con tarjeta, créditos o cupones, se te devolverá el monto de tu pedido en créditos"
Cuándo aparece:
- País NO es Chile ni Argentina
- Y ninguna de las condiciones anteriores se cumple
Condición técnica: Caso por defecto para países que no son CL/AR
Devolución de créditos: willRefundCredits = true
Variables Clave del Sistema
Política CANCELLATION-2-2
Países que aplican en Frontend:
- Chile (CL) únicamente
- Argentina (AR) únicamente
Nota: México (MX) tiene la política en backend pero NO se maneja en este componente frontend
Otros países: Usan sistema anti-fraude por defecto
Significado de "2-2":
- 2 horas: Tiempo límite antes del cierre de la tienda
- 2 horas: Tiempo total (1 hora mínima del pedido + 1 hora de buffer)
Condiciones Backend para Activación:
# Condiciones temporales (AMBAS deben cumplirse)
now_time_plus_2 > collect_before > now.time() # Menos de 2h para cierre
created_at < now_time # Pedido creado hace más de 1h
# Condiciones adicionales para penalización
order.total() >= basket_size # >= 200 (BASKET_SIZE)
order.payment_type == "1" # Pago en efectivo
is_applicable == true # Política activaHIGH_BASKET_SIZE (Frontend)
Cálculo técnico:
HIGH_BASKET_SIZE = cantCancelByTime && subtotal >= basketSize;
cantCancelByTime =
now + 2 >= closeTime ? deltaTimestamp < 60 * 60 * 1000 : false;Componentes:
subtotal: Monto total del pedido (calculado en OrderDetail)basketSize: Límite configurado (default: 190, desdeauthState.fraudSettings.basketSize)closeTime: Hora de cierre de la tienda (schedule.collectBefore)- deltaTimestamp: Tiempo transcurrido desde creación del pedido
now + 2: Hora actual + 2 horas de buffer
willRefundCredits (Lógica de Devolución)
Basado en el código del componente:
// Chile/Argentina únicamente
if (countryCode === "CL" || countryCode === "AR") {
if (policyType === "CANCELLATION-2-2" && isApplicable) return false;
else return true;
}
// Otros países
else if (isBanned || warningCancellationPolicy === "inflicts") return false;
else if (!HIGH_BASKET_SIZE && isFraudAttempt && usePromos)
return true; // Ambos casos
else if (
userCancelledOrdersCount >= 1 &&
warningCancellationPolicy === "not_inflicts"
) {
if (HIGH_BASKET_SIZE) return false;
else return true;
} else if (warningCancellationPolicy === "warning") {
if (HIGH_BASKET_SIZE) return false;
else return true;
} else if (HIGH_BASKET_SIZE) return false;
return true; // Caso por defectowarningCancellationPolicy (Backend)
Calculado por el sistema backend basado en configuración AWS S3:
'inflicts' (Política se aplica - más severo):
- Órdenes efectivas ≤ 8 Y cancelaciones = 5
- Órdenes efectivas > 8 Y cancelaciones ≥ 5 Y tasa ≥ 25%
'warning' (Advertencia - estado intermedio):
- Cancelaciones = 4 (una menos que el límite)
- inflicts_cancellation_policy = true Y last_opportunity_cancellation_policy = true
'not_inflicts' (No aplica política - normal):
- No cumple condiciones anteriores
Configuración AWS S3
Archivo: s3://cheaf-configuration/fraud_cancellation_policy/fraud_and_cancellation_configuration.json
Variables clave:
EFFECTIVE_ORDERS_CANCELLATION_POLICY: 8 (órdenes efectivas mínimas)CANCEL_ORDERS_CANCELLATION_POLICY: 5 (límite de cancelaciones)CANCEL_RATE_CANCELLATION_POLICY: 25% (tasa límite de cancelación)DAYS_RANGE_CANCELLATION_POLICY: 90 (días para evaluar política)BASKET_SIZE: 200 (límite para CANCELLATION-2-2 en backend)
Flujo Completo del Sistema
- Usuario hace clic "Cancelar" → Se abre CancelOrderModal
- Frontend consulta →
/orders/cancel-order/${orderId}/check_for_fraud/ - Backend ejecuta →
CancellationOrdersPolicycon configuración AWS S3 - Backend calcula:
- Cancelaciones en últimos 90 días (
userCancelledOrdersCount) - Tasa de cancelación vs órdenes efectivas
- Asigna
warningCancellationPolicysegún reglas - Evalúa
isFraudAttemptsi hay promociones
- Cancelaciones en últimos 90 días (
- Frontend evalúa:
- Primero: País (Chile/Argentina vs otros)
- Si otros países:
HIGH_BASKET_SIZE(timing + monto) - Si otros países: Combinación de variables de fraude
- Se muestra mensaje correspondiente según matriz de decisión
Referencia Técnica para Desarrolladores
// Flujo de decisión principal en renderMessage() - líneas 689-732
if (countryCode === "CL" || countryCode === "AR") {
if (policyType === "CANCELLATION-2-2" && isApplicable) {
return <CancellationChileMessage />; // Sin devolución
}
return <DefaultMessageChile />; // Con devolución
} else if (
isBanned ||
fraudStatus?.details?.warningCancellationPolicy === "inflicts"
) {
return <BannedMessage />; // Sin devolución
} else if (!HIGH_BASKET_SIZE && fraudStatus?.isFraudAttempt && usePromos) {
if (fraudStatus?.details?.warningCancellationPolicy === "warning") {
return <FraudWarningMessage />; // Con devolución (24h)
} else {
return <FraudMessage />; // Con devolución (24h)
}
} else if (
fraudStatus?.details?.userCancelledOrdersCount >= 1 &&
fraudStatus?.details?.warningCancellationPolicy === "not_inflicts"
) {
if (HIGH_BASKET_SIZE) {
return <HighBasketWarningMessage payWithCash={payWithCash} />; // Sin devolución
} else {
return <WarningMessage />; // Con devolución
}
} else if (fraudStatus?.details?.warningCancellationPolicy === "warning") {
if (HIGH_BASKET_SIZE) {
return <HighBasketPreBannedMessage payWithCash={payWithCash} />; // Sin devolución
} else {
return <PreBannedMessage />; // Con devolución
}
} else if (HIGH_BASKET_SIZE) {
return <HighBasketMessage payWithCash={payWithCash} />; // Sin devolución
}
return <DefaultMessage />; // Con devolución - caso por defectoPre-Orden (Beta)
Documentación del proceso de creación de una pre-orden en el sistema
Servicio de Cancelación de Pedidos
Documentación completa del servicio `perform_cancellation` que maneja la cancelación de pedidos con reglas diferenciadas por país, tipo de cuenta, y políticas de prevención de fraude. El sistema implementa flujos específicos para Chile/Argentina (con reglas especiales para Cencosud) y un flujo default para otros países.