--
-- This file is part of TALER
-- Copyright (C) 2023 Taler Systems SA
--
-- TALER 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.
--
-- TALER 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
-- TALER; see the file COPYING.  If not, see <http://www.gnu.org/licenses/>
--

CREATE OR REPLACE FUNCTION exchange_do_insert_aml_officer(
  IN in_decider_pub BYTEA,
  IN in_master_sig BYTEA,
  IN in_decider_name TEXT,
  IN in_is_active BOOLEAN,
  IN in_read_only BOOLEAN,
  IN in_last_change INT8,
  OUT out_last_change INT8)
LANGUAGE plpgsql
AS $$
BEGIN
-- aml_staff is append-only: one row per status change, the status in force
-- being the row with the greatest last_change.  Never UPDATE a row here.
-- The history is what lets an auditor say who was allowed to decide when,
-- and an in-place update leaves aml_staff_uuid where it was, so it is
-- invisible to every cursor that walks the table by its serial ID --
-- taler-auditor-sync would never carry the change to the auditor at all.

-- Check the new status is more recent than the one in force...
SELECT last_change
  INTO out_last_change
  FROM exchange.aml_staff
  WHERE decider_pub=in_decider_pub
  ORDER BY last_change DESC
  LIMIT 1;

IF NOT FOUND
THEN
  out_last_change=0;
ELSIF out_last_change >= in_last_change
THEN
  -- Refuse to insert an older status; leave out_last_change at the
  -- last_change we do have, so the caller can tell it was refused.
  RETURN;
END IF;

INSERT INTO exchange.aml_staff
  (decider_pub
  ,master_sig
  ,decider_name
  ,is_active
  ,read_only
  ,last_change
  ) VALUES
  (in_decider_pub
  ,in_master_sig
  ,in_decider_name
  ,in_is_active
  ,in_read_only
  ,in_last_change)
 -- A concurrent transaction may have appended the very same status
 -- between the SELECT above and here; that is a replay, not an error.
 ON CONFLICT (decider_pub, last_change) DO NOTHING;
END $$;


COMMENT ON FUNCTION exchange_do_insert_aml_officer(BYTEA, BYTEA, TEXT, BOOL, BOOL, INT8)
  IS 'Appends an AML staff status change, making sure it is more recent than the status currently in force';
