Flujo de cancelación de inscripciones

Cancelar una inscripción no es una acción única: el sistema elige una de cuatro ramas (branches) según dos variables:

  1. Estado de la orden vinculada (si existe).
  2. Política de cancelación vigente para la actividad (los “tiers” que devuelven X% de cupón según cuántos días faltan para el inicio).

El modal de cancelación se abre desde la tabla de Inscripciones o desde el detalle, y siempre exige un motivo (campo obligatorio).

Punto de entrada único

Tanto el administrador como el inscripto (desde su panel personal) abren el mismo modal. El sistema decide internamente cuál de los cuatro escenarios aplicar; el usuario no elige la rama, sólo confirma.

Ver el canvas visual para una mirada en diagrama.

Las 4 ramas

Rama (branch)Estado de la orden¿Hay tier aplicable?Qué hace el sistema
unpaid_orderpending o on-hold(no se evalúa)Cancela la orden + cancela la inscripción. Sin cupón.
paid_with_tierprocessing o completedOfrece dos opciones al usuario: emitir cupón o solicitar devolución.
paid_no_tierprocessing o completednoCancela la inscripción. La orden queda sin cambios. No se emite cupón.
no_ordersin orden vinculada / estado no contemplado(no aplica)Cancela la inscripción. Nada más.

A continuación cada rama en detalle.


Rama 1: unpaid_order (orden sin pago recibido)

Cuándo se dispara: la orden está en pending (pendiente de pago) o on-hold (en espera, sin pago confirmado).

Mensaje en el modal:

Según nuestros registros la orden N está pendiente de pago (no recibimos el pago). Al confirmar se cancelarán la orden y la inscripción. No se emite cupón de reembolso.

Acciones del sistema al confirmar:

  1. La orden de WooCommerce pasa a estado cancelled con una nota interna que cita la cancelación de la inscripción y el motivo.
  2. La inscripción pasa a cancelled.
  3. No se emiten cupones — no hubo pago, no hay nada que reembolsar.
  4. Se escriben las notas de auditoría: nota visible al cliente en la inscripción (emailed), nota en la orden, nota interna en el producto.

Definitividad

La cancelación es definitiva. Si más adelante la persona quiere volver a inscribirse, debe hacerlo de cero por la página pública.


Rama 2: paid_with_tier (orden pagada + política aplica)

Cuándo se dispara: la orden está en processing o completed, y la política de cancelación de la actividad tiene al menos un tier cuyo cutoff todavía no fue superado por la fecha de cancelación.

Cómo se elige el tier

Si la política tiene varios tiers (por ejemplo 100% hasta 30 días antes, 50% hasta 15 días antes, 25% hasta 7 días antes), el sistema toma el tier con el cutoff más cercano a la fecha de cancelación entre los que todavía no expiraron. Es “el último escalón al que llegaste antes de que se te pase”.

Mensaje en el modal:

La orden N está completada (pago recibido). Según la política de cancelación, te corresponde un cupón de X% para usar en próximas actividades.

El modal presenta dos opciones con jerarquía visual distinta:

Opción primaria (recomendada): Emitir un cupón

Card destacada arriba, fondo verde, botón grande.

Lo que dice el sistema:

Recibirás un cupón del X% válido para actividades del tipo que comiencen antes del DD de mes de AAAA.

Se cancela la inscripción inmediatamente y se emite el cupón en el momento.

Acciones al confirmar (botón “Emitir cupón y cancelar”):

  1. Se emite un único cupón (cupón de reembolso) restringido al primer tipo de actividad asociado a la actividad cancelada.
    • Porcentaje = el del tier seleccionado.
    • Validez = del día de hoy hasta hoy + max_days_applicable_for_activities_starting_from_now de la política.
    • El cupón se asocia al email del comprador (y, si aplica, al email del participante cuando la compra usó “no soy participante”).
  2. La orden pasa a estado refunded (reembolsada).
  3. La inscripción pasa a cancelled.
  4. Notas de auditoría en inscripción (emailed), orden (customer-visible), producto (interna), y el cupón emitido (interna).

Un solo cupón

Aunque la actividad tenga varios “tipos de actividad” asociados, se emite un único cupón (sobre el primer tipo) para evitar fragmentar el reembolso. El detalle textual del modal y del mail siempre indica para qué tipo es y hasta qué fecha sirve.

Opción secundaria: Reembolso del dinero

Card más sobria abajo, botón outline.

Lo que dice el sistema:

¿Preferís que te devolvamos el dinero? Cancelamos la inscripción y un organizador te contactará para coordinar la devolución del dinero por separado.

Acciones al confirmar (botón “Cancelar y solicitar devolución”):

  1. La inscripción pasa a cancelled (libera el lugar en la actividad).
  2. La orden NO se toca — sigue en su estado pagado. Un organizador resolverá el reembolso manualmente fuera del sistema (transferencia, etc.) y, una vez efectivizado, llevará la orden a refunded a mano desde WooCommerce.
  3. No se emite cupón.
  4. Notas: la nota visible al inscripto incluye una línea explicando que la devolución la coordina un organizador a la brevedad.

El sistema no efectúa el reembolso monetario

El sistema sólo registra la intención de pedir el dinero de vuelta. La transferencia/efectivo y el cambio de estado de la orden son manuales y están fuera del flujo automatizado.


