--
-- This file is part of TALER
-- Copyright (C) 2026 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/>
--

DROP FUNCTION IF EXISTS merchant_do_delete_order;
CREATE FUNCTION merchant_do_delete_order (
  IN in_order_id TEXT,
  IN in_now INT8,
  IN in_force BOOLEAN,
  OUT out_deleted BOOLEAN)
LANGUAGE plpgsql
AS $$
DECLARE
  my_paid BOOLEAN;
  my_claimed BOOLEAN;
BEGIN

-- An order that was claimed by a wallet has a row in
-- merchant_contract_terms; the row in merchant_orders (if any) then
-- merely holds the not-yet-claimed proposal.  Both deletions must
-- happen together, or a failure between them would leave the contract
-- terms behind without the order.  Doing both in one stored procedure
-- gives us that atomicity even though the caller runs in autocommit.
SELECT paid
  INTO my_paid
  FROM merchant_contract_terms
 WHERE order_id=in_order_id
   FOR UPDATE;
my_claimed = FOUND;

DELETE FROM merchant_orders
 WHERE order_id=in_order_id
   AND (  (pay_deadline < in_now)
       OR (NOT my_claimed)
       OR (in_force AND (NOT my_paid)) );
out_deleted = FOUND;

IF NOT in_force
THEN
  RETURN;
END IF;

DELETE FROM merchant_contract_terms
 WHERE order_id=in_order_id
   AND NOT paid;
IF FOUND
THEN
  out_deleted = TRUE;
END IF;

END $$;

COMMENT ON FUNCTION merchant_do_delete_order(TEXT, INT8, BOOLEAN)
  IS 'Deletes an order. The unclaimed proposal is removed if the pay deadline'
     ' has passed, if the order was never claimed, or (with in_force) if it'
     ' was claimed but not paid.  With in_force the claimed-but-unpaid'
     ' contract terms are removed in the same transaction.  Returns'
     ' out_deleted=TRUE if anything was deleted.';
