From 38ce7ff24fe3e5f5dff387300708367c78067c3d Mon Sep 17 00:00:00 2001 From: LarissaASLeite Date: Tue, 14 Jan 2025 17:58:56 +0100 Subject: [PATCH 01/17] P4ADEV-1744-add-api-finalize-sync-status --- build.gradle.kts | 11 +- gradle.lockfile | 2 + openapi/generated.openapi.json | 767 ++++++++++-------- openapi/p4pa-debt-position.openapi.yaml | 41 + .../DebtPositionControllerImpl.java | 8 + .../enums/DebtPositionStatus.java | 13 + .../mapper/DebtPositionMapper.java | 12 + .../mapper/InstallmentMapper.java | 11 + .../mapper/PaymentOptionMapper.java | 11 + .../pu/debtpositions/mapper/PersonMapper.java | 11 + .../debtpositions/mapper/TransferMapper.java | 12 + .../pu/debtpositions/model/DebtPosition.java | 2 + .../pu/debtpositions/model/PaymentOption.java | 2 + .../pu/debtpositions/model/Transfer.java | 2 + .../repository/DebtPositionRepository.java | 13 +- .../InstallmentNoPIIRepository.java | 9 + .../repository/PaymentOptionRepository.java | 7 + .../service/DebtPositionService.java | 11 + .../service/DebtPositionServiceImpl.java | 85 ++ .../service/DebtPositionServiceTest.java | 71 ++ .../pu/debtpositions/util/TestUtils.java | 4 + .../util/faker/DebtPositionFaker.java | 51 ++ .../util/faker/InstallmentFaker.java | 54 +- .../util/faker/PaymentOptionFaker.java | 40 + .../debtpositions/util/faker/PersonFaker.java | 16 + .../util/faker/TransferFaker.java | 40 + 26 files changed, 962 insertions(+), 344 deletions(-) create mode 100644 src/main/java/it/gov/pagopa/pu/debtpositions/enums/DebtPositionStatus.java create mode 100644 src/main/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapper.java create mode 100644 src/main/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapper.java create mode 100644 src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapper.java create mode 100644 src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PersonMapper.java create mode 100644 src/main/java/it/gov/pagopa/pu/debtpositions/mapper/TransferMapper.java create mode 100644 src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionService.java create mode 100644 src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImpl.java create mode 100644 src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceTest.java create mode 100644 src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/DebtPositionFaker.java create mode 100644 src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PaymentOptionFaker.java create mode 100644 src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/TransferFaker.java diff --git a/build.gradle.kts b/build.gradle.kts index f9bf15f..dafbc2e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -32,8 +32,8 @@ val springDocOpenApiVersion = "2.7.0" val openApiToolsVersion = "0.2.6" val micrometerVersion = "1.4.1" val postgresJdbcVersion = "42.7.4" - val bouncycastleVersion = "1.79" +val mapStructVersion = "1.6.3" dependencies { implementation("org.springframework.boot:spring-boot-starter") @@ -58,6 +58,15 @@ dependencies { compileOnly("org.projectlombok:lombok") annotationProcessor("org.projectlombok:lombok") + /** + * Mapstruct + * https://mapstruct.org/ + * mapstruct dependencies must always be placed after the lombok dependency + * or the generated mappers will return an empty object + **/ + implementation("org.mapstruct:mapstruct:$mapStructVersion") + annotationProcessor("org.mapstruct:mapstruct-processor:$mapStructVersion") + // Testing testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.mockito:mockito-core") diff --git a/gradle.lockfile b/gradle.lockfile index 4f2c81a..22633b9 100644 --- a/gradle.lockfile +++ b/gradle.lockfile @@ -60,6 +60,8 @@ org.atteo:evo-inflector:1.3=compileClasspath org.bouncycastle:bcprov-jdk18on:1.79=compileClasspath org.hibernate.orm:hibernate-core:6.6.4.Final=compileClasspath org.jspecify:jspecify:1.0.0=compileClasspath +org.mapstruct:mapstruct-processor:1.6.3=compileClasspath +org.mapstruct:mapstruct:1.6.3=compileClasspath org.openapitools:jackson-databind-nullable:0.2.6=compileClasspath org.postgresql:postgresql:42.7.4=compileClasspath org.projectlombok:lombok:1.18.36=compileClasspath diff --git a/openapi/generated.openapi.json b/openapi/generated.openapi.json index f1538f5..88c68e6 100644 --- a/openapi/generated.openapi.json +++ b/openapi/generated.openapi.json @@ -1261,6 +1261,40 @@ } } }, + "/crud/installments/search/findByIuvAndStatus" : { + "get" : { + "tags" : [ "installment-no-pii-search-controller" ], + "operationId" : "crud-installments-findByIuvAndStatus", + "parameters" : [ { + "name" : "iuv", + "in" : "query", + "schema" : { + "type" : "string" + } + }, { + "name" : "status", + "in" : "query", + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/hal+json" : { + "schema" : { + "$ref" : "#/components/schemas/InstallmentNoPII" + } + } + } + }, + "404" : { + "description" : "Not Found" + } + } + } + }, "/crud/installments/{id}" : { "get" : { "tags" : [ "installment-no-pii-entity-controller" ], @@ -2819,6 +2853,64 @@ "BearerAuth" : [ ] } ] } + }, + "/sync/status/{debtPositionId}" : { + "get" : { + "tags" : [ "debt-position" ], + "operationId" : "finalizeSyncStatus", + "parameters" : [ { + "name" : "debtPositionId", + "in" : "path", + "description" : "The ID of the debt position", + "required" : true, + "schema" : { + "type" : "integer", + "format" : "int64" + } + }, { + "name" : "SyncStatusDTO", + "in" : "query", + "required" : true, + "schema" : { + "$ref" : "#/components/schemas/SyncStatusDTO" + } + } ], + "responses" : { + "200" : { + "description" : "Ok", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/SyncStatusDTO" + } + } + } + }, + "400" : { + "description" : "Invalid request", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/SyncStatusDTO" + } + } + } + }, + "500" : { + "description" : "Internal server error", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/SyncStatusDTO" + } + } + } + } + }, + "security" : [ { + "BearerAuth" : [ ] + } ] + } } }, "components" : { @@ -2903,75 +2995,51 @@ } } }, - "InstallmentNoPII" : { + "Stamp" : { "type" : "object", "properties" : { - "installmentId" : { - "type" : "integer", - "format" : "int64" - }, - "paymentOptionId" : { - "type" : "integer", - "format" : "int64" - }, - "status" : { - "type" : "string" - }, - "iupdPagopa" : { - "type" : "string" - }, - "iud" : { - "type" : "string" - }, - "iuv" : { - "type" : "string" - }, - "iur" : { - "type" : "string" - }, - "iuf" : { + "stampType" : { "type" : "string" }, - "nav" : { + "stampHashDocument" : { "type" : "string" }, - "dueDate" : { - "type" : "string", - "format" : "date-time" - }, - "paymentTypeCode" : { + "stampProvincialResidence" : { "type" : "string" - }, - "amountCents" : { + } + } + }, + "PaymentOption" : { + "type" : "object", + "properties" : { + "paymentOptionId" : { "type" : "integer", "format" : "int64" }, - "notificationFeeCents" : { + "debtPositionId" : { "type" : "integer", "format" : "int64" }, - "remittanceInformation" : { - "type" : "string" - }, - "humanFriendlyRemittanceInformation" : { - "type" : "string" + "totalAmountCents" : { + "type" : "integer", + "format" : "int64" }, - "balance" : { + "status" : { "type" : "string" }, - "legacyPaymentMetadata" : { - "type" : "string" + "multiDebtor" : { + "type" : "boolean" }, - "personalDataId" : { - "type" : "integer", - "format" : "int64" + "dueDate" : { + "type" : "string", + "format" : "date-time" }, - "debtorEntityType" : { + "description" : { "type" : "string" }, - "debtorFiscalCodeHash" : { + "paymentOptionType" : { "type" : "string", - "format" : "byte" + "enum" : [ "SINGLE_INSTALLMENT", "INSTALMENTS", "DOWN_PAYMENT" ] }, "creationDate" : { "type" : "string", @@ -2990,20 +3058,6 @@ } } }, - "Stamp" : { - "type" : "object", - "properties" : { - "stampType" : { - "type" : "string" - }, - "stampHashDocument" : { - "type" : "string" - }, - "stampProvincialResidence" : { - "type" : "string" - } - } - }, "PageMetadata" : { "type" : "object", "properties" : { @@ -3025,16 +3079,16 @@ } } }, - "PagedModelInstallmentNoPII" : { + "PagedModelPaymentOption" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "installmentNoPIIs" : { + "paymentOptions" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/InstallmentNoPII" + "$ref" : "#/components/schemas/PaymentOption" } } } @@ -3047,16 +3101,16 @@ } } }, - "CollectionModelTransfer" : { + "CollectionModelInstallmentNoPII" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "transfers" : { + "installmentNoPIIs" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/TransferResponse" + "$ref" : "#/components/schemas/InstallmentNoPIIResponse" } } } @@ -3085,117 +3139,124 @@ } } }, - "DebtPositionTypeOrg" : { + "ReceiptNoPII" : { "type" : "object", "properties" : { - "debtPositionTypeOrgId" : { + "receiptId" : { "type" : "integer", "format" : "int64" }, - "debtPositionTypeId" : { + "installmentId" : { "type" : "integer", "format" : "int64" }, - "organizationId" : { + "paymentReceiptId" : { "type" : "integer", "format" : "int64" }, - "balance" : { + "noticeNumber" : { "type" : "string" }, - "code" : { + "orgFiscalCode" : { "type" : "string" }, - "description" : { + "outcome" : { "type" : "string" }, - "iban" : { + "creditorReferenceId" : { "type" : "string" }, - "postalIban" : { - "type" : "string" + "paymentAmountCents" : { + "type" : "integer", + "format" : "int64" }, - "postalAccountCode" : { + "description" : { "type" : "string" }, - "holderPostalCc" : { + "companyName" : { "type" : "string" }, - "orgSector" : { + "officeName" : { "type" : "string" }, - "xsdDefinitionRef" : { + "idPsp" : { "type" : "string" }, - "amountCents" : { - "type" : "integer", - "format" : "int64" - }, - "externalPaymentUrl" : { + "pspFiscalCode" : { "type" : "string" }, - "flagAnonymousFiscalCode" : { - "type" : "boolean" - }, - "flagMandatoryDueDate" : { - "type" : "boolean" - }, - "flagSpontaneous" : { - "type" : "boolean" - }, - "flagNotifyIo" : { - "type" : "boolean" - }, - "ioTemplateMessage" : { + "pspPartitaIva" : { "type" : "string" }, - "flagActive" : { - "type" : "boolean" + "pspCompanyName" : { + "type" : "string" }, - "flagNotifyOutcomePush" : { - "type" : "boolean" + "idChannel" : { + "type" : "string" }, - "notifyOutcomePushOrgSilServiceId" : { - "type" : "integer", - "format" : "int64" + "channelDescription" : { + "type" : "string" }, - "flagAmountActualization" : { - "type" : "boolean" + "paymentMethod" : { + "type" : "string" }, - "amountActualizationOrgSilServiceId" : { + "feeCents" : { "type" : "integer", "format" : "int64" }, - "flagExternal" : { - "type" : "boolean" + "paymentDateTime" : { + "type" : "string", + "format" : "date-time" }, - "creationDate" : { + "applicationDate" : { "type" : "string", "format" : "date-time" }, - "updateDate" : { + "transferDate" : { "type" : "string", "format" : "date-time" }, - "updateOperatorExternalId" : { - "type" : "integer", - "format" : "int64" + "standin" : { + "type" : "boolean" + }, + "debtorEntityType" : { + "type" : "string" + }, + "personalDataId" : { + "type" : "integer", + "format" : "int64" + }, + "debtorFiscalCodeHash" : { + "type" : "string", + "format" : "byte" + }, + "creationDate" : { + "type" : "string", + "format" : "date-time" + }, + "updateDate" : { + "type" : "string", + "format" : "date-time" + }, + "updateOperatorExternalId" : { + "type" : "integer", + "format" : "int64" }, "_links" : { "$ref" : "#/components/schemas/Links" } } }, - "PagedModelDebtPositionTypeOrg" : { + "PagedModelReceiptNoPII" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "debtPositionTypeOrgs" : { + "receiptNoPIIs" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/DebtPositionTypeOrg" + "$ref" : "#/components/schemas/ReceiptNoPII" } } } @@ -3208,46 +3269,76 @@ } } }, - "Transfer" : { + "InstallmentNoPII" : { "type" : "object", "properties" : { - "transferId" : { + "installmentId" : { "type" : "integer", "format" : "int64" }, - "installmentId" : { + "paymentOptionId" : { "type" : "integer", "format" : "int64" }, - "orgFiscalCode" : { + "status" : { "type" : "string" }, - "orgName" : { + "iupdPagopa" : { + "type" : "string" + }, + "iud" : { + "type" : "string" + }, + "iuv" : { + "type" : "string" + }, + "iur" : { + "type" : "string" + }, + "iuf" : { + "type" : "string" + }, + "nav" : { + "type" : "string" + }, + "dueDate" : { + "type" : "string", + "format" : "date-time" + }, + "paymentTypeCode" : { "type" : "string" }, "amountCents" : { "type" : "integer", "format" : "int64" }, + "notificationFeeCents" : { + "type" : "integer", + "format" : "int64" + }, "remittanceInformation" : { "type" : "string" }, - "stamp" : { - "$ref" : "#/components/schemas/Stamp" - }, - "iban" : { + "humanFriendlyRemittanceInformation" : { "type" : "string" }, - "postalIban" : { + "balance" : { "type" : "string" }, - "category" : { + "legacyPaymentMetadata" : { "type" : "string" }, - "transferIndex" : { + "personalDataId" : { "type" : "integer", "format" : "int64" }, + "debtorEntityType" : { + "type" : "string" + }, + "debtorFiscalCodeHash" : { + "type" : "string", + "format" : "byte" + }, "creationDate" : { "type" : "string", "format" : "date-time" @@ -3265,16 +3356,16 @@ } } }, - "PagedModelTransfer" : { + "PagedModelInstallmentNoPII" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "transfers" : { + "installmentNoPIIs" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/Transfer" + "$ref" : "#/components/schemas/InstallmentNoPII" } } } @@ -3287,50 +3378,68 @@ } } }, - "DebtPositionType" : { + "CollectionModelTransfer" : { "type" : "object", "properties" : { - "debtPositionTypeId" : { - "type" : "integer", - "format" : "int64" + "_embedded" : { + "type" : "object", + "properties" : { + "transfers" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/TransferResponse" + } + } + } }, - "brokerId" : { + "_links" : { + "$ref" : "#/components/schemas/Links" + } + } + }, + "DebtPosition" : { + "type" : "object", + "properties" : { + "debtPositionId" : { "type" : "integer", "format" : "int64" }, - "code" : { + "iupdOrg" : { "type" : "string" }, "description" : { "type" : "string" }, - "orgType" : { + "status" : { "type" : "string" }, - "macroArea" : { - "type" : "string" + "ingestionFlowFileId" : { + "type" : "integer", + "format" : "int64" }, - "serviceType" : { - "type" : "string" + "ingestionFlowFileLineNumber" : { + "type" : "integer", + "format" : "int64" }, - "collectingReason" : { - "type" : "string" + "organizationId" : { + "type" : "integer", + "format" : "int64" }, - "taxonomyCode" : { - "type" : "string" + "debtPositionTypeOrgId" : { + "type" : "integer", + "format" : "int64" }, - "flagAnonymousFiscalCode" : { - "type" : "boolean" + "notificationDate" : { + "type" : "string", + "format" : "date-time" }, - "flagMandatoryDueDate" : { - "type" : "boolean" + "validityDate" : { + "type" : "string", + "format" : "date-time" }, - "flagNotifyIo" : { + "flagIuvVolatile" : { "type" : "boolean" }, - "ioTemplateMessage" : { - "type" : "string" - }, "creationDate" : { "type" : "string", "format" : "date-time" @@ -3348,16 +3457,16 @@ } } }, - "PagedModelDebtPositionType" : { + "PagedModelDebtPosition" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "debtPositionTypes" : { + "debtPositions" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/DebtPositionType" + "$ref" : "#/components/schemas/DebtPosition" } } } @@ -3370,97 +3479,40 @@ } } }, - "ReceiptNoPII" : { + "CollectionModelPaymentOption" : { "type" : "object", "properties" : { - "receiptId" : { - "type" : "integer", - "format" : "int64" - }, - "installmentId" : { - "type" : "integer", - "format" : "int64" - }, - "paymentReceiptId" : { - "type" : "integer", - "format" : "int64" - }, - "noticeNumber" : { - "type" : "string" - }, - "orgFiscalCode" : { - "type" : "string" - }, - "outcome" : { - "type" : "string" - }, - "creditorReferenceId" : { - "type" : "string" + "_embedded" : { + "type" : "object", + "properties" : { + "paymentOptions" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/PaymentOptionResponse" + } + } + } }, - "paymentAmountCents" : { + "_links" : { + "$ref" : "#/components/schemas/Links" + } + } + }, + "DebtPositionTypeOrgOperators" : { + "type" : "object", + "properties" : { + "debtPositionTypeOrgOperatorId" : { "type" : "integer", "format" : "int64" }, - "description" : { - "type" : "string" - }, - "companyName" : { - "type" : "string" - }, - "officeName" : { - "type" : "string" - }, - "idPsp" : { - "type" : "string" - }, - "pspFiscalCode" : { - "type" : "string" - }, - "pspPartitaIva" : { - "type" : "string" - }, - "pspCompanyName" : { - "type" : "string" - }, - "idChannel" : { - "type" : "string" - }, - "channelDescription" : { - "type" : "string" - }, - "paymentMethod" : { - "type" : "string" - }, - "feeCents" : { + "debtPositionTypeOrgId" : { "type" : "integer", "format" : "int64" }, - "paymentDateTime" : { - "type" : "string", - "format" : "date-time" - }, - "applicationDate" : { - "type" : "string", - "format" : "date-time" - }, - "transferDate" : { - "type" : "string", - "format" : "date-time" - }, - "standin" : { - "type" : "boolean" - }, - "debtorEntityType" : { - "type" : "string" - }, - "personalDataId" : { + "operatorExternalUserId" : { "type" : "integer", "format" : "int64" }, - "debtorFiscalCodeHash" : { - "type" : "string", - "format" : "byte" - }, "creationDate" : { "type" : "string", "format" : "date-time" @@ -3478,16 +3530,16 @@ } } }, - "PagedModelReceiptNoPII" : { + "PagedModelDebtPositionTypeOrgOperators" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "receiptNoPIIs" : { + "debtPositionTypeOrgOperatorses" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/ReceiptNoPII" + "$ref" : "#/components/schemas/DebtPositionTypeOrgOperators" } } } @@ -3500,37 +3552,49 @@ } } }, - "PaymentOption" : { + "DebtPositionType" : { "type" : "object", "properties" : { - "paymentOptionId" : { + "debtPositionTypeId" : { "type" : "integer", "format" : "int64" }, - "debtPositionId" : { + "brokerId" : { "type" : "integer", "format" : "int64" }, - "totalAmountCents" : { - "type" : "integer", - "format" : "int64" + "code" : { + "type" : "string" }, - "status" : { + "description" : { "type" : "string" }, - "multiDebtor" : { - "type" : "boolean" + "orgType" : { + "type" : "string" }, - "dueDate" : { - "type" : "string", - "format" : "date-time" + "macroArea" : { + "type" : "string" }, - "description" : { + "serviceType" : { "type" : "string" }, - "paymentOptionType" : { - "type" : "string", - "enum" : [ "SINGLE_INSTALLMENT", "INSTALMENTS", "DOWN_PAYMENT" ] + "collectingReason" : { + "type" : "string" + }, + "taxonomyCode" : { + "type" : "string" + }, + "flagAnonymousFiscalCode" : { + "type" : "boolean" + }, + "flagMandatoryDueDate" : { + "type" : "boolean" + }, + "flagNotifyIo" : { + "type" : "boolean" + }, + "ioTemplateMessage" : { + "type" : "string" }, "creationDate" : { "type" : "string", @@ -3549,16 +3613,16 @@ } } }, - "PagedModelPaymentOption" : { + "PagedModelDebtPositionType" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "paymentOptions" : { + "debtPositionTypes" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/PaymentOption" + "$ref" : "#/components/schemas/DebtPositionType" } } } @@ -3571,37 +3635,43 @@ } } }, - "CollectionModelInstallmentNoPII" : { + "Transfer" : { "type" : "object", "properties" : { - "_embedded" : { - "type" : "object", - "properties" : { - "installmentNoPIIs" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/InstallmentNoPIIResponse" - } - } - } + "transferId" : { + "type" : "integer", + "format" : "int64" }, - "_links" : { - "$ref" : "#/components/schemas/Links" - } - } - }, - "DebtPositionTypeOrgOperators" : { - "type" : "object", - "properties" : { - "debtPositionTypeOrgOperatorId" : { + "installmentId" : { "type" : "integer", "format" : "int64" }, - "debtPositionTypeOrgId" : { + "orgFiscalCode" : { + "type" : "string" + }, + "orgName" : { + "type" : "string" + }, + "amountCents" : { "type" : "integer", "format" : "int64" }, - "operatorExternalUserId" : { + "remittanceInformation" : { + "type" : "string" + }, + "stamp" : { + "$ref" : "#/components/schemas/Stamp" + }, + "iban" : { + "type" : "string" + }, + "postalIban" : { + "type" : "string" + }, + "category" : { + "type" : "string" + }, + "transferIndex" : { "type" : "integer", "format" : "int64" }, @@ -3622,16 +3692,16 @@ } } }, - "PagedModelDebtPositionTypeOrgOperators" : { + "PagedModelTransfer" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "debtPositionTypeOrgOperatorses" : { + "transfers" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/DebtPositionTypeOrgOperators" + "$ref" : "#/components/schemas/Transfer" } } } @@ -3644,47 +3714,88 @@ } } }, - "DebtPosition" : { + "DebtPositionTypeOrg" : { "type" : "object", "properties" : { - "debtPositionId" : { + "debtPositionTypeOrgId" : { "type" : "integer", "format" : "int64" }, - "iupdOrg" : { + "debtPositionTypeId" : { + "type" : "integer", + "format" : "int64" + }, + "organizationId" : { + "type" : "integer", + "format" : "int64" + }, + "balance" : { + "type" : "string" + }, + "code" : { "type" : "string" }, "description" : { "type" : "string" }, - "status" : { + "iban" : { "type" : "string" }, - "ingestionFlowFileId" : { - "type" : "integer", - "format" : "int64" + "postalIban" : { + "type" : "string" }, - "ingestionFlowFileLineNumber" : { - "type" : "integer", - "format" : "int64" + "postalAccountCode" : { + "type" : "string" }, - "organizationId" : { + "holderPostalCc" : { + "type" : "string" + }, + "orgSector" : { + "type" : "string" + }, + "xsdDefinitionRef" : { + "type" : "string" + }, + "amountCents" : { "type" : "integer", "format" : "int64" }, - "debtPositionTypeOrgId" : { + "externalPaymentUrl" : { + "type" : "string" + }, + "flagAnonymousFiscalCode" : { + "type" : "boolean" + }, + "flagMandatoryDueDate" : { + "type" : "boolean" + }, + "flagSpontaneous" : { + "type" : "boolean" + }, + "flagNotifyIo" : { + "type" : "boolean" + }, + "ioTemplateMessage" : { + "type" : "string" + }, + "flagActive" : { + "type" : "boolean" + }, + "flagNotifyOutcomePush" : { + "type" : "boolean" + }, + "notifyOutcomePushOrgSilServiceId" : { "type" : "integer", "format" : "int64" }, - "notificationDate" : { - "type" : "string", - "format" : "date-time" + "flagAmountActualization" : { + "type" : "boolean" }, - "validityDate" : { - "type" : "string", - "format" : "date-time" + "amountActualizationOrgSilServiceId" : { + "type" : "integer", + "format" : "int64" }, - "flagIuvVolatile" : { + "flagExternal" : { "type" : "boolean" }, "creationDate" : { @@ -3704,16 +3815,16 @@ } } }, - "PagedModelDebtPosition" : { + "PagedModelDebtPositionTypeOrg" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "debtPositions" : { + "debtPositionTypeOrgs" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/DebtPosition" + "$ref" : "#/components/schemas/DebtPositionTypeOrg" } } } @@ -3726,25 +3837,6 @@ } } }, - "CollectionModelPaymentOption" : { - "type" : "object", - "properties" : { - "_embedded" : { - "type" : "object", - "properties" : { - "paymentOptions" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/PaymentOptionResponse" - } - } - } - }, - "_links" : { - "$ref" : "#/components/schemas/Links" - } - } - }, "DebtPositionTypeOrgOperatorsRequestBody" : { "type" : "object", "properties" : { @@ -4738,6 +4830,25 @@ } } }, + "IudSyncStatusUpdateDTO" : { + "type" : "object", + "properties" : { + "newStatus" : { + "type" : "string" + }, + "iupdPagopa" : { + "type" : "string" + } + } + }, + "SyncStatusDTO" : { + "type" : "object", + "properties" : { + "additionalProperties" : { + "$ref" : "#/components/schemas/IudSyncStatusUpdateDTO" + } + } + }, "Link" : { "type" : "object", "properties" : { diff --git a/openapi/p4pa-debt-position.openapi.yaml b/openapi/p4pa-debt-position.openapi.yaml index 3bd33f8..fc680ce 100644 --- a/openapi/p4pa-debt-position.openapi.yaml +++ b/openapi/p4pa-debt-position.openapi.yaml @@ -29,6 +29,36 @@ paths: description: Invalid request "500": description: Internal server error + /sync/status/{debtPositionId}: + put: + tags: + - debt-position + operationId: finalizeSyncStatus + parameters: + - name: debtPositionId + in: path + required: true + schema: + type: integer + format: int64 + description: The ID of the debt position + requestBody: + content: + application/json: + schema: + $ref: "#/components/schemas/SyncStatusDTO" + required: true + responses: + "200": + description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/DebtPositionDTO' + "400": + description: Invalid request + "500": + description: Internal server error security: - BearerAuth: [] components: @@ -309,3 +339,14 @@ components: type: string email: type: string + SyncStatusDTO: + type: object + additionalProperties: + $ref: "#/components/schemas/IudSyncStatusUpdateDTO" + IudSyncStatusUpdateDTO: + type: object + properties: + newStatus: + type: string + iupdPagopa: + type: string diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerImpl.java b/src/main/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerImpl.java index 975eca4..3b21d46 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerImpl.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerImpl.java @@ -2,13 +2,21 @@ import it.gov.pagopa.pu.debtpositions.controller.generated.DebtPositionApi; import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; +import it.gov.pagopa.pu.debtpositions.dto.generated.IudSyncStatusUpdateDTO; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RestController; +import java.util.Map; + @RestController public class DebtPositionControllerImpl implements DebtPositionApi { @Override public ResponseEntity createDebtPosition(DebtPositionDTO debtPositionDTO) { return DebtPositionApi.super.createDebtPosition(debtPositionDTO); } + + @Override + public ResponseEntity finalizeSyncStatus(Long debtPositionId, Map requestBody) { + return DebtPositionApi.super.finalizeSyncStatus(debtPositionId, requestBody); + } } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/enums/DebtPositionStatus.java b/src/main/java/it/gov/pagopa/pu/debtpositions/enums/DebtPositionStatus.java new file mode 100644 index 0000000..3496310 --- /dev/null +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/enums/DebtPositionStatus.java @@ -0,0 +1,13 @@ +package it.gov.pagopa.pu.debtpositions.enums; + +public enum DebtPositionStatus { + + TO_SYNC, + REPORTED, + PAID, + PARTIALLY_PAID, + CANCELLED, + INVALID, + EXPIRED, + UNPAID +} diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapper.java b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapper.java new file mode 100644 index 0000000..b1450e2 --- /dev/null +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapper.java @@ -0,0 +1,12 @@ +package it.gov.pagopa.pu.debtpositions.mapper; + +import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; +import it.gov.pagopa.pu.debtpositions.model.DebtPosition; +import org.mapstruct.Mapper; + +@Mapper(componentModel = "spring", uses = {PaymentOptionMapper.class}) +public interface DebtPositionMapper { + + DebtPositionDTO map(DebtPosition debtPosition); +} + diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapper.java b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapper.java new file mode 100644 index 0000000..c2d4c23 --- /dev/null +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapper.java @@ -0,0 +1,11 @@ +package it.gov.pagopa.pu.debtpositions.mapper; + +import it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentDTO; +import it.gov.pagopa.pu.debtpositions.model.InstallmentNoPII; +import org.mapstruct.Mapper; + +@Mapper(componentModel = "spring", uses = {TransferMapper.class, PersonMapper.class}) +public interface InstallmentMapper { + + InstallmentDTO map(InstallmentNoPII installment); +} diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapper.java b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapper.java new file mode 100644 index 0000000..950bb41 --- /dev/null +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapper.java @@ -0,0 +1,11 @@ +package it.gov.pagopa.pu.debtpositions.mapper; + +import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionDTO; +import it.gov.pagopa.pu.debtpositions.model.PaymentOption; +import org.mapstruct.Mapper; + +@Mapper(componentModel = "spring", uses = {InstallmentMapper.class}) +public interface PaymentOptionMapper { + + PaymentOptionDTO map(PaymentOption paymentOption); +} diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PersonMapper.java b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PersonMapper.java new file mode 100644 index 0000000..121c739 --- /dev/null +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PersonMapper.java @@ -0,0 +1,11 @@ +package it.gov.pagopa.pu.debtpositions.mapper; + +import it.gov.pagopa.pu.debtpositions.dto.Person; +import it.gov.pagopa.pu.debtpositions.dto.generated.PersonDTO; +import org.mapstruct.Mapper; + +@Mapper(componentModel = "spring") +public interface PersonMapper { + + PersonDTO map(Person person); +} diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/TransferMapper.java b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/TransferMapper.java new file mode 100644 index 0000000..68af4d7 --- /dev/null +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/TransferMapper.java @@ -0,0 +1,12 @@ +package it.gov.pagopa.pu.debtpositions.mapper; + +import it.gov.pagopa.pu.debtpositions.dto.generated.TransferDTO; +import it.gov.pagopa.pu.debtpositions.model.Transfer; +import org.mapstruct.Mapper; + +@Mapper(componentModel = "spring") +public interface TransferMapper { + + TransferDTO map(Transfer transfer); +} + diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/model/DebtPosition.java b/src/main/java/it/gov/pagopa/pu/debtpositions/model/DebtPosition.java index 4fbf4ed..8d15c1d 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/model/DebtPosition.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/model/DebtPosition.java @@ -2,6 +2,7 @@ import jakarta.persistence.*; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; @@ -26,6 +27,7 @@ @AllArgsConstructor @NoArgsConstructor @Data +@Builder public class DebtPosition implements Serializable { @Id diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/model/PaymentOption.java b/src/main/java/it/gov/pagopa/pu/debtpositions/model/PaymentOption.java index 826e992..34d8d42 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/model/PaymentOption.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/model/PaymentOption.java @@ -3,6 +3,7 @@ import it.gov.pagopa.pu.debtpositions.enums.PaymentOptionType; import jakarta.persistence.*; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; @@ -15,6 +16,7 @@ @AllArgsConstructor @NoArgsConstructor @Data +@Builder public class PaymentOption implements Serializable { @Id diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/model/Transfer.java b/src/main/java/it/gov/pagopa/pu/debtpositions/model/Transfer.java index f7a5551..235d7cd 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/model/Transfer.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/model/Transfer.java @@ -2,6 +2,7 @@ import jakarta.persistence.*; import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; @@ -13,6 +14,7 @@ @AllArgsConstructor @NoArgsConstructor @Data +@Builder public class Transfer implements Serializable { @Id diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/repository/DebtPositionRepository.java b/src/main/java/it/gov/pagopa/pu/debtpositions/repository/DebtPositionRepository.java index 786892f..d39be75 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/repository/DebtPositionRepository.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/repository/DebtPositionRepository.java @@ -3,11 +3,18 @@ import it.gov.pagopa.pu.debtpositions.model.DebtPosition; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.data.rest.core.annotation.RepositoryRestResource; @RepositoryRestResource(path = "debt-positions") -public interface DebtPositionRepository extends JpaRepository { +public interface DebtPositionRepository extends JpaRepository { - @EntityGraph(value = "completeDebtPosition") - DebtPosition findOneWithAllDataByDebtPositionId(Long debtPositionId); + @EntityGraph(value = "completeDebtPosition") + DebtPosition findOneWithAllDataByDebtPositionId(Long debtPositionId); + + @Modifying + @Query("UPDATE DebtPosition d SET d.status = :status WHERE d.debtPositionId = :debtPositionId") + void updateStatus(@Param("debtPositionId") Long debtPositionId, @Param("status") String status); } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/repository/InstallmentNoPIIRepository.java b/src/main/java/it/gov/pagopa/pu/debtpositions/repository/InstallmentNoPIIRepository.java index a30da6c..00ecd3c 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/repository/InstallmentNoPIIRepository.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/repository/InstallmentNoPIIRepository.java @@ -2,9 +2,18 @@ import it.gov.pagopa.pu.debtpositions.model.InstallmentNoPII; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.data.rest.core.annotation.RepositoryRestResource; @RepositoryRestResource(path = "installments") public interface InstallmentNoPIIRepository extends JpaRepository { + InstallmentNoPII findByIudAndIupdPagopaAndStatus(String iud, String iupdPagopa, String status); + + @Modifying + @Query("UPDATE InstallmentNoPII i SET i.status = :status WHERE i.installmentId = :installmentId") + void updateStatus(@Param("installmentId") Long installmentId, @Param("status") String status); + } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/repository/PaymentOptionRepository.java b/src/main/java/it/gov/pagopa/pu/debtpositions/repository/PaymentOptionRepository.java index d2613bb..cc8cea8 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/repository/PaymentOptionRepository.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/repository/PaymentOptionRepository.java @@ -2,9 +2,16 @@ import it.gov.pagopa.pu.debtpositions.model.PaymentOption; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.data.rest.core.annotation.RepositoryRestResource; @RepositoryRestResource(path = "payment-options") public interface PaymentOptionRepository extends JpaRepository { + @Modifying + @Query("UPDATE PaymentOption p SET p.status = :status WHERE p.paymentOptionId = :paymentOptionId") + void updateStatus(@Param("paymentOptionId") Long paymentOptionId, @Param("status") String status); + } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionService.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionService.java new file mode 100644 index 0000000..937c310 --- /dev/null +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionService.java @@ -0,0 +1,11 @@ +package it.gov.pagopa.pu.debtpositions.service; + +import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; +import it.gov.pagopa.pu.debtpositions.dto.generated.IudSyncStatusUpdateDTO; + +import java.util.Map; + +public interface DebtPositionService { + + DebtPositionDTO finalizeSyncStatus(Long debtPositionId, Map syncStatusDTO); +} diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImpl.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImpl.java new file mode 100644 index 0000000..6beff3e --- /dev/null +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImpl.java @@ -0,0 +1,85 @@ +package it.gov.pagopa.pu.debtpositions.service; + +import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; +import it.gov.pagopa.pu.debtpositions.dto.generated.IudSyncStatusUpdateDTO; +import it.gov.pagopa.pu.debtpositions.mapper.DebtPositionMapper; +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.repository.DebtPositionRepository; +import it.gov.pagopa.pu.debtpositions.repository.InstallmentNoPIIRepository; +import it.gov.pagopa.pu.debtpositions.repository.PaymentOptionRepository; + +import java.util.Map; + +import static it.gov.pagopa.pu.debtpositions.enums.DebtPositionStatus.TO_SYNC; + +public class DebtPositionServiceImpl implements DebtPositionService{ + + private final DebtPositionRepository debtPositionRepository; + private final PaymentOptionRepository paymentOptionRepository; + private final InstallmentNoPIIRepository installmentNoPIIRepository; + private final DebtPositionMapper debtPositionMapper; + + public DebtPositionServiceImpl(DebtPositionRepository debtPositionRepository, PaymentOptionRepository paymentOptionRepository, InstallmentNoPIIRepository installmentNoPIIRepository, DebtPositionMapper debtPositionMapper) { + this.debtPositionRepository = debtPositionRepository; + this.paymentOptionRepository = paymentOptionRepository; + this.installmentNoPIIRepository = installmentNoPIIRepository; + this.debtPositionMapper = debtPositionMapper; + } + + @Override + public DebtPositionDTO finalizeSyncStatus(Long debtPositionId, Map syncStatusDTO) { + DebtPosition debtPosition = debtPositionRepository.findOneWithAllDataByDebtPositionId(debtPositionId); + + debtPosition.getPaymentOptions().stream() + .filter(paymentOption -> { + boolean anyUpdated = paymentOption.getInstallments().stream() + .filter(installment -> TO_SYNC.name().equals(installment.getStatus())) + .filter(installment -> syncStatusDTO.containsKey(installment.getIud())) + .filter(installment -> installment.getIupdPagopa().equals(syncStatusDTO.get(installment.getIud()).getIupdPagopa())) + .map(installment -> { + IudSyncStatusUpdateDTO updateDTO = syncStatusDTO.get(installment.getIud()); + installment.setStatus(updateDTO.getNewStatus()); + installmentNoPIIRepository.updateStatus( + installment.getInstallmentId(), + updateDTO.getNewStatus() + ); + return true; + }) + .findAny() + .orElse(false); + + if (anyUpdated) { + updatePaymentOptionStatus(paymentOption); + } + return anyUpdated; + }) + .findAny() + .ifPresent(op -> updateDebtPositionStatus(debtPosition)); + + return debtPositionMapper.map(debtPosition); + } + + private void updatePaymentOptionStatus(PaymentOption paymentOption) { + paymentOption.getInstallments().stream() + .map(InstallmentNoPII::getStatus) + .distinct() + .reduce((first, second) -> null) + .ifPresent(unifiedStatus -> { + paymentOption.setStatus(unifiedStatus); + paymentOptionRepository.updateStatus(paymentOption.getPaymentOptionId(), unifiedStatus); + }); + } + + private void updateDebtPositionStatus(DebtPosition debtPosition) { + debtPosition.getPaymentOptions().stream() + .map(PaymentOption::getStatus) + .distinct() + .reduce((first, second) -> null) + .ifPresent(unifiedStatus -> { + debtPosition.setStatus(unifiedStatus); + debtPositionRepository.updateStatus(debtPosition.getDebtPositionId(), unifiedStatus); + }); + } +} diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceTest.java new file mode 100644 index 0000000..1d542cc --- /dev/null +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceTest.java @@ -0,0 +1,71 @@ +package it.gov.pagopa.pu.debtpositions.service; + +import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; +import it.gov.pagopa.pu.debtpositions.dto.generated.IudSyncStatusUpdateDTO; +import it.gov.pagopa.pu.debtpositions.mapper.DebtPositionMapper; +import it.gov.pagopa.pu.debtpositions.model.DebtPosition; +import it.gov.pagopa.pu.debtpositions.repository.DebtPositionRepository; +import it.gov.pagopa.pu.debtpositions.repository.InstallmentNoPIIRepository; +import it.gov.pagopa.pu.debtpositions.repository.PaymentOptionRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.HashMap; +import java.util.Map; + +import static it.gov.pagopa.pu.debtpositions.util.faker.DebtPositionFaker.buildDebtPosition; +import static it.gov.pagopa.pu.debtpositions.util.faker.DebtPositionFaker.buildDebtPositionDTO; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +@ExtendWith(MockitoExtension.class) +class DebtPositionServiceTest { + + @Mock + private DebtPositionRepository debtPositionRepositoryMock; + @Mock + private PaymentOptionRepository paymentOptionRepositoryMock; + @Mock + private InstallmentNoPIIRepository installmentNoPIIRepositoryMock; + @Mock + private DebtPositionMapper debtPositionMapperMock; + + private DebtPositionService service; + + @BeforeEach + void setUp(){ + service = new DebtPositionServiceImpl(debtPositionRepositoryMock, paymentOptionRepositoryMock, installmentNoPIIRepositoryMock, debtPositionMapperMock); + } + + @Test + void givenFinalizeSyncStatusThenOk(){ + Long id = 1L; + String newStatus = "newStatus"; + DebtPosition debtPosition = buildDebtPosition(); + Mockito.when(debtPositionRepositoryMock.findOneWithAllDataByDebtPositionId(id)).thenReturn(debtPosition); + + Mockito.doNothing().when(installmentNoPIIRepositoryMock).updateStatus(id, newStatus); + + Mockito.doNothing().when(paymentOptionRepositoryMock).updateStatus(id, newStatus); + + Mockito.doNothing().when(debtPositionRepositoryMock).updateStatus(id, newStatus); + + Mockito.when(debtPositionMapperMock.map(debtPosition)).thenReturn(buildDebtPositionDTO()); + + Map syncStatusDTO = new HashMap<>(); + IudSyncStatusUpdateDTO iudSyncStatusUpdateDTO = IudSyncStatusUpdateDTO.builder() + .newStatus(newStatus) + .iupdPagopa("iupdPagopa") + .build(); + + syncStatusDTO.put("iud", iudSyncStatusUpdateDTO); + + DebtPositionDTO debtPositionDTO = service.finalizeSyncStatus(id, syncStatusDTO); + System.out.println("debtPositionDTO: " + debtPositionDTO); + + assertNotNull(debtPositionDTO); + } +} diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/TestUtils.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/TestUtils.java index c285205..12e534e 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/util/TestUtils.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/TestUtils.java @@ -2,11 +2,15 @@ import org.junit.jupiter.api.Assertions; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; import java.util.Arrays; import java.util.HashSet; import java.util.Set; public class TestUtils { + public static final OffsetDateTime OFFSET_DATE_TIME = OffsetDateTime.of(2025, 1, 1, 0,0,0, 0, ZoneOffset.UTC); + private TestUtils(){} /** diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/DebtPositionFaker.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/DebtPositionFaker.java new file mode 100644 index 0000000..9307ec7 --- /dev/null +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/DebtPositionFaker.java @@ -0,0 +1,51 @@ +package it.gov.pagopa.pu.debtpositions.util.faker; + +import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; +import it.gov.pagopa.pu.debtpositions.model.DebtPosition; + +import java.util.List; + +import static it.gov.pagopa.pu.debtpositions.util.TestUtils.OFFSET_DATE_TIME; +import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.buildPaymentOption; +import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.buildPaymentOptionDTO; + +public class DebtPositionFaker { + + public static DebtPositionDTO buildDebtPositionDTO() { + return DebtPositionDTO.builder() + .debtPositionId(1L) + .iupdOrg("iupdOrg") + .description("description") + .status("TO_SYNC") + .ingestionFlowFileId(1L) + .ingestionFlowFileLineNumber(1L) + .organizationId(1L) + .debtPositionTypeOrgId(1L) + .notificationDate(OFFSET_DATE_TIME) + .validityDate(OFFSET_DATE_TIME) + .flagIuvVolatile(false) + .creationDate(OFFSET_DATE_TIME) + .updateDate(OFFSET_DATE_TIME) + .paymentOptions(List.of(buildPaymentOptionDTO())) + .build(); + } + + public static DebtPosition buildDebtPosition() { + return DebtPosition.builder() + .debtPositionId(1L) + .iupdOrg("iupdOrg") + .description("description") + .status("TO_SYNC") + .ingestionFlowFileId(1L) + .ingestionFlowFileLineNumber(1L) + .organizationId(1L) + .debtPositionTypeOrgId(1L) + .notificationDate(OFFSET_DATE_TIME) + .validityDate(OFFSET_DATE_TIME) + .flagIuvVolatile(false) + .creationDate(OFFSET_DATE_TIME) + .updateDate(OFFSET_DATE_TIME) + .paymentOptions(List.of(buildPaymentOption())) + .build(); + } +} diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java index b07a24f..f7b3565 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java @@ -2,30 +2,32 @@ import it.gov.pagopa.pu.debtpositions.dto.Installment; import it.gov.pagopa.pu.debtpositions.dto.InstallmentPIIDTO; +import it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentDTO; +import it.gov.pagopa.pu.debtpositions.dto.generated.TransferDTO; import it.gov.pagopa.pu.debtpositions.model.InstallmentNoPII; -import java.time.OffsetDateTime; -import java.time.ZoneOffset; +import java.util.ArrayList; import java.util.List; +import static it.gov.pagopa.pu.debtpositions.util.TestUtils.OFFSET_DATE_TIME; import static it.gov.pagopa.pu.debtpositions.util.faker.PersonFaker.buildPerson; +import static it.gov.pagopa.pu.debtpositions.util.faker.PersonFaker.buildPersonDTO; +import static it.gov.pagopa.pu.debtpositions.util.faker.TransferFaker.buildTransferDTO; public class InstallmentFaker { - static OffsetDateTime date = OffsetDateTime.of(2025, 1, 1, 0,0,0, 0, ZoneOffset.UTC); - public static Installment buildInstallment(){ return Installment.builder() .installmentId(1L) .paymentOptionId(1L) - .status("status") + .status("TO_SYNC") .iupdPagopa("iupdPagoPa") .iud("iud") .iuv("iuv") .iur("iur") .iuf("iuf") .nav("nav") - .dueDate(date) + .dueDate(OFFSET_DATE_TIME) .paymentTypeCode("paymentTypeCode") .amountCents(100L) .notificationFeeCents(100L) @@ -35,8 +37,8 @@ public static Installment buildInstallment(){ .balance("balance") .transfers(List.of()) .debtor(buildPerson()) - .creationDate(date) - .updateDate(date) + .creationDate(OFFSET_DATE_TIME) + .updateDate(OFFSET_DATE_TIME) .updateOperatorExternalId(1L) .build(); } @@ -45,14 +47,14 @@ public static InstallmentNoPII buildInstallmentNoPII(){ return InstallmentNoPII.builder() .installmentId(1L) .paymentOptionId(1L) - .status("status") + .status("TO_SYNC") .iupdPagopa("iupdPagoPa") .iud("iud") .iuv("iuv") .iur("iur") .iuf("iuf") .nav("nav") - .dueDate(date) + .dueDate(OFFSET_DATE_TIME) .paymentTypeCode("paymentTypeCode") .amountCents(100L) .notificationFeeCents(100L) @@ -62,8 +64,8 @@ public static InstallmentNoPII buildInstallmentNoPII(){ .debtorEntityType('F') .debtorFiscalCodeHash(new byte[] {}) .balance("balance") - .creationDate(date) - .updateDate(date) + .creationDate(OFFSET_DATE_TIME) + .updateDate(OFFSET_DATE_TIME) .updateOperatorExternalId(1L) .build(); } @@ -74,4 +76,32 @@ public static InstallmentPIIDTO buildInstallmentPIIDTO(){ .build(); } + public static InstallmentDTO buildInstallmentDTO() { + List transfers = new ArrayList<>(); + transfers.add(buildTransferDTO()); + return InstallmentDTO.builder() + .installmentId(1L) + .paymentOptionId(1L) + .status("TO_SYNC") + .iud("iud") + .iuv("iuv") + .iur("iur") + .iuf("iuf") + .nav("nav") + .iupdPagopa("iupdPagopa") + .dueDate(OFFSET_DATE_TIME) + .paymentTypeCode("paymentTypeCode") + .amountCents(100L) + .notificationFeeCents(100L) + .remittanceInformation("remittanceInformation") + .humanFriendlyRemittanceInformation("humanFriendlyRemittanceInformation") + .balance("balance") + .legacyPaymentMetadata("legacyPaymentMetadata") + .debtor(buildPersonDTO()) + .transfers(transfers) + .creationDate(OFFSET_DATE_TIME) + .updateDate(OFFSET_DATE_TIME) + .build(); + } + } diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PaymentOptionFaker.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PaymentOptionFaker.java new file mode 100644 index 0000000..99fb3dd --- /dev/null +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PaymentOptionFaker.java @@ -0,0 +1,40 @@ +package it.gov.pagopa.pu.debtpositions.util.faker; + +import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionDTO; +import it.gov.pagopa.pu.debtpositions.enums.PaymentOptionType; +import it.gov.pagopa.pu.debtpositions.model.PaymentOption; + +import java.util.List; + +import static it.gov.pagopa.pu.debtpositions.util.TestUtils.OFFSET_DATE_TIME; +import static it.gov.pagopa.pu.debtpositions.util.faker.InstallmentFaker.buildInstallmentDTO; +import static it.gov.pagopa.pu.debtpositions.util.faker.InstallmentFaker.buildInstallmentNoPII; + +public class PaymentOptionFaker { + + public static PaymentOptionDTO buildPaymentOptionDTO() { + return PaymentOptionDTO.builder() + .paymentOptionId(1L) + .totalAmountCents(1L) + .status("TO_SYNC") + .multiDebtor(false) + .dueDate(OFFSET_DATE_TIME) + .description("description") + .paymentOptionType(PaymentOptionDTO.PaymentOptionTypeEnum.DOWN_PAYMENT) + .installments(List.of(buildInstallmentDTO())) + .build(); + } + + public static PaymentOption buildPaymentOption() { + return PaymentOption.builder() + .paymentOptionId(1L) + .totalAmountCents(1L) + .status("TO_SYNC") + .multiDebtor(false) + .dueDate(OFFSET_DATE_TIME) + .description("description") + .paymentOptionType(PaymentOptionType.DOWN_PAYMENT) + .installments(List.of(buildInstallmentNoPII())) + .build(); + } +} diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PersonFaker.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PersonFaker.java index 66ce868..d572f21 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PersonFaker.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PersonFaker.java @@ -1,6 +1,7 @@ package it.gov.pagopa.pu.debtpositions.util.faker; import it.gov.pagopa.pu.debtpositions.dto.Person; +import it.gov.pagopa.pu.debtpositions.dto.generated.PersonDTO; public class PersonFaker { @@ -18,4 +19,19 @@ public static Person buildPerson(){ .email("email@test.it") .build(); } + + public static PersonDTO buildPersonDTO() { + return PersonDTO.builder() + .entityType("entityType") + .fiscalCode("fiscalCode") + .fullName("fullName") + .address("address") + .civic("civic") + .postalCode("postalCode") + .location("location") + .province("province") + .nation("nation") + .email("email@test.it") + .build(); + } } diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/TransferFaker.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/TransferFaker.java new file mode 100644 index 0000000..3586219 --- /dev/null +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/TransferFaker.java @@ -0,0 +1,40 @@ +package it.gov.pagopa.pu.debtpositions.util.faker; + +import it.gov.pagopa.pu.debtpositions.dto.generated.TransferDTO; +import it.gov.pagopa.pu.debtpositions.model.Stamp; +import it.gov.pagopa.pu.debtpositions.model.Transfer; + +public class TransferFaker { + + public static TransferDTO buildTransferDTO(){ + return TransferDTO.builder() + .transferId(1L) + .orgFiscalCode("orgFiscalCode") + .orgName("orgName") + .amountCents(100L) + .remittanceInformation("remittanceInformation") + .stampType("stampType") + .stampHashDocument("stampHashDocument") + .stampProvincialResidence("stampProvincialResidence") + .iban("iban") + .postalIban("postalIban") + .category("category") + .transferIndex(1) + .build(); + } + + public static Transfer buildTransfer(){ + return Transfer.builder() + .transferId(1L) + .orgFiscalCode("orgFiscalCode") + .orgName("orgName") + .amountCents(100L) + .remittanceInformation("remittanceInformation") + .stamp(new Stamp()) + .iban("iban") + .postalIban("postalIban") + .category("category") + .transferIndex(1L) + .build(); + } +} From 40e3008bd0bf8cb73176e8e8c9676364f67235ff Mon Sep 17 00:00:00 2001 From: LarissaASLeite Date: Wed, 15 Jan 2025 11:02:16 +0100 Subject: [PATCH 02/17] P4ADEV-1744-add-api-finalize-sync-status --- openapi/p4pa-debt-position.openapi.yaml | 4 - .../DebtPositionControllerImpl.java | 2 +- .../mapper/DebtPositionMapper.java | 12 +-- .../mapper/InstallmentMapper.java | 8 -- .../mapper/PaymentOptionMapper.java | 6 -- .../pu/debtpositions/mapper/PersonMapper.java | 7 -- .../debtpositions/mapper/TransferMapper.java | 6 -- .../service/DebtPositionService.java | 2 +- .../service/DebtPositionServiceImpl.java | 10 +- .../service/DebtPositionServiceImplTest.java | 77 ++++++++++------ .../service/DebtPositionServiceTest.java | 71 -------------- .../util/faker/DebtPositionFaker.java | 92 ++++++++----------- .../util/faker/InstallmentFaker.java | 47 +++++----- .../util/faker/PaymentOptionFaker.java | 55 +++++------ 14 files changed, 147 insertions(+), 252 deletions(-) delete mode 100644 src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceTest.java diff --git a/openapi/p4pa-debt-position.openapi.yaml b/openapi/p4pa-debt-position.openapi.yaml index fee917d..62d5133 100644 --- a/openapi/p4pa-debt-position.openapi.yaml +++ b/openapi/p4pa-debt-position.openapi.yaml @@ -51,10 +51,6 @@ paths: responses: "200": description: Ok - content: - application/json: - schema: - $ref: '#/components/schemas/DebtPositionDTO' "400": description: Invalid request "500": diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerImpl.java b/src/main/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerImpl.java index 3b21d46..8ad3ccb 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerImpl.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerImpl.java @@ -16,7 +16,7 @@ public ResponseEntity createDebtPosition(DebtPositionDTO debtPo } @Override - public ResponseEntity finalizeSyncStatus(Long debtPositionId, Map requestBody) { + public ResponseEntity finalizeSyncStatus(Long debtPositionId, Map requestBody) { return DebtPositionApi.super.finalizeSyncStatus(debtPositionId, requestBody); } } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapper.java b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapper.java index ed77ed3..1da5455 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapper.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapper.java @@ -5,11 +5,13 @@ 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 org.mapstruct.Mapper; import org.springframework.data.util.Pair; import org.springframework.stereotype.Service; -import java.util.*; +import java.util.HashMap; +import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.stream.Collector; import java.util.stream.Collectors; @@ -56,9 +58,3 @@ public Pair> mapToModel(DebtPos } } -//@Mapper(componentModel = "spring", uses = {PaymentOptionMapper.class}) -//public interface DebtPositionMapper { -// -// DebtPositionDTO map(DebtPosition debtPosition); -//} - diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapper.java b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapper.java index 21af36c..74c8671 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapper.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapper.java @@ -2,8 +2,6 @@ import it.gov.pagopa.pu.debtpositions.dto.Installment; import it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentDTO; -import it.gov.pagopa.pu.debtpositions.model.InstallmentNoPII; -import org.mapstruct.Mapper; import org.springframework.stereotype.Service; @Service @@ -47,9 +45,3 @@ public Installment mapToModel(InstallmentDTO dto) { } } - -//@Mapper(componentModel = "spring", uses = {TransferMapper.class, PersonMapper.class}) -//public interface InstallmentMapper { -// -// InstallmentDTO map(InstallmentNoPII installment); -//} diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapper.java b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapper.java index d734d59..24e2271 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapper.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapper.java @@ -6,7 +6,6 @@ import it.gov.pagopa.pu.debtpositions.enums.PaymentOptionType; import it.gov.pagopa.pu.debtpositions.model.InstallmentNoPII; import it.gov.pagopa.pu.debtpositions.model.PaymentOption; -import org.mapstruct.Mapper; import org.springframework.data.util.Pair; import org.springframework.stereotype.Service; @@ -57,8 +56,3 @@ public Pair> mapToModel(Paymen return Pair.of(paymentOption, installmentMapping); } } -//@Mapper(componentModel = "spring", uses = {InstallmentMapper.class}) -//public interface PaymentOptionMapper { -// -// PaymentOptionDTO map(PaymentOption paymentOption); -//} diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PersonMapper.java b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PersonMapper.java index 17706e4..d44fe51 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PersonMapper.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PersonMapper.java @@ -2,7 +2,6 @@ import it.gov.pagopa.pu.debtpositions.dto.Person; import it.gov.pagopa.pu.debtpositions.dto.generated.PersonDTO; -import org.mapstruct.Mapper; import org.springframework.stereotype.Service; @Service @@ -24,9 +23,3 @@ public Person mapToModel(PersonDTO dto) { } } - -//@Mapper(componentModel = "spring") -//public interface PersonMapper { -// -// PersonDTO map(Person person); -//} diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/TransferMapper.java b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/TransferMapper.java index 075a17d..08437ac 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/TransferMapper.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/TransferMapper.java @@ -3,7 +3,6 @@ import it.gov.pagopa.pu.debtpositions.dto.generated.TransferDTO; import it.gov.pagopa.pu.debtpositions.model.Stamp; import it.gov.pagopa.pu.debtpositions.model.Transfer; -import org.mapstruct.Mapper; import org.springframework.stereotype.Service; @Service @@ -26,8 +25,3 @@ public Transfer mapToModel(TransferDTO dto) { } } -//@Mapper(componentModel = "spring") -//public interface TransferMapper { -// -// TransferDTO map(Transfer transfer); -//} diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionService.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionService.java index 405b1a3..58cb626 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionService.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionService.java @@ -8,5 +8,5 @@ public interface DebtPositionService { void saveDebtPosition(DebtPositionDTO debtPositionDTO); - DebtPositionDTO finalizeSyncStatus(Long debtPositionId, Map syncStatusDTO); + void finalizeSyncStatus(Long debtPositionId, Map syncStatusDTO); } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImpl.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImpl.java index 5a44643..0eed636 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImpl.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImpl.java @@ -2,7 +2,6 @@ import it.gov.pagopa.pu.debtpositions.dto.Installment; import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; -import it.gov.pagopa.pu.debtpositions.mapper.*; import it.gov.pagopa.pu.debtpositions.dto.generated.IudSyncStatusUpdateDTO; import it.gov.pagopa.pu.debtpositions.mapper.DebtPositionMapper; import it.gov.pagopa.pu.debtpositions.model.DebtPosition; @@ -11,9 +10,6 @@ import it.gov.pagopa.pu.debtpositions.repository.*; import jakarta.transaction.Transactional; import org.springframework.data.util.Pair; -import it.gov.pagopa.pu.debtpositions.repository.DebtPositionRepository; -import it.gov.pagopa.pu.debtpositions.repository.InstallmentNoPIIRepository; -import it.gov.pagopa.pu.debtpositions.repository.PaymentOptionRepository; import java.util.Map; @@ -30,7 +26,7 @@ public class DebtPositionServiceImpl implements DebtPositionService { public DebtPositionServiceImpl(DebtPositionRepository debtPositionRepository, PaymentOptionRepository paymentOptionRepository, InstallmentPIIRepository installmentRepository, TransferRepository transferRepository, - DebtPositionMapper debtPositionMapper) { + DebtPositionMapper debtPositionMapper, InstallmentNoPIIRepository installmentNoPIIRepository) { this.debtPositionRepository = debtPositionRepository; this.paymentOptionRepository = paymentOptionRepository; this.installmentRepository = installmentRepository; @@ -64,7 +60,7 @@ public void saveDebtPosition(DebtPositionDTO debtPositionDTO) { } @Override - public DebtPositionDTO finalizeSyncStatus(Long debtPositionId, Map syncStatusDTO) { + public void finalizeSyncStatus(Long debtPositionId, Map syncStatusDTO) { DebtPosition debtPosition = debtPositionRepository.findOneWithAllDataByDebtPositionId(debtPositionId); debtPosition.getPaymentOptions().stream() @@ -92,8 +88,6 @@ public DebtPositionDTO finalizeSyncStatus(Long debtPositionId, Map updateDebtPositionStatus(debtPosition)); - - return debtPositionMapper.map(debtPosition); } private void updatePaymentOptionStatus(PaymentOption paymentOption) { diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImplTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImplTest.java index 8425e99..5f0805f 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImplTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImplTest.java @@ -2,15 +2,13 @@ import it.gov.pagopa.pu.debtpositions.dto.Installment; import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; +import it.gov.pagopa.pu.debtpositions.dto.generated.IudSyncStatusUpdateDTO; import it.gov.pagopa.pu.debtpositions.mapper.*; 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.repository.DebtPositionRepository; -import it.gov.pagopa.pu.debtpositions.repository.InstallmentPIIRepository; -import it.gov.pagopa.pu.debtpositions.repository.PaymentOptionRepository; -import it.gov.pagopa.pu.debtpositions.repository.TransferRepository; +import it.gov.pagopa.pu.debtpositions.repository.*; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -19,6 +17,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.util.Pair; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeSet; @@ -34,28 +33,23 @@ class DebtPositionServiceImplTest { @Mock - private DebtPositionRepository debtPositionRepository; - + private DebtPositionRepository debtPositionRepositoryMock; @Mock - private PaymentOptionRepository paymentOptionRepository; - + private PaymentOptionRepository paymentOptionRepositoryMock; @Mock - private InstallmentPIIRepository installmentRepository; - + private InstallmentPIIRepository installmentRepositoryMock; @Mock - private TransferRepository transferRepository; - + private TransferRepository transferRepositoryMock; @Mock - private DebtPositionMapper debtPositionMapper; + private InstallmentNoPIIRepository installmentNoPIIRepositoryMock; + @Mock + private DebtPositionMapper debtPositionMapperMock; - private DebtPositionServiceImpl debtPositionService; + private DebtPositionService service; @BeforeEach - void setUp() { - debtPositionService = new DebtPositionServiceImpl( - debtPositionRepository, paymentOptionRepository, installmentRepository, transferRepository, - debtPositionMapper - ); + void setUp(){ + service = new DebtPositionServiceImpl(debtPositionRepositoryMock, paymentOptionRepositoryMock, installmentRepositoryMock, transferRepositoryMock, debtPositionMapperMock, installmentNoPIIRepositoryMock); } @Test @@ -85,18 +79,43 @@ void givenValidDebtPositionDTO_WhenSaveDebtPosition_ThenSaveAllEntities() { Transfer savedTransfer = new Transfer(); savedTransfer.setTransferId(1L); - Mockito.when(debtPositionMapper.mapToModel(debtPositionDTO)).thenReturn(mappedPair); - Mockito.when(debtPositionRepository.save(Mockito.any(DebtPosition.class))).thenReturn(savedDebtPosition); - Mockito.when(paymentOptionRepository.save(Mockito.any(PaymentOption.class))).thenReturn(savedPaymentOption); - Mockito.when(installmentRepository.save(Mockito.any(Installment.class))).thenReturn(savedInstallment.getInstallmentId()); - Mockito.when(transferRepository.save(Mockito.any(Transfer.class))).thenReturn(savedTransfer); + Mockito.when(debtPositionMapperMock.mapToModel(debtPositionDTO)).thenReturn(mappedPair); + Mockito.when(debtPositionRepositoryMock.save(Mockito.any(DebtPosition.class))).thenReturn(savedDebtPosition); + Mockito.when(paymentOptionRepositoryMock.save(Mockito.any(PaymentOption.class))).thenReturn(savedPaymentOption); + Mockito.when(installmentRepositoryMock.save(Mockito.any(Installment.class))).thenReturn(savedInstallment.getInstallmentId()); + Mockito.when(transferRepositoryMock.save(Mockito.any(Transfer.class))).thenReturn(savedTransfer); + + service.saveDebtPosition(debtPositionDTO); + + Mockito.verify(debtPositionRepositoryMock, Mockito.times(1)).save(debtPosition); + Mockito.verify(paymentOptionRepositoryMock, Mockito.times(1)).save(paymentOption); + Mockito.verify(installmentRepositoryMock, Mockito.times(1)).save(installment); + Mockito.verify(transferRepositoryMock, Mockito.times(1)).save(transfer); + } + + @Test + void givenFinalizeSyncStatusThenOk(){ + Long id = 1L; + String newStatus = "newStatus"; + DebtPosition debtPosition = buildDebtPosition(); + Mockito.when(debtPositionRepositoryMock.findOneWithAllDataByDebtPositionId(id)).thenReturn(debtPosition); + + Mockito.doNothing().when(installmentNoPIIRepositoryMock).updateStatus(id, newStatus); + + Mockito.doNothing().when(paymentOptionRepositoryMock).updateStatus(id, newStatus); + + Mockito.doNothing().when(debtPositionRepositoryMock).updateStatus(id, newStatus); + + + Map syncStatusDTO = new HashMap<>(); + IudSyncStatusUpdateDTO iudSyncStatusUpdateDTO = IudSyncStatusUpdateDTO.builder() + .newStatus(newStatus) + .iupdPagopa("iupdPagopa") + .build(); - debtPositionService.saveDebtPosition(debtPositionDTO); + syncStatusDTO.put("iud", iudSyncStatusUpdateDTO); - Mockito.verify(debtPositionRepository, Mockito.times(1)).save(debtPosition); - Mockito.verify(paymentOptionRepository, Mockito.times(1)).save(paymentOption); - Mockito.verify(installmentRepository, Mockito.times(1)).save(installment); - Mockito.verify(transferRepository, Mockito.times(1)).save(transfer); + service.finalizeSyncStatus(id, syncStatusDTO); } } diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceTest.java deleted file mode 100644 index 1d542cc..0000000 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceTest.java +++ /dev/null @@ -1,71 +0,0 @@ -package it.gov.pagopa.pu.debtpositions.service; - -import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; -import it.gov.pagopa.pu.debtpositions.dto.generated.IudSyncStatusUpdateDTO; -import it.gov.pagopa.pu.debtpositions.mapper.DebtPositionMapper; -import it.gov.pagopa.pu.debtpositions.model.DebtPosition; -import it.gov.pagopa.pu.debtpositions.repository.DebtPositionRepository; -import it.gov.pagopa.pu.debtpositions.repository.InstallmentNoPIIRepository; -import it.gov.pagopa.pu.debtpositions.repository.PaymentOptionRepository; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.util.HashMap; -import java.util.Map; - -import static it.gov.pagopa.pu.debtpositions.util.faker.DebtPositionFaker.buildDebtPosition; -import static it.gov.pagopa.pu.debtpositions.util.faker.DebtPositionFaker.buildDebtPositionDTO; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -@ExtendWith(MockitoExtension.class) -class DebtPositionServiceTest { - - @Mock - private DebtPositionRepository debtPositionRepositoryMock; - @Mock - private PaymentOptionRepository paymentOptionRepositoryMock; - @Mock - private InstallmentNoPIIRepository installmentNoPIIRepositoryMock; - @Mock - private DebtPositionMapper debtPositionMapperMock; - - private DebtPositionService service; - - @BeforeEach - void setUp(){ - service = new DebtPositionServiceImpl(debtPositionRepositoryMock, paymentOptionRepositoryMock, installmentNoPIIRepositoryMock, debtPositionMapperMock); - } - - @Test - void givenFinalizeSyncStatusThenOk(){ - Long id = 1L; - String newStatus = "newStatus"; - DebtPosition debtPosition = buildDebtPosition(); - Mockito.when(debtPositionRepositoryMock.findOneWithAllDataByDebtPositionId(id)).thenReturn(debtPosition); - - Mockito.doNothing().when(installmentNoPIIRepositoryMock).updateStatus(id, newStatus); - - Mockito.doNothing().when(paymentOptionRepositoryMock).updateStatus(id, newStatus); - - Mockito.doNothing().when(debtPositionRepositoryMock).updateStatus(id, newStatus); - - Mockito.when(debtPositionMapperMock.map(debtPosition)).thenReturn(buildDebtPositionDTO()); - - Map syncStatusDTO = new HashMap<>(); - IudSyncStatusUpdateDTO iudSyncStatusUpdateDTO = IudSyncStatusUpdateDTO.builder() - .newStatus(newStatus) - .iupdPagopa("iupdPagopa") - .build(); - - syncStatusDTO.put("iud", iudSyncStatusUpdateDTO); - - DebtPositionDTO debtPositionDTO = service.finalizeSyncStatus(id, syncStatusDTO); - System.out.println("debtPositionDTO: " + debtPositionDTO); - - assertNotNull(debtPositionDTO); - } -} diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/DebtPositionFaker.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/DebtPositionFaker.java index 5c25880..47291c3 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/DebtPositionFaker.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/DebtPositionFaker.java @@ -3,69 +3,53 @@ import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; import it.gov.pagopa.pu.debtpositions.model.DebtPosition; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; import java.util.List; import java.util.TreeSet; -import java.util.TreeSet; -import static it.gov.pagopa.pu.debtpositions.util.TestUtils.OFFSET_DATE_TIME; import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.buildPaymentOption; import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.buildPaymentOptionDTO; public class DebtPositionFaker { - public static DebtPositionDTO buildDebtPositionDTO() { - return DebtPositionDTO.builder() - .debtPositionId(1L) - .iupdOrg("iupdOrg") - .description("description") - .status("TO_SYNC") - .ingestionFlowFileId(1L) - .ingestionFlowFileLineNumber(1L) - .organizationId(1L) - .debtPositionTypeOrgId(1L) - .notificationDate(OFFSET_DATE_TIME) - .validityDate(OFFSET_DATE_TIME) - .flagIuvVolatile(false) - .creationDate(OFFSET_DATE_TIME) - .updateDate(OFFSET_DATE_TIME) - .paymentOptions(List.of(buildPaymentOptionDTO())) - .build(); - } + private static final OffsetDateTime DATE = OffsetDateTime.of(2025, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC); public static DebtPosition buildDebtPosition() { - return DebtPosition.builder() - .debtPositionId(1L) - .iupdOrg("iupdOrg") - .description("description") - .status("TO_SYNC") - .ingestionFlowFileId(1L) - .ingestionFlowFileLineNumber(1L) - .organizationId(1L) - .debtPositionTypeOrgId(1L) - .notificationDate(OFFSET_DATE_TIME) - .validityDate(OFFSET_DATE_TIME) - .flagIuvVolatile(false) - .creationDate(OFFSET_DATE_TIME) - .updateDate(OFFSET_DATE_TIME) - .paymentOptions(List.of(buildPaymentOption())) - .build(); + DebtPosition debtPosition = new DebtPosition(); + debtPosition.setDebtPositionId(1L); + debtPosition.setIupdOrg("IUPD_ORG"); + debtPosition.setDescription("Test Description"); + debtPosition.setStatus("ACTIVE"); + debtPosition.setIngestionFlowFileId(1001L); + debtPosition.setIngestionFlowFileLineNumber(10L); + debtPosition.setOrganizationId(500L); + debtPosition.setDebtPositionTypeOrgId(200L); + debtPosition.setNotificationDate(DATE); + debtPosition.setValidityDate(DATE); + debtPosition.setFlagIuvVolatile(true); + debtPosition.setCreationDate(DATE.toLocalDateTime()); + debtPosition.setUpdateDate(DATE.toLocalDateTime()); + debtPosition.setPaymentOptions(new TreeSet<>(List.of(buildPaymentOption()))); + return debtPosition; + } + + public static DebtPositionDTO buildDebtPositionDTO() { + DebtPositionDTO debtPositionDTO = new DebtPositionDTO(); + debtPositionDTO.setDebtPositionId(1L); + debtPositionDTO.setIupdOrg("IUPD_ORG"); + debtPositionDTO.setDescription("Test Description"); + debtPositionDTO.setStatus("ACTIVE"); + debtPositionDTO.setIngestionFlowFileId(1001L); + debtPositionDTO.setIngestionFlowFileLineNumber(10L); + debtPositionDTO.setOrganizationId(500L); + debtPositionDTO.setDebtPositionTypeOrgId(200L); + debtPositionDTO.setNotificationDate(DATE); + debtPositionDTO.setValidityDate(DATE); + debtPositionDTO.setFlagIuvVolatile(true); + debtPositionDTO.setCreationDate(DATE); + debtPositionDTO.setUpdateDate(DATE); + debtPositionDTO.setPaymentOptions(List.of(buildPaymentOptionDTO())); + return debtPositionDTO; } -// public static DebtPosition buildDebtPosition() { -// DebtPosition debtPosition = new DebtPosition(); -// debtPosition.setDebtPositionId(1L); -// debtPosition.setIupdOrg("IUPD_ORG"); -// debtPosition.setDescription("Test Description"); -// debtPosition.setStatus("ACTIVE"); -// debtPosition.setIngestionFlowFileId(1001L); -// debtPosition.setIngestionFlowFileLineNumber(10L); -// debtPosition.setOrganizationId(500L); -// debtPosition.setDebtPositionTypeOrgId(200L); -// debtPosition.setNotificationDate(DATE); -// debtPosition.setValidityDate(DATE); -// debtPosition.setFlagIuvVolatile(true); -// debtPosition.setCreationDate(DATE.toLocalDateTime()); -// debtPosition.setUpdateDate(DATE.toLocalDateTime()); -// debtPosition.setPaymentOptions(new TreeSet<>(List.of(buildPaymentOption()))); -// return debtPosition; -// } } diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java index 9b39de9..8e4b451 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java @@ -3,31 +3,34 @@ import it.gov.pagopa.pu.debtpositions.dto.Installment; import it.gov.pagopa.pu.debtpositions.dto.InstallmentPIIDTO; import it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentDTO; -import it.gov.pagopa.pu.debtpositions.dto.generated.TransferDTO; import it.gov.pagopa.pu.debtpositions.model.InstallmentNoPII; -import java.util.ArrayList; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; import java.util.List; -import static it.gov.pagopa.pu.debtpositions.util.TestUtils.OFFSET_DATE_TIME; import static it.gov.pagopa.pu.debtpositions.util.faker.PersonFaker.buildPerson; import static it.gov.pagopa.pu.debtpositions.util.faker.PersonFaker.buildPersonDTO; -import static it.gov.pagopa.pu.debtpositions.util.faker.TransferFaker.buildTransferDTO; +import static it.gov.pagopa.pu.debtpositions.util.faker.TransferFaker.buildTransfer; public class InstallmentFaker { + static LocalDateTime date = LocalDateTime.of(2025, 1, 1, 0,0,0, 0); + static OffsetDateTime offsetDateTime = OffsetDateTime.of(date, ZoneOffset.UTC); + public static Installment buildInstallment(){ return Installment.builder() .installmentId(1L) .paymentOptionId(1L) - .status("TO_SYNC") + .status("status") .iupdPagopa("iupdPagoPa") .iud("iud") .iuv("iuv") .iur("iur") .iuf("iuf") .nav("nav") - .dueDate(OFFSET_DATE_TIME) + .dueDate(offsetDateTime) .paymentTypeCode("paymentTypeCode") .amountCents(100L) .notificationFeeCents(100L) @@ -37,9 +40,9 @@ public static Installment buildInstallment(){ .balance("balance") .transfers(List.of(buildTransfer())) .debtor(buildPerson()) - .creationDate(OFFSET_DATE_TIME) - .updateDate(OFFSET_DATE_TIME) - .updateOperatorExternalId(1L) + .creationDate(date) + .updateDate(date) + .updateOperatorExternalId("OPERATOREXTERNALUSERID") .build(); } @@ -47,14 +50,14 @@ public static InstallmentNoPII buildInstallmentNoPII(){ return InstallmentNoPII.builder() .installmentId(1L) .paymentOptionId(1L) - .status("TO_SYNC") + .status("status") .iupdPagopa("iupdPagoPa") .iud("iud") .iuv("iuv") .iur("iur") .iuf("iuf") .nav("nav") - .dueDate(OFFSET_DATE_TIME) + .dueDate(offsetDateTime) .paymentTypeCode("paymentTypeCode") .amountCents(100L) .notificationFeeCents(100L) @@ -64,9 +67,9 @@ public static InstallmentNoPII buildInstallmentNoPII(){ .debtorEntityType('F') .debtorFiscalCodeHash(new byte[] {}) .balance("balance") - .creationDate(OFFSET_DATE_TIME) - .updateDate(OFFSET_DATE_TIME) - .updateOperatorExternalId(1L) + .creationDate(date) + .updateDate(date) + .updateOperatorExternalId("OPERATOREXTERNALID") .build(); } @@ -103,30 +106,28 @@ public static Installment buildInstallmentNoUpdate(){ } public static InstallmentDTO buildInstallmentDTO() { - List transfers = new ArrayList<>(); - transfers.add(buildTransferDTO()); return InstallmentDTO.builder() .installmentId(1L) .paymentOptionId(1L) - .status("TO_SYNC") + .status("status") + .iupdPagopa("iupdPagoPa") .iud("iud") .iuv("iuv") .iur("iur") .iuf("iuf") .nav("nav") - .iupdPagopa("iupdPagopa") - .dueDate(OFFSET_DATE_TIME) + .dueDate(date.atOffset(ZoneOffset.UTC)) .paymentTypeCode("paymentTypeCode") .amountCents(100L) .notificationFeeCents(100L) .remittanceInformation("remittanceInformation") + .legacyPaymentMetadata("legacyPaymentMetadata") .humanFriendlyRemittanceInformation("humanFriendlyRemittanceInformation") .balance("balance") - .legacyPaymentMetadata("legacyPaymentMetadata") .debtor(buildPersonDTO()) - .transfers(transfers) - .creationDate(OFFSET_DATE_TIME) - .updateDate(OFFSET_DATE_TIME) + .transfers(List.of()) + .creationDate(date.atOffset(ZoneOffset.UTC)) + .updateDate(date.atOffset(ZoneOffset.UTC)) .build(); } diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PaymentOptionFaker.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PaymentOptionFaker.java index 99fb3dd..3c09bd4 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PaymentOptionFaker.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PaymentOptionFaker.java @@ -4,37 +4,40 @@ import it.gov.pagopa.pu.debtpositions.enums.PaymentOptionType; import it.gov.pagopa.pu.debtpositions.model.PaymentOption; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; import java.util.List; - -import static it.gov.pagopa.pu.debtpositions.util.TestUtils.OFFSET_DATE_TIME; -import static it.gov.pagopa.pu.debtpositions.util.faker.InstallmentFaker.buildInstallmentDTO; -import static it.gov.pagopa.pu.debtpositions.util.faker.InstallmentFaker.buildInstallmentNoPII; +import java.util.TreeSet; public class PaymentOptionFaker { - public static PaymentOptionDTO buildPaymentOptionDTO() { - return PaymentOptionDTO.builder() - .paymentOptionId(1L) - .totalAmountCents(1L) - .status("TO_SYNC") - .multiDebtor(false) - .dueDate(OFFSET_DATE_TIME) - .description("description") - .paymentOptionType(PaymentOptionDTO.PaymentOptionTypeEnum.DOWN_PAYMENT) - .installments(List.of(buildInstallmentDTO())) - .build(); - } + private static final OffsetDateTime DATE = OffsetDateTime.of(2025, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC); public static PaymentOption buildPaymentOption() { - return PaymentOption.builder() - .paymentOptionId(1L) - .totalAmountCents(1L) - .status("TO_SYNC") - .multiDebtor(false) - .dueDate(OFFSET_DATE_TIME) - .description("description") - .paymentOptionType(PaymentOptionType.DOWN_PAYMENT) - .installments(List.of(buildInstallmentNoPII())) - .build(); + PaymentOption paymentOption = new PaymentOption(); + paymentOption.setPaymentOptionId(1L); + paymentOption.setDebtPositionId(1L); + paymentOption.setTotalAmountCents(2000L); + paymentOption.setDueDate(DATE); + paymentOption.setStatus("PENDING"); + paymentOption.setMultiDebtor(true); + paymentOption.setDescription("Payment description"); + paymentOption.setPaymentOptionType(PaymentOptionType.SINGLE_INSTALLMENT); + paymentOption.setInstallments(new TreeSet<>()); + return paymentOption; + } + + public static PaymentOptionDTO buildPaymentOptionDTO() { + PaymentOptionDTO paymentOptionDTO = new PaymentOptionDTO(); + paymentOptionDTO.setPaymentOptionId(1L); + paymentOptionDTO.setDebtPositionId(1L); + paymentOptionDTO.setTotalAmountCents(2000L); + paymentOptionDTO.setDueDate(DATE); + paymentOptionDTO.setStatus("PENDING"); + paymentOptionDTO.setMultiDebtor(true); + paymentOptionDTO.setDescription("Payment description"); + paymentOptionDTO.setPaymentOptionType(PaymentOptionDTO.PaymentOptionTypeEnum.SINGLE_INSTALLMENT); + paymentOptionDTO.setInstallments(List.of()); + return paymentOptionDTO; } } From 0d13047b8e534c665844f103283159c622aede53 Mon Sep 17 00:00:00 2001 From: LarissaASLeite Date: Wed, 15 Jan 2025 16:35:15 +0100 Subject: [PATCH 03/17] P4ADEV-1744-add-api-finalize-sync-status --- .../DebtPositionControllerImpl.java | 11 ++- .../service/DebtPositionServiceImpl.java | 78 +++++++++---------- .../DebtPositionControllerTest.java | 56 +++++++++++++ .../service/DebtPositionServiceImplTest.java | 71 +++++++++++++++-- .../util/faker/DebtPositionFaker.java | 3 +- .../util/faker/InstallmentFaker.java | 8 +- .../util/faker/PaymentOptionFaker.java | 7 +- 7 files changed, 177 insertions(+), 57 deletions(-) create mode 100644 src/test/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerTest.java diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerImpl.java b/src/main/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerImpl.java index 8ad3ccb..332bd1f 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerImpl.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerImpl.java @@ -3,6 +3,8 @@ import it.gov.pagopa.pu.debtpositions.controller.generated.DebtPositionApi; import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; import it.gov.pagopa.pu.debtpositions.dto.generated.IudSyncStatusUpdateDTO; +import it.gov.pagopa.pu.debtpositions.service.DebtPositionService; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RestController; @@ -10,6 +12,12 @@ @RestController public class DebtPositionControllerImpl implements DebtPositionApi { + private final DebtPositionService debtPositionService; + + public DebtPositionControllerImpl(DebtPositionService debtPositionService) { + this.debtPositionService = debtPositionService; + } + @Override public ResponseEntity createDebtPosition(DebtPositionDTO debtPositionDTO) { return DebtPositionApi.super.createDebtPosition(debtPositionDTO); @@ -17,6 +25,7 @@ public ResponseEntity createDebtPosition(DebtPositionDTO debtPo @Override public ResponseEntity finalizeSyncStatus(Long debtPositionId, Map requestBody) { - return DebtPositionApi.super.finalizeSyncStatus(debtPositionId, requestBody); + debtPositionService.finalizeSyncStatus(debtPositionId, requestBody); + return new ResponseEntity<>(HttpStatus.OK); } } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImpl.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImpl.java index 0eed636..18a1190 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImpl.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImpl.java @@ -11,7 +11,10 @@ import jakarta.transaction.Transactional; import org.springframework.data.util.Pair; +import java.util.List; import java.util.Map; +import java.util.Optional; +import java.util.stream.Stream; import static it.gov.pagopa.pu.debtpositions.enums.DebtPositionStatus.TO_SYNC; @@ -63,53 +66,46 @@ public void saveDebtPosition(DebtPositionDTO debtPositionDTO) { public void finalizeSyncStatus(Long debtPositionId, Map syncStatusDTO) { DebtPosition debtPosition = debtPositionRepository.findOneWithAllDataByDebtPositionId(debtPositionId); - debtPosition.getPaymentOptions().stream() - .filter(paymentOption -> { - boolean anyUpdated = paymentOption.getInstallments().stream() - .filter(installment -> TO_SYNC.name().equals(installment.getStatus())) - .filter(installment -> syncStatusDTO.containsKey(installment.getIud())) - .filter(installment -> installment.getIupdPagopa().equals(syncStatusDTO.get(installment.getIud()).getIupdPagopa())) - .map(installment -> { - IudSyncStatusUpdateDTO updateDTO = syncStatusDTO.get(installment.getIud()); - installment.setStatus(updateDTO.getNewStatus()); - installmentNoPIIRepository.updateStatus( - installment.getInstallmentId(), - updateDTO.getNewStatus() - ); - return true; - }) - .findAny() - .orElse(false); - - if (anyUpdated) { - updatePaymentOptionStatus(paymentOption); - } - return anyUpdated; - }) - .findAny() - .ifPresent(op -> updateDebtPositionStatus(debtPosition)); + debtPosition.getPaymentOptions().forEach(paymentOption -> + paymentOption.getInstallments().stream() + .filter(installment -> TO_SYNC.name().equals(installment.getStatus())) + .filter(installment -> syncStatusDTO.containsKey(installment.getIud())) + .filter(installment -> installment.getIupdPagopa().equals(syncStatusDTO.get(installment.getIud()).getIupdPagopa())) + .forEach(installment -> { + IudSyncStatusUpdateDTO updateDTO = syncStatusDTO.get(installment.getIud()); + installment.setStatus(updateDTO.getNewStatus()); + installmentNoPIIRepository.updateStatus( + installment.getInstallmentId(), + updateDTO.getNewStatus() + ); + })); + + debtPosition.getPaymentOptions().forEach(this::updatePaymentOptionStatus); + + updateDebtPositionStatus(debtPosition); + } + + private Optional verifyStatusUniqueness(Stream stream) { + List distinctItems = stream.distinct().toList(); + return distinctItems.size() == 1 + ? Optional.of(distinctItems.getFirst()) + : Optional.empty(); } private void updatePaymentOptionStatus(PaymentOption paymentOption) { - paymentOption.getInstallments().stream() - .map(InstallmentNoPII::getStatus) - .distinct() - .reduce((first, second) -> null) - .ifPresent(unifiedStatus -> { - paymentOption.setStatus(unifiedStatus); - paymentOptionRepository.updateStatus(paymentOption.getPaymentOptionId(), unifiedStatus); - }); + verifyStatusUniqueness(paymentOption.getInstallments().stream().map(InstallmentNoPII::getStatus)) + .ifPresent(status -> { + paymentOption.setStatus(status); + paymentOptionRepository.updateStatus(paymentOption.getPaymentOptionId(), status); + }); } private void updateDebtPositionStatus(DebtPosition debtPosition) { - debtPosition.getPaymentOptions().stream() - .map(PaymentOption::getStatus) - .distinct() - .reduce((first, second) -> null) - .ifPresent(unifiedStatus -> { - debtPosition.setStatus(unifiedStatus); - debtPositionRepository.updateStatus(debtPosition.getDebtPositionId(), unifiedStatus); - }); + verifyStatusUniqueness(debtPosition.getPaymentOptions().stream().map(PaymentOption::getStatus)) + .ifPresent(status -> { + debtPosition.setStatus(status); + debtPositionRepository.updateStatus(debtPosition.getDebtPositionId(), status); + }); } } diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerTest.java new file mode 100644 index 0000000..ecf6c91 --- /dev/null +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerTest.java @@ -0,0 +1,56 @@ +package it.gov.pagopa.pu.debtpositions.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import it.gov.pagopa.pu.debtpositions.dto.generated.IudSyncStatusUpdateDTO; +import it.gov.pagopa.pu.debtpositions.service.DebtPositionService; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.bean.override.mockito.MockitoBean; +import org.springframework.test.web.servlet.MockMvc; + +import java.util.HashMap; +import java.util.Map; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +@WebMvcTest(DebtPositionControllerImpl.class) +@AutoConfigureMockMvc(addFilters = false) +class DebtPositionControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @MockitoBean + private DebtPositionService service; + + @Test + void whenFinalizeSyncStatusThenOk() throws Exception { + Long id = 1L; + String newStatus = "UNPAID"; + + Map syncStatusDTO = new HashMap<>(); + IudSyncStatusUpdateDTO iudSyncStatusUpdateDTO = IudSyncStatusUpdateDTO.builder() + .newStatus(newStatus) + .iupdPagopa("iupdPagoPa") + .build(); + + syncStatusDTO.put("iud", iudSyncStatusUpdateDTO); + + Mockito.doNothing().when(service).finalizeSyncStatus(id, syncStatusDTO); + + mockMvc.perform( + put("/sync/status/1") + .contentType(MediaType.APPLICATION_JSON_VALUE) + .content(objectMapper.writeValueAsString(syncStatusDTO))) + .andExpect(status().isOk()) + .andReturn(); + } +} diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImplTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImplTest.java index 5f0805f..857d33f 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImplTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImplTest.java @@ -3,7 +3,7 @@ import it.gov.pagopa.pu.debtpositions.dto.Installment; import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; import it.gov.pagopa.pu.debtpositions.dto.generated.IudSyncStatusUpdateDTO; -import it.gov.pagopa.pu.debtpositions.mapper.*; +import it.gov.pagopa.pu.debtpositions.mapper.DebtPositionMapper; import it.gov.pagopa.pu.debtpositions.model.DebtPosition; import it.gov.pagopa.pu.debtpositions.model.InstallmentNoPII; import it.gov.pagopa.pu.debtpositions.model.PaymentOption; @@ -28,6 +28,9 @@ import static it.gov.pagopa.pu.debtpositions.util.faker.InstallmentFaker.buildInstallmentNoPII; import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.buildPaymentOption; import static it.gov.pagopa.pu.debtpositions.util.faker.TransferFaker.buildTransfer; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.mockito.Mockito.verify; @ExtendWith(MockitoExtension.class) class DebtPositionServiceImplTest { @@ -87,17 +90,19 @@ void givenValidDebtPositionDTO_WhenSaveDebtPosition_ThenSaveAllEntities() { service.saveDebtPosition(debtPositionDTO); - Mockito.verify(debtPositionRepositoryMock, Mockito.times(1)).save(debtPosition); - Mockito.verify(paymentOptionRepositoryMock, Mockito.times(1)).save(paymentOption); - Mockito.verify(installmentRepositoryMock, Mockito.times(1)).save(installment); - Mockito.verify(transferRepositoryMock, Mockito.times(1)).save(transfer); + verify(debtPositionRepositoryMock, Mockito.times(1)).save(debtPosition); + verify(paymentOptionRepositoryMock, Mockito.times(1)).save(paymentOption); + verify(installmentRepositoryMock, Mockito.times(1)).save(installment); + verify(transferRepositoryMock, Mockito.times(1)).save(transfer); } @Test void givenFinalizeSyncStatusThenOk(){ + // Given Long id = 1L; - String newStatus = "newStatus"; + String newStatus = "UNPAID"; DebtPosition debtPosition = buildDebtPosition(); + Mockito.when(debtPositionRepositoryMock.findOneWithAllDataByDebtPositionId(id)).thenReturn(debtPosition); Mockito.doNothing().when(installmentNoPIIRepositoryMock).updateStatus(id, newStatus); @@ -106,16 +111,68 @@ void givenFinalizeSyncStatusThenOk(){ Mockito.doNothing().when(debtPositionRepositoryMock).updateStatus(id, newStatus); + Map syncStatusDTO = new HashMap<>(); + IudSyncStatusUpdateDTO iudSyncStatusUpdateDTO = IudSyncStatusUpdateDTO.builder() + .newStatus(newStatus) + .iupdPagopa("iupdPagoPa") + .build(); + + syncStatusDTO.put("iud", iudSyncStatusUpdateDTO); + + // When + service.finalizeSyncStatus(id, syncStatusDTO); + System.out.println("debtPosition: " + debtPosition); + + // Then + verify(debtPositionRepositoryMock).findOneWithAllDataByDebtPositionId(id); + verify(installmentNoPIIRepositoryMock).updateStatus(id, newStatus); + verify(paymentOptionRepositoryMock).updateStatus(id, newStatus); + verify(debtPositionRepositoryMock).updateStatus(id, newStatus); + + assertEquals(newStatus, debtPosition.getStatus()); + assertEquals(newStatus, debtPosition.getPaymentOptions().getFirst().getStatus()); + assertEquals(newStatus, debtPosition.getPaymentOptions().getFirst().getInstallments().getFirst().getStatus()); + } + + @Test + void givenFinalizeSyncStatusWhenDifferentStatusThenOk(){ + // Given + Long id = 1L; + String newStatus = "UNPAID"; + DebtPosition debtPosition = buildDebtPosition(); + InstallmentNoPII installment = InstallmentNoPII.builder() + .installmentId(2L) + .paymentOptionId(1L) + .status("status") + .iupdPagopa("iupdPagoPa1") + .iud("iud1").build(); + + debtPosition.getPaymentOptions().getFirst().setInstallments(new TreeSet<>(List.of(buildInstallmentNoPII(), installment))); + + Mockito.when(debtPositionRepositoryMock.findOneWithAllDataByDebtPositionId(id)).thenReturn(debtPosition); + + Mockito.doNothing().when(installmentNoPIIRepositoryMock).updateStatus(id, newStatus); Map syncStatusDTO = new HashMap<>(); IudSyncStatusUpdateDTO iudSyncStatusUpdateDTO = IudSyncStatusUpdateDTO.builder() .newStatus(newStatus) - .iupdPagopa("iupdPagopa") + .iupdPagopa("iupdPagoPa") .build(); syncStatusDTO.put("iud", iudSyncStatusUpdateDTO); + // When service.finalizeSyncStatus(id, syncStatusDTO); + System.out.println("debtPosition: " + debtPosition); + + // Then + verify(debtPositionRepositoryMock).findOneWithAllDataByDebtPositionId(id); + verify(installmentNoPIIRepositoryMock).updateStatus(id, newStatus); + + assertNotEquals(newStatus, debtPosition.getStatus()); + assertNotEquals(newStatus, debtPosition.getPaymentOptions().getFirst().getStatus()); + assertEquals(newStatus, debtPosition.getPaymentOptions().getFirst().getInstallments().getFirst().getStatus()); + assertNotEquals(newStatus, debtPosition.getPaymentOptions().getFirst().getInstallments().getLast().getStatus()); } } diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/DebtPositionFaker.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/DebtPositionFaker.java index 47291c3..01efd1e 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/DebtPositionFaker.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/DebtPositionFaker.java @@ -8,8 +8,7 @@ import java.util.List; import java.util.TreeSet; -import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.buildPaymentOption; -import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.buildPaymentOptionDTO; +import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.*; public class DebtPositionFaker { diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java index 8e4b451..1034bc5 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java @@ -23,7 +23,7 @@ public static Installment buildInstallment(){ return Installment.builder() .installmentId(1L) .paymentOptionId(1L) - .status("status") + .status("TO_SYNC") .iupdPagopa("iupdPagoPa") .iud("iud") .iuv("iuv") @@ -50,7 +50,7 @@ public static InstallmentNoPII buildInstallmentNoPII(){ return InstallmentNoPII.builder() .installmentId(1L) .paymentOptionId(1L) - .status("status") + .status("TO_SYNC") .iupdPagopa("iupdPagoPa") .iud("iud") .iuv("iuv") @@ -83,7 +83,7 @@ public static Installment buildInstallmentNoUpdate(){ return Installment.builder() .installmentId(1L) .paymentOptionId(1L) - .status("status") + .status("TO_SYNC") .iupdPagopa("iupdPagoPa") .iud("iud") .iuv("iuv") @@ -109,7 +109,7 @@ public static InstallmentDTO buildInstallmentDTO() { return InstallmentDTO.builder() .installmentId(1L) .paymentOptionId(1L) - .status("status") + .status("TO_SYNC") .iupdPagopa("iupdPagoPa") .iud("iud") .iuv("iuv") diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PaymentOptionFaker.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PaymentOptionFaker.java index 3c09bd4..c51ceb3 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PaymentOptionFaker.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PaymentOptionFaker.java @@ -9,6 +9,8 @@ import java.util.List; import java.util.TreeSet; +import static it.gov.pagopa.pu.debtpositions.util.faker.InstallmentFaker.*; + public class PaymentOptionFaker { private static final OffsetDateTime DATE = OffsetDateTime.of(2025, 1, 1, 0, 0, 0, 0, ZoneOffset.UTC); @@ -23,10 +25,11 @@ public static PaymentOption buildPaymentOption() { paymentOption.setMultiDebtor(true); paymentOption.setDescription("Payment description"); paymentOption.setPaymentOptionType(PaymentOptionType.SINGLE_INSTALLMENT); - paymentOption.setInstallments(new TreeSet<>()); + paymentOption.setInstallments(new TreeSet<>(List.of(buildInstallmentNoPII()))); return paymentOption; } + public static PaymentOptionDTO buildPaymentOptionDTO() { PaymentOptionDTO paymentOptionDTO = new PaymentOptionDTO(); paymentOptionDTO.setPaymentOptionId(1L); @@ -37,7 +40,7 @@ public static PaymentOptionDTO buildPaymentOptionDTO() { paymentOptionDTO.setMultiDebtor(true); paymentOptionDTO.setDescription("Payment description"); paymentOptionDTO.setPaymentOptionType(PaymentOptionDTO.PaymentOptionTypeEnum.SINGLE_INSTALLMENT); - paymentOptionDTO.setInstallments(List.of()); + paymentOptionDTO.setInstallments(List.of(buildInstallmentDTO())); return paymentOptionDTO; } } From 06e1503da977b7b54f9a540e59cbdc0c8641de08 Mon Sep 17 00:00:00 2001 From: LarissaASLeite Date: Wed, 15 Jan 2025 16:44:36 +0100 Subject: [PATCH 04/17] P4ADEV-1744-add-api-finalize-sync-status --- openapi/generated.openapi.json | 638 +++++++++++------- .../service/DebtPositionServiceImpl.java | 2 + 2 files changed, 410 insertions(+), 230 deletions(-) diff --git a/openapi/generated.openapi.json b/openapi/generated.openapi.json index ff37dd7..8d47c74 100644 --- a/openapi/generated.openapi.json +++ b/openapi/generated.openapi.json @@ -809,6 +809,34 @@ } } }, + "/crud/debt-positions/search/updateStatus" : { + "get" : { + "tags" : [ "debt-position-search-controller" ], + "operationId" : "crud-debt-positions-updateStatus", + "parameters" : [ { + "name" : "debtPositionId", + "in" : "query", + "schema" : { + "type" : "integer", + "format" : "int64" + } + }, { + "name" : "status", + "in" : "query", + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + }, + "404" : { + "description" : "Not Found" + } + } + } + }, "/crud/debt-positions/{id}" : { "get" : { "tags" : [ "debt-position-entity-controller" ], @@ -1261,6 +1289,74 @@ } } }, + "/crud/installments/search/findByIudAndIupdPagopaAndStatus" : { + "get" : { + "tags" : [ "installment-no-pii-search-controller" ], + "operationId" : "crud-installments-findByIudAndIupdPagopaAndStatus", + "parameters" : [ { + "name" : "iud", + "in" : "query", + "schema" : { + "type" : "string" + } + }, { + "name" : "iupdPagopa", + "in" : "query", + "schema" : { + "type" : "string" + } + }, { + "name" : "status", + "in" : "query", + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK", + "content" : { + "application/hal+json" : { + "schema" : { + "$ref" : "#/components/schemas/InstallmentNoPII" + } + } + } + }, + "404" : { + "description" : "Not Found" + } + } + } + }, + "/crud/installments/search/updateStatus" : { + "get" : { + "tags" : [ "installment-no-pii-search-controller" ], + "operationId" : "crud-installments-updateStatus", + "parameters" : [ { + "name" : "installmentId", + "in" : "query", + "schema" : { + "type" : "integer", + "format" : "int64" + } + }, { + "name" : "status", + "in" : "query", + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + }, + "404" : { + "description" : "Not Found" + } + } + } + }, "/crud/installments/{id}" : { "get" : { "tags" : [ "installment-no-pii-entity-controller" ], @@ -1713,6 +1809,34 @@ } } }, + "/crud/payment-options/search/updateStatus" : { + "get" : { + "tags" : [ "payment-option-search-controller" ], + "operationId" : "crud-payment-options-updateStatus", + "parameters" : [ { + "name" : "paymentOptionId", + "in" : "query", + "schema" : { + "type" : "integer", + "format" : "int64" + } + }, { + "name" : "status", + "in" : "query", + "schema" : { + "type" : "string" + } + } ], + "responses" : { + "200" : { + "description" : "OK" + }, + "404" : { + "description" : "Not Found" + } + } + } + }, "/crud/payment-options/{id}" : { "get" : { "tags" : [ "payment-option-entity-controller" ], @@ -2769,6 +2893,49 @@ } } }, + "/sync/status/{debtPositionId}" : { + "put" : { + "tags" : [ "debt-position" ], + "operationId" : "finalizeSyncStatus", + "parameters" : [ { + "name" : "debtPositionId", + "in" : "path", + "description" : "The ID of the debt position", + "required" : true, + "schema" : { + "type" : "integer", + "format" : "int64" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "additionalProperties" : { + "$ref" : "#/components/schemas/IudSyncStatusUpdateDTO" + } + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "description" : "Ok" + }, + "400" : { + "description" : "Invalid request" + }, + "500" : { + "description" : "Internal server error" + } + }, + "security" : [ { + "BearerAuth" : [ ] + } ] + } + }, "/debt-positions" : { "post" : { "tags" : [ "debt-position" ], @@ -2903,7 +3070,21 @@ } } }, - "DebtPositionTypeOrg" : { + "Stamp" : { + "type" : "object", + "properties" : { + "stampType" : { + "type" : "string" + }, + "stampHashDocument" : { + "type" : "string" + }, + "stampProvincialResidence" : { + "type" : "string" + } + } + }, + "Transfer" : { "type" : "object", "properties" : { "creationDate" : { @@ -2917,87 +3098,43 @@ "updateOperatorExternalId" : { "type" : "string" }, - "debtPositionTypeOrgId" : { - "type" : "integer", - "format" : "int64" - }, - "debtPositionTypeId" : { + "transferId" : { "type" : "integer", "format" : "int64" }, - "organizationId" : { + "installmentId" : { "type" : "integer", "format" : "int64" }, - "balance" : { - "type" : "string" - }, - "code" : { - "type" : "string" - }, - "description" : { - "type" : "string" - }, - "iban" : { - "type" : "string" - }, - "postalIban" : { - "type" : "string" - }, - "postalAccountCode" : { - "type" : "string" - }, - "holderPostalCc" : { - "type" : "string" - }, - "orgSector" : { + "orgFiscalCode" : { "type" : "string" }, - "xsdDefinitionRef" : { + "orgName" : { "type" : "string" }, "amountCents" : { "type" : "integer", "format" : "int64" }, - "externalPaymentUrl" : { + "remittanceInformation" : { "type" : "string" }, - "flagAnonymousFiscalCode" : { - "type" : "boolean" - }, - "flagMandatoryDueDate" : { - "type" : "boolean" - }, - "flagSpontaneous" : { - "type" : "boolean" - }, - "flagNotifyIo" : { - "type" : "boolean" + "stamp" : { + "$ref" : "#/components/schemas/Stamp" }, - "ioTemplateMessage" : { + "iban" : { "type" : "string" }, - "flagActive" : { - "type" : "boolean" - }, - "flagNotifyOutcomePush" : { - "type" : "boolean" - }, - "notifyOutcomePushOrgSilServiceId" : { - "type" : "integer", - "format" : "int64" + "postalIban" : { + "type" : "string" }, - "flagAmountActualization" : { - "type" : "boolean" + "category" : { + "type" : "string" }, - "amountActualizationOrgSilServiceId" : { + "transferIndex" : { "type" : "integer", "format" : "int64" }, - "flagExternal" : { - "type" : "boolean" - }, "_links" : { "$ref" : "#/components/schemas/Links" } @@ -3024,16 +3161,16 @@ } } }, - "PagedModelDebtPositionTypeOrg" : { + "PagedModelTransfer" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "debtPositionTypeOrgs" : { + "transfers" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/DebtPositionTypeOrg" + "$ref" : "#/components/schemas/Transfer" } } } @@ -3046,7 +3183,7 @@ } } }, - "DebtPositionTypeOrgOperators" : { + "ReceiptNoPII" : { "type" : "object", "properties" : { "creationDate" : { @@ -3060,71 +3197,19 @@ "updateOperatorExternalId" : { "type" : "string" }, - "debtPositionTypeOrgOperatorId" : { + "receiptId" : { "type" : "integer", "format" : "int64" }, - "debtPositionTypeOrgId" : { + "installmentId" : { "type" : "integer", "format" : "int64" }, - "operatorExternalUserId" : { - "type" : "string" - }, - "_links" : { - "$ref" : "#/components/schemas/Links" - } - } - }, - "PagedModelDebtPositionTypeOrgOperators" : { - "type" : "object", - "properties" : { - "_embedded" : { - "type" : "object", - "properties" : { - "debtPositionTypeOrgOperatorses" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/DebtPositionTypeOrgOperators" - } - } - } - }, - "_links" : { - "$ref" : "#/components/schemas/Links" - }, - "page" : { - "$ref" : "#/components/schemas/PageMetadata" - } - } - }, - "ReceiptNoPII" : { - "type" : "object", - "properties" : { - "creationDate" : { - "type" : "string", - "format" : "date-time" - }, - "updateDate" : { - "type" : "string", - "format" : "date-time" - }, - "updateOperatorExternalId" : { - "type" : "string" - }, - "receiptId" : { - "type" : "integer", - "format" : "int64" - }, - "installmentId" : { - "type" : "integer", - "format" : "int64" - }, - "paymentReceiptId" : { - "type" : "integer", - "format" : "int64" - }, - "noticeNumber" : { + "paymentReceiptId" : { + "type" : "integer", + "format" : "int64" + }, + "noticeNumber" : { "type" : "string" }, "orgFiscalCode" : { @@ -3227,6 +3312,114 @@ } } }, + "PaymentOption" : { + "type" : "object", + "properties" : { + "creationDate" : { + "type" : "string", + "format" : "date-time" + }, + "updateDate" : { + "type" : "string", + "format" : "date-time" + }, + "updateOperatorExternalId" : { + "type" : "string" + }, + "paymentOptionId" : { + "type" : "integer", + "format" : "int64" + }, + "debtPositionId" : { + "type" : "integer", + "format" : "int64" + }, + "totalAmountCents" : { + "type" : "integer", + "format" : "int64" + }, + "status" : { + "type" : "string" + }, + "multiDebtor" : { + "type" : "boolean" + }, + "dueDate" : { + "type" : "string", + "format" : "date-time" + }, + "description" : { + "type" : "string" + }, + "paymentOptionType" : { + "type" : "string", + "enum" : [ "SINGLE_INSTALLMENT", "INSTALMENTS", "DOWN_PAYMENT" ] + }, + "_links" : { + "$ref" : "#/components/schemas/Links" + } + } + }, + "PagedModelPaymentOption" : { + "type" : "object", + "properties" : { + "_embedded" : { + "type" : "object", + "properties" : { + "paymentOptions" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/PaymentOption" + } + } + } + }, + "_links" : { + "$ref" : "#/components/schemas/Links" + }, + "page" : { + "$ref" : "#/components/schemas/PageMetadata" + } + } + }, + "CollectionModelInstallmentNoPII" : { + "type" : "object", + "properties" : { + "_embedded" : { + "type" : "object", + "properties" : { + "installmentNoPIIs" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/InstallmentNoPIIResponse" + } + } + } + }, + "_links" : { + "$ref" : "#/components/schemas/Links" + } + } + }, + "CollectionModelObject" : { + "type" : "object", + "properties" : { + "_embedded" : { + "type" : "object", + "properties" : { + "objects" : { + "type" : "array", + "items" : { + "type" : "object" + } + } + } + }, + "_links" : { + "$ref" : "#/components/schemas/Links" + } + } + }, "InstallmentNoPII" : { "type" : "object", "properties" : { @@ -3335,20 +3528,6 @@ } } }, - "Stamp" : { - "type" : "object", - "properties" : { - "stampType" : { - "type" : "string" - }, - "stampHashDocument" : { - "type" : "string" - }, - "stampProvincialResidence" : { - "type" : "string" - } - } - }, "CollectionModelTransfer" : { "type" : "object", "properties" : { @@ -3368,26 +3547,7 @@ } } }, - "CollectionModelObject" : { - "type" : "object", - "properties" : { - "_embedded" : { - "type" : "object", - "properties" : { - "objects" : { - "type" : "array", - "items" : { - "type" : "object" - } - } - } - }, - "_links" : { - "$ref" : "#/components/schemas/Links" - } - } - }, - "Transfer" : { + "DebtPositionType" : { "type" : "object", "properties" : { "creationDate" : { @@ -3401,58 +3561,62 @@ "updateOperatorExternalId" : { "type" : "string" }, - "transferId" : { + "debtPositionTypeId" : { "type" : "integer", "format" : "int64" }, - "installmentId" : { + "brokerId" : { "type" : "integer", "format" : "int64" }, - "orgFiscalCode" : { + "code" : { "type" : "string" }, - "orgName" : { + "description" : { "type" : "string" }, - "amountCents" : { - "type" : "integer", - "format" : "int64" - }, - "remittanceInformation" : { + "orgType" : { "type" : "string" }, - "stamp" : { - "$ref" : "#/components/schemas/Stamp" + "macroArea" : { + "type" : "string" }, - "iban" : { + "serviceType" : { "type" : "string" }, - "postalIban" : { + "collectingReason" : { "type" : "string" }, - "category" : { + "taxonomyCode" : { "type" : "string" }, - "transferIndex" : { - "type" : "integer", - "format" : "int64" + "flagAnonymousFiscalCode" : { + "type" : "boolean" + }, + "flagMandatoryDueDate" : { + "type" : "boolean" + }, + "flagNotifyIo" : { + "type" : "boolean" + }, + "ioTemplateMessage" : { + "type" : "string" }, "_links" : { "$ref" : "#/components/schemas/Links" } } }, - "PagedModelTransfer" : { + "PagedModelDebtPositionType" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "transfers" : { + "debtPositionTypes" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/Transfer" + "$ref" : "#/components/schemas/DebtPositionType" } } } @@ -3465,7 +3629,7 @@ } } }, - "PaymentOption" : { + "DebtPositionTypeOrgOperators" : { "type" : "object", "properties" : { "creationDate" : { @@ -3479,50 +3643,32 @@ "updateOperatorExternalId" : { "type" : "string" }, - "paymentOptionId" : { - "type" : "integer", - "format" : "int64" - }, - "debtPositionId" : { + "debtPositionTypeOrgOperatorId" : { "type" : "integer", "format" : "int64" }, - "totalAmountCents" : { + "debtPositionTypeOrgId" : { "type" : "integer", "format" : "int64" }, - "status" : { - "type" : "string" - }, - "multiDebtor" : { - "type" : "boolean" - }, - "dueDate" : { - "type" : "string", - "format" : "date-time" - }, - "description" : { + "operatorExternalUserId" : { "type" : "string" }, - "paymentOptionType" : { - "type" : "string", - "enum" : [ "SINGLE_INSTALLMENT", "INSTALMENTS", "DOWN_PAYMENT" ] - }, "_links" : { "$ref" : "#/components/schemas/Links" } } }, - "PagedModelPaymentOption" : { + "PagedModelDebtPositionTypeOrgOperators" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "paymentOptions" : { + "debtPositionTypeOrgOperatorses" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/PaymentOption" + "$ref" : "#/components/schemas/DebtPositionTypeOrgOperators" } } } @@ -3535,25 +3681,6 @@ } } }, - "CollectionModelInstallmentNoPII" : { - "type" : "object", - "properties" : { - "_embedded" : { - "type" : "object", - "properties" : { - "installmentNoPIIs" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/InstallmentNoPIIResponse" - } - } - } - }, - "_links" : { - "$ref" : "#/components/schemas/Links" - } - } - }, "DebtPosition" : { "type" : "object", "properties" : { @@ -3654,7 +3781,7 @@ } } }, - "DebtPositionType" : { + "DebtPositionTypeOrg" : { "type" : "object", "properties" : { "creationDate" : { @@ -3668,33 +3795,50 @@ "updateOperatorExternalId" : { "type" : "string" }, + "debtPositionTypeOrgId" : { + "type" : "integer", + "format" : "int64" + }, "debtPositionTypeId" : { "type" : "integer", "format" : "int64" }, - "brokerId" : { + "organizationId" : { "type" : "integer", "format" : "int64" }, + "balance" : { + "type" : "string" + }, "code" : { "type" : "string" }, "description" : { "type" : "string" }, - "orgType" : { + "iban" : { "type" : "string" }, - "macroArea" : { + "postalIban" : { "type" : "string" }, - "serviceType" : { + "postalAccountCode" : { "type" : "string" }, - "collectingReason" : { + "holderPostalCc" : { "type" : "string" }, - "taxonomyCode" : { + "orgSector" : { + "type" : "string" + }, + "xsdDefinitionRef" : { + "type" : "string" + }, + "amountCents" : { + "type" : "integer", + "format" : "int64" + }, + "externalPaymentUrl" : { "type" : "string" }, "flagAnonymousFiscalCode" : { @@ -3703,27 +3847,50 @@ "flagMandatoryDueDate" : { "type" : "boolean" }, + "flagSpontaneous" : { + "type" : "boolean" + }, "flagNotifyIo" : { "type" : "boolean" }, "ioTemplateMessage" : { "type" : "string" }, + "flagActive" : { + "type" : "boolean" + }, + "flagNotifyOutcomePush" : { + "type" : "boolean" + }, + "notifyOutcomePushOrgSilServiceId" : { + "type" : "integer", + "format" : "int64" + }, + "flagAmountActualization" : { + "type" : "boolean" + }, + "amountActualizationOrgSilServiceId" : { + "type" : "integer", + "format" : "int64" + }, + "flagExternal" : { + "type" : "boolean" + }, "_links" : { "$ref" : "#/components/schemas/Links" } } }, - "PagedModelDebtPositionType" : { + "PagedModelDebtPositionTypeOrg" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "debtPositionTypes" : { + "debtPositionTypeOrgs" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/DebtPositionType" + "$ref" : "#/components/schemas/DebtPositionTypeOrg" } } } @@ -4457,6 +4624,17 @@ } } }, + "IudSyncStatusUpdateDTO" : { + "type" : "object", + "properties" : { + "newStatus" : { + "type" : "string" + }, + "iupdPagopa" : { + "type" : "string" + } + } + }, "DebtPositionDTO" : { "required" : [ "debtPositionTypeOrgId", "organizationId", "paymentOptions" ], "type" : "object", @@ -4760,4 +4938,4 @@ } } } -} +} \ No newline at end of file diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImpl.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImpl.java index 18a1190..2e6eacb 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImpl.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImpl.java @@ -10,6 +10,7 @@ import it.gov.pagopa.pu.debtpositions.repository.*; import jakarta.transaction.Transactional; import org.springframework.data.util.Pair; +import org.springframework.stereotype.Service; import java.util.List; import java.util.Map; @@ -18,6 +19,7 @@ import static it.gov.pagopa.pu.debtpositions.enums.DebtPositionStatus.TO_SYNC; +@Service public class DebtPositionServiceImpl implements DebtPositionService { private final DebtPositionRepository debtPositionRepository; From 6679f7ce868a1f02d6b294ce73a18f825db43bab Mon Sep 17 00:00:00 2001 From: LarissaASLeite Date: Wed, 15 Jan 2025 16:52:17 +0100 Subject: [PATCH 05/17] P4ADEV-1744-add-api-finalize-sync-status --- .../pagopa/pu/debtpositions/mapper/DebtPositionMapper.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapper.java b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapper.java index 1da5455..26688db 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapper.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapper.java @@ -8,10 +8,7 @@ import org.springframework.data.util.Pair; import org.springframework.stereotype.Service; -import java.util.HashMap; -import java.util.Map; -import java.util.SortedSet; -import java.util.TreeSet; +import java.util.*; import java.util.stream.Collector; import java.util.stream.Collectors; From b9a02756fbf3b648aa3ce619e35b81c38f5adc35 Mon Sep 17 00:00:00 2001 From: LarissaASLeite Date: Wed, 15 Jan 2025 17:26:03 +0100 Subject: [PATCH 06/17] P4ADEV-1744-add-api-finalize-sync-status --- .../mapper/PaymentOptionMapperTest.java | 31 +++++++++++++------ 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapperTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapperTest.java index 1b2ad19..f737f4a 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapperTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapperTest.java @@ -1,36 +1,49 @@ package it.gov.pagopa.pu.debtpositions.mapper; -import it.gov.pagopa.pu.debtpositions.citizen.service.DataCipherService; import it.gov.pagopa.pu.debtpositions.dto.Installment; import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionDTO; import it.gov.pagopa.pu.debtpositions.model.InstallmentNoPII; import it.gov.pagopa.pu.debtpositions.model.PaymentOption; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.util.Pair; import java.util.Map; import static it.gov.pagopa.pu.debtpositions.util.TestUtils.checkNotNullFields; -import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.*; -import static org.junit.jupiter.api.Assertions.*; +import static it.gov.pagopa.pu.debtpositions.util.faker.InstallmentFaker.*; +import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.buildPaymentOption; +import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.buildPaymentOptionDTO; +import static org.junit.jupiter.api.Assertions.assertEquals; +@ExtendWith(MockitoExtension.class) class PaymentOptionMapperTest { @Mock - private DataCipherService dataCipherServiceMock; + private InstallmentMapper installmentMapperMock; + @Mock + private InstallmentPIIMapper installmentPIIMapperMock; + + private PaymentOptionMapper paymentOptionMapper; - private final PersonMapper personMapper = new PersonMapper(); - private final TransferMapper transferMapper = new TransferMapper(); - private final InstallmentMapper installmentMapper = new InstallmentMapper(personMapper, transferMapper); - private final InstallmentPIIMapper installmentPIIMapper = new InstallmentPIIMapper(dataCipherServiceMock); - private final PaymentOptionMapper paymentOptionMapper = new PaymentOptionMapper(installmentMapper, installmentPIIMapper); + @BeforeEach + void setUp(){ + paymentOptionMapper = new PaymentOptionMapper(installmentMapperMock, installmentPIIMapperMock); + } @Test void givenValidPaymentOptionDTO_WhenMapToModel_ThenReturnPaymentOptionAndInstallmentMap() { PaymentOption paymentOptionExpected = buildPaymentOption(); PaymentOptionDTO paymentOptionDTO = buildPaymentOptionDTO(); + Mockito.when(installmentMapperMock.mapToModel(buildInstallmentDTO())).thenReturn(buildInstallment()); + + Mockito.when(installmentPIIMapperMock.map(buildInstallment())).thenReturn(Pair.of(buildInstallmentNoPII(), buildInstallmentPIIDTO())); + Pair> result = paymentOptionMapper.mapToModel(paymentOptionDTO); assertEquals(paymentOptionExpected, result.getFirst()); From 925fe19cc68e0eb93f6e10a9c6947c053dff5406 Mon Sep 17 00:00:00 2001 From: RiccardoGiuliani Date: Thu, 16 Jan 2025 09:48:31 +0100 Subject: [PATCH 07/17] fix tests --- .../mapper/DebtPositionMapperTest.java | 29 +++++++++++++------ .../mapper/InstallmentMapperTest.java | 27 +++++++++++++++-- 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapperTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapperTest.java index 3f069b7..dc7e881 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapperTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapperTest.java @@ -1,36 +1,39 @@ package it.gov.pagopa.pu.debtpositions.mapper; -import it.gov.pagopa.pu.debtpositions.citizen.service.DataCipherService; import it.gov.pagopa.pu.debtpositions.dto.Installment; import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; 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 org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.util.Pair; +import java.util.HashMap; import java.util.Map; import static it.gov.pagopa.pu.debtpositions.util.TestUtils.checkNotNullFields; import static it.gov.pagopa.pu.debtpositions.util.faker.DebtPositionFaker.*; +import static it.gov.pagopa.pu.debtpositions.util.faker.InstallmentFaker.*; +import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.buildPaymentOption; +import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.buildPaymentOptionDTO; import static org.junit.jupiter.api.Assertions.*; +@ExtendWith(MockitoExtension.class) class DebtPositionMapperTest { @Mock - private DataCipherService dataCipherServiceMock; + private PaymentOptionMapper paymentOptionMapperMock; private DebtPositionMapper debtPositionMapper; @BeforeEach - void init(){ - PersonMapper personMapper = new PersonMapper(); - TransferMapper transferMapper = new TransferMapper(); - InstallmentMapper installmentMapper = new InstallmentMapper(personMapper, transferMapper); - InstallmentPIIMapper installmentPIIMapper = new InstallmentPIIMapper(dataCipherServiceMock); - PaymentOptionMapper paymentOptionMapper = new PaymentOptionMapper(installmentMapper, installmentPIIMapper); - debtPositionMapper = new DebtPositionMapper(paymentOptionMapper); + void setUp(){ + debtPositionMapper = new DebtPositionMapper(paymentOptionMapperMock); } @Test @@ -38,6 +41,14 @@ void givenValidDebtPositionDTO_whenMapToModel_thenReturnDebtPositionAndInstallme DebtPosition debtPositionExpected = buildDebtPosition(); DebtPositionDTO debtPositionDTO = buildDebtPositionDTO(); + Map installmentMap = new HashMap<>(); + installmentMap.put(buildInstallmentNoPII(), buildInstallment()); + + PaymentOption paymentOption = buildPaymentOption(); + Pair> paymentOptionPair = Pair.of(paymentOption, installmentMap); + + Mockito.when(paymentOptionMapperMock.mapToModel(buildPaymentOptionDTO())).thenReturn(paymentOptionPair); + Pair> result = debtPositionMapper.mapToModel(debtPositionDTO); assertEquals(debtPositionExpected, result.getFirst()); diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapperTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapperTest.java index 1baf93d..732d759 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapperTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapperTest.java @@ -2,23 +2,44 @@ import it.gov.pagopa.pu.debtpositions.dto.Installment; import it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentDTO; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; import static it.gov.pagopa.pu.debtpositions.util.TestUtils.checkNotNullFields; +import static it.gov.pagopa.pu.debtpositions.util.faker.PersonFaker.buildPerson; +import static it.gov.pagopa.pu.debtpositions.util.faker.PersonFaker.buildPersonDTO; +import static it.gov.pagopa.pu.debtpositions.util.faker.TransferFaker.buildTransfer; +import static it.gov.pagopa.pu.debtpositions.util.faker.TransferFaker.buildTransferDTO; import static org.junit.jupiter.api.Assertions.*; import static it.gov.pagopa.pu.debtpositions.util.faker.InstallmentFaker.*; +@ExtendWith(MockitoExtension.class) class InstallmentMapperTest { - private final PersonMapper personMapper = new PersonMapper(); - private final TransferMapper transferMapper = new TransferMapper(); - private final InstallmentMapper installmentMapper = new InstallmentMapper(personMapper, transferMapper); + @Mock + private final PersonMapper personMapperMock = new PersonMapper(); + @Mock + private final TransferMapper transferMapperMock = new TransferMapper(); + + private InstallmentMapper installmentMapper; + + @BeforeEach + void setUp(){ + installmentMapper = new InstallmentMapper(personMapperMock, transferMapperMock); + } @Test void givenValidInstallmentDTO_WhenMapToModel_ThenReturnInstallment() { Installment installmentExpected = buildInstallmentNoUpdate(); InstallmentDTO installmentDTO = buildInstallmentDTO(); + Mockito.when(personMapperMock.mapToModel(buildPersonDTO())).thenReturn(buildPerson()); + Mockito.when(transferMapperMock.mapToModel(buildTransferDTO())).thenReturn(buildTransfer()); + Installment result = installmentMapper.mapToModel(installmentDTO); assertEquals(installmentExpected, result); From 14da8f9bee5bf7c7a9e56fbe2dfe1c4ca48bd2e6 Mon Sep 17 00:00:00 2001 From: RiccardoGiuliani Date: Thu, 16 Jan 2025 09:54:43 +0100 Subject: [PATCH 08/17] fix tests --- .../pagopa/pu/debtpositions/util/faker/InstallmentFaker.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java index 1034bc5..2a4e79c 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java @@ -13,6 +13,7 @@ import static it.gov.pagopa.pu.debtpositions.util.faker.PersonFaker.buildPerson; import static it.gov.pagopa.pu.debtpositions.util.faker.PersonFaker.buildPersonDTO; import static it.gov.pagopa.pu.debtpositions.util.faker.TransferFaker.buildTransfer; +import static it.gov.pagopa.pu.debtpositions.util.faker.TransferFaker.buildTransferDTO; public class InstallmentFaker { @@ -99,7 +100,7 @@ public static Installment buildInstallmentNoUpdate(){ .humanFriendlyRemittanceInformation("humanFriendlyRemittanceInformation") .balance("balance") .debtor(buildPerson()) - .transfers(List.of()) + .transfers(List.of(buildTransfer())) .creationDate(date) .updateDate(date) .build(); @@ -125,7 +126,7 @@ public static InstallmentDTO buildInstallmentDTO() { .humanFriendlyRemittanceInformation("humanFriendlyRemittanceInformation") .balance("balance") .debtor(buildPersonDTO()) - .transfers(List.of()) + .transfers(List.of(buildTransferDTO())) .creationDate(date.atOffset(ZoneOffset.UTC)) .updateDate(date.atOffset(ZoneOffset.UTC)) .build(); From cacad3779fd0302f35523f78196e8274b4302d7f Mon Sep 17 00:00:00 2001 From: LarissaASLeite Date: Thu, 16 Jan 2025 10:23:50 +0100 Subject: [PATCH 09/17] P4ADEV-1744-add-api-finalize-sync-status --- .../pu/debtpositions/mapper/InstallmentMapperTest.java | 4 ++-- .../gov/pagopa/pu/debtpositions/mapper/PersonMapperTest.java | 5 ++++- .../pagopa/pu/debtpositions/mapper/TransferMapperTest.java | 5 ++++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapperTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapperTest.java index 732d759..ecbff8e 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapperTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapperTest.java @@ -21,9 +21,9 @@ class InstallmentMapperTest { @Mock - private final PersonMapper personMapperMock = new PersonMapper(); + private PersonMapper personMapperMock; @Mock - private final TransferMapper transferMapperMock = new TransferMapper(); + private TransferMapper transferMapperMock; private InstallmentMapper installmentMapper; diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/PersonMapperTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/PersonMapperTest.java index 2135b07..d0cb30c 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/PersonMapperTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/PersonMapperTest.java @@ -3,14 +3,17 @@ import it.gov.pagopa.pu.debtpositions.dto.Person; import it.gov.pagopa.pu.debtpositions.dto.generated.PersonDTO; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; import static it.gov.pagopa.pu.debtpositions.util.TestUtils.checkNotNullFields; import static it.gov.pagopa.pu.debtpositions.util.faker.PersonFaker.*; import static org.junit.jupiter.api.Assertions.assertEquals; +@ExtendWith(MockitoExtension.class) class PersonMapperTest { - private final PersonMapper personMapper = new PersonMapper(); + private PersonMapper personMapper; @Test void givenValidPersonDTO_WhenMapToModel_ThenReturnPerson() { diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/TransferMapperTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/TransferMapperTest.java index 835a033..8f7fbbe 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/TransferMapperTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/TransferMapperTest.java @@ -3,14 +3,17 @@ import it.gov.pagopa.pu.debtpositions.dto.generated.TransferDTO; import it.gov.pagopa.pu.debtpositions.model.Transfer; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; import static it.gov.pagopa.pu.debtpositions.util.TestUtils.checkNotNullFields; import static it.gov.pagopa.pu.debtpositions.util.faker.TransferFaker.*; import static org.junit.jupiter.api.Assertions.assertEquals; +@ExtendWith(MockitoExtension.class) class TransferMapperTest { - private final TransferMapper transferMapper = new TransferMapper(); + private TransferMapper transferMapper; @Test void givenValidTransferDTO_WhenMapToModel_ThenReturnTransfer() { From 7ac2824adec22fdae7c2ab5dac02fc6a3900bebc Mon Sep 17 00:00:00 2001 From: LarissaASLeite Date: Thu, 16 Jan 2025 12:21:48 +0100 Subject: [PATCH 10/17] P4ADEV-1744-add-api-finalize-sync-status --- .../mapper/DebtPositionMapperTest.java | 10 +- .../mapper/InstallmentMapperTest.java | 7 +- .../mapper/InstallmentPIIMapperTest.java | 5 +- .../mapper/PaymentOptionMapperTest.java | 4 +- .../mapper/PersonMapperTest.java | 13 ++- .../mapper/TransferMapperTest.java | 13 ++- .../service/DebtPositionServiceImplTest.java | 2 - .../debtpositions/util/ReflectionUtils.java | 40 +++++++ .../pu/debtpositions/util/TestUtils.java | 102 +++++++++++++++++- .../util/faker/InstallmentFaker.java | 2 +- 10 files changed, 173 insertions(+), 25 deletions(-) create mode 100644 src/test/java/it/gov/pagopa/pu/debtpositions/util/ReflectionUtils.java diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapperTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapperTest.java index dc7e881..3a5cbef 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapperTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapperTest.java @@ -17,11 +17,13 @@ import java.util.Map; import static it.gov.pagopa.pu.debtpositions.util.TestUtils.checkNotNullFields; -import static it.gov.pagopa.pu.debtpositions.util.faker.DebtPositionFaker.*; -import static it.gov.pagopa.pu.debtpositions.util.faker.InstallmentFaker.*; +import static it.gov.pagopa.pu.debtpositions.util.TestUtils.reflectionEqualsByName; +import static it.gov.pagopa.pu.debtpositions.util.faker.DebtPositionFaker.buildDebtPosition; +import static it.gov.pagopa.pu.debtpositions.util.faker.DebtPositionFaker.buildDebtPositionDTO; +import static it.gov.pagopa.pu.debtpositions.util.faker.InstallmentFaker.buildInstallment; +import static it.gov.pagopa.pu.debtpositions.util.faker.InstallmentFaker.buildInstallmentNoPII; import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.buildPaymentOption; import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.buildPaymentOptionDTO; -import static org.junit.jupiter.api.Assertions.*; @ExtendWith(MockitoExtension.class) class DebtPositionMapperTest { @@ -51,7 +53,7 @@ void givenValidDebtPositionDTO_whenMapToModel_thenReturnDebtPositionAndInstallme Pair> result = debtPositionMapper.mapToModel(debtPositionDTO); - assertEquals(debtPositionExpected, result.getFirst()); + reflectionEqualsByName(debtPositionExpected, result.getFirst()); checkNotNullFields(result.getFirst(), "updateOperatorExternalId"); } diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapperTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapperTest.java index ecbff8e..5f681ab 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapperTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapperTest.java @@ -10,12 +10,13 @@ import org.mockito.junit.jupiter.MockitoExtension; import static it.gov.pagopa.pu.debtpositions.util.TestUtils.checkNotNullFields; +import static it.gov.pagopa.pu.debtpositions.util.TestUtils.reflectionEqualsByName; +import static it.gov.pagopa.pu.debtpositions.util.faker.InstallmentFaker.buildInstallmentDTO; +import static it.gov.pagopa.pu.debtpositions.util.faker.InstallmentFaker.buildInstallmentNoUpdate; import static it.gov.pagopa.pu.debtpositions.util.faker.PersonFaker.buildPerson; import static it.gov.pagopa.pu.debtpositions.util.faker.PersonFaker.buildPersonDTO; import static it.gov.pagopa.pu.debtpositions.util.faker.TransferFaker.buildTransfer; import static it.gov.pagopa.pu.debtpositions.util.faker.TransferFaker.buildTransferDTO; -import static org.junit.jupiter.api.Assertions.*; -import static it.gov.pagopa.pu.debtpositions.util.faker.InstallmentFaker.*; @ExtendWith(MockitoExtension.class) class InstallmentMapperTest { @@ -42,7 +43,7 @@ void givenValidInstallmentDTO_WhenMapToModel_ThenReturnInstallment() { Installment result = installmentMapper.mapToModel(installmentDTO); - assertEquals(installmentExpected, result); + reflectionEqualsByName(installmentExpected, result); checkNotNullFields(result, "updateOperatorExternalId", "noPII"); } } diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentPIIMapperTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentPIIMapperTest.java index 88966eb..c5d1ea9 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentPIIMapperTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentPIIMapperTest.java @@ -14,6 +14,7 @@ import org.springframework.data.util.Pair; import static it.gov.pagopa.pu.debtpositions.util.TestUtils.checkNotNullFields; +import static it.gov.pagopa.pu.debtpositions.util.TestUtils.reflectionEqualsByName; import static it.gov.pagopa.pu.debtpositions.util.faker.InstallmentFaker.*; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -46,8 +47,8 @@ void testMap(){ Pair result = mapper.map(installment); - assertEquals(installmentNoPIIExpected, result.getFirst()); - assertEquals(installmentPIIDTOExpected, result.getSecond()); + reflectionEqualsByName(installmentNoPIIExpected, result.getFirst()); + reflectionEqualsByName(installmentPIIDTOExpected, result.getSecond()); checkNotNullFields(result.getFirst(), "transfers", "personalDataId", "debtorFiscalCodeHash"); checkNotNullFields(result.getSecond()); } diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapperTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapperTest.java index f737f4a..7375f24 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapperTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapperTest.java @@ -15,10 +15,10 @@ import java.util.Map; import static it.gov.pagopa.pu.debtpositions.util.TestUtils.checkNotNullFields; +import static it.gov.pagopa.pu.debtpositions.util.TestUtils.reflectionEqualsByName; import static it.gov.pagopa.pu.debtpositions.util.faker.InstallmentFaker.*; import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.buildPaymentOption; import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.buildPaymentOptionDTO; -import static org.junit.jupiter.api.Assertions.assertEquals; @ExtendWith(MockitoExtension.class) class PaymentOptionMapperTest { @@ -46,7 +46,7 @@ void givenValidPaymentOptionDTO_WhenMapToModel_ThenReturnPaymentOptionAndInstall Pair> result = paymentOptionMapper.mapToModel(paymentOptionDTO); - assertEquals(paymentOptionExpected, result.getFirst()); + reflectionEqualsByName(paymentOptionExpected, result.getFirst()); checkNotNullFields(result.getFirst(), "updateOperatorExternalId", "creationDate", "updateDate"); } } diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/PersonMapperTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/PersonMapperTest.java index d0cb30c..bd157b8 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/PersonMapperTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/PersonMapperTest.java @@ -2,19 +2,26 @@ import it.gov.pagopa.pu.debtpositions.dto.Person; import it.gov.pagopa.pu.debtpositions.dto.generated.PersonDTO; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; import static it.gov.pagopa.pu.debtpositions.util.TestUtils.checkNotNullFields; -import static it.gov.pagopa.pu.debtpositions.util.faker.PersonFaker.*; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static it.gov.pagopa.pu.debtpositions.util.TestUtils.reflectionEqualsByName; +import static it.gov.pagopa.pu.debtpositions.util.faker.PersonFaker.buildPerson; +import static it.gov.pagopa.pu.debtpositions.util.faker.PersonFaker.buildPersonDTO; @ExtendWith(MockitoExtension.class) class PersonMapperTest { private PersonMapper personMapper; + @BeforeEach + void setUp() { + personMapper = new PersonMapper(); + } + @Test void givenValidPersonDTO_WhenMapToModel_ThenReturnPerson() { Person personExpected = buildPerson(); @@ -22,7 +29,7 @@ void givenValidPersonDTO_WhenMapToModel_ThenReturnPerson() { Person result = personMapper.mapToModel(personDTO); - assertEquals(personExpected, result); + reflectionEqualsByName(personExpected, result); checkNotNullFields(result); } } diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/TransferMapperTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/TransferMapperTest.java index 8f7fbbe..a944047 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/TransferMapperTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/TransferMapperTest.java @@ -2,19 +2,26 @@ import it.gov.pagopa.pu.debtpositions.dto.generated.TransferDTO; import it.gov.pagopa.pu.debtpositions.model.Transfer; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; import static it.gov.pagopa.pu.debtpositions.util.TestUtils.checkNotNullFields; -import static it.gov.pagopa.pu.debtpositions.util.faker.TransferFaker.*; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static it.gov.pagopa.pu.debtpositions.util.TestUtils.reflectionEqualsByName; +import static it.gov.pagopa.pu.debtpositions.util.faker.TransferFaker.buildTransfer; +import static it.gov.pagopa.pu.debtpositions.util.faker.TransferFaker.buildTransferDTO; @ExtendWith(MockitoExtension.class) class TransferMapperTest { private TransferMapper transferMapper; + @BeforeEach + void setUp(){ + transferMapper = new TransferMapper(); + } + @Test void givenValidTransferDTO_WhenMapToModel_ThenReturnTransfer() { TransferDTO transferDTO = buildTransferDTO(); @@ -22,7 +29,7 @@ void givenValidTransferDTO_WhenMapToModel_ThenReturnTransfer() { Transfer result = transferMapper.mapToModel(transferDTO); - assertEquals(transferExpected, result); + reflectionEqualsByName(transferExpected, result); checkNotNullFields(result, "updateOperatorExternalId", "creationDate", "updateDate"); } } diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImplTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImplTest.java index 857d33f..8ffa09a 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImplTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImplTest.java @@ -121,7 +121,6 @@ void givenFinalizeSyncStatusThenOk(){ // When service.finalizeSyncStatus(id, syncStatusDTO); - System.out.println("debtPosition: " + debtPosition); // Then verify(debtPositionRepositoryMock).findOneWithAllDataByDebtPositionId(id); @@ -163,7 +162,6 @@ void givenFinalizeSyncStatusWhenDifferentStatusThenOk(){ // When service.finalizeSyncStatus(id, syncStatusDTO); - System.out.println("debtPosition: " + debtPosition); // Then verify(debtPositionRepositoryMock).findOneWithAllDataByDebtPositionId(id); diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/ReflectionUtils.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/ReflectionUtils.java new file mode 100644 index 0000000..e25685b --- /dev/null +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/ReflectionUtils.java @@ -0,0 +1,40 @@ +package it.gov.pagopa.pu.debtpositions.util; + +import com.fasterxml.jackson.annotation.JsonValue; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * The Class ReflectionUtils. + */ +public class ReflectionUtils { + + /** + * It will transform the input enum into a String, using the same logic of Jackson + */ + public static String enum2String(Enum o) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + final Object result = enum2Object(o); + + return result != null ? result.toString() : null; + } + + /** + * It will transform the input enum into an Object, using the same logic of Jackson + */ + private static Object enum2Object(Enum o) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { + Method jsonValueMethod = null; + for (Method m : o.getClass().getMethods()) { + if (m.getAnnotation(JsonValue.class) != null) { + jsonValueMethod = m; + break; + } + } + + if (jsonValueMethod == null) { + jsonValueMethod = o.getClass().getMethod("toString"); + } + + return jsonValueMethod.invoke(o); + } +} diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/TestUtils.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/TestUtils.java index 12e534e..a08ec38 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/util/TestUtils.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/TestUtils.java @@ -1,15 +1,18 @@ package it.gov.pagopa.pu.debtpositions.util; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; import org.junit.jupiter.api.Assertions; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.math.BigInteger; import java.time.OffsetDateTime; -import java.time.ZoneOffset; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; +import java.time.chrono.ChronoZonedDateTime; +import java.util.*; +@Slf4j public class TestUtils { - public static final OffsetDateTime OFFSET_DATE_TIME = OffsetDateTime.of(2025, 1, 1, 0,0,0, 0, ZoneOffset.UTC); private TestUtils(){} @@ -26,4 +29,93 @@ public static void checkNotNullFields(Object o, String... excludedFields) { f -> !excludedFieldsSet.contains(f.getName())); } + public static List reflectionEqualsByName(Object o1, Object o2, String... ignoredFields) { + Set ignoredFieldSet = new HashSet<>(Arrays.asList(ignoredFields)); + Assertions.assertFalse(o1 == null ^ o2 == null, String.format("Both objects have to be null or not null:%n%s%n%s", o1 == null ? "null" : o1.getClass().getName(), o2 == null ? "null" : o2.getClass().getName())); + + List checked = new ArrayList<>(); + + if (o1 != null) { + for (Method m1 : o1.getClass().getMethods()) { + if ((m1.getName().startsWith("get") || m1.getName().startsWith("is")) && m1.getParameterCount() == 0 && !"getClass".equals(m1.getName())) { + String fieldName = StringUtils.uncapitalize(m1.getName().replaceFirst("^(?:get|is)", "")); + if (ignoredFieldSet.contains(fieldName)) { + continue; + } + Method m2 = null; + try { + m2 = Arrays.stream(o2.getClass().getMethods()).filter(m -> m.getName().equalsIgnoreCase(m1.getName()) && m.getParameterCount() == m1.getParameterCount()).findFirst().orElse(null); + + if (m2 == null) { + throw new NoSuchMethodException(); + } + + Object v1 = m1.invoke(o1); + Object v2 = m2.invoke(o2); + + boolean result = true; + + Assertions.assertFalse(v1 == null ^ v2 == null, String.format("Both objects have to be null or not null:%n%s = %s%n%s = %s", m1, v1 == null ? "null" : v1.getClass().getName(), m2, v2 == null ? "null" : v2.getClass().getName())); + if (v1 != null) { + if (v1.equals(v2)) { + //Do Nothing + } else if (v1 instanceof Comparable && v2 instanceof Comparable && ((Comparable) v1).compareTo(v2) == 0) { + //Do Nothing + } else if (OffsetDateTime.class.isAssignableFrom(v1.getClass()) && OffsetDateTime.class.isAssignableFrom(v2.getClass())) { + result = ((OffsetDateTime) v1).isEqual((OffsetDateTime) v2); + } else if (ChronoZonedDateTime.class.isAssignableFrom(v1.getClass()) && ChronoZonedDateTime.class.isAssignableFrom(v2.getClass())) { + result = ((ChronoZonedDateTime) v1).isEqual((ChronoZonedDateTime) v2); + } else if (v1.getClass().isAssignableFrom(v2.getClass()) && ((v1.getClass().isPrimitive() && v2.getClass().isPrimitive()) || (hasStandardEquals(v1.getClass()) && hasStandardEquals(v2.getClass())))) { + result = false; + } else if (BigInteger.class.isAssignableFrom(v1.getClass()) && Integer.class.isAssignableFrom(v2.getClass())) { + result = ((BigInteger) v1).intValue() == ((int) v2); + } else if (BigInteger.class.isAssignableFrom(v2.getClass()) && Integer.class.isAssignableFrom(v1.getClass())) { + result = ((BigInteger) v2).intValue() == ((int) v1); + } else if (BigInteger.class.isAssignableFrom(v1.getClass()) && Long.class.isAssignableFrom(v2.getClass())) { + result = ((BigInteger) v1).longValue() == ((long) v2); + } else if (BigInteger.class.isAssignableFrom(v2.getClass()) && Long.class.isAssignableFrom(v1.getClass())) { + result = ((BigInteger) v2).longValue() == ((long) v1); + } else if (String.class.isAssignableFrom(v1.getClass()) && Enum.class.isAssignableFrom(v2.getClass())) { + v2 = ReflectionUtils.enum2String((Enum) v2); + result = v1.equals(v2); + } else if (String.class.isAssignableFrom(v2.getClass()) && Enum.class.isAssignableFrom(v1.getClass())) { + v1 = ReflectionUtils.enum2String((Enum) v1); + result = v2.equals(v1); + } else { + boolean equals = v1.toString().equals(v2.toString()); + if (Enum.class.isAssignableFrom(v2.getClass()) && Enum.class.isAssignableFrom(v1.getClass())) { + result = equals; + } else if (String.class.isAssignableFrom(v1.getClass()) || String.class.isAssignableFrom(v2.getClass())) { + result = equals; + } else { + checked.addAll(reflectionEqualsByName(v1, v2)); + } + } + + checked.add(m1); + } + + Assertions.assertTrue(result, String.format("Invalid compare between methods%n%s = %s%n%s = %s", m1, v1, m2, v2)); + } catch (NoSuchMethodException e) { + log.debug("Method {} is not defined in {}{}", m1, o2.getClass().getName(), e.getMessage()); + } catch (IllegalAccessException | + InvocationTargetException e) { + throw new IllegalStateException(String.format("[ERROR] Something gone wrong comparing %s with %s%n%s", m1, m2, e.getMessage())); + } + } + } + } + return checked; + } + + private static boolean hasStandardEquals(Class clazz) { + try { + return !clazz.getMethod("equals", Object.class).equals(Object.class.getMethod("equals", Object.class)); + } catch (NoSuchMethodException e) { + // This exception cannot be thrown + e.printStackTrace(); + throw new RuntimeException(e); + } + } + } diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java index 2a4e79c..7e9f844 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java @@ -70,7 +70,7 @@ public static InstallmentNoPII buildInstallmentNoPII(){ .balance("balance") .creationDate(date) .updateDate(date) - .updateOperatorExternalId("OPERATOREXTERNALID") + .updateOperatorExternalId("OPERATOREXTERNALUSERID") .build(); } From a4c0aea7c58eb8667a2349f0ce47dcffd64ecad8 Mon Sep 17 00:00:00 2001 From: LarissaASLeite Date: Thu, 16 Jan 2025 16:44:59 +0100 Subject: [PATCH 11/17] P4ADEV-1744-add-api-finalize-sync-status --- openapi/p4pa-debt-position.openapi.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openapi/p4pa-debt-position.openapi.yaml b/openapi/p4pa-debt-position.openapi.yaml index 62d5133..de46d75 100644 --- a/openapi/p4pa-debt-position.openapi.yaml +++ b/openapi/p4pa-debt-position.openapi.yaml @@ -29,7 +29,7 @@ paths: description: Invalid request "500": description: Internal server error - /sync/status/{debtPositionId}: + /debt-positions/{debtPositionId}/finalize-sync-status: put: tags: - debt-position From 847690d12393f71d5138fe0ee2f4f08f4158d974 Mon Sep 17 00:00:00 2001 From: LarissaASLeite Date: Mon, 20 Jan 2025 11:43:15 +0100 Subject: [PATCH 12/17] P4ADEV-1744-add-api-finalize-sync-status --- build.gradle.kts | 1 + openapi/generated.openapi.json | 714 ++++++++---------- openapi/p4pa-debt-position.openapi.yaml | 74 +- .../DebtPositionControllerImpl.java | 15 +- .../pu/debtpositions/dto/Installment.java | 3 +- .../enums/DebtPositionStatus.java | 13 - .../DebtPositionExceptionHandler.java | 46 ++ .../custom/InvalidStatusException.java | 8 + .../pu/debtpositions/model/DebtPosition.java | 10 +- .../debtpositions/model/InstallmentNoPII.java | 4 +- .../pu/debtpositions/model/PaymentOption.java | 10 +- .../repository/DebtPositionRepository.java | 7 +- .../InstallmentNoPIIRepository.java | 12 +- .../repository/PaymentOptionRepository.java | 7 +- .../service/DebtPositionService.java | 4 - .../service/DebtPositionServiceImpl.java | 61 +- ...PositionHierarchyStatusAlignerService.java | 10 + ...tionHierarchyStatusAlignerServiceImpl.java | 62 ++ .../statusalign/StatusRulesHandler.java | 87 +++ ...DebtPositionInnerStatusAlignerService.java | 8 + ...PositionInnerStatusAlignerServiceImpl.java | 25 + .../DebtPositionStatusChecker.java | 41 + ...aymentOptionInnerStatusAlignerService.java | 8 + ...ntOptionInnerStatusAlignerServiceImpl.java | 25 + .../PaymentOptionStatusChecker.java | 42 ++ .../DebtPositionControllerTest.java | 6 +- .../DebtPositionExceptionHandlerTest.java | 61 ++ .../service/DebtPositionServiceImplTest.java | 134 +--- ...tionHierarchyStatusAlignerServiceTest.java | 100 +++ ...PositionInnerStatusAlignerServiceTest.java | 61 ++ .../DebtPositionStatusCheckerTest.java | 86 +++ ...ntOptionInnerStatusAlignerServiceTest.java | 62 ++ .../PaymentOptionStatusCheckerTest.java | 85 +++ .../pu/debtpositions/util/TestUtils.java | 2 +- .../util/faker/DebtPositionFaker.java | 8 +- .../util/faker/InstallmentFaker.java | 9 +- .../util/faker/PaymentOptionFaker.java | 5 +- 37 files changed, 1274 insertions(+), 642 deletions(-) delete mode 100644 src/main/java/it/gov/pagopa/pu/debtpositions/enums/DebtPositionStatus.java create mode 100644 src/main/java/it/gov/pagopa/pu/debtpositions/exception/DebtPositionExceptionHandler.java create mode 100644 src/main/java/it/gov/pagopa/pu/debtpositions/exception/custom/InvalidStatusException.java create mode 100644 src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerService.java create mode 100644 src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerServiceImpl.java create mode 100644 src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/StatusRulesHandler.java create mode 100644 src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionInnerStatusAlignerService.java create mode 100644 src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionInnerStatusAlignerServiceImpl.java create mode 100644 src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusChecker.java create mode 100644 src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionInnerStatusAlignerService.java create mode 100644 src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionInnerStatusAlignerServiceImpl.java create mode 100644 src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusChecker.java create mode 100644 src/test/java/it/gov/pagopa/pu/debtpositions/exception/DebtPositionExceptionHandlerTest.java create mode 100644 src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerServiceTest.java create mode 100644 src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionInnerStatusAlignerServiceTest.java create mode 100644 src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusCheckerTest.java create mode 100644 src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionInnerStatusAlignerServiceTest.java create mode 100644 src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusCheckerTest.java diff --git a/build.gradle.kts b/build.gradle.kts index dafbc2e..a9087ad 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -71,6 +71,7 @@ dependencies { testImplementation("org.springframework.boot:spring-boot-starter-test") testImplementation("org.mockito:mockito-core") testImplementation ("org.projectlombok:lombok") + testAnnotationProcessor("org.projectlombok:lombok") testImplementation("com.h2database:h2") } diff --git a/openapi/generated.openapi.json b/openapi/generated.openapi.json index 8d47c74..b0112ae 100644 --- a/openapi/generated.openapi.json +++ b/openapi/generated.openapi.json @@ -809,34 +809,6 @@ } } }, - "/crud/debt-positions/search/updateStatus" : { - "get" : { - "tags" : [ "debt-position-search-controller" ], - "operationId" : "crud-debt-positions-updateStatus", - "parameters" : [ { - "name" : "debtPositionId", - "in" : "query", - "schema" : { - "type" : "integer", - "format" : "int64" - } - }, { - "name" : "status", - "in" : "query", - "schema" : { - "type" : "string" - } - } ], - "responses" : { - "200" : { - "description" : "OK" - }, - "404" : { - "description" : "Not Found" - } - } - } - }, "/crud/debt-positions/{id}" : { "get" : { "tags" : [ "debt-position-entity-controller" ], @@ -1289,74 +1261,6 @@ } } }, - "/crud/installments/search/findByIudAndIupdPagopaAndStatus" : { - "get" : { - "tags" : [ "installment-no-pii-search-controller" ], - "operationId" : "crud-installments-findByIudAndIupdPagopaAndStatus", - "parameters" : [ { - "name" : "iud", - "in" : "query", - "schema" : { - "type" : "string" - } - }, { - "name" : "iupdPagopa", - "in" : "query", - "schema" : { - "type" : "string" - } - }, { - "name" : "status", - "in" : "query", - "schema" : { - "type" : "string" - } - } ], - "responses" : { - "200" : { - "description" : "OK", - "content" : { - "application/hal+json" : { - "schema" : { - "$ref" : "#/components/schemas/InstallmentNoPII" - } - } - } - }, - "404" : { - "description" : "Not Found" - } - } - } - }, - "/crud/installments/search/updateStatus" : { - "get" : { - "tags" : [ "installment-no-pii-search-controller" ], - "operationId" : "crud-installments-updateStatus", - "parameters" : [ { - "name" : "installmentId", - "in" : "query", - "schema" : { - "type" : "integer", - "format" : "int64" - } - }, { - "name" : "status", - "in" : "query", - "schema" : { - "type" : "string" - } - } ], - "responses" : { - "200" : { - "description" : "OK" - }, - "404" : { - "description" : "Not Found" - } - } - } - }, "/crud/installments/{id}" : { "get" : { "tags" : [ "installment-no-pii-entity-controller" ], @@ -1809,34 +1713,6 @@ } } }, - "/crud/payment-options/search/updateStatus" : { - "get" : { - "tags" : [ "payment-option-search-controller" ], - "operationId" : "crud-payment-options-updateStatus", - "parameters" : [ { - "name" : "paymentOptionId", - "in" : "query", - "schema" : { - "type" : "integer", - "format" : "int64" - } - }, { - "name" : "status", - "in" : "query", - "schema" : { - "type" : "string" - } - } ], - "responses" : { - "200" : { - "description" : "OK" - }, - "404" : { - "description" : "Not Found" - } - } - } - }, "/crud/payment-options/{id}" : { "get" : { "tags" : [ "payment-option-entity-controller" ], @@ -2893,7 +2769,7 @@ } } }, - "/sync/status/{debtPositionId}" : { + "/debt-positions/{debtPositionId}/finalize-sync-status" : { "put" : { "tags" : [ "debt-position" ], "operationId" : "finalizeSyncStatus", @@ -3070,21 +2946,7 @@ } } }, - "Stamp" : { - "type" : "object", - "properties" : { - "stampType" : { - "type" : "string" - }, - "stampHashDocument" : { - "type" : "string" - }, - "stampProvincialResidence" : { - "type" : "string" - } - } - }, - "Transfer" : { + "InstallmentNoPII" : { "type" : "object", "properties" : { "creationDate" : { @@ -3098,48 +2960,92 @@ "updateOperatorExternalId" : { "type" : "string" }, - "transferId" : { + "installmentId" : { "type" : "integer", "format" : "int64" }, - "installmentId" : { + "paymentOptionId" : { "type" : "integer", "format" : "int64" }, - "orgFiscalCode" : { + "status" : { "type" : "string" }, - "orgName" : { + "iupdPagopa" : { + "type" : "string" + }, + "iud" : { + "type" : "string" + }, + "iuv" : { + "type" : "string" + }, + "iur" : { + "type" : "string" + }, + "iuf" : { + "type" : "string" + }, + "nav" : { + "type" : "string" + }, + "dueDate" : { + "type" : "string", + "format" : "date-time" + }, + "paymentTypeCode" : { "type" : "string" }, "amountCents" : { "type" : "integer", "format" : "int64" }, + "notificationFeeCents" : { + "type" : "integer", + "format" : "int64" + }, "remittanceInformation" : { "type" : "string" }, - "stamp" : { - "$ref" : "#/components/schemas/Stamp" - }, - "iban" : { + "humanFriendlyRemittanceInformation" : { "type" : "string" }, - "postalIban" : { + "balance" : { "type" : "string" }, - "category" : { + "legacyPaymentMetadata" : { "type" : "string" }, - "transferIndex" : { + "personalDataId" : { "type" : "integer", "format" : "int64" }, + "debtorEntityType" : { + "type" : "string" + }, + "debtorFiscalCodeHash" : { + "type" : "string", + "format" : "byte" + }, "_links" : { "$ref" : "#/components/schemas/Links" } } }, + "Stamp" : { + "type" : "object", + "properties" : { + "stampType" : { + "type" : "string" + }, + "stampHashDocument" : { + "type" : "string" + }, + "stampProvincialResidence" : { + "type" : "string" + } + } + }, "PageMetadata" : { "type" : "object", "properties" : { @@ -3161,16 +3067,16 @@ } } }, - "PagedModelTransfer" : { + "PagedModelInstallmentNoPII" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "transfers" : { + "installmentNoPIIs" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/Transfer" + "$ref" : "#/components/schemas/InstallmentNoPII" } } } @@ -3183,7 +3089,45 @@ } } }, - "ReceiptNoPII" : { + "CollectionModelTransfer" : { + "type" : "object", + "properties" : { + "_embedded" : { + "type" : "object", + "properties" : { + "transfers" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/TransferResponse" + } + } + } + }, + "_links" : { + "$ref" : "#/components/schemas/Links" + } + } + }, + "CollectionModelObject" : { + "type" : "object", + "properties" : { + "_embedded" : { + "type" : "object", + "properties" : { + "objects" : { + "type" : "array", + "items" : { + "type" : "object" + } + } + } + }, + "_links" : { + "$ref" : "#/components/schemas/Links" + } + } + }, + "DebtPositionTypeOrg" : { "type" : "object", "properties" : { "creationDate" : { @@ -3197,109 +3141,102 @@ "updateOperatorExternalId" : { "type" : "string" }, - "receiptId" : { + "debtPositionTypeOrgId" : { "type" : "integer", "format" : "int64" }, - "installmentId" : { + "debtPositionTypeId" : { "type" : "integer", "format" : "int64" }, - "paymentReceiptId" : { + "organizationId" : { "type" : "integer", "format" : "int64" }, - "noticeNumber" : { + "balance" : { "type" : "string" }, - "orgFiscalCode" : { + "code" : { "type" : "string" }, - "outcome" : { + "description" : { "type" : "string" }, - "creditorReferenceId" : { + "iban" : { "type" : "string" }, - "paymentAmountCents" : { - "type" : "integer", - "format" : "int64" - }, - "description" : { + "postalIban" : { "type" : "string" }, - "companyName" : { + "postalAccountCode" : { "type" : "string" }, - "officeName" : { + "holderPostalCc" : { "type" : "string" }, - "idPsp" : { + "orgSector" : { "type" : "string" }, - "pspFiscalCode" : { - "type" : "string" - }, - "pspPartitaIva" : { + "xsdDefinitionRef" : { "type" : "string" }, - "pspCompanyName" : { - "type" : "string" + "amountCents" : { + "type" : "integer", + "format" : "int64" }, - "idChannel" : { + "externalPaymentUrl" : { "type" : "string" }, - "channelDescription" : { - "type" : "string" + "flagAnonymousFiscalCode" : { + "type" : "boolean" }, - "paymentMethod" : { - "type" : "string" + "flagMandatoryDueDate" : { + "type" : "boolean" }, - "feeCents" : { - "type" : "integer", - "format" : "int64" + "flagSpontaneous" : { + "type" : "boolean" }, - "paymentDateTime" : { - "type" : "string", - "format" : "date-time" + "flagNotifyIo" : { + "type" : "boolean" }, - "applicationDate" : { - "type" : "string", - "format" : "date-time" + "ioTemplateMessage" : { + "type" : "string" }, - "transferDate" : { - "type" : "string", - "format" : "date-time" + "flagActive" : { + "type" : "boolean" }, - "standin" : { + "flagNotifyOutcomePush" : { "type" : "boolean" }, - "debtorEntityType" : { - "type" : "string" + "notifyOutcomePushOrgSilServiceId" : { + "type" : "integer", + "format" : "int64" }, - "personalDataId" : { + "flagAmountActualization" : { + "type" : "boolean" + }, + "amountActualizationOrgSilServiceId" : { "type" : "integer", "format" : "int64" }, - "debtorFiscalCodeHash" : { - "type" : "string", - "format" : "byte" + "flagExternal" : { + "type" : "boolean" }, "_links" : { "$ref" : "#/components/schemas/Links" } } }, - "PagedModelReceiptNoPII" : { + "PagedModelDebtPositionTypeOrg" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "receiptNoPIIs" : { + "debtPositionTypeOrgs" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/ReceiptNoPII" + "$ref" : "#/components/schemas/DebtPositionTypeOrg" } } } @@ -3312,7 +3249,7 @@ } } }, - "PaymentOption" : { + "Transfer" : { "type" : "object", "properties" : { "creationDate" : { @@ -3326,50 +3263,58 @@ "updateOperatorExternalId" : { "type" : "string" }, - "paymentOptionId" : { + "transferId" : { "type" : "integer", "format" : "int64" }, - "debtPositionId" : { + "installmentId" : { "type" : "integer", "format" : "int64" }, - "totalAmountCents" : { + "orgFiscalCode" : { + "type" : "string" + }, + "orgName" : { + "type" : "string" + }, + "amountCents" : { "type" : "integer", "format" : "int64" }, - "status" : { + "remittanceInformation" : { "type" : "string" }, - "multiDebtor" : { - "type" : "boolean" + "stamp" : { + "$ref" : "#/components/schemas/Stamp" }, - "dueDate" : { - "type" : "string", - "format" : "date-time" + "iban" : { + "type" : "string" }, - "description" : { + "postalIban" : { "type" : "string" }, - "paymentOptionType" : { - "type" : "string", - "enum" : [ "SINGLE_INSTALLMENT", "INSTALMENTS", "DOWN_PAYMENT" ] + "category" : { + "type" : "string" + }, + "transferIndex" : { + "type" : "integer", + "format" : "int64" }, "_links" : { "$ref" : "#/components/schemas/Links" } } }, - "PagedModelPaymentOption" : { + "PagedModelTransfer" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "paymentOptions" : { + "transfers" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/PaymentOption" + "$ref" : "#/components/schemas/Transfer" } } } @@ -3382,45 +3327,59 @@ } } }, - "CollectionModelInstallmentNoPII" : { + "DebtPositionTypeOrgOperators" : { "type" : "object", "properties" : { - "_embedded" : { - "type" : "object", - "properties" : { - "installmentNoPIIs" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/InstallmentNoPIIResponse" - } - } - } + "creationDate" : { + "type" : "string", + "format" : "date-time" + }, + "updateDate" : { + "type" : "string", + "format" : "date-time" + }, + "updateOperatorExternalId" : { + "type" : "string" + }, + "debtPositionTypeOrgOperatorId" : { + "type" : "integer", + "format" : "int64" + }, + "debtPositionTypeOrgId" : { + "type" : "integer", + "format" : "int64" + }, + "operatorExternalUserId" : { + "type" : "string" }, "_links" : { "$ref" : "#/components/schemas/Links" } } }, - "CollectionModelObject" : { + "PagedModelDebtPositionTypeOrgOperators" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "objects" : { + "debtPositionTypeOrgOperatorses" : { "type" : "array", "items" : { - "type" : "object" + "$ref" : "#/components/schemas/DebtPositionTypeOrgOperators" } } } }, "_links" : { "$ref" : "#/components/schemas/Links" + }, + "page" : { + "$ref" : "#/components/schemas/PageMetadata" } } }, - "InstallmentNoPII" : { + "PaymentOption" : { "type" : "object", "properties" : { "creationDate" : { @@ -3434,88 +3393,50 @@ "updateOperatorExternalId" : { "type" : "string" }, - "installmentId" : { - "type" : "integer", - "format" : "int64" - }, "paymentOptionId" : { "type" : "integer", "format" : "int64" }, - "status" : { - "type" : "string" - }, - "iupdPagopa" : { - "type" : "string" - }, - "iud" : { - "type" : "string" - }, - "iuv" : { - "type" : "string" - }, - "iur" : { - "type" : "string" - }, - "iuf" : { - "type" : "string" - }, - "nav" : { - "type" : "string" - }, - "dueDate" : { - "type" : "string", - "format" : "date-time" - }, - "paymentTypeCode" : { - "type" : "string" - }, - "amountCents" : { + "debtPositionId" : { "type" : "integer", "format" : "int64" }, - "notificationFeeCents" : { + "totalAmountCents" : { "type" : "integer", "format" : "int64" }, - "remittanceInformation" : { - "type" : "string" - }, - "humanFriendlyRemittanceInformation" : { - "type" : "string" - }, - "balance" : { + "status" : { "type" : "string" }, - "legacyPaymentMetadata" : { - "type" : "string" + "multiDebtor" : { + "type" : "boolean" }, - "personalDataId" : { - "type" : "integer", - "format" : "int64" + "dueDate" : { + "type" : "string", + "format" : "date-time" }, - "debtorEntityType" : { + "description" : { "type" : "string" }, - "debtorFiscalCodeHash" : { + "paymentOptionType" : { "type" : "string", - "format" : "byte" + "enum" : [ "SINGLE_INSTALLMENT", "INSTALMENTS", "DOWN_PAYMENT" ] }, "_links" : { "$ref" : "#/components/schemas/Links" } } }, - "PagedModelInstallmentNoPII" : { + "PagedModelPaymentOption" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "installmentNoPIIs" : { + "paymentOptions" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/InstallmentNoPII" + "$ref" : "#/components/schemas/PaymentOption" } } } @@ -3528,16 +3449,16 @@ } } }, - "CollectionModelTransfer" : { + "CollectionModelInstallmentNoPII" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "transfers" : { + "installmentNoPIIs" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/TransferResponse" + "$ref" : "#/components/schemas/InstallmentNoPIIResponse" } } } @@ -3629,7 +3550,7 @@ } } }, - "DebtPositionTypeOrgOperators" : { + "ReceiptNoPII" : { "type" : "object", "properties" : { "creationDate" : { @@ -3643,32 +3564,109 @@ "updateOperatorExternalId" : { "type" : "string" }, - "debtPositionTypeOrgOperatorId" : { + "receiptId" : { "type" : "integer", "format" : "int64" }, - "debtPositionTypeOrgId" : { + "installmentId" : { "type" : "integer", "format" : "int64" }, - "operatorExternalUserId" : { + "paymentReceiptId" : { + "type" : "integer", + "format" : "int64" + }, + "noticeNumber" : { + "type" : "string" + }, + "orgFiscalCode" : { + "type" : "string" + }, + "outcome" : { + "type" : "string" + }, + "creditorReferenceId" : { "type" : "string" }, + "paymentAmountCents" : { + "type" : "integer", + "format" : "int64" + }, + "description" : { + "type" : "string" + }, + "companyName" : { + "type" : "string" + }, + "officeName" : { + "type" : "string" + }, + "idPsp" : { + "type" : "string" + }, + "pspFiscalCode" : { + "type" : "string" + }, + "pspPartitaIva" : { + "type" : "string" + }, + "pspCompanyName" : { + "type" : "string" + }, + "idChannel" : { + "type" : "string" + }, + "channelDescription" : { + "type" : "string" + }, + "paymentMethod" : { + "type" : "string" + }, + "feeCents" : { + "type" : "integer", + "format" : "int64" + }, + "paymentDateTime" : { + "type" : "string", + "format" : "date-time" + }, + "applicationDate" : { + "type" : "string", + "format" : "date-time" + }, + "transferDate" : { + "type" : "string", + "format" : "date-time" + }, + "standin" : { + "type" : "boolean" + }, + "debtorEntityType" : { + "type" : "string" + }, + "personalDataId" : { + "type" : "integer", + "format" : "int64" + }, + "debtorFiscalCodeHash" : { + "type" : "string", + "format" : "byte" + }, "_links" : { "$ref" : "#/components/schemas/Links" } } }, - "PagedModelDebtPositionTypeOrgOperators" : { + "PagedModelReceiptNoPII" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "debtPositionTypeOrgOperatorses" : { + "receiptNoPIIs" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/DebtPositionTypeOrgOperators" + "$ref" : "#/components/schemas/ReceiptNoPII" } } } @@ -3781,128 +3779,6 @@ } } }, - "DebtPositionTypeOrg" : { - "type" : "object", - "properties" : { - "creationDate" : { - "type" : "string", - "format" : "date-time" - }, - "updateDate" : { - "type" : "string", - "format" : "date-time" - }, - "updateOperatorExternalId" : { - "type" : "string" - }, - "debtPositionTypeOrgId" : { - "type" : "integer", - "format" : "int64" - }, - "debtPositionTypeId" : { - "type" : "integer", - "format" : "int64" - }, - "organizationId" : { - "type" : "integer", - "format" : "int64" - }, - "balance" : { - "type" : "string" - }, - "code" : { - "type" : "string" - }, - "description" : { - "type" : "string" - }, - "iban" : { - "type" : "string" - }, - "postalIban" : { - "type" : "string" - }, - "postalAccountCode" : { - "type" : "string" - }, - "holderPostalCc" : { - "type" : "string" - }, - "orgSector" : { - "type" : "string" - }, - "xsdDefinitionRef" : { - "type" : "string" - }, - "amountCents" : { - "type" : "integer", - "format" : "int64" - }, - "externalPaymentUrl" : { - "type" : "string" - }, - "flagAnonymousFiscalCode" : { - "type" : "boolean" - }, - "flagMandatoryDueDate" : { - "type" : "boolean" - }, - "flagSpontaneous" : { - "type" : "boolean" - }, - "flagNotifyIo" : { - "type" : "boolean" - }, - "ioTemplateMessage" : { - "type" : "string" - }, - "flagActive" : { - "type" : "boolean" - }, - "flagNotifyOutcomePush" : { - "type" : "boolean" - }, - "notifyOutcomePushOrgSilServiceId" : { - "type" : "integer", - "format" : "int64" - }, - "flagAmountActualization" : { - "type" : "boolean" - }, - "amountActualizationOrgSilServiceId" : { - "type" : "integer", - "format" : "int64" - }, - "flagExternal" : { - "type" : "boolean" - }, - "_links" : { - "$ref" : "#/components/schemas/Links" - } - } - }, - "PagedModelDebtPositionTypeOrg" : { - "type" : "object", - "properties" : { - "_embedded" : { - "type" : "object", - "properties" : { - "debtPositionTypeOrgs" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/DebtPositionTypeOrg" - } - } - } - }, - "_links" : { - "$ref" : "#/components/schemas/Links" - }, - "page" : { - "$ref" : "#/components/schemas/PageMetadata" - } - } - }, "DebtPositionTypeOrgOperatorsRequestBody" : { "type" : "object", "properties" : { diff --git a/openapi/p4pa-debt-position.openapi.yaml b/openapi/p4pa-debt-position.openapi.yaml index de46d75..1d1b035 100644 --- a/openapi/p4pa-debt-position.openapi.yaml +++ b/openapi/p4pa-debt-position.openapi.yaml @@ -12,6 +12,13 @@ paths: tags: - debt-position operationId: createDebtPosition + parameters: + - name: massive + in: query + description: Indicates if the operation is massive (true) or single (false). + required: false + schema: + type: boolean requestBody: content: application/json: @@ -27,6 +34,8 @@ paths: $ref: '#/components/schemas/DebtPositionDTO' "400": description: Invalid request + "409": + description: Debt position already exists "500": description: Internal server error /debt-positions/{debtPositionId}/finalize-sync-status: @@ -53,8 +62,16 @@ paths: description: Ok "400": description: Invalid request - "500": - description: Internal server error + content: + application/json: + schema: + $ref: '#/components/schemas/DebtPositionErrorDTO' + '500': + description: Server Error + content: + application/json: + schema: + $ref: '#/components/schemas/DebtPositionErrorDTO' security: - BearerAuth: [] components: @@ -78,7 +95,7 @@ components: description: type: string status: - type: string + $ref: "#/components/schemas/DebtPositionStatus" ingestionFlowFileId: type: integer format: int64 @@ -126,7 +143,7 @@ components: type: integer format: int64 status: - type: string + $ref: "#/components/schemas/PaymentOptionStatus" multiDebtor: type: boolean dueDate: @@ -159,7 +176,7 @@ components: type: integer format: int64 status: - type: string + $ref: "#/components/schemas/InstallmentStatus" iupdPagopa: type: string iud: @@ -339,10 +356,42 @@ components: type: string email: type: string + DebtPositionStatus: + type: string + enum: + - TO_SYNC + - REPORTED + - PAID + - PARTIALLY_PAID + - CANCELLED + - INVALID + - EXPIRED + - UNPAID + PaymentOptionStatus: + type: string + enum: + - TO_SYNC + - REPORTED + - PAID + - PARTIALLY_PAID + - CANCELLED + - INVALID + - EXPIRED + - UNPAID + InstallmentStatus: + type: string + enum: + - TO_SYNC + - REPORTED + - PAID + - CANCELLED + - INVALID + - EXPIRED + - UNPAID SyncStatusDTO: type: object additionalProperties: - $ref: "#/components/schemas/IudSyncStatusUpdateDTO" + $ref: "#/components/schemas/IudSyncStatusUpdateDTO" IudSyncStatusUpdateDTO: type: object properties: @@ -350,3 +399,16 @@ components: type: string iupdPagopa: type: string + DebtPositionErrorDTO: + type: object + required: + - code + - message + properties: + code: + type: string + enum: + - DEBT_POSITION_IVALID_REQUEST + - DEBT_POSITION_GENERIC_ERROR + message: + type: string diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerImpl.java b/src/main/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerImpl.java index 332bd1f..bbc2efa 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerImpl.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerImpl.java @@ -3,7 +3,7 @@ import it.gov.pagopa.pu.debtpositions.controller.generated.DebtPositionApi; import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; import it.gov.pagopa.pu.debtpositions.dto.generated.IudSyncStatusUpdateDTO; -import it.gov.pagopa.pu.debtpositions.service.DebtPositionService; +import it.gov.pagopa.pu.debtpositions.service.statusalign.DebtPositionHierarchyStatusAlignerService; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RestController; @@ -12,20 +12,21 @@ @RestController public class DebtPositionControllerImpl implements DebtPositionApi { - private final DebtPositionService debtPositionService; - public DebtPositionControllerImpl(DebtPositionService debtPositionService) { - this.debtPositionService = debtPositionService; + private final DebtPositionHierarchyStatusAlignerService debtPositionHierarchyStatusAlignerService; + + public DebtPositionControllerImpl(DebtPositionHierarchyStatusAlignerService debtPositionHierarchyStatusAlignerService) { + this.debtPositionHierarchyStatusAlignerService = debtPositionHierarchyStatusAlignerService; } @Override - public ResponseEntity createDebtPosition(DebtPositionDTO debtPositionDTO) { - return DebtPositionApi.super.createDebtPosition(debtPositionDTO); + public ResponseEntity createDebtPosition(DebtPositionDTO debtPositionDTO, Boolean massive) { + return DebtPositionApi.super.createDebtPosition(debtPositionDTO, massive); } @Override public ResponseEntity finalizeSyncStatus(Long debtPositionId, Map requestBody) { - debtPositionService.finalizeSyncStatus(debtPositionId, requestBody); + debtPositionHierarchyStatusAlignerService.finalizeSyncStatus(debtPositionId, requestBody); return new ResponseEntity<>(HttpStatus.OK); } } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/dto/Installment.java b/src/main/java/it/gov/pagopa/pu/debtpositions/dto/Installment.java index 8843957..2c17304 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/dto/Installment.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/dto/Installment.java @@ -1,6 +1,7 @@ package it.gov.pagopa.pu.debtpositions.dto; import com.fasterxml.jackson.annotation.JsonIgnore; +import it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentStatus; import it.gov.pagopa.pu.debtpositions.model.InstallmentNoPII; import it.gov.pagopa.pu.debtpositions.model.Transfer; import lombok.AllArgsConstructor; @@ -20,7 +21,7 @@ public class Installment { private Long installmentId; private Long paymentOptionId; - private String status; + private InstallmentStatus status; private String iupdPagopa; private String iud; private String iuv; diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/enums/DebtPositionStatus.java b/src/main/java/it/gov/pagopa/pu/debtpositions/enums/DebtPositionStatus.java deleted file mode 100644 index 3496310..0000000 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/enums/DebtPositionStatus.java +++ /dev/null @@ -1,13 +0,0 @@ -package it.gov.pagopa.pu.debtpositions.enums; - -public enum DebtPositionStatus { - - TO_SYNC, - REPORTED, - PAID, - PARTIALLY_PAID, - CANCELLED, - INVALID, - EXPIRED, - UNPAID -} diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/exception/DebtPositionExceptionHandler.java b/src/main/java/it/gov/pagopa/pu/debtpositions/exception/DebtPositionExceptionHandler.java new file mode 100644 index 0000000..d38c2d2 --- /dev/null +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/exception/DebtPositionExceptionHandler.java @@ -0,0 +1,46 @@ +package it.gov.pagopa.pu.debtpositions.exception; + +import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionErrorDTO; +import it.gov.pagopa.pu.debtpositions.exception.custom.InvalidStatusException; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import org.springframework.core.Ordered; +import org.springframework.core.annotation.Order; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + + +@RestControllerAdvice +@Slf4j +@Order(Ordered.HIGHEST_PRECEDENCE) +public class DebtPositionExceptionHandler { + + @ExceptionHandler({InvalidStatusException.class}) + public ResponseEntity handleInternalError(RuntimeException ex, HttpServletRequest request){ + return handleWorkflowErrorException(ex, request, HttpStatus.BAD_REQUEST, DebtPositionErrorDTO.CodeEnum.IVALID_REQUEST); + } + + static ResponseEntity handleWorkflowErrorException(RuntimeException ex, HttpServletRequest request, HttpStatus httpStatus, DebtPositionErrorDTO.CodeEnum errorEnum) { + String message = logException(ex, request, httpStatus); + + return ResponseEntity + .status(httpStatus) + .body(DebtPositionErrorDTO.builder().code(errorEnum).message(message).build()); + } + + private static String logException(RuntimeException ex, HttpServletRequest request, HttpStatus httpStatus) { + String message = ex.getMessage(); + log.info("A {} occurred handling request {}: HttpStatus {} - {}", + ex.getClass(), + getRequestDetails(request), + httpStatus.value(), + message); + return message; + } + + static String getRequestDetails(HttpServletRequest request) { + return "%s %s".formatted(request.getMethod(), request.getRequestURI()); + } +} diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/exception/custom/InvalidStatusException.java b/src/main/java/it/gov/pagopa/pu/debtpositions/exception/custom/InvalidStatusException.java new file mode 100644 index 0000000..6cb026f --- /dev/null +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/exception/custom/InvalidStatusException.java @@ -0,0 +1,8 @@ +package it.gov.pagopa.pu.debtpositions.exception.custom; + +public class InvalidStatusException extends RuntimeException{ + + public InvalidStatusException(String message) { + super(message); + } +} diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/model/DebtPosition.java b/src/main/java/it/gov/pagopa/pu/debtpositions/model/DebtPosition.java index 49d3cef..75b06de 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/model/DebtPosition.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/model/DebtPosition.java @@ -1,11 +1,8 @@ package it.gov.pagopa.pu.debtpositions.model; +import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionStatus; import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; +import lombok.*; import java.io.Serializable; import java.time.OffsetDateTime; @@ -38,7 +35,8 @@ public class DebtPosition extends BaseEntity implements Serializable { private Long debtPositionId; private String iupdOrg; private String description; - private String status; + @Enumerated(EnumType.STRING) + private DebtPositionStatus status; private Long ingestionFlowFileId; private Long ingestionFlowFileLineNumber; private Long organizationId; diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/model/InstallmentNoPII.java b/src/main/java/it/gov/pagopa/pu/debtpositions/model/InstallmentNoPII.java index fd51a7a..7886c8f 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/model/InstallmentNoPII.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/model/InstallmentNoPII.java @@ -1,5 +1,6 @@ package it.gov.pagopa.pu.debtpositions.model; +import it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentStatus; import jakarta.annotation.Nonnull; import jakarta.persistence.*; import lombok.AllArgsConstructor; @@ -27,7 +28,8 @@ public class InstallmentNoPII extends BaseEntity implements Serializable, Compar @SequenceGenerator(name = "installment_generator", sequenceName = "installment_seq", allocationSize = 1) private Long installmentId; private Long paymentOptionId; - private String status; + @Enumerated(EnumType.STRING) + private InstallmentStatus status; private String iupdPagopa; private String iud; private String iuv; diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/model/PaymentOption.java b/src/main/java/it/gov/pagopa/pu/debtpositions/model/PaymentOption.java index 0913cf5..08af719 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/model/PaymentOption.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/model/PaymentOption.java @@ -1,13 +1,10 @@ package it.gov.pagopa.pu.debtpositions.model; +import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus; import it.gov.pagopa.pu.debtpositions.enums.PaymentOptionType; import jakarta.annotation.Nonnull; import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; +import lombok.*; import java.io.Serializable; import java.time.OffsetDateTime; @@ -29,7 +26,8 @@ public class PaymentOption extends BaseEntity implements Serializable, Comparabl private Long paymentOptionId; private Long debtPositionId; private Long totalAmountCents; - private String status; + @Enumerated(EnumType.STRING) + private PaymentOptionStatus status; private boolean multiDebtor; private OffsetDateTime dueDate; private String description; diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/repository/DebtPositionRepository.java b/src/main/java/it/gov/pagopa/pu/debtpositions/repository/DebtPositionRepository.java index d39be75..4911a04 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/repository/DebtPositionRepository.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/repository/DebtPositionRepository.java @@ -1,12 +1,15 @@ package it.gov.pagopa.pu.debtpositions.repository; +import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionStatus; import it.gov.pagopa.pu.debtpositions.model.DebtPosition; +import jakarta.transaction.Transactional; import org.springframework.data.jpa.repository.EntityGraph; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.data.rest.core.annotation.RepositoryRestResource; +import org.springframework.data.rest.core.annotation.RestResource; @RepositoryRestResource(path = "debt-positions") public interface DebtPositionRepository extends JpaRepository { @@ -14,7 +17,9 @@ public interface DebtPositionRepository extends JpaRepository { - InstallmentNoPII findByIudAndIupdPagopaAndStatus(String iud, String iupdPagopa, String status); - + @RestResource(exported = false) + @Transactional @Modifying - @Query("UPDATE InstallmentNoPII i SET i.status = :status WHERE i.installmentId = :installmentId") - void updateStatus(@Param("installmentId") Long installmentId, @Param("status") String status); + @Query("UPDATE InstallmentNoPII i SET i.status = :status, i.iupdPagopa = :iupdPagopa WHERE i.installmentId = :installmentId") + void updateStatusAndIupdPagopa(@Param("installmentId") Long installmentId, @Param("iupdPagopa") String iupdPagopa, @Param("status") InstallmentStatus status); + } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/repository/PaymentOptionRepository.java b/src/main/java/it/gov/pagopa/pu/debtpositions/repository/PaymentOptionRepository.java index cc8cea8..195100f 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/repository/PaymentOptionRepository.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/repository/PaymentOptionRepository.java @@ -1,17 +1,22 @@ package it.gov.pagopa.pu.debtpositions.repository; +import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus; import it.gov.pagopa.pu.debtpositions.model.PaymentOption; +import jakarta.transaction.Transactional; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.data.rest.core.annotation.RepositoryRestResource; +import org.springframework.data.rest.core.annotation.RestResource; @RepositoryRestResource(path = "payment-options") public interface PaymentOptionRepository extends JpaRepository { + @RestResource(exported = false) + @Transactional @Modifying @Query("UPDATE PaymentOption p SET p.status = :status WHERE p.paymentOptionId = :paymentOptionId") - void updateStatus(@Param("paymentOptionId") Long paymentOptionId, @Param("status") String status); + void updateStatus(@Param("paymentOptionId") Long paymentOptionId, @Param("status") PaymentOptionStatus status); } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionService.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionService.java index 58cb626..d834d09 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionService.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionService.java @@ -1,12 +1,8 @@ package it.gov.pagopa.pu.debtpositions.service; import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; -import it.gov.pagopa.pu.debtpositions.dto.generated.IudSyncStatusUpdateDTO; - -import java.util.Map; public interface DebtPositionService { void saveDebtPosition(DebtPositionDTO debtPositionDTO); - void finalizeSyncStatus(Long debtPositionId, Map syncStatusDTO); } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImpl.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImpl.java index 2e6eacb..f9900e6 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImpl.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImpl.java @@ -2,22 +2,19 @@ import it.gov.pagopa.pu.debtpositions.dto.Installment; import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; -import it.gov.pagopa.pu.debtpositions.dto.generated.IudSyncStatusUpdateDTO; import it.gov.pagopa.pu.debtpositions.mapper.DebtPositionMapper; 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.repository.*; +import it.gov.pagopa.pu.debtpositions.repository.DebtPositionRepository; +import it.gov.pagopa.pu.debtpositions.repository.InstallmentPIIRepository; +import it.gov.pagopa.pu.debtpositions.repository.PaymentOptionRepository; +import it.gov.pagopa.pu.debtpositions.repository.TransferRepository; import jakarta.transaction.Transactional; import org.springframework.data.util.Pair; import org.springframework.stereotype.Service; -import java.util.List; import java.util.Map; -import java.util.Optional; -import java.util.stream.Stream; - -import static it.gov.pagopa.pu.debtpositions.enums.DebtPositionStatus.TO_SYNC; @Service public class DebtPositionServiceImpl implements DebtPositionService { @@ -26,17 +23,15 @@ public class DebtPositionServiceImpl implements DebtPositionService { private final PaymentOptionRepository paymentOptionRepository; private final InstallmentPIIRepository installmentRepository; private final TransferRepository transferRepository; - private final InstallmentNoPIIRepository installmentNoPIIRepository; private final DebtPositionMapper debtPositionMapper; public DebtPositionServiceImpl(DebtPositionRepository debtPositionRepository, PaymentOptionRepository paymentOptionRepository, InstallmentPIIRepository installmentRepository, TransferRepository transferRepository, - DebtPositionMapper debtPositionMapper, InstallmentNoPIIRepository installmentNoPIIRepository) { + DebtPositionMapper debtPositionMapper) { this.debtPositionRepository = debtPositionRepository; this.paymentOptionRepository = paymentOptionRepository; this.installmentRepository = installmentRepository; this.transferRepository = transferRepository; - this.installmentNoPIIRepository = installmentNoPIIRepository; this.debtPositionMapper = debtPositionMapper; } @@ -63,51 +58,5 @@ public void saveDebtPosition(DebtPositionDTO debtPositionDTO) { }); }); } - - @Override - public void finalizeSyncStatus(Long debtPositionId, Map syncStatusDTO) { - DebtPosition debtPosition = debtPositionRepository.findOneWithAllDataByDebtPositionId(debtPositionId); - - debtPosition.getPaymentOptions().forEach(paymentOption -> - paymentOption.getInstallments().stream() - .filter(installment -> TO_SYNC.name().equals(installment.getStatus())) - .filter(installment -> syncStatusDTO.containsKey(installment.getIud())) - .filter(installment -> installment.getIupdPagopa().equals(syncStatusDTO.get(installment.getIud()).getIupdPagopa())) - .forEach(installment -> { - IudSyncStatusUpdateDTO updateDTO = syncStatusDTO.get(installment.getIud()); - installment.setStatus(updateDTO.getNewStatus()); - installmentNoPIIRepository.updateStatus( - installment.getInstallmentId(), - updateDTO.getNewStatus() - ); - })); - - debtPosition.getPaymentOptions().forEach(this::updatePaymentOptionStatus); - - updateDebtPositionStatus(debtPosition); - } - - private Optional verifyStatusUniqueness(Stream stream) { - List distinctItems = stream.distinct().toList(); - return distinctItems.size() == 1 - ? Optional.of(distinctItems.getFirst()) - : Optional.empty(); - } - - private void updatePaymentOptionStatus(PaymentOption paymentOption) { - verifyStatusUniqueness(paymentOption.getInstallments().stream().map(InstallmentNoPII::getStatus)) - .ifPresent(status -> { - paymentOption.setStatus(status); - paymentOptionRepository.updateStatus(paymentOption.getPaymentOptionId(), status); - }); - } - - private void updateDebtPositionStatus(DebtPosition debtPosition) { - verifyStatusUniqueness(debtPosition.getPaymentOptions().stream().map(PaymentOption::getStatus)) - .ifPresent(status -> { - debtPosition.setStatus(status); - debtPositionRepository.updateStatus(debtPosition.getDebtPositionId(), status); - }); - } } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerService.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerService.java new file mode 100644 index 0000000..52f0a72 --- /dev/null +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerService.java @@ -0,0 +1,10 @@ +package it.gov.pagopa.pu.debtpositions.service.statusalign; + +import it.gov.pagopa.pu.debtpositions.dto.generated.IudSyncStatusUpdateDTO; + +import java.util.Map; + +public interface DebtPositionHierarchyStatusAlignerService { + + void finalizeSyncStatus(Long debtPositionId, Map syncStatusDTO); +} diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerServiceImpl.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerServiceImpl.java new file mode 100644 index 0000000..d1e4283 --- /dev/null +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerServiceImpl.java @@ -0,0 +1,62 @@ +package it.gov.pagopa.pu.debtpositions.service.statusalign; + +import it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentStatus; +import it.gov.pagopa.pu.debtpositions.dto.generated.IudSyncStatusUpdateDTO; +import it.gov.pagopa.pu.debtpositions.exception.custom.InvalidStatusException; +import it.gov.pagopa.pu.debtpositions.model.DebtPosition; +import it.gov.pagopa.pu.debtpositions.repository.DebtPositionRepository; +import it.gov.pagopa.pu.debtpositions.repository.InstallmentNoPIIRepository; +import it.gov.pagopa.pu.debtpositions.service.statusalign.debtposition.DebtPositionInnerStatusAlignerService; +import it.gov.pagopa.pu.debtpositions.service.statusalign.paymentoption.PaymentOptionInnerStatusAlignerService; +import jakarta.transaction.Transactional; + +import java.util.Map; + +import static it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentStatus.TO_SYNC; + +public class DebtPositionHierarchyStatusAlignerServiceImpl implements DebtPositionHierarchyStatusAlignerService { + + private final DebtPositionRepository debtPositionRepository; + private final InstallmentNoPIIRepository installmentNoPIIRepository; + private final PaymentOptionInnerStatusAlignerService paymentOptionInnerStatusAlignerService; + private final DebtPositionInnerStatusAlignerService debtPositionInnerStatusAlignerService; + + + public DebtPositionHierarchyStatusAlignerServiceImpl(DebtPositionRepository debtPositionRepository, + InstallmentNoPIIRepository installmentNoPIIRepository, PaymentOptionInnerStatusAlignerService paymentOptionInnerStatusAlignerService, DebtPositionInnerStatusAlignerService debtPositionInnerStatusAlignerService) { + this.debtPositionRepository = debtPositionRepository; + this.installmentNoPIIRepository = installmentNoPIIRepository; + this.paymentOptionInnerStatusAlignerService = paymentOptionInnerStatusAlignerService; + this.debtPositionInnerStatusAlignerService = debtPositionInnerStatusAlignerService; + } + + @Transactional + @Override + public void finalizeSyncStatus(Long debtPositionId, Map syncStatusDTO) { + DebtPosition debtPosition = debtPositionRepository.findOneWithAllDataByDebtPositionId(debtPositionId); + + debtPosition.getPaymentOptions().forEach(paymentOption -> + paymentOption.getInstallments().stream() + .filter(installment -> TO_SYNC.equals(installment.getStatus())) + .filter(installment -> syncStatusDTO.containsKey(installment.getIud())) + .forEach(installment -> { + IudSyncStatusUpdateDTO updateDTO = syncStatusDTO.get(installment.getIud()); + + try { + InstallmentStatus newStatus = InstallmentStatus.valueOf(updateDTO.getNewStatus().toUpperCase()); + installment.setStatus(newStatus); + installmentNoPIIRepository.updateStatusAndIupdPagopa( + installment.getInstallmentId(), + updateDTO.getIupdPagopa(), + newStatus + ); + } catch (IllegalArgumentException e) { + throw new InvalidStatusException("Invalid status: " + updateDTO.getNewStatus()); + } + }) + ); + + debtPosition.getPaymentOptions().forEach(paymentOptionInnerStatusAlignerService::updatePaymentOptionStatus); + debtPositionInnerStatusAlignerService.updateDebtPositionStatus(debtPosition); + } +} diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/StatusRulesHandler.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/StatusRulesHandler.java new file mode 100644 index 0000000..def1b30 --- /dev/null +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/StatusRulesHandler.java @@ -0,0 +1,87 @@ +package it.gov.pagopa.pu.debtpositions.service.statusalign; + +import java.util.List; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.function.Predicate; + +public abstract class StatusRulesHandler> { + + private final E syncStatus; + private final E paidStatus; + private final E unpaidStatus; + private final E expiredStatus; + private final E cancelledStatus; + private final E reportedStatus; + private final E invalidStatus; + + protected StatusRulesHandler(E syncStatus, E paidStatus, E unpaidStatus, E expiredStatus, E cancelledStatus, E reportedStatus, E invalidStatus) { + this.syncStatus = syncStatus; + this.paidStatus = paidStatus; + this.unpaidStatus = unpaidStatus; + this.expiredStatus = expiredStatus; + this.cancelledStatus = cancelledStatus; + this.reportedStatus = reportedStatus; + this.invalidStatus = invalidStatus; + } + + public > void updateEntityStatus(T entity, + Function> childStatusExtractor, + Function, C> statusDeterminer, + BiConsumer statusUpdater, + BiConsumer repositoryUpdater) { + + List childStatuses = childStatusExtractor.apply(entity); + C newStatus = statusDeterminer.apply(childStatuses); + statusUpdater.accept(entity, newStatus); + repositoryUpdater.accept(entity, newStatus); + } + + public boolean isToSync(List statusList) { + return statusList.contains(syncStatus); + } + + public boolean isPartiallyPaid(List statusList) { + return statusList.contains(paidStatus) && + (statusList.contains(unpaidStatus) || statusList.contains(expiredStatus)); + } + + public boolean isUnpaid(List statusList) { + return allMatchOrEmpty(statusList, status -> status.equals(unpaidStatus)) || + (allMatchOrEmpty(statusList, status -> status.equals(cancelledStatus) || status.equals(unpaidStatus)) && + statusList.contains(unpaidStatus)); + } + + public boolean isPaid(List statusList) { + return allMatchOrEmpty(statusList, status -> status.equals(paidStatus)) || + (allMatchOrEmpty(statusList, status -> status.equals(cancelledStatus) || status.equals(paidStatus)) && + statusList.contains(paidStatus)); + } + + public boolean isReported(List statusList) { + return allMatchOrEmpty(statusList, status -> status.equals(reportedStatus)) || + (allMatchOrEmpty(statusList, status -> status.equals(cancelledStatus) || status.equals(reportedStatus)) && + statusList.contains(reportedStatus)); + } + + public boolean isInvalid(List statusList) { + return allMatchOrEmpty(statusList, status -> status.equals(invalidStatus)) || + (allMatchOrEmpty(statusList, status -> status.equals(cancelledStatus) || status.equals(invalidStatus)) && + statusList.contains(invalidStatus)); + } + + public boolean isCancelled(List statusList) { + return allMatchOrEmpty(statusList, status -> status.equals(cancelledStatus)); + } + + public boolean isExpired(List statusList) { + return allMatchOrEmpty(statusList, status -> status.equals(expiredStatus)); + } + + private boolean allMatchOrEmpty(List statusList, Predicate predicate) { + if (statusList.isEmpty()) { + return false; + } + return statusList.stream().allMatch(predicate); + } +} diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionInnerStatusAlignerService.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionInnerStatusAlignerService.java new file mode 100644 index 0000000..fc896e0 --- /dev/null +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionInnerStatusAlignerService.java @@ -0,0 +1,8 @@ +package it.gov.pagopa.pu.debtpositions.service.statusalign.debtposition; + +import it.gov.pagopa.pu.debtpositions.model.DebtPosition; + +public interface DebtPositionInnerStatusAlignerService { + + void updateDebtPositionStatus(DebtPosition debtPosition); +} diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionInnerStatusAlignerServiceImpl.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionInnerStatusAlignerServiceImpl.java new file mode 100644 index 0000000..950754d --- /dev/null +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionInnerStatusAlignerServiceImpl.java @@ -0,0 +1,25 @@ +package it.gov.pagopa.pu.debtpositions.service.statusalign.debtposition; + +import it.gov.pagopa.pu.debtpositions.model.DebtPosition; +import it.gov.pagopa.pu.debtpositions.model.PaymentOption; +import it.gov.pagopa.pu.debtpositions.repository.DebtPositionRepository; + +public class DebtPositionInnerStatusAlignerServiceImpl extends DebtPositionStatusChecker implements DebtPositionInnerStatusAlignerService{ + + private final DebtPositionRepository debtPositionRepository; + + public DebtPositionInnerStatusAlignerServiceImpl(DebtPositionRepository debtPositionRepository) { + this.debtPositionRepository = debtPositionRepository; + } + + @Override + public void updateDebtPositionStatus(DebtPosition debtPosition) { + updateEntityStatus( + debtPosition, + dp -> dp.getPaymentOptions().stream().map(PaymentOption::getStatus).toList(), + this::determineDebtPositionStatus, + DebtPosition::setStatus, + (dp, newStatus) -> debtPositionRepository.updateStatus(dp.getDebtPositionId(), newStatus) + ); + } +} diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusChecker.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusChecker.java new file mode 100644 index 0000000..e1c8178 --- /dev/null +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusChecker.java @@ -0,0 +1,41 @@ +package it.gov.pagopa.pu.debtpositions.service.statusalign.debtposition; + +import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionStatus; +import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus; +import it.gov.pagopa.pu.debtpositions.exception.custom.InvalidStatusException; +import it.gov.pagopa.pu.debtpositions.service.statusalign.StatusRulesHandler; +import org.springframework.stereotype.Service; + +import java.util.List; + +import static it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus.*; + +@Service +public class DebtPositionStatusChecker extends StatusRulesHandler { + + public DebtPositionStatusChecker() { + super(TO_SYNC, PAID, UNPAID, EXPIRED, CANCELLED, REPORTED, INVALID); + } + + public DebtPositionStatus determineDebtPositionStatus(List paymentOptionStatusList) { + if (isToSync(paymentOptionStatusList)){ + return DebtPositionStatus.TO_SYNC; + } else if (isPartiallyPaid(paymentOptionStatusList)){ + return DebtPositionStatus.PARTIALLY_PAID; + } else if (isUnpaid(paymentOptionStatusList)){ + return DebtPositionStatus.UNPAID; + } else if (isPaid(paymentOptionStatusList)){ + return DebtPositionStatus.PAID; + } else if (isReported(paymentOptionStatusList)){ + return DebtPositionStatus.REPORTED; + } else if (isInvalid(paymentOptionStatusList)){ + return DebtPositionStatus.INVALID; + } else if (isCancelled(paymentOptionStatusList)){ + return DebtPositionStatus.CANCELLED; + } else if (isExpired(paymentOptionStatusList)){ + return DebtPositionStatus.EXPIRED; + } else { + throw new InvalidStatusException("Unable to determine status for DebtPosition"); + } + } +} diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionInnerStatusAlignerService.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionInnerStatusAlignerService.java new file mode 100644 index 0000000..0b54fb1 --- /dev/null +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionInnerStatusAlignerService.java @@ -0,0 +1,8 @@ +package it.gov.pagopa.pu.debtpositions.service.statusalign.paymentoption; + +import it.gov.pagopa.pu.debtpositions.model.PaymentOption; + +public interface PaymentOptionInnerStatusAlignerService { + + void updatePaymentOptionStatus(PaymentOption paymentOption); +} diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionInnerStatusAlignerServiceImpl.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionInnerStatusAlignerServiceImpl.java new file mode 100644 index 0000000..456826d --- /dev/null +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionInnerStatusAlignerServiceImpl.java @@ -0,0 +1,25 @@ +package it.gov.pagopa.pu.debtpositions.service.statusalign.paymentoption; + +import it.gov.pagopa.pu.debtpositions.model.InstallmentNoPII; +import it.gov.pagopa.pu.debtpositions.model.PaymentOption; +import it.gov.pagopa.pu.debtpositions.repository.PaymentOptionRepository; + +public class PaymentOptionInnerStatusAlignerServiceImpl extends PaymentOptionStatusChecker implements PaymentOptionInnerStatusAlignerService{ + + private final PaymentOptionRepository paymentOptionRepository; + + public PaymentOptionInnerStatusAlignerServiceImpl(PaymentOptionRepository paymentOptionRepository) { + this.paymentOptionRepository = paymentOptionRepository; + } + + @Override + public void updatePaymentOptionStatus(PaymentOption paymentOption) { + updateEntityStatus( + paymentOption, + po -> po.getInstallments().stream().map(InstallmentNoPII::getStatus).toList(), + this::determinePaymentOptionStatus, + PaymentOption::setStatus, + (po, newStatus) -> paymentOptionRepository.updateStatus(po.getPaymentOptionId(), newStatus) + ); + } +} diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusChecker.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusChecker.java new file mode 100644 index 0000000..b0dc968 --- /dev/null +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusChecker.java @@ -0,0 +1,42 @@ +package it.gov.pagopa.pu.debtpositions.service.statusalign.paymentoption; + +import it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentStatus; +import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus; +import it.gov.pagopa.pu.debtpositions.exception.custom.InvalidStatusException; +import it.gov.pagopa.pu.debtpositions.service.statusalign.StatusRulesHandler; +import org.springframework.stereotype.Service; + +import java.util.List; + +import static it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus.TO_SYNC; + +@Service +public class PaymentOptionStatusChecker extends StatusRulesHandler{ + + public PaymentOptionStatusChecker() { + super(InstallmentStatus.TO_SYNC, InstallmentStatus.PAID, InstallmentStatus.UNPAID, + InstallmentStatus.EXPIRED, InstallmentStatus.CANCELLED, InstallmentStatus.REPORTED, InstallmentStatus.INVALID); + } + + public PaymentOptionStatus determinePaymentOptionStatus(List installmentStatusList) { + if (isToSync(installmentStatusList)) { + return TO_SYNC; + } else if (isPartiallyPaid(installmentStatusList)) { + return PaymentOptionStatus.PARTIALLY_PAID; + } else if (isUnpaid(installmentStatusList)) { + return PaymentOptionStatus.UNPAID; + } else if (isPaid(installmentStatusList)) { + return PaymentOptionStatus.PAID; + } else if (isReported(installmentStatusList)) { + return PaymentOptionStatus.REPORTED; + } else if (isInvalid(installmentStatusList)) { + return PaymentOptionStatus.INVALID; + } else if (isCancelled(installmentStatusList)) { + return PaymentOptionStatus.CANCELLED; + } else if (isExpired(installmentStatusList)) { + return PaymentOptionStatus.EXPIRED; + } else { + throw new InvalidStatusException("Unable to determine status for PaymentOption"); + } + } +} diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerTest.java index ecf6c91..e90d997 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerTest.java @@ -2,7 +2,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import it.gov.pagopa.pu.debtpositions.dto.generated.IudSyncStatusUpdateDTO; -import it.gov.pagopa.pu.debtpositions.service.DebtPositionService; +import it.gov.pagopa.pu.debtpositions.service.statusalign.DebtPositionHierarchyStatusAlignerService; import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.springframework.beans.factory.annotation.Autowired; @@ -29,7 +29,7 @@ class DebtPositionControllerTest { private ObjectMapper objectMapper; @MockitoBean - private DebtPositionService service; + private DebtPositionHierarchyStatusAlignerService service; @Test void whenFinalizeSyncStatusThenOk() throws Exception { @@ -47,7 +47,7 @@ void whenFinalizeSyncStatusThenOk() throws Exception { Mockito.doNothing().when(service).finalizeSyncStatus(id, syncStatusDTO); mockMvc.perform( - put("/sync/status/1") + put("/debt-positions/1/finalize-sync-status") .contentType(MediaType.APPLICATION_JSON_VALUE) .content(objectMapper.writeValueAsString(syncStatusDTO))) .andExpect(status().isOk()) diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/exception/DebtPositionExceptionHandlerTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/exception/DebtPositionExceptionHandlerTest.java new file mode 100644 index 0000000..888e168 --- /dev/null +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/exception/DebtPositionExceptionHandlerTest.java @@ -0,0 +1,61 @@ +package it.gov.pagopa.pu.debtpositions.exception; + +import it.gov.pagopa.pu.debtpositions.exception.custom.InvalidStatusException; +import lombok.extern.slf4j.Slf4j; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.http.MediaType; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.bean.override.mockito.MockitoSpyBean; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import static org.mockito.Mockito.doThrow; + +@ExtendWith({SpringExtension.class, MockitoExtension.class}) +@WebMvcTest(value = {DebtPositionExceptionHandlerTest.TestController.class}, excludeAutoConfiguration = SecurityAutoConfiguration.class) +@ContextConfiguration(classes = { + DebtPositionExceptionHandlerTest.TestController.class, + DebtPositionExceptionHandler.class}) +public class DebtPositionExceptionHandlerTest { + + public static final String DATA = "data"; + @Autowired + private MockMvc mockMvc; + + @MockitoSpyBean + private TestController testControllerSpy; + + @RestController + @Slf4j + static class TestController { + + @GetMapping("/test") + String testEndpoint(@RequestParam(DATA) String data) { + return "OK"; + } + } + + @Test + void handleInvalidStatusExceptionError() throws Exception { + doThrow(new InvalidStatusException("Error")).when(testControllerSpy).testEndpoint(DATA); + + mockMvc.perform(MockMvcRequestBuilders.get("/test") + .param(DATA, DATA) + .contentType(MediaType.APPLICATION_JSON) + .accept(MediaType.APPLICATION_JSON)) + .andExpect(MockMvcResultMatchers.status().isBadRequest()) + .andExpect(MockMvcResultMatchers.jsonPath("$.code").value("DEBT_POSITION_IVALID_REQUEST")) + .andExpect(MockMvcResultMatchers.jsonPath("$.message").value("Error")); + + } +} diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImplTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImplTest.java index 8ffa09a..8425e99 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImplTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/service/DebtPositionServiceImplTest.java @@ -2,13 +2,15 @@ import it.gov.pagopa.pu.debtpositions.dto.Installment; import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; -import it.gov.pagopa.pu.debtpositions.dto.generated.IudSyncStatusUpdateDTO; -import it.gov.pagopa.pu.debtpositions.mapper.DebtPositionMapper; +import it.gov.pagopa.pu.debtpositions.mapper.*; 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.repository.*; +import it.gov.pagopa.pu.debtpositions.repository.DebtPositionRepository; +import it.gov.pagopa.pu.debtpositions.repository.InstallmentPIIRepository; +import it.gov.pagopa.pu.debtpositions.repository.PaymentOptionRepository; +import it.gov.pagopa.pu.debtpositions.repository.TransferRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -17,7 +19,6 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.data.util.Pair; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TreeSet; @@ -28,31 +29,33 @@ import static it.gov.pagopa.pu.debtpositions.util.faker.InstallmentFaker.buildInstallmentNoPII; import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.buildPaymentOption; import static it.gov.pagopa.pu.debtpositions.util.faker.TransferFaker.buildTransfer; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.mockito.Mockito.verify; @ExtendWith(MockitoExtension.class) class DebtPositionServiceImplTest { @Mock - private DebtPositionRepository debtPositionRepositoryMock; - @Mock - private PaymentOptionRepository paymentOptionRepositoryMock; + private DebtPositionRepository debtPositionRepository; + @Mock - private InstallmentPIIRepository installmentRepositoryMock; + private PaymentOptionRepository paymentOptionRepository; + @Mock - private TransferRepository transferRepositoryMock; + private InstallmentPIIRepository installmentRepository; + @Mock - private InstallmentNoPIIRepository installmentNoPIIRepositoryMock; + private TransferRepository transferRepository; + @Mock - private DebtPositionMapper debtPositionMapperMock; + private DebtPositionMapper debtPositionMapper; - private DebtPositionService service; + private DebtPositionServiceImpl debtPositionService; @BeforeEach - void setUp(){ - service = new DebtPositionServiceImpl(debtPositionRepositoryMock, paymentOptionRepositoryMock, installmentRepositoryMock, transferRepositoryMock, debtPositionMapperMock, installmentNoPIIRepositoryMock); + void setUp() { + debtPositionService = new DebtPositionServiceImpl( + debtPositionRepository, paymentOptionRepository, installmentRepository, transferRepository, + debtPositionMapper + ); } @Test @@ -82,95 +85,18 @@ void givenValidDebtPositionDTO_WhenSaveDebtPosition_ThenSaveAllEntities() { Transfer savedTransfer = new Transfer(); savedTransfer.setTransferId(1L); - Mockito.when(debtPositionMapperMock.mapToModel(debtPositionDTO)).thenReturn(mappedPair); - Mockito.when(debtPositionRepositoryMock.save(Mockito.any(DebtPosition.class))).thenReturn(savedDebtPosition); - Mockito.when(paymentOptionRepositoryMock.save(Mockito.any(PaymentOption.class))).thenReturn(savedPaymentOption); - Mockito.when(installmentRepositoryMock.save(Mockito.any(Installment.class))).thenReturn(savedInstallment.getInstallmentId()); - Mockito.when(transferRepositoryMock.save(Mockito.any(Transfer.class))).thenReturn(savedTransfer); - - service.saveDebtPosition(debtPositionDTO); - - verify(debtPositionRepositoryMock, Mockito.times(1)).save(debtPosition); - verify(paymentOptionRepositoryMock, Mockito.times(1)).save(paymentOption); - verify(installmentRepositoryMock, Mockito.times(1)).save(installment); - verify(transferRepositoryMock, Mockito.times(1)).save(transfer); - } - - @Test - void givenFinalizeSyncStatusThenOk(){ - // Given - Long id = 1L; - String newStatus = "UNPAID"; - DebtPosition debtPosition = buildDebtPosition(); - - Mockito.when(debtPositionRepositoryMock.findOneWithAllDataByDebtPositionId(id)).thenReturn(debtPosition); - - Mockito.doNothing().when(installmentNoPIIRepositoryMock).updateStatus(id, newStatus); - - Mockito.doNothing().when(paymentOptionRepositoryMock).updateStatus(id, newStatus); - - Mockito.doNothing().when(debtPositionRepositoryMock).updateStatus(id, newStatus); - - Map syncStatusDTO = new HashMap<>(); - IudSyncStatusUpdateDTO iudSyncStatusUpdateDTO = IudSyncStatusUpdateDTO.builder() - .newStatus(newStatus) - .iupdPagopa("iupdPagoPa") - .build(); - - syncStatusDTO.put("iud", iudSyncStatusUpdateDTO); - - // When - service.finalizeSyncStatus(id, syncStatusDTO); - - // Then - verify(debtPositionRepositoryMock).findOneWithAllDataByDebtPositionId(id); - verify(installmentNoPIIRepositoryMock).updateStatus(id, newStatus); - verify(paymentOptionRepositoryMock).updateStatus(id, newStatus); - verify(debtPositionRepositoryMock).updateStatus(id, newStatus); - - assertEquals(newStatus, debtPosition.getStatus()); - assertEquals(newStatus, debtPosition.getPaymentOptions().getFirst().getStatus()); - assertEquals(newStatus, debtPosition.getPaymentOptions().getFirst().getInstallments().getFirst().getStatus()); - } - - @Test - void givenFinalizeSyncStatusWhenDifferentStatusThenOk(){ - // Given - Long id = 1L; - String newStatus = "UNPAID"; - DebtPosition debtPosition = buildDebtPosition(); - InstallmentNoPII installment = InstallmentNoPII.builder() - .installmentId(2L) - .paymentOptionId(1L) - .status("status") - .iupdPagopa("iupdPagoPa1") - .iud("iud1").build(); - - debtPosition.getPaymentOptions().getFirst().setInstallments(new TreeSet<>(List.of(buildInstallmentNoPII(), installment))); - - Mockito.when(debtPositionRepositoryMock.findOneWithAllDataByDebtPositionId(id)).thenReturn(debtPosition); - - Mockito.doNothing().when(installmentNoPIIRepositoryMock).updateStatus(id, newStatus); - - Map syncStatusDTO = new HashMap<>(); - IudSyncStatusUpdateDTO iudSyncStatusUpdateDTO = IudSyncStatusUpdateDTO.builder() - .newStatus(newStatus) - .iupdPagopa("iupdPagoPa") - .build(); - - syncStatusDTO.put("iud", iudSyncStatusUpdateDTO); - - // When - service.finalizeSyncStatus(id, syncStatusDTO); + Mockito.when(debtPositionMapper.mapToModel(debtPositionDTO)).thenReturn(mappedPair); + Mockito.when(debtPositionRepository.save(Mockito.any(DebtPosition.class))).thenReturn(savedDebtPosition); + Mockito.when(paymentOptionRepository.save(Mockito.any(PaymentOption.class))).thenReturn(savedPaymentOption); + Mockito.when(installmentRepository.save(Mockito.any(Installment.class))).thenReturn(savedInstallment.getInstallmentId()); + Mockito.when(transferRepository.save(Mockito.any(Transfer.class))).thenReturn(savedTransfer); - // Then - verify(debtPositionRepositoryMock).findOneWithAllDataByDebtPositionId(id); - verify(installmentNoPIIRepositoryMock).updateStatus(id, newStatus); + debtPositionService.saveDebtPosition(debtPositionDTO); - assertNotEquals(newStatus, debtPosition.getStatus()); - assertNotEquals(newStatus, debtPosition.getPaymentOptions().getFirst().getStatus()); - assertEquals(newStatus, debtPosition.getPaymentOptions().getFirst().getInstallments().getFirst().getStatus()); - assertNotEquals(newStatus, debtPosition.getPaymentOptions().getFirst().getInstallments().getLast().getStatus()); + Mockito.verify(debtPositionRepository, Mockito.times(1)).save(debtPosition); + Mockito.verify(paymentOptionRepository, Mockito.times(1)).save(paymentOption); + Mockito.verify(installmentRepository, Mockito.times(1)).save(installment); + Mockito.verify(transferRepository, Mockito.times(1)).save(transfer); } } diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerServiceTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerServiceTest.java new file mode 100644 index 0000000..448c15b --- /dev/null +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerServiceTest.java @@ -0,0 +1,100 @@ +package it.gov.pagopa.pu.debtpositions.service.statusalign; + +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.IudSyncStatusUpdateDTO; +import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus; +import it.gov.pagopa.pu.debtpositions.exception.custom.InvalidStatusException; +import it.gov.pagopa.pu.debtpositions.model.DebtPosition; +import it.gov.pagopa.pu.debtpositions.repository.DebtPositionRepository; +import it.gov.pagopa.pu.debtpositions.repository.InstallmentNoPIIRepository; +import it.gov.pagopa.pu.debtpositions.service.statusalign.debtposition.DebtPositionInnerStatusAlignerService; +import it.gov.pagopa.pu.debtpositions.service.statusalign.paymentoption.PaymentOptionInnerStatusAlignerService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.HashMap; +import java.util.Map; + +import static it.gov.pagopa.pu.debtpositions.util.faker.DebtPositionFaker.buildDebtPosition; +import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.buildPaymentOption; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +class DebtPositionHierarchyStatusAlignerServiceTest { + + @Mock + private DebtPositionRepository debtPositionRepositoryMock; + @Mock + private InstallmentNoPIIRepository installmentNoPIIRepositoryMock; + @Mock + private PaymentOptionInnerStatusAlignerService paymentOptionInnerStatusAlignerServiceMock; + @Mock + private DebtPositionInnerStatusAlignerService debtPositionInnerStatusAlignerServiceMock; + + private DebtPositionHierarchyStatusAlignerService service; + + @BeforeEach + void setUp() { + service = new DebtPositionHierarchyStatusAlignerServiceImpl(debtPositionRepositoryMock, installmentNoPIIRepositoryMock, paymentOptionInnerStatusAlignerServiceMock, debtPositionInnerStatusAlignerServiceMock); + } + + @Test + void givenFinalizeSyncStatusThenOk() { + Long id = 1L; + String newStatus = "UNPAID"; + String iupdPagoPa = "iupdPagoPa"; + DebtPosition debtPosition = buildDebtPosition(); + + Mockito.when(debtPositionRepositoryMock.findOneWithAllDataByDebtPositionId(id)).thenReturn(debtPosition); + Mockito.doNothing().when(installmentNoPIIRepositoryMock).updateStatusAndIupdPagopa(id, iupdPagoPa, InstallmentStatus.valueOf(newStatus)); + Mockito.doNothing().when(paymentOptionInnerStatusAlignerServiceMock).updatePaymentOptionStatus(buildPaymentOption()); + Mockito.doNothing().when(debtPositionInnerStatusAlignerServiceMock).updateDebtPositionStatus(debtPosition); + + Map syncStatusDTO = new HashMap<>(); + IudSyncStatusUpdateDTO iudSyncStatusUpdateDTO = IudSyncStatusUpdateDTO.builder() + .newStatus(newStatus) + .iupdPagopa(iupdPagoPa) + .build(); + + syncStatusDTO.put("iud", iudSyncStatusUpdateDTO); + service.finalizeSyncStatus(id, syncStatusDTO); + + verify(debtPositionRepositoryMock).findOneWithAllDataByDebtPositionId(id); + verify(installmentNoPIIRepositoryMock).updateStatusAndIupdPagopa(id, iupdPagoPa, InstallmentStatus.valueOf(newStatus)); + verify(paymentOptionInnerStatusAlignerServiceMock).updatePaymentOptionStatus(buildPaymentOption()); + verify(debtPositionInnerStatusAlignerServiceMock).updateDebtPositionStatus(debtPosition); + + assertEquals(DebtPositionStatus.UNPAID, debtPosition.getStatus()); + assertEquals(PaymentOptionStatus.UNPAID, debtPosition.getPaymentOptions().getFirst().getStatus()); + assertEquals(InstallmentStatus.UNPAID, debtPosition.getPaymentOptions().getFirst().getInstallments().getFirst().getStatus()); + } + + @Test + void givenFinalizeSyncStatusWhenIllegalStatusThenThrowInvalidStatusException() { + Long id = 1L; + String newStatus = "newStatus"; + String iupdPagoPa = "iupdPagoPa"; + DebtPosition debtPosition = buildDebtPosition(); + + Mockito.when(debtPositionRepositoryMock.findOneWithAllDataByDebtPositionId(id)).thenReturn(debtPosition); + + Map syncStatusDTO = new HashMap<>(); + IudSyncStatusUpdateDTO iudSyncStatusUpdateDTO = IudSyncStatusUpdateDTO.builder() + .newStatus(newStatus) + .iupdPagopa(iupdPagoPa) + .build(); + + syncStatusDTO.put("iud", iudSyncStatusUpdateDTO); + + Exception exception = assertThrows(InvalidStatusException.class, () -> service.finalizeSyncStatus(id, syncStatusDTO)); + assertEquals("Invalid status: newStatus", exception.getMessage()); + + } +} diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionInnerStatusAlignerServiceTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionInnerStatusAlignerServiceTest.java new file mode 100644 index 0000000..54b060f --- /dev/null +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionInnerStatusAlignerServiceTest.java @@ -0,0 +1,61 @@ +package it.gov.pagopa.pu.debtpositions.service.statusalign.debtposition; + +import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionStatus; +import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus; +import it.gov.pagopa.pu.debtpositions.model.DebtPosition; +import it.gov.pagopa.pu.debtpositions.model.PaymentOption; +import it.gov.pagopa.pu.debtpositions.repository.DebtPositionRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.TreeSet; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +class DebtPositionInnerStatusAlignerServiceTest { + + @Mock + private DebtPositionRepository debtPositionRepositoryMock; + + private DebtPositionInnerStatusAlignerService debtPositionInnerStatusAlignerService; + + @BeforeEach + void setUp() { + debtPositionInnerStatusAlignerService = new DebtPositionInnerStatusAlignerServiceImpl(debtPositionRepositoryMock); + } + + @Test + void testUpdateDebtPositionStatus() { + // given + DebtPosition debtPosition = new DebtPosition(); + debtPosition.setDebtPositionId(1L); + + PaymentOption paymentOption1 = new PaymentOption(); + paymentOption1.setPaymentOptionId(1L); + paymentOption1.setStatus(PaymentOptionStatus.TO_SYNC); + + PaymentOption paymentOption2 = new PaymentOption(); + paymentOption2.setPaymentOptionId(2L); + paymentOption2.setStatus(PaymentOptionStatus.PAID); + + debtPosition.setPaymentOptions(new TreeSet<>(List.of(paymentOption1, paymentOption2))); + + Mockito.doNothing().when(debtPositionRepositoryMock).updateStatus(1L, DebtPositionStatus.TO_SYNC); + + // when + debtPositionInnerStatusAlignerService.updateDebtPositionStatus(debtPosition); + + // then + assertEquals(DebtPositionStatus.TO_SYNC, debtPosition.getStatus()); + verify(debtPositionRepositoryMock, times(1)).updateStatus(1L, DebtPositionStatus.TO_SYNC); + } +} + diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusCheckerTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusCheckerTest.java new file mode 100644 index 0000000..b281b77 --- /dev/null +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusCheckerTest.java @@ -0,0 +1,86 @@ +package it.gov.pagopa.pu.debtpositions.service.statusalign.debtposition; + +import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionStatus; +import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus; +import it.gov.pagopa.pu.debtpositions.exception.custom.InvalidStatusException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class DebtPositionStatusCheckerTest { + + private DebtPositionStatusChecker checker; + + @BeforeEach + void setUp() { + checker = new DebtPositionStatusChecker(); + } + + @Test + void testDetermineDebtPositionStatus_ToSync() { + List paymentOptionStatusList = List.of(PaymentOptionStatus.TO_SYNC, PaymentOptionStatus.PAID); + DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + assertEquals(DebtPositionStatus.TO_SYNC, result); + } + + @Test + void testDetermineDebtPositionStatus_PartiallyPaid() { + List paymentOptionStatusList = List.of(PaymentOptionStatus.PAID, PaymentOptionStatus.UNPAID); + DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + assertEquals(DebtPositionStatus.PARTIALLY_PAID, result); + } + + @Test + void testDetermineDebtPositionStatus_Unpaid() { + List paymentOptionStatusList = List.of(PaymentOptionStatus.UNPAID, PaymentOptionStatus.UNPAID); + DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + assertEquals(DebtPositionStatus.UNPAID, result); + } + + @Test + void testDetermineDebtPositionStatus_Paid() { + List paymentOptionStatusList = List.of(PaymentOptionStatus.PAID, PaymentOptionStatus.PAID); + DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + assertEquals(DebtPositionStatus.PAID, result); + } + + @Test + void testDetermineDebtPositionStatus_Reported() { + List paymentOptionStatusList = List.of(PaymentOptionStatus.REPORTED, PaymentOptionStatus.CANCELLED); + DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + assertEquals(DebtPositionStatus.REPORTED, result); + } + + @Test + void testDetermineDebtPositionStatus_Invalid() { + List paymentOptionStatusList = List.of(PaymentOptionStatus.INVALID, PaymentOptionStatus.CANCELLED); + DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + assertEquals(DebtPositionStatus.INVALID, result); + } + + @Test + void testDetermineDebtPositionStatus_Cancelled() { + List paymentOptionStatusList = List.of(PaymentOptionStatus.CANCELLED, PaymentOptionStatus.CANCELLED); + DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + assertEquals(DebtPositionStatus.CANCELLED, result); + } + + @Test + void testDetermineDebtPositionStatus_Expired() { + List paymentOptionStatusList = List.of(PaymentOptionStatus.EXPIRED, PaymentOptionStatus.EXPIRED); + DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + assertEquals(DebtPositionStatus.EXPIRED, result); + } + + @Test + void testDetermineDebtPositionStatus_InvalidStatus() { + List paymentOptionStatusList = List.of(); + Exception exception = assertThrows(InvalidStatusException.class, () -> checker.determineDebtPositionStatus(paymentOptionStatusList)); + assertEquals("Unable to determine status for DebtPosition", exception.getMessage()); + } +} + diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionInnerStatusAlignerServiceTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionInnerStatusAlignerServiceTest.java new file mode 100644 index 0000000..eb0ee89 --- /dev/null +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionInnerStatusAlignerServiceTest.java @@ -0,0 +1,62 @@ +package it.gov.pagopa.pu.debtpositions.service.statusalign.paymentoption; + +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.InstallmentNoPII; +import it.gov.pagopa.pu.debtpositions.model.PaymentOption; +import it.gov.pagopa.pu.debtpositions.repository.PaymentOptionRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.TreeSet; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +@ExtendWith(MockitoExtension.class) +class PaymentOptionInnerStatusAlignerServiceTest { + + @Mock + private PaymentOptionRepository paymentOptionRepositoryMock; + + private PaymentOptionInnerStatusAlignerService service; + + @BeforeEach + void setUp() { + service = new PaymentOptionInnerStatusAlignerServiceImpl(paymentOptionRepositoryMock); + } + + @Test + void testUpdatePaymentOptionStatus(){ + // given + PaymentOption paymentOption = new PaymentOption(); + paymentOption.setPaymentOptionId(1L); + + InstallmentNoPII installmentNoPII1 = new InstallmentNoPII(); + installmentNoPII1.setInstallmentId(1L); + installmentNoPII1.setStatus(InstallmentStatus.TO_SYNC); + + InstallmentNoPII installmentNoPII2 = new InstallmentNoPII(); + installmentNoPII2.setInstallmentId(1L); + installmentNoPII2.setStatus(InstallmentStatus.PAID); + + paymentOption.setInstallments(new TreeSet<>(List.of(installmentNoPII1, installmentNoPII2))); + + Mockito.doNothing().when(paymentOptionRepositoryMock).updateStatus(1L, PaymentOptionStatus.TO_SYNC); + + // when + service.updatePaymentOptionStatus(paymentOption); + + // then + assertEquals(PaymentOptionStatus.TO_SYNC, paymentOption.getStatus()); + verify(paymentOptionRepositoryMock, times(1)).updateStatus(1L, PaymentOptionStatus.TO_SYNC); + } + + +} diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusCheckerTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusCheckerTest.java new file mode 100644 index 0000000..572c81c --- /dev/null +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusCheckerTest.java @@ -0,0 +1,85 @@ +package it.gov.pagopa.pu.debtpositions.service.statusalign.paymentoption; + +import it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentStatus; +import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus; +import it.gov.pagopa.pu.debtpositions.exception.custom.InvalidStatusException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class PaymentOptionStatusCheckerTest { + + private PaymentOptionStatusChecker checker; + + @BeforeEach + void setUp() { + checker = new PaymentOptionStatusChecker(); + } + + @Test + void testDeterminePaymentOptionStatus_ToSync() { + List installmentStatusList = List.of(InstallmentStatus.TO_SYNC, InstallmentStatus.PAID); + PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + assertEquals(PaymentOptionStatus.TO_SYNC, result); + } + + @Test + void testDeterminePaymentOptionStatus_PartiallyPaid() { + List installmentStatusList = List.of(InstallmentStatus.PAID, InstallmentStatus.UNPAID); + PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + assertEquals(PaymentOptionStatus.PARTIALLY_PAID, result); + } + + @Test + void testDeterminePaymentOptionStatus_Unpaid() { + List installmentStatusList = List.of(InstallmentStatus.UNPAID, InstallmentStatus.UNPAID); + PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + assertEquals(PaymentOptionStatus.UNPAID, result); + } + + @Test + void testDeterminePaymentOptionStatus_Paid() { + List installmentStatusList = List.of(InstallmentStatus.PAID, InstallmentStatus.PAID); + PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + assertEquals(PaymentOptionStatus.PAID, result); + } + + @Test + void testDeterminePaymentOptionStatus_Reported() { + List installmentStatusList = List.of(InstallmentStatus.REPORTED, InstallmentStatus.CANCELLED); + PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + assertEquals(PaymentOptionStatus.REPORTED, result); + } + + @Test + void testDeterminePaymentOptionStatus_Invalid() { + List installmentStatusList = List.of(InstallmentStatus.INVALID, InstallmentStatus.CANCELLED); + PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + assertEquals(PaymentOptionStatus.INVALID, result); + } + + @Test + void testDeterminePaymentOptionStatus_Cancelled() { + List installmentStatusList = List.of(InstallmentStatus.CANCELLED, InstallmentStatus.CANCELLED); + PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + assertEquals(PaymentOptionStatus.CANCELLED, result); + } + + @Test + void testDeterminePaymentOptionStatus_Expired() { + List installmentStatusList = List.of(InstallmentStatus.EXPIRED, InstallmentStatus.EXPIRED); + PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + assertEquals(PaymentOptionStatus.EXPIRED, result); + } + + @Test + void testDeterminePaymentOptionStatus_InvalidStatus() { + List installmentStatusList = List.of(); + Exception exception = assertThrows(InvalidStatusException.class, () -> checker.determinePaymentOptionStatus(installmentStatusList)); + assertEquals("Unable to determine status for PaymentOption", exception.getMessage()); + } +} diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/TestUtils.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/TestUtils.java index a08ec38..605cfad 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/util/TestUtils.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/TestUtils.java @@ -97,7 +97,7 @@ public static List reflectionEqualsByName(Object o1, Object o2, String.. Assertions.assertTrue(result, String.format("Invalid compare between methods%n%s = %s%n%s = %s", m1, v1, m2, v2)); } catch (NoSuchMethodException e) { - log.debug("Method {} is not defined in {}{}", m1, o2.getClass().getName(), e.getMessage()); + log.warn("Method {} is not defined in {}{}", m1, o2.getClass().getName(), e.getMessage()); } catch (IllegalAccessException | InvocationTargetException e) { throw new IllegalStateException(String.format("[ERROR] Something gone wrong comparing %s with %s%n%s", m1, m2, e.getMessage())); diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/DebtPositionFaker.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/DebtPositionFaker.java index 01efd1e..9260711 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/DebtPositionFaker.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/DebtPositionFaker.java @@ -1,6 +1,7 @@ package it.gov.pagopa.pu.debtpositions.util.faker; import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; +import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionStatus; import it.gov.pagopa.pu.debtpositions.model.DebtPosition; import java.time.OffsetDateTime; @@ -8,7 +9,8 @@ import java.util.List; import java.util.TreeSet; -import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.*; +import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.buildPaymentOption; +import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.buildPaymentOptionDTO; public class DebtPositionFaker { @@ -19,7 +21,7 @@ public static DebtPosition buildDebtPosition() { debtPosition.setDebtPositionId(1L); debtPosition.setIupdOrg("IUPD_ORG"); debtPosition.setDescription("Test Description"); - debtPosition.setStatus("ACTIVE"); + debtPosition.setStatus(DebtPositionStatus.UNPAID); debtPosition.setIngestionFlowFileId(1001L); debtPosition.setIngestionFlowFileLineNumber(10L); debtPosition.setOrganizationId(500L); @@ -38,7 +40,7 @@ public static DebtPositionDTO buildDebtPositionDTO() { debtPositionDTO.setDebtPositionId(1L); debtPositionDTO.setIupdOrg("IUPD_ORG"); debtPositionDTO.setDescription("Test Description"); - debtPositionDTO.setStatus("ACTIVE"); + debtPositionDTO.setStatus(DebtPositionStatus.UNPAID); debtPositionDTO.setIngestionFlowFileId(1001L); debtPositionDTO.setIngestionFlowFileLineNumber(10L); debtPositionDTO.setOrganizationId(500L); diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java index 7e9f844..3c8540d 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java @@ -3,6 +3,7 @@ import it.gov.pagopa.pu.debtpositions.dto.Installment; import it.gov.pagopa.pu.debtpositions.dto.InstallmentPIIDTO; import it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentDTO; +import it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentStatus; import it.gov.pagopa.pu.debtpositions.model.InstallmentNoPII; import java.time.LocalDateTime; @@ -24,7 +25,7 @@ public static Installment buildInstallment(){ return Installment.builder() .installmentId(1L) .paymentOptionId(1L) - .status("TO_SYNC") + .status(InstallmentStatus.TO_SYNC) .iupdPagopa("iupdPagoPa") .iud("iud") .iuv("iuv") @@ -51,7 +52,7 @@ public static InstallmentNoPII buildInstallmentNoPII(){ return InstallmentNoPII.builder() .installmentId(1L) .paymentOptionId(1L) - .status("TO_SYNC") + .status(InstallmentStatus.TO_SYNC) .iupdPagopa("iupdPagoPa") .iud("iud") .iuv("iuv") @@ -84,7 +85,7 @@ public static Installment buildInstallmentNoUpdate(){ return Installment.builder() .installmentId(1L) .paymentOptionId(1L) - .status("TO_SYNC") + .status(InstallmentStatus.TO_SYNC) .iupdPagopa("iupdPagoPa") .iud("iud") .iuv("iuv") @@ -110,7 +111,7 @@ public static InstallmentDTO buildInstallmentDTO() { return InstallmentDTO.builder() .installmentId(1L) .paymentOptionId(1L) - .status("TO_SYNC") + .status(InstallmentStatus.TO_SYNC) .iupdPagopa("iupdPagoPa") .iud("iud") .iuv("iuv") diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PaymentOptionFaker.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PaymentOptionFaker.java index c51ceb3..916b84e 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PaymentOptionFaker.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PaymentOptionFaker.java @@ -1,6 +1,7 @@ package it.gov.pagopa.pu.debtpositions.util.faker; import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionDTO; +import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus; import it.gov.pagopa.pu.debtpositions.enums.PaymentOptionType; import it.gov.pagopa.pu.debtpositions.model.PaymentOption; @@ -21,7 +22,7 @@ public static PaymentOption buildPaymentOption() { paymentOption.setDebtPositionId(1L); paymentOption.setTotalAmountCents(2000L); paymentOption.setDueDate(DATE); - paymentOption.setStatus("PENDING"); + paymentOption.setStatus(PaymentOptionStatus.UNPAID); paymentOption.setMultiDebtor(true); paymentOption.setDescription("Payment description"); paymentOption.setPaymentOptionType(PaymentOptionType.SINGLE_INSTALLMENT); @@ -36,7 +37,7 @@ public static PaymentOptionDTO buildPaymentOptionDTO() { paymentOptionDTO.setDebtPositionId(1L); paymentOptionDTO.setTotalAmountCents(2000L); paymentOptionDTO.setDueDate(DATE); - paymentOptionDTO.setStatus("PENDING"); + paymentOptionDTO.setStatus(PaymentOptionStatus.UNPAID); paymentOptionDTO.setMultiDebtor(true); paymentOptionDTO.setDescription("Payment description"); paymentOptionDTO.setPaymentOptionType(PaymentOptionDTO.PaymentOptionTypeEnum.SINGLE_INSTALLMENT); From 534ec97416c948ed6f6754b059043cb42eb23776 Mon Sep 17 00:00:00 2001 From: LarissaASLeite Date: Mon, 20 Jan 2025 12:04:54 +0100 Subject: [PATCH 13/17] P4ADEV-1744-add-api-finalize-sync-status --- .../DebtPositionHierarchyStatusAlignerServiceImpl.java | 2 ++ .../DebtPositionInnerStatusAlignerServiceImpl.java | 2 ++ .../statusalign/debtposition/DebtPositionStatusChecker.java | 4 ++-- .../PaymentOptionInnerStatusAlignerServiceImpl.java | 2 ++ .../statusalign/paymentoption/PaymentOptionStatusChecker.java | 4 ++-- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerServiceImpl.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerServiceImpl.java index d1e4283..8613d0d 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerServiceImpl.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerServiceImpl.java @@ -9,11 +9,13 @@ import it.gov.pagopa.pu.debtpositions.service.statusalign.debtposition.DebtPositionInnerStatusAlignerService; import it.gov.pagopa.pu.debtpositions.service.statusalign.paymentoption.PaymentOptionInnerStatusAlignerService; import jakarta.transaction.Transactional; +import org.springframework.stereotype.Service; import java.util.Map; import static it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentStatus.TO_SYNC; +@Service public class DebtPositionHierarchyStatusAlignerServiceImpl implements DebtPositionHierarchyStatusAlignerService { private final DebtPositionRepository debtPositionRepository; diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionInnerStatusAlignerServiceImpl.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionInnerStatusAlignerServiceImpl.java index 950754d..82691ef 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionInnerStatusAlignerServiceImpl.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionInnerStatusAlignerServiceImpl.java @@ -3,7 +3,9 @@ import it.gov.pagopa.pu.debtpositions.model.DebtPosition; import it.gov.pagopa.pu.debtpositions.model.PaymentOption; import it.gov.pagopa.pu.debtpositions.repository.DebtPositionRepository; +import org.springframework.stereotype.Service; +@Service public class DebtPositionInnerStatusAlignerServiceImpl extends DebtPositionStatusChecker implements DebtPositionInnerStatusAlignerService{ private final DebtPositionRepository debtPositionRepository; diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusChecker.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusChecker.java index e1c8178..a769892 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusChecker.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusChecker.java @@ -4,13 +4,13 @@ import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus; import it.gov.pagopa.pu.debtpositions.exception.custom.InvalidStatusException; import it.gov.pagopa.pu.debtpositions.service.statusalign.StatusRulesHandler; -import org.springframework.stereotype.Service; +import org.springframework.stereotype.Component; import java.util.List; import static it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus.*; -@Service +@Component public class DebtPositionStatusChecker extends StatusRulesHandler { public DebtPositionStatusChecker() { diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionInnerStatusAlignerServiceImpl.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionInnerStatusAlignerServiceImpl.java index 456826d..518fc0b 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionInnerStatusAlignerServiceImpl.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionInnerStatusAlignerServiceImpl.java @@ -3,7 +3,9 @@ import it.gov.pagopa.pu.debtpositions.model.InstallmentNoPII; import it.gov.pagopa.pu.debtpositions.model.PaymentOption; import it.gov.pagopa.pu.debtpositions.repository.PaymentOptionRepository; +import org.springframework.stereotype.Service; +@Service public class PaymentOptionInnerStatusAlignerServiceImpl extends PaymentOptionStatusChecker implements PaymentOptionInnerStatusAlignerService{ private final PaymentOptionRepository paymentOptionRepository; diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusChecker.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusChecker.java index b0dc968..55281f5 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusChecker.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusChecker.java @@ -4,13 +4,13 @@ import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus; import it.gov.pagopa.pu.debtpositions.exception.custom.InvalidStatusException; import it.gov.pagopa.pu.debtpositions.service.statusalign.StatusRulesHandler; -import org.springframework.stereotype.Service; +import org.springframework.stereotype.Component; import java.util.List; import static it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus.TO_SYNC; -@Service +@Component public class PaymentOptionStatusChecker extends StatusRulesHandler{ public PaymentOptionStatusChecker() { From c35340ac11342e1d92a73df44dada18ab6c00188 Mon Sep 17 00:00:00 2001 From: LarissaASLeite Date: Mon, 20 Jan 2025 12:06:42 +0100 Subject: [PATCH 14/17] P4ADEV-1744-add-api-finalize-sync-status --- openapi/generated.openapi.json | 665 +++++++++++++++++++-------------- 1 file changed, 388 insertions(+), 277 deletions(-) diff --git a/openapi/generated.openapi.json b/openapi/generated.openapi.json index 2ee7ebb..81115bf 100644 --- a/openapi/generated.openapi.json +++ b/openapi/generated.openapi.json @@ -2772,6 +2772,63 @@ } } }, + "/debt-positions/{debtPositionId}/finalize-sync-status" : { + "put" : { + "tags" : [ "debt-position" ], + "operationId" : "finalizeSyncStatus", + "parameters" : [ { + "name" : "debtPositionId", + "in" : "path", + "description" : "The ID of the debt position", + "required" : true, + "schema" : { + "type" : "integer", + "format" : "int64" + } + } ], + "requestBody" : { + "content" : { + "application/json" : { + "schema" : { + "type" : "object", + "additionalProperties" : { + "$ref" : "#/components/schemas/IudSyncStatusUpdateDTO" + } + } + } + }, + "required" : true + }, + "responses" : { + "200" : { + "description" : "Ok" + }, + "400" : { + "description" : "Invalid request", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/DebtPositionErrorDTO" + } + } + } + }, + "500" : { + "description" : "Server Error", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/DebtPositionErrorDTO" + } + } + } + } + }, + "security" : [ { + "BearerAuth" : [ ] + } ] + } + }, "/receipts" : { "post" : { "tags" : [ "receipt" ], @@ -2807,6 +2864,16 @@ } } }, + "409" : { + "description" : "Debt position already exists", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/ReceiptDTO" + } + } + } + }, "500" : { "description" : "Internal server error", "content" : { @@ -2827,6 +2894,15 @@ "post" : { "tags" : [ "debt-position" ], "operationId" : "createDebtPosition", + "parameters" : [ { + "name" : "massive", + "in" : "query", + "description" : "Indicates if the operation is massive (true) or single (false).", + "required" : false, + "schema" : { + "type" : "boolean" + } + } ], "requestBody" : { "content" : { "application/json" : { @@ -2957,7 +3033,7 @@ } } }, - "DebtPositionType" : { + "InstallmentNoPII" : { "type" : "object", "properties" : { "creationDate" : { @@ -2971,164 +3047,110 @@ "updateOperatorExternalId" : { "type" : "string" }, - "debtPositionTypeId" : { + "installmentId" : { "type" : "integer", "format" : "int64" }, - "brokerId" : { + "paymentOptionId" : { "type" : "integer", "format" : "int64" }, - "code" : { - "type" : "string" + "status" : { + "type" : "string", + "enum" : [ "TO_SYNC", "REPORTED", "PAID", "CANCELLED", "INVALID", "EXPIRED", "UNPAID" ] }, - "description" : { + "iupdPagopa" : { "type" : "string" }, - "orgType" : { + "iud" : { "type" : "string" }, - "macroArea" : { + "iuv" : { "type" : "string" }, - "serviceType" : { + "iur" : { "type" : "string" }, - "collectingReason" : { + "iuf" : { "type" : "string" }, - "taxonomyCode" : { + "nav" : { "type" : "string" }, - "flagAnonymousFiscalCode" : { - "type" : "boolean" - }, - "flagMandatoryDueDate" : { - "type" : "boolean" - }, - "flagNotifyIo" : { - "type" : "boolean" + "dueDate" : { + "type" : "string", + "format" : "date-time" }, - "ioTemplateMessage" : { + "paymentTypeCode" : { "type" : "string" }, - "_links" : { - "$ref" : "#/components/schemas/Links" - } - } - }, - "PageMetadata" : { - "type" : "object", - "properties" : { - "size" : { - "type" : "integer", - "format" : "int64" - }, - "totalElements" : { + "amountCents" : { "type" : "integer", "format" : "int64" }, - "totalPages" : { + "notificationFeeCents" : { "type" : "integer", "format" : "int64" }, - "number" : { - "type" : "integer", - "format" : "int64" - } - } - }, - "PagedModelDebtPositionType" : { - "type" : "object", - "properties" : { - "_embedded" : { - "type" : "object", - "properties" : { - "debtPositionTypes" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/DebtPositionType" - } - } - } - }, - "_links" : { - "$ref" : "#/components/schemas/Links" + "remittanceInformation" : { + "type" : "string" }, - "page" : { - "$ref" : "#/components/schemas/PageMetadata" - } - } - }, - "DebtPosition" : { - "type" : "object", - "properties" : { - "creationDate" : { - "type" : "string", - "format" : "date-time" + "humanFriendlyRemittanceInformation" : { + "type" : "string" }, - "updateDate" : { - "type" : "string", - "format" : "date-time" + "balance" : { + "type" : "string" }, - "updateOperatorExternalId" : { + "legacyPaymentMetadata" : { "type" : "string" }, - "debtPositionId" : { + "personalDataId" : { "type" : "integer", "format" : "int64" }, - "iupdOrg" : { - "type" : "string" - }, - "description" : { + "debtorEntityType" : { "type" : "string" }, - "status" : { - "type" : "string" + "debtorFiscalCodeHash" : { + "type" : "string", + "format" : "byte" }, - "ingestionFlowFileId" : { + "_links" : { + "$ref" : "#/components/schemas/Links" + } + } + }, + "PageMetadata" : { + "type" : "object", + "properties" : { + "size" : { "type" : "integer", "format" : "int64" }, - "ingestionFlowFileLineNumber" : { + "totalElements" : { "type" : "integer", "format" : "int64" }, - "organizationId" : { + "totalPages" : { "type" : "integer", "format" : "int64" }, - "debtPositionTypeOrgId" : { + "number" : { "type" : "integer", "format" : "int64" - }, - "notificationDate" : { - "type" : "string", - "format" : "date-time" - }, - "validityDate" : { - "type" : "string", - "format" : "date-time" - }, - "flagIuvVolatile" : { - "type" : "boolean" - }, - "_links" : { - "$ref" : "#/components/schemas/Links" } } }, - "PagedModelDebtPosition" : { + "PagedModelInstallmentNoPII" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "debtPositions" : { + "installmentNoPIIs" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/DebtPosition" + "$ref" : "#/components/schemas/InstallmentNoPII" } } } @@ -3155,16 +3177,16 @@ } } }, - "CollectionModelPaymentOption" : { + "CollectionModelTransfer" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "paymentOptions" : { + "transfers" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/PaymentOptionResponse" + "$ref" : "#/components/schemas/TransferResponse" } } } @@ -3245,6 +3267,135 @@ } } }, + "ReceiptNoPII" : { + "type" : "object", + "properties" : { + "creationDate" : { + "type" : "string", + "format" : "date-time" + }, + "updateDate" : { + "type" : "string", + "format" : "date-time" + }, + "updateOperatorExternalId" : { + "type" : "string" + }, + "receiptId" : { + "type" : "integer", + "format" : "int64" + }, + "installmentId" : { + "type" : "integer", + "format" : "int64" + }, + "paymentReceiptId" : { + "type" : "integer", + "format" : "int64" + }, + "noticeNumber" : { + "type" : "string" + }, + "orgFiscalCode" : { + "type" : "string" + }, + "outcome" : { + "type" : "string" + }, + "creditorReferenceId" : { + "type" : "string" + }, + "paymentAmountCents" : { + "type" : "integer", + "format" : "int64" + }, + "description" : { + "type" : "string" + }, + "companyName" : { + "type" : "string" + }, + "officeName" : { + "type" : "string" + }, + "idPsp" : { + "type" : "string" + }, + "pspFiscalCode" : { + "type" : "string" + }, + "pspPartitaIva" : { + "type" : "string" + }, + "pspCompanyName" : { + "type" : "string" + }, + "idChannel" : { + "type" : "string" + }, + "channelDescription" : { + "type" : "string" + }, + "paymentMethod" : { + "type" : "string" + }, + "feeCents" : { + "type" : "integer", + "format" : "int64" + }, + "paymentDateTime" : { + "type" : "string", + "format" : "date-time" + }, + "applicationDate" : { + "type" : "string", + "format" : "date-time" + }, + "transferDate" : { + "type" : "string", + "format" : "date-time" + }, + "standin" : { + "type" : "boolean" + }, + "debtorEntityType" : { + "type" : "string" + }, + "personalDataId" : { + "type" : "integer", + "format" : "int64" + }, + "debtorFiscalCodeHash" : { + "type" : "string", + "format" : "byte" + }, + "_links" : { + "$ref" : "#/components/schemas/Links" + } + } + }, + "PagedModelReceiptNoPII" : { + "type" : "object", + "properties" : { + "_embedded" : { + "type" : "object", + "properties" : { + "receiptNoPIIs" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/ReceiptNoPII" + } + } + } + }, + "_links" : { + "$ref" : "#/components/schemas/Links" + }, + "page" : { + "$ref" : "#/components/schemas/PageMetadata" + } + } + }, "DebtPositionTypeOrg" : { "type" : "object", "properties" : { @@ -3367,7 +3518,7 @@ } } }, - "InstallmentNoPII" : { + "PaymentOption" : { "type" : "object", "properties" : { "creationDate" : { @@ -3378,91 +3529,54 @@ "type" : "string", "format" : "date-time" }, - "updateOperatorExternalId" : { - "type" : "string" - }, - "installmentId" : { - "type" : "integer", - "format" : "int64" - }, - "paymentOptionId" : { - "type" : "integer", - "format" : "int64" - }, - "status" : { - "type" : "string" - }, - "iupdPagopa" : { - "type" : "string" - }, - "iud" : { - "type" : "string" - }, - "iuv" : { - "type" : "string" - }, - "iur" : { - "type" : "string" - }, - "iuf" : { - "type" : "string" - }, - "nav" : { - "type" : "string" - }, - "dueDate" : { - "type" : "string", - "format" : "date-time" - }, - "paymentTypeCode" : { + "updateOperatorExternalId" : { "type" : "string" }, - "amountCents" : { + "paymentOptionId" : { "type" : "integer", "format" : "int64" }, - "notificationFeeCents" : { + "debtPositionId" : { "type" : "integer", "format" : "int64" }, - "remittanceInformation" : { - "type" : "string" - }, - "humanFriendlyRemittanceInformation" : { - "type" : "string" + "totalAmountCents" : { + "type" : "integer", + "format" : "int64" }, - "balance" : { - "type" : "string" + "status" : { + "type" : "string", + "enum" : [ "TO_SYNC", "REPORTED", "PAID", "PARTIALLY_PAID", "CANCELLED", "INVALID", "EXPIRED", "UNPAID" ] }, - "legacyPaymentMetadata" : { - "type" : "string" + "multiDebtor" : { + "type" : "boolean" }, - "personalDataId" : { - "type" : "integer", - "format" : "int64" + "dueDate" : { + "type" : "string", + "format" : "date-time" }, - "debtorEntityType" : { + "description" : { "type" : "string" }, - "debtorFiscalCodeHash" : { + "paymentOptionType" : { "type" : "string", - "format" : "byte" + "enum" : [ "SINGLE_INSTALLMENT", "INSTALMENTS", "DOWN_PAYMENT" ] }, "_links" : { "$ref" : "#/components/schemas/Links" } } }, - "PagedModelInstallmentNoPII" : { + "PagedModelPaymentOption" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "installmentNoPIIs" : { + "paymentOptions" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/InstallmentNoPII" + "$ref" : "#/components/schemas/PaymentOption" } } } @@ -3475,16 +3589,16 @@ } } }, - "CollectionModelTransfer" : { + "CollectionModelInstallmentNoPII" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "transfers" : { + "installmentNoPIIs" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/TransferResponse" + "$ref" : "#/components/schemas/InstallmentNoPIIResponse" } } } @@ -3494,7 +3608,7 @@ } } }, - "ReceiptNoPII" : { + "DebtPosition" : { "type" : "object", "properties" : { "creationDate" : { @@ -3508,109 +3622,62 @@ "updateOperatorExternalId" : { "type" : "string" }, - "receiptId" : { - "type" : "integer", - "format" : "int64" - }, - "installmentId" : { - "type" : "integer", - "format" : "int64" - }, - "paymentReceiptId" : { + "debtPositionId" : { "type" : "integer", "format" : "int64" }, - "noticeNumber" : { - "type" : "string" - }, - "orgFiscalCode" : { + "iupdOrg" : { "type" : "string" }, - "outcome" : { + "description" : { "type" : "string" }, - "creditorReferenceId" : { - "type" : "string" + "status" : { + "type" : "string", + "enum" : [ "TO_SYNC", "REPORTED", "PAID", "PARTIALLY_PAID", "CANCELLED", "INVALID", "EXPIRED", "UNPAID" ] }, - "paymentAmountCents" : { + "ingestionFlowFileId" : { "type" : "integer", "format" : "int64" }, - "description" : { - "type" : "string" - }, - "companyName" : { - "type" : "string" - }, - "officeName" : { - "type" : "string" - }, - "idPsp" : { - "type" : "string" - }, - "pspFiscalCode" : { - "type" : "string" - }, - "pspPartitaIva" : { - "type" : "string" - }, - "pspCompanyName" : { - "type" : "string" - }, - "idChannel" : { - "type" : "string" - }, - "channelDescription" : { - "type" : "string" - }, - "paymentMethod" : { - "type" : "string" + "ingestionFlowFileLineNumber" : { + "type" : "integer", + "format" : "int64" }, - "feeCents" : { + "organizationId" : { "type" : "integer", "format" : "int64" }, - "paymentDateTime" : { - "type" : "string", - "format" : "date-time" + "debtPositionTypeOrgId" : { + "type" : "integer", + "format" : "int64" }, - "applicationDate" : { + "notificationDate" : { "type" : "string", "format" : "date-time" }, - "transferDate" : { + "validityDate" : { "type" : "string", "format" : "date-time" }, - "standin" : { + "flagIuvVolatile" : { "type" : "boolean" }, - "debtorEntityType" : { - "type" : "string" - }, - "personalDataId" : { - "type" : "integer", - "format" : "int64" - }, - "debtorFiscalCodeHash" : { - "type" : "string", - "format" : "byte" - }, "_links" : { "$ref" : "#/components/schemas/Links" } } }, - "PagedModelReceiptNoPII" : { + "PagedModelDebtPosition" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "receiptNoPIIs" : { + "debtPositions" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/ReceiptNoPII" + "$ref" : "#/components/schemas/DebtPosition" } } } @@ -3623,6 +3690,25 @@ } } }, + "CollectionModelPaymentOption" : { + "type" : "object", + "properties" : { + "_embedded" : { + "type" : "object", + "properties" : { + "paymentOptions" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/PaymentOptionResponse" + } + } + } + }, + "_links" : { + "$ref" : "#/components/schemas/Links" + } + } + }, "Transfer" : { "type" : "object", "properties" : { @@ -3701,7 +3787,7 @@ } } }, - "PaymentOption" : { + "DebtPositionType" : { "type" : "object", "properties" : { "creationDate" : { @@ -3715,50 +3801,62 @@ "updateOperatorExternalId" : { "type" : "string" }, - "paymentOptionId" : { + "debtPositionTypeId" : { "type" : "integer", "format" : "int64" }, - "debtPositionId" : { + "brokerId" : { "type" : "integer", "format" : "int64" }, - "totalAmountCents" : { - "type" : "integer", - "format" : "int64" + "code" : { + "type" : "string" }, - "status" : { + "description" : { "type" : "string" }, - "multiDebtor" : { - "type" : "boolean" + "orgType" : { + "type" : "string" }, - "dueDate" : { - "type" : "string", - "format" : "date-time" + "macroArea" : { + "type" : "string" }, - "description" : { + "serviceType" : { "type" : "string" }, - "paymentOptionType" : { - "type" : "string", - "enum" : [ "SINGLE_INSTALLMENT", "INSTALMENTS", "DOWN_PAYMENT" ] + "collectingReason" : { + "type" : "string" + }, + "taxonomyCode" : { + "type" : "string" + }, + "flagAnonymousFiscalCode" : { + "type" : "boolean" + }, + "flagMandatoryDueDate" : { + "type" : "boolean" + }, + "flagNotifyIo" : { + "type" : "boolean" + }, + "ioTemplateMessage" : { + "type" : "string" }, "_links" : { "$ref" : "#/components/schemas/Links" } } }, - "PagedModelPaymentOption" : { + "PagedModelDebtPositionType" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "paymentOptions" : { + "debtPositionTypes" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/PaymentOption" + "$ref" : "#/components/schemas/DebtPositionType" } } } @@ -3771,25 +3869,6 @@ } } }, - "CollectionModelInstallmentNoPII" : { - "type" : "object", - "properties" : { - "_embedded" : { - "type" : "object", - "properties" : { - "installmentNoPIIs" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/InstallmentNoPIIResponse" - } - } - } - }, - "_links" : { - "$ref" : "#/components/schemas/Links" - } - } - }, "DebtPositionTypeOrgOperatorsRequestBody" : { "type" : "object", "properties" : { @@ -3996,7 +4075,8 @@ "type" : "string" }, "status" : { - "type" : "string" + "type" : "string", + "enum" : [ "TO_SYNC", "REPORTED", "PAID", "PARTIALLY_PAID", "CANCELLED", "INVALID", "EXPIRED", "UNPAID" ] }, "ingestionFlowFileId" : { "type" : "integer", @@ -4056,7 +4136,8 @@ "format" : "int64" }, "status" : { - "type" : "string" + "type" : "string", + "enum" : [ "TO_SYNC", "REPORTED", "PAID", "CANCELLED", "INVALID", "EXPIRED", "UNPAID" ] }, "iupdPagopa" : { "type" : "string" @@ -4149,7 +4230,8 @@ "format" : "int64" }, "status" : { - "type" : "string" + "type" : "string", + "enum" : [ "TO_SYNC", "REPORTED", "PAID", "PARTIALLY_PAID", "CANCELLED", "INVALID", "EXPIRED", "UNPAID" ] }, "multiDebtor" : { "type" : "boolean" @@ -4249,7 +4331,8 @@ "format" : "int64" }, "status" : { - "type" : "string" + "type" : "string", + "enum" : [ "TO_SYNC", "REPORTED", "PAID", "CANCELLED", "INVALID", "EXPIRED", "UNPAID" ] }, "iupdPagopa" : { "type" : "string" @@ -4336,7 +4419,8 @@ "format" : "int64" }, "status" : { - "type" : "string" + "type" : "string", + "enum" : [ "TO_SYNC", "REPORTED", "PAID", "PARTIALLY_PAID", "CANCELLED", "INVALID", "EXPIRED", "UNPAID" ] }, "multiDebtor" : { "type" : "boolean" @@ -4511,6 +4595,30 @@ } } }, + "DebtPositionErrorDTO" : { + "required" : [ "code", "message" ], + "type" : "object", + "properties" : { + "code" : { + "type" : "string", + "enum" : [ "DEBT_POSITION_IVALID_REQUEST", "DEBT_POSITION_GENERIC_ERROR" ] + }, + "message" : { + "type" : "string" + } + } + }, + "IudSyncStatusUpdateDTO" : { + "type" : "object", + "properties" : { + "newStatus" : { + "type" : "string" + }, + "iupdPagopa" : { + "type" : "string" + } + } + }, "PersonDTO" : { "required" : [ "email", "entityType", "fiscalCode", "fullName" ], "type" : "object", @@ -4661,7 +4769,8 @@ "type" : "string" }, "status" : { - "type" : "string" + "type" : "string", + "enum" : [ "TO_SYNC", "REPORTED", "PAID", "PARTIALLY_PAID", "CANCELLED", "INVALID", "EXPIRED", "UNPAID" ] }, "ingestionFlowFileId" : { "type" : "integer", @@ -4719,7 +4828,8 @@ "format" : "int64" }, "status" : { - "type" : "string" + "type" : "string", + "enum" : [ "TO_SYNC", "REPORTED", "PAID", "CANCELLED", "INVALID", "EXPIRED", "UNPAID" ] }, "iupdPagopa" : { "type" : "string" @@ -4802,7 +4912,8 @@ "format" : "int64" }, "status" : { - "type" : "string" + "type" : "string", + "enum" : [ "TO_SYNC", "REPORTED", "PAID", "PARTIALLY_PAID", "CANCELLED", "INVALID", "EXPIRED", "UNPAID" ] }, "multiDebtor" : { "type" : "boolean" From 7c7118b3efb569767cc318a59cc478740bbd71d8 Mon Sep 17 00:00:00 2001 From: LarissaASLeite Date: Mon, 20 Jan 2025 13:09:36 +0100 Subject: [PATCH 15/17] P4ADEV-1744-add-api-finalize-sync-status --- .../DebtPositionStatusCheckerTest.java | 77 +++++++++++++++++++ .../PaymentOptionStatusCheckerTest.java | 77 +++++++++++++++++++ 2 files changed, 154 insertions(+) diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusCheckerTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusCheckerTest.java index b281b77..a542170 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusCheckerTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusCheckerTest.java @@ -20,6 +20,9 @@ void setUp() { checker = new DebtPositionStatusChecker(); } + /** + * Test if the status is TO_SYNC when at least one PaymentOption has status TO_SYNC. + */ @Test void testDetermineDebtPositionStatus_ToSync() { List paymentOptionStatusList = List.of(PaymentOptionStatus.TO_SYNC, PaymentOptionStatus.PAID); @@ -27,6 +30,9 @@ void testDetermineDebtPositionStatus_ToSync() { assertEquals(DebtPositionStatus.TO_SYNC, result); } + /** + * Test if the status is PARTIALLY_PAID when there is at least one PAID and one UNPAID paymentOption. + */ @Test void testDetermineDebtPositionStatus_PartiallyPaid() { List paymentOptionStatusList = List.of(PaymentOptionStatus.PAID, PaymentOptionStatus.UNPAID); @@ -34,6 +40,19 @@ void testDetermineDebtPositionStatus_PartiallyPaid() { assertEquals(DebtPositionStatus.PARTIALLY_PAID, result); } + /** + * Test if the status is PARTIALLY_PAID when there is at least one PAID and one EXPIRED paymentOption. + */ + @Test + void testDeterminePaymentOptionStatus_PartiallyPaid2() { + List paymentOptionStatusList = List.of(PaymentOptionStatus.PAID, PaymentOptionStatus.EXPIRED); + DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + assertEquals(DebtPositionStatus.PARTIALLY_PAID, result); + } + + /** + * Test if the status is UNPAID when all paymentOptions are UNPAID. + */ @Test void testDetermineDebtPositionStatus_Unpaid() { List paymentOptionStatusList = List.of(PaymentOptionStatus.UNPAID, PaymentOptionStatus.UNPAID); @@ -41,6 +60,19 @@ void testDetermineDebtPositionStatus_Unpaid() { assertEquals(DebtPositionStatus.UNPAID, result); } + /** + * Test if the status is UNPAID when all paymentOptions are CANCELLED, with at least one UNPAID. + */ + @Test + void testDeterminePaymentOptionStatus_Unpaid2() { + List paymentOptionStatusList = List.of(PaymentOptionStatus.UNPAID, PaymentOptionStatus.CANCELLED, PaymentOptionStatus.CANCELLED); + DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + assertEquals(DebtPositionStatus.UNPAID, result); + } + + /** + * Test if the status is PAID when all paymentOptions are PAID. + */ @Test void testDetermineDebtPositionStatus_Paid() { List paymentOptionStatusList = List.of(PaymentOptionStatus.PAID, PaymentOptionStatus.PAID); @@ -48,6 +80,19 @@ void testDetermineDebtPositionStatus_Paid() { assertEquals(DebtPositionStatus.PAID, result); } + /** + * Test if the status is PAID when all paymentOptions are CANCELLED, with at least one PAID. + */ + @Test + void testDeterminePaymentOptionStatus_Paid2() { + List paymentOptionStatusList = List.of(PaymentOptionStatus.PAID, PaymentOptionStatus.CANCELLED); + DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + assertEquals(DebtPositionStatus.PAID, result); + } + + /** + * Test if the status is REPORTED when all paymentOptions are CANCELLED, with at least one REPORTED. + */ @Test void testDetermineDebtPositionStatus_Reported() { List paymentOptionStatusList = List.of(PaymentOptionStatus.REPORTED, PaymentOptionStatus.CANCELLED); @@ -55,13 +100,39 @@ void testDetermineDebtPositionStatus_Reported() { assertEquals(DebtPositionStatus.REPORTED, result); } + /** + * Test if the status is REPORTED when all paymentOptions are REPORTED. + */ + @Test + void testDeterminePaymentOptionStatus_Reported2() { + List paymentOptionStatusList = List.of(PaymentOptionStatus.REPORTED, PaymentOptionStatus.REPORTED); + DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + assertEquals(DebtPositionStatus.REPORTED, result); + } + + /** + * Test if the status is INVALID when all paymentOptions are INVALID. + */ @Test void testDetermineDebtPositionStatus_Invalid() { + List paymentOptionStatusList = List.of(PaymentOptionStatus.INVALID, PaymentOptionStatus.INVALID); + DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + assertEquals(DebtPositionStatus.INVALID, result); + } + + /** + * Test if the status is INVALID when all paymentOptions are CANCELLED, with at least one INVALID. + */ + @Test + void testDeterminePaymentOptionStatus_Invalid2() { List paymentOptionStatusList = List.of(PaymentOptionStatus.INVALID, PaymentOptionStatus.CANCELLED); DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); assertEquals(DebtPositionStatus.INVALID, result); } + /** + * Test if the status is CANCELLED when all paymentOptions are CANCELLED. + */ @Test void testDetermineDebtPositionStatus_Cancelled() { List paymentOptionStatusList = List.of(PaymentOptionStatus.CANCELLED, PaymentOptionStatus.CANCELLED); @@ -69,6 +140,9 @@ void testDetermineDebtPositionStatus_Cancelled() { assertEquals(DebtPositionStatus.CANCELLED, result); } + /** + * Test if the status is EXPIRED when all paymentOptions are EXPIRED. + */ @Test void testDetermineDebtPositionStatus_Expired() { List paymentOptionStatusList = List.of(PaymentOptionStatus.EXPIRED, PaymentOptionStatus.EXPIRED); @@ -76,6 +150,9 @@ void testDetermineDebtPositionStatus_Expired() { assertEquals(DebtPositionStatus.EXPIRED, result); } + /** + * Test if an exception is thrown when the list of paymentOptions is empty. + */ @Test void testDetermineDebtPositionStatus_InvalidStatus() { List paymentOptionStatusList = List.of(); diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusCheckerTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusCheckerTest.java index 572c81c..34b51fc 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusCheckerTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusCheckerTest.java @@ -20,6 +20,9 @@ void setUp() { checker = new PaymentOptionStatusChecker(); } + /** + * Test if the status is TO_SYNC when at least one Installment has status TO_SYNC. + */ @Test void testDeterminePaymentOptionStatus_ToSync() { List installmentStatusList = List.of(InstallmentStatus.TO_SYNC, InstallmentStatus.PAID); @@ -27,6 +30,9 @@ void testDeterminePaymentOptionStatus_ToSync() { assertEquals(PaymentOptionStatus.TO_SYNC, result); } + /** + * Test if the status is PARTIALLY_PAID when there is at least one PAID and one UNPAID installment. + */ @Test void testDeterminePaymentOptionStatus_PartiallyPaid() { List installmentStatusList = List.of(InstallmentStatus.PAID, InstallmentStatus.UNPAID); @@ -34,6 +40,19 @@ void testDeterminePaymentOptionStatus_PartiallyPaid() { assertEquals(PaymentOptionStatus.PARTIALLY_PAID, result); } + /** + * Test if the status is PARTIALLY_PAID when there is at least one PAID and one EXPIRED installment. + */ + @Test + void testDeterminePaymentOptionStatus_PartiallyPaid2() { + List installmentStatusList = List.of(InstallmentStatus.PAID, InstallmentStatus.EXPIRED); + PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + assertEquals(PaymentOptionStatus.PARTIALLY_PAID, result); + } + + /** + * Test if the status is UNPAID when all installments are UNPAID. + */ @Test void testDeterminePaymentOptionStatus_Unpaid() { List installmentStatusList = List.of(InstallmentStatus.UNPAID, InstallmentStatus.UNPAID); @@ -41,6 +60,19 @@ void testDeterminePaymentOptionStatus_Unpaid() { assertEquals(PaymentOptionStatus.UNPAID, result); } + /** + * Test if the status is UNPAID when all installments are CANCELLED, with at least one UNPAID. + */ + @Test + void testDeterminePaymentOptionStatus_Unpaid2() { + List installmentStatusList = List.of(InstallmentStatus.UNPAID, InstallmentStatus.CANCELLED, InstallmentStatus.CANCELLED); + PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + assertEquals(PaymentOptionStatus.UNPAID, result); + } + + /** + * Test if the status is PAID when all installments are PAID. + */ @Test void testDeterminePaymentOptionStatus_Paid() { List installmentStatusList = List.of(InstallmentStatus.PAID, InstallmentStatus.PAID); @@ -48,6 +80,19 @@ void testDeterminePaymentOptionStatus_Paid() { assertEquals(PaymentOptionStatus.PAID, result); } + /** + * Test if the status is PAID when all installments are CANCELLED, with at least one PAID. + */ + @Test + void testDeterminePaymentOptionStatus_Paid2() { + List installmentStatusList = List.of(InstallmentStatus.PAID, InstallmentStatus.CANCELLED); + PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + assertEquals(PaymentOptionStatus.PAID, result); + } + + /** + * Test if the status is REPORTED when all installments are CANCELLED, with at least one REPORTED. + */ @Test void testDeterminePaymentOptionStatus_Reported() { List installmentStatusList = List.of(InstallmentStatus.REPORTED, InstallmentStatus.CANCELLED); @@ -55,13 +100,39 @@ void testDeterminePaymentOptionStatus_Reported() { assertEquals(PaymentOptionStatus.REPORTED, result); } + /** + * Test if the status is REPORTED when all installments are REPORTED. + */ + @Test + void testDeterminePaymentOptionStatus_Reported2() { + List installmentStatusList = List.of(InstallmentStatus.REPORTED, InstallmentStatus.REPORTED); + PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + assertEquals(PaymentOptionStatus.REPORTED, result); + } + + /** + * Test if the status is INVALID when all installments are INVALID. + */ @Test void testDeterminePaymentOptionStatus_Invalid() { + List installmentStatusList = List.of(InstallmentStatus.INVALID, InstallmentStatus.INVALID); + PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + assertEquals(PaymentOptionStatus.INVALID, result); + } + + /** + * Test if the status is INVALID when all installments are CANCELLED, with at least one INVALID. + */ + @Test + void testDeterminePaymentOptionStatus_Invalid2() { List installmentStatusList = List.of(InstallmentStatus.INVALID, InstallmentStatus.CANCELLED); PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); assertEquals(PaymentOptionStatus.INVALID, result); } + /** + * Test if the status is CANCELLED when all installments are CANCELLED. + */ @Test void testDeterminePaymentOptionStatus_Cancelled() { List installmentStatusList = List.of(InstallmentStatus.CANCELLED, InstallmentStatus.CANCELLED); @@ -69,6 +140,9 @@ void testDeterminePaymentOptionStatus_Cancelled() { assertEquals(PaymentOptionStatus.CANCELLED, result); } + /** + * Test if the status is EXPIRED when all installments are EXPIRED. + */ @Test void testDeterminePaymentOptionStatus_Expired() { List installmentStatusList = List.of(InstallmentStatus.EXPIRED, InstallmentStatus.EXPIRED); @@ -76,6 +150,9 @@ void testDeterminePaymentOptionStatus_Expired() { assertEquals(PaymentOptionStatus.EXPIRED, result); } + /** + * Test if an exception is thrown when the list of installments is empty. + */ @Test void testDeterminePaymentOptionStatus_InvalidStatus() { List installmentStatusList = List.of(); From 0967ccdd7f406b954b710cd283adbfcc15facb52 Mon Sep 17 00:00:00 2001 From: LarissaASLeite Date: Mon, 20 Jan 2025 15:54:50 +0100 Subject: [PATCH 16/17] add-openapi for finalizeSyncStatus --- openapi/p4pa-debt-position.openapi.yaml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/openapi/p4pa-debt-position.openapi.yaml b/openapi/p4pa-debt-position.openapi.yaml index 0d39dac..88f60db 100644 --- a/openapi/p4pa-debt-position.openapi.yaml +++ b/openapi/p4pa-debt-position.openapi.yaml @@ -77,11 +77,15 @@ paths: content: application/json: schema: - $ref: "#/components/schemas/SyncStatusDTO" + $ref: "#/components/schemas/SyncStatusUpdateRequestDTO" required: true responses: "200": description: Ok + content: + application/json: + schema: + $ref: '#/components/schemas/DebtPositionDTO' "400": description: Invalid request content: @@ -410,7 +414,7 @@ components: - INVALID - EXPIRED - UNPAID - SyncStatusDTO: + SyncStatusUpdateRequestDTO: type: object additionalProperties: $ref: "#/components/schemas/IudSyncStatusUpdateDTO" From 141a36cffe370c909ad24155ced93246aa7c413c Mon Sep 17 00:00:00 2001 From: LarissaASLeite Date: Mon, 20 Jan 2025 22:21:36 +0100 Subject: [PATCH 17/17] P4ADEV-1744-add-api-finalize-sync-status --- openapi/generated.openapi.json | 1102 +++++++++-------- openapi/p4pa-debt-position.openapi.yaml | 7 +- .../DebtPositionControllerImpl.java | 8 +- .../mapper/DebtPositionMapper.java | 23 + .../mapper/InstallmentMapper.java | 31 + .../mapper/PaymentOptionMapper.java | 19 + .../pu/debtpositions/mapper/PersonMapper.java | 1 - .../debtpositions/mapper/TransferMapper.java | 19 + ...PositionHierarchyStatusAlignerService.java | 5 +- ...tionHierarchyStatusAlignerServiceImpl.java | 49 +- .../statusalign/StatusRulesHandler.java | 76 +- ...PositionInnerStatusAlignerServiceImpl.java | 15 +- .../DebtPositionStatusChecker.java | 32 +- ...ntOptionInnerStatusAlignerServiceImpl.java | 12 +- .../PaymentOptionStatusChecker.java | 32 +- .../DebtPositionControllerTest.java | 22 +- .../DebtPositionExceptionHandlerTest.java | 3 +- .../mapper/DebtPositionMapperTest.java | 2 + .../mapper/InstallmentMapperTest.java | 2 + .../mapper/PaymentOptionMapperTest.java | 2 + ...tionHierarchyStatusAlignerServiceTest.java | 80 +- .../DebtPositionStatusCheckerTest.java | 103 +- .../PaymentOptionStatusCheckerTest.java | 113 +- .../util/faker/DebtPositionFaker.java | 2 +- .../util/faker/InstallmentFaker.java | 2 +- .../util/faker/PaymentOptionFaker.java | 2 +- 26 files changed, 1024 insertions(+), 740 deletions(-) diff --git a/openapi/generated.openapi.json b/openapi/generated.openapi.json index 81115bf..e382e53 100644 --- a/openapi/generated.openapi.json +++ b/openapi/generated.openapi.json @@ -2792,7 +2792,7 @@ "schema" : { "type" : "object", "additionalProperties" : { - "$ref" : "#/components/schemas/IudSyncStatusUpdateDTO" + "$ref" : "#/components/schemas/IupdSyncStatusUpdateDTO" } } } @@ -2801,7 +2801,14 @@ }, "responses" : { "200" : { - "description" : "Ok" + "description" : "Ok", + "content" : { + "application/json" : { + "schema" : { + "$ref" : "#/components/schemas/DebtPositionDTO" + } + } + } }, "400" : { "description" : "Invalid request", @@ -3033,7 +3040,7 @@ } } }, - "InstallmentNoPII" : { + "Transfer" : { "type" : "object", "properties" : { "creationDate" : { @@ -3047,74 +3054,43 @@ "updateOperatorExternalId" : { "type" : "string" }, - "installmentId" : { + "transferId" : { "type" : "integer", "format" : "int64" }, - "paymentOptionId" : { + "installmentId" : { "type" : "integer", "format" : "int64" }, - "status" : { - "type" : "string", - "enum" : [ "TO_SYNC", "REPORTED", "PAID", "CANCELLED", "INVALID", "EXPIRED", "UNPAID" ] - }, - "iupdPagopa" : { - "type" : "string" - }, - "iud" : { - "type" : "string" - }, - "iuv" : { - "type" : "string" - }, - "iur" : { - "type" : "string" - }, - "iuf" : { - "type" : "string" - }, - "nav" : { + "orgFiscalCode" : { "type" : "string" }, - "dueDate" : { - "type" : "string", - "format" : "date-time" - }, - "paymentTypeCode" : { + "orgName" : { "type" : "string" }, "amountCents" : { "type" : "integer", "format" : "int64" }, - "notificationFeeCents" : { - "type" : "integer", - "format" : "int64" - }, "remittanceInformation" : { "type" : "string" }, - "humanFriendlyRemittanceInformation" : { + "stamp" : { + "$ref" : "#/components/schemas/Stamp" + }, + "iban" : { "type" : "string" }, - "balance" : { + "postalIban" : { "type" : "string" }, - "legacyPaymentMetadata" : { + "category" : { "type" : "string" }, - "personalDataId" : { + "transferIndex" : { "type" : "integer", "format" : "int64" }, - "debtorEntityType" : { - "type" : "string" - }, - "debtorFiscalCodeHash" : { - "type" : "string", - "format" : "byte" - }, "_links" : { "$ref" : "#/components/schemas/Links" } @@ -3141,16 +3117,16 @@ } } }, - "PagedModelInstallmentNoPII" : { + "PagedModelTransfer" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "installmentNoPIIs" : { + "transfers" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/InstallmentNoPII" + "$ref" : "#/components/schemas/Transfer" } } } @@ -3177,16 +3153,98 @@ } } }, - "CollectionModelTransfer" : { + "DebtPosition" : { + "type" : "object", + "properties" : { + "creationDate" : { + "type" : "string", + "format" : "date-time" + }, + "updateDate" : { + "type" : "string", + "format" : "date-time" + }, + "updateOperatorExternalId" : { + "type" : "string" + }, + "debtPositionId" : { + "type" : "integer", + "format" : "int64" + }, + "iupdOrg" : { + "type" : "string" + }, + "description" : { + "type" : "string" + }, + "status" : { + "type" : "string", + "enum" : [ "TO_SYNC", "REPORTED", "PAID", "PARTIALLY_PAID", "CANCELLED", "INVALID", "EXPIRED", "UNPAID" ] + }, + "ingestionFlowFileId" : { + "type" : "integer", + "format" : "int64" + }, + "ingestionFlowFileLineNumber" : { + "type" : "integer", + "format" : "int64" + }, + "organizationId" : { + "type" : "integer", + "format" : "int64" + }, + "debtPositionTypeOrgId" : { + "type" : "integer", + "format" : "int64" + }, + "notificationDate" : { + "type" : "string", + "format" : "date-time" + }, + "validityDate" : { + "type" : "string", + "format" : "date-time" + }, + "flagIuvVolatile" : { + "type" : "boolean" + }, + "_links" : { + "$ref" : "#/components/schemas/Links" + } + } + }, + "PagedModelDebtPosition" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "transfers" : { + "debtPositions" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/TransferResponse" + "$ref" : "#/components/schemas/DebtPosition" + } + } + } + }, + "_links" : { + "$ref" : "#/components/schemas/Links" + }, + "page" : { + "$ref" : "#/components/schemas/PageMetadata" + } + } + }, + "CollectionModelPaymentOption" : { + "type" : "object", + "properties" : { + "_embedded" : { + "type" : "object", + "properties" : { + "paymentOptions" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/PaymentOptionResponse" } } } @@ -3215,7 +3273,7 @@ } } }, - "DebtPositionTypeOrgOperators" : { + "PaymentOption" : { "type" : "object", "properties" : { "creationDate" : { @@ -3229,32 +3287,51 @@ "updateOperatorExternalId" : { "type" : "string" }, - "debtPositionTypeOrgOperatorId" : { + "paymentOptionId" : { "type" : "integer", "format" : "int64" }, - "debtPositionTypeOrgId" : { + "debtPositionId" : { "type" : "integer", "format" : "int64" }, - "operatorExternalUserId" : { + "totalAmountCents" : { + "type" : "integer", + "format" : "int64" + }, + "status" : { + "type" : "string", + "enum" : [ "TO_SYNC", "REPORTED", "PAID", "PARTIALLY_PAID", "CANCELLED", "INVALID", "EXPIRED", "UNPAID" ] + }, + "multiDebtor" : { + "type" : "boolean" + }, + "dueDate" : { + "type" : "string", + "format" : "date-time" + }, + "description" : { "type" : "string" }, + "paymentOptionType" : { + "type" : "string", + "enum" : [ "SINGLE_INSTALLMENT", "INSTALMENTS", "DOWN_PAYMENT" ] + }, "_links" : { "$ref" : "#/components/schemas/Links" } } }, - "PagedModelDebtPositionTypeOrgOperators" : { + "PagedModelPaymentOption" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "debtPositionTypeOrgOperatorses" : { + "paymentOptions" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/DebtPositionTypeOrgOperators" + "$ref" : "#/components/schemas/PaymentOption" } } } @@ -3267,7 +3344,26 @@ } } }, - "ReceiptNoPII" : { + "CollectionModelInstallmentNoPII" : { + "type" : "object", + "properties" : { + "_embedded" : { + "type" : "object", + "properties" : { + "installmentNoPIIs" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/InstallmentNoPIIResponse" + } + } + } + }, + "_links" : { + "$ref" : "#/components/schemas/Links" + } + } + }, + "InstallmentNoPII" : { "type" : "object", "properties" : { "creationDate" : { @@ -3281,90 +3377,70 @@ "updateOperatorExternalId" : { "type" : "string" }, - "receiptId" : { - "type" : "integer", - "format" : "int64" - }, "installmentId" : { "type" : "integer", "format" : "int64" }, - "paymentReceiptId" : { + "paymentOptionId" : { "type" : "integer", "format" : "int64" }, - "noticeNumber" : { - "type" : "string" + "status" : { + "type" : "string", + "enum" : [ "TO_SYNC", "REPORTED", "PAID", "CANCELLED", "INVALID", "EXPIRED", "UNPAID" ] }, - "orgFiscalCode" : { + "iupdPagopa" : { "type" : "string" }, - "outcome" : { + "iud" : { "type" : "string" }, - "creditorReferenceId" : { + "iuv" : { "type" : "string" }, - "paymentAmountCents" : { - "type" : "integer", - "format" : "int64" - }, - "description" : { + "iur" : { "type" : "string" }, - "companyName" : { + "iuf" : { "type" : "string" }, - "officeName" : { + "nav" : { "type" : "string" }, - "idPsp" : { - "type" : "string" + "dueDate" : { + "type" : "string", + "format" : "date-time" }, - "pspFiscalCode" : { + "paymentTypeCode" : { "type" : "string" }, - "pspPartitaIva" : { - "type" : "string" + "amountCents" : { + "type" : "integer", + "format" : "int64" }, - "pspCompanyName" : { - "type" : "string" + "notificationFeeCents" : { + "type" : "integer", + "format" : "int64" }, - "idChannel" : { + "remittanceInformation" : { "type" : "string" }, - "channelDescription" : { + "humanFriendlyRemittanceInformation" : { "type" : "string" }, - "paymentMethod" : { + "balance" : { "type" : "string" }, - "feeCents" : { - "type" : "integer", - "format" : "int64" - }, - "paymentDateTime" : { - "type" : "string", - "format" : "date-time" - }, - "applicationDate" : { - "type" : "string", - "format" : "date-time" - }, - "transferDate" : { - "type" : "string", - "format" : "date-time" - }, - "standin" : { - "type" : "boolean" - }, - "debtorEntityType" : { + "legacyPaymentMetadata" : { "type" : "string" }, "personalDataId" : { "type" : "integer", "format" : "int64" }, + "debtorEntityType" : { + "type" : "string" + }, "debtorFiscalCodeHash" : { "type" : "string", "format" : "byte" @@ -3374,16 +3450,16 @@ } } }, - "PagedModelReceiptNoPII" : { + "PagedModelInstallmentNoPII" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "receiptNoPIIs" : { + "installmentNoPIIs" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/ReceiptNoPII" + "$ref" : "#/components/schemas/InstallmentNoPII" } } } @@ -3396,7 +3472,26 @@ } } }, - "DebtPositionTypeOrg" : { + "CollectionModelTransfer" : { + "type" : "object", + "properties" : { + "_embedded" : { + "type" : "object", + "properties" : { + "transfers" : { + "type" : "array", + "items" : { + "$ref" : "#/components/schemas/TransferResponse" + } + } + } + }, + "_links" : { + "$ref" : "#/components/schemas/Links" + } + } + }, + "ReceiptNoPII" : { "type" : "object", "properties" : { "creationDate" : { @@ -3410,173 +3505,109 @@ "updateOperatorExternalId" : { "type" : "string" }, - "debtPositionTypeOrgId" : { + "receiptId" : { "type" : "integer", "format" : "int64" }, - "debtPositionTypeId" : { + "installmentId" : { "type" : "integer", "format" : "int64" }, - "organizationId" : { + "paymentReceiptId" : { "type" : "integer", "format" : "int64" }, - "balance" : { + "noticeNumber" : { "type" : "string" }, - "code" : { + "orgFiscalCode" : { "type" : "string" }, - "description" : { + "outcome" : { "type" : "string" }, - "iban" : { + "creditorReferenceId" : { "type" : "string" }, - "postalIban" : { - "type" : "string" + "paymentAmountCents" : { + "type" : "integer", + "format" : "int64" }, - "postalAccountCode" : { + "description" : { "type" : "string" }, - "holderPostalCc" : { + "companyName" : { "type" : "string" }, - "orgSector" : { + "officeName" : { "type" : "string" }, - "xsdDefinitionRef" : { + "idPsp" : { "type" : "string" }, - "amountCents" : { - "type" : "integer", - "format" : "int64" - }, - "externalPaymentUrl" : { + "pspFiscalCode" : { "type" : "string" }, - "flagAnonymousFiscalCode" : { - "type" : "boolean" - }, - "flagMandatoryDueDate" : { - "type" : "boolean" - }, - "flagSpontaneous" : { - "type" : "boolean" - }, - "flagNotifyIo" : { - "type" : "boolean" - }, - "ioTemplateMessage" : { + "pspPartitaIva" : { "type" : "string" }, - "flagActive" : { - "type" : "boolean" + "pspCompanyName" : { + "type" : "string" }, - "flagNotifyOutcomePush" : { - "type" : "boolean" + "idChannel" : { + "type" : "string" }, - "notifyOutcomePushOrgSilServiceId" : { - "type" : "integer", - "format" : "int64" + "channelDescription" : { + "type" : "string" }, - "flagAmountActualization" : { - "type" : "boolean" + "paymentMethod" : { + "type" : "string" }, - "amountActualizationOrgSilServiceId" : { + "feeCents" : { "type" : "integer", "format" : "int64" }, - "flagExternal" : { - "type" : "boolean" - }, - "_links" : { - "$ref" : "#/components/schemas/Links" - } - } - }, - "PagedModelDebtPositionTypeOrg" : { - "type" : "object", - "properties" : { - "_embedded" : { - "type" : "object", - "properties" : { - "debtPositionTypeOrgs" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/DebtPositionTypeOrg" - } - } - } - }, - "_links" : { - "$ref" : "#/components/schemas/Links" - }, - "page" : { - "$ref" : "#/components/schemas/PageMetadata" - } - } - }, - "PaymentOption" : { - "type" : "object", - "properties" : { - "creationDate" : { + "paymentDateTime" : { "type" : "string", "format" : "date-time" }, - "updateDate" : { + "applicationDate" : { "type" : "string", "format" : "date-time" }, - "updateOperatorExternalId" : { - "type" : "string" - }, - "paymentOptionId" : { - "type" : "integer", - "format" : "int64" - }, - "debtPositionId" : { - "type" : "integer", - "format" : "int64" - }, - "totalAmountCents" : { - "type" : "integer", - "format" : "int64" - }, - "status" : { + "transferDate" : { "type" : "string", - "enum" : [ "TO_SYNC", "REPORTED", "PAID", "PARTIALLY_PAID", "CANCELLED", "INVALID", "EXPIRED", "UNPAID" ] + "format" : "date-time" }, - "multiDebtor" : { + "standin" : { "type" : "boolean" }, - "dueDate" : { - "type" : "string", - "format" : "date-time" - }, - "description" : { + "debtorEntityType" : { "type" : "string" }, - "paymentOptionType" : { + "personalDataId" : { + "type" : "integer", + "format" : "int64" + }, + "debtorFiscalCodeHash" : { "type" : "string", - "enum" : [ "SINGLE_INSTALLMENT", "INSTALMENTS", "DOWN_PAYMENT" ] + "format" : "byte" }, "_links" : { "$ref" : "#/components/schemas/Links" } } }, - "PagedModelPaymentOption" : { + "PagedModelReceiptNoPII" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "paymentOptions" : { + "receiptNoPIIs" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/PaymentOption" + "$ref" : "#/components/schemas/ReceiptNoPII" } } } @@ -3589,26 +3620,7 @@ } } }, - "CollectionModelInstallmentNoPII" : { - "type" : "object", - "properties" : { - "_embedded" : { - "type" : "object", - "properties" : { - "installmentNoPIIs" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/InstallmentNoPIIResponse" - } - } - } - }, - "_links" : { - "$ref" : "#/components/schemas/Links" - } - } - }, - "DebtPosition" : { + "DebtPositionType" : { "type" : "object", "properties" : { "creationDate" : { @@ -3622,62 +3634,62 @@ "updateOperatorExternalId" : { "type" : "string" }, - "debtPositionId" : { + "debtPositionTypeId" : { "type" : "integer", "format" : "int64" }, - "iupdOrg" : { + "brokerId" : { + "type" : "integer", + "format" : "int64" + }, + "code" : { "type" : "string" }, "description" : { "type" : "string" }, - "status" : { - "type" : "string", - "enum" : [ "TO_SYNC", "REPORTED", "PAID", "PARTIALLY_PAID", "CANCELLED", "INVALID", "EXPIRED", "UNPAID" ] + "orgType" : { + "type" : "string" }, - "ingestionFlowFileId" : { - "type" : "integer", - "format" : "int64" + "macroArea" : { + "type" : "string" }, - "ingestionFlowFileLineNumber" : { - "type" : "integer", - "format" : "int64" + "serviceType" : { + "type" : "string" }, - "organizationId" : { - "type" : "integer", - "format" : "int64" + "collectingReason" : { + "type" : "string" }, - "debtPositionTypeOrgId" : { - "type" : "integer", - "format" : "int64" + "taxonomyCode" : { + "type" : "string" }, - "notificationDate" : { - "type" : "string", - "format" : "date-time" + "flagAnonymousFiscalCode" : { + "type" : "boolean" }, - "validityDate" : { - "type" : "string", - "format" : "date-time" + "flagMandatoryDueDate" : { + "type" : "boolean" }, - "flagIuvVolatile" : { + "flagNotifyIo" : { "type" : "boolean" }, + "ioTemplateMessage" : { + "type" : "string" + }, "_links" : { "$ref" : "#/components/schemas/Links" } } }, - "PagedModelDebtPosition" : { + "PagedModelDebtPositionType" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "debtPositions" : { + "debtPositionTypes" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/DebtPosition" + "$ref" : "#/components/schemas/DebtPositionType" } } } @@ -3690,26 +3702,7 @@ } } }, - "CollectionModelPaymentOption" : { - "type" : "object", - "properties" : { - "_embedded" : { - "type" : "object", - "properties" : { - "paymentOptions" : { - "type" : "array", - "items" : { - "$ref" : "#/components/schemas/PaymentOptionResponse" - } - } - } - }, - "_links" : { - "$ref" : "#/components/schemas/Links" - } - } - }, - "Transfer" : { + "DebtPositionTypeOrgOperators" : { "type" : "object", "properties" : { "creationDate" : { @@ -3723,58 +3716,32 @@ "updateOperatorExternalId" : { "type" : "string" }, - "transferId" : { - "type" : "integer", - "format" : "int64" - }, - "installmentId" : { + "debtPositionTypeOrgOperatorId" : { "type" : "integer", "format" : "int64" }, - "orgFiscalCode" : { - "type" : "string" - }, - "orgName" : { - "type" : "string" - }, - "amountCents" : { + "debtPositionTypeOrgId" : { "type" : "integer", "format" : "int64" }, - "remittanceInformation" : { - "type" : "string" - }, - "stamp" : { - "$ref" : "#/components/schemas/Stamp" - }, - "iban" : { - "type" : "string" - }, - "postalIban" : { - "type" : "string" - }, - "category" : { + "operatorExternalUserId" : { "type" : "string" }, - "transferIndex" : { - "type" : "integer", - "format" : "int64" - }, "_links" : { "$ref" : "#/components/schemas/Links" } } }, - "PagedModelTransfer" : { + "PagedModelDebtPositionTypeOrgOperators" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "transfers" : { + "debtPositionTypeOrgOperatorses" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/Transfer" + "$ref" : "#/components/schemas/DebtPositionTypeOrgOperators" } } } @@ -3787,7 +3754,7 @@ } } }, - "DebtPositionType" : { + "DebtPositionTypeOrg" : { "type" : "object", "properties" : { "creationDate" : { @@ -3801,33 +3768,50 @@ "updateOperatorExternalId" : { "type" : "string" }, + "debtPositionTypeOrgId" : { + "type" : "integer", + "format" : "int64" + }, "debtPositionTypeId" : { "type" : "integer", "format" : "int64" }, - "brokerId" : { + "organizationId" : { "type" : "integer", "format" : "int64" }, + "balance" : { + "type" : "string" + }, "code" : { "type" : "string" }, "description" : { "type" : "string" }, - "orgType" : { + "iban" : { "type" : "string" }, - "macroArea" : { + "postalIban" : { "type" : "string" }, - "serviceType" : { + "postalAccountCode" : { "type" : "string" }, - "collectingReason" : { + "holderPostalCc" : { "type" : "string" }, - "taxonomyCode" : { + "orgSector" : { + "type" : "string" + }, + "xsdDefinitionRef" : { + "type" : "string" + }, + "amountCents" : { + "type" : "integer", + "format" : "int64" + }, + "externalPaymentUrl" : { "type" : "string" }, "flagAnonymousFiscalCode" : { @@ -3836,27 +3820,50 @@ "flagMandatoryDueDate" : { "type" : "boolean" }, + "flagSpontaneous" : { + "type" : "boolean" + }, "flagNotifyIo" : { "type" : "boolean" }, "ioTemplateMessage" : { "type" : "string" }, + "flagActive" : { + "type" : "boolean" + }, + "flagNotifyOutcomePush" : { + "type" : "boolean" + }, + "notifyOutcomePushOrgSilServiceId" : { + "type" : "integer", + "format" : "int64" + }, + "flagAmountActualization" : { + "type" : "boolean" + }, + "amountActualizationOrgSilServiceId" : { + "type" : "integer", + "format" : "int64" + }, + "flagExternal" : { + "type" : "boolean" + }, "_links" : { "$ref" : "#/components/schemas/Links" } } }, - "PagedModelDebtPositionType" : { + "PagedModelDebtPositionTypeOrg" : { "type" : "object", "properties" : { "_embedded" : { "type" : "object", "properties" : { - "debtPositionTypes" : { + "debtPositionTypeOrgs" : { "type" : "array", "items" : { - "$ref" : "#/components/schemas/DebtPositionType" + "$ref" : "#/components/schemas/DebtPositionTypeOrg" } } } @@ -4422,242 +4429,89 @@ "type" : "string", "enum" : [ "TO_SYNC", "REPORTED", "PAID", "PARTIALLY_PAID", "CANCELLED", "INVALID", "EXPIRED", "UNPAID" ] }, - "multiDebtor" : { - "type" : "boolean" - }, - "dueDate" : { - "type" : "string", - "format" : "date-time" - }, - "description" : { - "type" : "string" - }, - "paymentOptionType" : { - "type" : "string", - "enum" : [ "SINGLE_INSTALLMENT", "INSTALMENTS", "DOWN_PAYMENT" ] - } - } - }, - "TransferResponse" : { - "type" : "object", - "properties" : { - "creationDate" : { - "type" : "string", - "format" : "date-time" - }, - "updateDate" : { - "type" : "string", - "format" : "date-time" - }, - "updateOperatorExternalId" : { - "type" : "string" - }, - "transferId" : { - "type" : "integer", - "format" : "int64" - }, - "installmentId" : { - "type" : "integer", - "format" : "int64" - }, - "orgFiscalCode" : { - "type" : "string" - }, - "orgName" : { - "type" : "string" - }, - "amountCents" : { - "type" : "integer", - "format" : "int64" - }, - "remittanceInformation" : { - "type" : "string" - }, - "stamp" : { - "$ref" : "#/components/schemas/Stamp" - }, - "iban" : { - "type" : "string" - }, - "postalIban" : { - "type" : "string" - }, - "category" : { - "type" : "string" - }, - "transferIndex" : { - "type" : "integer", - "format" : "int64" - } - } - }, - "ReceiptNoPIIRequestBody" : { - "type" : "object", - "properties" : { - "creationDate" : { - "type" : "string", - "format" : "date-time" - }, - "updateDate" : { - "type" : "string", - "format" : "date-time" - }, - "updateOperatorExternalId" : { - "type" : "string" - }, - "receiptId" : { - "type" : "integer", - "format" : "int64" - }, - "installmentId" : { - "type" : "integer", - "format" : "int64" - }, - "paymentReceiptId" : { - "type" : "integer", - "format" : "int64" - }, - "noticeNumber" : { - "type" : "string" - }, - "orgFiscalCode" : { - "type" : "string" - }, - "outcome" : { - "type" : "string" - }, - "creditorReferenceId" : { - "type" : "string" - }, - "paymentAmountCents" : { - "type" : "integer", - "format" : "int64" - }, - "description" : { - "type" : "string" - }, - "companyName" : { - "type" : "string" - }, - "officeName" : { - "type" : "string" - }, - "idPsp" : { - "type" : "string" - }, - "pspFiscalCode" : { - "type" : "string" - }, - "pspPartitaIva" : { - "type" : "string" - }, - "pspCompanyName" : { - "type" : "string" - }, - "idChannel" : { - "type" : "string" - }, - "channelDescription" : { - "type" : "string" - }, - "paymentMethod" : { - "type" : "string" - }, - "feeCents" : { - "type" : "integer", - "format" : "int64" - }, - "paymentDateTime" : { - "type" : "string", - "format" : "date-time" - }, - "applicationDate" : { - "type" : "string", - "format" : "date-time" - }, - "transferDate" : { - "type" : "string", - "format" : "date-time" - }, - "standin" : { - "type" : "boolean" - }, - "debtorEntityType" : { - "type" : "string" - }, - "personalDataId" : { - "type" : "integer", - "format" : "int64" - }, - "debtorFiscalCodeHash" : { - "type" : "string", - "format" : "byte" - } - } - }, - "DebtPositionErrorDTO" : { - "required" : [ "code", "message" ], - "type" : "object", - "properties" : { - "code" : { - "type" : "string", - "enum" : [ "DEBT_POSITION_IVALID_REQUEST", "DEBT_POSITION_GENERIC_ERROR" ] - }, - "message" : { - "type" : "string" - } - } - }, - "IudSyncStatusUpdateDTO" : { - "type" : "object", - "properties" : { - "newStatus" : { - "type" : "string" - }, - "iupdPagopa" : { + "multiDebtor" : { + "type" : "boolean" + }, + "dueDate" : { + "type" : "string", + "format" : "date-time" + }, + "description" : { "type" : "string" + }, + "paymentOptionType" : { + "type" : "string", + "enum" : [ "SINGLE_INSTALLMENT", "INSTALMENTS", "DOWN_PAYMENT" ] } } }, - "PersonDTO" : { - "required" : [ "email", "entityType", "fiscalCode", "fullName" ], + "TransferResponse" : { "type" : "object", "properties" : { - "entityType" : { - "type" : "string" + "creationDate" : { + "type" : "string", + "format" : "date-time" }, - "fiscalCode" : { - "type" : "string" + "updateDate" : { + "type" : "string", + "format" : "date-time" }, - "fullName" : { + "updateOperatorExternalId" : { "type" : "string" }, - "address" : { - "type" : "string" + "transferId" : { + "type" : "integer", + "format" : "int64" }, - "civic" : { + "installmentId" : { + "type" : "integer", + "format" : "int64" + }, + "orgFiscalCode" : { "type" : "string" }, - "postalCode" : { + "orgName" : { "type" : "string" }, - "location" : { + "amountCents" : { + "type" : "integer", + "format" : "int64" + }, + "remittanceInformation" : { "type" : "string" }, - "province" : { + "stamp" : { + "$ref" : "#/components/schemas/Stamp" + }, + "iban" : { "type" : "string" }, - "nation" : { + "postalIban" : { "type" : "string" }, - "email" : { + "category" : { "type" : "string" + }, + "transferIndex" : { + "type" : "integer", + "format" : "int64" } } }, - "ReceiptDTO" : { + "ReceiptNoPIIRequestBody" : { "type" : "object", "properties" : { + "creationDate" : { + "type" : "string", + "format" : "date-time" + }, + "updateDate" : { + "type" : "string", + "format" : "date-time" + }, + "updateOperatorExternalId" : { + "type" : "string" + }, "receiptId" : { "type" : "integer", "format" : "int64" @@ -4667,7 +4521,8 @@ "format" : "int64" }, "paymentReceiptId" : { - "type" : "string" + "type" : "integer", + "format" : "int64" }, "noticeNumber" : { "type" : "string" @@ -4731,26 +4586,19 @@ "type" : "string", "format" : "date-time" }, - "receiptBytes" : { - "type" : "string", - "format" : "byte" - }, "standin" : { "type" : "boolean" }, - "debtor" : { - "$ref" : "#/components/schemas/PersonDTO" - }, - "payer" : { - "$ref" : "#/components/schemas/PersonDTO" + "debtorEntityType" : { + "type" : "string" }, - "creationDate" : { - "type" : "string", - "format" : "date-time" + "personalDataId" : { + "type" : "integer", + "format" : "int64" }, - "updateDate" : { + "debtorFiscalCodeHash" : { "type" : "string", - "format" : "date-time" + "format" : "byte" } } }, @@ -4937,6 +4785,42 @@ } } }, + "PersonDTO" : { + "required" : [ "email", "entityType", "fiscalCode", "fullName" ], + "type" : "object", + "properties" : { + "entityType" : { + "type" : "string" + }, + "fiscalCode" : { + "type" : "string" + }, + "fullName" : { + "type" : "string" + }, + "address" : { + "type" : "string" + }, + "civic" : { + "type" : "string" + }, + "postalCode" : { + "type" : "string" + }, + "location" : { + "type" : "string" + }, + "province" : { + "type" : "string" + }, + "nation" : { + "type" : "string" + }, + "email" : { + "type" : "string" + } + } + }, "TransferDTO" : { "required" : [ "amountCents", "category", "orgFiscalCode", "orgName", "remittanceInformation" ], "type" : "object", @@ -4986,6 +4870,130 @@ } } }, + "DebtPositionErrorDTO" : { + "required" : [ "code", "message" ], + "type" : "object", + "properties" : { + "code" : { + "type" : "string", + "enum" : [ "DEBT_POSITION_IVALID_REQUEST", "DEBT_POSITION_GENERIC_ERROR" ] + }, + "message" : { + "type" : "string" + } + } + }, + "IupdSyncStatusUpdateDTO" : { + "type" : "object", + "properties" : { + "newStatus" : { + "type" : "string", + "enum" : [ "TO_SYNC", "REPORTED", "PAID", "CANCELLED", "INVALID", "EXPIRED", "UNPAID" ] + }, + "iupdPagopa" : { + "type" : "string" + } + } + }, + "ReceiptDTO" : { + "type" : "object", + "properties" : { + "receiptId" : { + "type" : "integer", + "format" : "int64" + }, + "installmentId" : { + "type" : "integer", + "format" : "int64" + }, + "paymentReceiptId" : { + "type" : "string" + }, + "noticeNumber" : { + "type" : "string" + }, + "orgFiscalCode" : { + "type" : "string" + }, + "outcome" : { + "type" : "string" + }, + "creditorReferenceId" : { + "type" : "string" + }, + "paymentAmountCents" : { + "type" : "integer", + "format" : "int64" + }, + "description" : { + "type" : "string" + }, + "companyName" : { + "type" : "string" + }, + "officeName" : { + "type" : "string" + }, + "idPsp" : { + "type" : "string" + }, + "pspFiscalCode" : { + "type" : "string" + }, + "pspPartitaIva" : { + "type" : "string" + }, + "pspCompanyName" : { + "type" : "string" + }, + "idChannel" : { + "type" : "string" + }, + "channelDescription" : { + "type" : "string" + }, + "paymentMethod" : { + "type" : "string" + }, + "feeCents" : { + "type" : "integer", + "format" : "int64" + }, + "paymentDateTime" : { + "type" : "string", + "format" : "date-time" + }, + "applicationDate" : { + "type" : "string", + "format" : "date-time" + }, + "transferDate" : { + "type" : "string", + "format" : "date-time" + }, + "receiptBytes" : { + "type" : "string", + "format" : "byte" + }, + "standin" : { + "type" : "boolean" + }, + "debtor" : { + "$ref" : "#/components/schemas/PersonDTO" + }, + "payer" : { + "$ref" : "#/components/schemas/PersonDTO" + }, + "creationDate" : { + "type" : "string", + "format" : "date-time" + }, + "updateDate" : { + "type" : "string", + "format" : "date-time" + } + } + }, "Link" : { "type" : "object", "properties" : { diff --git a/openapi/p4pa-debt-position.openapi.yaml b/openapi/p4pa-debt-position.openapi.yaml index 88f60db..c251187 100644 --- a/openapi/p4pa-debt-position.openapi.yaml +++ b/openapi/p4pa-debt-position.openapi.yaml @@ -417,14 +417,15 @@ components: SyncStatusUpdateRequestDTO: type: object additionalProperties: - $ref: "#/components/schemas/IudSyncStatusUpdateDTO" - IudSyncStatusUpdateDTO: + $ref: "#/components/schemas/IupdSyncStatusUpdateDTO" + IupdSyncStatusUpdateDTO: type: object properties: newStatus: - type: string + $ref: "#/components/schemas/InstallmentStatus" iupdPagopa: type: string + DebtPositionErrorDTO: type: object required: diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerImpl.java b/src/main/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerImpl.java index bbc2efa..00f7a91 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerImpl.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerImpl.java @@ -2,7 +2,7 @@ import it.gov.pagopa.pu.debtpositions.controller.generated.DebtPositionApi; import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; -import it.gov.pagopa.pu.debtpositions.dto.generated.IudSyncStatusUpdateDTO; +import it.gov.pagopa.pu.debtpositions.dto.generated.IupdSyncStatusUpdateDTO; import it.gov.pagopa.pu.debtpositions.service.statusalign.DebtPositionHierarchyStatusAlignerService; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -25,8 +25,8 @@ public ResponseEntity createDebtPosition(DebtPositionDTO debtPo } @Override - public ResponseEntity finalizeSyncStatus(Long debtPositionId, Map requestBody) { - debtPositionHierarchyStatusAlignerService.finalizeSyncStatus(debtPositionId, requestBody); - return new ResponseEntity<>(HttpStatus.OK); + public ResponseEntity finalizeSyncStatus(Long debtPositionId, Map requestBody) { + DebtPositionDTO body = debtPositionHierarchyStatusAlignerService.finalizeSyncStatus(debtPositionId, requestBody); + return new ResponseEntity<>(body, HttpStatus.OK); } } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapper.java b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapper.java index 26688db..14b443f 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapper.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapper.java @@ -8,6 +8,7 @@ import org.springframework.data.util.Pair; import org.springframework.stereotype.Service; +import java.time.OffsetDateTime; import java.util.*; import java.util.stream.Collector; import java.util.stream.Collectors; @@ -53,5 +54,27 @@ public Pair> mapToModel(DebtPos return Pair.of(debtPosition, installmentMapping); } + + public DebtPositionDTO mapToDto(DebtPosition debtPosition){ + return DebtPositionDTO.builder() + .debtPositionId(debtPosition.getDebtPositionId()) + .iupdOrg(debtPosition.getIupdOrg()) + .description(debtPosition.getDescription()) + .status(debtPosition.getStatus()) + .ingestionFlowFileId(debtPosition.getIngestionFlowFileId()) + .ingestionFlowFileLineNumber(debtPosition.getIngestionFlowFileLineNumber()) + .organizationId(debtPosition.getOrganizationId()) + .debtPositionTypeOrgId(debtPosition.getDebtPositionTypeOrgId()) + .notificationDate(debtPosition.getNotificationDate()) + .validityDate(debtPosition.getValidityDate()) + .flagIuvVolatile(debtPosition.isFlagIuvVolatile()) + .creationDate(OffsetDateTime.from(debtPosition.getCreationDate())) + .updateDate(OffsetDateTime.from(debtPosition.getUpdateDate())) + .paymentOptions( + debtPosition.getPaymentOptions().stream() + .map(paymentOptionMapper::mapToDto) + .toList() + ) .build(); + } } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapper.java b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapper.java index 74c8671..3fdfca9 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapper.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapper.java @@ -2,8 +2,11 @@ import it.gov.pagopa.pu.debtpositions.dto.Installment; import it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentDTO; +import it.gov.pagopa.pu.debtpositions.model.InstallmentNoPII; import org.springframework.stereotype.Service; +import java.time.OffsetDateTime; + @Service public class InstallmentMapper { @@ -44,4 +47,32 @@ public Installment mapToModel(InstallmentDTO dto) { return installment; } + public InstallmentDTO mapToDto(InstallmentNoPII installment) { + return InstallmentDTO.builder() + .installmentId(installment.getInstallmentId()) + .paymentOptionId(installment.getPaymentOptionId()) + .status(installment.getStatus()) + .iupdPagopa(installment.getIupdPagopa()) + .iud(installment.getIud()) + .iuv(installment.getIuv()) + .iur(installment.getIur()) + .iuf(installment.getIuf()) + .nav(installment.getNav()) + .dueDate(installment.getDueDate()) + .paymentTypeCode(installment.getPaymentTypeCode()) + .amountCents(installment.getAmountCents()) + .notificationFeeCents(installment.getNotificationFeeCents()) + .remittanceInformation(installment.getRemittanceInformation()) + .humanFriendlyRemittanceInformation(installment.getHumanFriendlyRemittanceInformation()) + .balance(installment.getBalance()) + .legacyPaymentMetadata(installment.getLegacyPaymentMetadata()) + .transfers(installment.getTransfers().stream() + .map(transferMapper::mapToDto) + .toList()) + .creationDate(OffsetDateTime.from(installment.getCreationDate())) + .updateDate(OffsetDateTime.from(installment.getUpdateDate())) + .build(); + } + + } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapper.java b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapper.java index 24e2271..8258efb 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapper.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapper.java @@ -55,4 +55,23 @@ public Pair> mapToModel(Paymen return Pair.of(paymentOption, installmentMapping); } + + public PaymentOptionDTO mapToDto(PaymentOption paymentOption) { + return PaymentOptionDTO.builder() + .paymentOptionId(paymentOption.getPaymentOptionId()) + .debtPositionId(paymentOption.getDebtPositionId()) + .totalAmountCents(paymentOption.getTotalAmountCents()) + .status(paymentOption.getStatus()) + .multiDebtor(paymentOption.isMultiDebtor()) + .dueDate(paymentOption.getDueDate()) + .description(paymentOption.getDescription()) + .paymentOptionType(PaymentOptionDTO.PaymentOptionTypeEnum.valueOf(paymentOption.getPaymentOptionType().name())) + .installments( + paymentOption.getInstallments().stream() + .map(installmentMapper::mapToDto) + .toList() + ) + .build(); + } + } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PersonMapper.java b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PersonMapper.java index d44fe51..ec4adbb 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PersonMapper.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/PersonMapper.java @@ -21,5 +21,4 @@ public Person mapToModel(PersonDTO dto) { person.setEmail(dto.getEmail()); return person; } - } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/TransferMapper.java b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/TransferMapper.java index 08437ac..e6528f5 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/TransferMapper.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/mapper/TransferMapper.java @@ -24,4 +24,23 @@ public Transfer mapToModel(TransferDTO dto) { return transfer; } + public TransferDTO mapToDto(Transfer transfer) { + return TransferDTO.builder() + .transferId(transfer.getTransferId()) + .installmentId(transfer.getInstallmentId()) + .orgFiscalCode(transfer.getOrgFiscalCode()) + .orgName(transfer.getOrgName()) + .amountCents(transfer.getAmountCents()) + .remittanceInformation(transfer.getRemittanceInformation()) + .stampType(transfer.getStamp().getStampType()) + .stampHashDocument(transfer.getStamp().getStampHashDocument()) + .stampProvincialResidence(transfer.getStamp().getStampProvincialResidence()) + .iban(transfer.getIban()) + .postalIban(transfer.getPostalIban()) + .category(transfer.getCategory()) + .transferIndex(transfer.getTransferIndex()) + .build(); + } + + } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerService.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerService.java index 52f0a72..23c37c6 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerService.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerService.java @@ -1,10 +1,11 @@ package it.gov.pagopa.pu.debtpositions.service.statusalign; -import it.gov.pagopa.pu.debtpositions.dto.generated.IudSyncStatusUpdateDTO; +import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; +import it.gov.pagopa.pu.debtpositions.dto.generated.IupdSyncStatusUpdateDTO; import java.util.Map; public interface DebtPositionHierarchyStatusAlignerService { - void finalizeSyncStatus(Long debtPositionId, Map syncStatusDTO); + DebtPositionDTO finalizeSyncStatus(Long debtPositionId, Map syncStatusDTO); } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerServiceImpl.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerServiceImpl.java index 8613d0d..3a041f4 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerServiceImpl.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerServiceImpl.java @@ -1,14 +1,16 @@ package it.gov.pagopa.pu.debtpositions.service.statusalign; +import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; import it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentStatus; -import it.gov.pagopa.pu.debtpositions.dto.generated.IudSyncStatusUpdateDTO; -import it.gov.pagopa.pu.debtpositions.exception.custom.InvalidStatusException; +import it.gov.pagopa.pu.debtpositions.dto.generated.IupdSyncStatusUpdateDTO; +import it.gov.pagopa.pu.debtpositions.mapper.DebtPositionMapper; import it.gov.pagopa.pu.debtpositions.model.DebtPosition; import it.gov.pagopa.pu.debtpositions.repository.DebtPositionRepository; import it.gov.pagopa.pu.debtpositions.repository.InstallmentNoPIIRepository; import it.gov.pagopa.pu.debtpositions.service.statusalign.debtposition.DebtPositionInnerStatusAlignerService; import it.gov.pagopa.pu.debtpositions.service.statusalign.paymentoption.PaymentOptionInnerStatusAlignerService; import jakarta.transaction.Transactional; +import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.util.Map; @@ -16,49 +18,60 @@ import static it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentStatus.TO_SYNC; @Service +@Slf4j public class DebtPositionHierarchyStatusAlignerServiceImpl implements DebtPositionHierarchyStatusAlignerService { private final DebtPositionRepository debtPositionRepository; private final InstallmentNoPIIRepository installmentNoPIIRepository; private final PaymentOptionInnerStatusAlignerService paymentOptionInnerStatusAlignerService; private final DebtPositionInnerStatusAlignerService debtPositionInnerStatusAlignerService; + private final DebtPositionMapper debtPositionMapper; public DebtPositionHierarchyStatusAlignerServiceImpl(DebtPositionRepository debtPositionRepository, - InstallmentNoPIIRepository installmentNoPIIRepository, PaymentOptionInnerStatusAlignerService paymentOptionInnerStatusAlignerService, DebtPositionInnerStatusAlignerService debtPositionInnerStatusAlignerService) { + InstallmentNoPIIRepository installmentNoPIIRepository, PaymentOptionInnerStatusAlignerService paymentOptionInnerStatusAlignerService, DebtPositionInnerStatusAlignerService debtPositionInnerStatusAlignerService, DebtPositionMapper debtPositionMapper) { this.debtPositionRepository = debtPositionRepository; this.installmentNoPIIRepository = installmentNoPIIRepository; this.paymentOptionInnerStatusAlignerService = paymentOptionInnerStatusAlignerService; this.debtPositionInnerStatusAlignerService = debtPositionInnerStatusAlignerService; + this.debtPositionMapper = debtPositionMapper; } @Transactional @Override - public void finalizeSyncStatus(Long debtPositionId, Map syncStatusDTO) { + public DebtPositionDTO finalizeSyncStatus(Long debtPositionId, Map syncStatusDTO) { DebtPosition debtPosition = debtPositionRepository.findOneWithAllDataByDebtPositionId(debtPositionId); debtPosition.getPaymentOptions().forEach(paymentOption -> paymentOption.getInstallments().stream() - .filter(installment -> TO_SYNC.equals(installment.getStatus())) - .filter(installment -> syncStatusDTO.containsKey(installment.getIud())) - .forEach(installment -> { - IudSyncStatusUpdateDTO updateDTO = syncStatusDTO.get(installment.getIud()); + .filter(installment -> { + boolean isToSync = TO_SYNC.equals(installment.getStatus()); + boolean hasIud = syncStatusDTO.containsKey(installment.getIud()); - try { - InstallmentStatus newStatus = InstallmentStatus.valueOf(updateDTO.getNewStatus().toUpperCase()); - installment.setStatus(newStatus); - installmentNoPIIRepository.updateStatusAndIupdPagopa( - installment.getInstallmentId(), - updateDTO.getIupdPagopa(), - newStatus - ); - } catch (IllegalArgumentException e) { - throw new InvalidStatusException("Invalid status: " + updateDTO.getNewStatus()); + if (!hasIud) { + log.error("Installment with IUD [{}] is not present in the syncStatusDTO map", installment.getIud()); + } else if (!isToSync) { + log.error("Installment with IUD [{}] does not have TO_SYNC status", installment.getIud()); } + + return isToSync && hasIud; + }) + .forEach(installment -> { + IupdSyncStatusUpdateDTO updateDTO = syncStatusDTO.get(installment.getIud()); + + InstallmentStatus newStatus = updateDTO.getNewStatus(); + installment.setStatus(newStatus); + installmentNoPIIRepository.updateStatusAndIupdPagopa( + installment.getInstallmentId(), + updateDTO.getIupdPagopa(), + newStatus + ); }) ); debtPosition.getPaymentOptions().forEach(paymentOptionInnerStatusAlignerService::updatePaymentOptionStatus); debtPositionInnerStatusAlignerService.updateDebtPositionStatus(debtPosition); + + return debtPositionMapper.mapToDto(debtPosition); } } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/StatusRulesHandler.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/StatusRulesHandler.java index def1b30..37b7483 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/StatusRulesHandler.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/StatusRulesHandler.java @@ -1,11 +1,9 @@ package it.gov.pagopa.pu.debtpositions.service.statusalign; import java.util.List; -import java.util.function.BiConsumer; -import java.util.function.Function; -import java.util.function.Predicate; +import java.util.Set; -public abstract class StatusRulesHandler> { +public abstract class StatusRulesHandler, T, D> { private final E syncStatus; private final E paidStatus; @@ -25,63 +23,59 @@ protected StatusRulesHandler(E syncStatus, E paidStatus, E unpaidStatus, E expir this.invalidStatus = invalidStatus; } - public > void updateEntityStatus(T entity, - Function> childStatusExtractor, - Function, C> statusDeterminer, - BiConsumer statusUpdater, - BiConsumer repositoryUpdater) { - - List childStatuses = childStatusExtractor.apply(entity); - C newStatus = statusDeterminer.apply(childStatuses); - statusUpdater.accept(entity, newStatus); - repositoryUpdater.accept(entity, newStatus); + public void updateEntityStatus(T entity) { + List childStatuses = getChildStatuses(entity); + D newStatus = calculateNewStatus(childStatuses); + setStatus(entity, newStatus); + storeStatus(entity, newStatus); } - public boolean isToSync(List statusList) { - return statusList.contains(syncStatus); + protected abstract List getChildStatuses(T entity); + + protected abstract D calculateNewStatus(List childStatuses); + + protected abstract void setStatus(T entity, D newStatus); + + protected abstract void storeStatus(T entity, D newStatus); + + public boolean isToSync(List childrenStatusList) { + return childrenStatusList.contains(syncStatus); } - public boolean isPartiallyPaid(List statusList) { - return statusList.contains(paidStatus) && - (statusList.contains(unpaidStatus) || statusList.contains(expiredStatus)); + public boolean isPartiallyPaid(List childrenStatusList) { + return childrenStatusList.contains(paidStatus) && + (childrenStatusList.contains(unpaidStatus) || childrenStatusList.contains(expiredStatus)); } - public boolean isUnpaid(List statusList) { - return allMatchOrEmpty(statusList, status -> status.equals(unpaidStatus)) || - (allMatchOrEmpty(statusList, status -> status.equals(cancelledStatus) || status.equals(unpaidStatus)) && - statusList.contains(unpaidStatus)); + public boolean isUnpaid(List childrenStatusList) { + return allMatch(childrenStatusList, unpaidStatus, Set.of(cancelledStatus)); } - public boolean isPaid(List statusList) { - return allMatchOrEmpty(statusList, status -> status.equals(paidStatus)) || - (allMatchOrEmpty(statusList, status -> status.equals(cancelledStatus) || status.equals(paidStatus)) && - statusList.contains(paidStatus)); + public boolean isPaid(List childrenStatusList) { + return allMatch(childrenStatusList, paidStatus, Set.of(cancelledStatus)); } - public boolean isReported(List statusList) { - return allMatchOrEmpty(statusList, status -> status.equals(reportedStatus)) || - (allMatchOrEmpty(statusList, status -> status.equals(cancelledStatus) || status.equals(reportedStatus)) && - statusList.contains(reportedStatus)); + public boolean isReported(List childrenStatusList) { + return allMatch(childrenStatusList, reportedStatus, Set.of(cancelledStatus)); } - public boolean isInvalid(List statusList) { - return allMatchOrEmpty(statusList, status -> status.equals(invalidStatus)) || - (allMatchOrEmpty(statusList, status -> status.equals(cancelledStatus) || status.equals(invalidStatus)) && - statusList.contains(invalidStatus)); + public boolean isInvalid(List childrenStatusList) { + return allMatch(childrenStatusList, invalidStatus, Set.of(cancelledStatus)); } - public boolean isCancelled(List statusList) { - return allMatchOrEmpty(statusList, status -> status.equals(cancelledStatus)); + public boolean isCancelled(List childrenStatusList) { + return allMatch(childrenStatusList, cancelledStatus, Set.of()); } - public boolean isExpired(List statusList) { - return allMatchOrEmpty(statusList, status -> status.equals(expiredStatus)); + public boolean isExpired(List childrenStatusList) { + return allMatch(childrenStatusList, expiredStatus, Set.of()); } - private boolean allMatchOrEmpty(List statusList, Predicate predicate) { + private boolean allMatch(List statusList, E requiredState, Set allowedStatuses) { if (statusList.isEmpty()) { return false; } - return statusList.stream().allMatch(predicate); + return statusList.contains(requiredState) && + statusList.stream().allMatch(status -> requiredState.equals(status) || allowedStatuses.contains(status)); } } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionInnerStatusAlignerServiceImpl.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionInnerStatusAlignerServiceImpl.java index 82691ef..09408ab 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionInnerStatusAlignerServiceImpl.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionInnerStatusAlignerServiceImpl.java @@ -1,27 +1,18 @@ package it.gov.pagopa.pu.debtpositions.service.statusalign.debtposition; import it.gov.pagopa.pu.debtpositions.model.DebtPosition; -import it.gov.pagopa.pu.debtpositions.model.PaymentOption; import it.gov.pagopa.pu.debtpositions.repository.DebtPositionRepository; import org.springframework.stereotype.Service; @Service -public class DebtPositionInnerStatusAlignerServiceImpl extends DebtPositionStatusChecker implements DebtPositionInnerStatusAlignerService{ - - private final DebtPositionRepository debtPositionRepository; +public class DebtPositionInnerStatusAlignerServiceImpl extends DebtPositionStatusChecker implements DebtPositionInnerStatusAlignerService { public DebtPositionInnerStatusAlignerServiceImpl(DebtPositionRepository debtPositionRepository) { - this.debtPositionRepository = debtPositionRepository; + super(debtPositionRepository); } @Override public void updateDebtPositionStatus(DebtPosition debtPosition) { - updateEntityStatus( - debtPosition, - dp -> dp.getPaymentOptions().stream().map(PaymentOption::getStatus).toList(), - this::determineDebtPositionStatus, - DebtPosition::setStatus, - (dp, newStatus) -> debtPositionRepository.updateStatus(dp.getDebtPositionId(), newStatus) - ); + updateEntityStatus(debtPosition); } } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusChecker.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusChecker.java index a769892..5727554 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusChecker.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusChecker.java @@ -3,21 +3,26 @@ import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionStatus; import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus; import it.gov.pagopa.pu.debtpositions.exception.custom.InvalidStatusException; +import it.gov.pagopa.pu.debtpositions.model.DebtPosition; +import it.gov.pagopa.pu.debtpositions.model.PaymentOption; +import it.gov.pagopa.pu.debtpositions.repository.DebtPositionRepository; import it.gov.pagopa.pu.debtpositions.service.statusalign.StatusRulesHandler; -import org.springframework.stereotype.Component; import java.util.List; import static it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus.*; -@Component -public class DebtPositionStatusChecker extends StatusRulesHandler { +public class DebtPositionStatusChecker extends StatusRulesHandler { - public DebtPositionStatusChecker() { + private final DebtPositionRepository debtPositionRepository; + + public DebtPositionStatusChecker(DebtPositionRepository debtPositionRepository) { super(TO_SYNC, PAID, UNPAID, EXPIRED, CANCELLED, REPORTED, INVALID); + this.debtPositionRepository = debtPositionRepository; } - public DebtPositionStatus determineDebtPositionStatus(List paymentOptionStatusList) { + @Override + public DebtPositionStatus calculateNewStatus(List paymentOptionStatusList) { if (isToSync(paymentOptionStatusList)){ return DebtPositionStatus.TO_SYNC; } else if (isPartiallyPaid(paymentOptionStatusList)){ @@ -38,4 +43,21 @@ public DebtPositionStatus determineDebtPositionStatus(List throw new InvalidStatusException("Unable to determine status for DebtPosition"); } } + + @Override + protected List getChildStatuses(DebtPosition debtPosition) { + return debtPosition.getPaymentOptions().stream() + .map(PaymentOption::getStatus) + .toList(); + } + + @Override + protected void setStatus(DebtPosition debtPosition, DebtPositionStatus newStatus) { + debtPosition.setStatus(newStatus); + } + + @Override + protected void storeStatus(DebtPosition debtPosition, DebtPositionStatus newStatus) { + debtPositionRepository.updateStatus(debtPosition.getDebtPositionId(), newStatus); + } } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionInnerStatusAlignerServiceImpl.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionInnerStatusAlignerServiceImpl.java index 518fc0b..8dd7020 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionInnerStatusAlignerServiceImpl.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionInnerStatusAlignerServiceImpl.java @@ -1,6 +1,5 @@ package it.gov.pagopa.pu.debtpositions.service.statusalign.paymentoption; -import it.gov.pagopa.pu.debtpositions.model.InstallmentNoPII; import it.gov.pagopa.pu.debtpositions.model.PaymentOption; import it.gov.pagopa.pu.debtpositions.repository.PaymentOptionRepository; import org.springframework.stereotype.Service; @@ -8,20 +7,13 @@ @Service public class PaymentOptionInnerStatusAlignerServiceImpl extends PaymentOptionStatusChecker implements PaymentOptionInnerStatusAlignerService{ - private final PaymentOptionRepository paymentOptionRepository; public PaymentOptionInnerStatusAlignerServiceImpl(PaymentOptionRepository paymentOptionRepository) { - this.paymentOptionRepository = paymentOptionRepository; + super(paymentOptionRepository); } @Override public void updatePaymentOptionStatus(PaymentOption paymentOption) { - updateEntityStatus( - paymentOption, - po -> po.getInstallments().stream().map(InstallmentNoPII::getStatus).toList(), - this::determinePaymentOptionStatus, - PaymentOption::setStatus, - (po, newStatus) -> paymentOptionRepository.updateStatus(po.getPaymentOptionId(), newStatus) - ); + updateEntityStatus(paymentOption); } } diff --git a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusChecker.java b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusChecker.java index 55281f5..c40adcf 100644 --- a/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusChecker.java +++ b/src/main/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusChecker.java @@ -3,22 +3,27 @@ import it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentStatus; import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus; import it.gov.pagopa.pu.debtpositions.exception.custom.InvalidStatusException; +import it.gov.pagopa.pu.debtpositions.model.InstallmentNoPII; +import it.gov.pagopa.pu.debtpositions.model.PaymentOption; +import it.gov.pagopa.pu.debtpositions.repository.PaymentOptionRepository; import it.gov.pagopa.pu.debtpositions.service.statusalign.StatusRulesHandler; -import org.springframework.stereotype.Component; import java.util.List; import static it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus.TO_SYNC; -@Component -public class PaymentOptionStatusChecker extends StatusRulesHandler{ +public class PaymentOptionStatusChecker extends StatusRulesHandler { - public PaymentOptionStatusChecker() { + private final PaymentOptionRepository paymentOptionRepository; + + public PaymentOptionStatusChecker(PaymentOptionRepository paymentOptionRepository) { super(InstallmentStatus.TO_SYNC, InstallmentStatus.PAID, InstallmentStatus.UNPAID, InstallmentStatus.EXPIRED, InstallmentStatus.CANCELLED, InstallmentStatus.REPORTED, InstallmentStatus.INVALID); + this.paymentOptionRepository = paymentOptionRepository; } - public PaymentOptionStatus determinePaymentOptionStatus(List installmentStatusList) { + @Override + public PaymentOptionStatus calculateNewStatus(List installmentStatusList) { if (isToSync(installmentStatusList)) { return TO_SYNC; } else if (isPartiallyPaid(installmentStatusList)) { @@ -39,4 +44,21 @@ public PaymentOptionStatus determinePaymentOptionStatus(List throw new InvalidStatusException("Unable to determine status for PaymentOption"); } } + + @Override + protected List getChildStatuses(PaymentOption paymentOption) { + return paymentOption.getInstallments().stream() + .map(InstallmentNoPII::getStatus) + .toList(); + } + + @Override + protected void setStatus(PaymentOption paymentOption, PaymentOptionStatus newStatus) { + paymentOption.setStatus(newStatus); + } + + @Override + protected void storeStatus(PaymentOption paymentOption, PaymentOptionStatus newStatus) { + paymentOptionRepository.updateStatus(paymentOption.getPaymentOptionId(), newStatus); + } } diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerTest.java index e90d997..98fc8fd 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/controller/DebtPositionControllerTest.java @@ -1,7 +1,9 @@ package it.gov.pagopa.pu.debtpositions.controller; import com.fasterxml.jackson.databind.ObjectMapper; -import it.gov.pagopa.pu.debtpositions.dto.generated.IudSyncStatusUpdateDTO; +import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; +import it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentStatus; +import it.gov.pagopa.pu.debtpositions.dto.generated.IupdSyncStatusUpdateDTO; import it.gov.pagopa.pu.debtpositions.service.statusalign.DebtPositionHierarchyStatusAlignerService; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -11,10 +13,13 @@ import org.springframework.http.MediaType; import org.springframework.test.context.bean.override.mockito.MockitoBean; import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.MvcResult; import java.util.HashMap; import java.util.Map; +import static it.gov.pagopa.pu.debtpositions.util.faker.DebtPositionFaker.buildDebtPositionDTO; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -34,23 +39,26 @@ class DebtPositionControllerTest { @Test void whenFinalizeSyncStatusThenOk() throws Exception { Long id = 1L; - String newStatus = "UNPAID"; + InstallmentStatus newStatus = InstallmentStatus.TO_SYNC; - Map syncStatusDTO = new HashMap<>(); - IudSyncStatusUpdateDTO iudSyncStatusUpdateDTO = IudSyncStatusUpdateDTO.builder() + Map syncStatusDTO = new HashMap<>(); + IupdSyncStatusUpdateDTO iupdSyncStatusUpdateDTO = IupdSyncStatusUpdateDTO.builder() .newStatus(newStatus) .iupdPagopa("iupdPagoPa") .build(); - syncStatusDTO.put("iud", iudSyncStatusUpdateDTO); + syncStatusDTO.put("iud", iupdSyncStatusUpdateDTO); - Mockito.doNothing().when(service).finalizeSyncStatus(id, syncStatusDTO); + Mockito.when(service.finalizeSyncStatus(id, syncStatusDTO)).thenReturn(buildDebtPositionDTO()); - mockMvc.perform( + MvcResult result = mockMvc.perform( put("/debt-positions/1/finalize-sync-status") .contentType(MediaType.APPLICATION_JSON_VALUE) .content(objectMapper.writeValueAsString(syncStatusDTO))) .andExpect(status().isOk()) .andReturn(); + + DebtPositionDTO resultResponse = objectMapper.readValue(result.getResponse().getContentAsString(), DebtPositionDTO.class); + assertEquals(buildDebtPositionDTO(), resultResponse); } } diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/exception/DebtPositionExceptionHandlerTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/exception/DebtPositionExceptionHandlerTest.java index 888e168..b5805ba 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/exception/DebtPositionExceptionHandlerTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/exception/DebtPositionExceptionHandlerTest.java @@ -4,7 +4,6 @@ import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration; import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; @@ -21,7 +20,7 @@ import static org.mockito.Mockito.doThrow; -@ExtendWith({SpringExtension.class, MockitoExtension.class}) +@ExtendWith({SpringExtension.class}) @WebMvcTest(value = {DebtPositionExceptionHandlerTest.TestController.class}, excludeAutoConfiguration = SecurityAutoConfiguration.class) @ContextConfiguration(classes = { DebtPositionExceptionHandlerTest.TestController.class, diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapperTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapperTest.java index 3a5cbef..fb36844 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapperTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/DebtPositionMapperTest.java @@ -2,6 +2,7 @@ import it.gov.pagopa.pu.debtpositions.dto.Installment; import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionDTO; +import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionStatus; import it.gov.pagopa.pu.debtpositions.model.DebtPosition; import it.gov.pagopa.pu.debtpositions.model.InstallmentNoPII; import it.gov.pagopa.pu.debtpositions.model.PaymentOption; @@ -41,6 +42,7 @@ void setUp(){ @Test void givenValidDebtPositionDTO_whenMapToModel_thenReturnDebtPositionAndInstallmentMap() { DebtPosition debtPositionExpected = buildDebtPosition(); + debtPositionExpected.setStatus(DebtPositionStatus.UNPAID); DebtPositionDTO debtPositionDTO = buildDebtPositionDTO(); Map installmentMap = new HashMap<>(); diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapperTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapperTest.java index 5f681ab..048c60f 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapperTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/InstallmentMapperTest.java @@ -2,6 +2,7 @@ import it.gov.pagopa.pu.debtpositions.dto.Installment; import it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentDTO; +import it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentStatus; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -36,6 +37,7 @@ void setUp(){ @Test void givenValidInstallmentDTO_WhenMapToModel_ThenReturnInstallment() { Installment installmentExpected = buildInstallmentNoUpdate(); + installmentExpected.setStatus(InstallmentStatus.UNPAID); InstallmentDTO installmentDTO = buildInstallmentDTO(); Mockito.when(personMapperMock.mapToModel(buildPersonDTO())).thenReturn(buildPerson()); diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapperTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapperTest.java index 7375f24..27f827e 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapperTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/mapper/PaymentOptionMapperTest.java @@ -2,6 +2,7 @@ import it.gov.pagopa.pu.debtpositions.dto.Installment; import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionDTO; +import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus; import it.gov.pagopa.pu.debtpositions.model.InstallmentNoPII; import it.gov.pagopa.pu.debtpositions.model.PaymentOption; import org.junit.jupiter.api.BeforeEach; @@ -38,6 +39,7 @@ void setUp(){ @Test void givenValidPaymentOptionDTO_WhenMapToModel_ThenReturnPaymentOptionAndInstallmentMap() { PaymentOption paymentOptionExpected = buildPaymentOption(); + paymentOptionExpected.setStatus(PaymentOptionStatus.UNPAID); PaymentOptionDTO paymentOptionDTO = buildPaymentOptionDTO(); Mockito.when(installmentMapperMock.mapToModel(buildInstallmentDTO())).thenReturn(buildInstallment()); diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerServiceTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerServiceTest.java index 448c15b..5bfed30 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerServiceTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/DebtPositionHierarchyStatusAlignerServiceTest.java @@ -1,10 +1,7 @@ package it.gov.pagopa.pu.debtpositions.service.statusalign; -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.IudSyncStatusUpdateDTO; -import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus; -import it.gov.pagopa.pu.debtpositions.exception.custom.InvalidStatusException; +import it.gov.pagopa.pu.debtpositions.dto.generated.*; +import it.gov.pagopa.pu.debtpositions.mapper.DebtPositionMapper; import it.gov.pagopa.pu.debtpositions.model.DebtPosition; import it.gov.pagopa.pu.debtpositions.repository.DebtPositionRepository; import it.gov.pagopa.pu.debtpositions.repository.InstallmentNoPIIRepository; @@ -20,10 +17,13 @@ import java.util.HashMap; import java.util.Map; +import static it.gov.pagopa.pu.debtpositions.util.TestUtils.reflectionEqualsByName; import static it.gov.pagopa.pu.debtpositions.util.faker.DebtPositionFaker.buildDebtPosition; +import static it.gov.pagopa.pu.debtpositions.util.faker.DebtPositionFaker.buildDebtPositionDTO; import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.buildPaymentOption; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @ExtendWith(MockitoExtension.class) @@ -37,64 +37,90 @@ class DebtPositionHierarchyStatusAlignerServiceTest { private PaymentOptionInnerStatusAlignerService paymentOptionInnerStatusAlignerServiceMock; @Mock private DebtPositionInnerStatusAlignerService debtPositionInnerStatusAlignerServiceMock; + @Mock + private DebtPositionMapper debtPositionMapperMock; private DebtPositionHierarchyStatusAlignerService service; @BeforeEach void setUp() { - service = new DebtPositionHierarchyStatusAlignerServiceImpl(debtPositionRepositoryMock, installmentNoPIIRepositoryMock, paymentOptionInnerStatusAlignerServiceMock, debtPositionInnerStatusAlignerServiceMock); + service = new DebtPositionHierarchyStatusAlignerServiceImpl(debtPositionRepositoryMock, installmentNoPIIRepositoryMock, paymentOptionInnerStatusAlignerServiceMock, debtPositionInnerStatusAlignerServiceMock, debtPositionMapperMock); } @Test void givenFinalizeSyncStatusThenOk() { Long id = 1L; - String newStatus = "UNPAID"; + InstallmentStatus newStatus = InstallmentStatus.UNPAID; String iupdPagoPa = "iupdPagoPa"; DebtPosition debtPosition = buildDebtPosition(); Mockito.when(debtPositionRepositoryMock.findOneWithAllDataByDebtPositionId(id)).thenReturn(debtPosition); - Mockito.doNothing().when(installmentNoPIIRepositoryMock).updateStatusAndIupdPagopa(id, iupdPagoPa, InstallmentStatus.valueOf(newStatus)); + Mockito.doNothing().when(installmentNoPIIRepositoryMock).updateStatusAndIupdPagopa(id, iupdPagoPa, newStatus); Mockito.doNothing().when(paymentOptionInnerStatusAlignerServiceMock).updatePaymentOptionStatus(buildPaymentOption()); Mockito.doNothing().when(debtPositionInnerStatusAlignerServiceMock).updateDebtPositionStatus(debtPosition); + Mockito.when(debtPositionMapperMock.mapToDto(debtPosition)).thenReturn(buildDebtPositionDTO()); - Map syncStatusDTO = new HashMap<>(); - IudSyncStatusUpdateDTO iudSyncStatusUpdateDTO = IudSyncStatusUpdateDTO.builder() + Map syncStatusDTO = new HashMap<>(); + IupdSyncStatusUpdateDTO iupdSyncStatusUpdateDTO = IupdSyncStatusUpdateDTO.builder() .newStatus(newStatus) .iupdPagopa(iupdPagoPa) .build(); - syncStatusDTO.put("iud", iudSyncStatusUpdateDTO); - service.finalizeSyncStatus(id, syncStatusDTO); + syncStatusDTO.put("iud", iupdSyncStatusUpdateDTO); + DebtPositionDTO result = service.finalizeSyncStatus(id, syncStatusDTO); - verify(debtPositionRepositoryMock).findOneWithAllDataByDebtPositionId(id); - verify(installmentNoPIIRepositoryMock).updateStatusAndIupdPagopa(id, iupdPagoPa, InstallmentStatus.valueOf(newStatus)); - verify(paymentOptionInnerStatusAlignerServiceMock).updatePaymentOptionStatus(buildPaymentOption()); - verify(debtPositionInnerStatusAlignerServiceMock).updateDebtPositionStatus(debtPosition); + assertEquals(DebtPositionStatus.UNPAID, result.getStatus()); + assertEquals(PaymentOptionStatus.UNPAID, result.getPaymentOptions().getFirst().getStatus()); + assertEquals(InstallmentStatus.UNPAID, result.getPaymentOptions().getFirst().getInstallments().getFirst().getStatus()); + reflectionEqualsByName(buildDebtPositionDTO(), result); + } + + @Test + void givenFinalizeSyncStatusWhenIsNotSyncThenDoNotUpdateStatus() { + Long id = 1L; + InstallmentStatus newStatus = InstallmentStatus.UNPAID; + String iupdPagoPa = "iupdPagoPa"; + DebtPosition debtPosition = buildDebtPosition(); + debtPosition.getPaymentOptions().getFirst().getInstallments().getFirst().setStatus(InstallmentStatus.PAID); + + Mockito.when(debtPositionRepositoryMock.findOneWithAllDataByDebtPositionId(id)).thenReturn(debtPosition); + + Map syncStatusDTO = new HashMap<>(); + IupdSyncStatusUpdateDTO iupdSyncStatusUpdateDTO = IupdSyncStatusUpdateDTO.builder() + .newStatus(newStatus) + .iupdPagopa(iupdPagoPa) + .build(); - assertEquals(DebtPositionStatus.UNPAID, debtPosition.getStatus()); - assertEquals(PaymentOptionStatus.UNPAID, debtPosition.getPaymentOptions().getFirst().getStatus()); - assertEquals(InstallmentStatus.UNPAID, debtPosition.getPaymentOptions().getFirst().getInstallments().getFirst().getStatus()); + syncStatusDTO.put("iud", iupdSyncStatusUpdateDTO); + + DebtPositionDTO result = service.finalizeSyncStatus(id, syncStatusDTO); + + assertNull(result); + verify(debtPositionRepositoryMock).findOneWithAllDataByDebtPositionId(id); + verify(installmentNoPIIRepositoryMock, times(0)).updateStatusAndIupdPagopa(id, iupdPagoPa, newStatus); } @Test - void givenFinalizeSyncStatusWhenIllegalStatusThenThrowInvalidStatusException() { + void givenFinalizeSyncStatusWhenDoesNotHaveIudThenDoNotUpdateStatus() { Long id = 1L; - String newStatus = "newStatus"; + InstallmentStatus newStatus = InstallmentStatus.UNPAID; String iupdPagoPa = "iupdPagoPa"; DebtPosition debtPosition = buildDebtPosition(); Mockito.when(debtPositionRepositoryMock.findOneWithAllDataByDebtPositionId(id)).thenReturn(debtPosition); - Map syncStatusDTO = new HashMap<>(); - IudSyncStatusUpdateDTO iudSyncStatusUpdateDTO = IudSyncStatusUpdateDTO.builder() + Map syncStatusDTO = new HashMap<>(); + IupdSyncStatusUpdateDTO iupdSyncStatusUpdateDTO = IupdSyncStatusUpdateDTO.builder() .newStatus(newStatus) .iupdPagopa(iupdPagoPa) .build(); - syncStatusDTO.put("iud", iudSyncStatusUpdateDTO); + syncStatusDTO.put("fake-iud", iupdSyncStatusUpdateDTO); - Exception exception = assertThrows(InvalidStatusException.class, () -> service.finalizeSyncStatus(id, syncStatusDTO)); - assertEquals("Invalid status: newStatus", exception.getMessage()); + DebtPositionDTO result = service.finalizeSyncStatus(id, syncStatusDTO); + assertNull(result); + verify(debtPositionRepositoryMock).findOneWithAllDataByDebtPositionId(id); + verify(installmentNoPIIRepositoryMock, times(0)).updateStatusAndIupdPagopa(id, iupdPagoPa, newStatus); } } diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusCheckerTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusCheckerTest.java index a542170..afe185b 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusCheckerTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/debtposition/DebtPositionStatusCheckerTest.java @@ -3,30 +3,43 @@ import it.gov.pagopa.pu.debtpositions.dto.generated.DebtPositionStatus; import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus; import it.gov.pagopa.pu.debtpositions.exception.custom.InvalidStatusException; +import it.gov.pagopa.pu.debtpositions.model.DebtPosition; +import it.gov.pagopa.pu.debtpositions.model.PaymentOption; +import it.gov.pagopa.pu.debtpositions.repository.DebtPositionRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; import java.util.List; +import java.util.TreeSet; +import static it.gov.pagopa.pu.debtpositions.util.faker.DebtPositionFaker.buildDebtPosition; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +@ExtendWith(MockitoExtension.class) class DebtPositionStatusCheckerTest { + @Mock + private DebtPositionRepository debtPositionRepositoryMock; + private DebtPositionStatusChecker checker; @BeforeEach void setUp() { - checker = new DebtPositionStatusChecker(); + checker = new DebtPositionStatusChecker(debtPositionRepositoryMock); } /** * Test if the status is TO_SYNC when at least one PaymentOption has status TO_SYNC. */ @Test - void testDetermineDebtPositionStatus_ToSync() { + void testCalculateNewStatus_ToSync() { List paymentOptionStatusList = List.of(PaymentOptionStatus.TO_SYNC, PaymentOptionStatus.PAID); - DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + DebtPositionStatus result = checker.calculateNewStatus(paymentOptionStatusList); assertEquals(DebtPositionStatus.TO_SYNC, result); } @@ -34,9 +47,9 @@ void testDetermineDebtPositionStatus_ToSync() { * Test if the status is PARTIALLY_PAID when there is at least one PAID and one UNPAID paymentOption. */ @Test - void testDetermineDebtPositionStatus_PartiallyPaid() { + void testCalculateNewStatus_PartiallyPaid() { List paymentOptionStatusList = List.of(PaymentOptionStatus.PAID, PaymentOptionStatus.UNPAID); - DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + DebtPositionStatus result = checker.calculateNewStatus(paymentOptionStatusList); assertEquals(DebtPositionStatus.PARTIALLY_PAID, result); } @@ -46,7 +59,7 @@ void testDetermineDebtPositionStatus_PartiallyPaid() { @Test void testDeterminePaymentOptionStatus_PartiallyPaid2() { List paymentOptionStatusList = List.of(PaymentOptionStatus.PAID, PaymentOptionStatus.EXPIRED); - DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + DebtPositionStatus result = checker.calculateNewStatus(paymentOptionStatusList); assertEquals(DebtPositionStatus.PARTIALLY_PAID, result); } @@ -54,9 +67,9 @@ void testDeterminePaymentOptionStatus_PartiallyPaid2() { * Test if the status is UNPAID when all paymentOptions are UNPAID. */ @Test - void testDetermineDebtPositionStatus_Unpaid() { + void testCalculateNewStatus_Unpaid() { List paymentOptionStatusList = List.of(PaymentOptionStatus.UNPAID, PaymentOptionStatus.UNPAID); - DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + DebtPositionStatus result = checker.calculateNewStatus(paymentOptionStatusList); assertEquals(DebtPositionStatus.UNPAID, result); } @@ -66,7 +79,7 @@ void testDetermineDebtPositionStatus_Unpaid() { @Test void testDeterminePaymentOptionStatus_Unpaid2() { List paymentOptionStatusList = List.of(PaymentOptionStatus.UNPAID, PaymentOptionStatus.CANCELLED, PaymentOptionStatus.CANCELLED); - DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + DebtPositionStatus result = checker.calculateNewStatus(paymentOptionStatusList); assertEquals(DebtPositionStatus.UNPAID, result); } @@ -74,9 +87,9 @@ void testDeterminePaymentOptionStatus_Unpaid2() { * Test if the status is PAID when all paymentOptions are PAID. */ @Test - void testDetermineDebtPositionStatus_Paid() { + void testCalculateNewStatus_Paid() { List paymentOptionStatusList = List.of(PaymentOptionStatus.PAID, PaymentOptionStatus.PAID); - DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + DebtPositionStatus result = checker.calculateNewStatus(paymentOptionStatusList); assertEquals(DebtPositionStatus.PAID, result); } @@ -86,7 +99,7 @@ void testDetermineDebtPositionStatus_Paid() { @Test void testDeterminePaymentOptionStatus_Paid2() { List paymentOptionStatusList = List.of(PaymentOptionStatus.PAID, PaymentOptionStatus.CANCELLED); - DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + DebtPositionStatus result = checker.calculateNewStatus(paymentOptionStatusList); assertEquals(DebtPositionStatus.PAID, result); } @@ -94,9 +107,9 @@ void testDeterminePaymentOptionStatus_Paid2() { * Test if the status is REPORTED when all paymentOptions are CANCELLED, with at least one REPORTED. */ @Test - void testDetermineDebtPositionStatus_Reported() { + void testCalculateNewStatus_Reported() { List paymentOptionStatusList = List.of(PaymentOptionStatus.REPORTED, PaymentOptionStatus.CANCELLED); - DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + DebtPositionStatus result = checker.calculateNewStatus(paymentOptionStatusList); assertEquals(DebtPositionStatus.REPORTED, result); } @@ -106,7 +119,7 @@ void testDetermineDebtPositionStatus_Reported() { @Test void testDeterminePaymentOptionStatus_Reported2() { List paymentOptionStatusList = List.of(PaymentOptionStatus.REPORTED, PaymentOptionStatus.REPORTED); - DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + DebtPositionStatus result = checker.calculateNewStatus(paymentOptionStatusList); assertEquals(DebtPositionStatus.REPORTED, result); } @@ -114,9 +127,9 @@ void testDeterminePaymentOptionStatus_Reported2() { * Test if the status is INVALID when all paymentOptions are INVALID. */ @Test - void testDetermineDebtPositionStatus_Invalid() { + void testCalculateNewStatus_Invalid() { List paymentOptionStatusList = List.of(PaymentOptionStatus.INVALID, PaymentOptionStatus.INVALID); - DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + DebtPositionStatus result = checker.calculateNewStatus(paymentOptionStatusList); assertEquals(DebtPositionStatus.INVALID, result); } @@ -126,7 +139,7 @@ void testDetermineDebtPositionStatus_Invalid() { @Test void testDeterminePaymentOptionStatus_Invalid2() { List paymentOptionStatusList = List.of(PaymentOptionStatus.INVALID, PaymentOptionStatus.CANCELLED); - DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + DebtPositionStatus result = checker.calculateNewStatus(paymentOptionStatusList); assertEquals(DebtPositionStatus.INVALID, result); } @@ -134,9 +147,9 @@ void testDeterminePaymentOptionStatus_Invalid2() { * Test if the status is CANCELLED when all paymentOptions are CANCELLED. */ @Test - void testDetermineDebtPositionStatus_Cancelled() { + void testCalculateNewStatus_Cancelled() { List paymentOptionStatusList = List.of(PaymentOptionStatus.CANCELLED, PaymentOptionStatus.CANCELLED); - DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + DebtPositionStatus result = checker.calculateNewStatus(paymentOptionStatusList); assertEquals(DebtPositionStatus.CANCELLED, result); } @@ -144,9 +157,9 @@ void testDetermineDebtPositionStatus_Cancelled() { * Test if the status is EXPIRED when all paymentOptions are EXPIRED. */ @Test - void testDetermineDebtPositionStatus_Expired() { + void testCalculateNewStatus_Expired() { List paymentOptionStatusList = List.of(PaymentOptionStatus.EXPIRED, PaymentOptionStatus.EXPIRED); - DebtPositionStatus result = checker.determineDebtPositionStatus(paymentOptionStatusList); + DebtPositionStatus result = checker.calculateNewStatus(paymentOptionStatusList); assertEquals(DebtPositionStatus.EXPIRED, result); } @@ -154,10 +167,52 @@ void testDetermineDebtPositionStatus_Expired() { * Test if an exception is thrown when the list of paymentOptions is empty. */ @Test - void testDetermineDebtPositionStatus_InvalidStatus() { + void testCalculateNewStatus_InvalidStatus() { List paymentOptionStatusList = List.of(); - Exception exception = assertThrows(InvalidStatusException.class, () -> checker.determineDebtPositionStatus(paymentOptionStatusList)); + Exception exception = assertThrows(InvalidStatusException.class, () -> checker.calculateNewStatus(paymentOptionStatusList)); assertEquals("Unable to determine status for DebtPosition", exception.getMessage()); } + + @Test + void testGetChildStatuses() { + DebtPosition debtPosition = new DebtPosition(); + PaymentOption option1 = new PaymentOption(); + option1.setPaymentOptionId(1L); + option1.setStatus(PaymentOptionStatus.PAID); + + PaymentOption option2 = new PaymentOption(); + option2.setPaymentOptionId(2L); + option2.setStatus(PaymentOptionStatus.UNPAID); + + debtPosition.setPaymentOptions(new TreeSet<>(List.of(option1, option2))); + + List statuses = checker.getChildStatuses(debtPosition); + + assertEquals(2, statuses.size()); + assertEquals(PaymentOptionStatus.PAID, statuses.get(0)); + assertEquals(PaymentOptionStatus.UNPAID, statuses.get(1)); + } + + @Test + void testSetStatus() { + DebtPosition debtPosition = buildDebtPosition(); + DebtPositionStatus newStatus = DebtPositionStatus.PAID; + + checker.setStatus(debtPosition, newStatus); + + assertEquals(newStatus, debtPosition.getStatus()); + } + + @Test + void testStoreStatus() { + DebtPosition debtPosition = buildDebtPosition(); + DebtPositionStatus newStatus = DebtPositionStatus.PAID; + + Mockito.doNothing().when(debtPositionRepositoryMock).updateStatus(1L, newStatus); + + checker.storeStatus(debtPosition, newStatus); + + Mockito.verify(debtPositionRepositoryMock).updateStatus(1L, newStatus); + } } diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusCheckerTest.java b/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusCheckerTest.java index 34b51fc..38a5b52 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusCheckerTest.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/service/statusalign/paymentoption/PaymentOptionStatusCheckerTest.java @@ -3,30 +3,43 @@ import it.gov.pagopa.pu.debtpositions.dto.generated.InstallmentStatus; import it.gov.pagopa.pu.debtpositions.dto.generated.PaymentOptionStatus; import it.gov.pagopa.pu.debtpositions.exception.custom.InvalidStatusException; +import it.gov.pagopa.pu.debtpositions.model.InstallmentNoPII; +import it.gov.pagopa.pu.debtpositions.model.PaymentOption; +import it.gov.pagopa.pu.debtpositions.repository.PaymentOptionRepository; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; import java.util.List; +import java.util.TreeSet; +import static it.gov.pagopa.pu.debtpositions.util.faker.PaymentOptionFaker.buildPaymentOption; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; +@ExtendWith(MockitoExtension.class) class PaymentOptionStatusCheckerTest { + @Mock + private PaymentOptionRepository paymentOptionRepositoryMock; + private PaymentOptionStatusChecker checker; @BeforeEach void setUp() { - checker = new PaymentOptionStatusChecker(); + checker = new PaymentOptionStatusChecker(paymentOptionRepositoryMock); } /** * Test if the status is TO_SYNC when at least one Installment has status TO_SYNC. */ @Test - void testDeterminePaymentOptionStatus_ToSync() { + void testCalculateNewStatus_ToSync() { List installmentStatusList = List.of(InstallmentStatus.TO_SYNC, InstallmentStatus.PAID); - PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + PaymentOptionStatus result = checker.calculateNewStatus(installmentStatusList); assertEquals(PaymentOptionStatus.TO_SYNC, result); } @@ -34,9 +47,9 @@ void testDeterminePaymentOptionStatus_ToSync() { * Test if the status is PARTIALLY_PAID when there is at least one PAID and one UNPAID installment. */ @Test - void testDeterminePaymentOptionStatus_PartiallyPaid() { + void testCalculateNewStatus_PartiallyPaid() { List installmentStatusList = List.of(InstallmentStatus.PAID, InstallmentStatus.UNPAID); - PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + PaymentOptionStatus result = checker.calculateNewStatus(installmentStatusList); assertEquals(PaymentOptionStatus.PARTIALLY_PAID, result); } @@ -44,9 +57,9 @@ void testDeterminePaymentOptionStatus_PartiallyPaid() { * Test if the status is PARTIALLY_PAID when there is at least one PAID and one EXPIRED installment. */ @Test - void testDeterminePaymentOptionStatus_PartiallyPaid2() { + void testCalculateNewStatus_PartiallyPaid2() { List installmentStatusList = List.of(InstallmentStatus.PAID, InstallmentStatus.EXPIRED); - PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + PaymentOptionStatus result = checker.calculateNewStatus(installmentStatusList); assertEquals(PaymentOptionStatus.PARTIALLY_PAID, result); } @@ -54,9 +67,9 @@ void testDeterminePaymentOptionStatus_PartiallyPaid2() { * Test if the status is UNPAID when all installments are UNPAID. */ @Test - void testDeterminePaymentOptionStatus_Unpaid() { + void testCalculateNewStatus_Unpaid() { List installmentStatusList = List.of(InstallmentStatus.UNPAID, InstallmentStatus.UNPAID); - PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + PaymentOptionStatus result = checker.calculateNewStatus(installmentStatusList); assertEquals(PaymentOptionStatus.UNPAID, result); } @@ -64,9 +77,9 @@ void testDeterminePaymentOptionStatus_Unpaid() { * Test if the status is UNPAID when all installments are CANCELLED, with at least one UNPAID. */ @Test - void testDeterminePaymentOptionStatus_Unpaid2() { + void testCalculateNewStatus_Unpaid2() { List installmentStatusList = List.of(InstallmentStatus.UNPAID, InstallmentStatus.CANCELLED, InstallmentStatus.CANCELLED); - PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + PaymentOptionStatus result = checker.calculateNewStatus(installmentStatusList); assertEquals(PaymentOptionStatus.UNPAID, result); } @@ -74,9 +87,9 @@ void testDeterminePaymentOptionStatus_Unpaid2() { * Test if the status is PAID when all installments are PAID. */ @Test - void testDeterminePaymentOptionStatus_Paid() { + void testCalculateNewStatus_Paid() { List installmentStatusList = List.of(InstallmentStatus.PAID, InstallmentStatus.PAID); - PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + PaymentOptionStatus result = checker.calculateNewStatus(installmentStatusList); assertEquals(PaymentOptionStatus.PAID, result); } @@ -84,9 +97,9 @@ void testDeterminePaymentOptionStatus_Paid() { * Test if the status is PAID when all installments are CANCELLED, with at least one PAID. */ @Test - void testDeterminePaymentOptionStatus_Paid2() { + void testCalculateNewStatus_Paid2() { List installmentStatusList = List.of(InstallmentStatus.PAID, InstallmentStatus.CANCELLED); - PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + PaymentOptionStatus result = checker.calculateNewStatus(installmentStatusList); assertEquals(PaymentOptionStatus.PAID, result); } @@ -94,9 +107,9 @@ void testDeterminePaymentOptionStatus_Paid2() { * Test if the status is REPORTED when all installments are CANCELLED, with at least one REPORTED. */ @Test - void testDeterminePaymentOptionStatus_Reported() { + void testCalculateNewStatus_Reported() { List installmentStatusList = List.of(InstallmentStatus.REPORTED, InstallmentStatus.CANCELLED); - PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + PaymentOptionStatus result = checker.calculateNewStatus(installmentStatusList); assertEquals(PaymentOptionStatus.REPORTED, result); } @@ -104,9 +117,9 @@ void testDeterminePaymentOptionStatus_Reported() { * Test if the status is REPORTED when all installments are REPORTED. */ @Test - void testDeterminePaymentOptionStatus_Reported2() { + void testCalculateNewStatus_Reported2() { List installmentStatusList = List.of(InstallmentStatus.REPORTED, InstallmentStatus.REPORTED); - PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + PaymentOptionStatus result = checker.calculateNewStatus(installmentStatusList); assertEquals(PaymentOptionStatus.REPORTED, result); } @@ -114,9 +127,9 @@ void testDeterminePaymentOptionStatus_Reported2() { * Test if the status is INVALID when all installments are INVALID. */ @Test - void testDeterminePaymentOptionStatus_Invalid() { + void testCalculateNewStatus_Invalid() { List installmentStatusList = List.of(InstallmentStatus.INVALID, InstallmentStatus.INVALID); - PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + PaymentOptionStatus result = checker.calculateNewStatus(installmentStatusList); assertEquals(PaymentOptionStatus.INVALID, result); } @@ -124,9 +137,9 @@ void testDeterminePaymentOptionStatus_Invalid() { * Test if the status is INVALID when all installments are CANCELLED, with at least one INVALID. */ @Test - void testDeterminePaymentOptionStatus_Invalid2() { + void testCalculateNewStatus_Invalid2() { List installmentStatusList = List.of(InstallmentStatus.INVALID, InstallmentStatus.CANCELLED); - PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + PaymentOptionStatus result = checker.calculateNewStatus(installmentStatusList); assertEquals(PaymentOptionStatus.INVALID, result); } @@ -134,9 +147,9 @@ void testDeterminePaymentOptionStatus_Invalid2() { * Test if the status is CANCELLED when all installments are CANCELLED. */ @Test - void testDeterminePaymentOptionStatus_Cancelled() { + void testCalculateNewStatus_Cancelled() { List installmentStatusList = List.of(InstallmentStatus.CANCELLED, InstallmentStatus.CANCELLED); - PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + PaymentOptionStatus result = checker.calculateNewStatus(installmentStatusList); assertEquals(PaymentOptionStatus.CANCELLED, result); } @@ -144,9 +157,9 @@ void testDeterminePaymentOptionStatus_Cancelled() { * Test if the status is EXPIRED when all installments are EXPIRED. */ @Test - void testDeterminePaymentOptionStatus_Expired() { + void testCalculateNewStatus_Expired() { List installmentStatusList = List.of(InstallmentStatus.EXPIRED, InstallmentStatus.EXPIRED); - PaymentOptionStatus result = checker.determinePaymentOptionStatus(installmentStatusList); + PaymentOptionStatus result = checker.calculateNewStatus(installmentStatusList); assertEquals(PaymentOptionStatus.EXPIRED, result); } @@ -154,9 +167,51 @@ void testDeterminePaymentOptionStatus_Expired() { * Test if an exception is thrown when the list of installments is empty. */ @Test - void testDeterminePaymentOptionStatus_InvalidStatus() { + void testCalculateNewStatus_InvalidStatus() { List installmentStatusList = List.of(); - Exception exception = assertThrows(InvalidStatusException.class, () -> checker.determinePaymentOptionStatus(installmentStatusList)); + Exception exception = assertThrows(InvalidStatusException.class, () -> checker.calculateNewStatus(installmentStatusList)); assertEquals("Unable to determine status for PaymentOption", exception.getMessage()); } + + @Test + void testGetChildStatuses() { + PaymentOption paymentOption = new PaymentOption(); + InstallmentNoPII installmentNoPII1 = new InstallmentNoPII(); + installmentNoPII1.setInstallmentId(1L); + installmentNoPII1.setStatus(InstallmentStatus.PAID); + + InstallmentNoPII installmentNoPII2 = new InstallmentNoPII(); + installmentNoPII2.setInstallmentId(2L); + installmentNoPII2.setStatus(InstallmentStatus.UNPAID); + + paymentOption.setInstallments(new TreeSet<>(List.of(installmentNoPII1, installmentNoPII2))); + + List statuses = checker.getChildStatuses(paymentOption); + + assertEquals(2, statuses.size()); + assertEquals(InstallmentStatus.PAID, statuses.get(0)); + assertEquals(InstallmentStatus.UNPAID, statuses.get(1)); + } + + @Test + void testSetStatus() { + PaymentOption paymentOption = buildPaymentOption(); + PaymentOptionStatus newStatus = PaymentOptionStatus.PAID; + + checker.setStatus(paymentOption, newStatus); + + assertEquals(newStatus, paymentOption.getStatus()); + } + + @Test + void testStoreStatus() { + PaymentOption paymentOption = buildPaymentOption(); + PaymentOptionStatus newStatus = PaymentOptionStatus.PAID; + + Mockito.doNothing().when(paymentOptionRepositoryMock).updateStatus(1L, newStatus); + + checker.storeStatus(paymentOption, newStatus); + + Mockito.verify(paymentOptionRepositoryMock).updateStatus(1L, newStatus); + } } diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/DebtPositionFaker.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/DebtPositionFaker.java index 9260711..82d6dfe 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/DebtPositionFaker.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/DebtPositionFaker.java @@ -21,7 +21,7 @@ public static DebtPosition buildDebtPosition() { debtPosition.setDebtPositionId(1L); debtPosition.setIupdOrg("IUPD_ORG"); debtPosition.setDescription("Test Description"); - debtPosition.setStatus(DebtPositionStatus.UNPAID); + debtPosition.setStatus(DebtPositionStatus.TO_SYNC); debtPosition.setIngestionFlowFileId(1001L); debtPosition.setIngestionFlowFileLineNumber(10L); debtPosition.setOrganizationId(500L); diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java index 3c8540d..23e2ef6 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/InstallmentFaker.java @@ -111,7 +111,7 @@ public static InstallmentDTO buildInstallmentDTO() { return InstallmentDTO.builder() .installmentId(1L) .paymentOptionId(1L) - .status(InstallmentStatus.TO_SYNC) + .status(InstallmentStatus.UNPAID) .iupdPagopa("iupdPagoPa") .iud("iud") .iuv("iuv") diff --git a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PaymentOptionFaker.java b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PaymentOptionFaker.java index 916b84e..109e7ec 100644 --- a/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PaymentOptionFaker.java +++ b/src/test/java/it/gov/pagopa/pu/debtpositions/util/faker/PaymentOptionFaker.java @@ -22,7 +22,7 @@ public static PaymentOption buildPaymentOption() { paymentOption.setDebtPositionId(1L); paymentOption.setTotalAmountCents(2000L); paymentOption.setDueDate(DATE); - paymentOption.setStatus(PaymentOptionStatus.UNPAID); + paymentOption.setStatus(PaymentOptionStatus.TO_SYNC); paymentOption.setMultiDebtor(true); paymentOption.setDescription("Payment description"); paymentOption.setPaymentOptionType(PaymentOptionType.SINGLE_INSTALLMENT);