--
-- This file is part of Anastasis
-- Copyright (C) 2026 Anastasis SARL
--
-- ANASTASIS is free software; you can redistribute it and/or modify it under the
-- terms of the GNU General Public License as published by the Free Software
-- Foundation; either version 3, or (at your option) any later version.
--
-- ANASTASIS is distributed in the hope that it will be useful, but WITHOUT ANY
-- WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
-- A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License along with
-- ANASTASIS; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
--

-- Everything in one big transaction
BEGIN;

-- Check patch versioning is in place.
SELECT _v.register_patch('stasis-0004', NULL, NULL);

SET search_path TO anastasis;

-- A provider may now price its service in several currencies at once, so an
-- amount is only meaningful together with the currency it is in.  The old
-- taler_amount type has no room for one: it was written on the assumption
-- that the whole provider used exactly one currency, which was then read out
-- of [anastasis] CURRENCY at result-parsing time.  Replace it with the
-- merchant's taler_amount_currency, which carries the currency in the row.
--
-- anastasis_do_insert_recdoc_payment() names taler_amount in its signature
-- and therefore depends on the type.  It has to be dropped before the type
-- can be, and dropping it here costs nothing: every anastasis-dbinit run
-- recreates all stored procedures from procedures.sql.  Doing it explicitly
-- rather than with DROP TYPE ... CASCADE keeps the dependency visible, and
-- makes an unexpected second dependent an error instead of a silent drop.
DROP FUNCTION IF EXISTS anastasis_do_insert_recdoc_payment;

CREATE TYPE taler_amount_currency
  AS
  (val INT8
  ,frac INT4
  ,curr VARCHAR(12)
  );
COMMENT ON TYPE taler_amount_currency
  IS 'Stores an amount with its currency, fraction is in units of 1/100000000 of the base value';

-- Existing payment rows were all made in the provider's single configured
-- currency, but that currency is in the configuration file and not reachable
-- from here.  Stamp them KUDOS: these three columns have never been read back
-- by any released version (the getters either did not select the column or
-- selected it without binding a result), so no decision depends on the value
-- being right, and the alternative -- a NULL currency -- would make them
-- unparseable rather than merely historical.
ALTER TABLE anastasis_truth_payment
  ALTER COLUMN amount TYPE taler_amount_currency
  USING ROW((amount).val, (amount).frac, 'KUDOS')::taler_amount_currency;
COMMENT ON COLUMN anastasis_truth_payment.amount
  IS 'Amount we were paid, in the currency the user chose to pay in. Rows migrated from before multi-currency support read KUDOS regardless of what was actually paid.';

ALTER TABLE anastasis_recdoc_payment
  ALTER COLUMN amount TYPE taler_amount_currency
  USING ROW((amount).val, (amount).frac, 'KUDOS')::taler_amount_currency;
COMMENT ON COLUMN anastasis_recdoc_payment.amount
  IS 'Amount we were paid, in the currency the user chose to pay in. Rows migrated from before multi-currency support read KUDOS regardless of what was actually paid.';

ALTER TABLE anastasis_challenge_payment
  ALTER COLUMN amount TYPE taler_amount_currency
  USING ROW((amount).val, (amount).frac, 'KUDOS')::taler_amount_currency;
COMMENT ON COLUMN anastasis_challenge_payment.amount
  IS 'Amount we were paid, in the currency the user chose to pay in. This is what a refund of the challenge returns, so it must be the currency actually received. Rows migrated from before multi-currency support read KUDOS regardless of what was actually paid.';

-- The IBAN column is different: it *is* read back, by
-- ANASTASIS_DB_iterate_auth_iban_transfers(), and the IBAN plugin compares
-- what it finds against the expected transfer amount.  Stamping it KUDOS
-- would make every pre-upgrade transfer fail that comparison and silently
-- invalidate all in-flight IBAN challenges.  Leave the currency NULL here;
-- anastasis-dbinit fills it in from [anastasis] CURRENCY, which is the one
-- place that knows the bank account's currency.
ALTER TABLE anastasis_auth_iban_in
  ALTER COLUMN credit TYPE taler_amount_currency
  USING ROW((credit).val, (credit).frac, NULL)::taler_amount_currency;
COMMENT ON COLUMN anastasis_auth_iban_in.credit
  IS 'Amount we were credited, in the currency of the provider bank account ([anastasis] CURRENCY)';

DROP TYPE taler_amount;

COMMIT;
