4
4
import lombok .RequiredArgsConstructor ;
5
5
import lombok .extern .slf4j .Slf4j ;
6
6
import lombok .val ;
7
+ import org .cardanofoundation .lob .app .accounting_reporting_core .domain .core .TransactionProblem ;
7
8
import org .cardanofoundation .lob .app .accounting_reporting_core .domain .core .TransactionType ;
8
9
import org .cardanofoundation .lob .app .accounting_reporting_core .domain .core .ValidationStatus ;
9
10
import org .cardanofoundation .lob .app .accounting_reporting_core .domain .entity .Rejection ;
10
11
import org .cardanofoundation .lob .app .accounting_reporting_core .domain .entity .TransactionEntity ;
12
+ import org .cardanofoundation .lob .app .accounting_reporting_core .resource .requests .TransactionId ;
13
+ import org .cardanofoundation .lob .app .accounting_reporting_core .resource .requests .TransactionsRequest ;
11
14
import org .cardanofoundation .lob .app .accounting_reporting_core .service .internal .LedgerService ;
15
+ import org .springframework .dao .DataAccessException ;
12
16
import org .springframework .stereotype .Service ;
13
17
import org .springframework .transaction .annotation .Transactional ;
14
18
import org .zalando .problem .Problem ;
15
19
20
+ import java .util .ArrayList ;
16
21
import java .util .List ;
17
22
import java .util .Optional ;
18
23
import java .util .Set ;
19
24
import java .util .stream .Collectors ;
20
25
21
- import static org .cardanofoundation .lob .app .accounting_reporting_core .domain .core .ValidationStatus .FAILED ;
26
+ import static org .cardanofoundation .lob .app .accounting_reporting_core .domain .core .TransactionStatus .FAIL ;
27
+ import static org .springframework .transaction .annotation .Propagation .REQUIRES_NEW ;
22
28
23
29
@ Service
24
30
@ Slf4j
@@ -30,119 +36,220 @@ public class TransactionRepositoryGateway {
30
36
private final TransactionRepository transactionRepository ;
31
37
private final LedgerService ledgerService ;
32
38
33
- @ Transactional
34
- public Either <Problem , Boolean > approveTransaction (String transactionId ) {
39
+ @ Transactional (propagation = REQUIRES_NEW )
40
+ // TODO optimise performance because we have to load transaction from db each time and we don't save it in bulk
41
+ private Either <TransactionProblem , TransactionEntity > approveTransaction (String transactionId ) {
35
42
log .info ("Approving transaction: {}" , transactionId );
36
43
37
44
val txM = transactionRepository .findById (transactionId );
38
45
39
46
if (txM .isEmpty ()) {
40
- return Either . left ( Problem .builder ()
47
+ val problem = Problem .builder ()
41
48
.withTitle ("TX_NOT_FOUND" )
42
49
.withDetail (STR ."Transaction with id \{transactionId } not found" )
43
50
.with ("transactionId" , transactionId )
44
- .build ()
45
- );
51
+ .build ();
52
+
53
+ return Either .left (new TransactionProblem (transactionId , problem ));
46
54
}
47
55
48
56
val tx = txM .orElseThrow ();
49
57
50
- if (tx .getAutomatedValidationStatus () == FAILED ) {
51
- return Either . left ( Problem .builder ()
58
+ if (tx .getStatus () == FAIL ) {
59
+ val problem = Problem .builder ()
52
60
.withTitle ("CANNOT_APPROVE_FAILED_TX" )
53
61
.withDetail (STR ."Cannot approve a failed transaction, transactionId: \{transactionId }" )
54
62
.with ("transactionId" , transactionId )
55
- .build ()
56
- );
63
+ .build ();
64
+
65
+ return Either .left (new TransactionProblem (transactionId , problem ));
57
66
}
58
67
59
68
tx .setTransactionApproved (true );
60
69
61
70
val savedTx = transactionRepository .save (tx );
62
- val organisationId = savedTx .getOrganisation ().getId ();
63
71
64
- if (savedTx .getTransactionApproved ()) {
65
- ledgerService .checkIfThereAreTransactionsToDispatch (organisationId , Set .of (savedTx ));
72
+ return Either .right (savedTx );
73
+ }
74
+
75
+ @ Transactional (propagation = REQUIRES_NEW )
76
+ // TODO optimise performance because we have to load transaction from db each time and we don't save it in bulk
77
+ private Either <TransactionProblem , TransactionEntity > approveTransactionsDispatch (String transactionId ) {
78
+ log .info ("Approving transaction to dispatch: {}" , transactionId );
79
+
80
+ val txM = transactionRepository .findById (transactionId );
81
+
82
+ if (txM .isEmpty ()) {
83
+ val problem = Problem .builder ()
84
+ .withTitle ("TX_NOT_FOUND" )
85
+ .withDetail (STR ."Transaction with id \{transactionId } not found" )
86
+ .with ("transactionId" , transactionId )
87
+ .build ();
66
88
67
- return Either .right ( savedTx . getTransactionApproved ( ));
89
+ return Either .left ( new TransactionProblem ( transactionId , problem ));
68
90
}
69
91
70
- return Either .right (false );
71
- }
92
+ val tx = txM .orElseThrow ();
72
93
73
- @ Transactional
74
- public Set <String > approveTransactions (String organisationId , Set <String > transactionIds ) {
75
- log .info ("Approving transactions: {}" , transactionIds );
94
+ if (tx .getStatus () == FAIL ) {
95
+ val problem = Problem .builder ()
96
+ .withTitle ("CANNOT_APPROVE_FAILED_TX" )
97
+ .withDetail (STR ."Cannot approve a failed transaction, transactionId: \{transactionId }" )
98
+ .with ("transactionId" , transactionId )
99
+ .build ();
76
100
77
- val transactions = transactionRepository .findAllById (transactionIds )
78
- .stream ()
79
- .filter (tx -> tx .getAutomatedValidationStatus () != FAILED )
80
- .peek (tx -> tx .setTransactionApproved (true ))
81
- .collect (Collectors .toSet ());
101
+ return Either .left (new TransactionProblem (transactionId , problem ));
102
+ }
82
103
83
- val savedTxs = transactionRepository .saveAll (transactions );
104
+ if (!tx .getTransactionApproved ()) {
105
+ val problem = Problem .builder ()
106
+ .withTitle ("TX_NOT_APPROVED" )
107
+ .withDetail (STR ."Cannot approve a transaction that has not been approved before, transactionId: \{transactionId }" )
108
+ .with ("transactionId" , transactionId )
109
+ .build ();
110
+
111
+ return Either .left (new TransactionProblem (transactionId , problem ));
112
+ }
113
+
114
+ tx .setLedgerDispatchApproved (true );
84
115
85
- ledgerService . checkIfThereAreTransactionsToDispatch ( organisationId , Set . copyOf ( savedTxs ) );
116
+ val savedTx = transactionRepository . save ( tx );
86
117
87
- return savedTxs . stream (). map ( TransactionEntity :: getId ). collect ( Collectors . toSet () );
118
+ return Either . right ( savedTx );
88
119
}
89
120
90
- @ Transactional
91
- public Set <String > approveTransactionsDispatch (String organisationId , Set <String > transactionIds ) {
92
- log .info ("Approving transactions dispatch: {}" , transactionIds );
121
+ public List <Either <TransactionProblem , TransactionEntity >> approveTransactions (TransactionsRequest transactionsRequest ) {
122
+ val organisationId = transactionsRequest .getOrganisationId ();
93
123
94
- val transactions = transactionRepository . findAllById ( transactionIds )
124
+ val transactionIds = transactionsRequest . getTransactionIds ( )
95
125
.stream ()
96
- .filter (tx -> tx .getAutomatedValidationStatus () != FAILED )
97
- .peek (tx -> tx .setLedgerDispatchApproved (true ))
126
+ .map (TransactionId ::getId )
98
127
.collect (Collectors .toSet ());
99
128
100
- val savedTxs = transactionRepository .saveAll (transactions );
129
+ val transactionsApprovalResponseListE = new ArrayList <Either <TransactionProblem , TransactionEntity >>();
130
+ for (val transactionId : transactionIds ) {
131
+ try {
132
+ val transactionEntities = approveTransaction (transactionId );
101
133
102
- ledgerService .checkIfThereAreTransactionsToDispatch (organisationId , Set .copyOf (savedTxs ));
134
+ transactionsApprovalResponseListE .add (transactionEntities );
135
+ } catch (DataAccessException dae ) {
136
+ log .error ("Error approving transaction: {}" , transactionId , dae );
103
137
104
- return savedTxs .stream ().map (TransactionEntity ::getId ).collect (Collectors .toSet ());
105
- }
138
+ val problem = Problem .builder ()
139
+ .withTitle ("DB_ERROR" )
140
+ .withDetail (STR ."DB error approving transaction: \{transactionId }" )
141
+ .with ("transactionId" , transactionId )
142
+ .with ("error" , dae .getMessage ())
143
+ .build ();
106
144
107
- @ Transactional
108
- public Either < Problem , Boolean > approveTransactionDispatch ( String transactionId ) {
109
- log . info ( "Approving transaction dispatch: {}" , transactionId );
145
+ transactionsApprovalResponseListE . add ( Either . left ( new TransactionProblem ( transactionId , problem )));
146
+ }
147
+ }
110
148
111
- val txM = transactionRepository .findById (transactionId );
149
+ val transactionSuccesses = transactionsApprovalResponseListE .stream ()
150
+ .filter (Either ::isRight )
151
+ .map (Either ::get )
152
+ .collect (Collectors .toSet ());
112
153
113
- if (txM .isEmpty ()) {
114
- return Either .left (Problem .builder ()
115
- .withTitle ("TX_NOT_FOUND" )
116
- .withDetail (STR ."Transaction with id \{transactionId } not found" )
117
- .with ("transactionId" , transactionId )
118
- .build ()
119
- );
120
- }
154
+ ledgerService .checkIfThereAreTransactionsToDispatch (organisationId , transactionSuccesses );
121
155
122
- val tx = txM .orElseThrow ();
156
+ return transactionsApprovalResponseListE ;
157
+ }
123
158
124
- if (tx .getAutomatedValidationStatus () == FAILED ) {
125
- return Either .left (Problem .builder ()
126
- .withTitle ("CANNOT_APPROVE_FAILED_TX" )
127
- .withDetail (STR ."Cannot approve dispatch for a failed transaction, transactionId: \{transactionId }" )
128
- .with ("transactionId" , transactionId )
129
- .build ()
130
- );
131
- }
159
+ public List <Either <TransactionProblem , TransactionEntity >> approveTransactionsDispatch (TransactionsRequest transactionsRequest ) {
160
+ val organisationId = transactionsRequest .getOrganisationId ();
132
161
133
- tx .setLedgerDispatchApproved (true );
162
+ val transactionIds = transactionsRequest .getTransactionIds ()
163
+ .stream ()
164
+ .map (TransactionId ::getId )
165
+ .collect (Collectors .toSet ());
134
166
135
- val savedTx = transactionRepository .save (tx );
167
+ val transactionsApprovalResponseListE = new ArrayList <Either <TransactionProblem , TransactionEntity >>();
168
+ for (val transactionId : transactionIds ) {
169
+ try {
170
+ val transactionEntities = approveTransactionsDispatch (transactionId );
136
171
137
- if (savedTx .getLedgerDispatchApproved ()) {
138
- ledgerService .checkIfThereAreTransactionsToDispatch (savedTx .getOrganisation ().getId (), Set .of (savedTx ));
172
+ transactionsApprovalResponseListE .add (transactionEntities );
173
+ } catch (DataAccessException dae ) {
174
+ log .error ("Error approving transaction publish: {}" , transactionId , dae );
139
175
140
- return Either .right (savedTx .getLedgerDispatchApproved ());
176
+ val problem = Problem .builder ()
177
+ .withTitle ("DB_ERROR" )
178
+ .withDetail (STR ."DB error approving transaction publish:\{transactionId }" )
179
+ .with ("transactionId" , transactionId )
180
+ .with ("error" , dae .getMessage ())
181
+ .build ();
182
+
183
+ transactionsApprovalResponseListE .add (Either .left (new TransactionProblem (transactionId , problem )));
184
+ }
141
185
}
142
186
143
- return Either .right (false );
187
+ val transactionSuccesses = transactionsApprovalResponseListE .stream ()
188
+ .filter (Either ::isRight )
189
+ .map (Either ::get )
190
+ .collect (Collectors .toSet ());
191
+
192
+ ledgerService .checkIfThereAreTransactionsToDispatch (organisationId , transactionSuccesses );
193
+
194
+ return transactionsApprovalResponseListE ;
144
195
}
145
196
197
+ // @Transactional
198
+ // public Set<String> approveTransactionsDispatch(String organisationId, Set<String> transactionIds) {
199
+ // log.info("Approving transactions dispatch: {}", transactionIds);
200
+ //
201
+ // val transactions = transactionRepository.findAllById(transactionIds)
202
+ // .stream()
203
+ // .filter(tx -> tx.getAutomatedValidationStatus() != FAILED)
204
+ // .peek(tx -> tx.setLedgerDispatchApproved(true))
205
+ // .collect(Collectors.toSet());
206
+ //
207
+ // val savedTxs = transactionRepository.saveAll(transactions);
208
+ //
209
+ // ledgerService.checkIfThereAreTransactionsToDispatch(organisationId, Set.copyOf(savedTxs));
210
+ //
211
+ // return savedTxs.stream().map(TransactionEntity::getId).collect(Collectors.toSet());
212
+ // }
213
+
214
+ // @Transactional
215
+ // public Either<Problem, Boolean> approveTransactionDispatch(String transactionId) {
216
+ // log.info("Approving transaction dispatch: {}", transactionId);
217
+ //
218
+ // val txM = transactionRepository.findById(transactionId);
219
+ //
220
+ // if (txM.isEmpty()) {
221
+ // return Either.left(Problem.builder()
222
+ // .withTitle("TX_NOT_FOUND")
223
+ // .withDetail(STR."Transaction with id \{transactionId} not found")
224
+ // .with("transactionId", transactionId)
225
+ // .build()
226
+ // );
227
+ // }
228
+ //
229
+ // val tx = txM.orElseThrow();
230
+ //
231
+ // if (tx.getAutomatedValidationStatus() == FAILED) {
232
+ // return Either.left(Problem.builder()
233
+ // .withTitle("CANNOT_APPROVE_FAILED_TX")
234
+ // .withDetail(STR."Cannot approve dispatch for a failed transaction, transactionId: \{transactionId}")
235
+ // .with("transactionId", transactionId)
236
+ // .build()
237
+ // );
238
+ // }
239
+ //
240
+ // tx.setLedgerDispatchApproved(true);
241
+ //
242
+ // val savedTx = transactionRepository.save(tx);
243
+ //
244
+ // if (savedTx.getLedgerDispatchApproved()) {
245
+ // ledgerService.checkIfThereAreTransactionsToDispatch(savedTx.getOrganisation().getId(), Set.of(savedTx));
246
+ //
247
+ // return Either.right(savedTx.getLedgerDispatchApproved());
248
+ // }
249
+ //
250
+ // return Either.right(false);
251
+ // }
252
+
146
253
public Either <Problem , Boolean > changeTransactionComment (String txId , String userComment ) {
147
254
val txM = transactionRepository .findById (txId );
148
255
@@ -205,16 +312,15 @@ public Optional<TransactionEntity> findById(String transactionId) {
205
312
}
206
313
207
314
public List <TransactionEntity > findByAllId (Set <String > transactionIds ) {
208
-
209
315
return transactionRepository .findAllById (transactionIds );
210
316
}
211
317
212
- private static Set <String > transactionIds (Set <TransactionEntity > transactions ) {
213
- return transactions
214
- .stream ()
215
- .map (TransactionEntity ::getId )
216
- .collect (Collectors .toSet ());
217
- }
318
+ // private static Set<String> transactionIds(Set<TransactionEntity> transactions) {
319
+ // return transactions
320
+ // .stream()
321
+ // .map(TransactionEntity::getId)
322
+ // .collect(Collectors.toSet());
323
+ // }
218
324
219
325
public List <TransactionEntity > findAllByStatus (String organisationId ,
220
326
List <ValidationStatus > validationStatuses ,
@@ -225,4 +331,5 @@ public List<TransactionEntity> findAllByStatus(String organisationId,
225
331
public List <TransactionEntity > listAll () {
226
332
return transactionRepository .findAll ();
227
333
}
334
+
228
335
}
0 commit comments