summaryrefslogtreecommitdiff
path: root/src/backenddb/pg_insert_deposit_to_transfer.sql
blob: b2e587f124146dc742682a6f1a1e7ea144795655 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
--
-- This file is part of TALER
-- Copyright (C) 2024 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 merchant_insert_deposit_to_transfer (
  IN in_deposit_serial INT8,
  IN in_amount_with_fee taler_amount_currency,
  IN in_execution_time INT8,
  IN in_exchange_sig BYTEA,
  IN in_exchange_pub BYTEA,
  IN in_wtid BYTEA,
  OUT out_wire_pending_cleared BOOL,
  OUT out_conflict BOOL,
  OUT out_no_exchange_pub BOOL)
LANGUAGE plpgsql
AS $$
DECLARE
  my_signkey_serial INT8;
DECLARE
  my_confirmed BOOL;
DECLARE
  my_decose INT8;
DECLARE
  my_order_serial INT8;
BEGIN

-- Find exchange sign key
SELECT signkey_serial
  INTO my_signkey_serial
  FROM merchant_exchange_signing_keys
 WHERE exchange_pub=in_exchange_pub
   ORDER BY start_date DESC
   LIMIT 1;

IF NOT FOUND
THEN
  out_no_exchange_pub=TRUE;
  out_conflict=FALSE;
  out_wire_pending_cleared=FALSE;
  RETURN;
END IF;
out_no_exchange_pub=FALSE;


-- Try to insert new wire transfer
INSERT INTO merchant_deposit_to_transfer
  (deposit_serial
  ,coin_contribution_value
  ,wtid
  ,execution_time
  ,signkey_serial
  ,exchange_sig
  )
  VALUES
  (in_deposit_serial
  ,in_amount_with_fee
  ,in_wtid
  ,in_execution_time
  ,my_signkey_serial
  ,in_exchange_sig
  )
  ON CONFLICT DO NOTHING;

IF NOT FOUND
THEN
  -- Same or conflicting wire transfer existed in the table already
  -- Note: we don't distinguish here between
  -- conflict and duplicate. Do we need to?
  out_conflict=TRUE;
  out_wire_pending_cleared=FALSE;
  return;
END IF;
out_conflict=FALSE;


-- Check if we already imported the (confirmed)
-- wire transfer *and* if it is mapped to this deposit.
PERFORM
  FROM merchant_transfers mt
  JOIN merchant_transfer_to_coin mtc
    USING (credit_serial)
  WHERE mt.wtid=in_wtid
    AND mt.confirmed
    AND mtc.deposit_serial=in_deposit_serial;

IF NOT FOUND
THEN
  out_wire_pending_cleared=FALSE;
  RETURN;
END IF;


RAISE NOTICE 'checking affected deposit confirmation for completion';

SELECT deposit_confirmation_serial
  INTO my_decose
  FROM merchant_deposits
 WHERE deposit_serial=in_deposit_serial;

-- we made a change, check about clearing wire_pending
-- for the entire deposit confirmation
UPDATE merchant_deposit_confirmations
  SET wire_pending=FALSE
  WHERE (deposit_confirmation_serial=decose)
    AND NOT EXISTS
    (SELECT 1
      FROM merchant_deposits md
      LEFT JOIN merchant_deposit_to_transfer mdtt
        USING (wtid)
      WHERE md.deposit_confirmation_serial=my_decose
        AND mdtt.credit_serial IS NULL);
-- credit_serial will be NULL due to LEFT JOIN
-- if we do not have an entry in mdtt for the deposit
-- and thus some entry in md was not yet wired.

IF NOT FOUND
THEN
  out_wire_pending_cleared=FALSE;
  RETURN;
END IF;
out_wire_pending_cleared=TRUE;


RAISE NOTICE 'checking affected contracts for completion';

-- Check if all deposit confirmations of the same
-- contract are now wired.
SELECT deposit_confirmation_serial
  INTO my_order_serial
  FROM merchant_deposit_confirmations
 WHERE deposit_confirmation_serial=my_decose;
-- The above MUST succeed by invariants.

-- Check about setting 'wired' for the contract term.
-- Note: the same contract may be paid from
-- multiple exchanges, so we need to check if
-- payments were wired from all of them!
UPDATE merchant_contract_terms
  SET wired=TRUE
  WHERE (order_serial=my_order_serial)
    AND NOT EXISTS
    (SELECT 1
       FROM merchant_deposit_confirmations mdc
      WHERE mdc.wire_pending
        AND mdc.order_serial=my_order_serial);

END $$;