Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,10 @@
import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionStatus;
import it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentStatus;
import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus;
import it.gov.pagopa.pu.debtpositions.model.DebtPosition;
import it.gov.pagopa.pu.debtpositions.model.InstallmentNoPII;
import it.gov.pagopa.pu.debtpositions.model.PaymentOption;
import it.gov.pagopa.pu.debtpositions.model.Transfer;
import it.gov.pagopa.pu.debtpositions.exception.custom.NotFoundException;
import it.gov.pagopa.pu.debtpositions.model.*;
import it.gov.pagopa.pu.debtpositions.repository.DebtPositionTypeOrgRepository;
import it.gov.pagopa.pu.debtpositions.service.BalanceResolverService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.List;
Expand All @@ -20,10 +18,12 @@
@Service
public class TechnicalMixedDebtPositionMapper {

private final DebtPositionTypeOrgRepository debtPositionTypeOrgRepository;
private final BalanceResolverService balanceResolverService;

public TechnicalMixedDebtPositionMapper(BalanceResolverService balanceResolverService) {
public TechnicalMixedDebtPositionMapper(BalanceResolverService balanceResolverService, DebtPositionTypeOrgRepository debtPositionTypeOrgRepository) {
this.balanceResolverService = balanceResolverService;
this.debtPositionTypeOrgRepository = debtPositionTypeOrgRepository;
}

public DebtPosition toTechnicalMixedDebtPosition(DebtPosition debtPosition,
Expand All @@ -47,14 +47,15 @@ public DebtPosition toTechnicalMixedDebtPosition(DebtPosition debtPosition,
debtPosition.isFlagPuPagoPaPayment());
technicalMixedDp.setPaymentOptions(
toTechnicalMixedDPPaymentOptions(
debtPosition, isUnpayable, mixedDpAdditionalDataList, accessToken));
debtPosition, isUnpayable, mixedDpAdditionalDataList, debtPositionTypeOrgId, accessToken));

return technicalMixedDp;
}