Rama 3: paid_no_tier (orden pagada pero política expirada)

Cuándo se dispara: la orden está en processing o completed, pero la fecha de cancelación está fuera del plazo de todos los tiers de la política (todos los cutoffs ya se pasaron).

Mensaje en el modal:

La orden N está completada, pero el día de la cancelación quedó fuera del plazo cubierto por la política. Sólo cancelamos la inscripción; si corresponde un reembolso parcial habrá que coordinarlo por separado.

Acciones del sistema al confirmar:

  1. La inscripción pasa a cancelled.
  2. La orden NO se toca.
  3. No se emite cupón — la política ya no califica.
  4. Notas de auditoría habituales.

Cuándo elegir esta rama

No es una “rama elegible”: la elige el sistema cuando no hay tier que califique. Si pasaron todos los cutoffs (por ejemplo, la actividad ya empezó hace 5 días y el último tier era “hasta 0 días antes”), automáticamente se entra en paid_no_tier.


Rama 4: no_order (sin orden vinculada)

Cuándo se dispara:

  • La inscripción nunca tuvo orden asociada (típico de lista de espera).
  • O la orden está en un estado no contemplado por el flujo (por ejemplo failed, cancelled previa, refunded previa).

Mensaje en el modal:

No hay una orden vinculada a esta inscripción. La cancelación es definitiva. Si más adelante se desea volver a realizar inscripción, se puede hacer nuevamente por la página pública.

Acciones del sistema al confirmar:

  1. La inscripción pasa a cancelled.
  2. No se toca ninguna orden (no hay).
  3. No se emite cupón.
  4. Notas de auditoría habituales.

Resumen visual

                   ┌─────────────────────────────┐
                   │  Click "Cancelar           │
                   │  inscripción" + motivo      │
                   └──────────────┬──────────────┘
                                  │
                  ┌───────────────┴───────────────┐
                  │ ¿La inscripción tiene orden?  │
                  └───────────────┬───────────────┘
                       NO         │         SÍ
                  ┌────┘                       └────┐
                  ▼                                 ▼
            ┌──────────┐                ┌──────────────────┐
            │ no_order │                │ ¿Estado orden?   │
            └──────────┘                └────────┬─────────┘
                                                 │
                ┌────────────┬───────────────────┼───────────────┐
                ▼            ▼                   ▼               ▼
           pending /     processing /        otro estado     pago recibido
           on-hold       completed                            sin tier aplicable
                │             │                                    │
                ▼             ▼                                    ▼
        ┌─────────────┐  ┌──────────────────┐              ┌──────────────┐
        │ unpaid_     │  │ ¿Tier aplica?    │              │ paid_no_tier │
        │ order       │  └────┬──────┬──────┘              └──────────────┘
        └─────────────┘     SÍ│      │NO
                              ▼      └───────► paid_no_tier
                      ┌────────────────┐
                      │ paid_with_tier │
                      │ (2 opciones:   │
                      │  cupón / $$$ ) │
                      └────────────────┘

Para el detalle visual completo con todas las acciones de cada rama: abrir el canvas.

Auditoría: qué quedó registrado

Cada cancelación deja rastro en hasta cuatro lugares simultáneamente:

EntidadNotaAudiencia¿Va por mail?
InscripciónAsistente, actividad, fechas, motivo, detalle del cupón o aviso de devoluciónCliente y staff
Orden (WC)“Cancelación de inscripción N procesada. Motivo del cliente: …”Cliente y staffNo (visible en WC)
ProductoBranch, intent, motivo, tier aplicado, cupones emitidos, cambio de estado de ordenStaff (interna)No
Cada cupón emitidoOrigen (cancelación de inscripción), motivo, tier aplicado, estado de ordenStaff (interna)No

Datos en el email al inscripto

El email siempre incluye nombre del asistente, nombre de la actividad, fechas de inicio y fin de la actividad, motivo de cancelación, y — si corresponde — detalle del cupón con su validez en formato DD de mes de AAAA.

Política de cancelación: configuración

La política se define en dos niveles:

  1. Por actividad (cancelation_policy en el meta del producto): definida al crear o editar la actividad. Es la que efectivamente se evalúa.
  2. Default del sitio: configurable en wp-admin → Configuración → Política de cancelación. Cuando se crea una actividad nueva, se snapshot-ea ese default al producto. Cambios posteriores al default no afectan actividades ya creadas.

Para los detalles: Política de cancelación default y Política de cancelación por actividad.

Datos técnicos (para devs)

Para implementadores que necesiten reproducir o extender el flujo:

  • Orquestador: CDC\Application\Registration\CancelRegistration (PHP).
  • Algoritmo de selección de tier: CancellationPolicy::pick_tier_for_cancellation() — “earliest unmissed cutoff” entre los tiers de la política. Cubierto por tests/Domain/Cancellation/CancellationPolicyTest.php (25 tests).
  • Emisor de cupones: CDC\Coupons\Refund_Coupon_Generator::emit_refund_coupons() — un cupón único sobre el primer término de pa_tipo_de_actividad.
  • Endpoints REST: GET /wp-json/cdc/v1/registrations/{id}/cancel/preview (preview) y POST /wp-json/cdc/v1/registrations/{id}/cancel (execute).
  • Modal: cdc-landings/components/admin/registrations/CancelRegistrationModal.tsx.