CHEFMANAGER IA 3.9.0 · VALIDACIÓN DE ENTREGA (FOOD COURT FASE 4 · PAGO DIVIDIDO)
==================================================================================

Misma metodología que docs/VALIDACION-3.8.0.txt: servidor PHP real (`php -S`)
sirviendo el paquete completo, peticiones HTTP reales con cookies de sesión,
no invocación directa de clases.

RESULTADOS ESTRUCTURALES

- php -l sobre los archivos PHP modificados/nuevos: sin errores de sintaxis.
- Instalación SQLite nueva ejecutando Database::connection() de verdad:
  conecta sin errores, PRAGMA integrity_check=ok, 0 violaciones de llaves
  foráneas, 178 tablas (176 de la 3.8.0 + food_court_order_payments y
  food_court_order_payment_operators). Migración
  sqlite-v21-food-court-payments.sql aditiva y no falla sobre una base que
  ya tiene la 3.8.0 completa; segunda conexión (idempotencia) sin errores.

PRUEBA FUNCIONAL DE EXTREMO A EXTREMO (HTTP real contra `php -S`, con cookies
de sesión reales)

Se repitió el mismo escenario de la validación de 3.8.0: una cuenta de
plataforma, dos negocios nuevos ("Comidas Test B" y "Pollos Test C"), un
patio de comidas con ambos como operadores activos, y un pedido maestro real
por HTTP con una línea de cada operador (total 110: 50 de "Comidas B" y 60
de "Pollos C").

1. POST .../orders/{id}/payments con amount=100 (no coincide con el saldo
   real de 110) → 422 ("El monto debe coincidir exactamente con el saldo de
   los subpedidos seleccionados (Bs 110.00).").
2. POST .../orders/{id}/payments con operator_ids=[999] (operador que no
   pertenece al pedido) → 422 ("Uno de los operadores no pertenece a este
   pedido.").
3. POST .../orders/{id}/payments con method=qr, amount=50,
   operator_ids=[1] (solo "Comidas B") → 201, pago aplicado. El subpedido de
   "Comidas B" queda payment_status=paid, status=confirmed (pasó
   automáticamente de pending a confirmed, igual que haría su propio
   checkout). El estado de pago del grupo pasa a "partial", saldo pendiente
   60.
4. Reintentar cubrir el mismo operador (operator_ids=[1]) → 409/422 ("El
   subpedido de "Comidas B" ya está pagado."). Confirma que un pago central
   no puede cobrar dos veces un subpedido ya cubierto.
5. POST .../orders/{id}/payments sin operator_ids (cubre automáticamente
   todos los subpedidos aún pendientes: solo queda "Pollos C", saldo 60) con
   amount=60 → 201, pago aplicado. El estado de pago del grupo pasa a
   "paid", saldo pendiente 0.
6. GET .../orders/{id} (detalle del pedido maestro) → ambos subpedidos con
   payment_status=paid y status=confirmed; sección "payment" con
   status="paid", outstanding=0, y el historial de los dos pagos centrales
   con su desglose por operador (applied_to).
7. El dueño de "Comidas Test B" consulta su propio GET /orders/{id} (vista
   normal, sin ningún cambio) → ve su subpedido con status=confirmed,
   payment_status=paid, paid_at con la hora del pago central. Confirma que
   el pago central es visible para el negocio sin ninguna pantalla nueva.
8. El dueño de "Comidas Test B" avanza su subpedido ya pagado a "preparing"
   con el endpoint normal PUT /orders/{id}/status → permitido sin bloqueo
   de pago-antes-de-cocina (ese bloqueo ya lo satisface el pago central).
9. El dueño de "Comidas Test B" intenta llamar directamente
   POST .../orders/{id}/payments (el endpoint de administración del patio)
   → 403 ("No tienes permiso para administrar este patio de comidas").
   Confirma que un negocio individual no puede registrar pagos centrales de
   todo el patio, solo cobrar su propio subpedido con su propio checkout.
10. GET público food-court-track con el token del pedido maestro → devuelve
    status="confirmed" (estado conjunto) y payment_status="paid" (estado de
    pago conjunto), visibles para el cliente sin sesión.
11. Consulta directa a la base tras aplicar un pago central: 0 filas en
    `sales` para ese pedido, 0 filas en `payments` y 0 en `cash_movements`
    para ese negocio, y orders.payment_status="paid". Confirma por datos
    reales, no solo por lectura de código, que un pago central no fabrica
    ninguna venta ni movimiento de caja de un negocio ajeno — ver
    "DECISIONES DE DISEÑO Y LÍMITES DELIBERADOS" en docs/RELEASE-3.9.0.txt.

NO CUBIERTO POR ESTA VALIDACIÓN

- No hay interfaz de usuario que probar en esta fase.
- No se probó pago parcial de un solo subpedido individual, porque esta
  fase no lo admite por diseño (ver docs/RELEASE-3.9.0.txt).
- No se probó reversa ni anulación de un pago central, porque esta fase no
  la implementa.
- No se probó un escenario con más de dos operadores ni con montos que
  requieran redondeo a más de dos decimales.
