# Schema Nickel para `treasury` (Caja + Movimiento + Transferencia).

let positive_int = std.contract.from_predicate (fun n =>
  std.is_number n && n > 0
) in

let non_negative_int = std.contract.from_predicate (fun n =>
  std.is_number n && n >= 0
) in

let currency_iso = std.contract.from_predicate (fun s =>
  std.is_string s && std.string.length s == 3
) in

let movimiento_tipo = std.contract.from_predicate (fun s =>
  std.is_string s && std.array.elem s ["in", "out"]
) in

{
  Caja = {
    id | String,
    name | String,
    saldo | non_negative_int,
    currency | currency_iso,
  },

  Movimiento = {
    id | String,
    caja_id | String,
    monto | positive_int,
    tipo | movimiento_tipo,
    timestamp | String,
    memo | String | optional,
  },

  # Patrón obligatorio para record + cross-field predicate: chain
  # via Sequence (aplicar `from_predicate` directo al record rebota
  # con "missing definition").
  Transferencia = std.contract.Sequence [
    {
      id | String,
      source_caja_id | String,
      dest_caja_id | String,
      monto | positive_int,
      currency | currency_iso,
      timestamp | String,
      memo | String | optional,
    },
    std.contract.from_predicate (fun r =>
      r.source_caja_id != r.dest_caja_id
    ),
  ],
}
