diff --git a/src/main/java/dev/vality/fraudbusters/config/payment/PaymentFraudoConfig.java b/src/main/java/dev/vality/fraudbusters/config/payment/PaymentFraudoConfig.java index a69e0f48..5683fce6 100644 --- a/src/main/java/dev/vality/fraudbusters/config/payment/PaymentFraudoConfig.java +++ b/src/main/java/dev/vality/fraudbusters/config/payment/PaymentFraudoConfig.java @@ -2,6 +2,7 @@ import dev.vality.damsel.wb_list.WbListServiceSrv; import dev.vality.fraudbusters.fraud.constant.PaymentCheckedField; +import dev.vality.fraudbusters.fraud.localstorage.LocalPaymentFieldResolver; import dev.vality.fraudbusters.fraud.localstorage.LocalResultStorageRepository; import dev.vality.fraudbusters.fraud.localstorage.aggregator.LocalCountAggregatorDecorator; import dev.vality.fraudbusters.fraud.localstorage.aggregator.LocalSumAggregatorDecorator; @@ -99,6 +100,12 @@ public FieldResolver paymentModelFieldResolve return new PaymentModelFieldResolver(); } + @Bean + public LocalPaymentFieldResolver localPaymentFieldResolver( + DatabasePaymentFieldResolver databasePaymentFieldResolver) { + return new LocalPaymentFieldResolver(databasePaymentFieldResolver); + } + @Bean public InListFinder paymentInListFinder( WbListServiceSrv.Iface wbListServiceSrv, @@ -139,6 +146,7 @@ public CountPaymentAggregator countResultAggr RefundRepository refundRepository, ChargebackRepository chargebackRepository, DatabasePaymentFieldResolver databasePaymentFieldResolver, + LocalPaymentFieldResolver localPaymentFieldResolver, TimeBoundaryService timeBoundaryService) { CountAggregatorImpl countAggregatorDecorator = new CountAggregatorImpl( @@ -150,7 +158,7 @@ public CountPaymentAggregator countResultAggr ); return new LocalCountAggregatorDecorator( countAggregatorDecorator, - databasePaymentFieldResolver, + localPaymentFieldResolver, localResultStorageRepository, timeBoundaryService ); @@ -163,6 +171,7 @@ public SumPaymentAggregator sumResultAggregat RefundRepository refundRepository, ChargebackRepository chargebackRepository, DatabasePaymentFieldResolver databasePaymentFieldResolver, + LocalPaymentFieldResolver localPaymentFieldResolver, TimeBoundaryService timeBoundaryService) { SumAggregatorImpl sumAggregator = new SumAggregatorImpl( @@ -174,7 +183,7 @@ public SumPaymentAggregator sumResultAggregat ); return new LocalSumAggregatorDecorator( sumAggregator, - databasePaymentFieldResolver, + localPaymentFieldResolver, localResultStorageRepository, timeBoundaryService ); @@ -185,13 +194,14 @@ public UniqueValueAggregator uniqueValueResul LocalResultStorageRepository localResultStorageRepository, PaymentRepository fraudResultRepository, DatabasePaymentFieldResolver databasePaymentFieldResolver, + LocalPaymentFieldResolver localPaymentFieldResolver, TimeBoundaryService timeBoundaryService) { UniqueValueAggregatorImpl uniqueValueAggregator = new UniqueValueAggregatorImpl(databasePaymentFieldResolver, fraudResultRepository, timeBoundaryService); return new LocalUniqueValueAggregatorDecorator( uniqueValueAggregator, - databasePaymentFieldResolver, + localPaymentFieldResolver, localResultStorageRepository, timeBoundaryService ); diff --git a/src/main/java/dev/vality/fraudbusters/fraud/localstorage/LocalPaymentFieldResolver.java b/src/main/java/dev/vality/fraudbusters/fraud/localstorage/LocalPaymentFieldResolver.java new file mode 100644 index 00000000..96bf1851 --- /dev/null +++ b/src/main/java/dev/vality/fraudbusters/fraud/localstorage/LocalPaymentFieldResolver.java @@ -0,0 +1,37 @@ +package dev.vality.fraudbusters.fraud.localstorage; + +import dev.vality.fraudbusters.fraud.constant.PaymentCheckedField; +import dev.vality.fraudbusters.fraud.model.FieldModel; +import dev.vality.fraudbusters.fraud.model.PaymentModel; +import dev.vality.fraudbusters.fraud.payment.resolver.DatabasePaymentFieldResolver; +import lombok.RequiredArgsConstructor; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +@RequiredArgsConstructor +public class LocalPaymentFieldResolver { + + private final DatabasePaymentFieldResolver databasePaymentFieldResolver; + + public FieldModel resolve(PaymentCheckedField field, PaymentModel model) { + FieldModel fieldModel = databasePaymentFieldResolver.resolve(field, model); + return new FieldModel(resolveName(field), fieldModel.getValue()); + } + + public String resolveName(PaymentCheckedField field) { + return field.name(); + } + + @NotNull + public List resolveListFields(PaymentModel model, List fields) { + if (fields != null) { + return fields.stream() + .map(field -> resolve(field, model)) + .collect(Collectors.toList()); + } + return new ArrayList<>(); + } +} diff --git a/src/main/java/dev/vality/fraudbusters/fraud/localstorage/LocalResultStorageRepository.java b/src/main/java/dev/vality/fraudbusters/fraud/localstorage/LocalResultStorageRepository.java index f0a96d8d..8e5de83d 100644 --- a/src/main/java/dev/vality/fraudbusters/fraud/localstorage/LocalResultStorageRepository.java +++ b/src/main/java/dev/vality/fraudbusters/fraud/localstorage/LocalResultStorageRepository.java @@ -42,7 +42,8 @@ public Integer countOperationByFieldWithGroupBy( List fieldModels) { List checkedPayments = localStorage.get(); int count = (int) checkedPayments.stream() - .filter(checkedPayment -> filterPaymentByValue(from, to, fieldModels, checkedPayment)) + .filter(checkedPayment -> filterPaymentByValue( + fieldName, value, from, to, fieldModels, checkedPayment)) .count(); log.debug("LocalResultStorageRepository countOperationByFieldWithGroupBy: {}", count); return count; @@ -57,7 +58,8 @@ public Long sumOperationByFieldWithGroupBy( List fieldModels) { List checkedPayments = localStorage.get(); long sum = checkedPayments.stream() - .filter(checkedPayment -> filterPaymentByValue(from, to, fieldModels, checkedPayment)) + .filter(checkedPayment -> filterPaymentByValue( + fieldName, value, from, to, fieldModels, checkedPayment)) .mapToLong(CheckedPayment::getAmount) .sum(); log.debug("LocalResultStorageRepository sumOperationByFieldWithGroupBy: {}", sum); @@ -88,7 +90,8 @@ public Integer uniqCountOperationWithGroupBy( List fieldModels) { List checkedPayments = localStorage.get(); long count = checkedPayments.stream() - .filter(checkedPayment -> filterPaymentByValue(from, to, fieldModels, checkedPayment)) + .filter(checkedPayment -> filterPaymentByValue( + fieldNameBy, value, from, to, fieldModels, checkedPayment)) .map(checkedPayment -> paymentFieldValueResolver.resolve(fieldNameCount, checkedPayment)) .distinct() .count(); @@ -97,12 +100,15 @@ public Integer uniqCountOperationWithGroupBy( } private boolean filterPaymentByValue( + String fieldName, + Object value, Long from, Long to, List fieldModels, CheckedPayment checkedPayment) { return checkedPayment.getEventTime() >= from && checkedPayment.getEventTime() <= to + && paymentFieldValueFilter.filter(fieldName, value, checkedPayment) && fieldModels.stream() .allMatch(fieldModel -> paymentFieldValueFilter.filter( fieldModel.getName(), @@ -121,6 +127,8 @@ public Integer countOperationSuccessWithGroupBy( List checkedPayments = localStorage.get(); return (int) checkedPayments.stream() .filter(checkedPayment -> filterByStatusAndFields( + fieldName, + value, from, to, fieldModels, @@ -136,6 +144,8 @@ public Integer countOperationPendingWithGroupBy(String fieldName, Object value, List checkedPayments = localStorage.get(); return (int) checkedPayments.stream() .filter(checkedPayment -> filterByStatusAndFields( + fieldName, + value, from, to, fieldModels, @@ -156,6 +166,8 @@ public Integer countOperationErrorWithGroupBy( List checkedPayments = localStorage.get(); return (int) checkedPayments.stream() .filter(checkedPayment -> filterByStatusAndFields( + fieldName, + value, from, to, fieldModels, @@ -177,6 +189,8 @@ public Integer countOperationErrorWithGroupBy( List checkedPayments = localStorage.get(); return (int) checkedPayments.stream() .filter(checkedPayment -> filterByStatusAndFields( + fieldName, + value, from, to, fieldModels, @@ -195,6 +209,8 @@ public Long sumOperationSuccessWithGroupBy( List checkedPayments = localStorage.get(); return checkedPayments.stream() .filter(checkedPayment -> filterByStatusAndFields( + fieldName, + value, from, to, fieldModels, @@ -216,6 +232,8 @@ public Long sumOperationErrorWithGroupBy( List checkedPayments = localStorage.get(); return checkedPayments.stream() .filter(checkedPayment -> filterByStatusAndFields( + fieldName, + value, from, to, fieldModels, @@ -236,6 +254,8 @@ public Long sumOperationErrorWithGroupBy(String fieldName, List checkedPayments = localStorage.get(); return checkedPayments.stream() .filter(checkedPayment -> filterByStatusAndFields( + fieldName, + value, from, to, fieldModels, @@ -247,19 +267,14 @@ public Long sumOperationErrorWithGroupBy(String fieldName, } private boolean filterByStatusAndFields( + String fieldName, + Object value, Long from, Long to, List fieldModels, CheckedPayment checkedPayment, PaymentStatus paymentStatus) { - return checkedPayment.getEventTime() >= from - && checkedPayment.getEventTime() <= to - && fieldModels.stream() - .allMatch(fieldModel -> paymentFieldValueFilter.filter( - fieldModel.getName(), - fieldModel.getValue(), - checkedPayment - )) + return filterPaymentByValue(fieldName, value, from, to, fieldModels, checkedPayment) && paymentStatus.name().equals(checkedPayment.getPaymentStatus()); } diff --git a/src/main/java/dev/vality/fraudbusters/fraud/localstorage/aggregator/LocalCountAggregatorDecorator.java b/src/main/java/dev/vality/fraudbusters/fraud/localstorage/aggregator/LocalCountAggregatorDecorator.java index 1f15279e..5be2ddff 100644 --- a/src/main/java/dev/vality/fraudbusters/fraud/localstorage/aggregator/LocalCountAggregatorDecorator.java +++ b/src/main/java/dev/vality/fraudbusters/fraud/localstorage/aggregator/LocalCountAggregatorDecorator.java @@ -4,11 +4,11 @@ import dev.vality.fraudbusters.exception.RuleFunctionException; import dev.vality.fraudbusters.fraud.AggregateGroupingFunction; import dev.vality.fraudbusters.fraud.constant.PaymentCheckedField; +import dev.vality.fraudbusters.fraud.localstorage.LocalPaymentFieldResolver; import dev.vality.fraudbusters.fraud.localstorage.LocalResultStorageRepository; import dev.vality.fraudbusters.fraud.model.FieldModel; import dev.vality.fraudbusters.fraud.model.PaymentModel; import dev.vality.fraudbusters.fraud.payment.aggregator.clickhouse.CountAggregatorImpl; -import dev.vality.fraudbusters.fraud.payment.resolver.DatabasePaymentFieldResolver; import dev.vality.fraudbusters.service.TimeBoundaryService; import dev.vality.fraudbusters.util.TimestampUtil; import dev.vality.fraudo.model.TimeWindow; @@ -25,7 +25,7 @@ public class LocalCountAggregatorDecorator implements CountPaymentAggregator { private final CountAggregatorImpl countAggregator; - private final DatabasePaymentFieldResolver databasePaymentFieldResolver; + private final LocalPaymentFieldResolver localPaymentFieldResolver; private final LocalResultStorageRepository localStorageRepository; private final TimeBoundaryService timeBoundaryService; @@ -36,11 +36,11 @@ public Integer count( TimeWindow timeWindow, List list) { Integer count = countAggregator.count(checkedField, paymentModel, timeWindow, list); - FieldModel resolve = databasePaymentFieldResolver.resolve(checkedField, paymentModel); + FieldModel resolve = localPaymentFieldResolver.resolve(checkedField, paymentModel); Instant timestamp = TimestampUtil.instantFromPaymentModel(paymentModel); TimeBound timeBound = timeBoundaryService.getBoundary(timestamp, timeWindow); Integer localCount = localStorageRepository.countOperationByField( - checkedField.name(), + resolve.getName(), resolve.getValue(), timeBound.getLeft().getEpochSecond(), timeBound.getRight().getEpochSecond() @@ -74,10 +74,10 @@ public Integer countError( Integer countError = countAggregator.countError(checkedField, paymentModel, timeWindow, errorCode, list); Instant timestamp = TimestampUtil.instantFromPaymentModel(paymentModel); TimeBound timeBound = timeBoundaryService.getBoundary(timestamp, timeWindow); - FieldModel resolve = databasePaymentFieldResolver.resolve(checkedField, paymentModel); - List eventFields = databasePaymentFieldResolver.resolveListFields(paymentModel, list); + FieldModel resolve = localPaymentFieldResolver.resolve(checkedField, paymentModel); + List eventFields = localPaymentFieldResolver.resolveListFields(paymentModel, list); Integer localCount = localStorageRepository.countOperationErrorWithGroupBy( - checkedField.name(), + resolve.getName(), resolve.getValue(), timeBound.getLeft().getEpochSecond(), timeBound.getRight().getEpochSecond(), @@ -105,10 +105,10 @@ public Integer countError(PaymentCheckedField paymentCheckedField, PaymentModel Integer countError = countAggregator.countError(paymentCheckedField, paymentModel, timeWindow, list); Instant timestamp = TimestampUtil.instantFromPaymentModel(paymentModel); TimeBound timeBound = timeBoundaryService.getBoundary(timestamp, timeWindow); - FieldModel resolve = databasePaymentFieldResolver.resolve(paymentCheckedField, paymentModel); - List eventFields = databasePaymentFieldResolver.resolveListFields(paymentModel, list); + FieldModel resolve = localPaymentFieldResolver.resolve(paymentCheckedField, paymentModel); + List eventFields = localPaymentFieldResolver.resolveListFields(paymentModel, list); Integer localCount = localStorageRepository.countOperationErrorWithGroupBy( - paymentCheckedField.name(), + resolve.getName(), resolve.getValue(), timeBound.getLeft().getEpochSecond(), timeBound.getRight().getEpochSecond(), @@ -171,13 +171,13 @@ private Integer getCount( try { Instant timestamp = TimestampUtil.instantFromPaymentModel(paymentModel); TimeBound timeBound = timeBoundaryService.getBoundary(timestamp, timeWindow); - FieldModel resolve = databasePaymentFieldResolver.resolve(checkedField, paymentModel); - List eventFields = databasePaymentFieldResolver.resolveListFields(paymentModel, list); + FieldModel resolve = localPaymentFieldResolver.resolve(checkedField, paymentModel); + List eventFields = localPaymentFieldResolver.resolveListFields(paymentModel, list); Integer count = aggregateFunction.accept( resolve.getName(), resolve.getValue(), - timeBound.getLeft().toEpochMilli(), - timeBound.getRight().toEpochMilli(), + timeBound.getLeft().getEpochSecond(), + timeBound.getRight().getEpochSecond(), eventFields ); log.debug( diff --git a/src/main/java/dev/vality/fraudbusters/fraud/localstorage/aggregator/LocalSumAggregatorDecorator.java b/src/main/java/dev/vality/fraudbusters/fraud/localstorage/aggregator/LocalSumAggregatorDecorator.java index 3f13e342..503b3273 100644 --- a/src/main/java/dev/vality/fraudbusters/fraud/localstorage/aggregator/LocalSumAggregatorDecorator.java +++ b/src/main/java/dev/vality/fraudbusters/fraud/localstorage/aggregator/LocalSumAggregatorDecorator.java @@ -4,11 +4,11 @@ import dev.vality.fraudbusters.exception.RuleFunctionException; import dev.vality.fraudbusters.fraud.AggregateGroupingFunction; import dev.vality.fraudbusters.fraud.constant.PaymentCheckedField; +import dev.vality.fraudbusters.fraud.localstorage.LocalPaymentFieldResolver; import dev.vality.fraudbusters.fraud.localstorage.LocalResultStorageRepository; import dev.vality.fraudbusters.fraud.model.FieldModel; import dev.vality.fraudbusters.fraud.model.PaymentModel; import dev.vality.fraudbusters.fraud.payment.aggregator.clickhouse.SumAggregatorImpl; -import dev.vality.fraudbusters.fraud.payment.resolver.DatabasePaymentFieldResolver; import dev.vality.fraudbusters.service.TimeBoundaryService; import dev.vality.fraudbusters.util.TimestampUtil; import dev.vality.fraudo.model.TimeWindow; @@ -25,7 +25,7 @@ public class LocalSumAggregatorDecorator implements SumPaymentAggregator { private final SumAggregatorImpl sumAggregatorImpl; - private final DatabasePaymentFieldResolver databasePaymentFieldResolver; + private final LocalPaymentFieldResolver localPaymentFieldResolver; private final LocalResultStorageRepository localStorageRepository; private final TimeBoundaryService timeBoundaryService; @@ -36,12 +36,12 @@ public Double sum( TimeWindow timeWindow, List list) { Double sum = sumAggregatorImpl.sum(checkedField, paymentModel, timeWindow, list); - FieldModel resolve = databasePaymentFieldResolver.resolve(checkedField, paymentModel); + FieldModel resolve = localPaymentFieldResolver.resolve(checkedField, paymentModel); Instant now = TimestampUtil.instantFromPaymentModel(paymentModel); TimeBound timeBound = timeBoundaryService.getBoundary(now, timeWindow); - List eventFields = databasePaymentFieldResolver.resolveListFields(paymentModel, list); + List eventFields = localPaymentFieldResolver.resolveListFields(paymentModel, list); Long localSum = localStorageRepository.sumOperationByFieldWithGroupBy( - checkedField.name(), + resolve.getName(), resolve.getValue(), timeBound.getLeft().getEpochSecond(), timeBound.getRight().getEpochSecond(), @@ -80,10 +80,10 @@ public Double sumError(PaymentCheckedField checkedField, Double sumError = sumAggregatorImpl.sumError(checkedField, paymentModel, timeWindow, errorCode, list); Instant now = TimestampUtil.instantFromPaymentModel(paymentModel); TimeBound timeBound = timeBoundaryService.getBoundary(now, timeWindow); - FieldModel resolve = databasePaymentFieldResolver.resolve(checkedField, paymentModel); - List eventFields = databasePaymentFieldResolver.resolveListFields(paymentModel, list); + FieldModel resolve = localPaymentFieldResolver.resolve(checkedField, paymentModel); + List eventFields = localPaymentFieldResolver.resolveListFields(paymentModel, list); Long localSum = localStorageRepository.sumOperationErrorWithGroupBy( - checkedField.name(), + resolve.getName(), resolve.getValue(), timeBound.getLeft().getEpochSecond(), timeBound.getRight().getEpochSecond(), @@ -113,10 +113,10 @@ public Double sumError(PaymentCheckedField checkedField, Double sumError = sumAggregatorImpl.sumError(checkedField, paymentModel, timeWindow, list); Instant now = TimestampUtil.instantFromPaymentModel(paymentModel); TimeBound timeBound = timeBoundaryService.getBoundary(now, timeWindow); - FieldModel resolve = databasePaymentFieldResolver.resolve(checkedField, paymentModel); - List eventFields = databasePaymentFieldResolver.resolveListFields(paymentModel, list); + FieldModel resolve = localPaymentFieldResolver.resolve(checkedField, paymentModel); + List eventFields = localPaymentFieldResolver.resolveListFields(paymentModel, list); Long localSum = localStorageRepository.sumOperationErrorWithGroupBy( - checkedField.name(), + resolve.getName(), resolve.getValue(), timeBound.getLeft().getEpochSecond(), timeBound.getRight().getEpochSecond(), @@ -175,13 +175,13 @@ private Double getSum( try { Instant now = TimestampUtil.instantFromPaymentModel(paymentModel); TimeBound timeBound = timeBoundaryService.getBoundary(now, timeWindow); - FieldModel resolve = databasePaymentFieldResolver.resolve(checkedField, paymentModel); - List eventFields = databasePaymentFieldResolver.resolveListFields(paymentModel, list); + FieldModel resolve = localPaymentFieldResolver.resolve(checkedField, paymentModel); + List eventFields = localPaymentFieldResolver.resolveListFields(paymentModel, list); Long sum = aggregateFunction.accept( resolve.getName(), resolve.getValue(), - timeBound.getLeft().toEpochMilli(), - timeBound.getRight().toEpochMilli(), + timeBound.getLeft().getEpochSecond(), + timeBound.getRight().getEpochSecond(), eventFields ); double resultSum = withCurrent diff --git a/src/main/java/dev/vality/fraudbusters/fraud/localstorage/aggregator/LocalUniqueValueAggregatorDecorator.java b/src/main/java/dev/vality/fraudbusters/fraud/localstorage/aggregator/LocalUniqueValueAggregatorDecorator.java index 70ff3df7..3bc30bc4 100644 --- a/src/main/java/dev/vality/fraudbusters/fraud/localstorage/aggregator/LocalUniqueValueAggregatorDecorator.java +++ b/src/main/java/dev/vality/fraudbusters/fraud/localstorage/aggregator/LocalUniqueValueAggregatorDecorator.java @@ -3,11 +3,11 @@ import dev.vality.fraudbusters.domain.TimeBound; import dev.vality.fraudbusters.exception.RuleFunctionException; import dev.vality.fraudbusters.fraud.constant.PaymentCheckedField; +import dev.vality.fraudbusters.fraud.localstorage.LocalPaymentFieldResolver; import dev.vality.fraudbusters.fraud.localstorage.LocalResultStorageRepository; import dev.vality.fraudbusters.fraud.model.FieldModel; import dev.vality.fraudbusters.fraud.model.PaymentModel; import dev.vality.fraudbusters.fraud.payment.aggregator.clickhouse.UniqueValueAggregatorImpl; -import dev.vality.fraudbusters.fraud.payment.resolver.DatabasePaymentFieldResolver; import dev.vality.fraudbusters.service.TimeBoundaryService; import dev.vality.fraudbusters.util.TimestampUtil; import dev.vality.fraudo.aggregator.UniqueValueAggregator; @@ -23,7 +23,7 @@ public class LocalUniqueValueAggregatorDecorator implements UniqueValueAggregator { private final UniqueValueAggregatorImpl uniqueValueAggregator; - private final DatabasePaymentFieldResolver databasePaymentFieldResolver; + private final LocalPaymentFieldResolver localPaymentFieldResolver; private final LocalResultStorageRepository localStorageRepository; private final TimeBoundaryService timeBoundaryService; @@ -38,14 +38,14 @@ public Integer countUniqueValue( Integer uniq = uniqueValueAggregator.countUniqueValue(countField, paymentModel, onField, timeWindow, list); Instant timestamp = TimestampUtil.instantFromPaymentModel(paymentModel); TimeBound timeBound = timeBoundaryService.getBoundary(timestamp, timeWindow); - FieldModel resolve = databasePaymentFieldResolver.resolve(countField, paymentModel); - List fieldModels = databasePaymentFieldResolver.resolveListFields(paymentModel, list); + FieldModel resolve = localPaymentFieldResolver.resolve(countField, paymentModel); + List fieldModels = localPaymentFieldResolver.resolveListFields(paymentModel, list); Integer localUniqCountOperation = localStorageRepository.uniqCountOperationWithGroupBy( resolve.getName(), resolve.getValue(), - databasePaymentFieldResolver.resolve(onField), - timeBound.getLeft().toEpochMilli(), - timeBound.getRight().toEpochMilli(), + localPaymentFieldResolver.resolveName(onField), + timeBound.getLeft().getEpochSecond(), + timeBound.getRight().getEpochSecond(), fieldModels ); int result = localUniqCountOperation + uniq; diff --git a/src/test/java/dev/vality/fraudbusters/fraud/localstorage/LocalResultStorageRepositoryTest.java b/src/test/java/dev/vality/fraudbusters/fraud/localstorage/LocalResultStorageRepositoryTest.java new file mode 100644 index 00000000..d4e894b0 --- /dev/null +++ b/src/test/java/dev/vality/fraudbusters/fraud/localstorage/LocalResultStorageRepositoryTest.java @@ -0,0 +1,119 @@ +package dev.vality.fraudbusters.fraud.localstorage; + +import dev.vality.damsel.fraudbusters.PaymentStatus; +import dev.vality.fraudbusters.domain.CheckedPayment; +import dev.vality.fraudbusters.fraud.constant.PaymentCheckedField; +import dev.vality.fraudbusters.fraud.filter.PaymentFieldValueFilter; +import dev.vality.fraudbusters.fraud.filter.PaymentFieldValueResolver; +import dev.vality.fraudbusters.fraud.model.FieldModel; +import dev.vality.fraudbusters.fraud.model.PaymentModel; +import dev.vality.fraudbusters.fraud.payment.resolver.DatabasePaymentFieldResolver; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class LocalResultStorageRepositoryTest { + + private static final long FROM = 50L; + private static final long TO = 150L; + private static final String TOKEN = "token-a"; + + private LocalResultStorageRepository repository; + + @BeforeEach + void setUp() { + LocalResultStorage storage = new LocalResultStorage(); + PaymentFieldValueResolver resolver = new PaymentFieldValueResolver(); + repository = new LocalResultStorageRepository( + storage, + new PaymentFieldValueFilter(resolver), + resolver + ); + + storage.get().addAll(List.of( + payment(TOKEN, "same@example.com", PaymentStatus.captured, null, 10L), + payment(TOKEN, "same@example.com", PaymentStatus.pending, null, 20L), + payment(TOKEN, "other@example.com", PaymentStatus.failed, "E1", 30L), + payment(TOKEN, "other@example.com", PaymentStatus.failed, "E2", 40L), + payment("token-b", "one@example.com", PaymentStatus.captured, null, 100L), + payment("token-c", "two@example.com", PaymentStatus.failed, "E1", 200L) + )); + } + + @Test + void shouldApplyMainFieldFilterToGeneralAggregations() { + assertEquals(4, repository.countOperationByFieldWithGroupBy( + PaymentCheckedField.CARD_TOKEN.name(), TOKEN, FROM, TO, List.of())); + assertEquals(100L, repository.sumOperationByFieldWithGroupBy( + PaymentCheckedField.CARD_TOKEN.name(), TOKEN, FROM, TO, List.of())); + assertEquals(2, repository.uniqCountOperationWithGroupBy( + PaymentCheckedField.CARD_TOKEN.name(), + TOKEN, + PaymentCheckedField.EMAIL.name(), + FROM, + TO, + List.of() + )); + } + + @Test + void shouldApplyMainFieldFilterToStatusCounts() { + String fieldName = PaymentCheckedField.CARD_TOKEN.name(); + + assertEquals(1, repository.countOperationSuccessWithGroupBy( + fieldName, TOKEN, FROM, TO, List.of())); + assertEquals(1, repository.countOperationPendingWithGroupBy( + fieldName, TOKEN, FROM, TO, List.of())); + assertEquals(2, repository.countOperationErrorWithGroupBy( + fieldName, TOKEN, FROM, TO, List.of())); + assertEquals(1, repository.countOperationErrorWithGroupBy( + fieldName, TOKEN, FROM, TO, List.of(), "E1")); + } + + @Test + void shouldApplyMainFieldFilterToStatusSums() { + String fieldName = PaymentCheckedField.CARD_TOKEN.name(); + + assertEquals(10L, repository.sumOperationSuccessWithGroupBy( + fieldName, TOKEN, FROM, TO, List.of())); + assertEquals(70L, repository.sumOperationErrorWithGroupBy( + fieldName, TOKEN, FROM, TO, List.of())); + assertEquals(30L, repository.sumOperationErrorWithGroupBy( + fieldName, TOKEN, FROM, TO, List.of(), "E1")); + } + + @Test + void shouldResolveDifferentFieldNamesForClickHouseAndLocalStorage() { + DatabasePaymentFieldResolver resolver = new DatabasePaymentFieldResolver(); + LocalPaymentFieldResolver localResolver = new LocalPaymentFieldResolver(resolver); + PaymentModel payment = new PaymentModel(); + payment.setCardToken(TOKEN); + + List clickHouseFields = + resolver.resolveListFields(payment, List.of(PaymentCheckedField.CARD_TOKEN)); + List localFields = + localResolver.resolveListFields(payment, List.of(PaymentCheckedField.CARD_TOKEN)); + + assertEquals("cardToken", clickHouseFields.get(0).getName()); + assertEquals("CARD_TOKEN", localFields.get(0).getName()); + } + + private CheckedPayment payment( + String cardToken, + String email, + PaymentStatus status, + String errorCode, + Long amount) { + CheckedPayment payment = new CheckedPayment(); + payment.setEventTime(100L); + payment.setCardToken(cardToken); + payment.setEmail(email); + payment.setPaymentStatus(status.name()); + payment.setErrorCode(errorCode); + payment.setAmount(amount); + return payment; + } +}