From 1c9998a9f354b977e6be1ba5d7f7e616b3d87ed6 Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Mon, 12 Feb 2024 14:58:36 +0100 Subject: [PATCH 01/30] PAGOPA-1492 adding entities for multi cart --- .../controller/CalculatorController.java | 12 +++++----- .../calculator/model/PaymentNoticeItem.java | 19 ++++++++++++++++ .../model/PaymentOptionByPspMulti.java | 22 +++++++++++++++++++ .../calculator/model/PaymentOptionMulti.java | 20 +++++++++++++++++ 4 files changed, 67 insertions(+), 6 deletions(-) create mode 100644 src/main/java/it/gov/pagopa/afm/calculator/model/PaymentNoticeItem.java create mode 100644 src/main/java/it/gov/pagopa/afm/calculator/model/PaymentOptionByPspMulti.java create mode 100644 src/main/java/it/gov/pagopa/afm/calculator/model/PaymentOptionMulti.java diff --git a/src/main/java/it/gov/pagopa/afm/calculator/controller/CalculatorController.java b/src/main/java/it/gov/pagopa/afm/calculator/controller/CalculatorController.java index 4cb29478..1061f224 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/controller/CalculatorController.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/controller/CalculatorController.java @@ -10,6 +10,8 @@ import io.swagger.v3.oas.annotations.tags.Tag; import it.gov.pagopa.afm.calculator.model.PaymentOption; import it.gov.pagopa.afm.calculator.model.PaymentOptionByPsp; +import it.gov.pagopa.afm.calculator.model.PaymentOptionByPspMulti; +import it.gov.pagopa.afm.calculator.model.PaymentOptionMulti; import it.gov.pagopa.afm.calculator.model.ProblemJson; import it.gov.pagopa.afm.calculator.model.PspSearchCriteria; import it.gov.pagopa.afm.calculator.model.calculator.BundleOption; @@ -237,7 +239,7 @@ public BundleOption getFees( public BundleOption getFeesByPspMulti( @Parameter(description = "PSP identifier", required = true) @PathVariable("idPsp") String idPsp, - @RequestBody @Valid PaymentOptionByPsp paymentOptionByPsp, + @RequestBody @Valid PaymentOptionByPspMulti paymentOptionByPsp, @RequestParam(required = false, defaultValue = "10") Integer maxOccurrences, @RequestParam(required = false, defaultValue = "true") @Parameter( @@ -245,10 +247,8 @@ public BundleOption getFeesByPspMulti( "Flag for the exclusion of Poste bundles: false -> excluded, true or null ->" + " included") String allCcp) { - PaymentOption paymentOption = - PaymentOption.builder() - .paymentAmount(paymentOptionByPsp.getPaymentAmount()) - .primaryCreditorInstitution(paymentOptionByPsp.getPrimaryCreditorInstitution()) + PaymentOptionMulti paymentOption = + PaymentOptionMulti.builder() .paymentMethod(paymentOptionByPsp.getPaymentMethod()) .touchpoint(paymentOptionByPsp.getTouchpoint()) .idPspList( @@ -258,8 +258,8 @@ public BundleOption getFeesByPspMulti( .idChannel(paymentOptionByPsp.getIdChannel()) .idBrokerPsp(paymentOptionByPsp.getIdBrokerPsp()) .build())) - .transferList(paymentOptionByPsp.getTransferList()) .bin(paymentOptionByPsp.getBin()) + .paymentNotice(paymentOptionByPsp.getPaymentNotice()) .build(); return BundleOption.builder() .belowThreshold(false) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/model/PaymentNoticeItem.java b/src/main/java/it/gov/pagopa/afm/calculator/model/PaymentNoticeItem.java new file mode 100644 index 00000000..214e9e7f --- /dev/null +++ b/src/main/java/it/gov/pagopa/afm/calculator/model/PaymentNoticeItem.java @@ -0,0 +1,19 @@ +package it.gov.pagopa.afm.calculator.model; + +import lombok.*; + +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +@AllArgsConstructor +@NoArgsConstructor +@Data +@Builder +@ToString +public class PaymentNoticeItem { + @NotNull private Long paymentAmount; + @NotNull private String primaryCreditorInstitution; + @Valid @NotNull @NotEmpty private List transferList; +} diff --git a/src/main/java/it/gov/pagopa/afm/calculator/model/PaymentOptionByPspMulti.java b/src/main/java/it/gov/pagopa/afm/calculator/model/PaymentOptionByPspMulti.java new file mode 100644 index 00000000..e2776338 --- /dev/null +++ b/src/main/java/it/gov/pagopa/afm/calculator/model/PaymentOptionByPspMulti.java @@ -0,0 +1,22 @@ +package it.gov.pagopa.afm.calculator.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.ArrayList; + +@AllArgsConstructor +@NoArgsConstructor +@Data +public class PaymentOptionByPspMulti { + private String idChannel; + private String idBrokerPsp; + private String paymentMethod; + private String touchpoint; + private String bin; + @Valid @NotNull @NotEmpty private ArrayList paymentNotice; +} diff --git a/src/main/java/it/gov/pagopa/afm/calculator/model/PaymentOptionMulti.java b/src/main/java/it/gov/pagopa/afm/calculator/model/PaymentOptionMulti.java new file mode 100644 index 00000000..89211995 --- /dev/null +++ b/src/main/java/it/gov/pagopa/afm/calculator/model/PaymentOptionMulti.java @@ -0,0 +1,20 @@ +package it.gov.pagopa.afm.calculator.model; + +import lombok.*; +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.util.List; + +@AllArgsConstructor +@NoArgsConstructor +@Data +@Builder +@ToString +public class PaymentOptionMulti { + private String bin; + private String paymentMethod; + private String touchpoint; + private List idPspList; + @Valid @NotNull @NotEmpty private List paymentNotice; +} From d8bdb738bdac05cd063e87500dc95ecf21dacdc9 Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Mon, 12 Feb 2024 16:27:20 +0100 Subject: [PATCH 02/30] PAGOPA-1492 adding entities for multi cart output --- .../model/calculatorMulti/BundleOption.java | 26 ++++++++++++ .../calculator/model/calculatorMulti/Fee.java | 18 +++++++++ .../model/calculatorMulti/Transfer.java | 40 +++++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/BundleOption.java create mode 100644 src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Fee.java create mode 100644 src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Transfer.java diff --git a/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/BundleOption.java b/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/BundleOption.java new file mode 100644 index 00000000..36799da9 --- /dev/null +++ b/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/BundleOption.java @@ -0,0 +1,26 @@ +package it.gov.pagopa.afm.calculator.model.calculatorMulti; + +import io.swagger.v3.oas.annotations.media.Schema; +import java.io.Serializable; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Builder +@Data +@NoArgsConstructor +@AllArgsConstructor +public class BundleOption implements Serializable { + /** generated serialVersionUID */ + private static final long serialVersionUID = -7404184031676587394L; + + @Schema( + description = + "if true (the payment amount is lower than the threshold value) the bundles onus is not" + + " calculated (always false)") + private Boolean belowThreshold; + + private List bundleOptions; +} diff --git a/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Fee.java b/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Fee.java new file mode 100644 index 00000000..f338d107 --- /dev/null +++ b/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Fee.java @@ -0,0 +1,18 @@ +package it.gov.pagopa.afm.calculator.model.calculatorMulti; + +import lombok.*; +import java.io.Serializable; + +@Builder +@Data +@ToString +@AllArgsConstructor +@NoArgsConstructor +public class Fee implements Serializable { + /** generated serialVersionUID */ + private static final long serialVersionUID = 1287710978645388173L; + + private String creditorInstitution; + private long primaryCiIncurredFee; + private long actualCiIncurredFee; +} diff --git a/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Transfer.java b/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Transfer.java new file mode 100644 index 00000000..7286ca6e --- /dev/null +++ b/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Transfer.java @@ -0,0 +1,40 @@ +package it.gov.pagopa.afm.calculator.model.calculatorMulti; + +import lombok.*; +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; +import java.io.Serializable; +import java.util.Comparator; +import java.util.List; + +@Builder +@Data +@ToString +@AllArgsConstructor +@NoArgsConstructor +public class Transfer implements Comparable, Serializable { + /** generated serialVersionUID */ + private static final long serialVersionUID = 1287710978645388173L; + + private Long taxPayerFee; + private String paymentMethod; + private String touchpoint; + private String idBundle; + private String bundleName; + private String bundleDescription; + private String idCiBundle; + private String idPsp; + private String idChannel; + private String idBrokerPsp; + private Boolean onUs; + private String abi; + private String pspBusinessName; + @Valid @NotNull @NotEmpty private List fees; + + @Override + public int compareTo(Transfer t) { + // order by onUs + return Comparator.comparing((Transfer tr) -> tr.onUs).reversed().compare(this, t); + } +} From 6db37324186dfc1d341ad9e0691b31f2204e5bdf Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Tue, 13 Feb 2024 18:10:34 +0100 Subject: [PATCH 03/30] PAGOPA-1492 adding initialization of service --- .../afm/calculator/service/CalculatorService.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java index 3d8453a3..df1d9a09 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java @@ -57,6 +57,17 @@ public BundleOption calculate(@Valid PaymentOption paymentOption, int limit, boo .build(); } + public BundleOption calculateMulti(@Valid PaymentOption paymentOption, int limit, boolean allCcp) { + List filteredBundles = cosmosRepository.findByPaymentOption(paymentOption, allCcp); + Collections.shuffle(filteredBundles, new Random()); + + return BundleOption.builder() + .belowThreshold(isBelowThreshold(paymentOption.getPaymentAmount())) + // calculate the taxPayerFee + .bundleOptions(calculateTaxPayerFee(paymentOption, limit, filteredBundles)) + .build(); + } + private List calculateTaxPayerFee( PaymentOption paymentOption, int limit, List bundles) { From 9389f90e1f8e4377a114783a863e5b463ed00009 Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Tue, 13 Feb 2024 18:30:07 +0100 Subject: [PATCH 04/30] PAGOPA-1492 inserting method --- .../afm/calculator/service/CalculatorService.java | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java index df1d9a09..89e04a9f 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java @@ -6,6 +6,7 @@ import it.gov.pagopa.afm.calculator.exception.AppError; import it.gov.pagopa.afm.calculator.exception.AppException; import it.gov.pagopa.afm.calculator.model.PaymentOption; +import it.gov.pagopa.afm.calculator.model.PaymentOptionMulti; import it.gov.pagopa.afm.calculator.model.TransferCategoryRelation; import it.gov.pagopa.afm.calculator.model.calculator.BundleOption; import it.gov.pagopa.afm.calculator.model.calculator.Transfer; @@ -57,15 +58,8 @@ public BundleOption calculate(@Valid PaymentOption paymentOption, int limit, boo .build(); } - public BundleOption calculateMulti(@Valid PaymentOption paymentOption, int limit, boolean allCcp) { - List filteredBundles = cosmosRepository.findByPaymentOption(paymentOption, allCcp); - Collections.shuffle(filteredBundles, new Random()); - - return BundleOption.builder() - .belowThreshold(isBelowThreshold(paymentOption.getPaymentAmount())) - // calculate the taxPayerFee - .bundleOptions(calculateTaxPayerFee(paymentOption, limit, filteredBundles)) - .build(); + public BundleOption calculateMulti(@Valid PaymentOptionMulti paymentOption, int limit, boolean allCcp) { + return null; } private List calculateTaxPayerFee( From ddc7709603678a2ff3cb41889dc4782e99ae4c5c Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Wed, 14 Feb 2024 13:52:27 +0100 Subject: [PATCH 05/30] PAGOPA-1492 start logic implementation --- .../repository/CosmosRepository.java | 160 ++++++++++++++++++ .../calculator/service/UtilityComponent.java | 20 +++ 2 files changed, 180 insertions(+) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java b/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java index 80c541be..9e8f0bed 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java @@ -9,7 +9,9 @@ import it.gov.pagopa.afm.calculator.entity.Touchpoint; import it.gov.pagopa.afm.calculator.entity.ValidBundle; import it.gov.pagopa.afm.calculator.exception.AppException; +import it.gov.pagopa.afm.calculator.model.PaymentNoticeItem; import it.gov.pagopa.afm.calculator.model.PaymentOption; +import it.gov.pagopa.afm.calculator.model.PaymentOptionMulti; import it.gov.pagopa.afm.calculator.model.PspSearchCriteria; import it.gov.pagopa.afm.calculator.service.UtilityComponent; import it.gov.pagopa.afm.calculator.util.CriteriaBuilder; @@ -62,6 +64,112 @@ public List findByPaymentOption(PaymentOption paymentOption, boolea return getFilteredBundles(paymentOption, validBundles); } + @Cacheable(value = "findValidBundlesMulti") + public List findByPaymentOption(PaymentOptionMulti paymentOption, boolean allCcp) { + Iterable validBundles = findValidBundlesMulti(paymentOption, allCcp); + paymentOption.getPaymentNotice().forEach(paymentNoticeItem -> { + + }); + return getFilteredBundlesMulti(paymentOption.getPaymentNotice().get(0), validBundles); //TODO stream payment notice + } + + /** + * Null value are ignored -> they are skipped when building the filters + * + * @param paymentOption Get the Body of the Request + * @return the filtered bundles + */ + private Iterable findValidBundlesMulti(PaymentOptionMulti paymentOption, boolean allCcp) { + + // add filter by Payment Amount: minPaymentAmount <= paymentAmount < maxPaymentAmount + /* + var minFilter = + CriteriaBuilder.lessThan("minPaymentAmount", paymentOption.getPaymentAmount()); + var maxFilter = + CriteriaBuilder.greaterThanEqual("maxPaymentAmount", paymentOption.getPaymentAmount()); + var queryResult = and(minFilter, maxFilter); + */ + + Criteria queryResult = null; + // add filter by Touch Point: touchpoint= || touchpoint==null + if (paymentOption.getTouchpoint() != null + && !paymentOption.getTouchpoint().equalsIgnoreCase("any")) { + var touchpointNameFilter = isEqualOrAny("name", paymentOption.getTouchpoint()); + Iterable touchpoint = + cosmosTemplate.find( + new CosmosQuery(touchpointNameFilter), Touchpoint.class, "touchpoints"); + + if (Iterables.size(touchpoint) == 0) { + throw new AppException( + HttpStatus.NOT_FOUND, + "Touchpoint not found", + "Cannot find touchpont with name: '" + paymentOption.getTouchpoint() + "'"); + } + + var touchpointFilter = isEqualOrAny("touchpoint", touchpoint.iterator().next().getName()); + queryResult = and(queryResult, touchpointFilter); + } + + // add filter by Payment Method: paymentMethod= || paymentMethod==null + if (paymentOption.getPaymentMethod() != null + && !paymentOption.getPaymentMethod().equalsIgnoreCase("any")) { + var paymentTypeNameFilter = isEqualOrNull("name", paymentOption.getPaymentMethod()); + Iterable paymentType = + cosmosTemplate.find( + new CosmosQuery(paymentTypeNameFilter), PaymentType.class, "paymenttypes"); + + if (Iterables.size(paymentType) == 0) { + throw new AppException( + HttpStatus.NOT_FOUND, + "PaymentType not found", + "Cannot find payment type with name: '" + paymentOption.getPaymentMethod() + "'"); + } + + var paymentTypeFilter = isEqualOrNull("paymentType", paymentType.iterator().next().getName()); + queryResult = and(queryResult, paymentTypeFilter); + } + + // add filter by PSP: psp in list + Iterator iterator = + Optional.ofNullable(paymentOption.getIdPspList()) + .orElse(Collections.emptyList()) + .iterator(); + if (iterator.hasNext()) { + queryResult = this.getPspFilterCriteria(queryResult, iterator); + } + + // add filter by Transfer Category: transferCategory[] contains one of paymentOption + List categoryList = utilityComponent.getTransferCategoryList(paymentOption.getPaymentNotice().get(0)); //TODO iterate payment notice + if (categoryList != null) { + var taxonomyFilter = + categoryList.parallelStream() + .filter(Objects::nonNull) + .filter(elem -> !elem.isEmpty()) + .map(elem -> arrayContains("transferCategoryList", elem)) + .reduce(CriteriaBuilder::or); + + if (taxonomyFilter.isPresent()) { + var taxonomyOrNull = or(taxonomyFilter.get(), isNull("transferCategoryList")); + queryResult = and(queryResult, taxonomyOrNull); + } + } + + // add filter for Poste bundles + if (!allCcp) { + var allCcpFilter = isNotEqual(ID_PSP_PARAM, pspPosteId); + queryResult = and(queryResult, allCcpFilter); + } + + // add filter for PSP whitelist + if (!CollectionUtils.isEmpty(pspWhitelist)) { + var pspIn = in(ID_PSP_PARAM, pspWhitelist); + queryResult = and(queryResult, pspIn); + } + + // execute the query + return cosmosTemplate.find(new CosmosQuery(queryResult), ValidBundle.class, "validbundles"); + } + /** * Null value are ignored -> they are skipped when building the filters * @@ -156,6 +264,44 @@ private Iterable findValidBundles(PaymentOption paymentOption, bool return cosmosTemplate.find(new CosmosQuery(queryResult), ValidBundle.class, "validbundles"); } + /** + * These filters are done with Java (not with cosmos query) + * + * @param paymentNoticeItem the request + * @param validBundles the valid bundles + * @return the GLOBAL bundles and PRIVATE|PUBLIC bundles of the CI + */ + private List getFilteredBundlesMulti( + PaymentNoticeItem paymentNoticeItem, Iterable validBundles) { + Iterable filteredValidBundles = filterMinMaxAmount(paymentNoticeItem, validBundles); + var onlyMarcaBolloDigitale = + paymentNoticeItem.getTransferList().stream() + .filter(Objects::nonNull) + .filter(elem -> Boolean.TRUE.equals(elem.getDigitalStamp())) + .count(); + var transferListSize = paymentNoticeItem.getTransferList().size(); + + return StreamSupport.stream(filteredValidBundles.spliterator(), true) + .filter(bundle -> digitalStampFilter(transferListSize, onlyMarcaBolloDigitale, bundle)) + // Gets the GLOBAL bundles and PRIVATE|PUBLIC bundles of the CI + .filter(bundle -> globalAndRelatedFilter(paymentNoticeItem, bundle)) + .collect(Collectors.toList()); + } + + /** + * These filters are done with Java (not with cosmos query) + * + * @param paymentNoticeItem the request + * @param validBundles the valid bundles + * @return the GLOBAL bundles and PRIVATE|PUBLIC bundles of the CI + */ + private Iterable filterMinMaxAmount(PaymentNoticeItem paymentNoticeItem, Iterable validBundles){ + return StreamSupport.stream(validBundles.spliterator(), true) + .filter(validBundle -> validBundle.getMaxPaymentAmount() <= paymentNoticeItem.getPaymentAmount()) + .filter(validBundle -> validBundle.getMaxPaymentAmount() > paymentNoticeItem.getPaymentAmount()) + .toList(); + } + /** * These filters are done with Java (not with cosmos query) * @@ -219,6 +365,20 @@ private static boolean globalAndRelatedFilter(PaymentOption paymentOption, Valid return isGlobal(bundle) || belongsCI(bundle); } + /** + * Gets the GLOBAL bundles and PRIVATE|PUBLIC bundles of the CI + * + * @param paymentNoticeItem the request + * @param bundle a valid bundle + * @return True if the valid bundle meets the criteria. + */ + private static boolean globalAndRelatedFilter(PaymentNoticeItem paymentNoticeItem, ValidBundle bundle) { + // filter the ci-bundle list + bundle.setCiBundleList(filterByCI(paymentNoticeItem.getPrimaryCreditorInstitution(), bundle)); + return isGlobal(bundle) || belongsCI(bundle); + } + + /** * @param bundle a valid bundle * @return True if the bundle is related with the CI diff --git a/src/main/java/it/gov/pagopa/afm/calculator/service/UtilityComponent.java b/src/main/java/it/gov/pagopa/afm/calculator/service/UtilityComponent.java index 7fc66a04..3938f2f6 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/service/UtilityComponent.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/service/UtilityComponent.java @@ -2,7 +2,9 @@ import it.gov.pagopa.afm.calculator.entity.ValidBundle; import it.gov.pagopa.afm.calculator.model.BundleType; +import it.gov.pagopa.afm.calculator.model.PaymentNoticeItem; import it.gov.pagopa.afm.calculator.model.PaymentOption; +import it.gov.pagopa.afm.calculator.model.PaymentOptionMulti; import it.gov.pagopa.afm.calculator.model.TransferListItem; import java.util.ArrayList; import java.util.List; @@ -55,6 +57,24 @@ public List getTransferCategoryList(PaymentOption paymentOption) { : null; } + /** + * Retrieve the transfer category list from the transfer list of payment option (OR of transfer + * categories) + * + * @param paymentNoticeItem request + * @return list of string about transfer categories + */ + @Cacheable(value = "getTransferCategoryList") + public List getTransferCategoryList(PaymentNoticeItem paymentNoticeItem) { + log.debug("getTransferCategoryList"); + return paymentNoticeItem.getTransferList() != null + ? paymentNoticeItem.getTransferList().parallelStream() + .map(TransferListItem::getTransferCategory) + .distinct() + .collect(Collectors.toList()) + : null; + } + /** * Retrieve the transfer category list of primary creditor institution contained in the transfer * list of payment option From a2c2493db022d4f21c663c86caadef601fbd26fb Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Thu, 15 Feb 2024 10:29:20 +0100 Subject: [PATCH 06/30] PAGOPA-1492 fixing transfer logic --- .../afm/calculator/repository/CosmosRepository.java | 2 +- .../afm/calculator/service/UtilityComponent.java | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java b/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java index 9e8f0bed..80ed1182 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java @@ -139,7 +139,7 @@ private Iterable findValidBundlesMulti(PaymentOptionMulti paymentOp } // add filter by Transfer Category: transferCategory[] contains one of paymentOption - List categoryList = utilityComponent.getTransferCategoryList(paymentOption.getPaymentNotice().get(0)); //TODO iterate payment notice + List categoryList = utilityComponent.getTransferCategoryList(paymentOption); if (categoryList != null) { var taxonomyFilter = categoryList.parallelStream() diff --git a/src/main/java/it/gov/pagopa/afm/calculator/service/UtilityComponent.java b/src/main/java/it/gov/pagopa/afm/calculator/service/UtilityComponent.java index 3938f2f6..78b281a0 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/service/UtilityComponent.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/service/UtilityComponent.java @@ -61,14 +61,18 @@ public List getTransferCategoryList(PaymentOption paymentOption) { * Retrieve the transfer category list from the transfer list of payment option (OR of transfer * categories) * - * @param paymentNoticeItem request + * @param paymentOptionMulti request * @return list of string about transfer categories */ @Cacheable(value = "getTransferCategoryList") - public List getTransferCategoryList(PaymentNoticeItem paymentNoticeItem) { + public List getTransferCategoryList(PaymentOptionMulti paymentOptionMulti) { + List transferList = new ArrayList<>(); + paymentOptionMulti.getPaymentNotice().forEach(paymentNoticeItem -> { + transferList.addAll(paymentNoticeItem.getTransferList()); + }); log.debug("getTransferCategoryList"); - return paymentNoticeItem.getTransferList() != null - ? paymentNoticeItem.getTransferList().parallelStream() + return transferList != null + ? transferList.parallelStream() .map(TransferListItem::getTransferCategory) .distinct() .collect(Collectors.toList()) From e550132e7edccf93727e07e2f55907b22dd40645 Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Thu, 15 Feb 2024 15:11:00 +0100 Subject: [PATCH 07/30] PAGOPA-1492 fixing logic paymentNotice multiple CIs --- .../repository/CosmosRepository.java | 48 +++++++++++++------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java b/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java index 80ed1182..e0061fbb 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java @@ -13,6 +13,7 @@ import it.gov.pagopa.afm.calculator.model.PaymentOption; import it.gov.pagopa.afm.calculator.model.PaymentOptionMulti; import it.gov.pagopa.afm.calculator.model.PspSearchCriteria; +import it.gov.pagopa.afm.calculator.model.TransferListItem; import it.gov.pagopa.afm.calculator.service.UtilityComponent; import it.gov.pagopa.afm.calculator.util.CriteriaBuilder; import org.apache.commons.lang3.StringUtils; @@ -70,7 +71,7 @@ public List findByPaymentOption(PaymentOptionMulti paymentOption, b paymentOption.getPaymentNotice().forEach(paymentNoticeItem -> { }); - return getFilteredBundlesMulti(paymentOption.getPaymentNotice().get(0), validBundles); //TODO stream payment notice + return getFilteredBundlesMulti(paymentOption, validBundles); } /** @@ -267,38 +268,42 @@ private Iterable findValidBundles(PaymentOption paymentOption, bool /** * These filters are done with Java (not with cosmos query) * - * @param paymentNoticeItem the request + * @param paymentOptionMulti the request * @param validBundles the valid bundles * @return the GLOBAL bundles and PRIVATE|PUBLIC bundles of the CI */ private List getFilteredBundlesMulti( - PaymentNoticeItem paymentNoticeItem, Iterable validBundles) { - Iterable filteredValidBundles = filterMinMaxAmount(paymentNoticeItem, validBundles); + PaymentOptionMulti paymentOptionMulti, Iterable validBundles) { + var wrapper = new Object(){ long paymentAmount = 0; }; + paymentOptionMulti.getPaymentNotice().forEach(paymentNoticeItem -> wrapper.paymentAmount += paymentNoticeItem.getPaymentAmount()); + Iterable filteredValidBundles = filterMinMaxAmount(wrapper.paymentAmount, validBundles); + List transferList = new ArrayList<>(); + paymentOptionMulti.getPaymentNotice().forEach(paymentNoticeItem -> transferList.addAll(paymentNoticeItem.getTransferList())); var onlyMarcaBolloDigitale = - paymentNoticeItem.getTransferList().stream() + transferList.stream() .filter(Objects::nonNull) .filter(elem -> Boolean.TRUE.equals(elem.getDigitalStamp())) .count(); - var transferListSize = paymentNoticeItem.getTransferList().size(); + var transferListSize = transferList.size(); return StreamSupport.stream(filteredValidBundles.spliterator(), true) .filter(bundle -> digitalStampFilter(transferListSize, onlyMarcaBolloDigitale, bundle)) // Gets the GLOBAL bundles and PRIVATE|PUBLIC bundles of the CI - .filter(bundle -> globalAndRelatedFilter(paymentNoticeItem, bundle)) + .filter(bundle -> globalAndRelatedFilter(paymentOptionMulti, bundle)) .collect(Collectors.toList()); } /** * These filters are done with Java (not with cosmos query) * - * @param paymentNoticeItem the request + * @param paymentAmount the request * @param validBundles the valid bundles * @return the GLOBAL bundles and PRIVATE|PUBLIC bundles of the CI */ - private Iterable filterMinMaxAmount(PaymentNoticeItem paymentNoticeItem, Iterable validBundles){ + private Iterable filterMinMaxAmount(long paymentAmount, Iterable validBundles){ return StreamSupport.stream(validBundles.spliterator(), true) - .filter(validBundle -> validBundle.getMaxPaymentAmount() <= paymentNoticeItem.getPaymentAmount()) - .filter(validBundle -> validBundle.getMaxPaymentAmount() > paymentNoticeItem.getPaymentAmount()) + .filter(validBundle -> validBundle.getMaxPaymentAmount() <= paymentAmount) + .filter(validBundle -> validBundle.getMaxPaymentAmount() > paymentAmount) .toList(); } @@ -368,16 +373,31 @@ private static boolean globalAndRelatedFilter(PaymentOption paymentOption, Valid /** * Gets the GLOBAL bundles and PRIVATE|PUBLIC bundles of the CI * - * @param paymentNoticeItem the request + * @param paymentOptionMulti the request * @param bundle a valid bundle * @return True if the valid bundle meets the criteria. */ - private static boolean globalAndRelatedFilter(PaymentNoticeItem paymentNoticeItem, ValidBundle bundle) { + private static boolean globalAndRelatedFilter(PaymentOptionMulti paymentOptionMulti, ValidBundle bundle) { // filter the ci-bundle list - bundle.setCiBundleList(filterByCI(paymentNoticeItem.getPrimaryCreditorInstitution(), bundle)); + bundle.setCiBundleList(filteredCiBundles(paymentOptionMulti, bundle)); return isGlobal(bundle) || belongsCI(bundle); } + /** + * Check if all the ci fiscal codes in the payment notice are present in the ciBundle + * + * @param paymentOptionMulti the request + * @param bundle a valid bundle + * @return empty list if at least one element is not present, otherwise the full list + */ + private static List filteredCiBundles(PaymentOptionMulti paymentOptionMulti, ValidBundle bundle) { + List ciBundlesFiscalCodes = new ArrayList<>(); + bundle.getCiBundleList().forEach(ciBundle -> ciBundlesFiscalCodes.add(ciBundle.getCiFiscalCode())); + boolean allCiBundlesPresent = paymentOptionMulti.getPaymentNotice().stream() + .anyMatch(paymentNoticeItem -> ciBundlesFiscalCodes.contains(paymentNoticeItem.getPrimaryCreditorInstitution())); + return allCiBundlesPresent ? bundle.getCiBundleList() : new ArrayList<>(); + } + /** * @param bundle a valid bundle From 6b2f198f98688277220d7fae2b41451a682bbff9 Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Mon, 19 Feb 2024 18:25:51 +0100 Subject: [PATCH 08/30] PAGOPA-1492 adding more output logic --- .../controller/CalculatorController.java | 7 +- .../calculator/model/PaymentOptionMulti.java | 4 + .../model/calculatorMulti/Transfer.java | 1 + .../repository/CosmosRepository.java | 16 +- .../calculator/service/CalculatorService.java | 144 +++++++++++++++++- .../calculator/service/UtilityComponent.java | 25 ++- 6 files changed, 178 insertions(+), 19 deletions(-) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/controller/CalculatorController.java b/src/main/java/it/gov/pagopa/afm/calculator/controller/CalculatorController.java index 1061f224..84290489 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/controller/CalculatorController.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/controller/CalculatorController.java @@ -320,7 +320,7 @@ public BundleOption getFeesByPspMulti( value = "/fees/multi", produces = {MediaType.APPLICATION_JSON_VALUE}) public BundleOption getFeesMulti( - @RequestBody @Valid PaymentOption paymentOption, + @RequestBody @Valid PaymentOptionMulti paymentOption, @RequestParam(required = false, defaultValue = "10") Integer maxOccurrences, @RequestParam(required = false, defaultValue = "true") @Parameter( @@ -328,8 +328,7 @@ public BundleOption getFeesMulti( "Flag for the exclusion of Poste bundles: false -> excluded, true or null ->" + " included") String allCcp) { - return BundleOption.builder() - .belowThreshold(false) - .build(); + return calculatorService.calculateMulti( + paymentOption, maxOccurrences, StringUtils.isBlank(allCcp) || Boolean.parseBoolean(allCcp)); } } diff --git a/src/main/java/it/gov/pagopa/afm/calculator/model/PaymentOptionMulti.java b/src/main/java/it/gov/pagopa/afm/calculator/model/PaymentOptionMulti.java index 89211995..e79dac16 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/model/PaymentOptionMulti.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/model/PaymentOptionMulti.java @@ -17,4 +17,8 @@ public class PaymentOptionMulti { private String touchpoint; private List idPspList; @Valid @NotNull @NotEmpty private List paymentNotice; + + public Long getPaymentAmount () { + return this.getPaymentNotice().stream().mapToLong(PaymentNoticeItem::getPaymentAmount).sum(); + } } diff --git a/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Transfer.java b/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Transfer.java index 7286ca6e..1428df55 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Transfer.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Transfer.java @@ -18,6 +18,7 @@ public class Transfer implements Comparable, Serializable { private static final long serialVersionUID = 1287710978645388173L; private Long taxPayerFee; + private Long actualPayerFee; private String paymentMethod; private String touchpoint; private String idBundle; diff --git a/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java b/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java index e0061fbb..a563bfdb 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java @@ -68,9 +68,7 @@ public List findByPaymentOption(PaymentOption paymentOption, boolea @Cacheable(value = "findValidBundlesMulti") public List findByPaymentOption(PaymentOptionMulti paymentOption, boolean allCcp) { Iterable validBundles = findValidBundlesMulti(paymentOption, allCcp); - paymentOption.getPaymentNotice().forEach(paymentNoticeItem -> { - - }); + ValidBundle x = validBundles.iterator().next(); return getFilteredBundlesMulti(paymentOption, validBundles); } @@ -83,15 +81,11 @@ public List findByPaymentOption(PaymentOptionMulti paymentOption, b private Iterable findValidBundlesMulti(PaymentOptionMulti paymentOption, boolean allCcp) { // add filter by Payment Amount: minPaymentAmount <= paymentAmount < maxPaymentAmount - /* var minFilter = CriteriaBuilder.lessThan("minPaymentAmount", paymentOption.getPaymentAmount()); var maxFilter = CriteriaBuilder.greaterThanEqual("maxPaymentAmount", paymentOption.getPaymentAmount()); var queryResult = and(minFilter, maxFilter); - */ - - Criteria queryResult = null; // add filter by Touch Point: touchpoint= || touchpoint==null if (paymentOption.getTouchpoint() != null && !paymentOption.getTouchpoint().equalsIgnoreCase("any")) { @@ -274,9 +268,8 @@ private Iterable findValidBundles(PaymentOption paymentOption, bool */ private List getFilteredBundlesMulti( PaymentOptionMulti paymentOptionMulti, Iterable validBundles) { - var wrapper = new Object(){ long paymentAmount = 0; }; - paymentOptionMulti.getPaymentNotice().forEach(paymentNoticeItem -> wrapper.paymentAmount += paymentNoticeItem.getPaymentAmount()); - Iterable filteredValidBundles = filterMinMaxAmount(wrapper.paymentAmount, validBundles); + + // marca da bollo digitale check List transferList = new ArrayList<>(); paymentOptionMulti.getPaymentNotice().forEach(paymentNoticeItem -> transferList.addAll(paymentNoticeItem.getTransferList())); var onlyMarcaBolloDigitale = @@ -286,7 +279,7 @@ private List getFilteredBundlesMulti( .count(); var transferListSize = transferList.size(); - return StreamSupport.stream(filteredValidBundles.spliterator(), true) + return StreamSupport.stream(validBundles.spliterator(), true) .filter(bundle -> digitalStampFilter(transferListSize, onlyMarcaBolloDigitale, bundle)) // Gets the GLOBAL bundles and PRIVATE|PUBLIC bundles of the CI .filter(bundle -> globalAndRelatedFilter(paymentOptionMulti, bundle)) @@ -301,6 +294,7 @@ private List getFilteredBundlesMulti( * @return the GLOBAL bundles and PRIVATE|PUBLIC bundles of the CI */ private Iterable filterMinMaxAmount(long paymentAmount, Iterable validBundles){ + ValidBundle x = validBundles.iterator().next(); return StreamSupport.stream(validBundles.spliterator(), true) .filter(validBundle -> validBundle.getMaxPaymentAmount() <= paymentAmount) .filter(validBundle -> validBundle.getMaxPaymentAmount() > paymentAmount) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java index 89e04a9f..04e66390 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java @@ -5,11 +5,13 @@ import it.gov.pagopa.afm.calculator.entity.ValidBundle; import it.gov.pagopa.afm.calculator.exception.AppError; import it.gov.pagopa.afm.calculator.exception.AppException; +import it.gov.pagopa.afm.calculator.model.PaymentNoticeItem; import it.gov.pagopa.afm.calculator.model.PaymentOption; import it.gov.pagopa.afm.calculator.model.PaymentOptionMulti; import it.gov.pagopa.afm.calculator.model.TransferCategoryRelation; import it.gov.pagopa.afm.calculator.model.calculator.BundleOption; import it.gov.pagopa.afm.calculator.model.calculator.Transfer; +import it.gov.pagopa.afm.calculator.model.calculatorMulti.Fee; import it.gov.pagopa.afm.calculator.repository.CosmosRepository; import lombok.Setter; import org.apache.commons.lang3.StringUtils; @@ -21,12 +23,15 @@ import javax.validation.Valid; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Random; import java.util.function.Predicate; import java.util.stream.Collectors; import static it.gov.pagopa.afm.calculator.service.UtilityComponent.inTransferList; +import static it.gov.pagopa.afm.calculator.service.UtilityComponent.inTransferListMulti; import static it.gov.pagopa.afm.calculator.service.UtilityComponent.isGlobal; @Service @@ -59,7 +64,11 @@ public BundleOption calculate(@Valid PaymentOption paymentOption, int limit, boo } public BundleOption calculateMulti(@Valid PaymentOptionMulti paymentOption, int limit, boolean allCcp) { - return null; + List filteredBundles = cosmosRepository.findByPaymentOption(paymentOption, allCcp); + Collections.shuffle(filteredBundles, new Random()); + return BundleOption.builder() + .belowThreshold(isBelowThreshold(paymentOption.getPaymentAmount())) + .build(); } private List calculateTaxPayerFee( @@ -123,6 +132,74 @@ private List calculateTaxPayerFee( return transfers.stream().limit(limit).collect(Collectors.toList()); } + private List calculateTaxPayerFeeMulti( + PaymentOptionMulti paymentOption, int limit, List bundles) { + + HashMap primaryCiInTransferListMap = new HashMap<>(); + paymentOption.getPaymentNotice().forEach(paymentNoticeItem -> { + if(!primaryCiInTransferListMap.containsKey(paymentNoticeItem.getPrimaryCreditorInstitution())) { + primaryCiInTransferListMap.put( + paymentNoticeItem.getPrimaryCreditorInstitution(), + inTransferList(paymentNoticeItem.getPrimaryCreditorInstitution(), paymentNoticeItem.getTransferList())); + } else { + //TODO lancia eccezione, due paymentNoticeItem con stesso org fiscal code + } + }); + + List transfers = new ArrayList<>(); + + // 1. Check if ONUS payment: + // - ONUS payment = if the bundle ABI attribute matching the one extracted via BIN from the + // issuers table + // 2. The returned transfer list must contain: + // - if ONUS payment = Only the bundles with the idChannel attribute ending in '_ONUS' + // - if not ONUS payment = Only the bundles with the idChannel attribute NOT ending in '_ONUS' + + // 1.a: get issuers by BIN + List issuers = + StringUtils.isNotBlank(paymentOption.getBin()) + ? issuersService.getIssuersByBIN(paymentOption.getBin()) + : new ArrayList<>(); + + // 1.b: all records extracted via a specific BIN must have the same ABI otherwise the exception + // is raised + // - the limit(2) operation is used to terminate as soon as two distinct ABI objects are found + if (isUniqueAbi(issuers)) { + throw new AppException(AppError.ISSUERS_BIN_WITH_DIFFERENT_ABI_ERROR, paymentOption.getBin()); + } + + for (ValidBundle bundle : bundles) { + + // 1.c: check if onus payment type + boolean isOnusPaymentType = isOnusPayment(issuers, bundle); + + // 2.a: if ONUS payment -> return the transfer list only for bundles with the idChannel + // attribute ending in '_ONUS' + if (isOnusPaymentType && isOnusBundle(bundle)) { + transfers.addAll(this.getTransferList(paymentOption, primaryCiInTransferListMap, bundle)); + } + // 2.b: if not ONUS payment -> return the transfer list only for bundles with the idChannel + // attribute NOT ending in '_ONUS' + if (!isOnusPaymentType && !isOnusBundle(bundle)) { + transfers.addAll(this.getTransferList(paymentOption, primaryCiInTransferList, bundle)); + } + } + + // if it is a payment on the AMEX circuit --> filter to return only AMEX_ONUS + if (this.isAMEXAbi(issuers)) { + Predicate abiPredicate = t -> amexABI.equalsIgnoreCase(t.getAbi()); + Predicate onusPredicate = t -> Boolean.TRUE.equals(t.getOnUs()); + transfers = + transfers.stream().filter(abiPredicate.and(onusPredicate)).collect(Collectors.toList()); + } + + // sort according onus and taxpayer fee + Collections.sort(transfers); + + sortByFeePerPsp(transfers); + + return transfers.stream().limit(limit).collect(Collectors.toList()); + } private boolean isOnusBundle(ValidBundle bundle) { return StringUtils.endsWithIgnoreCase(bundle.getIdChannel(), ONUS_BUNDLE_SUFFIX); @@ -156,6 +233,20 @@ private List getTransferList( return transfers; } + private List getTransferList( + PaymentOptionMulti paymentOption, Map primaryCiInTransferListMap, ValidBundle bundle) { + List transfers = new ArrayList<>(); + paymentOption.getPaymentNotice().forEach(paymentNoticeItem -> { + if(primaryCiInTransferListMap.containsKey(paymentNoticeItem.getPrimaryCreditorInstitution())) { + List x = analyzeFee(paymentNoticeItem, bundle); + } else { + it.gov.pagopa.afm.calculator.model.calculatorMulti.Transfer transfer = null; + transfers.add(transfer); + } + }); + return transfers; + } + /** * Add in {@code transfers} the created transfer objects * @@ -236,6 +327,57 @@ private void analyzeTransferList( } } + private List analyzeFee( + PaymentNoticeItem paymentNoticeItem, ValidBundle bundle) { + List fees = new ArrayList<>(); + List primaryTransferCategoryList = + utilityComponent.getPrimaryTransferCategoryListMulti( + paymentNoticeItem, paymentNoticeItem.getPrimaryCreditorInstitution()); + var ciBundles = + bundle.getCiBundleList() != null ? bundle.getCiBundleList() : new ArrayList(); + + // analyze public and private bundles + for (CiBundle cibundle : ciBundles) { + if (cibundle.getAttributes() != null && !cibundle.getAttributes().isEmpty()) { + fees.addAll( + cibundle + .getAttributes() + .parallelStream() + .filter( + attribute -> + (attribute.getTransferCategory() == null + || (TransferCategoryRelation.EQUAL.equals( + attribute.getTransferCategoryRelation()) + && primaryTransferCategoryList.contains( + attribute.getTransferCategory()) + || (TransferCategoryRelation.NOT_EQUAL.equals( + attribute.getTransferCategoryRelation()) + && !primaryTransferCategoryList.contains( + attribute.getTransferCategory()))))) + .map( + attribute -> { + return createFee(attribute.getMaxPaymentAmount(), cibundle.getCiFiscalCode()); + }) + .collect(Collectors.toList())); + } + } + return fees; + } + + /** + * @param creditorInstitution code of the creditor instiution + * @param primaryCiIncurredFee fee of CI + * @return Create transfer item + */ + private Fee createFee( + long primaryCiIncurredFee, + String creditorInstitution) { + return Fee.builder() + .creditorInstitution(creditorInstitution) + .primaryCiIncurredFee(primaryCiIncurredFee) + .build(); + } + /** * @param taxPayerFee fee of the user * @param primaryCiIncurredFee fee of CI diff --git a/src/main/java/it/gov/pagopa/afm/calculator/service/UtilityComponent.java b/src/main/java/it/gov/pagopa/afm/calculator/service/UtilityComponent.java index 78b281a0..c863643a 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/service/UtilityComponent.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/service/UtilityComponent.java @@ -67,9 +67,7 @@ public List getTransferCategoryList(PaymentOption paymentOption) { @Cacheable(value = "getTransferCategoryList") public List getTransferCategoryList(PaymentOptionMulti paymentOptionMulti) { List transferList = new ArrayList<>(); - paymentOptionMulti.getPaymentNotice().forEach(paymentNoticeItem -> { - transferList.addAll(paymentNoticeItem.getTransferList()); - }); + paymentOptionMulti.getPaymentNotice().forEach(paymentNoticeItem -> transferList.addAll(paymentNoticeItem.getTransferList())); log.debug("getTransferCategoryList"); return transferList != null ? transferList.parallelStream() @@ -99,4 +97,25 @@ public List getPrimaryTransferCategoryList( .collect(Collectors.toList()) : new ArrayList<>(); } + + /** + * Retrieve the transfer category list of primary creditor institution contained in the transfer + * list of payment option + * + * @param paymentNoticeItem request + * @param primaryCreditorInstitution fiscal code fo the CI + * @return list of string about transfer categories of primary creditor institution + */ + @Cacheable(value = "getPrimaryTransferCategoryListMulti") + public List getPrimaryTransferCategoryListMulti( + PaymentNoticeItem paymentNoticeItem, String primaryCreditorInstitution) { + log.debug("getPrimaryTransferCategoryList {} ", primaryCreditorInstitution); + return paymentNoticeItem.getTransferList() != null + ? paymentNoticeItem.getTransferList().parallelStream() + .filter(elem -> primaryCreditorInstitution.equals(elem.getCreditorInstitution())) + .map(TransferListItem::getTransferCategory) + .distinct() + .collect(Collectors.toList()) + : new ArrayList<>(); + } } From 2d3506e0eb77b7e89ca55f4525ec0e79139b6b1d Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Tue, 20 Feb 2024 11:57:48 +0100 Subject: [PATCH 09/30] PAGOPA-1492 output logic wip transfer created --- .../calculator/service/CalculatorService.java | 105 ++++++++++++++++-- 1 file changed, 93 insertions(+), 12 deletions(-) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java index 04e66390..56dd9d84 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java @@ -29,9 +29,9 @@ import java.util.Random; import java.util.function.Predicate; import java.util.stream.Collectors; +import java.util.stream.Stream; import static it.gov.pagopa.afm.calculator.service.UtilityComponent.inTransferList; -import static it.gov.pagopa.afm.calculator.service.UtilityComponent.inTransferListMulti; import static it.gov.pagopa.afm.calculator.service.UtilityComponent.isGlobal; @Service @@ -132,7 +132,7 @@ private List calculateTaxPayerFee( return transfers.stream().limit(limit).collect(Collectors.toList()); } - private List calculateTaxPayerFeeMulti( + private List calculateTaxPayerFeeMulti( PaymentOptionMulti paymentOption, int limit, List bundles) { HashMap primaryCiInTransferListMap = new HashMap<>(); @@ -146,7 +146,7 @@ private List calculateTaxPayerFeeMulti( } }); - List transfers = new ArrayList<>(); + List transfers = new ArrayList<>(); // 1. Check if ONUS payment: // - ONUS payment = if the bundle ABI attribute matching the one extracted via BIN from the @@ -181,14 +181,14 @@ private List calculateTaxPayerFeeMulti( // 2.b: if not ONUS payment -> return the transfer list only for bundles with the idChannel // attribute NOT ending in '_ONUS' if (!isOnusPaymentType && !isOnusBundle(bundle)) { - transfers.addAll(this.getTransferList(paymentOption, primaryCiInTransferList, bundle)); + transfers.addAll(this.getTransferList(paymentOption, primaryCiInTransferListMap, bundle)); } } // if it is a payment on the AMEX circuit --> filter to return only AMEX_ONUS if (this.isAMEXAbi(issuers)) { - Predicate abiPredicate = t -> amexABI.equalsIgnoreCase(t.getAbi()); - Predicate onusPredicate = t -> Boolean.TRUE.equals(t.getOnUs()); + Predicate abiPredicate = t -> amexABI.equalsIgnoreCase(t.getAbi()); + Predicate onusPredicate = t -> Boolean.TRUE.equals(t.getOnUs()); transfers = transfers.stream().filter(abiPredicate.and(onusPredicate)).collect(Collectors.toList()); } @@ -236,17 +236,56 @@ private List getTransferList( private List getTransferList( PaymentOptionMulti paymentOption, Map primaryCiInTransferListMap, ValidBundle bundle) { List transfers = new ArrayList<>(); + List> ciDiscountedFees = new ArrayList<>(); paymentOption.getPaymentNotice().forEach(paymentNoticeItem -> { if(primaryCiInTransferListMap.containsKey(paymentNoticeItem.getPrimaryCreditorInstitution())) { - List x = analyzeFee(paymentNoticeItem, bundle); + ciDiscountedFees.add(analyzeFee(paymentNoticeItem, bundle)); } else { - it.gov.pagopa.afm.calculator.model.calculatorMulti.Transfer transfer = null; - transfers.add(transfer); + transfers.add(createTransfer(bundle, paymentOption, new ArrayList<>())); } }); + List> combinedFees = getCartesianProduct(ciDiscountedFees); + combinedFees.stream().forEach(fees -> { + orderFee(paymentOption.getPaymentAmount(), fees); + transfers.add(createTransfer(bundle, paymentOption, fees)); + }); return transfers; } + private void orderFee (long paymentAmount, List fees) { + for(Fee fee: fees) { + if(paymentAmount - fee.getPrimaryCiIncurredFee() >= 0) { + paymentAmount -= fee.getPrimaryCiIncurredFee(); + fee.setActualCiIncurredFee(fee.getPrimaryCiIncurredFee()); + } else { + if(paymentAmount > 0) { + fee.setActualCiIncurredFee(fee.getPrimaryCiIncurredFee() - paymentAmount); + paymentAmount = 0; + } else { + break; + } + } + } + } + + private List> getCartesianProduct(List> sets) { + return cartesianProduct(sets,0).collect(Collectors.toList()); + } + + private Stream> cartesianProduct(List> sets, int index) { + if (index == sets.size()) { + List emptyList = new ArrayList<>(); + return Stream.of(emptyList); + } + List currentSet = sets.get(index); + return currentSet.stream().flatMap(element -> cartesianProduct(sets, index+1) + .map(list -> { + List newList = new ArrayList<>(list); + newList.add(0, element); + return newList; + })); + } + /** * Add in {@code transfers} the created transfer objects * @@ -355,9 +394,7 @@ private List analyzeFee( && !primaryTransferCategoryList.contains( attribute.getTransferCategory()))))) .map( - attribute -> { - return createFee(attribute.getMaxPaymentAmount(), cibundle.getCiFiscalCode()); - }) + attribute -> createFee(attribute.getMaxPaymentAmount(), cibundle.getCiFiscalCode())) .collect(Collectors.toList())); } } @@ -378,6 +415,35 @@ private Fee createFee( .build(); } + /** + * @param bundle info of the Bundle + * @param paymentOption the payment option involved in the transaction + * @param fees the fees to include in the transfer + * @return Create transfer item + */ + private it.gov.pagopa.afm.calculator.model.calculatorMulti.Transfer createTransfer( + ValidBundle bundle, + PaymentOptionMulti paymentOption, + List fees) { + long actualPayerFee = bundle.getPaymentAmount() - fees.stream().mapToLong(Fee::getActualCiIncurredFee).sum(); + return it.gov.pagopa.afm.calculator.model.calculatorMulti.Transfer.builder() + .taxPayerFee(bundle.getPaymentAmount()) + .actualPayerFee(Math.max(0, actualPayerFee)) + .paymentMethod(bundle.getPaymentType() == null ? "ANY" : bundle.getPaymentType()) + .touchpoint(bundle.getTouchpoint()) + .idBundle(bundle.getId()) + .bundleName(bundle.getName()) + .bundleDescription(bundle.getDescription()) + .idPsp(bundle.getIdPsp()) + .idBrokerPsp(bundle.getIdBrokerPsp()) + .idChannel(bundle.getIdChannel()) + .onUs(this.getOnUsValue(bundle, paymentOption)) + .abi(bundle.getAbi()) + .pspBusinessName(bundle.getPspBusinessName()) + .fees(fees) + .build(); + } + /** * @param taxPayerFee fee of the user * @param primaryCiIncurredFee fee of CI @@ -424,6 +490,21 @@ && isOnusBundle(bundle)) { return onusValue; } + private Boolean getOnUsValue(ValidBundle bundle, PaymentOptionMulti paymentOption) { + boolean onusValue = false; + + // if PaymentType is CP and amount > threshold and idChannel endsWith '_ONUS' ---> onus value + // true + if (bundle.getPaymentType() != null + && StringUtils.equalsIgnoreCase(bundle.getPaymentType(), "cp") + && !isBelowThreshold(paymentOption.getPaymentAmount()) + && isOnusBundle(bundle)) { + + onusValue = true; + } + return onusValue; + } + private boolean isBelowThreshold(long paymentAmount) { return paymentAmount < Long.parseLong(StringUtils.trim(amountThreshold)); } From df63b0e73f91b4ab51f81d224f34c87e2bac7bd6 Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Tue, 20 Feb 2024 12:13:56 +0100 Subject: [PATCH 10/30] PAGOPA-1492 logic fixed --- .../controller/CalculatorController.java | 2 +- .../calculator/service/CalculatorService.java | 27 ++++++++++++++++--- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/controller/CalculatorController.java b/src/main/java/it/gov/pagopa/afm/calculator/controller/CalculatorController.java index 84290489..99023838 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/controller/CalculatorController.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/controller/CalculatorController.java @@ -319,7 +319,7 @@ public BundleOption getFeesByPspMulti( @PostMapping( value = "/fees/multi", produces = {MediaType.APPLICATION_JSON_VALUE}) - public BundleOption getFeesMulti( + public it.gov.pagopa.afm.calculator.model.calculatorMulti.BundleOption getFeesMulti( @RequestBody @Valid PaymentOptionMulti paymentOption, @RequestParam(required = false, defaultValue = "10") Integer maxOccurrences, @RequestParam(required = false, defaultValue = "true") diff --git a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java index 56dd9d84..1d025539 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java @@ -63,11 +63,13 @@ public BundleOption calculate(@Valid PaymentOption paymentOption, int limit, boo .build(); } - public BundleOption calculateMulti(@Valid PaymentOptionMulti paymentOption, int limit, boolean allCcp) { + public it.gov.pagopa.afm.calculator.model.calculatorMulti.BundleOption calculateMulti(@Valid PaymentOptionMulti paymentOption, int limit, boolean allCcp) { List filteredBundles = cosmosRepository.findByPaymentOption(paymentOption, allCcp); Collections.shuffle(filteredBundles, new Random()); - return BundleOption.builder() + + return it.gov.pagopa.afm.calculator.model.calculatorMulti.BundleOption.builder() .belowThreshold(isBelowThreshold(paymentOption.getPaymentAmount())) + .bundleOptions(calculateTaxPayerFeeMulti(paymentOption, limit, filteredBundles)) .build(); } @@ -196,7 +198,7 @@ private List calcul // sort according onus and taxpayer fee Collections.sort(transfers); - sortByFeePerPsp(transfers); + sortByFeePerPspMulti(transfers); return transfers.stream().limit(limit).collect(Collectors.toList()); } @@ -245,7 +247,7 @@ private List getTra } }); List> combinedFees = getCartesianProduct(ciDiscountedFees); - combinedFees.stream().forEach(fees -> { + combinedFees.forEach(fees -> { orderFee(paymentOption.getPaymentAmount(), fees); transfers.add(createTransfer(bundle, paymentOption, fees)); }); @@ -525,4 +527,21 @@ private static void sortByFeePerPsp(List transfers) { return 0; // fixed to 0 because we don't want to sort by PSP name. }); } + + /** + * sort by bundles' fee grouped by PSP + * + * @param transfers list of transfers to sort + */ + private static void sortByFeePerPspMulti(List transfers) { + transfers.sort( + (t1, t2) -> { + int primarySort = t1.getIdPsp().compareTo(t2.getIdPsp()); + if (primarySort == 0) { + // if two bundles are of the same PSP we'll sort by fees + return t1.getTaxPayerFee().compareTo(t2.getTaxPayerFee()); + } + return 0; // fixed to 0 because we don't want to sort by PSP name. + }); + } } From 4e440052534bced44ebd18fafdab008dd5bdabf5 Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Tue, 20 Feb 2024 12:49:37 +0100 Subject: [PATCH 11/30] PAGOPA-1492 fixing minor logic issues --- .../pagopa/afm/calculator/service/CalculatorService.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java index 1d025539..c08248ba 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java @@ -248,7 +248,7 @@ private List getTra }); List> combinedFees = getCartesianProduct(ciDiscountedFees); combinedFees.forEach(fees -> { - orderFee(paymentOption.getPaymentAmount(), fees); + orderFee(bundle.getPaymentAmount(), fees); transfers.add(createTransfer(bundle, paymentOption, fees)); }); return transfers; @@ -261,7 +261,7 @@ private void orderFee (long paymentAmount, List fees) { fee.setActualCiIncurredFee(fee.getPrimaryCiIncurredFee()); } else { if(paymentAmount > 0) { - fee.setActualCiIncurredFee(fee.getPrimaryCiIncurredFee() - paymentAmount); + fee.setActualCiIncurredFee(paymentAmount); paymentAmount = 0; } else { break; @@ -379,7 +379,8 @@ private List analyzeFee( // analyze public and private bundles for (CiBundle cibundle : ciBundles) { - if (cibundle.getAttributes() != null && !cibundle.getAttributes().isEmpty()) { + if (cibundle.getAttributes() != null && !cibundle.getAttributes().isEmpty() + && paymentNoticeItem.getPrimaryCreditorInstitution().equals(cibundle.getCiFiscalCode())) { fees.addAll( cibundle .getAttributes() From e83c18a5c2eb9b8d08e0fd24923af4bc45719ee3 Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Tue, 20 Feb 2024 12:52:30 +0100 Subject: [PATCH 12/30] PAGOPA-1492 randomization of fees for compliance --- .../it/gov/pagopa/afm/calculator/service/CalculatorService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java index c08248ba..6bd9332b 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java @@ -255,6 +255,7 @@ private List getTra } private void orderFee (long paymentAmount, List fees) { + Collections.shuffle(fees); for(Fee fee: fees) { if(paymentAmount - fee.getPrimaryCiIncurredFee() >= 0) { paymentAmount -= fee.getPrimaryCiIncurredFee(); From 99e85dad5a1059752f35d59e112c696809573a36 Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Tue, 20 Feb 2024 14:47:22 +0100 Subject: [PATCH 13/30] PAGOPA-1492 fixing return of not ciBundle --- .../pagopa/afm/calculator/service/CalculatorService.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java index 6bd9332b..c3a29882 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java @@ -238,12 +238,14 @@ private List getTransferList( private List getTransferList( PaymentOptionMulti paymentOption, Map primaryCiInTransferListMap, ValidBundle bundle) { List transfers = new ArrayList<>(); + if(bundle.getCiBundleList().isEmpty()) { + transfers.add(createTransfer(bundle, paymentOption, new ArrayList<>())); + return transfers; + } List> ciDiscountedFees = new ArrayList<>(); paymentOption.getPaymentNotice().forEach(paymentNoticeItem -> { if(primaryCiInTransferListMap.containsKey(paymentNoticeItem.getPrimaryCreditorInstitution())) { ciDiscountedFees.add(analyzeFee(paymentNoticeItem, bundle)); - } else { - transfers.add(createTransfer(bundle, paymentOption, new ArrayList<>())); } }); List> combinedFees = getCartesianProduct(ciDiscountedFees); From cbcce085112f49788289bbb064a7175986155ba0 Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Wed, 21 Feb 2024 11:38:16 +0100 Subject: [PATCH 14/30] PAGOPA-1492 solving overwrite problem --- .../pagopa/afm/calculator/service/CalculatorService.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java index c3a29882..dc079057 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java @@ -14,6 +14,7 @@ import it.gov.pagopa.afm.calculator.model.calculatorMulti.Fee; import it.gov.pagopa.afm.calculator.repository.CosmosRepository; import lombok.Setter; +import org.apache.commons.lang3.SerializationUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -249,10 +250,10 @@ private List getTra } }); List> combinedFees = getCartesianProduct(ciDiscountedFees); - combinedFees.forEach(fees -> { + for(List fees: combinedFees) { orderFee(bundle.getPaymentAmount(), fees); transfers.add(createTransfer(bundle, paymentOption, fees)); - }); + } return transfers; } @@ -286,7 +287,7 @@ private Stream> cartesianProduct(List> sets, int index) { return currentSet.stream().flatMap(element -> cartesianProduct(sets, index+1) .map(list -> { List newList = new ArrayList<>(list); - newList.add(0, element); + newList.add(0, SerializationUtils.clone(element)); return newList; })); } From 6211b21e417bb4bd7f92d2d76318122182d0d07a Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Wed, 21 Feb 2024 14:17:19 +0100 Subject: [PATCH 15/30] PAGOPA-1492 changing idCiBundle to multiple --- .../model/calculatorMulti/Transfer.java | 2 +- .../calculator/service/CalculatorService.java | 40 ++++++++----------- 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Transfer.java b/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Transfer.java index 1428df55..7da1068f 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Transfer.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Transfer.java @@ -24,7 +24,7 @@ public class Transfer implements Comparable, Serializable { private String idBundle; private String bundleName; private String bundleDescription; - private String idCiBundle; + private List idsCiBundle; private String idPsp; private String idChannel; private String idBrokerPsp; diff --git a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java index dc079057..24cafc08 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java @@ -24,9 +24,7 @@ import javax.validation.Valid; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.Random; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -138,17 +136,6 @@ private List calculateTaxPayerFee( private List calculateTaxPayerFeeMulti( PaymentOptionMulti paymentOption, int limit, List bundles) { - HashMap primaryCiInTransferListMap = new HashMap<>(); - paymentOption.getPaymentNotice().forEach(paymentNoticeItem -> { - if(!primaryCiInTransferListMap.containsKey(paymentNoticeItem.getPrimaryCreditorInstitution())) { - primaryCiInTransferListMap.put( - paymentNoticeItem.getPrimaryCreditorInstitution(), - inTransferList(paymentNoticeItem.getPrimaryCreditorInstitution(), paymentNoticeItem.getTransferList())); - } else { - //TODO lancia eccezione, due paymentNoticeItem con stesso org fiscal code - } - }); - List transfers = new ArrayList<>(); // 1. Check if ONUS payment: @@ -179,12 +166,12 @@ private List calcul // 2.a: if ONUS payment -> return the transfer list only for bundles with the idChannel // attribute ending in '_ONUS' if (isOnusPaymentType && isOnusBundle(bundle)) { - transfers.addAll(this.getTransferList(paymentOption, primaryCiInTransferListMap, bundle)); + transfers.addAll(this.getTransferList(paymentOption, bundle)); } // 2.b: if not ONUS payment -> return the transfer list only for bundles with the idChannel // attribute NOT ending in '_ONUS' if (!isOnusPaymentType && !isOnusBundle(bundle)) { - transfers.addAll(this.getTransferList(paymentOption, primaryCiInTransferListMap, bundle)); + transfers.addAll(this.getTransferList(paymentOption, bundle)); } } @@ -237,26 +224,29 @@ private List getTransferList( } private List getTransferList( - PaymentOptionMulti paymentOption, Map primaryCiInTransferListMap, ValidBundle bundle) { + PaymentOptionMulti paymentOption, ValidBundle bundle) { List transfers = new ArrayList<>(); if(bundle.getCiBundleList().isEmpty()) { - transfers.add(createTransfer(bundle, paymentOption, new ArrayList<>())); + transfers.add(createTransfer(bundle, paymentOption, new ArrayList<>(), new ArrayList<>())); return transfers; } List> ciDiscountedFees = new ArrayList<>(); - paymentOption.getPaymentNotice().forEach(paymentNoticeItem -> { - if(primaryCiInTransferListMap.containsKey(paymentNoticeItem.getPrimaryCreditorInstitution())) { - ciDiscountedFees.add(analyzeFee(paymentNoticeItem, bundle)); - } - }); + paymentOption.getPaymentNotice().forEach(paymentNoticeItem -> ciDiscountedFees.add(analyzeFee(paymentNoticeItem, bundle))); List> combinedFees = getCartesianProduct(ciDiscountedFees); for(List fees: combinedFees) { orderFee(bundle.getPaymentAmount(), fees); - transfers.add(createTransfer(bundle, paymentOption, fees)); + List idsCiBundle = bundle.getCiBundleList().stream() + .filter(ciBundle -> getFiscalCodesFromFees(fees).contains(ciBundle.getCiFiscalCode())) + .map(CiBundle::getId).toList(); + transfers.add(createTransfer(bundle, paymentOption, fees, idsCiBundle)); } return transfers; } + private List getFiscalCodesFromFees(List fees){ + return fees.stream().map(Fee::getCreditorInstitution).toList(); + } + private void orderFee (long paymentAmount, List fees) { Collections.shuffle(fees); for(Fee fee: fees) { @@ -431,7 +421,8 @@ private Fee createFee( private it.gov.pagopa.afm.calculator.model.calculatorMulti.Transfer createTransfer( ValidBundle bundle, PaymentOptionMulti paymentOption, - List fees) { + List fees, + List idsCiBundles) { long actualPayerFee = bundle.getPaymentAmount() - fees.stream().mapToLong(Fee::getActualCiIncurredFee).sum(); return it.gov.pagopa.afm.calculator.model.calculatorMulti.Transfer.builder() .taxPayerFee(bundle.getPaymentAmount()) @@ -444,6 +435,7 @@ private it.gov.pagopa.afm.calculator.model.calculatorMulti.Transfer createTransf .idPsp(bundle.getIdPsp()) .idBrokerPsp(bundle.getIdBrokerPsp()) .idChannel(bundle.getIdChannel()) + .idsCiBundle(idsCiBundles) .onUs(this.getOnUsValue(bundle, paymentOption)) .abi(bundle.getAbi()) .pspBusinessName(bundle.getPspBusinessName()) From f38f472286e8e28c2653fbe33b6ebe296c5825e2 Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Wed, 21 Feb 2024 14:53:08 +0100 Subject: [PATCH 16/30] PAGOPA-1492 refactoring logic for payment notice with same code --- .../afm/calculator/service/CalculatorService.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java index 24cafc08..961c4fb1 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java @@ -24,7 +24,9 @@ import javax.validation.Valid; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Random; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -230,9 +232,11 @@ private List getTra transfers.add(createTransfer(bundle, paymentOption, new ArrayList<>(), new ArrayList<>())); return transfers; } - List> ciDiscountedFees = new ArrayList<>(); - paymentOption.getPaymentNotice().forEach(paymentNoticeItem -> ciDiscountedFees.add(analyzeFee(paymentNoticeItem, bundle))); - List> combinedFees = getCartesianProduct(ciDiscountedFees); + Map> ciDiscountedFeesMap = new HashMap<>(); + paymentOption.getPaymentNotice().forEach( + paymentNoticeItem -> ciDiscountedFeesMap.put(paymentNoticeItem.getPrimaryCreditorInstitution(), analyzeFee(paymentNoticeItem, bundle)) + ); + List> combinedFees = getCartesianProduct(new ArrayList<>(ciDiscountedFeesMap.values())); for(List fees: combinedFees) { orderFee(bundle.getPaymentAmount(), fees); List idsCiBundle = bundle.getCiBundleList().stream() From 2e0a99675d96b1e866cf93e2bbdd643fd84a4871 Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Wed, 21 Feb 2024 16:07:28 +0100 Subject: [PATCH 17/30] PAGOPA-1492 adding first tests --- .../controller/CalculatorControllerTest.java | 17 ++++++++++++ .../service/CalculatorServiceTest.java | 2 +- src/test/resources/requests/getFeesMulti.json | 27 +++++++++++++++++++ .../resources/responses/getFeesMulti.json | 22 +++++++++++++++ 4 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/test/resources/requests/getFeesMulti.json create mode 100644 src/test/resources/responses/getFeesMulti.json diff --git a/src/test/java/it/gov/pagopa/afm/calculator/controller/CalculatorControllerTest.java b/src/test/java/it/gov/pagopa/afm/calculator/controller/CalculatorControllerTest.java index 1f713be6..754c41a1 100644 --- a/src/test/java/it/gov/pagopa/afm/calculator/controller/CalculatorControllerTest.java +++ b/src/test/java/it/gov/pagopa/afm/calculator/controller/CalculatorControllerTest.java @@ -9,6 +9,7 @@ import it.gov.pagopa.afm.calculator.TestUtil; import it.gov.pagopa.afm.calculator.model.PaymentOption; +import it.gov.pagopa.afm.calculator.model.PaymentOptionMulti; import it.gov.pagopa.afm.calculator.model.calculator.BundleOption; import it.gov.pagopa.afm.calculator.service.CalculatorService; import java.io.IOException; @@ -33,7 +34,10 @@ class CalculatorControllerTest { @BeforeEach void setup() throws IOException { BundleOption result = TestUtil.readObjectFromFile("responses/getFees.json", BundleOption.class); + it.gov.pagopa.afm.calculator.model.calculatorMulti.BundleOption resultMulti = + TestUtil.readObjectFromFile("responses/getFeesMulti.json", it.gov.pagopa.afm.calculator.model.calculatorMulti.BundleOption.class); when(calculatorService.calculate(any(), anyInt(), any(Boolean.class))).thenReturn(result); + when(calculatorService.calculateMulti(any(), anyInt(), any(Boolean.class))).thenReturn(resultMulti); } @Test @@ -61,4 +65,17 @@ void getFees() throws Exception { .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON)); } + + @Test + @CsvSource({"/fees/multi"}) + void getFeesMulti() throws Exception { + var paymentOption = TestUtil.readObjectFromFile("requests/getFeesMulti.json", PaymentOptionMulti.class); + + mvc.perform( + post("/fees/multi") + .content(TestUtil.toJson(paymentOption)) + .contentType(MediaType.APPLICATION_JSON)) + .andExpect(status().isOk()) + .andExpect(content().contentType(MediaType.APPLICATION_JSON)); + } } diff --git a/src/test/java/it/gov/pagopa/afm/calculator/service/CalculatorServiceTest.java b/src/test/java/it/gov/pagopa/afm/calculator/service/CalculatorServiceTest.java index b3d124f2..82f34da9 100644 --- a/src/test/java/it/gov/pagopa/afm/calculator/service/CalculatorServiceTest.java +++ b/src/test/java/it/gov/pagopa/afm/calculator/service/CalculatorServiceTest.java @@ -435,7 +435,7 @@ void calculate_multipleTransferCreation() throws IOException, JSONException { List bundles = TestUtil.getMockMultipleValidBundle(); - Mockito.doReturn(bundles).when(cosmosRepository).findByPaymentOption(any(), any(Boolean.class)); + Mockito.doReturn(bundles).when(cosmosRepository).findByPaymentOption(any(PaymentOption.class), any(Boolean.class)); var paymentOption = TestUtil.readObjectFromFile("requests/getFeesMultipleTransfer.json", PaymentOption.class); diff --git a/src/test/resources/requests/getFeesMulti.json b/src/test/resources/requests/getFeesMulti.json new file mode 100644 index 00000000..958ab692 --- /dev/null +++ b/src/test/resources/requests/getFeesMulti.json @@ -0,0 +1,27 @@ +{ + "paymentMethod": "CP", + "touchpoint": "CHECKOUT", + "idPspList": [], + "paymentNotice": [ + { + "primaryCreditorInstitution": "77777777777", + "paymentAmount": 12000, + "transferList": [ + { + "creditorInstitution": "77777777777", + "transferCategory": "TAX1" + } + ] + }, + { + "primaryCreditorInstitution": "88888888888", + "paymentAmount": 1000, + "transferList": [ + { + "creditorInstitution": "88888888888", + "transferCategory": "TAX1" + } + ] + } + ] +} diff --git a/src/test/resources/responses/getFeesMulti.json b/src/test/resources/responses/getFeesMulti.json new file mode 100644 index 00000000..8cb9e125 --- /dev/null +++ b/src/test/resources/responses/getFeesMulti.json @@ -0,0 +1,22 @@ +{ + "belowThreshold": false, + "bundleOptions": [ + { + "taxPayerFee": 0, + "actualPayerFee": 1, + "paymentMethod": "CP", + "touchpoint": "1", + "idBundle": "1", + "bundleName": "bundle1", + "bundleDescription": null, + "idsCiBundle": [], + "idPsp": "ABC", + "idChannel": "13212880150_07_ONUS", + "idBrokerPsp": null, + "onUs": true, + "abi": "14156", + "pspBusinessName": "psp business name 1", + "fees": [] + } + ] +} From 365d022833bd929a94c2b1ef9c220f13c9a5d7ff Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Wed, 21 Feb 2024 16:22:02 +0100 Subject: [PATCH 18/30] PAGOPA-1492 removing security hotspot --- .../it/gov/pagopa/afm/calculator/service/CalculatorService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java index 961c4fb1..71e8bbc2 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java @@ -66,7 +66,7 @@ public BundleOption calculate(@Valid PaymentOption paymentOption, int limit, boo public it.gov.pagopa.afm.calculator.model.calculatorMulti.BundleOption calculateMulti(@Valid PaymentOptionMulti paymentOption, int limit, boolean allCcp) { List filteredBundles = cosmosRepository.findByPaymentOption(paymentOption, allCcp); - Collections.shuffle(filteredBundles, new Random()); + Collections.shuffle(filteredBundles); return it.gov.pagopa.afm.calculator.model.calculatorMulti.BundleOption.builder() .belowThreshold(isBelowThreshold(paymentOption.getPaymentAmount())) From 880ce0d8e604da70fc6c827fdbd101c92550c676 Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Wed, 21 Feb 2024 16:40:46 +0100 Subject: [PATCH 19/30] PAGOPA-1492 adding parametrized test --- .../calculator/controller/CalculatorControllerTest.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/test/java/it/gov/pagopa/afm/calculator/controller/CalculatorControllerTest.java b/src/test/java/it/gov/pagopa/afm/calculator/controller/CalculatorControllerTest.java index 754c41a1..b56896f6 100644 --- a/src/test/java/it/gov/pagopa/afm/calculator/controller/CalculatorControllerTest.java +++ b/src/test/java/it/gov/pagopa/afm/calculator/controller/CalculatorControllerTest.java @@ -15,6 +15,7 @@ import java.io.IOException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.CsvSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; @@ -66,13 +67,13 @@ void getFees() throws Exception { .andExpect(content().contentType(MediaType.APPLICATION_JSON)); } - @Test - @CsvSource({"/fees/multi"}) - void getFeesMulti() throws Exception { + @ParameterizedTest + @CsvSource({"/fees/multi", "/psps/12345/fees"}) + void getFeesMulti(String uri) throws Exception { var paymentOption = TestUtil.readObjectFromFile("requests/getFeesMulti.json", PaymentOptionMulti.class); mvc.perform( - post("/fees/multi") + post(uri) .content(TestUtil.toJson(paymentOption)) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) From 4d18b30f08e613815fa4622dbc065d7e0fa0a0a6 Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Wed, 21 Feb 2024 18:20:33 +0100 Subject: [PATCH 20/30] PAGOPA-1492 fixing byPsp call --- .../afm/calculator/controller/CalculatorController.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/controller/CalculatorController.java b/src/main/java/it/gov/pagopa/afm/calculator/controller/CalculatorController.java index 99023838..ab66f8fb 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/controller/CalculatorController.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/controller/CalculatorController.java @@ -236,7 +236,7 @@ public BundleOption getFees( @PostMapping( value = "/psps/{idPsp}/fees/multi", produces = {MediaType.APPLICATION_JSON_VALUE}) - public BundleOption getFeesByPspMulti( + public it.gov.pagopa.afm.calculator.model.calculatorMulti.BundleOption getFeesByPspMulti( @Parameter(description = "PSP identifier", required = true) @PathVariable("idPsp") String idPsp, @RequestBody @Valid PaymentOptionByPspMulti paymentOptionByPsp, @@ -261,9 +261,8 @@ public BundleOption getFeesByPspMulti( .bin(paymentOptionByPsp.getBin()) .paymentNotice(paymentOptionByPsp.getPaymentNotice()) .build(); - return BundleOption.builder() - .belowThreshold(false) - .build(); + return calculatorService.calculateMulti( + paymentOption, maxOccurrences, StringUtils.isBlank(allCcp) || Boolean.parseBoolean(allCcp)); } @Operation( From c3a3ed9d16ac56f7643ed95acb2a8a5a1e3159d8 Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Wed, 21 Feb 2024 18:27:09 +0100 Subject: [PATCH 21/30] PAGOPA-1492 fixing controller test --- .../afm/calculator/controller/CalculatorControllerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/it/gov/pagopa/afm/calculator/controller/CalculatorControllerTest.java b/src/test/java/it/gov/pagopa/afm/calculator/controller/CalculatorControllerTest.java index b56896f6..1e97e2d3 100644 --- a/src/test/java/it/gov/pagopa/afm/calculator/controller/CalculatorControllerTest.java +++ b/src/test/java/it/gov/pagopa/afm/calculator/controller/CalculatorControllerTest.java @@ -68,7 +68,7 @@ void getFees() throws Exception { } @ParameterizedTest - @CsvSource({"/fees/multi", "/psps/12345/fees"}) + @CsvSource({"/fees/multi", "/psps/12345/fees/multi"}) void getFeesMulti(String uri) throws Exception { var paymentOption = TestUtil.readObjectFromFile("requests/getFeesMulti.json", PaymentOptionMulti.class); From 15cd3e9d8440db5fd1035da3ac47d24e3b1e8ac8 Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Thu, 22 Feb 2024 11:30:25 +0100 Subject: [PATCH 22/30] PAGOPA-1492 adding first service tests --- .../repository/CosmosRepository.java | 17 ------- .../calculator/service/CalculatorService.java | 9 ++-- .../service/CalculatorServiceTest.java | 49 +++++++++++++++++++ src/test/resources/requests/getFeesMulti.json | 5 +- .../requests/getFeesMultiBinNotFound.json | 28 +++++++++++ .../requests/getFeesMultiBinNull.json | 27 ++++++++++ .../requests/getFeesMultiPspList.json | 48 ++++++++++++++++++ .../resources/responses/getFeesMulti.json | 16 ++++-- .../resources/responses/getFeesMulti2.json | 30 ++++++++++++ .../responses/getFeesMultiBinNotFound.json | 4 ++ .../responses/getFeesMultiBinNull.json | 4 ++ 11 files changed, 211 insertions(+), 26 deletions(-) create mode 100644 src/test/resources/requests/getFeesMultiBinNotFound.json create mode 100644 src/test/resources/requests/getFeesMultiBinNull.json create mode 100644 src/test/resources/requests/getFeesMultiPspList.json create mode 100644 src/test/resources/responses/getFeesMulti2.json create mode 100644 src/test/resources/responses/getFeesMultiBinNotFound.json create mode 100644 src/test/resources/responses/getFeesMultiBinNull.json diff --git a/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java b/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java index a563bfdb..0ca2b720 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java @@ -9,7 +9,6 @@ import it.gov.pagopa.afm.calculator.entity.Touchpoint; import it.gov.pagopa.afm.calculator.entity.ValidBundle; import it.gov.pagopa.afm.calculator.exception.AppException; -import it.gov.pagopa.afm.calculator.model.PaymentNoticeItem; import it.gov.pagopa.afm.calculator.model.PaymentOption; import it.gov.pagopa.afm.calculator.model.PaymentOptionMulti; import it.gov.pagopa.afm.calculator.model.PspSearchCriteria; @@ -68,7 +67,6 @@ public List findByPaymentOption(PaymentOption paymentOption, boolea @Cacheable(value = "findValidBundlesMulti") public List findByPaymentOption(PaymentOptionMulti paymentOption, boolean allCcp) { Iterable validBundles = findValidBundlesMulti(paymentOption, allCcp); - ValidBundle x = validBundles.iterator().next(); return getFilteredBundlesMulti(paymentOption, validBundles); } @@ -286,21 +284,6 @@ private List getFilteredBundlesMulti( .collect(Collectors.toList()); } - /** - * These filters are done with Java (not with cosmos query) - * - * @param paymentAmount the request - * @param validBundles the valid bundles - * @return the GLOBAL bundles and PRIVATE|PUBLIC bundles of the CI - */ - private Iterable filterMinMaxAmount(long paymentAmount, Iterable validBundles){ - ValidBundle x = validBundles.iterator().next(); - return StreamSupport.stream(validBundles.spliterator(), true) - .filter(validBundle -> validBundle.getMaxPaymentAmount() <= paymentAmount) - .filter(validBundle -> validBundle.getMaxPaymentAmount() > paymentAmount) - .toList(); - } - /** * These filters are done with Java (not with cosmos query) * diff --git a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java index 71e8bbc2..fdd25985 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java @@ -233,9 +233,12 @@ private List getTra return transfers; } Map> ciDiscountedFeesMap = new HashMap<>(); - paymentOption.getPaymentNotice().forEach( - paymentNoticeItem -> ciDiscountedFeesMap.put(paymentNoticeItem.getPrimaryCreditorInstitution(), analyzeFee(paymentNoticeItem, bundle)) - ); + paymentOption.getPaymentNotice().forEach(paymentNoticeItem -> { + List discountedFees = analyzeFee(paymentNoticeItem, bundle); + if(!discountedFees.isEmpty()){ + ciDiscountedFeesMap.put(paymentNoticeItem.getPrimaryCreditorInstitution(), discountedFees); + } + }); List> combinedFees = getCartesianProduct(new ArrayList<>(ciDiscountedFeesMap.values())); for(List fees: combinedFees) { orderFee(bundle.getPaymentAmount(), fees); diff --git a/src/test/java/it/gov/pagopa/afm/calculator/service/CalculatorServiceTest.java b/src/test/java/it/gov/pagopa/afm/calculator/service/CalculatorServiceTest.java index 82f34da9..fb6aa193 100644 --- a/src/test/java/it/gov/pagopa/afm/calculator/service/CalculatorServiceTest.java +++ b/src/test/java/it/gov/pagopa/afm/calculator/service/CalculatorServiceTest.java @@ -19,6 +19,7 @@ import it.gov.pagopa.afm.calculator.initializer.Initializer; import it.gov.pagopa.afm.calculator.model.BundleType; import it.gov.pagopa.afm.calculator.model.PaymentOption; +import it.gov.pagopa.afm.calculator.model.PaymentOptionMulti; import it.gov.pagopa.afm.calculator.model.calculator.BundleOption; import it.gov.pagopa.afm.calculator.repository.CosmosRepository; import java.io.IOException; @@ -448,4 +449,52 @@ void calculate_multipleTransferCreation() throws IOException, JSONException { assertEquals(false, result.getBundleOptions().get(3).getOnUs()); assertEquals(false, result.getBundleOptions().get(4).getOnUs()); } + + @ParameterizedTest + @CsvSource({ + "requests/getFeesMulti.json, responses/getFeesMulti.json", + "requests/getFeesMultiBinNull.json, responses/getFeesMultiBinNull.json", + "requests/getFeesMultiPspList.json, responses/getFeesMulti.json", + "requests/getFeesMultiBinNotFound.json, responses/getFeesMultiBinNotFound.json" + }) + @Order(13) + void calculateMulti(String input, String output) throws IOException, JSONException { + Touchpoint touchpoint = TestUtil.getMockTouchpoints(); + PaymentType paymentType = TestUtil.getMockPaymentType(); + + when(cosmosTemplate.find(any(CosmosQuery.class), any(), anyString())) + .thenReturn( + Collections.singleton(touchpoint), + Collections.singleton(paymentType), + Collections.singleton(TestUtil.getMockValidBundle())); + + var paymentOption = TestUtil.readObjectFromFile(input, PaymentOptionMulti.class); + var result = calculatorService.calculateMulti(paymentOption, 10, true); + String actual = TestUtil.toJson(result); + + String expected = TestUtil.readStringFromFile(output); + JSONAssert.assertEquals(expected, actual, JSONCompareMode.STRICT); + } + + @Test + @Order(14) + void calculateMulti2() throws IOException, JSONException { + ValidBundle validBundle = TestUtil.getMockValidBundle(); + validBundle.setIdPsp("77777777777"); + Touchpoint touchpoint = TestUtil.getMockTouchpoints(); + PaymentType paymentType = TestUtil.getMockPaymentType(); + + when(cosmosTemplate.find(any(CosmosQuery.class), any(), anyString())) + .thenReturn( + Collections.singleton(touchpoint), + Collections.singleton(paymentType), + Collections.singleton(validBundle)); + + var paymentOption = TestUtil.readObjectFromFile("requests/getFeesMulti.json", PaymentOptionMulti.class); + var result = calculatorService.calculateMulti(paymentOption, 10, true); + String actual = TestUtil.toJson(result); + + String expected = TestUtil.readStringFromFile("responses/getFeesMulti2.json"); + JSONAssert.assertEquals(expected, actual, JSONCompareMode.STRICT); + } } diff --git a/src/test/resources/requests/getFeesMulti.json b/src/test/resources/requests/getFeesMulti.json index 958ab692..85ff3800 100644 --- a/src/test/resources/requests/getFeesMulti.json +++ b/src/test/resources/requests/getFeesMulti.json @@ -1,11 +1,12 @@ { + "bin": "1005066", "paymentMethod": "CP", "touchpoint": "CHECKOUT", "idPspList": [], "paymentNotice": [ { "primaryCreditorInstitution": "77777777777", - "paymentAmount": 12000, + "paymentAmount": 30, "transferList": [ { "creditorInstitution": "77777777777", @@ -15,7 +16,7 @@ }, { "primaryCreditorInstitution": "88888888888", - "paymentAmount": 1000, + "paymentAmount": 40, "transferList": [ { "creditorInstitution": "88888888888", diff --git a/src/test/resources/requests/getFeesMultiBinNotFound.json b/src/test/resources/requests/getFeesMultiBinNotFound.json new file mode 100644 index 00000000..c8a5b6c1 --- /dev/null +++ b/src/test/resources/requests/getFeesMultiBinNotFound.json @@ -0,0 +1,28 @@ +{ + "bin": "xxxxxxx", + "paymentMethod": "CP", + "touchpoint": "CHECKOUT", + "idPspList": [], + "paymentNotice": [ + { + "primaryCreditorInstitution": "77777777777", + "paymentAmount": 30, + "transferList": [ + { + "creditorInstitution": "77777777777", + "transferCategory": "TAX1" + } + ] + }, + { + "primaryCreditorInstitution": "88888888888", + "paymentAmount": 40, + "transferList": [ + { + "creditorInstitution": "88888888888", + "transferCategory": "TAX1" + } + ] + } + ] +} diff --git a/src/test/resources/requests/getFeesMultiBinNull.json b/src/test/resources/requests/getFeesMultiBinNull.json new file mode 100644 index 00000000..216f21d6 --- /dev/null +++ b/src/test/resources/requests/getFeesMultiBinNull.json @@ -0,0 +1,27 @@ +{ + "paymentMethod": "CP", + "touchpoint": "CHECKOUT", + "idPspList": [], + "paymentNotice": [ + { + "primaryCreditorInstitution": "77777777777", + "paymentAmount": 30, + "transferList": [ + { + "creditorInstitution": "77777777777", + "transferCategory": "TAX1" + } + ] + }, + { + "primaryCreditorInstitution": "88888888888", + "paymentAmount": 40, + "transferList": [ + { + "creditorInstitution": "88888888888", + "transferCategory": "TAX1" + } + ] + } + ] +} diff --git a/src/test/resources/requests/getFeesMultiPspList.json b/src/test/resources/requests/getFeesMultiPspList.json new file mode 100644 index 00000000..bc1c657c --- /dev/null +++ b/src/test/resources/requests/getFeesMultiPspList.json @@ -0,0 +1,48 @@ +{ + "bin": "1005066", + "paymentMethod": "CP", + "touchpoint": "CHECKOUT", + "idPspList": [ + { + "idPsp": "ABC", + "idChannel": "123_01", + "idBrokerPsp": "123" + }, + { + "idPsp": "ABC", + "idChannel": "123_02", + "idBrokerPsp": "123" + }, + { + "idPsp": "ABC ", + "idChannel": "", + "idBrokerPsp": "" + }, + { + "idPsp": "ABC ", + "idChannel": "123_03" + } + ], + "paymentNotice": [ + { + "primaryCreditorInstitution": "77777777777", + "paymentAmount": 30, + "transferList": [ + { + "creditorInstitution": "77777777777", + "transferCategory": "TAX1" + } + ] + }, + { + "primaryCreditorInstitution": "88888888888", + "paymentAmount": 40, + "transferList": [ + { + "creditorInstitution": "88888888888", + "transferCategory": "TAX1" + } + ] + } + ] +} diff --git a/src/test/resources/responses/getFeesMulti.json b/src/test/resources/responses/getFeesMulti.json index 8cb9e125..ea61821e 100644 --- a/src/test/resources/responses/getFeesMulti.json +++ b/src/test/resources/responses/getFeesMulti.json @@ -2,21 +2,29 @@ "belowThreshold": false, "bundleOptions": [ { - "taxPayerFee": 0, - "actualPayerFee": 1, + "taxPayerFee": 1, + "actualPayerFee": 0, "paymentMethod": "CP", "touchpoint": "1", "idBundle": "1", "bundleName": "bundle1", "bundleDescription": null, - "idsCiBundle": [], + "idsCiBundle": [ + "1" + ], "idPsp": "ABC", "idChannel": "13212880150_07_ONUS", "idBrokerPsp": null, "onUs": true, "abi": "14156", "pspBusinessName": "psp business name 1", - "fees": [] + "fees": [ + { + "creditorInstitution" : "77777777777", + "primaryCiIncurredFee": 10, + "actualCiIncurredFee": 1 + } + ] } ] } diff --git a/src/test/resources/responses/getFeesMulti2.json b/src/test/resources/responses/getFeesMulti2.json new file mode 100644 index 00000000..b23b8623 --- /dev/null +++ b/src/test/resources/responses/getFeesMulti2.json @@ -0,0 +1,30 @@ +{ + "belowThreshold": false, + "bundleOptions": [ + { + "taxPayerFee": 1, + "actualPayerFee": 0, + "paymentMethod": "CP", + "touchpoint": "1", + "idBundle": "1", + "bundleName": "bundle1", + "bundleDescription": null, + "idsCiBundle": [ + "1" + ], + "idPsp": "77777777777", + "idChannel": "13212880150_07_ONUS", + "idBrokerPsp": null, + "onUs": true, + "abi": "14156", + "pspBusinessName": "psp business name 1", + "fees": [ + { + "creditorInstitution" : "77777777777", + "primaryCiIncurredFee": 10, + "actualCiIncurredFee": 1 + } + ] + } + ] +} diff --git a/src/test/resources/responses/getFeesMultiBinNotFound.json b/src/test/resources/responses/getFeesMultiBinNotFound.json new file mode 100644 index 00000000..44c924c9 --- /dev/null +++ b/src/test/resources/responses/getFeesMultiBinNotFound.json @@ -0,0 +1,4 @@ +{ + "belowThreshold": false, + "bundleOptions": [] +} diff --git a/src/test/resources/responses/getFeesMultiBinNull.json b/src/test/resources/responses/getFeesMultiBinNull.json new file mode 100644 index 00000000..44c924c9 --- /dev/null +++ b/src/test/resources/responses/getFeesMultiBinNull.json @@ -0,0 +1,4 @@ +{ + "belowThreshold": false, + "bundleOptions": [] +} From 34b1d2a6e68964d759d802fd13f6c217bfdc4572 Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Thu, 22 Feb 2024 12:56:05 +0100 Subject: [PATCH 23/30] PAGOPA-1492 adding remaining service tests --- .../service/CalculatorServiceTest.java | 229 ++++++++++++++++++ .../resources/requests/getAmexFeesMulti.json | 28 +++ src/test/resources/requests/getFeesMulti.json | 6 +- .../resources/requests/getFeesMulti2.json | 27 +++ .../getFeesMultiBINwithMultipleABI.json | 28 +++ .../requests/getFeesMultiDigitalStamp.json | 30 +++ .../requests/getFeesMultiDigitalStamp2.json | 30 +++ .../requests/getFeesMultiDigitalStamp3.json | 29 +++ .../requests/getFeesMultiSubThreshold.json | 28 +++ .../resources/responses/getAmexFeesMulti.json | 30 +++ .../resources/responses/getFeesMulti3.json | 30 +++ .../getFeesMultiPaymentTypeNull.json | 30 +++ .../responses/getFeesMultiSubThreshold.json | 22 ++ 13 files changed, 544 insertions(+), 3 deletions(-) create mode 100644 src/test/resources/requests/getAmexFeesMulti.json create mode 100644 src/test/resources/requests/getFeesMulti2.json create mode 100644 src/test/resources/requests/getFeesMultiBINwithMultipleABI.json create mode 100644 src/test/resources/requests/getFeesMultiDigitalStamp.json create mode 100644 src/test/resources/requests/getFeesMultiDigitalStamp2.json create mode 100644 src/test/resources/requests/getFeesMultiDigitalStamp3.json create mode 100644 src/test/resources/requests/getFeesMultiSubThreshold.json create mode 100644 src/test/resources/responses/getAmexFeesMulti.json create mode 100644 src/test/resources/responses/getFeesMulti3.json create mode 100644 src/test/resources/responses/getFeesMultiPaymentTypeNull.json create mode 100644 src/test/resources/responses/getFeesMultiSubThreshold.json diff --git a/src/test/java/it/gov/pagopa/afm/calculator/service/CalculatorServiceTest.java b/src/test/java/it/gov/pagopa/afm/calculator/service/CalculatorServiceTest.java index fb6aa193..cb3814ab 100644 --- a/src/test/java/it/gov/pagopa/afm/calculator/service/CalculatorServiceTest.java +++ b/src/test/java/it/gov/pagopa/afm/calculator/service/CalculatorServiceTest.java @@ -497,4 +497,233 @@ void calculateMulti2() throws IOException, JSONException { String expected = TestUtil.readStringFromFile("responses/getFeesMulti2.json"); JSONAssert.assertEquals(expected, actual, JSONCompareMode.STRICT); } + + @Test + @Order(15) + void calculateMulti3() throws IOException, JSONException { + ValidBundle validBundle = TestUtil.getMockValidBundle(); + validBundle.setIdPsp("77777777777"); + + when(cosmosTemplate.find(any(CosmosQuery.class), any(), anyString())) + .thenReturn(Collections.singleton(validBundle)); + + var paymentOption = TestUtil.readObjectFromFile("requests/getFeesMulti2.json", PaymentOptionMulti.class); + var result = calculatorService.calculateMulti(paymentOption, 10, true); + String actual = TestUtil.toJson(result); + + String expected = TestUtil.readStringFromFile("responses/getFeesMulti3.json"); + JSONAssert.assertEquals(expected, actual, JSONCompareMode.STRICT); + } + + @Test + @Order(16) + void calculateMulti_invalidTouchpoint() throws IOException { + when(cosmosTemplate.find(any(CosmosQuery.class), any(), anyString())) + .thenReturn(Collections.emptyList(), Collections.singleton(TestUtil.getMockValidBundle())); + + var paymentOption = TestUtil.readObjectFromFile("requests/getFeesMulti.json", PaymentOptionMulti.class); + + AppException exception = + assertThrows( + AppException.class, () -> calculatorService.calculateMulti(paymentOption, 10, true)); + + assertEquals(HttpStatus.NOT_FOUND, exception.getHttpStatus()); + } + + @Test + @Order(17) + void calculateMulti_invalidPaymentMethod() throws IOException { + when(cosmosTemplate.find(any(CosmosQuery.class), any(), anyString())) + .thenReturn( + Collections.singleton(TestUtil.getMockTouchpoints()), + Collections.emptyList(), + Collections.singleton(TestUtil.getMockValidBundle())); + + var paymentOption = TestUtil.readObjectFromFile("requests/getFeesMulti.json", PaymentOptionMulti.class); + + AppException exception = + assertThrows( + AppException.class, () -> calculatorService.calculateMulti(paymentOption, 10, true)); + + assertEquals(HttpStatus.NOT_FOUND, exception.getHttpStatus()); + } + + @Test + @Order(18) + void calculateMulti_digitalStamp() throws IOException, JSONException { + Touchpoint touchpoint = TestUtil.getMockTouchpoints(); + PaymentType paymentType = TestUtil.getMockPaymentType(); + ValidBundle mockValidBundle = TestUtil.getMockValidBundle(); + mockValidBundle.setDigitalStamp(true); + mockValidBundle.setDigitalStampRestriction(true); + + when(cosmosTemplate.find(any(CosmosQuery.class), any(), anyString())) + .thenReturn( + Collections.singleton(touchpoint), + Collections.singleton(paymentType), + Collections.singleton(mockValidBundle)); + + var paymentOption = + TestUtil.readObjectFromFile("requests/getFeesMultiDigitalStamp.json", PaymentOptionMulti.class); + var result = calculatorService.calculateMulti(paymentOption, 10, true); + String actual = TestUtil.toJson(result); + + String expected = TestUtil.readStringFromFile("responses/getFeesMulti.json"); + JSONAssert.assertEquals(expected, actual, JSONCompareMode.STRICT); + } + + @Test + @Order(19) + void calculateMulti_digitalStamp2() throws IOException, JSONException { + Touchpoint touchpoint = TestUtil.getMockTouchpoints(); + PaymentType paymentType = TestUtil.getMockPaymentType(); + ValidBundle mockValidBundle = TestUtil.getMockValidBundle(); + mockValidBundle.setDigitalStamp(true); + + when(cosmosTemplate.find(any(CosmosQuery.class), any(), anyString())) + .thenReturn( + Collections.singleton(touchpoint), + Collections.singleton(paymentType), + Collections.singleton(mockValidBundle)); + + var paymentOption = + TestUtil.readObjectFromFile("requests/getFeesMultiDigitalStamp2.json", PaymentOptionMulti.class); + var result = calculatorService.calculateMulti(paymentOption, 10, true); + String actual = TestUtil.toJson(result); + + String expected = TestUtil.readStringFromFile("responses/getFeesMulti.json"); + JSONAssert.assertEquals(expected, actual, JSONCompareMode.STRICT); + } + + @Test + @Order(20) + void calculateMulti_BIN_with_different_ABI_error() throws IOException, JSONException { + Touchpoint touchpoint = TestUtil.getMockTouchpoints(); + PaymentType paymentType = TestUtil.getMockPaymentType(); + + when(cosmosTemplate.find(any(CosmosQuery.class), any(), anyString())) + .thenReturn( + Collections.singleton(touchpoint), + Collections.singleton(paymentType), + Collections.singleton(TestUtil.getMockValidBundle())); + + var paymentOption = + TestUtil.readObjectFromFile("requests/getFeesMultiBINwithMultipleABI.json", PaymentOptionMulti.class); + + AppException exception = + assertThrows( + AppException.class, () -> calculatorService.calculateMulti(paymentOption, 10, true)); + + assertEquals(HttpStatus.UNPROCESSABLE_ENTITY, exception.getHttpStatus()); + } + + @Test + @Order(21) + void calculateMulti_SubThreshold() throws IOException, JSONException { + Touchpoint touchpoint = TestUtil.getMockTouchpoints(); + PaymentType paymentType = TestUtil.getMockPaymentType(); + ValidBundle mockValidBundle = TestUtil.getMockValidBundle(); + mockValidBundle.setMinPaymentAmount(-10L); + mockValidBundle.setPaymentAmount(-5L); + mockValidBundle.setIdPsp("111111111111"); + mockValidBundle.setType(BundleType.GLOBAL); + + when(cosmosTemplate.find(any(CosmosQuery.class), any(), anyString())) + .thenReturn( + Collections.singleton(touchpoint), + Collections.singleton(paymentType), + Collections.singleton(mockValidBundle)); + + var paymentOption = + TestUtil.readObjectFromFile("requests/getFeesMultiSubThreshold.json", PaymentOptionMulti.class); + var result = calculatorService.calculateMulti(paymentOption, 10, true); + String actual = TestUtil.toJson(result); + + String expected = TestUtil.readStringFromFile("responses/getFeesMultiSubThreshold.json"); + JSONAssert.assertEquals(expected, actual, JSONCompareMode.STRICT); + } + + @Test + @Order(22) + void calculateMulti_paymentType_Null() throws IOException, JSONException { + Touchpoint touchpoint = TestUtil.getMockTouchpoints(); + PaymentType paymentType = TestUtil.getMockPaymentType(); + ValidBundle mockValidBundle = TestUtil.getMockValidBundle(); + mockValidBundle.setPaymentType(null); + + when(cosmosTemplate.find(any(CosmosQuery.class), any(), anyString())) + .thenReturn( + Collections.singleton(touchpoint), + Collections.singleton(paymentType), + Collections.singleton(mockValidBundle)); + + var paymentOption = TestUtil.readObjectFromFile("requests/getFeesMulti.json", PaymentOptionMulti.class); + var result = calculatorService.calculateMulti(paymentOption, 10, true); + String actual = TestUtil.toJson(result); + + String expected = TestUtil.readStringFromFile("responses/getFeesMultiPaymentTypeNull.json"); + JSONAssert.assertEquals(expected, actual, JSONCompareMode.STRICT); + } + + @Test + @Order(23) + void calculateMulti_digitalStamp3() throws IOException, JSONException { + Touchpoint touchpoint = TestUtil.getMockTouchpoints(); + PaymentType paymentType = TestUtil.getMockPaymentType(); + ValidBundle mockValidBundle = TestUtil.getMockValidBundle(); + mockValidBundle.setDigitalStamp(true); + + when(cosmosTemplate.find(any(CosmosQuery.class), any(), anyString())) + .thenReturn( + Collections.singleton(touchpoint), + Collections.singleton(paymentType), + Collections.singleton(mockValidBundle)); + + var paymentOption = + TestUtil.readObjectFromFile("requests/getFeesMultiDigitalStamp3.json", PaymentOptionMulti.class); + var result = calculatorService.calculateMulti(paymentOption, 10, true); + String actual = TestUtil.toJson(result); + + String expected = TestUtil.readStringFromFile("responses/getFeesMulti.json"); + JSONAssert.assertEquals(expected, actual, JSONCompareMode.STRICT); + } + + @Test + @Order(24) + void calculateMulti_allCcpFlagDown() throws IOException, JSONException { + Touchpoint touchpoint = TestUtil.getMockTouchpoints(); + PaymentType paymentType = TestUtil.getMockPaymentType(); + when(cosmosTemplate.find(any(CosmosQuery.class), any(), anyString())) + .thenReturn( + Collections.singleton(touchpoint), + Collections.singleton(paymentType), + Collections.singleton(TestUtil.getMockValidBundle())); + + var paymentOption = TestUtil.readObjectFromFile("requests/getFeesMulti.json", PaymentOptionMulti.class); + it.gov.pagopa.afm.calculator.model.calculatorMulti.BundleOption result = + calculatorService.calculateMulti(paymentOption, 10, false); + assertEquals(1, result.getBundleOptions().size()); + } + + @Test + @Order(25) + void calculateMulti_amexPayment() throws IOException, JSONException { + ValidBundle validBundle = TestUtil.getMockAmexValidBundle(); + Touchpoint touchpoint = TestUtil.getMockTouchpoints(); + PaymentType paymentType = TestUtil.getMockPaymentType(); + + when(cosmosTemplate.find(any(CosmosQuery.class), any(), anyString())) + .thenReturn( + Collections.singleton(touchpoint), + Collections.singleton(paymentType), + Collections.singleton(validBundle)); + + var paymentOption = + TestUtil.readObjectFromFile("requests/getAmexFeesMulti.json", PaymentOptionMulti.class); + var result = calculatorService.calculateMulti(paymentOption, 10, true); + String actual = TestUtil.toJson(result); + + String expected = TestUtil.readStringFromFile("responses/getAmexFeesMulti.json"); + JSONAssert.assertEquals(expected, actual, JSONCompareMode.STRICT); + } } diff --git a/src/test/resources/requests/getAmexFeesMulti.json b/src/test/resources/requests/getAmexFeesMulti.json new file mode 100644 index 00000000..0f7a4083 --- /dev/null +++ b/src/test/resources/requests/getAmexFeesMulti.json @@ -0,0 +1,28 @@ +{ + "bin": "340000", + "paymentMethod": "CP", + "touchpoint": "CHECKOUT", + "idPspList": [], + "paymentNotice": [ + { + "primaryCreditorInstitution": "77777777777", + "paymentAmount": 30, + "transferList": [ + { + "creditorInstitution": "77777777777", + "transferCategory": "TAX1" + } + ] + }, + { + "primaryCreditorInstitution": "77777777778", + "paymentAmount": 40, + "transferList": [ + { + "creditorInstitution": "77777777778", + "transferCategory": "TAX2" + } + ] + } + ] +} diff --git a/src/test/resources/requests/getFeesMulti.json b/src/test/resources/requests/getFeesMulti.json index 85ff3800..2d68f7b4 100644 --- a/src/test/resources/requests/getFeesMulti.json +++ b/src/test/resources/requests/getFeesMulti.json @@ -15,12 +15,12 @@ ] }, { - "primaryCreditorInstitution": "88888888888", + "primaryCreditorInstitution": "77777777778", "paymentAmount": 40, "transferList": [ { - "creditorInstitution": "88888888888", - "transferCategory": "TAX1" + "creditorInstitution": "77777777778", + "transferCategory": "TAX2" } ] } diff --git a/src/test/resources/requests/getFeesMulti2.json b/src/test/resources/requests/getFeesMulti2.json new file mode 100644 index 00000000..592f0bcc --- /dev/null +++ b/src/test/resources/requests/getFeesMulti2.json @@ -0,0 +1,27 @@ +{ + "bin": "1005066", + "paymentMethod": "ANY", + "idPspList": [], + "paymentNotice": [ + { + "primaryCreditorInstitution": "77777777777", + "paymentAmount": 30, + "transferList": [ + { + "creditorInstitution": "77777777777", + "transferCategory": "TAX1" + } + ] + }, + { + "primaryCreditorInstitution": "77777777778", + "paymentAmount": 40, + "transferList": [ + { + "creditorInstitution": "77777777778", + "transferCategory": "TAX2" + } + ] + } + ] +} diff --git a/src/test/resources/requests/getFeesMultiBINwithMultipleABI.json b/src/test/resources/requests/getFeesMultiBINwithMultipleABI.json new file mode 100644 index 00000000..99eb322a --- /dev/null +++ b/src/test/resources/requests/getFeesMultiBINwithMultipleABI.json @@ -0,0 +1,28 @@ +{ + "bin": "504317", + "paymentMethod": "CP", + "touchpoint": "CHECKOUT", + "idPspList": [], + "paymentNotice": [ + { + "primaryCreditorInstitution": "77777777777", + "paymentAmount": 30, + "transferList": [ + { + "creditorInstitution": "77777777777", + "transferCategory": "TAX1" + } + ] + }, + { + "primaryCreditorInstitution": "88888888888", + "paymentAmount": 40, + "transferList": [ + { + "creditorInstitution": "88888888888", + "transferCategory": "TAX1" + } + ] + } + ] +} diff --git a/src/test/resources/requests/getFeesMultiDigitalStamp.json b/src/test/resources/requests/getFeesMultiDigitalStamp.json new file mode 100644 index 00000000..9029f219 --- /dev/null +++ b/src/test/resources/requests/getFeesMultiDigitalStamp.json @@ -0,0 +1,30 @@ +{ + "bin": "1005066", + "paymentMethod": "CP", + "touchpoint": "CHECKOUT", + "idPspList": [], + "paymentNotice": [ + { + "primaryCreditorInstitution": "77777777777", + "paymentAmount": 30, + "transferList": [ + { + "creditorInstitution": "77777777777", + "transferCategory": "TAX1", + "digitalStamp": true + } + ] + }, + { + "primaryCreditorInstitution": "77777777778", + "paymentAmount": 40, + "transferList": [ + { + "creditorInstitution": "77777777778", + "transferCategory": "TAX2", + "digitalStamp": true + } + ] + } + ] +} diff --git a/src/test/resources/requests/getFeesMultiDigitalStamp2.json b/src/test/resources/requests/getFeesMultiDigitalStamp2.json new file mode 100644 index 00000000..9029f219 --- /dev/null +++ b/src/test/resources/requests/getFeesMultiDigitalStamp2.json @@ -0,0 +1,30 @@ +{ + "bin": "1005066", + "paymentMethod": "CP", + "touchpoint": "CHECKOUT", + "idPspList": [], + "paymentNotice": [ + { + "primaryCreditorInstitution": "77777777777", + "paymentAmount": 30, + "transferList": [ + { + "creditorInstitution": "77777777777", + "transferCategory": "TAX1", + "digitalStamp": true + } + ] + }, + { + "primaryCreditorInstitution": "77777777778", + "paymentAmount": 40, + "transferList": [ + { + "creditorInstitution": "77777777778", + "transferCategory": "TAX2", + "digitalStamp": true + } + ] + } + ] +} diff --git a/src/test/resources/requests/getFeesMultiDigitalStamp3.json b/src/test/resources/requests/getFeesMultiDigitalStamp3.json new file mode 100644 index 00000000..3ae3f236 --- /dev/null +++ b/src/test/resources/requests/getFeesMultiDigitalStamp3.json @@ -0,0 +1,29 @@ +{ + "bin": "1005066", + "paymentMethod": "CP", + "touchpoint": "CHECKOUT", + "idPspList": [], + "paymentNotice": [ + { + "primaryCreditorInstitution": "77777777777", + "paymentAmount": 30, + "transferList": [ + { + "creditorInstitution": "77777777777", + "transferCategory": "TAX1", + "digitalStamp": true + } + ] + }, + { + "primaryCreditorInstitution": "77777777778", + "paymentAmount": 40, + "transferList": [ + { + "creditorInstitution": "77777777778", + "transferCategory": "TAX2" + } + ] + } + ] +} diff --git a/src/test/resources/requests/getFeesMultiSubThreshold.json b/src/test/resources/requests/getFeesMultiSubThreshold.json new file mode 100644 index 00000000..555fe711 --- /dev/null +++ b/src/test/resources/requests/getFeesMultiSubThreshold.json @@ -0,0 +1,28 @@ +{ + "bin": "1005066", + "paymentMethod": "CP", + "touchpoint": "CHECKOUT", + "idPspList": [], + "paymentNotice": [ + { + "primaryCreditorInstitution": "111111111111", + "paymentAmount": -3, + "transferList": [ + { + "creditorInstitution": "111111111111", + "transferCategory": "TAX1" + } + ] + }, + { + "primaryCreditorInstitution": "77777777778", + "paymentAmount": -2, + "transferList": [ + { + "creditorInstitution": "77777777778", + "transferCategory": "TAX2" + } + ] + } + ] +} diff --git a/src/test/resources/responses/getAmexFeesMulti.json b/src/test/resources/responses/getAmexFeesMulti.json new file mode 100644 index 00000000..c61bf33f --- /dev/null +++ b/src/test/resources/responses/getAmexFeesMulti.json @@ -0,0 +1,30 @@ +{ + "belowThreshold": false, + "bundleOptions": [ + { + "taxPayerFee": 1, + "actualPayerFee": 0, + "paymentMethod": "CP", + "touchpoint": "1", + "idBundle": "1", + "bundleName": "bundle1", + "bundleDescription": null, + "idsCiBundle": [ + "1" + ], + "idPsp": "AMEX", + "idChannel": "AMEX_ONUS", + "idBrokerPsp": null, + "onUs": true, + "abi": "AMREX", + "pspBusinessName": "psp business name amex", + "fees": [ + { + "creditorInstitution" : "77777777777", + "primaryCiIncurredFee": 10, + "actualCiIncurredFee": 1 + } + ] + } + ] +} diff --git a/src/test/resources/responses/getFeesMulti3.json b/src/test/resources/responses/getFeesMulti3.json new file mode 100644 index 00000000..b23b8623 --- /dev/null +++ b/src/test/resources/responses/getFeesMulti3.json @@ -0,0 +1,30 @@ +{ + "belowThreshold": false, + "bundleOptions": [ + { + "taxPayerFee": 1, + "actualPayerFee": 0, + "paymentMethod": "CP", + "touchpoint": "1", + "idBundle": "1", + "bundleName": "bundle1", + "bundleDescription": null, + "idsCiBundle": [ + "1" + ], + "idPsp": "77777777777", + "idChannel": "13212880150_07_ONUS", + "idBrokerPsp": null, + "onUs": true, + "abi": "14156", + "pspBusinessName": "psp business name 1", + "fees": [ + { + "creditorInstitution" : "77777777777", + "primaryCiIncurredFee": 10, + "actualCiIncurredFee": 1 + } + ] + } + ] +} diff --git a/src/test/resources/responses/getFeesMultiPaymentTypeNull.json b/src/test/resources/responses/getFeesMultiPaymentTypeNull.json new file mode 100644 index 00000000..aecb5c63 --- /dev/null +++ b/src/test/resources/responses/getFeesMultiPaymentTypeNull.json @@ -0,0 +1,30 @@ +{ + "belowThreshold": false, + "bundleOptions": [ + { + "taxPayerFee": 1, + "actualPayerFee": 0, + "paymentMethod": "ANY", + "touchpoint": "1", + "idBundle": "1", + "bundleName": "bundle1", + "bundleDescription": null, + "idsCiBundle": [ + "1" + ], + "idPsp": "ABC", + "idChannel": "13212880150_07_ONUS", + "idBrokerPsp": null, + "onUs": false, + "abi": "14156", + "pspBusinessName": "psp business name 1", + "fees": [ + { + "creditorInstitution" : "77777777777", + "primaryCiIncurredFee": 10, + "actualCiIncurredFee": 1 + } + ] + } + ] +} diff --git a/src/test/resources/responses/getFeesMultiSubThreshold.json b/src/test/resources/responses/getFeesMultiSubThreshold.json new file mode 100644 index 00000000..a55a792b --- /dev/null +++ b/src/test/resources/responses/getFeesMultiSubThreshold.json @@ -0,0 +1,22 @@ +{ + "belowThreshold": true, + "bundleOptions": [ + { + "taxPayerFee": -5, + "actualPayerFee": 0, + "paymentMethod": "CP", + "touchpoint": "1", + "idBundle": "1", + "bundleName": "bundle1", + "bundleDescription": null, + "idsCiBundle": [], + "idPsp": "111111111111", + "idChannel": "13212880150_07_ONUS", + "idBrokerPsp": null, + "onUs": false, + "abi": "14156", + "pspBusinessName": "psp business name 1", + "fees": [] + } + ] +} From af4cf267e01e90e1f1ba88fcd8a8442f0ed8ca19 Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Thu, 22 Feb 2024 14:13:35 +0100 Subject: [PATCH 24/30] PAGOPA-1492 trying to solve duplication --- .../repository/CosmosRepository.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java b/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java index 0ca2b720..f8acdbab 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java @@ -73,21 +73,21 @@ public List findByPaymentOption(PaymentOptionMulti paymentOption, b /** * Null value are ignored -> they are skipped when building the filters * - * @param paymentOption Get the Body of the Request + * @param paymentOptionMulti Get the Body of the Request * @return the filtered bundles */ - private Iterable findValidBundlesMulti(PaymentOptionMulti paymentOption, boolean allCcp) { + private Iterable findValidBundlesMulti(PaymentOptionMulti paymentOptionMulti, boolean allCcp) { // add filter by Payment Amount: minPaymentAmount <= paymentAmount < maxPaymentAmount var minFilter = - CriteriaBuilder.lessThan("minPaymentAmount", paymentOption.getPaymentAmount()); + CriteriaBuilder.lessThan("minPaymentAmount", paymentOptionMulti.getPaymentAmount()); var maxFilter = - CriteriaBuilder.greaterThanEqual("maxPaymentAmount", paymentOption.getPaymentAmount()); + CriteriaBuilder.greaterThanEqual("maxPaymentAmount", paymentOptionMulti.getPaymentAmount()); var queryResult = and(minFilter, maxFilter); // add filter by Touch Point: touchpoint= || touchpoint==null - if (paymentOption.getTouchpoint() != null - && !paymentOption.getTouchpoint().equalsIgnoreCase("any")) { - var touchpointNameFilter = isEqualOrAny("name", paymentOption.getTouchpoint()); + if (paymentOptionMulti.getTouchpoint() != null + && !paymentOptionMulti.getTouchpoint().equalsIgnoreCase("any")) { + var touchpointNameFilter = isEqualOrAny("name", paymentOptionMulti.getTouchpoint()); Iterable touchpoint = cosmosTemplate.find( new CosmosQuery(touchpointNameFilter), Touchpoint.class, "touchpoints"); @@ -96,7 +96,7 @@ private Iterable findValidBundlesMulti(PaymentOptionMulti paymentOp throw new AppException( HttpStatus.NOT_FOUND, "Touchpoint not found", - "Cannot find touchpont with name: '" + paymentOption.getTouchpoint() + "'"); + "Cannot find touchpont with name: '" + paymentOptionMulti.getTouchpoint() + "'"); } var touchpointFilter = isEqualOrAny("touchpoint", touchpoint.iterator().next().getName()); @@ -104,9 +104,9 @@ private Iterable findValidBundlesMulti(PaymentOptionMulti paymentOp } // add filter by Payment Method: paymentMethod= || paymentMethod==null - if (paymentOption.getPaymentMethod() != null - && !paymentOption.getPaymentMethod().equalsIgnoreCase("any")) { - var paymentTypeNameFilter = isEqualOrNull("name", paymentOption.getPaymentMethod()); + if (paymentOptionMulti.getPaymentMethod() != null + && !paymentOptionMulti.getPaymentMethod().equalsIgnoreCase("any")) { + var paymentTypeNameFilter = isEqualOrNull("name", paymentOptionMulti.getPaymentMethod()); Iterable paymentType = cosmosTemplate.find( new CosmosQuery(paymentTypeNameFilter), PaymentType.class, "paymenttypes"); @@ -115,7 +115,7 @@ private Iterable findValidBundlesMulti(PaymentOptionMulti paymentOp throw new AppException( HttpStatus.NOT_FOUND, "PaymentType not found", - "Cannot find payment type with name: '" + paymentOption.getPaymentMethod() + "'"); + "Cannot find payment type with name: '" + paymentOptionMulti.getPaymentMethod() + "'"); } var paymentTypeFilter = isEqualOrNull("paymentType", paymentType.iterator().next().getName()); @@ -124,7 +124,7 @@ private Iterable findValidBundlesMulti(PaymentOptionMulti paymentOp // add filter by PSP: psp in list Iterator iterator = - Optional.ofNullable(paymentOption.getIdPspList()) + Optional.ofNullable(paymentOptionMulti.getIdPspList()) .orElse(Collections.emptyList()) .iterator(); if (iterator.hasNext()) { @@ -132,7 +132,7 @@ private Iterable findValidBundlesMulti(PaymentOptionMulti paymentOp } // add filter by Transfer Category: transferCategory[] contains one of paymentOption - List categoryList = utilityComponent.getTransferCategoryList(paymentOption); + List categoryList = utilityComponent.getTransferCategoryList(paymentOptionMulti); if (categoryList != null) { var taxonomyFilter = categoryList.parallelStream() From b7233e0dfa7e5916d22d5a28c069134f9f8a7ec1 Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Thu, 22 Feb 2024 14:21:40 +0100 Subject: [PATCH 25/30] PAGOPA-1492 trying to solve duplication 2 --- .../pagopa/afm/calculator/repository/CosmosRepository.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java b/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java index f8acdbab..16c915aa 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java @@ -132,10 +132,10 @@ private Iterable findValidBundlesMulti(PaymentOptionMulti paymentOp } // add filter by Transfer Category: transferCategory[] contains one of paymentOption - List categoryList = utilityComponent.getTransferCategoryList(paymentOptionMulti); - if (categoryList != null) { + List categoryListMulti = utilityComponent.getTransferCategoryList(paymentOptionMulti); + if (categoryListMulti != null) { var taxonomyFilter = - categoryList.parallelStream() + categoryListMulti.parallelStream() .filter(Objects::nonNull) .filter(elem -> !elem.isEmpty()) .map(elem -> arrayContains("transferCategoryList", elem)) From 18dc50c06e6815489f36f1c7225e3977d0586fc4 Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Thu, 22 Feb 2024 15:16:28 +0100 Subject: [PATCH 26/30] PAGOPA-1492 adding test for partial commission --- .../gov/pagopa/afm/calculator/TestUtil.java | 22 ++++++++++++++ .../service/CalculatorServiceTest.java | 22 ++++++++++++++ .../responses/getFeesMultiHighCommission.json | 30 +++++++++++++++++++ 3 files changed, 74 insertions(+) create mode 100644 src/test/resources/responses/getFeesMultiHighCommission.json diff --git a/src/test/java/it/gov/pagopa/afm/calculator/TestUtil.java b/src/test/java/it/gov/pagopa/afm/calculator/TestUtil.java index 11bfcc23..e9169778 100644 --- a/src/test/java/it/gov/pagopa/afm/calculator/TestUtil.java +++ b/src/test/java/it/gov/pagopa/afm/calculator/TestUtil.java @@ -123,6 +123,28 @@ public static ValidBundle getMockAmexValidBundle() { .build(); } + public static ValidBundle getHighCommissionValidBundle() { + return ValidBundle.builder() + .id("1") + .idChannel("13212880150_07_ONUS") + .name("bundle1") + .idPsp("ABC") + .abi("14156") + .pspBusinessName("psp business name 1") + .paymentAmount(50L) + .minPaymentAmount(0L) + .maxPaymentAmount(1000L) + .type(BundleType.PUBLIC) + .touchpoint("1") + .paymentType("CP") + .transferCategoryList(List.of("TAX1")) + .ciBundleList(Collections.singletonList(getMockCiBundle())) + .digitalStamp(false) + .digitalStampRestriction(false) + .onUs(true) + .build(); + } + public static List getMockMultipleValidBundle() { List bundles = new ArrayList<>(); bundles.add( diff --git a/src/test/java/it/gov/pagopa/afm/calculator/service/CalculatorServiceTest.java b/src/test/java/it/gov/pagopa/afm/calculator/service/CalculatorServiceTest.java index cb3814ab..f3fc2887 100644 --- a/src/test/java/it/gov/pagopa/afm/calculator/service/CalculatorServiceTest.java +++ b/src/test/java/it/gov/pagopa/afm/calculator/service/CalculatorServiceTest.java @@ -726,4 +726,26 @@ void calculateMulti_amexPayment() throws IOException, JSONException { String expected = TestUtil.readStringFromFile("responses/getAmexFeesMulti.json"); JSONAssert.assertEquals(expected, actual, JSONCompareMode.STRICT); } + + @Test + @Order(25) + void calculateMultiHighCommission() throws IOException, JSONException { + ValidBundle validBundle = TestUtil.getHighCommissionValidBundle(); + Touchpoint touchpoint = TestUtil.getMockTouchpoints(); + PaymentType paymentType = TestUtil.getMockPaymentType(); + + when(cosmosTemplate.find(any(CosmosQuery.class), any(), anyString())) + .thenReturn( + Collections.singleton(touchpoint), + Collections.singleton(paymentType), + Collections.singleton(validBundle)); + + var paymentOption = + TestUtil.readObjectFromFile("requests/getFeesMulti.json", PaymentOptionMulti.class); + var result = calculatorService.calculateMulti(paymentOption, 10, true); + String actual = TestUtil.toJson(result); + + String expected = TestUtil.readStringFromFile("responses/getFeesMultiHighCommission.json"); + JSONAssert.assertEquals(expected, actual, JSONCompareMode.STRICT); + } } diff --git a/src/test/resources/responses/getFeesMultiHighCommission.json b/src/test/resources/responses/getFeesMultiHighCommission.json new file mode 100644 index 00000000..d82882a8 --- /dev/null +++ b/src/test/resources/responses/getFeesMultiHighCommission.json @@ -0,0 +1,30 @@ +{ + "belowThreshold": false, + "bundleOptions": [ + { + "taxPayerFee": 50, + "actualPayerFee": 40, + "paymentMethod": "CP", + "touchpoint": "1", + "idBundle": "1", + "bundleName": "bundle1", + "bundleDescription": null, + "idsCiBundle": [ + "1" + ], + "idPsp": "ABC", + "idChannel": "13212880150_07_ONUS", + "idBrokerPsp": null, + "onUs": true, + "abi": "14156", + "pspBusinessName": "psp business name 1", + "fees": [ + { + "creditorInstitution" : "77777777777", + "primaryCiIncurredFee": 10, + "actualCiIncurredFee": 10 + } + ] + } + ] +} From 50caf8003f7e6f955d039ba44ec031729484416d Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Fri, 23 Feb 2024 11:12:58 +0100 Subject: [PATCH 27/30] PAGOPA-1492 fixing regex and toList issue --- .../controller/CalculatorController.java | 4 +-- .../BundleOption.java | 2 +- .../Fee.java | 2 +- .../Transfer.java | 2 +- .../repository/CosmosRepository.java | 7 ++--- .../calculator/service/CalculatorService.java | 30 +++++++++---------- .../controller/CalculatorControllerTest.java | 4 +-- .../service/CalculatorServiceTest.java | 2 +- 8 files changed, 26 insertions(+), 27 deletions(-) rename src/main/java/it/gov/pagopa/afm/calculator/model/{calculatorMulti => calculatormulti}/BundleOption.java (91%) rename src/main/java/it/gov/pagopa/afm/calculator/model/{calculatorMulti => calculatormulti}/Fee.java (86%) rename src/main/java/it/gov/pagopa/afm/calculator/model/{calculatorMulti => calculatormulti}/Transfer.java (94%) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/controller/CalculatorController.java b/src/main/java/it/gov/pagopa/afm/calculator/controller/CalculatorController.java index ab66f8fb..d35127ab 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/controller/CalculatorController.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/controller/CalculatorController.java @@ -236,7 +236,7 @@ public BundleOption getFees( @PostMapping( value = "/psps/{idPsp}/fees/multi", produces = {MediaType.APPLICATION_JSON_VALUE}) - public it.gov.pagopa.afm.calculator.model.calculatorMulti.BundleOption getFeesByPspMulti( + public it.gov.pagopa.afm.calculator.model.calculatormulti.BundleOption getFeesByPspMulti( @Parameter(description = "PSP identifier", required = true) @PathVariable("idPsp") String idPsp, @RequestBody @Valid PaymentOptionByPspMulti paymentOptionByPsp, @@ -318,7 +318,7 @@ public it.gov.pagopa.afm.calculator.model.calculatorMulti.BundleOption getFeesBy @PostMapping( value = "/fees/multi", produces = {MediaType.APPLICATION_JSON_VALUE}) - public it.gov.pagopa.afm.calculator.model.calculatorMulti.BundleOption getFeesMulti( + public it.gov.pagopa.afm.calculator.model.calculatormulti.BundleOption getFeesMulti( @RequestBody @Valid PaymentOptionMulti paymentOption, @RequestParam(required = false, defaultValue = "10") Integer maxOccurrences, @RequestParam(required = false, defaultValue = "true") diff --git a/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/BundleOption.java b/src/main/java/it/gov/pagopa/afm/calculator/model/calculatormulti/BundleOption.java similarity index 91% rename from src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/BundleOption.java rename to src/main/java/it/gov/pagopa/afm/calculator/model/calculatormulti/BundleOption.java index 36799da9..07503cd2 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/BundleOption.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/model/calculatormulti/BundleOption.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.afm.calculator.model.calculatorMulti; +package it.gov.pagopa.afm.calculator.model.calculatormulti; import io.swagger.v3.oas.annotations.media.Schema; import java.io.Serializable; diff --git a/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Fee.java b/src/main/java/it/gov/pagopa/afm/calculator/model/calculatormulti/Fee.java similarity index 86% rename from src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Fee.java rename to src/main/java/it/gov/pagopa/afm/calculator/model/calculatormulti/Fee.java index f338d107..6c7bbb5b 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Fee.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/model/calculatormulti/Fee.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.afm.calculator.model.calculatorMulti; +package it.gov.pagopa.afm.calculator.model.calculatormulti; import lombok.*; import java.io.Serializable; diff --git a/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Transfer.java b/src/main/java/it/gov/pagopa/afm/calculator/model/calculatormulti/Transfer.java similarity index 94% rename from src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Transfer.java rename to src/main/java/it/gov/pagopa/afm/calculator/model/calculatormulti/Transfer.java index 7da1068f..4970e314 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/model/calculatorMulti/Transfer.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/model/calculatormulti/Transfer.java @@ -1,4 +1,4 @@ -package it.gov.pagopa.afm.calculator.model.calculatorMulti; +package it.gov.pagopa.afm.calculator.model.calculatormulti; import lombok.*; import javax.validation.Valid; diff --git a/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java b/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java index 16c915aa..d6a4f3ac 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java @@ -24,7 +24,6 @@ import org.springframework.util.CollectionUtils; import java.util.*; -import java.util.stream.Collectors; import java.util.stream.StreamSupport; import static it.gov.pagopa.afm.calculator.service.UtilityComponent.isGlobal; @@ -54,7 +53,7 @@ private static List filterByCI(String ciFiscalCode, ValidBundle bundle return bundle.getCiBundleList() != null ? bundle.getCiBundleList().parallelStream() .filter(ciBundle -> ciFiscalCode.equals(ciBundle.getCiFiscalCode())) - .collect(Collectors.toList()) + .toList() : null; } @@ -281,7 +280,7 @@ private List getFilteredBundlesMulti( .filter(bundle -> digitalStampFilter(transferListSize, onlyMarcaBolloDigitale, bundle)) // Gets the GLOBAL bundles and PRIVATE|PUBLIC bundles of the CI .filter(bundle -> globalAndRelatedFilter(paymentOptionMulti, bundle)) - .collect(Collectors.toList()); + .toList(); } /** @@ -304,7 +303,7 @@ private List getFilteredBundles( .filter(bundle -> digitalStampFilter(transferListSize, onlyMarcaBolloDigitale, bundle)) // Gets the GLOBAL bundles and PRIVATE|PUBLIC bundles of the CI .filter(bundle -> globalAndRelatedFilter(paymentOption, bundle)) - .collect(Collectors.toList()); + .toList(); } /** diff --git a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java index fdd25985..40ff1576 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java @@ -11,7 +11,7 @@ import it.gov.pagopa.afm.calculator.model.TransferCategoryRelation; import it.gov.pagopa.afm.calculator.model.calculator.BundleOption; import it.gov.pagopa.afm.calculator.model.calculator.Transfer; -import it.gov.pagopa.afm.calculator.model.calculatorMulti.Fee; +import it.gov.pagopa.afm.calculator.model.calculatormulti.Fee; import it.gov.pagopa.afm.calculator.repository.CosmosRepository; import lombok.Setter; import org.apache.commons.lang3.SerializationUtils; @@ -64,11 +64,11 @@ public BundleOption calculate(@Valid PaymentOption paymentOption, int limit, boo .build(); } - public it.gov.pagopa.afm.calculator.model.calculatorMulti.BundleOption calculateMulti(@Valid PaymentOptionMulti paymentOption, int limit, boolean allCcp) { + public it.gov.pagopa.afm.calculator.model.calculatormulti.BundleOption calculateMulti(@Valid PaymentOptionMulti paymentOption, int limit, boolean allCcp) { List filteredBundles = cosmosRepository.findByPaymentOption(paymentOption, allCcp); Collections.shuffle(filteredBundles); - return it.gov.pagopa.afm.calculator.model.calculatorMulti.BundleOption.builder() + return it.gov.pagopa.afm.calculator.model.calculatormulti.BundleOption.builder() .belowThreshold(isBelowThreshold(paymentOption.getPaymentAmount())) .bundleOptions(calculateTaxPayerFeeMulti(paymentOption, limit, filteredBundles)) .build(); @@ -135,10 +135,10 @@ private List calculateTaxPayerFee( return transfers.stream().limit(limit).collect(Collectors.toList()); } - private List calculateTaxPayerFeeMulti( + private List calculateTaxPayerFeeMulti( PaymentOptionMulti paymentOption, int limit, List bundles) { - List transfers = new ArrayList<>(); + List transfers = new ArrayList<>(); // 1. Check if ONUS payment: // - ONUS payment = if the bundle ABI attribute matching the one extracted via BIN from the @@ -179,8 +179,8 @@ private List calcul // if it is a payment on the AMEX circuit --> filter to return only AMEX_ONUS if (this.isAMEXAbi(issuers)) { - Predicate abiPredicate = t -> amexABI.equalsIgnoreCase(t.getAbi()); - Predicate onusPredicate = t -> Boolean.TRUE.equals(t.getOnUs()); + Predicate abiPredicate = t -> amexABI.equalsIgnoreCase(t.getAbi()); + Predicate onusPredicate = t -> Boolean.TRUE.equals(t.getOnUs()); transfers = transfers.stream().filter(abiPredicate.and(onusPredicate)).collect(Collectors.toList()); } @@ -225,9 +225,9 @@ private List getTransferList( return transfers; } - private List getTransferList( + private List getTransferList( PaymentOptionMulti paymentOption, ValidBundle bundle) { - List transfers = new ArrayList<>(); + List transfers = new ArrayList<>(); if(bundle.getCiBundleList().isEmpty()) { transfers.add(createTransfer(bundle, paymentOption, new ArrayList<>(), new ArrayList<>())); return transfers; @@ -321,7 +321,7 @@ private void analyzeTransferList( .map( attribute -> createTransfer(bundle.getPaymentAmount(), 0, bundle, null, paymentOption)) - .collect(Collectors.toList())); + .toList()); transfers.addAll( cibundle .getAttributes() @@ -354,7 +354,7 @@ private void analyzeTransferList( cibundle.getId(), paymentOption); }) - .collect(Collectors.toList())); + .toList()); } else { transfers.add( createTransfer(bundle.getPaymentAmount(), 0, bundle, cibundle.getId(), paymentOption)); @@ -399,7 +399,7 @@ private List analyzeFee( attribute.getTransferCategory()))))) .map( attribute -> createFee(attribute.getMaxPaymentAmount(), cibundle.getCiFiscalCode())) - .collect(Collectors.toList())); + .toList()); } } return fees; @@ -425,13 +425,13 @@ private Fee createFee( * @param fees the fees to include in the transfer * @return Create transfer item */ - private it.gov.pagopa.afm.calculator.model.calculatorMulti.Transfer createTransfer( + private it.gov.pagopa.afm.calculator.model.calculatormulti.Transfer createTransfer( ValidBundle bundle, PaymentOptionMulti paymentOption, List fees, List idsCiBundles) { long actualPayerFee = bundle.getPaymentAmount() - fees.stream().mapToLong(Fee::getActualCiIncurredFee).sum(); - return it.gov.pagopa.afm.calculator.model.calculatorMulti.Transfer.builder() + return it.gov.pagopa.afm.calculator.model.calculatormulti.Transfer.builder() .taxPayerFee(bundle.getPaymentAmount()) .actualPayerFee(Math.max(0, actualPayerFee)) .paymentMethod(bundle.getPaymentType() == null ? "ANY" : bundle.getPaymentType()) @@ -537,7 +537,7 @@ private static void sortByFeePerPsp(List transfers) { * * @param transfers list of transfers to sort */ - private static void sortByFeePerPspMulti(List transfers) { + private static void sortByFeePerPspMulti(List transfers) { transfers.sort( (t1, t2) -> { int primarySort = t1.getIdPsp().compareTo(t2.getIdPsp()); diff --git a/src/test/java/it/gov/pagopa/afm/calculator/controller/CalculatorControllerTest.java b/src/test/java/it/gov/pagopa/afm/calculator/controller/CalculatorControllerTest.java index 1e97e2d3..a891bf12 100644 --- a/src/test/java/it/gov/pagopa/afm/calculator/controller/CalculatorControllerTest.java +++ b/src/test/java/it/gov/pagopa/afm/calculator/controller/CalculatorControllerTest.java @@ -35,8 +35,8 @@ class CalculatorControllerTest { @BeforeEach void setup() throws IOException { BundleOption result = TestUtil.readObjectFromFile("responses/getFees.json", BundleOption.class); - it.gov.pagopa.afm.calculator.model.calculatorMulti.BundleOption resultMulti = - TestUtil.readObjectFromFile("responses/getFeesMulti.json", it.gov.pagopa.afm.calculator.model.calculatorMulti.BundleOption.class); + it.gov.pagopa.afm.calculator.model.calculatormulti.BundleOption resultMulti = + TestUtil.readObjectFromFile("responses/getFeesMulti.json", it.gov.pagopa.afm.calculator.model.calculatormulti.BundleOption.class); when(calculatorService.calculate(any(), anyInt(), any(Boolean.class))).thenReturn(result); when(calculatorService.calculateMulti(any(), anyInt(), any(Boolean.class))).thenReturn(resultMulti); } diff --git a/src/test/java/it/gov/pagopa/afm/calculator/service/CalculatorServiceTest.java b/src/test/java/it/gov/pagopa/afm/calculator/service/CalculatorServiceTest.java index f3fc2887..670b08b4 100644 --- a/src/test/java/it/gov/pagopa/afm/calculator/service/CalculatorServiceTest.java +++ b/src/test/java/it/gov/pagopa/afm/calculator/service/CalculatorServiceTest.java @@ -700,7 +700,7 @@ void calculateMulti_allCcpFlagDown() throws IOException, JSONException { Collections.singleton(TestUtil.getMockValidBundle())); var paymentOption = TestUtil.readObjectFromFile("requests/getFeesMulti.json", PaymentOptionMulti.class); - it.gov.pagopa.afm.calculator.model.calculatorMulti.BundleOption result = + it.gov.pagopa.afm.calculator.model.calculatormulti.BundleOption result = calculatorService.calculateMulti(paymentOption, 10, false); assertEquals(1, result.getBundleOptions().size()); } From ff0db55dc5020122a878a55d51f5eac825f0123e Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Fri, 23 Feb 2024 11:15:27 +0100 Subject: [PATCH 28/30] PAGOPA-1492 solving string issue --- .../afm/calculator/repository/CosmosRepository.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java b/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java index d6a4f3ac..cee47f9d 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/repository/CosmosRepository.java @@ -44,6 +44,8 @@ public class CosmosRepository { private static final String ID_PSP_PARAM = "idPsp"; + private static final String TRANSFER_CATEGORY_LIST = "transferCategoryList"; + /** * @param ciFiscalCode fiscal code of the CI * @param bundle a valid bundle @@ -137,11 +139,11 @@ private Iterable findValidBundlesMulti(PaymentOptionMulti paymentOp categoryListMulti.parallelStream() .filter(Objects::nonNull) .filter(elem -> !elem.isEmpty()) - .map(elem -> arrayContains("transferCategoryList", elem)) + .map(elem -> arrayContains(TRANSFER_CATEGORY_LIST, elem)) .reduce(CriteriaBuilder::or); if (taxonomyFilter.isPresent()) { - var taxonomyOrNull = or(taxonomyFilter.get(), isNull("transferCategoryList")); + var taxonomyOrNull = or(taxonomyFilter.get(), isNull(TRANSFER_CATEGORY_LIST)); queryResult = and(queryResult, taxonomyOrNull); } } @@ -231,11 +233,11 @@ private Iterable findValidBundles(PaymentOption paymentOption, bool categoryList.parallelStream() .filter(Objects::nonNull) .filter(elem -> !elem.isEmpty()) - .map(elem -> arrayContains("transferCategoryList", elem)) + .map(elem -> arrayContains(TRANSFER_CATEGORY_LIST, elem)) .reduce(CriteriaBuilder::or); if (taxonomyFilter.isPresent()) { - var taxonomyOrNull = or(taxonomyFilter.get(), isNull("transferCategoryList")); + var taxonomyOrNull = or(taxonomyFilter.get(), isNull(TRANSFER_CATEGORY_LIST)); queryResult = and(queryResult, taxonomyOrNull); } } From 4f79666f260b89c540ef5c7ac8011f81d9ab0696 Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Fri, 23 Feb 2024 11:18:35 +0100 Subject: [PATCH 29/30] PAGOPA-1492 fixing toList issue --- .../gov/pagopa/afm/calculator/service/CalculatorService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java index 40ff1576..9369beba 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/service/CalculatorService.java @@ -190,7 +190,7 @@ private List calcul sortByFeePerPspMulti(transfers); - return transfers.stream().limit(limit).collect(Collectors.toList()); + return transfers.stream().limit(limit).toList(); } private boolean isOnusBundle(ValidBundle bundle) { @@ -272,7 +272,7 @@ private void orderFee (long paymentAmount, List fees) { } private List> getCartesianProduct(List> sets) { - return cartesianProduct(sets,0).collect(Collectors.toList()); + return cartesianProduct(sets,0).toList(); } private Stream> cartesianProduct(List> sets, int index) { From db5c53dadd6cb1794b48a5b84f5074df07ccd0cb Mon Sep 17 00:00:00 2001 From: FedericoRuzzier <49512050+FedericoRuzzier@users.noreply.github.com> Date: Fri, 23 Feb 2024 11:22:57 +0100 Subject: [PATCH 30/30] PAGOPA-1492 fix cacheable string --- .../it/gov/pagopa/afm/calculator/service/UtilityComponent.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/it/gov/pagopa/afm/calculator/service/UtilityComponent.java b/src/main/java/it/gov/pagopa/afm/calculator/service/UtilityComponent.java index c863643a..d628fa2d 100644 --- a/src/main/java/it/gov/pagopa/afm/calculator/service/UtilityComponent.java +++ b/src/main/java/it/gov/pagopa/afm/calculator/service/UtilityComponent.java @@ -64,7 +64,7 @@ public List getTransferCategoryList(PaymentOption paymentOption) { * @param paymentOptionMulti request * @return list of string about transfer categories */ - @Cacheable(value = "getTransferCategoryList") + @Cacheable(value = "getTransferCategoryListMulti") public List getTransferCategoryList(PaymentOptionMulti paymentOptionMulti) { List transferList = new ArrayList<>(); paymentOptionMulti.getPaymentNotice().forEach(paymentNoticeItem -> transferList.addAll(paymentNoticeItem.getTransferList()));