Skip to content

Commit d0de2e3

Browse files
Remove duplicate transactions from input CSV (#63)
* remove duplicate transactions * enable ordering * camel route works when ordering is enabled * GOV-325: set note for duplicate transactions * GOV-325: perform deduplication when enabled * add null pointer checks * address review changes * address review comments
1 parent d2680a7 commit d0de2e3

4 files changed

Lines changed: 85 additions & 14 deletions

File tree

src/main/java/org/mifos/processor/bulk/camel/routes/OrderingRoute.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ public void configure() {
6060
case "account_number":
6161
key = transaction.getAccountNumber();
6262
break;
63+
case "payee_identifier":
64+
key = transaction.getPayeeIdentifier();
65+
break;
6366
case "amount":
6467
key = transaction.getAmount();
6568
break;

src/main/java/org/mifos/processor/bulk/zeebe/worker/OrderingWorker.java

Lines changed: 75 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,17 @@
33
import org.apache.camel.Exchange;
44
import org.apache.camel.support.DefaultExchange;
55
import org.mifos.processor.bulk.camel.routes.RouteId;
6+
import org.mifos.processor.bulk.schema.Transaction;
67
import org.springframework.stereotype.Component;
78

9+
import java.util.List;
810
import java.util.Map;
11+
import java.util.Set;
12+
import java.util.HashSet;
13+
import java.util.Objects;
914

1015
import static org.mifos.processor.bulk.camel.config.CamelProperties.SERVER_FILE_NAME;
16+
import static org.mifos.processor.bulk.camel.config.CamelProperties.TRANSACTION_LIST;
1117
import static org.mifos.processor.bulk.zeebe.ZeebeVariables.*;
1218

1319
@Component
@@ -26,26 +32,83 @@ public void setup() {
2632
newWorker(Worker.ORDERING, (client, job) -> {
2733
logger.debug("Job '{}' started from process '{}' with key {}", job.getType(), job.getBpmnProcessId(), job.getKey());
2834
Map<String, Object> variables = job.getVariablesAsMap();
35+
Exchange exchange = new DefaultExchange(camelContext);
36+
2937
if (workerConfig.isOrderingWorkerEnabled) {
3038
variables.put(ORDERING_FAILED, false);
39+
String filename = (String) variables.get(FILE_NAME);
40+
exchange.setProperty(SERVER_FILE_NAME, filename);
41+
42+
try {
43+
sendToCamelRoute(RouteId.ORDERING, exchange);
44+
assert !exchange.getProperty(ORDERING_FAILED, Boolean.class);
45+
} catch (Exception e) {
46+
variables.put(ORDERING_FAILED, true);
47+
}
48+
variables.put(ORDERING_FAILED, false);
49+
variables.put(ORDERED_BY, exchange.getProperty(ORDERED_BY));
3150
}
3251

33-
String filename = (String) variables.get(FILE_NAME);
34-
Exchange exchange = new DefaultExchange(camelContext);
35-
exchange.setProperty(SERVER_FILE_NAME, filename);
52+
if(workerConfig.isTransactionDeduplicationEnabled){
53+
List<Transaction> transactionList = exchange.getProperty(TRANSACTION_LIST, List.class);
54+
removeDuplicates(transactionList, workerConfig.isOrderingWorkerEnabled);
55+
variables.put(TRANSACTION_LIST, transactionList);
56+
}
57+
client.newCompleteCommand(job.getKey()).variables(variables).send();
58+
});
59+
}
60+
61+
private void removeDuplicates(List<Transaction> transactionList, boolean orderingEnabled){
62+
if(orderingEnabled){
63+
removeDuplicatesIfOrderingEnabled(transactionList);
64+
return;
65+
}
66+
removeDuplicatesIfOrderingDisabled(transactionList);
67+
}
68+
69+
private void removeDuplicatesIfOrderingEnabled(List<Transaction> transactionList){
3670

37-
try {
38-
sendToCamelRoute(RouteId.ORDERING, exchange);
39-
assert !exchange.getProperty(ORDERING_FAILED, Boolean.class);
40-
} catch (Exception e) {
41-
variables.put(ORDERING_FAILED, true);
71+
for (int i = 0; i <transactionList.size()-1; i++) {
72+
Transaction currentTransaction = transactionList.get(i);
73+
Transaction nextTransaction = transactionList.get(i + 1);
74+
75+
if (currentTransaction == null || nextTransaction == null) {
76+
continue;
77+
}
78+
String currentPayeeDetail = fetchPayeeDetail(currentTransaction);
79+
String nextPayeeDetail = fetchPayeeDetail(nextTransaction);
80+
81+
if (currentPayeeDetail.equals(nextPayeeDetail)) {
82+
currentTransaction.setNote("Duplicate transaction.");
4283
}
84+
}
85+
}
4386

44-
variables.put(ORDERING_FAILED, false);
45-
variables.put(ORDERED_BY, exchange.getProperty(ORDERED_BY));
87+
private void removeDuplicatesIfOrderingDisabled(List<Transaction> transactionList){
88+
Set<String> set = new HashSet<>();
4689

47-
client.newCompleteCommand(job.getKey()).variables(variables).send();
48-
});
90+
if(Objects.isNull(transactionList)){
91+
return;
92+
}
93+
94+
for(Transaction transaction : transactionList){
95+
String payeeDetail = fetchPayeeDetail(transaction);
96+
if(set.contains(payeeDetail)){
97+
transaction.setNote("Duplicate transaction.");
98+
}
99+
else{
100+
set.add(payeeDetail);
101+
}
102+
}
103+
}
104+
105+
private String fetchPayeeDetail(Transaction transaction){
106+
String payeeIdentifier = transaction.getPayeeIdentifier();
107+
String payeeIdentifierType = transaction.getPayeeIdentifierType();
108+
String amount = transaction.getAmount();
109+
String currency = transaction.getCurrency();
110+
111+
return String.format("%s%s%s%s", payeeIdentifier, payeeIdentifierType, amount, currency);
49112
}
50113

51114
}

src/main/java/org/mifos/processor/bulk/zeebe/worker/WorkerConfig.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,7 @@ public class WorkerConfig {
2727
@Value("${config.completion-threshold-check.enable}")
2828
public boolean isCompletionThresholdCheckEnabled;
2929

30+
@Value("config.deduplication.enabled")
31+
public boolean isTransactionDeduplicationEnabled;
32+
3033
}

src/main/resources/application.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ config:
8484
approval:
8585
enable: true
8686
ordering:
87-
enable: false
88-
field: "payment_mode"
87+
enable: true
88+
field: "payee_identifier"
8989
splitting:
9090
enable: false
9191
sub-batch-size: 5
@@ -101,6 +101,8 @@ config:
101101
completion-threshold: 95 # in percentage
102102
max-retry: 4 #can be as high as 30
103103
delay: 60 # in seconds
104+
deduplication:
105+
enabled: true
104106

105107
callback:
106108
max-retry: 3

0 commit comments

Comments
 (0)