private SortedSet<PaymentOption> toTechnicalMixedDPPaymentOptions(
DebtPosition debtPosition, boolean isUnpayable,
List<MixedDpAdditionalData> mixedDpAdditionalDataList, String accessToken) {
List<MixedDpAdditionalData> mixedDpAdditionalDataList,
Long debtPositionTypeOrgId, String accessToken) {
SortedSet<PaymentOption> set = new TreeSet<>();

for (PaymentOption paymentOption : debtPosition.getPaymentOptions()) {
Expand All @@ -72,7 +73,7 @@ private SortedSet<PaymentOption> toTechnicalMixedDPPaymentOptions(
technicalMixedDpPaymentOption.setInstallments(
toTechnicalMixedDPInstallments(debtPosition.getOrganizationId(),
paymentOption.getInstallments(),
isUnpayable, mixedDpAdditionalDataList, accessToken));
isUnpayable, mixedDpAdditionalDataList, debtPositionTypeOrgId, accessToken));

set.add(technicalMixedDpPaymentOption);
}
Expand All @@ -82,7 +83,8 @@ private SortedSet<PaymentOption> toTechnicalMixedDPPaymentOptions(

private SortedSet<InstallmentNoPII> toTechnicalMixedDPInstallments(
Long organizationId, SortedSet<InstallmentNoPII> installments, boolean isUnpayable,
List<MixedDpAdditionalData> mixedDpAdditionalDataList, String accessToken) {
List<MixedDpAdditionalData> mixedDpAdditionalDataList,
Long debtPositionTypeOrgId, String accessToken) {
SortedSet<InstallmentNoPII> set = new TreeSet<>();

installments.forEach(installment ->
Expand Down Expand Up @@ -142,9 +144,10 @@ private SortedSet<InstallmentNoPII> toTechnicalMixedDPInstallments(
technicalMixedDpInstallment.setTransfers(
toTechnicalMixedDPTransfers(transfer));

if (!isUnpayable && StringUtils.isNotBlank(mixedDpAdditionalData.getBalance())) {
String balanceResolved = balanceResolverService.resolveAmountBalance(organizationId, technicalMixedDpInstallment, accessToken);
technicalMixedDpInstallment.setBalance(balanceResolved);
if (!isUnpayable) {
DebtPositionTypeOrg debtPositionTypeOrg = debtPositionTypeOrgRepository.findById(debtPositionTypeOrgId)
.orElseThrow(() -> new NotFoundException("The DebtPositionTypeOrg with id " + debtPositionTypeOrgId + " was not found"));
balanceResolverService.updateBalanceResolvingAmount(technicalMixedDpInstallment, organizationId, debtPositionTypeOrg, accessToken);
}
set.add(technicalMixedDpInstallment);
}));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,38 +16,50 @@
@Slf4j
public class BalanceResolverService {

private final BalanceService balanceService;
private final OrganizationService organizationService;
private final BalanceService balanceService;
private final OrganizationService organizationService;

public BalanceResolverService(BalanceService balanceService, OrganizationService organizationService) {
this.balanceService = balanceService;
this.organizationService = organizationService;
public BalanceResolverService(BalanceService balanceService, OrganizationService organizationService) {
this.balanceService = balanceService;
this.organizationService = organizationService;
}

public String getBalanceDefault(Long organizationId, DebtPositionTypeOrg debtPositionTypeOrg, String accessToken) {
log.info("Retrieving balance from DebtPositionTypeOrg with orgId[{}] and debtPositionTypeCode[{}]", organizationId, debtPositionTypeOrg.getCode());

if (StringUtils.isNotBlank(debtPositionTypeOrg.getBalance())) {
return debtPositionTypeOrg.getBalance();
}

public String getBalanceDefault(Long organizationId, DebtPositionTypeOrg debtPositionTypeOrg, String accessToken) {
log.info("Retrieving balance from DebtPositionTypeOrg with orgId[{}] and debtPositionTypeCode[{}]", organizationId, debtPositionTypeOrg.getCode());
return balanceService.getBalanceByAssessmentRegistry(organizationId, debtPositionTypeOrg.getCode(), accessToken);
}

if (StringUtils.isNotBlank(debtPositionTypeOrg.getBalance())) {
return debtPositionTypeOrg.getBalance();
}
public String resolveAmountBalance(Long organizationId, InstallmentNoPII installment, String accessToken) {
Organization org = organizationService.getOrganizationById(organizationId, accessToken)
.orElseThrow(() -> new NotFoundException("Organization with id " + organizationId + " not found"));

return balanceService.getBalanceByAssessmentRegistry(organizationId, debtPositionTypeOrg.getCode(), accessToken);
}
Long totalAmountCentsPrimaryOrg = installment.getTransfers().stream()
.filter(transfer -> transfer.getOrgFiscalCode().equals(org.getOrgFiscalCode()))
.mapToLong(Transfer::getAmountCents).sum();

public String resolveAmountBalance(Long organizationId, InstallmentNoPII installment, String accessToken){
Organization org = organizationService.getOrganizationById(organizationId, accessToken)
.orElseThrow(() -> new NotFoundException("Organization with id " + organizationId + " not found"));
CalculateAmountBalanceRequest amountBalanceRequest = CalculateAmountBalanceRequest.builder()
.balance(installment.getBalance())
.amountCents(totalAmountCentsPrimaryOrg)
.remittanceInformation(installment.getRemittanceInformation())
.build();

Long totalAmountCentsPrimaryOrg = installment.getTransfers().stream()
.filter(transfer -> transfer.getOrgFiscalCode().equals(org.getOrgFiscalCode()))
.mapToLong(Transfer::getAmountCents).sum();
return balanceService.calculateAmountBalance(amountBalanceRequest, accessToken);
}

CalculateAmountBalanceRequest amountBalanceRequest = CalculateAmountBalanceRequest.builder()
.balance(installment.getBalance())
.amountCents(totalAmountCentsPrimaryOrg)
.remittanceInformation(installment.getRemittanceInformation())
.build();
public void updateBalanceResolvingAmount(InstallmentNoPII installment, Long organizationId, DebtPositionTypeOrg debtPositionTypeOrg, String accessToken) {
if (StringUtils.isBlank(installment.getBalance())) {
String balance = getBalanceDefault(organizationId, debtPositionTypeOrg, accessToken);
installment.setBalance(balance);
}

return balanceService.calculateAmountBalance(amountBalanceRequest, accessToken);
if (StringUtils.isNotBlank(installment.getBalance())) {
String balanceResolved = resolveAmountBalance(organizationId, installment, accessToken);
installment.setBalance(balanceResolved);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public DebtPosition updateInstallmentStatusOfDebtPosition(InstallmentNoPII insta
// set status of the found installment to PAID and link it to the receipt
log.info("Installment [{}] found for receipt [{}]", paidInstallment.getInstallmentId(), receiptDTO.getReceiptId());
updateInstallmentStatusAndFeeOfDebtPosition(paidInstallment, InstallmentStatus.PAID, receiptDTO);
updateBalanceResolvingAmount(paidInstallment, debtPosition.getOrganizationId(), accessToken);
resolveBalance(installment, accessToken, paidInstallment, debtPosition);
// update mbdAttachment of transfer entity if present in input ReceiptDTO
updateMbdAttachment(receiptDTO, paidInstallment);
}, () -> {
Expand Down Expand Up @@ -109,19 +109,11 @@ private void updateInstallmentStatusAndFeeOfDebtPosition(InstallmentNoPII instal
InstallmentUtils.setStatus(installment, status);
}

private void updateBalanceResolvingAmount(InstallmentNoPII installment, Long organizationId, String accessToken) {
if (StringUtils.isBlank(installment.getBalance())) {
DebtPositionTypeOrg debtPositionTypeOrg = debtPositionTypeOrgRepository.getDebtPositionTypeOrgByInstallmentId(installment.getInstallmentId());
if(debtPositionTypeOrg == null) {
throw new NotFoundException("The DebtPositionTypeOrg for installment with id " + installment.getInstallmentId() + " was not found");
}
String balance = balanceResolverService.getBalanceDefault(organizationId, debtPositionTypeOrg, accessToken);
installment.setBalance(balance);
}

if (StringUtils.isNotBlank(installment.getBalance())) {
String balanceResolved = balanceResolverService.resolveAmountBalance(organizationId, installment, accessToken);
installment.setBalance(balanceResolved);
private void resolveBalance(InstallmentNoPII installment, String accessToken, InstallmentNoPII paidInstallment, DebtPosition debtPosition) {
DebtPositionTypeOrg debtPositionTypeOrg = debtPositionTypeOrgRepository.getDebtPositionTypeOrgByInstallmentId(installment.getInstallmentId());
if (debtPositionTypeOrg == null) {
throw new NotFoundException("The DebtPositionTypeOrg for installment with id " + installment.getInstallmentId() + " was not found");
}
balanceResolverService.updateBalanceResolvingAmount(paidInstallment, debtPosition.getOrganizationId(), debtPositionTypeOrg, accessToken);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@
import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionStatus;
import it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentStatus;
import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus;
import it.gov.pagopa.pu.debtpositions.model.DebtPosition;
import it.gov.pagopa.pu.debtpositions.model.InstallmentNoPII;
import it.gov.pagopa.pu.debtpositions.model.PaymentOption;
import it.gov.pagopa.pu.debtpositions.model.Transfer;
import it.gov.pagopa.pu.debtpositions.model.*;
import it.gov.pagopa.pu.debtpositions.repository.DebtPositionTypeOrgRepository;
import it.gov.pagopa.pu.debtpositions.service.BalanceResolverService;
import it.gov.pagopa.pu.debtpositions.util.TestUtils;
import org.junit.jupiter.api.BeforeEach;
Expand All @@ -20,8 +18,10 @@
import org.mockito.junit.jupiter.MockitoExtension;

import java.util.List;
import java.util.Optional;

import static it.gov.pagopa.pu.debtpositions.util.faker.DebtPositionFaker.buildMixedDebtPosition;
import static it.gov.pagopa.pu.debtpositions.util.faker.DebtPositionTypeOrgFaker.buildDebtPositionTypeOrg;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;

Expand All @@ -30,14 +30,16 @@ class TechnicalMixedDebtPositionMapperTest {

@Mock
private BalanceResolverService balanceResolverServiceMock;
@Mock
private DebtPositionTypeOrgRepository debtPositionTypeOrgRepository;

private TechnicalMixedDebtPositionMapper mapper;

private final String accessToken = "ACCESSTOKEN";

@BeforeEach
void init() {
mapper = new TechnicalMixedDebtPositionMapper(balanceResolverServiceMock);
mapper = new TechnicalMixedDebtPositionMapper(balanceResolverServiceMock, debtPositionTypeOrgRepository);
}

@Test
Expand Down Expand Up @@ -78,16 +80,22 @@ void whenToTechnicalMixedDebtPositionPaidThenCorrectMapping() {
PaymentOption paymentOption = debtPosition.getPaymentOptions().getFirst();
InstallmentNoPII installment = paymentOption.getInstallments().getFirst();
Transfer transfer = installment.getTransfers().getFirst();
DebtPositionTypeOrg debtPositionTypeOrg = buildDebtPositionTypeOrg();

MixedDpAdditionalData mixedDpAdditionalData = MixedDpAdditionalData.builder()
.transferIndex(1)
.iud("IUD")
.balance("balance")
.balance("balanceResolved")
.legacyPaymentMetadata("legacyPaymentMetadata")
.build();

Mockito.when(balanceResolverServiceMock.resolveAmountBalance(Mockito.anyLong(), Mockito.any(), Mockito.anyString()))
.thenReturn("balanceResolved");
Mockito.when(debtPositionTypeOrgRepository.findById(1L))
.thenReturn(Optional.of(debtPositionTypeOrg));
Mockito.doNothing().when(balanceResolverServiceMock)
.updateBalanceResolvingAmount(Mockito.any(InstallmentNoPII.class),
Mockito.eq(debtPosition.getOrganizationId()),
Mockito.any(DebtPositionTypeOrg.class),
Mockito.eq(accessToken));

DebtPosition result = mapper.toTechnicalMixedDebtPosition(debtPosition, 1L,
false, List.of(mixedDpAdditionalData), accessToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,18 @@ class BalanceResolverServiceTest {

private BalanceResolverService service;

@Mock private BalanceService balanceServiceMock;
@Mock private OrganizationService organizationServiceMock;
@Mock
private BalanceService balanceServiceMock;
@Mock
private OrganizationService organizationServiceMock;

@BeforeEach
void setUp() {
service = new BalanceResolverService(balanceServiceMock, organizationServiceMock);
}

@Test
void givenDebtPositionTypeOrgWithBalanceWhenGetBalanceThenSuccess(){
void givenDebtPositionTypeOrgWithBalanceWhenGetBalanceThenSuccess() {
Long orgId = 1L;
String accessToken = "accessToken";

Expand All @@ -50,7 +52,7 @@ void givenDebtPositionTypeOrgWithBalanceWhenGetBalanceThenSuccess(){
}

@Test
void givenDebtPositionTypeOrgWithBalanceNullWhenGetBalanceThenSuccess(){
void givenDebtPositionTypeOrgWithBalanceNullWhenGetBalanceThenSuccess() {
Long orgId = 1L;
String accessToken = "accessToken";

Expand All @@ -65,7 +67,7 @@ void givenDebtPositionTypeOrgWithBalanceNullWhenGetBalanceThenSuccess(){
}

@Test
void givenInstallmentWhenResolveAmountBalanceThenSuccess(){
void givenInstallmentWhenResolveAmountBalanceThenSuccess() {
Long orgId = 1L;
String accessToken = "accessToken";
InstallmentNoPII installment = buildInstallmentNoPII();
Expand All @@ -81,7 +83,7 @@ void givenInstallmentWhenResolveAmountBalanceThenSuccess(){
}

@Test
void givenInstallmentWithOrgNotFoundWhenResolveAmountBalanceThenSuccess(){
void givenInstallmentWithOrgNotFoundWhenResolveAmountBalanceThenSuccess() {
Long orgId = 1L;
String accessToken = "accessToken";
InstallmentNoPII installment = buildInstallmentNoPII();
Expand All @@ -95,4 +97,59 @@ void givenInstallmentWithOrgNotFoundWhenResolveAmountBalanceThenSuccess(){
Mockito.verify(balanceServiceMock, times(0)).calculateAmountBalance(Mockito.any(), Mockito.anyString());
}

@Test
void givenInstallmentWithNoBalanceWhenUpdateBalanceResolvingAmountThenSuccess() {
Long orgId = 1L;
String accessToken = "accessToken";
InstallmentNoPII installment = buildInstallmentNoPII();
installment.setBalance(null);
DebtPositionTypeOrg debtPositionTypeOrg = buildDebtPositionTypeOrg();

Mockito.when(organizationServiceMock.getOrganizationById(orgId, accessToken))
.thenReturn(Optional.ofNullable(buildOrganization()));
CalculateAmountBalanceRequest amountBalanceRequest = CalculateAmountBalanceRequest.builder()
.balance("balance").amountCents(100L).remittanceInformation(installment.getRemittanceInformation()).build();
Mockito.when(balanceServiceMock.calculateAmountBalance(amountBalanceRequest, accessToken))
.thenReturn("balanceResolved");

service.updateBalanceResolvingAmount(installment, orgId, debtPositionTypeOrg, accessToken);

assertEquals("balanceResolved", installment.getBalance());
}

@Test
void givenInstallmentWhenUpdateBalanceResolvingAmountThenSuccess() {
Long orgId = 1L;
String accessToken = "accessToken";
InstallmentNoPII installment = buildInstallmentNoPII();
DebtPositionTypeOrg debtPositionTypeOrg = buildDebtPositionTypeOrg();

Mockito.when(organizationServiceMock.getOrganizationById(orgId, accessToken))
.thenReturn(Optional.ofNullable(buildOrganization()));
CalculateAmountBalanceRequest amountBalanceRequest = CalculateAmountBalanceRequest.builder()
.balance(installment.getBalance()).amountCents(100L).remittanceInformation(installment.getRemittanceInformation()).build();
Mockito.when(balanceServiceMock.calculateAmountBalance(amountBalanceRequest, accessToken))
.thenReturn("balanceResolved");

service.updateBalanceResolvingAmount(installment, orgId, debtPositionTypeOrg, accessToken);

assertEquals("balanceResolved", installment.getBalance());
}

@Test
void givenInstallmentWithEmptyBalanceWhenUpdateBalanceResolvingAmountThenSuccess() {
Long orgId = 1L;
String accessToken = "accessToken";
InstallmentNoPII installment = buildInstallmentNoPII();
installment.setBalance("");
DebtPositionTypeOrg debtPositionTypeOrg = buildDebtPositionTypeOrg();
debtPositionTypeOrg.setBalance("");

Mockito.when(balanceServiceMock.getBalanceByAssessmentRegistry(orgId, debtPositionTypeOrg.getCode(), accessToken))
.thenReturn("");

service.updateBalanceResolvingAmount(installment, orgId, debtPositionTypeOrg, accessToken);

assertEquals("", installment.getBalance());
}
}
Loading