# Prompt 5 — Liquidar y el tipo de cambio del día

Requiere el motor del prompt 1 y la página del prompt 2 o 3. Este prompt
cierra el ciclo del dinero: el grupo sabe quién le debe a quién, lo paga y lo
marca; y los gastos en otra moneda se convierten con el tipo del día sin que
nadie lo teclee.

---

Extiende mi divisor de gastos de viaje con dos cosas, SIN romper las pruebas
que ya pasan. Todo sigue siendo la misma bitácora de eventos que solo crece.

**1. Liquidar.** Tres eventos nuevos que entiende el motor (`reducir`):

- `{ tipo: 'pago', id, de, a, monto, moneda }` — "ya le pagué". Salda: en
  `saldos()` quien paga sube y quien cobra baja por el monto (en la moneda
  base). NO es un gasto: no suma al total del viaje. Se valida como un gasto:
  centavos enteros positivos, `de` distinto de `a`, un id repetido cuenta una
  vez. Se anula con el mismo evento `anulacion { gasto: idDelPago }`.
- `{ tipo: 'cobro', persona, texto }` — cómo le pagan a alguien (CLABE,
  enlace de Revolut o PayPal). Gana el último; recórtalo a 300 caracteres.
- `{ tipo: 'cambio', moneda, valor }` — el tipo de cambio que el GRUPO
  acordó para una moneda (cuántas unidades de la base vale 1 de esa moneda).
  Gana el último; `valor: null` lo quita. Código de 3 letras mayúsculas y
  valor numérico mayor que cero; lo demás se ignora.

En la interfaz: cada fila de "para quedar a mano" lleva un botón "Ya pagó"
que pregunta el monto con el total propuesto (se puede bajar: pago parcial;
más de lo que se debe se rechaza con aviso). Bajo la ÚLTIMA fila de cada
acreedor, sus datos de cobro con un botón "copiar" (copia el dato, no la
frase; un enlace https se vuelve tocable, armado como nodo y nunca como
HTML). Un enlace "¿Cómo te pagan?" deja a cada quien escribir los suyos.
Los pagos aparecen en la historia junto a los gastos y se pueden anular.

**2. El tipo de cambio del día.** Al abrir la página (y a lo más cada 12
horas) pide la tabla del Banco Central Europeo a
`https://api.frankfurter.dev/v1/latest?base=MXN` (cambia MXN por tu moneda
base), invierte los valores (la API da cuántos USD vale 1 MXN; tú quieres
cuántos MXN vale 1 USD) y guárdala en localStorage con su fecha. Sin red se
usa la guardada, o un set de arranque escrito en el código.

La regla que evita que los saldos se muevan solos: al CAPTURAR un gasto en
otra moneda, séllale el tipo que vale en ese momento: `{ tc, base }`. En el
motor, el tipo que vale para un gasto es, en este orden: (1) el acordado por
el grupo (evento `cambio`), que es una decisión explícita y manda; (2) el
sellado en el gasto si su `base` es la misma; (3) la tabla del día (para
gastos viejos sin sello). Si no hay ninguno, el gasto se aparta y se avisa,
como siempre: nunca se suma en silencio.

En la interfaz: bajo el arreglo, una línea discreta con los tipos que se
están usando ("1 JPY = 0.1097 MXN · BCE del 22/09 · ajustar"); "ajustar"
pide el tipo acordado para el grupo. El selector de moneda pone primero la
base, luego las populares, las ya usadas en el viaje y el resto de la
tabla, y una opción "Otra…" que pide el código y el tipo (el BCE no publica
pesos colombianos ni soles). Recuerda la última moneda usada por viaje: en
Japón todo es en yenes.

Pruebas en Node: un pago salda y un pago repetido cuenta una vez; un pago no
infla el total; anular un pago regresa la deuda; pago parcial; pagos
malformados (a sí mismo, negativo, fraccionario, texto) se ignoran; el sello
manda sobre la tabla; un sello de otra base se ignora; el acordado manda
sobre el sello y gana el último; quitarlo regresa al sello; con pagos y
monedas mezcladas los saldos siguen sumando cero.
