// transfer_between_cajas
// Two-input morphism. Conservation rule (Caja.saldo grouped by currency)
// is checked by the kernel against the produced ops; the script just emits
// the deltas.
//
// states.source / states.dest: the two Caja records.
// ids.source / ids.dest:       their UUIDs (string form).
// params: { monto:i64, timestamp:str, memo:str, transfer_id:str }

let source = input.states.source;
let dest   = input.states.dest;
let monto  = input.params.monto;

if monto <= 0 {
    throw "monto debe ser positivo"
}
if source.currency != dest.currency {
    throw "transferencia exige misma moneda; source=" + source.currency + " dest=" + dest.currency
}
let transfer_id = input.params.transfer_id;
if type_of(transfer_id) == "()" {
    throw "params.transfer_id es obligatorio (idempotencia)"
}

let new_source_saldo = source.saldo - monto;
let new_dest_saldo   = dest.saldo + monto;

[
    #{
        op: "set",
        path: #{ entity: "Caja", id: input.ids.source, field: "saldo" },
        value: new_source_saldo,
    },
    #{
        op: "set",
        path: #{ entity: "Caja", id: input.ids.dest, field: "saldo" },
        value: new_dest_saldo,
    },
    #{
        op: "create",
        entity: "Transferencia",
        id: transfer_id,
        data: #{
            id: transfer_id,
            source_caja_id: input.ids.source,
            dest_caja_id:   input.ids.dest,
            monto:          monto,
            currency:       source.currency,
            timestamp:      input.params.timestamp,
            memo:           input.params.memo,
        },
    },
]
