Line data Source code
1 : /*
2 : This file is part of TALER
3 : Copyright (C) 2017-2020 Taler Systems SA
4 :
5 : TALER is free software; you can redistribute it and/or modify it under the
6 : terms of the GNU General Public License as published by the Free Software
7 : Foundation; either version 3, or (at your option) any later version.
8 :
9 : TALER is distributed in the hope that it will be useful, but WITHOUT ANY
10 : WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 : A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12 :
13 : You should have received a copy of the GNU General Public License along with
14 : TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
15 : */
16 : /**
17 : * @file exchangedb/exchangedb_transactions.c
18 : * @brief Logic to compute transaction totals of a transaction list for a coin
19 : * @author Christian Grothoff
20 : */
21 : #include "exchange-database/free_coin_transaction_list.h"
22 :
23 :
24 : enum GNUNET_GenericReturnValue
25 4 : TALER_EXCHANGEDB_calculate_transaction_list_totals (
26 : struct TALER_EXCHANGEDB_TransactionList *tl,
27 : const struct TALER_Amount *off,
28 : struct TALER_Amount *ret)
29 : {
30 4 : struct TALER_Amount spent = *off;
31 : struct TALER_Amount refunded;
32 : struct TALER_Amount deposit_fee;
33 : bool have_refund;
34 :
35 4 : GNUNET_assert (GNUNET_OK ==
36 : TALER_amount_set_zero (spent.currency,
37 : &refunded));
38 4 : GNUNET_assert (GNUNET_OK ==
39 : TALER_amount_set_zero (spent.currency,
40 : &deposit_fee));
41 4 : have_refund = false;
42 4 : for (struct TALER_EXCHANGEDB_TransactionList *pos = tl;
43 11 : NULL != pos;
44 7 : pos = pos->next)
45 : {
46 7 : switch (pos->type)
47 : {
48 3 : case TALER_EXCHANGEDB_TT_DEPOSIT:
49 : /* spent += pos->amount_with_fee */
50 3 : if (0 >
51 3 : TALER_amount_add (&spent,
52 : &spent,
53 3 : &pos->details.deposit->amount_with_fee))
54 : {
55 0 : GNUNET_break (0);
56 0 : return GNUNET_SYSERR;
57 : }
58 3 : deposit_fee = pos->details.deposit->deposit_fee;
59 3 : break;
60 1 : case TALER_EXCHANGEDB_TT_MELT:
61 : /* spent += pos->amount_with_fee */
62 1 : if (0 >
63 1 : TALER_amount_add (&spent,
64 : &spent,
65 1 : &pos->details.melt->amount_with_fee))
66 : {
67 0 : GNUNET_break (0);
68 0 : return GNUNET_SYSERR;
69 : }
70 1 : break;
71 1 : case TALER_EXCHANGEDB_TT_REFUND:
72 : /* refunded += pos->refund_amount - pos->refund_fee */
73 1 : if (0 >
74 1 : TALER_amount_add (&refunded,
75 : &refunded,
76 1 : &pos->details.refund->refund_amount))
77 : {
78 0 : GNUNET_break (0);
79 0 : return GNUNET_SYSERR;
80 : }
81 1 : if (0 >
82 1 : TALER_amount_add (&spent,
83 : &spent,
84 1 : &pos->details.refund->refund_fee))
85 : {
86 0 : GNUNET_break (0);
87 0 : return GNUNET_SYSERR;
88 : }
89 1 : have_refund = true;
90 1 : break;
91 0 : case TALER_EXCHANGEDB_TT_RECOUP_REFRESH_RECEIVER:
92 : /* refunded += pos->value */
93 0 : if (0 >
94 0 : TALER_amount_add (&refunded,
95 : &refunded,
96 0 : &pos->details.old_coin_recoup->value))
97 : {
98 0 : GNUNET_break (0);
99 0 : return GNUNET_SYSERR;
100 : }
101 0 : break;
102 0 : case TALER_EXCHANGEDB_TT_RECOUP_WITHDRAW:
103 : /* spent += pos->value */
104 0 : if (0 >
105 0 : TALER_amount_add (&spent,
106 : &spent,
107 0 : &pos->details.recoup->value))
108 : {
109 0 : GNUNET_break (0);
110 0 : return GNUNET_SYSERR;
111 : }
112 0 : break;
113 0 : case TALER_EXCHANGEDB_TT_RECOUP_REFRESH:
114 : /* spent += pos->value */
115 0 : if (0 >
116 0 : TALER_amount_add (&spent,
117 : &spent,
118 0 : &pos->details.recoup_refresh->value))
119 : {
120 0 : GNUNET_break (0);
121 0 : return GNUNET_SYSERR;
122 : }
123 0 : break;
124 1 : case TALER_EXCHANGEDB_TT_PURSE_DEPOSIT:
125 : /* spent += pos->amount_with_fee */
126 1 : if (0 >
127 1 : TALER_amount_add (&spent,
128 : &spent,
129 1 : &pos->details.purse_deposit->amount))
130 : {
131 0 : GNUNET_break (0);
132 0 : return GNUNET_SYSERR;
133 : }
134 1 : deposit_fee = pos->details.purse_deposit->deposit_fee;
135 1 : break;
136 0 : case TALER_EXCHANGEDB_TT_PURSE_REFUND:
137 : /* refunded += pos->refund_amount - pos->refund_fee */
138 0 : if (0 >
139 0 : TALER_amount_add (&refunded,
140 : &refunded,
141 0 : &pos->details.purse_refund->refund_amount))
142 : {
143 0 : GNUNET_break (0);
144 0 : return GNUNET_SYSERR;
145 : }
146 0 : if (0 >
147 0 : TALER_amount_add (&spent,
148 : &spent,
149 0 : &pos->details.purse_refund->refund_fee))
150 : {
151 0 : GNUNET_break (0);
152 0 : return GNUNET_SYSERR;
153 : }
154 0 : have_refund = true;
155 0 : break;
156 1 : case TALER_EXCHANGEDB_TT_RESERVE_OPEN:
157 : /* spent += pos->amount_with_fee */
158 1 : if (0 >
159 1 : TALER_amount_add (&spent,
160 : &spent,
161 1 : &pos->details.reserve_open->coin_contribution))
162 : {
163 0 : GNUNET_break (0);
164 0 : return GNUNET_SYSERR;
165 : }
166 1 : break;
167 : }
168 : }
169 4 : if (have_refund)
170 : {
171 : /* If we gave any refund, also discount ONE deposit fee */
172 1 : if (0 >
173 1 : TALER_amount_add (&refunded,
174 : &refunded,
175 : &deposit_fee))
176 : {
177 0 : GNUNET_break (0);
178 0 : return GNUNET_SYSERR;
179 : }
180 : }
181 : /* spent = spent - refunded */
182 4 : if (0 >
183 4 : TALER_amount_subtract (&spent,
184 : &spent,
185 : &refunded))
186 : {
187 0 : GNUNET_break (0);
188 0 : return GNUNET_SYSERR;
189 : }
190 4 : *ret = spent;
191 4 : return GNUNET_OK;
192 : }
|