From 5ea951a38edd21c4438db6efec6c19db3c6bd0f6 Mon Sep 17 00:00:00 2001 From: Javier Polo Date: Mon, 2 May 2022 16:43:04 +0200 Subject: [PATCH] Release 4.9.0 --- build.gradle | 6 +- gradle.properties | 2 +- .../InfrastructureConnectorApplication.java | 9 +- .../infrastructure/batchjob/BatchJob.java | 10 + .../batchjob/BatchJobFailedItemId.java | 8 +- .../HMCHyperwalletAPIException.java | 28 ++ .../exceptions/HMCMiraklAPIException.java | 28 ++ .../service/TokenSynchronizationService.java | 17 + .../HMCHyperwalletAPIExceptionTest.java | 55 +++ .../exceptions/HMCMiraklAPIExceptionTest.java | 51 +++ .../InvoicesSpringContextConfiguration.java | 9 +- .../CreditNotesExtractBatchJob.java | 8 +- .../invoices/InvoicesExtractBatchJob.java | 8 +- .../service/hmc/InvoiceProcessService.java | 4 +- .../hmc/impl/InvoiceProcessServiceImpl.java | 7 +- .../hmc/impl/InvoiceProcessServiceMock.java | 6 +- .../HyperWalletPaymentExtractService.java | 8 +- .../HyperWalletPaymentExtractServiceImpl.java | 72 +++- ...erWalletPaymentExtractServiceImplTest.java | 88 ++++- ...tificationsSpringContextConfiguration.java | 9 +- ...bstractDocumentsBatchJobItemProcessor.java | 70 ++++ ...sStakeholdersDocumentsExtractBatchJob.java | 35 ++ ...keholdersDocumentsExtractBatchJobItem.java | 38 ++ ...DocumentsExtractBatchJobItemExtractor.java | 41 ++ ...DocumentsExtractBatchJobItemProcessor.java | 48 +++ .../SellersDocumentsExtractBatchJob.java | 35 ++ .../SellersDocumentsExtractBatchJobItem.java | 36 ++ ...DocumentsExtractBatchJobItemExtractor.java | 39 ++ ...DocumentsExtractBatchJobItemProcessor.java | 48 +++ .../paypal/kyc/jobs/DocumentsExtractJob.java | 48 +-- ...CDocumentBusinessStakeHolderInfoModel.java | 7 +- .../kyc/model/KYCDocumentInfoModel.java | 15 +- .../kyc/model/KYCDocumentSellerInfoModel.java | 6 +- .../kyc/service/DocumentsExtractService.java | 39 -- .../kyc/service/KYCReadyForReviewService.java | 4 +- ...lletBusinessStakeholderExtractService.java | 11 +- .../HyperwalletDocumentUploadService.java | 22 ++ .../HyperwalletSellerExtractService.java | 13 +- ...ractHyperwalletDocumentExtractService.java | 53 +++ ...BusinessStakeholderExtractServiceImpl.java | 134 +------ ...nessStakeholderExtractServiceMockImpl.java | 90 +---- .../HyperwalletDocumentUploadServiceImpl.java | 96 +++++ ...erwalletDocumentUploadServiceMockImpl.java | 88 +++++ .../HyperwalletSellerExtractServiceImpl.java | 100 +---- ...perwalletSellerExtractServiceMockImpl.java | 78 +--- ...essStakeholderDocumentsExtractService.java | 14 +- .../MiraklSellerDocumentsExtractService.java | 12 +- ...tractMiraklDocumentExtractServiceImpl.java | 16 +- ...takeholderDocumentsExtractServiceImpl.java | 203 +++++----- ...raklSellerDocumentsExtractServiceImpl.java | 146 ++++--- .../impl/DocumentsExtractServiceImpl.java | 97 ----- .../impl/KYCReadyForReviewServiceImpl.java | 68 +--- .../KYCReadyForReviewServiceMockImpl.java | 17 +- ...mentsExtractBatchJobItemExtractorTest.java | 47 +++ ...mentsExtractBatchJobItemProcessorTest.java | 110 ++++++ ...ldersDocumentsExtractBatchJobItemTest.java | 44 +++ ...keholdersDocumentsExtractBatchJobTest.java | 44 +++ ...mentsExtractBatchJobItemExtractorTest.java | 44 +++ ...mentsExtractBatchJobItemProcessorTest.java | 97 +++++ ...llersDocumentsExtractBatchJobItemTest.java | 38 ++ .../SellersDocumentsExtractBatchJobTest.java | 44 +++ .../kyc/jobs/DocumentsExtractJobTest.java | 111 +----- ...nessStakeholderExtractServiceImplTest.java | 356 +----------------- ...StakeholderExtractServiceMockImplTest.java | 118 ------ ...erwalletDocumentUploadServiceImplTest.java | 176 +++++++++ ...lletDocumentUploadServiceMockImplTest.java | 116 ++++++ ...perwalletSellerExtractServiceImplTest.java | 177 +-------- ...alletSellerExtractServiceMockImplTest.java | 101 ----- ...tMiraklDocumentExtractServiceImplTest.java | 6 +- ...holderDocumentsExtractServiceImplTest.java | 98 ++--- ...SellerDocumentsExtractServiceImplTest.java | 35 +- .../impl/DocumentsExtractServiceImplTest.java | 128 ------- .../KYCReadyForReviewServiceImplTest.java | 41 +- .../KYCReadyForReviewServiceMockImplTest.java | 14 +- ...tificationsSpringContextConfiguration.java | 9 +- .../ReportsSpringContextConfiguration.java | 9 +- .../SellersSpringContextConfiguration.java | 9 +- .../model/ABABankAccountModel.java | 25 ++ .../model/BankAccountModel.java | 80 +++- .../model/CanadianBankAccountModel.java | 25 ++ .../model/IBANBankAccountModel.java | 24 ++ .../model/UKBankAccountModel.java | 24 ++ ...ccountTokenSynchronizationServiceImpl.java | 147 ++++++++ ...yperwalletBankAccountRetryApiStrategy.java | 33 +- ...BankAccountServiceStrategyBankAccount.java | 6 +- ...BankAccountServiceStrategyBankAccount.java | 6 +- .../BankAccountExtractBatchJob.java | 8 +- ...nkAccountExtractBatchJobItemProcessor.java | 13 +- ...kAccountExtractBatchJobItemsExtractor.java | 8 +- .../BusinessStakeholdersExtractBatchJob.java | 7 +- .../IndividualSellersExtractBatchJob.java | 9 +- ...alSellersExtractBatchJobItemProcessor.java | 12 +- .../ProfessionalSellersExtractBatchJob.java | 7 +- ...alSellersExtractBatchJobItemProcessor.java | 12 +- .../impl/MiraklSellersExtractServiceImpl.java | 9 +- ...ellersTokenSynchronizationServiceImpl.java | 108 ++++++ ...ractHyperwalletSellerRetryApiStrategy.java | 82 ---- ...tractHyperwalletSellerServiceStrategy.java | 59 +++ ...yperWalletCreateSellerServiceStrategy.java | 53 ++- ...yperWalletUpdateSellerServiceStrategy.java | 39 +- ...yperWalletUserServiceStrategyExecutor.java | 10 +- .../AbstractHyperwalletRetryAPIStrategy.java | 36 -- .../model/ABABankAccountModelTest.java | 64 ++++ .../model/BankAccountModelTest.java | 37 +- .../model/CanadianBankAccountModelTest.java | 65 ++++ .../model/IBANBankAccountModelTest.java | 63 ++++ .../model/UKBankAccountModelTest.java | 64 ++++ ...ntTokenSynchronizationServiceImplTest.java | 146 +++++++ ...walletBankAccountRetryApiStrategyTest.java | 31 +- ...countExtractBatchJobItemProcessorTest.java | 12 +- ...ountExtractBatchJobItemsExtractorTest.java | 6 +- ...llersExtractBatchJobItemProcessorTest.java | 33 +- ...llersExtractBatchJobItemProcessorTest.java | 37 +- ...rsTokenSynchronizationServiceImplTest.java | 184 +++++++++ ...HyperwalletSellerRetryApiStrategyTest.java | 117 ------ ...tHyperwalletSellerServiceStrategyTest.java | 75 ++++ ...WalletCreateSellerServiceStrategyTest.java | 136 +++++-- ...WalletUpdateSellerServiceStrategyTest.java | 77 ++-- ...UserServiceStrategyExecutorSingleTest.java | 5 +- .../HyperwalletSellerServiceStrategyTest.java | 48 +++ ...stractHyperwalletRetryAPIStrategyTest.java | 62 --- 121 files changed, 3749 insertions(+), 2527 deletions(-) create mode 100644 infrastructure/src/main/java/com/paypal/infrastructure/batchjob/BatchJob.java create mode 100644 infrastructure/src/main/java/com/paypal/infrastructure/exceptions/HMCHyperwalletAPIException.java create mode 100644 infrastructure/src/main/java/com/paypal/infrastructure/exceptions/HMCMiraklAPIException.java create mode 100644 infrastructure/src/main/java/com/paypal/infrastructure/service/TokenSynchronizationService.java create mode 100644 infrastructure/src/test/java/com/paypal/infrastructure/exceptions/HMCHyperwalletAPIExceptionTest.java create mode 100644 infrastructure/src/test/java/com/paypal/infrastructure/exceptions/HMCMiraklAPIExceptionTest.java create mode 100644 kyc/src/main/java/com/paypal/kyc/batchjobs/AbstractDocumentsBatchJobItemProcessor.java create mode 100644 kyc/src/main/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJob.java create mode 100644 kyc/src/main/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobItem.java create mode 100644 kyc/src/main/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobItemExtractor.java create mode 100644 kyc/src/main/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobItemProcessor.java create mode 100644 kyc/src/main/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJob.java create mode 100644 kyc/src/main/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItem.java create mode 100644 kyc/src/main/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItemExtractor.java create mode 100644 kyc/src/main/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItemProcessor.java delete mode 100644 kyc/src/main/java/com/paypal/kyc/service/DocumentsExtractService.java create mode 100644 kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/HyperwalletDocumentUploadService.java create mode 100644 kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/AbstractHyperwalletDocumentExtractService.java create mode 100644 kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletDocumentUploadServiceImpl.java create mode 100644 kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletDocumentUploadServiceMockImpl.java delete mode 100644 kyc/src/main/java/com/paypal/kyc/service/impl/DocumentsExtractServiceImpl.java create mode 100644 kyc/src/test/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobItemExtractorTest.java create mode 100644 kyc/src/test/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobItemProcessorTest.java create mode 100644 kyc/src/test/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobItemTest.java create mode 100644 kyc/src/test/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobTest.java create mode 100644 kyc/src/test/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItemExtractorTest.java create mode 100644 kyc/src/test/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItemProcessorTest.java create mode 100644 kyc/src/test/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItemTest.java create mode 100644 kyc/src/test/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobTest.java delete mode 100644 kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletBusinessStakeholderExtractServiceMockImplTest.java create mode 100644 kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletDocumentUploadServiceImplTest.java create mode 100644 kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletDocumentUploadServiceMockImplTest.java delete mode 100644 kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletSellerExtractServiceMockImplTest.java delete mode 100644 kyc/src/test/java/com/paypal/kyc/service/impl/DocumentsExtractServiceImplTest.java create mode 100644 sellers/src/main/java/com/paypal/sellers/bankaccountextract/service/impl/BankAccountTokenSynchronizationServiceImpl.java create mode 100644 sellers/src/main/java/com/paypal/sellers/sellersextract/service/impl/SellersTokenSynchronizationServiceImpl.java delete mode 100644 sellers/src/main/java/com/paypal/sellers/sellersextract/service/strategies/AbstractHyperwalletSellerRetryApiStrategy.java create mode 100644 sellers/src/main/java/com/paypal/sellers/sellersextract/service/strategies/AbstractHyperwalletSellerServiceStrategy.java delete mode 100644 sellers/src/main/java/com/paypal/sellers/service/AbstractHyperwalletRetryAPIStrategy.java create mode 100644 sellers/src/test/java/com/paypal/sellers/bankaccountextract/service/impl/BankAccountTokenSynchronizationServiceImplTest.java create mode 100644 sellers/src/test/java/com/paypal/sellers/sellersextract/service/impl/SellersTokenSynchronizationServiceImplTest.java delete mode 100644 sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/AbstractHyperwalletSellerRetryApiStrategyTest.java create mode 100644 sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/AbstractHyperwalletSellerServiceStrategyTest.java create mode 100644 sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/HyperwalletSellerServiceStrategyTest.java delete mode 100644 sellers/src/test/java/com/paypal/sellers/service/AbstractHyperwalletRetryAPIStrategyTest.java diff --git a/build.gradle b/build.gradle index 7e2bcf39..de75e857 100644 --- a/build.gradle +++ b/build.gradle @@ -35,7 +35,6 @@ subprojects { apply plugin: 'java-library' apply plugin: 'java' apply plugin: 'io.spring.javaformat' - apply plugin: 'info.solidsoft.pitest' apply plugin: 'jacoco' java { @@ -43,10 +42,7 @@ subprojects { languageVersion = JavaLanguageVersion.of(15) } } - - pitest { - junit5PluginVersion = '0.12' - } + ext { set('springCloudVersion', "Hoxton.SR8") diff --git a/gradle.properties b/gradle.properties index a5476df5..1b10490f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,5 +1,5 @@ springBoot = 2.6.6 dependencyManagement = 1.0.11.RELEASE -projectVersion = 4.8.0 +projectVersion = 4.9.0 paypalHyperwalletDockerRepository = hyperwallet-mirakl-connector org.gradle.jvmargs = -XX:PermSize=1024M -XX:MaxPermSize=1024M diff --git a/infrastructure/src/main/java/com/paypal/infrastructure/InfrastructureConnectorApplication.java b/infrastructure/src/main/java/com/paypal/infrastructure/InfrastructureConnectorApplication.java index 2efabf91..cc6458af 100644 --- a/infrastructure/src/main/java/com/paypal/infrastructure/InfrastructureConnectorApplication.java +++ b/infrastructure/src/main/java/com/paypal/infrastructure/InfrastructureConnectorApplication.java @@ -1,15 +1,10 @@ package com.paypal.infrastructure; import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; @Slf4j -@SpringBootApplication +@ComponentScan public class InfrastructureConnectorApplication { - public static void main(final String[] args) { - SpringApplication.run(InfrastructureConnectorApplication.class, args); - } - } diff --git a/infrastructure/src/main/java/com/paypal/infrastructure/batchjob/BatchJob.java b/infrastructure/src/main/java/com/paypal/infrastructure/batchjob/BatchJob.java new file mode 100644 index 00000000..1ecc4891 --- /dev/null +++ b/infrastructure/src/main/java/com/paypal/infrastructure/batchjob/BatchJob.java @@ -0,0 +1,10 @@ +package com.paypal.infrastructure.batchjob; + +import org.quartz.Job; + +/** + * Marker interface for Batch Jobs + */ +public interface BatchJob extends Job { + +} diff --git a/infrastructure/src/main/java/com/paypal/infrastructure/batchjob/BatchJobFailedItemId.java b/infrastructure/src/main/java/com/paypal/infrastructure/batchjob/BatchJobFailedItemId.java index 7627455f..47719c11 100644 --- a/infrastructure/src/main/java/com/paypal/infrastructure/batchjob/BatchJobFailedItemId.java +++ b/infrastructure/src/main/java/com/paypal/infrastructure/batchjob/BatchJobFailedItemId.java @@ -1,6 +1,8 @@ package com.paypal.infrastructure.batchjob; +import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; import java.io.Serializable; @@ -8,10 +10,12 @@ * Data class for item id and type. */ @Data +@NoArgsConstructor +@AllArgsConstructor public class BatchJobFailedItemId implements Serializable { - private final String id; + private String id; - private final String type; + private String type; } diff --git a/infrastructure/src/main/java/com/paypal/infrastructure/exceptions/HMCHyperwalletAPIException.java b/infrastructure/src/main/java/com/paypal/infrastructure/exceptions/HMCHyperwalletAPIException.java new file mode 100644 index 00000000..f7d5bc07 --- /dev/null +++ b/infrastructure/src/main/java/com/paypal/infrastructure/exceptions/HMCHyperwalletAPIException.java @@ -0,0 +1,28 @@ +package com.paypal.infrastructure.exceptions; + +import com.hyperwallet.clientsdk.HyperwalletException; + +/** + * Base exception for all Hyperwallet Connector exceptions. + */ +public class HMCHyperwalletAPIException extends HMCException { + + protected static final String DEFAULT_MSG = "An error has occurred while invoking Hyperwallet API"; + + private final HyperwalletException hyperwalletException; + + public HMCHyperwalletAPIException(final String message, final HyperwalletException e) { + super(message, e); + hyperwalletException = e; + } + + public HMCHyperwalletAPIException(HyperwalletException e) { + super(DEFAULT_MSG, e); + hyperwalletException = e; + } + + public HyperwalletException getHyperwalletException() { + return hyperwalletException; + } + +} diff --git a/infrastructure/src/main/java/com/paypal/infrastructure/exceptions/HMCMiraklAPIException.java b/infrastructure/src/main/java/com/paypal/infrastructure/exceptions/HMCMiraklAPIException.java new file mode 100644 index 00000000..047cde32 --- /dev/null +++ b/infrastructure/src/main/java/com/paypal/infrastructure/exceptions/HMCMiraklAPIException.java @@ -0,0 +1,28 @@ +package com.paypal.infrastructure.exceptions; + +import com.mirakl.client.core.exception.MiraklException; + +/** + * Base exception for all Mirakl Connector exceptions. + */ +public class HMCMiraklAPIException extends HMCException { + + protected static final String DEFAULT_MSG = "An error has occurred while invoking Mirakl API"; + + private final MiraklException miraklException; + + public HMCMiraklAPIException(final String message, final MiraklException e) { + super(message, e); + miraklException = e; + } + + public HMCMiraklAPIException(MiraklException e) { + super(DEFAULT_MSG, e); + miraklException = e; + } + + public MiraklException getMiraklException() { + return miraklException; + } + +} diff --git a/infrastructure/src/main/java/com/paypal/infrastructure/service/TokenSynchronizationService.java b/infrastructure/src/main/java/com/paypal/infrastructure/service/TokenSynchronizationService.java new file mode 100644 index 00000000..92f56e81 --- /dev/null +++ b/infrastructure/src/main/java/com/paypal/infrastructure/service/TokenSynchronizationService.java @@ -0,0 +1,17 @@ +package com.paypal.infrastructure.service; + +/** + * Service for ensure the tokens in hypewallet and mirakl ar in sync + * + * @param + */ +public interface TokenSynchronizationService { + + /** + * Synchronize the tokens in hypewallet and mirakl for a specific item + * @param model that contains the item to synchronize + * @return the updated model item with the token in case there was a synchronization + */ + T synchronizeToken(T model); + +} diff --git a/infrastructure/src/test/java/com/paypal/infrastructure/exceptions/HMCHyperwalletAPIExceptionTest.java b/infrastructure/src/test/java/com/paypal/infrastructure/exceptions/HMCHyperwalletAPIExceptionTest.java new file mode 100644 index 00000000..75d0515a --- /dev/null +++ b/infrastructure/src/test/java/com/paypal/infrastructure/exceptions/HMCHyperwalletAPIExceptionTest.java @@ -0,0 +1,55 @@ +package com.paypal.infrastructure.exceptions; + +import com.hyperwallet.clientsdk.HyperwalletException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static com.paypal.infrastructure.exceptions.HMCHyperwalletAPIException.DEFAULT_MSG; +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(MockitoExtension.class) +class HMCHyperwalletAPIExceptionTest { + + private static final String HMC_HYPERWALLET_EXCEPTION_MESSAGE = "HMC Mirakl exception message"; + + private static final String HYPERWALLET_EXCEPTION_FIELD = "hyperwalletException"; + + private static final String DETAIL_MESSAGE_FIELD = "detailMessage"; + + @Mock + private HyperwalletException hyperwalletExceptionMock; + + @Test + void hMCHyperwalletAPIException_ShouldPopulateMessageAndException() { + + final HMCHyperwalletAPIException hmcHyperwalletAPIException = new HMCHyperwalletAPIException( + HMC_HYPERWALLET_EXCEPTION_MESSAGE, hyperwalletExceptionMock); + + assertThat(hmcHyperwalletAPIException) + .hasFieldOrPropertyWithValue(HYPERWALLET_EXCEPTION_FIELD, hyperwalletExceptionMock) + .hasFieldOrPropertyWithValue(DETAIL_MESSAGE_FIELD, HMC_HYPERWALLET_EXCEPTION_MESSAGE); + } + + @Test + void hMCHyperwalletAPIException_ShouldPopulateDefaultMessageAndException() { + + final HMCHyperwalletAPIException hmcHyperwalletAPIException = new HMCHyperwalletAPIException( + hyperwalletExceptionMock); + + assertThat(hmcHyperwalletAPIException) + .hasFieldOrPropertyWithValue(HYPERWALLET_EXCEPTION_FIELD, hyperwalletExceptionMock) + .hasFieldOrPropertyWithValue(DETAIL_MESSAGE_FIELD, DEFAULT_MSG); + } + + @Test + void hMCHyperwalletAPIException_ShouldReturnException() { + + final HMCHyperwalletAPIException hmcHyperwalletAPIException = new HMCHyperwalletAPIException( + hyperwalletExceptionMock); + + assertThat(hmcHyperwalletAPIException.getHyperwalletException()).isEqualTo(hyperwalletExceptionMock); + } + +} diff --git a/infrastructure/src/test/java/com/paypal/infrastructure/exceptions/HMCMiraklAPIExceptionTest.java b/infrastructure/src/test/java/com/paypal/infrastructure/exceptions/HMCMiraklAPIExceptionTest.java new file mode 100644 index 00000000..a8887f83 --- /dev/null +++ b/infrastructure/src/test/java/com/paypal/infrastructure/exceptions/HMCMiraklAPIExceptionTest.java @@ -0,0 +1,51 @@ +package com.paypal.infrastructure.exceptions; + +import com.mirakl.client.core.exception.MiraklException; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static com.paypal.infrastructure.exceptions.HMCMiraklAPIException.DEFAULT_MSG; +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(MockitoExtension.class) +class HMCMiraklAPIExceptionTest { + + private static final String HMC_MIRAKL_EXCEPTION_MESSAGE = "HMC Mirakl exception message"; + + private static final String MIRAKL_EXCEPTION_FIELD = "miraklException"; + + private static final String DETAIL_MESSAGE_FIELD = "detailMessage"; + + @Mock + private MiraklException miraklExceptionMock; + + @Test + void hMCMiraklAPIException_ShouldPopulateMessageAndException() { + + final HMCMiraklAPIException hmcMiraklAPIException = new HMCMiraklAPIException(HMC_MIRAKL_EXCEPTION_MESSAGE, + miraklExceptionMock); + + assertThat(hmcMiraklAPIException).hasFieldOrPropertyWithValue(MIRAKL_EXCEPTION_FIELD, miraklExceptionMock) + .hasFieldOrPropertyWithValue(DETAIL_MESSAGE_FIELD, HMC_MIRAKL_EXCEPTION_MESSAGE); + } + + @Test + void hMCMiraklAPIException_ShouldPopulateDefaultMessageAndException() { + + final HMCMiraklAPIException hmcMiraklAPIException = new HMCMiraklAPIException(miraklExceptionMock); + + assertThat(hmcMiraklAPIException).hasFieldOrPropertyWithValue(MIRAKL_EXCEPTION_FIELD, miraklExceptionMock) + .hasFieldOrPropertyWithValue(DETAIL_MESSAGE_FIELD, DEFAULT_MSG); + } + + @Test + void hMCMiraklAPIException_ShouldReturnException() { + + final HMCMiraklAPIException hmcMiraklAPIException = new HMCMiraklAPIException(miraklExceptionMock); + + assertThat(hmcMiraklAPIException.getMiraklException()).isEqualTo(miraklExceptionMock); + } + +} diff --git a/invoices/src/main/java/com/paypal/invoices/InvoicesSpringContextConfiguration.java b/invoices/src/main/java/com/paypal/invoices/InvoicesSpringContextConfiguration.java index d2f24954..8bdfabf6 100644 --- a/invoices/src/main/java/com/paypal/invoices/InvoicesSpringContextConfiguration.java +++ b/invoices/src/main/java/com/paypal/invoices/InvoicesSpringContextConfiguration.java @@ -3,18 +3,13 @@ import com.paypal.infrastructure.InfrastructureConnectorApplication; import com.paypal.invoices.infraestructure.configuration.InvoicesHyperwalletApiConfig; import com.paypal.invoices.infraestructure.configuration.InvoicesMiraklApiConfig; -import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.ComponentScan; -@SpringBootApplication +@ComponentScan @EnableConfigurationProperties({ InvoicesMiraklApiConfig.class, InvoicesHyperwalletApiConfig.class }) @ImportAutoConfiguration({ InfrastructureConnectorApplication.class }) public class InvoicesSpringContextConfiguration { - public static void main(final String[] args) { - SpringApplication.run(InvoicesSpringContextConfiguration.class, args); - } - } diff --git a/invoices/src/main/java/com/paypal/invoices/batchjobs/creditnotes/CreditNotesExtractBatchJob.java b/invoices/src/main/java/com/paypal/invoices/batchjobs/creditnotes/CreditNotesExtractBatchJob.java index 60dc8532..ab2fa368 100644 --- a/invoices/src/main/java/com/paypal/invoices/batchjobs/creditnotes/CreditNotesExtractBatchJob.java +++ b/invoices/src/main/java/com/paypal/invoices/batchjobs/creditnotes/CreditNotesExtractBatchJob.java @@ -1,9 +1,6 @@ package com.paypal.invoices.batchjobs.creditnotes; -import com.paypal.infrastructure.batchjob.AbstractBatchJob; -import com.paypal.infrastructure.batchjob.BatchJobContext; -import com.paypal.infrastructure.batchjob.BatchJobItemProcessor; -import com.paypal.infrastructure.batchjob.BatchJobItemsExtractor; +import com.paypal.infrastructure.batchjob.*; import org.springframework.stereotype.Service; /** @@ -11,7 +8,8 @@ * HyperWallet. */ @Service -public class CreditNotesExtractBatchJob extends AbstractBatchJob { +public class CreditNotesExtractBatchJob extends AbstractBatchJob + implements BatchJob { private final CreditNotesExtractBatchJobItemsExtractor creditNotesExtractBatchJobItemsExtractor; diff --git a/invoices/src/main/java/com/paypal/invoices/batchjobs/invoices/InvoicesExtractBatchJob.java b/invoices/src/main/java/com/paypal/invoices/batchjobs/invoices/InvoicesExtractBatchJob.java index f245c29d..4b993e11 100644 --- a/invoices/src/main/java/com/paypal/invoices/batchjobs/invoices/InvoicesExtractBatchJob.java +++ b/invoices/src/main/java/com/paypal/invoices/batchjobs/invoices/InvoicesExtractBatchJob.java @@ -1,9 +1,6 @@ package com.paypal.invoices.batchjobs.invoices; -import com.paypal.infrastructure.batchjob.AbstractBatchJob; -import com.paypal.infrastructure.batchjob.BatchJobContext; -import com.paypal.infrastructure.batchjob.BatchJobItemProcessor; -import com.paypal.infrastructure.batchjob.BatchJobItemsExtractor; +import com.paypal.infrastructure.batchjob.*; import org.springframework.stereotype.Service; /** @@ -11,7 +8,8 @@ * HyperWallet. */ @Service -public class InvoicesExtractBatchJob extends AbstractBatchJob { +public class InvoicesExtractBatchJob extends AbstractBatchJob + implements BatchJob { private final InvoicesExtractBatchJobItemsExtractor invoicesExtractBatchJobItemsExtractor; diff --git a/invoices/src/main/java/com/paypal/invoices/invoicesextract/service/hmc/InvoiceProcessService.java b/invoices/src/main/java/com/paypal/invoices/invoicesextract/service/hmc/InvoiceProcessService.java index 9efa7d17..0498a16f 100644 --- a/invoices/src/main/java/com/paypal/invoices/invoicesextract/service/hmc/InvoiceProcessService.java +++ b/invoices/src/main/java/com/paypal/invoices/invoicesextract/service/hmc/InvoiceProcessService.java @@ -1,6 +1,5 @@ package com.paypal.invoices.invoicesextract.service.hmc; -import com.hyperwallet.clientsdk.model.HyperwalletPayment; import com.paypal.invoices.invoicesextract.model.InvoiceModel; /** @@ -11,8 +10,7 @@ public interface InvoiceProcessService { /** * Execute pay invoice operator in HW for the given invoice. * @param invoice a {@link InvoiceModel}. - * @return a {@link HyperwalletPayment}. */ - HyperwalletPayment payOperator(final InvoiceModel invoice); + void payOperator(final InvoiceModel invoice); } diff --git a/invoices/src/main/java/com/paypal/invoices/invoicesextract/service/hmc/impl/InvoiceProcessServiceImpl.java b/invoices/src/main/java/com/paypal/invoices/invoicesextract/service/hmc/impl/InvoiceProcessServiceImpl.java index 8c83c4b0..32d709eb 100644 --- a/invoices/src/main/java/com/paypal/invoices/invoicesextract/service/hmc/impl/InvoiceProcessServiceImpl.java +++ b/invoices/src/main/java/com/paypal/invoices/invoicesextract/service/hmc/impl/InvoiceProcessServiceImpl.java @@ -24,13 +24,10 @@ protected InvoiceProcessServiceImpl(final HyperWalletPaymentExtractService hyper /** * {@inheritDoc} */ - public HyperwalletPayment payOperator(final InvoiceModel invoice) { - - HyperwalletPayment operatorPayment = null; + public void payOperator(final InvoiceModel invoice) { if (invoicesOperatorCommissionsConfig.isEnabled()) { - operatorPayment = super.hyperWalletPaymentExtractService.payInvoiceOperator(invoice); + super.hyperWalletPaymentExtractService.payInvoiceOperator(invoice); } - return operatorPayment; } } diff --git a/invoices/src/main/java/com/paypal/invoices/invoicesextract/service/hmc/impl/InvoiceProcessServiceMock.java b/invoices/src/main/java/com/paypal/invoices/invoicesextract/service/hmc/impl/InvoiceProcessServiceMock.java index 1bcee34e..2a30ecd4 100644 --- a/invoices/src/main/java/com/paypal/invoices/invoicesextract/service/hmc/impl/InvoiceProcessServiceMock.java +++ b/invoices/src/main/java/com/paypal/invoices/invoicesextract/service/hmc/impl/InvoiceProcessServiceMock.java @@ -26,13 +26,11 @@ protected InvoiceProcessServiceMock(final HyperWalletPaymentExtractService hyper /** * {@inheritDoc} */ - public HyperwalletPayment payOperator(InvoiceModel invoice) { + public void payOperator(InvoiceModel invoice) { - HyperwalletPayment operatorPayment = null; if (testingInvoicesSessionDataHelper.isOperatorCommissionsEnabled()) { - operatorPayment = super.hyperWalletPaymentExtractService.payInvoiceOperator(invoice); + super.hyperWalletPaymentExtractService.payInvoiceOperator(invoice); } - return operatorPayment; } } diff --git a/invoices/src/main/java/com/paypal/invoices/invoicesextract/service/hyperwallet/HyperWalletPaymentExtractService.java b/invoices/src/main/java/com/paypal/invoices/invoicesextract/service/hyperwallet/HyperWalletPaymentExtractService.java index f4cfb043..462c8254 100644 --- a/invoices/src/main/java/com/paypal/invoices/invoicesextract/service/hyperwallet/HyperWalletPaymentExtractService.java +++ b/invoices/src/main/java/com/paypal/invoices/invoicesextract/service/hyperwallet/HyperWalletPaymentExtractService.java @@ -13,23 +13,21 @@ public interface HyperWalletPaymentExtractService { * Creates a payment of type {@link HyperwalletPayment} based on {@code invoices} for * the payees * @param invoice the {@link InvoiceModel} - * @return */ - HyperwalletPayment payPayeeInvoice(InvoiceModel invoice); + void payPayeeInvoice(InvoiceModel invoice); /** * Creates a payment of type {@link HyperwalletPayment} based on {@code invoices} for * the payees * @param creditNote the {@link CreditNoteModel} - * @return */ - HyperwalletPayment payPayeeCreditNotes(CreditNoteModel creditNote); + void payPayeeCreditNotes(CreditNoteModel creditNote); /** * Create a payment of type {@link HyperwalletPayment} based on {@code invoices} for * the operator * @param invoice the {@link InvoiceModel} */ - HyperwalletPayment payInvoiceOperator(InvoiceModel invoice); + void payInvoiceOperator(InvoiceModel invoice); } diff --git a/invoices/src/main/java/com/paypal/invoices/invoicesextract/service/hyperwallet/impl/HyperWalletPaymentExtractServiceImpl.java b/invoices/src/main/java/com/paypal/invoices/invoicesextract/service/hyperwallet/impl/HyperWalletPaymentExtractServiceImpl.java index d31e6283..d9a26b56 100644 --- a/invoices/src/main/java/com/paypal/invoices/invoicesextract/service/hyperwallet/impl/HyperWalletPaymentExtractServiceImpl.java +++ b/invoices/src/main/java/com/paypal/invoices/invoicesextract/service/hyperwallet/impl/HyperWalletPaymentExtractServiceImpl.java @@ -2,7 +2,9 @@ import com.hyperwallet.clientsdk.Hyperwallet; import com.hyperwallet.clientsdk.HyperwalletException; +import com.hyperwallet.clientsdk.model.HyperwalletList; import com.hyperwallet.clientsdk.model.HyperwalletPayment; +import com.hyperwallet.clientsdk.model.HyperwalletPaymentListOptions; import com.paypal.infrastructure.converter.Converter; import com.paypal.infrastructure.exceptions.HMCException; import com.paypal.infrastructure.mail.MailNotificationUtil; @@ -15,9 +17,10 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; -import java.util.List; +import java.util.Collection; import java.util.Objects; -import java.util.stream.Collectors; +import java.util.Optional; +import java.util.stream.Stream; /** * Class that connects with hyperwallet to creates the payments @@ -54,33 +57,34 @@ public HyperWalletPaymentExtractServiceImpl( * @return */ @Override - public HyperwalletPayment payPayeeInvoice(InvoiceModel invoice) { - return payInvoice(invoice, payeeInvoiceModelToHyperwalletPaymentConverter); + public void payPayeeInvoice(InvoiceModel invoice) { + payInvoice(invoice, payeeInvoiceModelToHyperwalletPaymentConverter); } @Override - public HyperwalletPayment payPayeeCreditNotes(final CreditNoteModel creditNote) { - return payInvoice(creditNote, payeeCreditModelToHyperwalletPaymentConverter); + public void payPayeeCreditNotes(final CreditNoteModel creditNote) { + payInvoice(creditNote, payeeCreditModelToHyperwalletPaymentConverter); } @Override - public HyperwalletPayment payInvoiceOperator(InvoiceModel invoice) { - return payInvoice(invoice, operatorInvoiceModelToHyperwalletPaymentConverter); + public void payInvoiceOperator(InvoiceModel invoice) { + payInvoice(invoice, operatorInvoiceModelToHyperwalletPaymentConverter); } - protected HyperwalletPayment payInvoice(final T invoice, + protected void payInvoice(final T invoice, final Converter invoiceConverter) { HyperwalletPayment pendingPayment = invoiceConverter.convert(invoice); - log.info("Pending invoices to pay: [{}]", invoice.getInvoiceNumber()); + if (isInvoiceCreated(pendingPayment)) { + log.warn("Invoice {} already sent to Hyperwallet", pendingPayment.getClientPaymentId()); + return; + } - HyperwalletPayment paidInvoice = createPayment(pendingPayment); + log.info("Pending invoices to pay: [{}]", pendingPayment.getClientPaymentId()); - if (paidInvoice != null) { - log.info("Paid invoices: [{}]", paidInvoice.getClientPaymentId()); - } + HyperwalletPayment paidInvoice = createPayment(pendingPayment); - return paidInvoice; + log.info("Paid invoices: [{}]", paidInvoice.getClientPaymentId()); } protected HyperwalletPayment createPayment(final HyperwalletPayment hyperwalletPayment) { @@ -107,4 +111,42 @@ protected HyperwalletPayment createPayment(final HyperwalletPayment hyperwalletP } } + protected boolean isInvoiceCreated(HyperwalletPayment payment) { + try { + return getPayment(payment.getProgramToken(), payment.getClientPaymentId()).isPresent(); + } + catch (Exception e) { + // Let the flow of execution continue. Checking the existence of the payment + // shouldn't abort + // the payment creation process. If something is wrong the payment creation + // should fail and that + // is going to trigger the error reporting process (currently via email)s. + return false; + } + } + + protected Optional getPayment(final String programToken, final String clientPaymentId) { + try { + final Hyperwallet hyperwalletAPIClient = invoicesHyperwalletSDKService + .getHyperwalletInstanceWithProgramToken(programToken); + HyperwalletPaymentListOptions hyperwalletPaymentListOptions = new HyperwalletPaymentListOptions(); + hyperwalletPaymentListOptions.setClientPaymentId(clientPaymentId); + final HyperwalletList payments = hyperwalletAPIClient + .listPayments(hyperwalletPaymentListOptions); + + return getFirstElement(payments); + } + catch (final HyperwalletException e) { + log.error("Something went wrong trying to find payment for invoice [{}]", clientPaymentId); + log.error(HyperwalletLoggingErrorsUtil.stringify(e)); + + throw new HMCException("Error while invoking Hyperwallet", e); + } + } + + private Optional getFirstElement(HyperwalletList payments) { + return Stream.ofNullable(payments).map(HyperwalletList::getData).filter(Objects::nonNull) + .flatMap(Collection::stream).findFirst(); + } + } diff --git a/invoices/src/test/java/com/paypal/invoices/invoicesextract/service/hyperwallet/impl/HyperWalletPaymentExtractServiceImplTest.java b/invoices/src/test/java/com/paypal/invoices/invoicesextract/service/hyperwallet/impl/HyperWalletPaymentExtractServiceImplTest.java index 3c569de7..9f44e4b8 100644 --- a/invoices/src/test/java/com/paypal/invoices/invoicesextract/service/hyperwallet/impl/HyperWalletPaymentExtractServiceImplTest.java +++ b/invoices/src/test/java/com/paypal/invoices/invoicesextract/service/hyperwallet/impl/HyperWalletPaymentExtractServiceImplTest.java @@ -2,6 +2,7 @@ import com.hyperwallet.clientsdk.Hyperwallet; import com.hyperwallet.clientsdk.HyperwalletException; +import com.hyperwallet.clientsdk.model.HyperwalletList; import com.hyperwallet.clientsdk.model.HyperwalletPayment; import com.paypal.infrastructure.converter.Converter; import com.paypal.infrastructure.exceptions.HMCException; @@ -17,7 +18,9 @@ import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; -import static org.assertj.core.api.Assertions.assertThat; +import java.util.Collections; +import java.util.List; + import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.*; @@ -40,6 +43,9 @@ class HyperWalletPaymentExtractServiceImplTest { @Mock private HyperwalletPayment paymentOneMock, createdPaymentOneMock; + @Mock + private HyperwalletList paymentHyperwalletListMock; + @Mock private Converter invoiceModelToHyperwalletPaymentConverterMock; @@ -66,14 +72,12 @@ void payInvoice_shouldConvertInvoicesToHyperwalletPaymentCreatesOnePaymentPerInv when(hyperwalletMock.createPayment(paymentOneMock)).thenReturn(createdPaymentOneMock); when(paymentOneMock.getProgramToken()).thenReturn(PROGRAM_TOKEN); when(hyperwalletSDKService.getHyperwalletInstanceWithProgramToken(PROGRAM_TOKEN)).thenReturn(hyperwalletMock); + doReturn(false).when(testObj).isInvoiceCreated(paymentOneMock); - final HyperwalletPayment result = testObj.payInvoice(invoiceModelOneMock, - invoiceModelToHyperwalletPaymentConverterMock); + testObj.payInvoice(invoiceModelOneMock, invoiceModelToHyperwalletPaymentConverterMock); verify(invoiceModelToHyperwalletPaymentConverterMock).convert(invoiceModelOneMock); verify(hyperwalletMock).createPayment(paymentOneMock); - - assertThat(result).isEqualTo(createdPaymentOneMock); } @Test @@ -81,6 +85,7 @@ void payInvoice_shouldReturnNullWhenPaymentNotSuccessfullyCreatedOnHyperwallet() when(invoiceModelToHyperwalletPaymentConverterMock.convert(invoiceModelOneMock)).thenReturn(paymentOneMock); when(paymentOneMock.getProgramToken()).thenReturn(PROGRAM_TOKEN); when(hyperwalletSDKService.getHyperwalletInstanceWithProgramToken(PROGRAM_TOKEN)).thenReturn(hyperwalletMock); + doReturn(false).when(testObj).isInvoiceCreated(paymentOneMock); doThrow(new HyperwalletException("Something went wrong")).when(hyperwalletMock).createPayment(paymentOneMock); assertThatThrownBy(() -> testObj.payInvoice(invoiceModelOneMock, invoiceModelToHyperwalletPaymentConverterMock)) @@ -93,24 +98,20 @@ void payInvoice_shouldReturnNullWhenPaymentNotSuccessfullyCreatedOnHyperwallet() @Test void payPayee_shouldCallPayInvoiceWithTheProperConverter() { - doReturn(paymentOneMock).when(testObj).payInvoice(invoiceModelOneMock, - invoiceModelToHyperwalletPaymentConverterMock); + doNothing().when(testObj).payInvoice(invoiceModelOneMock, invoiceModelToHyperwalletPaymentConverterMock); - final HyperwalletPayment result = testObj.payPayeeInvoice(invoiceModelOneMock); + testObj.payPayeeInvoice(invoiceModelOneMock); verify(testObj).payInvoice(invoiceModelOneMock, invoiceModelToHyperwalletPaymentConverterMock); - assertThat(result).isEqualTo(paymentOneMock); } @Test void payOperator_shouldCallPayInvoiceWithTheProperConverter() { - doReturn(createdPaymentOneMock).when(testObj).payInvoice(invoiceModelOneMock, - invoiceModelToHyperwalletPaymentConverterMock); + doNothing().when(testObj).payInvoice(invoiceModelOneMock, invoiceModelToHyperwalletPaymentConverterMock); - final HyperwalletPayment result = testObj.payInvoiceOperator(invoiceModelOneMock); + testObj.payInvoiceOperator(invoiceModelOneMock); verify(testObj).payInvoice(invoiceModelOneMock, invoiceModelToHyperwalletPaymentConverterMock); - assertThat(result).isEqualTo(createdPaymentOneMock); } @Test @@ -121,6 +122,7 @@ void createPayment_shouldSendAnEmailWhenAnExceptionIsThrown() { when(paymentOneMock.getClientPaymentId()).thenReturn("000001234"); when(paymentOneMock.getProgramToken()).thenReturn(PROGRAM_TOKEN); when(hyperwalletSDKService.getHyperwalletInstanceWithProgramToken(PROGRAM_TOKEN)).thenReturn(hyperwalletMock); + doReturn(false).when(testObj).isInvoiceCreated(paymentOneMock); assertThatThrownBy(() -> testObj.payInvoice(invoiceModelOneMock, invoiceModelToHyperwalletPaymentConverterMock)) .isInstanceOf(HMCException.class); @@ -136,15 +138,13 @@ void payPayeeCreditNote_shouldConvertCreditNotesToHyperwalletPaymentCreatesOnePa when(creditNoteModelHyperwalletPaymentConverterMock.convert(creditNoteModelOneMock)).thenReturn(paymentOneMock); when(hyperwalletMock.createPayment(paymentOneMock)).thenReturn(createdPaymentOneMock); when(paymentOneMock.getProgramToken()).thenReturn(PROGRAM_TOKEN); - when(hyperwalletSDKService.getHyperwalletInstanceWithProgramToken(PROGRAM_TOKEN)).thenReturn(hyperwalletMock); + doReturn(false).when(testObj).isInvoiceCreated(paymentOneMock); - final HyperwalletPayment result = testObj.payPayeeCreditNotes(creditNoteModelOneMock); + testObj.payPayeeCreditNotes(creditNoteModelOneMock); verify(creditNoteModelHyperwalletPaymentConverterMock).convert(creditNoteModelOneMock); verify(hyperwalletMock).createPayment(paymentOneMock); - - assertThat(result).isEqualTo(createdPaymentOneMock); } @Test @@ -152,6 +152,8 @@ void payPayeeCreditNote_shouldThrowExceptionWhenPaymentNotSuccessfullyCreatedOnH when(creditNoteModelHyperwalletPaymentConverterMock.convert(creditNoteModelOneMock)).thenReturn(paymentOneMock); when(paymentOneMock.getProgramToken()).thenReturn(PROGRAM_TOKEN); when(hyperwalletSDKService.getHyperwalletInstanceWithProgramToken(PROGRAM_TOKEN)).thenReturn(hyperwalletMock); + doReturn(false).when(testObj).isInvoiceCreated(paymentOneMock); + doThrow(new HyperwalletException("Something went wrong")).when(hyperwalletMock).createPayment(paymentOneMock); assertThatThrownBy(() -> testObj.payPayeeCreditNotes(creditNoteModelOneMock)).isInstanceOf(HMCException.class); @@ -160,4 +162,56 @@ void payPayeeCreditNote_shouldThrowExceptionWhenPaymentNotSuccessfullyCreatedOnH verify(hyperwalletMock).createPayment(paymentOneMock); } + @Test + void payInvoice_shouldNotCreateInvoice_WhenInvoiceExists() { + when(invoiceModelToHyperwalletPaymentConverterMock.convert(invoiceModelOneMock)).thenReturn(paymentOneMock); + + doReturn(true).when(testObj).isInvoiceCreated(paymentOneMock); + + testObj.payInvoice(invoiceModelOneMock, invoiceModelToHyperwalletPaymentConverterMock); + + verify(testObj, times(0)).createPayment(any()); + } + + @Test + void payInvoice_shouldCheckIfInvoiceExistsAndCreateInvoice_WhenInvoiceNotExists() { + when(invoiceModelToHyperwalletPaymentConverterMock.convert(invoiceModelOneMock)).thenReturn(paymentOneMock); + when(hyperwalletMock.createPayment(paymentOneMock)).thenReturn(createdPaymentOneMock); + when(paymentOneMock.getProgramToken()).thenReturn(PROGRAM_TOKEN); + when(hyperwalletSDKService.getHyperwalletInstanceWithProgramToken(PROGRAM_TOKEN)).thenReturn(hyperwalletMock); + when(hyperwalletMock.listPayments(any())).thenReturn(paymentHyperwalletListMock); + + testObj.payInvoice(invoiceModelOneMock, invoiceModelToHyperwalletPaymentConverterMock); + + verify(hyperwalletMock).listPayments(any()); + } + + @Test + void payInvoice_shouldCheckIfInvoiceExistsAndNotCreateInvoice_WhenInvoiceExists() { + when(hyperwalletSDKService.getHyperwalletInstanceWithProgramToken(PROGRAM_TOKEN)).thenReturn(hyperwalletMock); + when(invoiceModelToHyperwalletPaymentConverterMock.convert(invoiceModelOneMock)).thenReturn(paymentOneMock); + when(hyperwalletMock.listPayments(any())).thenReturn(paymentHyperwalletListMock); + when(paymentHyperwalletListMock.getData()).thenReturn(List.of(paymentOneMock)); + when(paymentOneMock.getProgramToken()).thenReturn(PROGRAM_TOKEN); + + testObj.payInvoice(invoiceModelOneMock, invoiceModelToHyperwalletPaymentConverterMock); + + verify(hyperwalletMock).listPayments(any()); + } + + @Test + void payInvoice_shouldContinueWithCreation_WhenGetPaymentFails() { + when(hyperwalletSDKService.getHyperwalletInstanceWithProgramToken(PROGRAM_TOKEN)).thenReturn(hyperwalletMock); + when(invoiceModelOneMock.getHyperwalletProgram()).thenReturn(PROGRAM_TOKEN); + when(invoiceModelToHyperwalletPaymentConverterMock.convert(invoiceModelOneMock)).thenReturn(paymentOneMock); + doReturn(paymentOneMock).when(testObj).createPayment(any()); + + doThrow(new RuntimeException("Something went wrong")).when(hyperwalletMock).listPayments(any()); + + testObj.payInvoice(invoiceModelOneMock, invoiceModelToHyperwalletPaymentConverterMock); + + verify(testObj).createPayment(any()); + + } + } diff --git a/kyc/src/main/java/com/paypal/kyc/KYCNotificationsSpringContextConfiguration.java b/kyc/src/main/java/com/paypal/kyc/KYCNotificationsSpringContextConfiguration.java index 115d624b..d239ca6e 100644 --- a/kyc/src/main/java/com/paypal/kyc/KYCNotificationsSpringContextConfiguration.java +++ b/kyc/src/main/java/com/paypal/kyc/KYCNotificationsSpringContextConfiguration.java @@ -2,18 +2,13 @@ import com.paypal.infrastructure.InfrastructureConnectorApplication; import com.paypal.kyc.infrastructure.configuration.KYCMiraklApiConfig; -import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.ComponentScan; @ImportAutoConfiguration({ InfrastructureConnectorApplication.class }) @EnableConfigurationProperties({ KYCMiraklApiConfig.class }) -@SpringBootApplication +@ComponentScan public class KYCNotificationsSpringContextConfiguration { - public static void main(final String[] args) { - SpringApplication.run(KYCNotificationsSpringContextConfiguration.class, args); - } - } diff --git a/kyc/src/main/java/com/paypal/kyc/batchjobs/AbstractDocumentsBatchJobItemProcessor.java b/kyc/src/main/java/com/paypal/kyc/batchjobs/AbstractDocumentsBatchJobItemProcessor.java new file mode 100644 index 00000000..d82888ac --- /dev/null +++ b/kyc/src/main/java/com/paypal/kyc/batchjobs/AbstractDocumentsBatchJobItemProcessor.java @@ -0,0 +1,70 @@ +package com.paypal.kyc.batchjobs; + +import com.paypal.infrastructure.batchjob.BatchJobContext; +import com.paypal.infrastructure.batchjob.BatchJobItem; +import com.paypal.infrastructure.batchjob.BatchJobItemProcessor; +import com.paypal.kyc.batchjobs.businessstakeholders.BusinessStakeholdersDocumentsExtractBatchJobItemProcessor; +import com.paypal.kyc.batchjobs.sellers.SellersDocumentsExtractBatchJobItemProcessor; +import com.paypal.kyc.model.KYCDocumentInfoModel; +import com.paypal.kyc.model.KYCDocumentModel; +import com.paypal.kyc.service.KYCReadyForReviewService; +import lombok.extern.slf4j.Slf4j; + +import java.io.File; +import java.util.Objects; + +/** + * Class that holds common functionality for both + * {@link BusinessStakeholdersDocumentsExtractBatchJobItemProcessor} and + * {@link SellersDocumentsExtractBatchJobItemProcessor} + * + * @param the job item type. + */ +@Slf4j +public abstract class AbstractDocumentsBatchJobItemProcessor> + implements BatchJobItemProcessor { + + private final KYCReadyForReviewService kycReadyForReviewService; + + protected AbstractDocumentsBatchJobItemProcessor(KYCReadyForReviewService kycReadyForReviewService) { + this.kycReadyForReviewService = kycReadyForReviewService; + } + + /** + * {@inheritDoc} + */ + @Override + public void processItem(final BatchJobContext ctx, final T jobItem) { + boolean areDocumentsPushedToHW = pushAndFlagDocuments(jobItem); + + if (areDocumentsPushedToHW) { + notifyReadyToReviewDocuments(jobItem.getItem()); + } + + cleanUpDocumentsFiles(jobItem.getItem()); + } + + protected abstract boolean pushAndFlagDocuments(T jobItem); + + private void notifyReadyToReviewDocuments(final KYCDocumentInfoModel kycDocumentInfoModel) { + getKycReadyForReviewService().notifyReadyForReview(kycDocumentInfoModel); + } + + @SuppressWarnings("java:S3864") + protected void cleanUpDocumentsFiles(final R successFullPushedDocument) { + log.info("Cleaning up files from disk..."); + //@formatter:off + successFullPushedDocument.getDocuments().stream() + .map(KYCDocumentModel::getFile) + .filter(Objects::nonNull) + .peek(file -> log.info("File selected to be deleted [{}]", file.getAbsolutePath())) + .forEach(File::delete); + //@formatter:on + log.info("Cleaning up done successfully!"); + } + + protected KYCReadyForReviewService getKycReadyForReviewService() { + return kycReadyForReviewService; + } + +} diff --git a/kyc/src/main/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJob.java b/kyc/src/main/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJob.java new file mode 100644 index 00000000..96e03f36 --- /dev/null +++ b/kyc/src/main/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJob.java @@ -0,0 +1,35 @@ +package com.paypal.kyc.batchjobs.businessstakeholders; + +import com.paypal.infrastructure.batchjob.*; +import org.springframework.stereotype.Service; + +/** + * This job extracts the business stakeholders documents for all the modified shops in + * Mirakl and uploads the documents to Hyperwallet + */ +@Service +public class BusinessStakeholdersDocumentsExtractBatchJob extends + AbstractBatchJob implements BatchJob { + + private final BusinessStakeholdersDocumentsExtractBatchJobItemProcessor businessStakeholdersDocumentsExtractBatchJobItemProcessor; + + private final BusinessStakeholdersDocumentsExtractBatchJobItemExtractor businessStakeholdersDocumentsExtractBatchJobItemExtractor; + + public BusinessStakeholdersDocumentsExtractBatchJob( + BusinessStakeholdersDocumentsExtractBatchJobItemProcessor businessStakeholdersDocumentsExtractBatchJobItemProcessor, + BusinessStakeholdersDocumentsExtractBatchJobItemExtractor businessStakeholdersDocumentsExtractBatchJobItemExtractor) { + this.businessStakeholdersDocumentsExtractBatchJobItemProcessor = businessStakeholdersDocumentsExtractBatchJobItemProcessor; + this.businessStakeholdersDocumentsExtractBatchJobItemExtractor = businessStakeholdersDocumentsExtractBatchJobItemExtractor; + } + + @Override + protected BatchJobItemProcessor getBatchJobItemProcessor() { + return businessStakeholdersDocumentsExtractBatchJobItemProcessor; + } + + @Override + protected BatchJobItemsExtractor getBatchJobItemsExtractor() { + return businessStakeholdersDocumentsExtractBatchJobItemExtractor; + } + +} diff --git a/kyc/src/main/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobItem.java b/kyc/src/main/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobItem.java new file mode 100644 index 00000000..04b2a680 --- /dev/null +++ b/kyc/src/main/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobItem.java @@ -0,0 +1,38 @@ +package com.paypal.kyc.batchjobs.businessstakeholders; + +import com.paypal.infrastructure.batchjob.AbstractBatchJobItem; +import com.paypal.kyc.model.KYCDocumentBusinessStakeHolderInfoModel; + +/** + * Class that holds the needed information for batch processing + * {@link KYCDocumentBusinessStakeHolderInfoModel} + */ +public class BusinessStakeholdersDocumentsExtractBatchJobItem + extends AbstractBatchJobItem { + + protected BusinessStakeholdersDocumentsExtractBatchJobItem(final KYCDocumentBusinessStakeHolderInfoModel item) { + super(item); + } + + /** + * Returns the {@code clientUserId}, {@code BusinessStakeholderMiraklNumber} and + * {@code token} of a {@link KYCDocumentBusinessStakeHolderInfoModel} + * @return the {@link String} as the item identifier. + */ + @Override + public String getItemId() { + return getItem().getClientUserId() + "-" + getItem().getBusinessStakeholderMiraklNumber() + "-" + + getItem().getToken(); + } + + /** + * Returns the type as {@link String} of the + * {@link com.paypal.infrastructure.batchjob.BatchJobItem} + * @return {@code BusinessStakeholderDocument} + */ + @Override + public String getItemType() { + return "BusinessStakeholderDocument"; + } + +} diff --git a/kyc/src/main/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobItemExtractor.java b/kyc/src/main/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobItemExtractor.java new file mode 100644 index 00000000..5850eca7 --- /dev/null +++ b/kyc/src/main/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobItemExtractor.java @@ -0,0 +1,41 @@ +package com.paypal.kyc.batchjobs.businessstakeholders; + +import com.paypal.infrastructure.batchjob.AbstractDeltaBatchJobItemsExtractor; +import com.paypal.infrastructure.batchjob.BatchJobContext; +import com.paypal.kyc.service.documents.files.mirakl.MiraklBusinessStakeholderDocumentsExtractService; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.Date; +import java.util.stream.Collectors; + +/** + * Handles the extraction of business stakeholders documents. It retrieves all documents + * from shops that have been modified in Mirakl. + */ +@Service +public class BusinessStakeholdersDocumentsExtractBatchJobItemExtractor + extends AbstractDeltaBatchJobItemsExtractor { + + private final MiraklBusinessStakeholderDocumentsExtractService miraklBusinessStakeholderDocumentsExtractService; + + public BusinessStakeholdersDocumentsExtractBatchJobItemExtractor( + MiraklBusinessStakeholderDocumentsExtractService miraklBusinessStakeholderDocumentsExtractService) { + this.miraklBusinessStakeholderDocumentsExtractService = miraklBusinessStakeholderDocumentsExtractService; + } + + /** + * Retrieves all the business stakeholder documents modified since the {@code delta} + * time and returns them as a {@link Collection} of + * {@link BusinessStakeholdersDocumentsExtractBatchJobItem} + * @param delta the cut-out {@link Date} + * @return a {@link Collection} of + * {@link BusinessStakeholdersDocumentsExtractBatchJobItem} + */ + @Override + protected Collection getItems(final Date delta) { + return miraklBusinessStakeholderDocumentsExtractService.extractBusinessStakeholderDocuments(delta).stream() + .map(BusinessStakeholdersDocumentsExtractBatchJobItem::new).collect(Collectors.toList()); + } + +} diff --git a/kyc/src/main/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobItemProcessor.java b/kyc/src/main/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobItemProcessor.java new file mode 100644 index 00000000..4ca3ef79 --- /dev/null +++ b/kyc/src/main/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobItemProcessor.java @@ -0,0 +1,48 @@ +package com.paypal.kyc.batchjobs.businessstakeholders; + +import com.paypal.kyc.batchjobs.AbstractDocumentsBatchJobItemProcessor; +import com.paypal.kyc.service.KYCReadyForReviewService; +import com.paypal.kyc.service.documents.files.hyperwallet.HyperwalletBusinessStakeholderExtractService; +import com.paypal.kyc.service.documents.files.mirakl.MiraklBusinessStakeholderDocumentsExtractService; +import org.springframework.stereotype.Service; + +/** + * Handles processing of business stakeholder documents by pushing them to Hyperwallet. + */ +@Service +public class BusinessStakeholdersDocumentsExtractBatchJobItemProcessor + extends AbstractDocumentsBatchJobItemProcessor { + + private final MiraklBusinessStakeholderDocumentsExtractService miraklBusinessStakeholderDocumentsExtractService; + + private final HyperwalletBusinessStakeholderExtractService hyperwalletBusinessStakeholderExtractService; + + public BusinessStakeholdersDocumentsExtractBatchJobItemProcessor( + MiraklBusinessStakeholderDocumentsExtractService miraklBusinessStakeholderDocumentsExtractService, + HyperwalletBusinessStakeholderExtractService hyperwalletBusinessStakeholderExtractService, + KYCReadyForReviewService kycReadyForReviewService) { + super(kycReadyForReviewService); + this.miraklBusinessStakeholderDocumentsExtractService = miraklBusinessStakeholderDocumentsExtractService; + this.hyperwalletBusinessStakeholderExtractService = hyperwalletBusinessStakeholderExtractService; + } + + /** + * Push and flag the {@link BusinessStakeholdersDocumentsExtractBatchJobItem} with the + * {@link HyperwalletBusinessStakeholderExtractService} and + * {@link MiraklBusinessStakeholderDocumentsExtractService} + * @param jobItem The {@link BusinessStakeholdersDocumentsExtractBatchJobItem} + * @return If document was pushed to Hyperwallet + */ + @Override + protected boolean pushAndFlagDocuments(final BusinessStakeholdersDocumentsExtractBatchJobItem jobItem) { + boolean areDocumentsPushedToHW = hyperwalletBusinessStakeholderExtractService.pushDocuments(jobItem.getItem()); + + if (areDocumentsPushedToHW) { + miraklBusinessStakeholderDocumentsExtractService + .setBusinessStakeholderFlagKYCToPushBusinessStakeholderDocumentsToFalse(jobItem.getItem()); + } + + return areDocumentsPushedToHW; + } + +} diff --git a/kyc/src/main/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJob.java b/kyc/src/main/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJob.java new file mode 100644 index 00000000..b000e3f0 --- /dev/null +++ b/kyc/src/main/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJob.java @@ -0,0 +1,35 @@ +package com.paypal.kyc.batchjobs.sellers; + +import com.paypal.infrastructure.batchjob.*; +import org.springframework.stereotype.Service; + +/** + * This job extracts the seller documents for all the modified shops in Mirakl and uploads + * the documents to Hyperwallet + */ +@Service +public class SellersDocumentsExtractBatchJob + extends AbstractBatchJob implements BatchJob { + + private final SellersDocumentsExtractBatchJobItemProcessor sellersDocumentsExtractBatchJobItemProcessor; + + private final SellersDocumentsExtractBatchJobItemExtractor sellersDocumentsExtractBatchJobItemExtractor; + + public SellersDocumentsExtractBatchJob( + SellersDocumentsExtractBatchJobItemProcessor sellersDocumentsExtractBatchJobItemProcessor, + SellersDocumentsExtractBatchJobItemExtractor sellersDocumentsExtractBatchJobItemExtractor) { + this.sellersDocumentsExtractBatchJobItemProcessor = sellersDocumentsExtractBatchJobItemProcessor; + this.sellersDocumentsExtractBatchJobItemExtractor = sellersDocumentsExtractBatchJobItemExtractor; + } + + @Override + protected BatchJobItemProcessor getBatchJobItemProcessor() { + return sellersDocumentsExtractBatchJobItemProcessor; + } + + @Override + protected BatchJobItemsExtractor getBatchJobItemsExtractor() { + return sellersDocumentsExtractBatchJobItemExtractor; + } + +} diff --git a/kyc/src/main/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItem.java b/kyc/src/main/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItem.java new file mode 100644 index 00000000..ee3ae1ca --- /dev/null +++ b/kyc/src/main/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItem.java @@ -0,0 +1,36 @@ +package com.paypal.kyc.batchjobs.sellers; + +import com.paypal.infrastructure.batchjob.AbstractBatchJobItem; +import com.paypal.kyc.model.KYCDocumentBusinessStakeHolderInfoModel; +import com.paypal.kyc.model.KYCDocumentSellerInfoModel; + +/** + * Class that holds the needed information for batch processing + * {@link KYCDocumentSellerInfoModel} + */ +public class SellersDocumentsExtractBatchJobItem extends AbstractBatchJobItem { + + protected SellersDocumentsExtractBatchJobItem(final KYCDocumentSellerInfoModel item) { + super(item); + } + + /** + * Returns the {@code clientUserId} of a {@link KYCDocumentSellerInfoModel} + * @return the {@link String} as the item identifier. + */ + @Override + public String getItemId() { + return getItem().getClientUserId(); + } + + /** + * Returns the type as {@link String} of the + * {@link com.paypal.infrastructure.batchjob.BatchJobItem} + * @return {@code SellerDocument} + */ + @Override + public String getItemType() { + return "SellerDocument"; + } + +} diff --git a/kyc/src/main/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItemExtractor.java b/kyc/src/main/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItemExtractor.java new file mode 100644 index 00000000..da919864 --- /dev/null +++ b/kyc/src/main/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItemExtractor.java @@ -0,0 +1,39 @@ +package com.paypal.kyc.batchjobs.sellers; + +import com.paypal.infrastructure.batchjob.AbstractDeltaBatchJobItemsExtractor; +import com.paypal.infrastructure.batchjob.BatchJobContext; +import com.paypal.kyc.service.documents.files.mirakl.MiraklSellerDocumentsExtractService; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.Date; +import java.util.stream.Collectors; + +/** + * Handles the extraction of seller documents. It retrieves all documents from shops that + * have been modified in Mirakl. + */ +@Service +public class SellersDocumentsExtractBatchJobItemExtractor + extends AbstractDeltaBatchJobItemsExtractor { + + private final MiraklSellerDocumentsExtractService miraklSellerDocumentsExtractService; + + public SellersDocumentsExtractBatchJobItemExtractor( + final MiraklSellerDocumentsExtractService miraklSellerDocumentsExtractService) { + this.miraklSellerDocumentsExtractService = miraklSellerDocumentsExtractService; + } + + /** + * Retrieves all the seller documents modified since the {@code delta} time and + * returns them as a {@link Collection} of {@link SellersDocumentsExtractBatchJobItem} + * @param delta the cut-out {@link Date} + * @return a {@link Collection} of {@link SellersDocumentsExtractBatchJobItem} + */ + @Override + protected Collection getItems(final Date delta) { + return miraklSellerDocumentsExtractService.extractProofOfIdentityAndBusinessSellerDocuments(delta).stream() + .map(SellersDocumentsExtractBatchJobItem::new).collect(Collectors.toList()); + } + +} diff --git a/kyc/src/main/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItemProcessor.java b/kyc/src/main/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItemProcessor.java new file mode 100644 index 00000000..7734aac7 --- /dev/null +++ b/kyc/src/main/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItemProcessor.java @@ -0,0 +1,48 @@ +package com.paypal.kyc.batchjobs.sellers; + +import com.paypal.kyc.batchjobs.AbstractDocumentsBatchJobItemProcessor; +import com.paypal.kyc.service.KYCReadyForReviewService; +import com.paypal.kyc.service.documents.files.hyperwallet.HyperwalletSellerExtractService; +import com.paypal.kyc.service.documents.files.mirakl.MiraklSellerDocumentsExtractService; +import org.springframework.stereotype.Service; + +/** + * Handles processing of seller documents by pushing them to Hyperwallet. + */ +@Service +public class SellersDocumentsExtractBatchJobItemProcessor + extends AbstractDocumentsBatchJobItemProcessor { + + private final MiraklSellerDocumentsExtractService miraklSellerDocumentsExtractService; + + private final HyperwalletSellerExtractService hyperwalletSellerExtractService; + + public SellersDocumentsExtractBatchJobItemProcessor( + final MiraklSellerDocumentsExtractService miraklSellerDocumentsExtractService, + final HyperwalletSellerExtractService hyperwalletSellerExtractService, + final KYCReadyForReviewService kycReadyForReviewService) { + super(kycReadyForReviewService); + this.miraklSellerDocumentsExtractService = miraklSellerDocumentsExtractService; + this.hyperwalletSellerExtractService = hyperwalletSellerExtractService; + } + + /** + * Push and flag the {@link SellersDocumentsExtractBatchJobItem} with the + * {@link HyperwalletSellerExtractService} and + * {@link MiraklSellerDocumentsExtractService} + * @param jobItem The {@link SellersDocumentsExtractBatchJobItem} + * @return If document was pushed to Hyperwallet + */ + @Override + protected boolean pushAndFlagDocuments(final SellersDocumentsExtractBatchJobItem jobItem) { + boolean areDocumentsPushedToHW = hyperwalletSellerExtractService.pushDocuments(jobItem.getItem()); + + if (areDocumentsPushedToHW) { + miraklSellerDocumentsExtractService + .setFlagToPushProofOfIdentityAndBusinessSellerDocumentsToFalse(jobItem.getItem()); + } + + return areDocumentsPushedToHW; + } + +} diff --git a/kyc/src/main/java/com/paypal/kyc/jobs/DocumentsExtractJob.java b/kyc/src/main/java/com/paypal/kyc/jobs/DocumentsExtractJob.java index a4f4cadf..8b8d314f 100644 --- a/kyc/src/main/java/com/paypal/kyc/jobs/DocumentsExtractJob.java +++ b/kyc/src/main/java/com/paypal/kyc/jobs/DocumentsExtractJob.java @@ -1,18 +1,9 @@ package com.paypal.kyc.jobs; -import com.paypal.infrastructure.job.AbstractDeltaInfoJob; -import com.paypal.kyc.model.KYCDocumentInfoModel; -import com.paypal.kyc.service.DocumentsExtractService; -import com.paypal.kyc.service.KYCReadyForReviewService; +import com.paypal.kyc.batchjobs.businessstakeholders.BusinessStakeholdersDocumentsExtractBatchJob; +import com.paypal.kyc.batchjobs.sellers.SellersDocumentsExtractBatchJob; import lombok.extern.slf4j.Slf4j; -import org.quartz.DisallowConcurrentExecution; -import org.quartz.JobExecutionContext; -import org.quartz.PersistJobDataAfterExecution; - -import javax.annotation.Resource; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; +import org.quartz.*; /** * Extract documents job for extracting Mirakl sellers documents data and populate them on @@ -21,32 +12,25 @@ @Slf4j @PersistJobDataAfterExecution @DisallowConcurrentExecution -public class DocumentsExtractJob extends AbstractDeltaInfoJob { +public class DocumentsExtractJob implements Job { + + private final SellersDocumentsExtractBatchJob sellersDocumentsExtractBatchJob; - @Resource - private DocumentsExtractService documentsExtractService; + private final BusinessStakeholdersDocumentsExtractBatchJob businessStakeholdersDocumentsExtractBatchJob; - @Resource - private KYCReadyForReviewService kycReadyForReviewService; + public DocumentsExtractJob(SellersDocumentsExtractBatchJob sellersDocumentsExtractBatchJob, + BusinessStakeholdersDocumentsExtractBatchJob businessStakeholdersDocumentsExtractBatchJob) { + this.sellersDocumentsExtractBatchJob = sellersDocumentsExtractBatchJob; + this.businessStakeholdersDocumentsExtractBatchJob = businessStakeholdersDocumentsExtractBatchJob; + } /** - * {@inheritDoc} Fetches all the proof of identity, business documents and business - * stakeholders and exports this information to Hyperwallet - *

- * If at least one of them was successfully sent, it also sets the customer to Ready - * for Review in Hyperwallet + * {@inheritDoc} */ @Override - public void execute(final JobExecutionContext context) { - final Date delta = getDelta(context); - final List documents = new ArrayList<>(); - - documents.addAll(documentsExtractService.extractProofOfIdentityAndBusinessSellerDocuments(delta)); - documents.addAll(documentsExtractService.extractBusinessStakeholderDocuments(delta)); - - kycReadyForReviewService.notifyReadyForReview(documents); - - documentsExtractService.cleanUpDocumentsFiles(documents); + public void execute(final JobExecutionContext context) throws JobExecutionException { + sellersDocumentsExtractBatchJob.execute(context); + businessStakeholdersDocumentsExtractBatchJob.execute(context); } } diff --git a/kyc/src/main/java/com/paypal/kyc/model/KYCDocumentBusinessStakeHolderInfoModel.java b/kyc/src/main/java/com/paypal/kyc/model/KYCDocumentBusinessStakeHolderInfoModel.java index 79e23e78..265d87d0 100644 --- a/kyc/src/main/java/com/paypal/kyc/model/KYCDocumentBusinessStakeHolderInfoModel.java +++ b/kyc/src/main/java/com/paypal/kyc/model/KYCDocumentBusinessStakeHolderInfoModel.java @@ -120,6 +120,12 @@ public boolean hasSelectedDocumentsControlFieldsInBusinessStakeholder() { return true; } + @Override + public String getDocumentTracingIdentifier() { + return "Shop Id [%s] and Business Stakeholder number [%s]".formatted(getClientUserId(), + getBusinessStakeholderMiraklNumber()); + } + public Builder toBuilder() { //@formatter:off return KYCDocumentBusinessStakeHolderInfoModel.builder() @@ -133,7 +139,6 @@ public Builder toBuilder() { .proofOfIdentity(proofOfIdentity) .miraklShopDocuments(miraklShopDocuments) .contact(contact) - .sentToHyperwallet(sentToHyperwallet) .notifiedDocumentsReadyForReview(notifiedDocumentsReadyForReview) .hyperwalletProgram(hyperwalletProgram) .documents(getDocuments()); diff --git a/kyc/src/main/java/com/paypal/kyc/model/KYCDocumentInfoModel.java b/kyc/src/main/java/com/paypal/kyc/model/KYCDocumentInfoModel.java index 40ec5af1..4439b624 100644 --- a/kyc/src/main/java/com/paypal/kyc/model/KYCDocumentInfoModel.java +++ b/kyc/src/main/java/com/paypal/kyc/model/KYCDocumentInfoModel.java @@ -4,6 +4,7 @@ import com.mirakl.client.mmp.domain.shop.document.MiraklShopDocument; import lombok.Getter; import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; @@ -31,8 +32,6 @@ public class KYCDocumentInfoModel implements Serializable { protected final transient List miraklShopDocuments; - protected final boolean sentToHyperwallet; - protected final String hyperwalletProgram; private final List documents; @@ -44,7 +43,6 @@ protected KYCDocumentInfoModel(final Builder builder) { requiresKYC = builder.requiresKYC; proofOfIdentity = builder.proofOfIdentity; miraklShopDocuments = builder.miraklShopDocuments; - sentToHyperwallet = builder.sentToHyperwallet; documents = builder.documents; hyperwalletProgram = builder.hyperwalletProgram; } @@ -67,6 +65,10 @@ public boolean areDocumentsFilled() { return false; } + public String getDocumentTracingIdentifier() { + return StringUtils.EMPTY; + } + @Override public boolean equals(final Object o) { if (this == o) { @@ -105,8 +107,6 @@ public abstract static class Builder> { protected List documents; - protected boolean sentToHyperwallet; - protected String hyperwalletProgram; public abstract T getThis(); @@ -146,11 +146,6 @@ public T countryIsoCode(final String countryIsoCode) { return getThis(); } - public T sentToHyperwallet(final boolean sentToHyperwallet) { - this.sentToHyperwallet = sentToHyperwallet; - return getThis(); - } - public T hyperwalletProgram(final String hyperwalletProgram) { this.hyperwalletProgram = hyperwalletProgram; return getThis(); diff --git a/kyc/src/main/java/com/paypal/kyc/model/KYCDocumentSellerInfoModel.java b/kyc/src/main/java/com/paypal/kyc/model/KYCDocumentSellerInfoModel.java index 846ec15c..d8f6df59 100644 --- a/kyc/src/main/java/com/paypal/kyc/model/KYCDocumentSellerInfoModel.java +++ b/kyc/src/main/java/com/paypal/kyc/model/KYCDocumentSellerInfoModel.java @@ -123,6 +123,11 @@ public boolean areDocumentsFilled() { return isAddressDocumentsFilled() && isIdentityDocumentsFilled(); } + @Override + public String getDocumentTracingIdentifier() { + return "shop Id [%s]".formatted(getClientUserId()); + } + @Override public boolean equals(final Object o) { if (this == o) { @@ -164,7 +169,6 @@ public Builder toBuilder() { .proofOfAddress(proofOfAddress) .proofOfBusiness(proofOfBusiness) .miraklShopDocuments(miraklShopDocuments) - .sentToHyperwallet(sentToHyperwallet) .hyperwalletProgram(hyperwalletProgram) .documents(getDocuments()); //@formatter:on diff --git a/kyc/src/main/java/com/paypal/kyc/service/DocumentsExtractService.java b/kyc/src/main/java/com/paypal/kyc/service/DocumentsExtractService.java deleted file mode 100644 index d1a5d00d..00000000 --- a/kyc/src/main/java/com/paypal/kyc/service/DocumentsExtractService.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.paypal.kyc.service; - -import com.paypal.kyc.model.KYCDocumentBusinessStakeHolderInfoModel; -import com.paypal.kyc.model.KYCDocumentInfoModel; -import com.paypal.kyc.model.KYCDocumentSellerInfoModel; - -import java.util.Collection; -import java.util.Date; -import java.util.List; - -/** - * Manages document extract logic for KYC verification in HW - */ -public interface DocumentsExtractService { - - /** - * Manages input-output logic from Mirakl to Hyperwallet for KYC proof of - * identity/business verification for sellers - * @param delta - * @return - */ - List extractProofOfIdentityAndBusinessSellerDocuments(Date delta); - - /** - * Manages input-output logic from Mirakl to Hyperwallet for KYC verification for - * sellers - * @param delta - * @return - */ - Collection extractBusinessStakeholderDocuments(Date delta); - - /** - * Clean all documents from hard disk received as parameter - * @param successFullPushedListOfDocuments - * @param Class that extends from {@link KYCDocumentInfoModel} - */ - void cleanUpDocumentsFiles(final List successFullPushedListOfDocuments); - -} diff --git a/kyc/src/main/java/com/paypal/kyc/service/KYCReadyForReviewService.java b/kyc/src/main/java/com/paypal/kyc/service/KYCReadyForReviewService.java index da98954a..a2e1943b 100644 --- a/kyc/src/main/java/com/paypal/kyc/service/KYCReadyForReviewService.java +++ b/kyc/src/main/java/com/paypal/kyc/service/KYCReadyForReviewService.java @@ -2,8 +2,6 @@ import com.paypal.kyc.model.KYCDocumentInfoModel; -import java.util.List; - /** * Service in charge of sending a notification when business-related, proof of identity or * proof of business documents are updated and imported to Hyperwallet @@ -13,6 +11,6 @@ */ public interface KYCReadyForReviewService { - void notifyReadyForReview(List documentsTriedToBeSent); + void notifyReadyForReview(KYCDocumentInfoModel kycDocumentInfoModel); } diff --git a/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/HyperwalletBusinessStakeholderExtractService.java b/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/HyperwalletBusinessStakeholderExtractService.java index b05a887d..043cc03d 100644 --- a/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/HyperwalletBusinessStakeholderExtractService.java +++ b/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/HyperwalletBusinessStakeholderExtractService.java @@ -21,13 +21,10 @@ public interface HyperwalletBusinessStakeholderExtractService { List getKYCRequiredVerificationBusinessStakeHolders(String hyperwalletProgram, String userToken); /** - * Pushes the documents into HW and returns the list of - * KYCDocumentBusinessStakeHolderInfoModel that were correctly uploaded to HW - * @param kycBusinessStakeHolderInfoModels List of stakeholder documents to push - * @return the correct list of {@link KYCDocumentBusinessStakeHolderInfoModel} pushed - * to hyperwallet + * Pushes the documents into HW + * @param kycBusinessStakeHolderInfoModel Business stakeholders documents to push + * @return If the document was pushed to HW */ - List pushBusinessStakeholderDocuments( - List kycBusinessStakeHolderInfoModels); + boolean pushDocuments(final KYCDocumentBusinessStakeHolderInfoModel kycBusinessStakeHolderInfoModel); } diff --git a/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/HyperwalletDocumentUploadService.java b/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/HyperwalletDocumentUploadService.java new file mode 100644 index 00000000..01f3d34f --- /dev/null +++ b/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/HyperwalletDocumentUploadService.java @@ -0,0 +1,22 @@ +package com.paypal.kyc.service.documents.files.hyperwallet; + +import com.hyperwallet.clientsdk.model.HyperwalletVerificationDocument; +import com.paypal.kyc.model.KYCDocumentInfoModel; + +import java.util.List; + +/** + * Interface to upload documents to Hyperwallet. It can upload both sellers and business + * stakeholders documents. + */ +public interface HyperwalletDocumentUploadService { + + /** + * Upload a document to Hyperwallet + * @param kycDocumentInfoModel Documents to push + * @param hyperwalletVerificationDocuments List of documents in Hyperwallet format + */ + void uploadDocument(KYCDocumentInfoModel kycDocumentInfoModel, + List hyperwalletVerificationDocuments); + +} diff --git a/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/HyperwalletSellerExtractService.java b/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/HyperwalletSellerExtractService.java index 8745850e..c3aacf41 100644 --- a/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/HyperwalletSellerExtractService.java +++ b/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/HyperwalletSellerExtractService.java @@ -2,21 +2,16 @@ import com.paypal.kyc.model.KYCDocumentSellerInfoModel; -import java.util.List; - /** * Interface that manages logic of pushing documents to Hyperwallet at seller level */ public interface HyperwalletSellerExtractService { /** - * Pushes proof of identity/business documents into HW and returns the list of - * KYCDocumentInfoModel that were correctly uploaded to HW - * @param kycDocumentSellerInfoModelList - * @return the correct list of {@link KYCDocumentSellerInfoModel} pushed to - * hyperwallet + * Pushes proof of identity/business documents into HW + * @param kycDocumentSellerInfoModel + * @return If the document was pushed to HW */ - List pushProofOfIdentityAndBusinessSellerDocuments( - List kycDocumentSellerInfoModelList); + boolean pushDocuments(KYCDocumentSellerInfoModel kycDocumentSellerInfoModel); } diff --git a/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/AbstractHyperwalletDocumentExtractService.java b/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/AbstractHyperwalletDocumentExtractService.java new file mode 100644 index 00000000..be4097f1 --- /dev/null +++ b/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/AbstractHyperwalletDocumentExtractService.java @@ -0,0 +1,53 @@ +package com.paypal.kyc.service.documents.files.hyperwallet.impl; + +import com.hyperwallet.clientsdk.model.HyperwalletVerificationDocument; +import com.paypal.kyc.model.KYCDocumentInfoModel; +import com.paypal.kyc.service.HyperwalletSDKService; +import com.paypal.kyc.service.documents.files.hyperwallet.HyperwalletDocumentUploadService; +import lombok.extern.slf4j.Slf4j; + +import java.util.List; + +/** + * Class that holds common functionality for both + * {@link HyperwalletBusinessStakeholderExtractServiceImpl} and + * {@link HyperwalletSellerExtractServiceImpl} + * + * @param the job item type. + */ +@Slf4j +public abstract class AbstractHyperwalletDocumentExtractService { + + private final HyperwalletSDKService hyperwalletSDKService; + + private final HyperwalletDocumentUploadService hyperwalletDocumentUploadService; + + protected AbstractHyperwalletDocumentExtractService(final HyperwalletSDKService hyperwalletSDKService, + final HyperwalletDocumentUploadService hyperwalletDocumentUploadService) { + this.hyperwalletSDKService = hyperwalletSDKService; + this.hyperwalletDocumentUploadService = hyperwalletDocumentUploadService; + } + + public boolean pushDocuments(final T kycDocumentInfoModel) { + + if (!kycDocumentInfoModel.areDocumentsFilled()) { + log.warn("Mandatory documents missing for shop with id [{}] ", kycDocumentInfoModel.getClientUserId()); + return false; + } + + final List hyperwalletVerificationDocuments = getHyperwalletVerificationDocuments( + kycDocumentInfoModel); + + hyperwalletDocumentUploadService.uploadDocument(kycDocumentInfoModel, hyperwalletVerificationDocuments); + + return true; + } + + protected abstract List getHyperwalletVerificationDocuments( + T kycDocumentInfoModel); + + protected HyperwalletSDKService getHyperwalletSDKService() { + return hyperwalletSDKService; + } + +} diff --git a/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletBusinessStakeholderExtractServiceImpl.java b/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletBusinessStakeholderExtractServiceImpl.java index a3033158..03ead3b6 100644 --- a/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletBusinessStakeholderExtractServiceImpl.java +++ b/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletBusinessStakeholderExtractServiceImpl.java @@ -1,29 +1,24 @@ package com.paypal.kyc.service.documents.files.hyperwallet.impl; import com.hyperwallet.clientsdk.Hyperwallet; -import com.hyperwallet.clientsdk.HyperwalletException; import com.hyperwallet.clientsdk.model.HyperwalletBusinessStakeholder; import com.hyperwallet.clientsdk.model.HyperwalletList; import com.hyperwallet.clientsdk.model.HyperwalletVerificationDocument; -import com.paypal.infrastructure.mail.MailNotificationUtil; -import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; -import com.paypal.infrastructure.util.LoggingConstantsUtil; import com.paypal.kyc.model.KYCDocumentBusinessStakeHolderInfoModel; import com.paypal.kyc.service.HyperwalletSDKService; import com.paypal.kyc.service.documents.files.hyperwallet.HyperwalletBusinessStakeholderExtractService; +import com.paypal.kyc.service.documents.files.hyperwallet.HyperwalletDocumentUploadService; import com.paypal.kyc.strategies.documents.files.hyperwallet.businessstakeholder.impl.KYCBusinessStakeholderDocumentInfoModelToHWVerificationDocumentExecutor; import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.ObjectUtils; -import org.apache.commons.lang3.tuple.Pair; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Service; -import java.util.*; -import java.util.function.Predicate; +import java.util.Collections; +import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; -import java.util.stream.Stream; import static com.hyperwallet.clientsdk.model.HyperwalletBusinessStakeholder.VerificationStatus.REQUIRED; @@ -34,20 +29,17 @@ @Service @Getter @Profile({ "!qa" }) -public class HyperwalletBusinessStakeholderExtractServiceImpl implements HyperwalletBusinessStakeholderExtractService { - - private final HyperwalletSDKService hyperwalletSDKService; +public class HyperwalletBusinessStakeholderExtractServiceImpl + extends AbstractHyperwalletDocumentExtractService + implements HyperwalletBusinessStakeholderExtractService { private final KYCBusinessStakeholderDocumentInfoModelToHWVerificationDocumentExecutor kycBusinessStakeholderDocumentInfoModelToHWVerificationDocumentExecutor; - private final MailNotificationUtil kycMailNotificationUtil; - - protected HyperwalletBusinessStakeholderExtractServiceImpl(final HyperwalletSDKService hyperwalletSDKService, - final KYCBusinessStakeholderDocumentInfoModelToHWVerificationDocumentExecutor kycBusinessStakeholderDocumentInfoModelToHWVerificationDocumentExecutor, - final MailNotificationUtil kycMailNotificationUtil) { - this.hyperwalletSDKService = hyperwalletSDKService; + public HyperwalletBusinessStakeholderExtractServiceImpl(HyperwalletSDKService hyperwalletSDKService, + HyperwalletDocumentUploadService hyperwalletDocumentUploadService, + KYCBusinessStakeholderDocumentInfoModelToHWVerificationDocumentExecutor kycBusinessStakeholderDocumentInfoModelToHWVerificationDocumentExecutor) { + super(hyperwalletSDKService, hyperwalletDocumentUploadService); this.kycBusinessStakeholderDocumentInfoModelToHWVerificationDocumentExecutor = kycBusinessStakeholderDocumentInfoModelToHWVerificationDocumentExecutor; - this.kycMailNotificationUtil = kycMailNotificationUtil; } /** @@ -56,7 +48,7 @@ protected HyperwalletBusinessStakeholderExtractServiceImpl(final HyperwalletSDKS @Override public List getKYCRequiredVerificationBusinessStakeHolders(final String hyperwalletProgram, final String userToken) { - final Hyperwallet hyperwallet = hyperwalletSDKService.getHyperwalletInstance(hyperwalletProgram); + final Hyperwallet hyperwallet = getHyperwalletSDKService().getHyperwalletInstance(hyperwalletProgram); final List businessStakeholders = getBusinessStakeholders(userToken, hyperwallet); @@ -75,105 +67,11 @@ private List getBusinessStakeholders(final Strin .filter(CollectionUtils::isNotEmpty).orElse(Collections.emptyList()); } - /** - * {@inheritDoc} - */ @Override - public List pushBusinessStakeholderDocuments( - final List kycBusinessStakeHolderInfoModels) { - //@formatter:off - if (CollectionUtils.isEmpty(kycBusinessStakeHolderInfoModels)) { - return List.of(); - } - - final Map> businessStakeholdersGroupedByShops = kycBusinessStakeHolderInfoModels - .stream() - .collect(Collectors.groupingBy(KYCDocumentBusinessStakeHolderInfoModel::getClientUserId)); - - printShopsToSkip(businessStakeholdersGroupedByShops); - - //@formatter:off - final List businessStakeholderToBePushed = businessStakeholdersGroupedByShops.values() - .stream() - .filter(Predicate.not(this::hasAnyDocumentNotFilled)) - .flatMap(Collection::stream) - .collect(Collectors.toList()); - //@formatter:on - - //@formatter:on - final Map> hyperwalletVerificationDocumentsToBePushed = businessStakeholderToBePushed - .stream() - .map(businessStakeHolderElement -> Pair.of(businessStakeHolderElement, - kycBusinessStakeholderDocumentInfoModelToHWVerificationDocumentExecutor - .execute(businessStakeHolderElement))) - .collect(Collectors.toMap(Pair::getLeft, Pair::getRight)); - //@formatter:off - - //@formatter:off - return hyperwalletVerificationDocumentsToBePushed.entrySet() - .stream() - .filter(kycDocumentInfoModelListEntry -> ObjectUtils.isNotEmpty(kycDocumentInfoModelListEntry.getValue())) - .map(this::callHyperwalletAPI) - .filter(Objects::nonNull) - .collect(Collectors.toList()); - //@formatter:on - } - - /** - * Manages the way to push KYC documents to another system - * @param entry contains {@link KYCDocumentBusinessStakeHolderInfoModel} and its - * {@link List} associated - * @return {@link KYCDocumentBusinessStakeHolderInfoModel} object when it has been - * processed successfully. Null when it fails - */ - protected KYCDocumentBusinessStakeHolderInfoModel callHyperwalletAPI( - final Map.Entry> entry) { - final KYCDocumentBusinessStakeHolderInfoModel kycDocumentBusinessStakeHolderInfoModel = entry.getKey(); - final String documentsToUpload = entry.getValue().stream() - .map(hyperwalletVerificationDocument -> hyperwalletVerificationDocument.getUploadFiles().keySet()) - .flatMap(Collection::stream).collect(Collectors.joining(LoggingConstantsUtil.LIST_LOGGING_SEPARATOR)); - try { - final Hyperwallet hyperwallet = hyperwalletSDKService - .getHyperwalletInstance(kycDocumentBusinessStakeHolderInfoModel.getHyperwalletProgram()); - hyperwallet.uploadStakeholderDocuments(kycDocumentBusinessStakeHolderInfoModel.getUserToken(), - kycDocumentBusinessStakeHolderInfoModel.getToken(), entry.getValue()); - log.info("Documents [{}] uploaded for shop with id [{}] and business stakeholder number {}", - documentsToUpload, kycDocumentBusinessStakeHolderInfoModel.getClientUserId(), - kycDocumentBusinessStakeHolderInfoModel.getBusinessStakeholderMiraklNumber()); - return kycDocumentBusinessStakeHolderInfoModel.toBuilder().sentToHyperwallet(true).build(); - } - catch (final HyperwalletException e) { - log.error("Error uploading document to Hyperwallet: [{}]", HyperwalletLoggingErrorsUtil.stringify(e)); - kycMailNotificationUtil.sendPlainTextEmail("Issue detected pushing documents into Hyperwallet", - String.format( - "Something went wrong pushing documents to Hyperwallet for shop Id [%s] and business stakeholder number [%s]%n%s", - kycDocumentBusinessStakeHolderInfoModel.getClientUserId(), - kycDocumentBusinessStakeHolderInfoModel.getBusinessStakeholderMiraklNumber(), - HyperwalletLoggingErrorsUtil.stringify(e))); - return kycDocumentBusinessStakeHolderInfoModel; - } - } - - private void printShopsToSkip( - final Map> kycDocumentInfoModelCollection) { - //@formatter:off - final List shopsToSkip = Optional.ofNullable(kycDocumentInfoModelCollection).orElse(Map.of()) - .entrySet() - .stream() - .filter(entry -> hasAnyDocumentNotFilled(entry.getValue())) - .map(Map.Entry::getKey) - .collect(Collectors.toList()); - - if (!CollectionUtils.isEmpty(shopsToSkip)) { - log.warn("Mandatory documents missing for shop with id [{}] ", String.join(LoggingConstantsUtil.LIST_LOGGING_SEPARATOR, shopsToSkip)); - } - //@formatter:on - } - - private boolean hasAnyDocumentNotFilled( - final List businessStakeHolderInfoModelList) { - return Stream.ofNullable(businessStakeHolderInfoModelList).flatMap(Collection::stream) - .anyMatch(Predicate.not(KYCDocumentBusinessStakeHolderInfoModel::areDocumentsFilled)); + protected List getHyperwalletVerificationDocuments( + KYCDocumentBusinessStakeHolderInfoModel kycBusinessStakeHolderInfoModel) { + return kycBusinessStakeholderDocumentInfoModelToHWVerificationDocumentExecutor + .execute(kycBusinessStakeHolderInfoModel); } } diff --git a/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletBusinessStakeholderExtractServiceMockImpl.java b/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletBusinessStakeholderExtractServiceMockImpl.java index 128fc7db..efe6e829 100644 --- a/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletBusinessStakeholderExtractServiceMockImpl.java +++ b/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletBusinessStakeholderExtractServiceMockImpl.java @@ -1,22 +1,12 @@ package com.paypal.kyc.service.documents.files.hyperwallet.impl; -import com.google.gson.Gson; -import com.hyperwallet.clientsdk.HyperwalletException; -import com.hyperwallet.clientsdk.model.HyperwalletVerificationDocument; -import com.paypal.infrastructure.mail.MailNotificationUtil; -import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; -import com.paypal.kyc.model.KYCDocumentBusinessStakeHolderInfoModel; -import com.paypal.kyc.model.KYCDocumentModel; import com.paypal.kyc.service.HyperwalletSDKService; +import com.paypal.kyc.service.documents.files.hyperwallet.HyperwalletDocumentUploadService; import com.paypal.kyc.strategies.documents.files.hyperwallet.businessstakeholder.impl.KYCBusinessStakeholderDocumentInfoModelToHWVerificationDocumentExecutor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Service; -import org.springframework.web.client.RestTemplate; - -import java.util.*; -import java.util.stream.Collectors; /** * Class that mocks behaviour of sending business stakeholder KYC documents to mockserver @@ -29,77 +19,11 @@ public class HyperwalletBusinessStakeholderExtractServiceMockImpl extends HyperwalletBusinessStakeholderExtractServiceImpl { - private static final String FAILING_FILES = "fail"; - - private final String mockServerUrl; - - private final RestTemplate restTemplate; - - private static final String HYPERWALLET_PUSH_DOCUMENTS = "/hyperwallet/v4/{userToken}/{bstToken}/documents"; - - public HyperwalletBusinessStakeholderExtractServiceMockImpl(final HyperwalletSDKService hyperwalletSDKService, - final KYCBusinessStakeholderDocumentInfoModelToHWVerificationDocumentExecutor kycBusinessStakeholderDocumentInfoModelToHWVerificationDocumentMultipleStrategyFactory, - final MailNotificationUtil kycMailNotificationUtil, @Value("${mockserver.url}") final String mockServerUrl, - final RestTemplate restTemplate) { - super(hyperwalletSDKService, - kycBusinessStakeholderDocumentInfoModelToHWVerificationDocumentMultipleStrategyFactory, - kycMailNotificationUtil); - this.mockServerUrl = mockServerUrl; - this.restTemplate = restTemplate; - } - - /** - * {@inheritDoc} - */ - @Override - protected KYCDocumentBusinessStakeHolderInfoModel callHyperwalletAPI( - final Map.Entry> entry) { - final KYCDocumentBusinessStakeHolderInfoModel kycDocumentBusinessStakeHolderInfoModel = entry.getKey(); - final List hyperwalletVerificationDocuments = entry.getValue(); - - final String postURL = HYPERWALLET_PUSH_DOCUMENTS - .replace("{userToken}", kycDocumentBusinessStakeHolderInfoModel.getUserToken()) - .replace("{bstToken}", kycDocumentBusinessStakeHolderInfoModel.getToken()); - try { - if (checkFailingFiles(hyperwalletVerificationDocuments)) { - throw new HyperwalletException("Something bad happened"); - } - Gson gsonConverter = new Gson(); - restTemplate.postForObject(getMockServerUrl() + postURL, gsonConverter.toJson(entry.getValue()), - Object.class); - log.info("Pushed successfully to mockserver documents [{}] for shopId [{}]", - kycDocumentBusinessStakeHolderInfoModel.getIdentityDocuments().stream() - .map(KYCDocumentModel::getDocumentFieldName).collect(Collectors.joining(",")), - kycDocumentBusinessStakeHolderInfoModel.getClientUserId()); - - return kycDocumentBusinessStakeHolderInfoModel.toBuilder().sentToHyperwallet(true).build(); - } - catch (HyperwalletException ex) { - log.error("Error uploading document to hyperwallet: [{}]", HyperwalletLoggingErrorsUtil.stringify(ex)); - getKycMailNotificationUtil().sendPlainTextEmail("Issue detected pushing documents into Hyperwallet", - String.format( - "Something went wrong pushing documents to Hyperwallet for shop Id [%s] and business stakeholder number [%s]%n%s", - kycDocumentBusinessStakeHolderInfoModel.getClientUserId(), - kycDocumentBusinessStakeHolderInfoModel.getBusinessStakeholderMiraklNumber(), - HyperwalletLoggingErrorsUtil.stringify(ex))); - - return kycDocumentBusinessStakeHolderInfoModel; - } - } - - private boolean checkFailingFiles(final List originalFiles) { - //@formatter:off - return Optional.ofNullable(originalFiles).orElse(List.of()).stream() - .map(HyperwalletVerificationDocument::getUploadFiles) - .filter(Objects::nonNull) - .map(Map::values) - .flatMap(Collection::stream) - .anyMatch(fileName -> fileName.contains(FAILING_FILES)); - //@formatter:on - } - - protected String getMockServerUrl() { - return mockServerUrl; + public HyperwalletBusinessStakeholderExtractServiceMockImpl(HyperwalletSDKService hyperwalletSDKService, + @Qualifier("hyperwalletDocumentUploadServiceMock") HyperwalletDocumentUploadService hyperwalletDocumentUploadService, + KYCBusinessStakeholderDocumentInfoModelToHWVerificationDocumentExecutor kycBusinessStakeholderDocumentInfoModelToHWVerificationDocumentExecutor) { + super(hyperwalletSDKService, hyperwalletDocumentUploadService, + kycBusinessStakeholderDocumentInfoModelToHWVerificationDocumentExecutor); } } diff --git a/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletDocumentUploadServiceImpl.java b/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletDocumentUploadServiceImpl.java new file mode 100644 index 00000000..50e9345a --- /dev/null +++ b/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletDocumentUploadServiceImpl.java @@ -0,0 +1,96 @@ +package com.paypal.kyc.service.documents.files.hyperwallet.impl; + +import com.hyperwallet.clientsdk.Hyperwallet; +import com.hyperwallet.clientsdk.HyperwalletException; +import com.hyperwallet.clientsdk.model.HyperwalletVerificationDocument; +import com.paypal.infrastructure.exceptions.HMCHyperwalletAPIException; +import com.paypal.infrastructure.mail.MailNotificationUtil; +import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; +import com.paypal.infrastructure.util.LoggingConstantsUtil; +import com.paypal.kyc.model.KYCDocumentBusinessStakeHolderInfoModel; +import com.paypal.kyc.model.KYCDocumentInfoModel; +import com.paypal.kyc.model.KYCDocumentSellerInfoModel; +import com.paypal.kyc.service.HyperwalletSDKService; +import com.paypal.kyc.service.documents.files.hyperwallet.HyperwalletDocumentUploadService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +/** + * {@inheritDoc} + */ +@Profile({ "!qa" }) +@Slf4j +@Service +public class HyperwalletDocumentUploadServiceImpl implements HyperwalletDocumentUploadService { + + private final HyperwalletSDKService hyperwalletSDKService; + + private final MailNotificationUtil kycMailNotificationUtil; + + public HyperwalletDocumentUploadServiceImpl(final HyperwalletSDKService hyperwalletSDKService, + final MailNotificationUtil kycMailNotificationUtil) { + this.hyperwalletSDKService = hyperwalletSDKService; + this.kycMailNotificationUtil = kycMailNotificationUtil; + } + + /** + * {@inheritDoc} + */ + @Override + public void uploadDocument(KYCDocumentInfoModel kycDocumentInfoModel, + List hyperwalletVerificationDocuments) { + try { + final Hyperwallet hyperwallet = hyperwalletSDKService + .getHyperwalletInstance(kycDocumentInfoModel.getHyperwalletProgram()); + + invokeHyperwalletAPI(kycDocumentInfoModel, hyperwalletVerificationDocuments, hyperwallet); + + logUploadedDocuments(kycDocumentInfoModel, hyperwalletVerificationDocuments); + } + catch (final HyperwalletException e) { + log.error("Error uploading document to Hyperwallet: [{}]", HyperwalletLoggingErrorsUtil.stringify(e)); + + reportError(kycDocumentInfoModel, e); + + throw new HMCHyperwalletAPIException(e); + } + } + + protected void invokeHyperwalletAPI(KYCDocumentInfoModel kycDocumentInfoModel, + List hyperwalletVerificationDocuments, Hyperwallet hyperwallet) { + if (kycDocumentInfoModel instanceof KYCDocumentBusinessStakeHolderInfoModel) { + KYCDocumentBusinessStakeHolderInfoModel kycDocumentBusinessStakeHolderInfoModel = (KYCDocumentBusinessStakeHolderInfoModel) kycDocumentInfoModel; + hyperwallet.uploadStakeholderDocuments(kycDocumentInfoModel.getUserToken(), + kycDocumentBusinessStakeHolderInfoModel.getToken(), hyperwalletVerificationDocuments); + } + else { + KYCDocumentSellerInfoModel kycDocumentSellerInfoModel = (KYCDocumentSellerInfoModel) kycDocumentInfoModel; + hyperwallet.uploadUserDocuments(kycDocumentSellerInfoModel.getUserToken(), + hyperwalletVerificationDocuments); + } + } + + private void reportError(KYCDocumentInfoModel kycDocumentInfoModel, HyperwalletException e) { + kycMailNotificationUtil.sendPlainTextEmail("Issue detected pushing documents into Hyperwallet", + String.format("Something went wrong pushing documents to Hyperwallet for %s%n%s", + kycDocumentInfoModel.getDocumentTracingIdentifier(), + HyperwalletLoggingErrorsUtil.stringify(e))); + } + + protected void logUploadedDocuments(final KYCDocumentInfoModel kycDocumentInfoModel, + final List hyperwalletVerificationDocuments) { + + final String documentsToUpload = hyperwalletVerificationDocuments.stream() + .map(hyperwalletVerificationDocument -> hyperwalletVerificationDocument.getUploadFiles().keySet()) + .flatMap(Collection::stream).collect(Collectors.joining(LoggingConstantsUtil.LIST_LOGGING_SEPARATOR)); + + log.info("Documents [{}] uploaded for {}", documentsToUpload, + kycDocumentInfoModel.getDocumentTracingIdentifier()); + } + +} diff --git a/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletDocumentUploadServiceMockImpl.java b/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletDocumentUploadServiceMockImpl.java new file mode 100644 index 00000000..3c4349de --- /dev/null +++ b/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletDocumentUploadServiceMockImpl.java @@ -0,0 +1,88 @@ +package com.paypal.kyc.service.documents.files.hyperwallet.impl; + +import com.google.gson.Gson; +import com.hyperwallet.clientsdk.Hyperwallet; +import com.hyperwallet.clientsdk.HyperwalletException; +import com.hyperwallet.clientsdk.model.HyperwalletVerificationDocument; +import com.paypal.infrastructure.mail.MailNotificationUtil; +import com.paypal.kyc.model.KYCDocumentBusinessStakeHolderInfoModel; +import com.paypal.kyc.model.KYCDocumentInfoModel; +import com.paypal.kyc.model.KYCDocumentSellerInfoModel; +import com.paypal.kyc.service.HyperwalletSDKService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.util.*; + +/** + * Class that mocks behaviour of sending KYC documents to mockserver instead of sending + * them to HW + */ +@Profile({ "qa" }) +@Slf4j +@Service("hyperwalletDocumentUploadServiceMock") +public class HyperwalletDocumentUploadServiceMockImpl extends HyperwalletDocumentUploadServiceImpl { + + private static final String FAILING_FILES = "fail"; + + private static final String HYPERWALLET_PUSH_DOCUMENTS_BSTK = "/hyperwallet/v4/{userToken}/{bstToken}/documents"; + + private static final String HYPERWALLET_PUSH_DOCUMENTS_SELLER = "/hyperwallet/v4/{userToken}/documents"; + + private final String mockServerUrl; + + private final RestTemplate restTemplate; + + public HyperwalletDocumentUploadServiceMockImpl(HyperwalletSDKService hyperwalletSDKService, + MailNotificationUtil kycMailNotificationUtil, @Value("${mockserver.url}") String mockServerUrl, + RestTemplate restTemplate) { + super(hyperwalletSDKService, kycMailNotificationUtil); + this.mockServerUrl = mockServerUrl; + this.restTemplate = restTemplate; + } + + @Override + protected void invokeHyperwalletAPI(KYCDocumentInfoModel kycDocumentInfoModel, + List hyperwalletVerificationDocuments, Hyperwallet hyperwallet) { + final String postURL = getPostURL(kycDocumentInfoModel); + + if (checkFailingFiles(hyperwalletVerificationDocuments)) { + throw new HyperwalletException("Something bad happened"); + } + Gson gsonConverter = new Gson(); + restTemplate.postForObject(getMockServerUrl() + postURL, gsonConverter.toJson(hyperwalletVerificationDocuments), + Object.class); + } + + private String getPostURL(KYCDocumentInfoModel kycDocumentInfoModel) { + if (kycDocumentInfoModel instanceof KYCDocumentBusinessStakeHolderInfoModel) { + KYCDocumentBusinessStakeHolderInfoModel kycDocumentBusinessStakeHolderInfoModel = (KYCDocumentBusinessStakeHolderInfoModel) kycDocumentInfoModel; + return HYPERWALLET_PUSH_DOCUMENTS_BSTK + .replace("{userToken}", kycDocumentBusinessStakeHolderInfoModel.getUserToken()) + .replace("{bstToken}", kycDocumentBusinessStakeHolderInfoModel.getToken()); + } + else { + KYCDocumentSellerInfoModel kycDocumentSellerInfoModel = (KYCDocumentSellerInfoModel) kycDocumentInfoModel; + return HYPERWALLET_PUSH_DOCUMENTS_SELLER.replace("{userToken}", kycDocumentSellerInfoModel.getUserToken()); + } + } + + private boolean checkFailingFiles(final List originalFiles) { + //@formatter:off + return Optional.ofNullable(originalFiles).orElse(List.of()).stream() + .map(HyperwalletVerificationDocument::getUploadFiles) + .filter(Objects::nonNull) + .map(Map::values) + .flatMap(Collection::stream) + .anyMatch(fileName -> fileName.contains(FAILING_FILES)); + //@formatter:on + } + + protected String getMockServerUrl() { + return mockServerUrl; + } + +} diff --git a/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletSellerExtractServiceImpl.java b/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletSellerExtractServiceImpl.java index 9b49c041..089d429a 100644 --- a/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletSellerExtractServiceImpl.java +++ b/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletSellerExtractServiceImpl.java @@ -1,30 +1,17 @@ package com.paypal.kyc.service.documents.files.hyperwallet.impl; -import com.hyperwallet.clientsdk.Hyperwallet; -import com.hyperwallet.clientsdk.HyperwalletException; import com.hyperwallet.clientsdk.model.HyperwalletVerificationDocument; -import com.paypal.infrastructure.mail.MailNotificationUtil; -import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; -import com.paypal.infrastructure.util.LoggingConstantsUtil; -import com.paypal.kyc.model.KYCDocumentInfoModel; import com.paypal.kyc.model.KYCDocumentSellerInfoModel; import com.paypal.kyc.service.HyperwalletSDKService; +import com.paypal.kyc.service.documents.files.hyperwallet.HyperwalletDocumentUploadService; import com.paypal.kyc.service.documents.files.hyperwallet.HyperwalletSellerExtractService; import com.paypal.kyc.strategies.documents.files.hyperwallet.seller.impl.KYCDocumentInfoToHWVerificationDocumentExecutor; import lombok.Getter; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.ObjectUtils; -import org.apache.commons.lang3.tuple.Pair; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Service; -import org.springframework.util.CollectionUtils; -import java.util.Collection; import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.Predicate; -import java.util.stream.Collectors; /** * Implementation of {@link HyperwalletSellerExtractService} @@ -33,88 +20,23 @@ @Slf4j @Getter @Service -public class HyperwalletSellerExtractServiceImpl implements HyperwalletSellerExtractService { - - private final HyperwalletSDKService hyperwalletSDKService; - - private final MailNotificationUtil kycMailNotificationUtil; +public class HyperwalletSellerExtractServiceImpl + extends AbstractHyperwalletDocumentExtractService + implements HyperwalletSellerExtractService { private final KYCDocumentInfoToHWVerificationDocumentExecutor kycDocumentInfoToHWVerificationDocumentExecutor; - public HyperwalletSellerExtractServiceImpl( - final KYCDocumentInfoToHWVerificationDocumentExecutor kycDocumentInfoToHWVerificationDocumentExecutor, - final HyperwalletSDKService hyperwalletSDKService, final MailNotificationUtil kycMailNotificationUtil) { - this.hyperwalletSDKService = hyperwalletSDKService; - this.kycMailNotificationUtil = kycMailNotificationUtil; + public HyperwalletSellerExtractServiceImpl(HyperwalletSDKService hyperwalletSDKService, + HyperwalletDocumentUploadService hyperwalletDocumentUploadService, + KYCDocumentInfoToHWVerificationDocumentExecutor kycDocumentInfoToHWVerificationDocumentExecutor) { + super(hyperwalletSDKService, hyperwalletDocumentUploadService); this.kycDocumentInfoToHWVerificationDocumentExecutor = kycDocumentInfoToHWVerificationDocumentExecutor; } - /** - * {@inheritDoc} - */ @Override - public List pushProofOfIdentityAndBusinessSellerDocuments( - final List kycDocumentSellerInfoModelList) { - //@formatter:off - printShopsToSkip(kycDocumentSellerInfoModelList); - final Map> kycDocumentInfoModelListMap = kycDocumentSellerInfoModelList - .stream() - .filter(KYCDocumentSellerInfoModel::areDocumentsFilled) - .map(kycDocumentInfoModel -> Pair.of(kycDocumentInfoModel, - kycDocumentInfoToHWVerificationDocumentExecutor.execute(kycDocumentInfoModel))) - .collect(Collectors.toMap(Pair::getLeft, Pair::getRight)); - //@formatter:on - - //@formatter:off - return kycDocumentInfoModelListMap.entrySet() - .stream() - .filter(kycDocumentInfoModelListEntry -> ObjectUtils.isNotEmpty(kycDocumentInfoModelListEntry.getValue())) - .map(this::callHyperwalletAPI) - .filter(Objects::nonNull) - .map(document -> document.toBuilder().sentToHyperwallet(true).build()) - .collect(Collectors.toList()); - //@formatter:on - } - - /** - * {@inheritDoc} - */ - protected KYCDocumentSellerInfoModel callHyperwalletAPI( - final Map.Entry> entry) { - final KYCDocumentSellerInfoModel kycDocumentSellerInfoModel = entry.getKey(); - final String documentsToUpload = entry.getValue().stream() - .map(hyperwalletVerificationDocument -> hyperwalletVerificationDocument.getUploadFiles().keySet()) - .flatMap(Collection::stream).collect(Collectors.joining(LoggingConstantsUtil.LIST_LOGGING_SEPARATOR)); - try { - - final Hyperwallet hyperwallet = hyperwalletSDKService - .getHyperwalletInstance(kycDocumentSellerInfoModel.getHyperwalletProgram()); - hyperwallet.uploadUserDocuments(kycDocumentSellerInfoModel.getUserToken(), entry.getValue()); - log.info("Documents [{}] uploaded for shop with id [{}]", documentsToUpload, - kycDocumentSellerInfoModel.getClientUserId()); - return kycDocumentSellerInfoModel; - } - catch (final HyperwalletException e) { - log.error("Error uploading document to hyperwallet: [{}]", HyperwalletLoggingErrorsUtil.stringify(e)); - kycMailNotificationUtil.sendPlainTextEmail("Issue detected pushing documents into Hyperwallet", - String.format("Something went wrong pushing documents to Hyperwallet for shop Id [%s]%n%s", - kycDocumentSellerInfoModel.getClientUserId(), HyperwalletLoggingErrorsUtil.stringify(e))); - return null; - } - } - - private void printShopsToSkip(final List kycDocumentInfoModelCollection) { - //@formatter:off - final List shopsToSkip = kycDocumentInfoModelCollection.stream() - .filter(Predicate.not(KYCDocumentSellerInfoModel::areDocumentsFilled)) - .collect(Collectors.toList()); - if (!CollectionUtils.isEmpty(shopsToSkip)) { - log.warn("Mandatory documents missing for shop with id [{}] ", - shopsToSkip.stream() - .map(KYCDocumentInfoModel::getClientUserId) - .collect(Collectors.joining(LoggingConstantsUtil.LIST_LOGGING_SEPARATOR))); - } - //@formatter:on + protected List getHyperwalletVerificationDocuments( + KYCDocumentSellerInfoModel kycDocumentSellerInfoModel) { + return kycDocumentInfoToHWVerificationDocumentExecutor.execute(kycDocumentSellerInfoModel); } } diff --git a/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletSellerExtractServiceMockImpl.java b/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletSellerExtractServiceMockImpl.java index c7b0b283..ab2f2ece 100644 --- a/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletSellerExtractServiceMockImpl.java +++ b/kyc/src/main/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletSellerExtractServiceMockImpl.java @@ -1,20 +1,12 @@ package com.paypal.kyc.service.documents.files.hyperwallet.impl; -import com.google.gson.Gson; -import com.hyperwallet.clientsdk.HyperwalletException; -import com.hyperwallet.clientsdk.model.HyperwalletVerificationDocument; -import com.paypal.infrastructure.mail.MailNotificationUtil; -import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; -import com.paypal.kyc.model.KYCDocumentSellerInfoModel; import com.paypal.kyc.service.HyperwalletSDKService; +import com.paypal.kyc.service.documents.files.hyperwallet.HyperwalletDocumentUploadService; import com.paypal.kyc.strategies.documents.files.hyperwallet.seller.impl.KYCDocumentInfoToHWVerificationDocumentExecutor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Profile; import org.springframework.stereotype.Service; -import org.springframework.web.client.RestTemplate; - -import java.util.*; /** * Class that mocks behaviour of sending seller KYC documents to mockserver instead of @@ -25,68 +17,10 @@ @Service("hyperwalletSellerExtractService") public class HyperwalletSellerExtractServiceMockImpl extends HyperwalletSellerExtractServiceImpl { - private static final String FAILING_FILES = "fail"; - - private final String mockServerUrl; - - private final RestTemplate restTemplate; - - private static final String HYPERWALLET_PUSH_DOCUMENTS = "/hyperwallet/v4/{userToken}/documents"; - - public HyperwalletSellerExtractServiceMockImpl( - final KYCDocumentInfoToHWVerificationDocumentExecutor kycDocumentInfoToHWVerificationDocumentMultipleStrategyFactory, - @Value("${mockserver.url}") final String mockServerUrl, final RestTemplate restTemplate, - final MailNotificationUtil kycMailNotificationUtil, final HyperwalletSDKService hyperwalletSDKService) { - super(kycDocumentInfoToHWVerificationDocumentMultipleStrategyFactory, hyperwalletSDKService, - kycMailNotificationUtil); - this.mockServerUrl = mockServerUrl; - this.restTemplate = restTemplate; - } - - @Override - protected KYCDocumentSellerInfoModel callHyperwalletAPI( - final Map.Entry> entry) { - final KYCDocumentSellerInfoModel kycDocumentSellerInfoModel = entry.getKey(); - final List hyperwalletVerificationDocuments = entry.getValue(); - - final String postURL = HYPERWALLET_PUSH_DOCUMENTS.replace("{userToken}", - kycDocumentSellerInfoModel.getUserToken()); - try { - if (checkFailingFiles(hyperwalletVerificationDocuments)) { - throw new HyperwalletException("Something bad happened"); - } - Gson gsonConverter = new Gson(); - restTemplate.postForObject(getMockServerUrl() + postURL, gsonConverter.toJson(entry.getValue()), - Object.class); - log.info("Pushed successfully to mockserver documents for shopId [{}]", - kycDocumentSellerInfoModel.getClientUserId()); - - return kycDocumentSellerInfoModel; - } - catch (HyperwalletException ex) { - log.error("Error uploading document to hyperwallet: [{}]", HyperwalletLoggingErrorsUtil.stringify(ex)); - getKycMailNotificationUtil().sendPlainTextEmail("Issue detected pushing documents into Hyperwallet", - String.format("Something went wrong pushing documents to Hyperwallet for shop Id [%s]%n%s", - String.join(",", kycDocumentSellerInfoModel.getClientUserId()), - HyperwalletLoggingErrorsUtil.stringify(ex))); - - return null; - } - } - - private boolean checkFailingFiles(final List originalFiles) { - //@formatter:off - return Optional.ofNullable(originalFiles).orElse(List.of()).stream() - .map(HyperwalletVerificationDocument::getUploadFiles) - .filter(Objects::nonNull) - .map(Map::values) - .flatMap(Collection::stream) - .anyMatch(fileName -> fileName.contains(FAILING_FILES)); - //@formatter:on - } - - protected String getMockServerUrl() { - return mockServerUrl; + public HyperwalletSellerExtractServiceMockImpl(HyperwalletSDKService hyperwalletSDKService, + @Qualifier("hyperwalletDocumentUploadServiceMock") HyperwalletDocumentUploadService hyperwalletDocumentUploadService, + KYCDocumentInfoToHWVerificationDocumentExecutor kycDocumentInfoToHWVerificationDocumentExecutor) { + super(hyperwalletSDKService, hyperwalletDocumentUploadService, kycDocumentInfoToHWVerificationDocumentExecutor); } } diff --git a/kyc/src/main/java/com/paypal/kyc/service/documents/files/mirakl/MiraklBusinessStakeholderDocumentsExtractService.java b/kyc/src/main/java/com/paypal/kyc/service/documents/files/mirakl/MiraklBusinessStakeholderDocumentsExtractService.java index 4b64c8f9..0df6b81f 100644 --- a/kyc/src/main/java/com/paypal/kyc/service/documents/files/mirakl/MiraklBusinessStakeholderDocumentsExtractService.java +++ b/kyc/src/main/java/com/paypal/kyc/service/documents/files/mirakl/MiraklBusinessStakeholderDocumentsExtractService.java @@ -1,11 +1,9 @@ package com.paypal.kyc.service.documents.files.mirakl; -import com.mirakl.client.mmp.operator.domain.shop.update.MiraklUpdatedShops; import com.paypal.kyc.model.KYCDocumentBusinessStakeHolderInfoModel; import java.util.Date; import java.util.List; -import java.util.Optional; /** * Interface that manages logic of getting business stakeholder information related to KYC @@ -34,13 +32,11 @@ List getKYCCustomValuesRequiredVerificationBusinessStakeholders(String s /** * Sets KYC required verification flag for business stakeholder to false in Mirakl - * @param correctlySentBusinessStakeholderDocuments - * {@link List} of all business stakeholder - * to be unchecked from KYC verification - * @return {@link Optional} if everything was fine. Otherwise - * empty. + * @param correctlySentBusinessStakeholderDocument + * {@link KYCDocumentBusinessStakeHolderInfoModel} a business stakeholder to be + * unchecked from KYC verification. */ - Optional setBusinessStakeholderFlagKYCToPushBusinessStakeholderDocumentsToFalse( - List correctlySentBusinessStakeholderDocuments); + void setBusinessStakeholderFlagKYCToPushBusinessStakeholderDocumentsToFalse( + KYCDocumentBusinessStakeHolderInfoModel correctlySentBusinessStakeholderDocument); } diff --git a/kyc/src/main/java/com/paypal/kyc/service/documents/files/mirakl/MiraklSellerDocumentsExtractService.java b/kyc/src/main/java/com/paypal/kyc/service/documents/files/mirakl/MiraklSellerDocumentsExtractService.java index 98458cbe..0b6d3b93 100644 --- a/kyc/src/main/java/com/paypal/kyc/service/documents/files/mirakl/MiraklSellerDocumentsExtractService.java +++ b/kyc/src/main/java/com/paypal/kyc/service/documents/files/mirakl/MiraklSellerDocumentsExtractService.java @@ -1,13 +1,11 @@ package com.paypal.kyc.service.documents.files.mirakl; -import com.mirakl.client.mmp.operator.domain.shop.update.MiraklUpdatedShops; import com.paypal.kyc.model.KYCDocumentBusinessStakeHolderInfoModel; import com.paypal.kyc.model.KYCDocumentInfoModel; import com.paypal.kyc.model.KYCDocumentSellerInfoModel; import java.util.Date; import java.util.List; -import java.util.Optional; /** * Interface that manages logic of getting seller information related to KYC in Mirakl @@ -34,12 +32,10 @@ public interface MiraklSellerDocumentsExtractService extends MiraklDocumentsExtr /** * Sets KYC required verification proof of identity/business flag for seller to false * in Mirakl - * @param successFullPushedListOfDocuments {@link List} of - * all seller to be unchecked from KYC verification - * @return {@link Optional} if everything was fine. Otherwise - * empty. + * @param successFullPushedListOfDocument {@link KYCDocumentSellerInfoModel} seller to + * be unchecked from KYC verification */ - Optional setFlagToPushProofOfIdentityAndBusinessSellerDocumentsToFalse( - List successFullPushedListOfDocuments); + void setFlagToPushProofOfIdentityAndBusinessSellerDocumentsToFalse( + KYCDocumentSellerInfoModel successFullPushedListOfDocument); } diff --git a/kyc/src/main/java/com/paypal/kyc/service/documents/files/mirakl/impl/AbstractMiraklDocumentExtractServiceImpl.java b/kyc/src/main/java/com/paypal/kyc/service/documents/files/mirakl/impl/AbstractMiraklDocumentExtractServiceImpl.java index 00e677e7..9831120e 100644 --- a/kyc/src/main/java/com/paypal/kyc/service/documents/files/mirakl/impl/AbstractMiraklDocumentExtractServiceImpl.java +++ b/kyc/src/main/java/com/paypal/kyc/service/documents/files/mirakl/impl/AbstractMiraklDocumentExtractServiceImpl.java @@ -1,8 +1,11 @@ package com.paypal.kyc.service.documents.files.mirakl.impl; +import com.mirakl.client.core.exception.MiraklException; import com.mirakl.client.mmp.domain.shop.document.MiraklShopDocument; import com.mirakl.client.mmp.operator.core.MiraklMarketplacePlatformOperatorApiClient; import com.mirakl.client.mmp.request.shop.document.MiraklDeleteShopDocumentRequest; +import com.paypal.infrastructure.mail.MailNotificationUtil; +import com.paypal.infrastructure.util.MiraklLoggingErrorsUtil; import com.paypal.kyc.model.KYCDocumentInfoModel; import com.paypal.kyc.service.documents.files.mirakl.MiraklDocumentsExtractService; import lombok.extern.slf4j.Slf4j; @@ -18,9 +21,13 @@ public abstract class AbstractMiraklDocumentExtractServiceImpl implements Mirakl private final MiraklMarketplacePlatformOperatorApiClient miraklOperatorClient; + private final MailNotificationUtil kycMailNotificationUtil; + protected AbstractMiraklDocumentExtractServiceImpl( - final MiraklMarketplacePlatformOperatorApiClient miraklOperatorClient) { + final MiraklMarketplacePlatformOperatorApiClient miraklOperatorClient, + final MailNotificationUtil kycMailNotificationUtil) { this.miraklOperatorClient = miraklOperatorClient; + this.kycMailNotificationUtil = kycMailNotificationUtil; } /** @@ -59,4 +66,11 @@ public void deleteDocuments(final List documentsToBeDeleted) .forEach(miraklOperatorClient::deleteShopDocument); } + protected void reportError(final String shopIdentifier, final MiraklException e) { + + kycMailNotificationUtil.sendPlainTextEmail("Issue setting push document flags to false in Mirakl", + String.format("Something went wrong setting push document flag to false in Mirakl for %s%n%s", + shopIdentifier, MiraklLoggingErrorsUtil.stringify(e))); + } + } diff --git a/kyc/src/main/java/com/paypal/kyc/service/documents/files/mirakl/impl/MiraklBusinessStakeholderDocumentsExtractServiceImpl.java b/kyc/src/main/java/com/paypal/kyc/service/documents/files/mirakl/impl/MiraklBusinessStakeholderDocumentsExtractServiceImpl.java index f067cda6..7314bb4e 100644 --- a/kyc/src/main/java/com/paypal/kyc/service/documents/files/mirakl/impl/MiraklBusinessStakeholderDocumentsExtractServiceImpl.java +++ b/kyc/src/main/java/com/paypal/kyc/service/documents/files/mirakl/impl/MiraklBusinessStakeholderDocumentsExtractServiceImpl.java @@ -13,9 +13,9 @@ import com.mirakl.client.mmp.request.additionalfield.MiraklRequestAdditionalFieldValue; import com.mirakl.client.mmp.request.shop.MiraklGetShopsRequest; import com.paypal.infrastructure.converter.Converter; +import com.paypal.infrastructure.exceptions.HMCMiraklAPIException; import com.paypal.infrastructure.mail.MailNotificationUtil; import com.paypal.infrastructure.util.LoggingConstantsUtil; -import com.paypal.infrastructure.util.MiraklLoggingErrorsUtil; import com.paypal.kyc.converter.KYCBusinessStakeHolderConverter; import com.paypal.kyc.model.KYCDocumentBusinessStakeHolderInfoModel; import com.paypal.kyc.model.KYCDocumentInfoModel; @@ -50,20 +50,17 @@ public class MiraklBusinessStakeholderDocumentsExtractServiceImpl extends Abstra private final MiraklMarketplacePlatformOperatorApiClient miraklOperatorClient; - private final MailNotificationUtil kycMailNotificationUtil; - public MiraklBusinessStakeholderDocumentsExtractServiceImpl( final MiraklBusinessStakeholderDocumentDownloadExtractService miraklBusinessStakeholderDocumentDownloadExtractService, final Converter miraklGetShopsRequestConverter, final KYCBusinessStakeHolderConverter kycBusinessStakeHolderConverter, final MiraklMarketplacePlatformOperatorApiClient miraklOperatorClient, final MailNotificationUtil kycMailNotificationUtil) { - super(miraklOperatorClient); + super(miraklOperatorClient, kycMailNotificationUtil); this.miraklBusinessStakeholderDocumentDownloadExtractService = miraklBusinessStakeholderDocumentDownloadExtractService; this.miraklGetShopsRequestConverter = miraklGetShopsRequestConverter; this.kycBusinessStakeHolderConverter = kycBusinessStakeHolderConverter; this.miraklOperatorClient = miraklOperatorClient; - this.kycMailNotificationUtil = kycMailNotificationUtil; } /** @@ -76,32 +73,32 @@ public List extractBusinessStakeholderD final MiraklShops shops = miraklOperatorClient.getShops(miraklGetShopsRequest); //@formatter:off - log.info("Retrieved modified shops since [{}]: [{}]", delta, - Stream.ofNullable(shops.getShops()) - .flatMap(Collection::stream) - .map(MiraklShop::getId) - .collect(Collectors.joining(LoggingConstantsUtil.LIST_LOGGING_SEPARATOR))); - //@formatter:on + log.info("Retrieved modified shops since [{}]: [{}]", delta, + Stream.ofNullable(shops.getShops()) + .flatMap(Collection::stream) + .map(MiraklShop::getId) + .collect(Collectors.joining(LoggingConstantsUtil.LIST_LOGGING_SEPARATOR))); + //@formatter:on //@formatter:off - final List kycBusinessStakeHolderInfoModelList = Stream.ofNullable(shops.getShops()) - .flatMap(Collection::stream) - .map(this::populateBusinessStakeholderForMiraklShop) - .flatMap(Collection::stream) - .collect(Collectors.toList()); - //@formatter:on + final List kycBusinessStakeHolderInfoModelList = Stream.ofNullable(shops.getShops()) + .flatMap(Collection::stream) + .map(this::populateBusinessStakeholderForMiraklShop) + .flatMap(Collection::stream) + .collect(Collectors.toList()); + //@formatter:on //@formatter:off - final Map> shopsWithBusinessStakeholderVerificationRequired = kycBusinessStakeHolderInfoModelList.stream() - .filter(kycDocStk -> kycDocStk.isRequiresKYC() || kycDocStk.isRequiresLetterOfAuthorization()) - .collect(Collectors.groupingBy(KYCDocumentInfoModel::getClientUserId)); - //@formatter:on + final Map> shopsWithBusinessStakeholderVerificationRequired = kycBusinessStakeHolderInfoModelList.stream() + .filter(kycDocStk -> kycDocStk.isRequiresKYC() || kycDocStk.isRequiresLetterOfAuthorization()) + .collect(Collectors.groupingBy(KYCDocumentInfoModel::getClientUserId)); + //@formatter:on if (!CollectionUtils.isEmpty(shopsWithBusinessStakeholderVerificationRequired)) { //@formatter:off - log.info("Shops with KYC business stakeholder verification required: [{}]", - String.join(LoggingConstantsUtil.LIST_LOGGING_SEPARATOR, shopsWithBusinessStakeholderVerificationRequired.keySet())); - //@formatter:on + log.info("Shops with KYC business stakeholder verification required: [{}]", + String.join(LoggingConstantsUtil.LIST_LOGGING_SEPARATOR, shopsWithBusinessStakeholderVerificationRequired.keySet())); + //@formatter:on } skipShopsWithNonBusinessStakeholderSelectedDocuments(shopsWithBusinessStakeholderVerificationRequired); @@ -113,40 +110,32 @@ public List extractBusinessStakeholderD .flatMap(Collection::stream).collect(Collectors.toList()); //@formatter:off - return shopsWithBusinessSelectedVerificationDocuments.stream() - .filter(kycBusinessStakeHolderInfoModel -> !ObjectUtils.isEmpty(kycBusinessStakeHolderInfoModel.getUserToken())) - .map(miraklBusinessStakeholderDocumentDownloadExtractService::getBusinessStakeholderDocumentsSelectedBySeller) - .collect(Collectors.toList()); - //@formatter:on + return shopsWithBusinessSelectedVerificationDocuments.stream() + .filter(kycBusinessStakeHolderInfoModel -> !ObjectUtils.isEmpty(kycBusinessStakeHolderInfoModel.getUserToken())) + .map(miraklBusinessStakeholderDocumentDownloadExtractService::getBusinessStakeholderDocumentsSelectedBySeller) + .collect(Collectors.toList()); + //@formatter:on } /** * {@inheritDoc} */ @Override - public Optional setBusinessStakeholderFlagKYCToPushBusinessStakeholderDocumentsToFalse( - final List successfullyPushedListOfDocuments) { - - if (CollectionUtils.isEmpty(successfullyPushedListOfDocuments)) { - return Optional.empty(); - } + public void setBusinessStakeholderFlagKYCToPushBusinessStakeholderDocumentsToFalse( + final KYCDocumentBusinessStakeHolderInfoModel successfullyPushedListOfDocument) { - final Map> kycFlagToFalse = successfullyPushedListOfDocuments - .stream().filter(KYCDocumentBusinessStakeHolderInfoModel::isSentToHyperwallet) - .collect(Collectors.groupingBy(KYCDocumentBusinessStakeHolderInfoModel::getClientUserId)); - - return miraklUpdateKYCShopCall(kycFlagToFalse); + miraklUpdateKYCShopCall(successfullyPushedListOfDocument); } private List populateBusinessStakeholderForMiraklShop( final MiraklShop miraklShop) { //@formatter:off - return IntStream.range(1, 6) - .mapToObj(i -> kycBusinessStakeHolderConverter.convert(miraklShop, i)) - .filter(Objects::nonNull) - .filter(Predicate.not(KYCDocumentBusinessStakeHolderInfoModel::isEmpty)) - .collect(Collectors.toCollection(ArrayList::new)); - //@formatter:on + return IntStream.range(1, 6) + .mapToObj(i -> kycBusinessStakeHolderConverter.convert(miraklShop, i)) + .filter(Objects::nonNull) + .filter(Predicate.not(KYCDocumentBusinessStakeHolderInfoModel::isEmpty)) + .collect(Collectors.toCollection(ArrayList::new)); + //@formatter:on } private Optional extractMiraklShop(final String shopId) { @@ -168,17 +157,17 @@ public List getKYCCustomValuesRequiredVerificationBusinessStakeholders(f if (Objects.nonNull(shopId) && !CollectionUtils.isEmpty(requiredVerificationBusinessStakeholderTokens)) { final Optional miraklShop = extractMiraklShop(shopId); //@formatter:off - final List requiredVerificationBusinessStakeHolderCodes = miraklShop - .map(AbstractMiraklShop::getAdditionalFieldValues).stream() - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .filter(element -> element.getCode().contains(HYPERWALLET_PREFIX + STAKEHOLDER_PREFIX + STAKEHOLDER_TOKEN_PREFIX)) - .filter(MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue.class::isInstance) - .map(MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue.class::cast) - .filter(element -> requiredVerificationBusinessStakeholderTokens.contains(element.getValue())) - .map(MiraklAdditionalFieldValue::getCode) - .collect(Collectors.toList()); - //@formatter:on + final List requiredVerificationBusinessStakeHolderCodes = miraklShop + .map(AbstractMiraklShop::getAdditionalFieldValues).stream() + .filter(Objects::nonNull) + .flatMap(Collection::stream) + .filter(element -> element.getCode().contains(HYPERWALLET_PREFIX + STAKEHOLDER_PREFIX + STAKEHOLDER_TOKEN_PREFIX)) + .filter(MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue.class::isInstance) + .map(MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue.class::cast) + .filter(element -> requiredVerificationBusinessStakeholderTokens.contains(element.getValue())) + .map(MiraklAdditionalFieldValue::getCode) + .collect(Collectors.toList()); + //@formatter:on return Optional.of(requiredVerificationBusinessStakeHolderCodes).orElse(List.of()).stream() .map(requiredVerificationBusinessStakeHolderCode -> HYPERWALLET_PREFIX + STAKEHOLDER_PREFIX + REQUIRED_PROOF_IDENTITY.concat(requiredVerificationBusinessStakeHolderCode @@ -201,66 +190,74 @@ private void skipShopsWithNonBusinessStakeholderSelectedDocuments( if (!CollectionUtils.isEmpty(shopsWithNotAllBstkDocumentsSelected)) { //@formatter:off - shopsWithNotAllBstkDocumentsSelected.forEach((key, value) -> - log.warn("Skipping shop with id [{}] because business stakeholders with following numbers has not selected a document for uploading [{}]", key, value)); - //@formatter:on + shopsWithNotAllBstkDocumentsSelected.forEach((key, value) -> + log.warn("Skipping shop with id [{}] because business stakeholders with following numbers has not selected a document for uploading [{}]", key, value)); + //@formatter:on } } - private Optional miraklUpdateKYCShopCall( - final Map> shopsToUpdate) { - if (CollectionUtils.isEmpty(shopsToUpdate)) { - return Optional.empty(); - } + private void miraklUpdateKYCShopCall(final KYCDocumentBusinessStakeHolderInfoModel shopToUpdate) { - final List miraklShopsToUpdate = shopsToUpdate.entrySet().stream() - .map(this::getMiraklUpdateShopWithProofOfDocumentFields).collect(Collectors.toList()); + final MiraklUpdateShop miraklShopToUpdate = getMiraklUpdateShopWithProofOfDocumentFields(shopToUpdate); + final MiraklUpdateShopsRequest miraklUpdateShopRequest = new MiraklUpdateShopsRequest( + List.of(miraklShopToUpdate)); - final MiraklUpdateShopsRequest miraklUpdateShopRequest = new MiraklUpdateShopsRequest(miraklShopsToUpdate); try { + final MiraklUpdatedShops miraklUpdatedShops = miraklOperatorClient.updateShops(miraklUpdateShopRequest); - //@formatter:on - log.info("Setting required KYC and letter of authorisation flag for shops with ids [{}] to false", - miraklUpdatedShops.getShopReturns().stream().map(MiraklUpdatedShopReturn::getShopUpdated) - .map(MiraklShop::getId) - .collect(Collectors.joining(LoggingConstantsUtil.LIST_LOGGING_SEPARATOR))); - return Optional.of(miraklUpdatedShops); - //@formatter:off + logUpdatedShops(miraklUpdatedShops); - } catch (final MiraklException e) { - log.error("Something went wrong when removing flag to retrieve documents for shops [{}]", String.join(",", shopsToUpdate.keySet())); - kycMailNotificationUtil.sendPlainTextEmail("Issue setting push document flags to false in Mirakl", - String.format("Something went wrong setting push document flag to false in Mirakl for shop Id [%s]%n%s", - String.join(",", shopsToUpdate.keySet()), - MiraklLoggingErrorsUtil.stringify(e))); } + catch (final MiraklException e) { + + log.error("Something went wrong when removing flag to retrieve documents for shop [{}]", + shopToUpdate.getClientUserId()); + + reportError(shopToUpdate.getDocumentTracingIdentifier(), e); - return Optional.empty(); + throw new HMCMiraklAPIException(e); + } } - private MiraklUpdateShop getMiraklUpdateShopWithProofOfDocumentFields(final Map.Entry> entry) { - final MiraklUpdateShop miraklUpdateShop = new MiraklUpdateShop(); - miraklUpdateShop.setShopId(Long.valueOf(entry.getKey())); + private void logUpdatedShops(final MiraklUpdatedShops miraklUpdatedShops) { - //@formatter:off - final List additionalValues = entry.getValue().stream() - .filter(KYCDocumentBusinessStakeHolderInfoModel::isRequiresKYC) - .map(businessStakeholder -> new MiraklRequestAdditionalFieldValue.MiraklSimpleRequestAdditionalFieldValue( - HYPERWALLET_PREFIX + STAKEHOLDER_PREFIX + REQUIRED_PROOF_IDENTITY - + businessStakeholder.getBusinessStakeholderMiraklNumber(), - Boolean.FALSE.toString().toLowerCase())) - .collect(Collectors.toList()); - - additionalValues.addAll(entry.getValue().stream() - .filter(KYCDocumentBusinessStakeHolderInfoModel::isRequiresLetterOfAuthorization) - .map(businessStakeholder -> new MiraklRequestAdditionalFieldValue.MiraklSimpleRequestAdditionalFieldValue( - HYPERWALLET_KYC_REQUIRED_PROOF_AUTHORIZATION_BUSINESS_FIELD, - Boolean.FALSE.toString().toLowerCase())) - .collect(Collectors.toList())); //@formatter:on + log.info("Setting required KYC and letter of authorisation flag for shop with id [{}] to false", + miraklUpdatedShops.getShopReturns().stream().map(MiraklUpdatedShopReturn::getShopUpdated) + .map(MiraklShop::getId) + .collect(Collectors.joining(LoggingConstantsUtil.LIST_LOGGING_SEPARATOR))); + //@formatter:off - miraklUpdateShop.setAdditionalFieldValues(additionalValues); - return miraklUpdateShop; - } + } + + private MiraklUpdateShop getMiraklUpdateShopWithProofOfDocumentFields(final KYCDocumentBusinessStakeHolderInfoModel shopToUpdate) { + + final MiraklUpdateShop miraklUpdateShop = new MiraklUpdateShop(); + miraklUpdateShop.setShopId(Long.valueOf(shopToUpdate.getClientUserId())); + + final List additionalValues = new ArrayList<>(); + + if (shopToUpdate.isRequiresKYC()) { + + final MiraklRequestAdditionalFieldValue miraklRequestProofIdentity= new MiraklRequestAdditionalFieldValue.MiraklSimpleRequestAdditionalFieldValue( + HYPERWALLET_PREFIX + STAKEHOLDER_PREFIX + REQUIRED_PROOF_IDENTITY + + shopToUpdate.getBusinessStakeholderMiraklNumber(), + Boolean.FALSE.toString().toLowerCase()); + + additionalValues.add(miraklRequestProofIdentity); + } + + if (shopToUpdate.isRequiresLetterOfAuthorization()) { + + final MiraklRequestAdditionalFieldValue miraklRequestProofOfAuthorization = new MiraklRequestAdditionalFieldValue.MiraklSimpleRequestAdditionalFieldValue( + HYPERWALLET_KYC_REQUIRED_PROOF_AUTHORIZATION_BUSINESS_FIELD, + Boolean.FALSE.toString().toLowerCase()); + + additionalValues.add(miraklRequestProofOfAuthorization); + } + + miraklUpdateShop.setAdditionalFieldValues(additionalValues); + return miraklUpdateShop; + } } diff --git a/kyc/src/main/java/com/paypal/kyc/service/documents/files/mirakl/impl/MiraklSellerDocumentsExtractServiceImpl.java b/kyc/src/main/java/com/paypal/kyc/service/documents/files/mirakl/impl/MiraklSellerDocumentsExtractServiceImpl.java index d45145e5..5ab4f334 100644 --- a/kyc/src/main/java/com/paypal/kyc/service/documents/files/mirakl/impl/MiraklSellerDocumentsExtractServiceImpl.java +++ b/kyc/src/main/java/com/paypal/kyc/service/documents/files/mirakl/impl/MiraklSellerDocumentsExtractServiceImpl.java @@ -11,6 +11,7 @@ import com.mirakl.client.mmp.request.additionalfield.MiraklRequestAdditionalFieldValue; import com.mirakl.client.mmp.request.shop.MiraklGetShopsRequest; import com.paypal.infrastructure.converter.Converter; +import com.paypal.infrastructure.exceptions.HMCMiraklAPIException; import com.paypal.infrastructure.mail.MailNotificationUtil; import com.paypal.infrastructure.util.LoggingConstantsUtil; import com.paypal.infrastructure.util.MiraklLoggingErrorsUtil; @@ -45,20 +46,17 @@ public class MiraklSellerDocumentsExtractServiceImpl extends AbstractMiraklDocum private final MiraklMarketplacePlatformOperatorApiClient miraklOperatorClient; - private final MailNotificationUtil kycMailNotificationUtil; - public MiraklSellerDocumentsExtractServiceImpl( final MiraklSellerDocumentDownloadExtractService miraklSellerDocumentDownloadExtractService, final Converter miraklGetShopsRequestConverter, final Converter miraklShopKYCDocumentInfoModelConverter, final MiraklMarketplacePlatformOperatorApiClient miraklOperatorClient, final MailNotificationUtil kycMailNotificationUtil) { - super(miraklOperatorClient); + super(miraklOperatorClient, kycMailNotificationUtil); this.miraklSellerDocumentDownloadExtractService = miraklSellerDocumentDownloadExtractService; this.miraklGetShopsRequestConverter = miraklGetShopsRequestConverter; this.miraklShopKYCDocumentInfoModelConverter = miraklShopKYCDocumentInfoModelConverter; this.miraklOperatorClient = miraklOperatorClient; - this.kycMailNotificationUtil = kycMailNotificationUtil; } /** @@ -71,24 +69,24 @@ public List extractProofOfIdentityAndBusinessSellerD final MiraklShops shops = miraklOperatorClient.getShops(miraklGetShopsRequest); //@formatter:off - log.info("Retrieved modified shops since [{}]: [{}]", delta, - Stream.ofNullable(shops.getShops()) - .flatMap(Collection::stream) - .map(MiraklShop::getId) - .collect(Collectors.joining(LoggingConstantsUtil.LIST_LOGGING_SEPARATOR))); - //@formatter:on + log.info("Retrieved modified shops since [{}]: [{}]", delta, + Stream.ofNullable(shops.getShops()) + .flatMap(Collection::stream) + .map(MiraklShop::getId) + .collect(Collectors.joining(LoggingConstantsUtil.LIST_LOGGING_SEPARATOR))); + //@formatter:on //@formatter:off - final List kycDocumentInfoList = Stream.ofNullable(shops.getShops()) - .flatMap(Collection::stream) - .map(miraklShopKYCDocumentInfoModelConverter::convert) - .collect(Collectors.toList()); - //@formatter:on + final List kycDocumentInfoList = Stream.ofNullable(shops.getShops()) + .flatMap(Collection::stream) + .map(miraklShopKYCDocumentInfoModelConverter::convert) + .collect(Collectors.toList()); + //@formatter:on //@formatter:off - final Map> documentGroups = kycDocumentInfoList.stream() - .collect(Collectors.groupingBy(KYCDocumentSellerInfoModel::isRequiresKYC)); - //@formatter:on + final Map> documentGroups = kycDocumentInfoList.stream() + .collect(Collectors.groupingBy(KYCDocumentSellerInfoModel::isRequiresKYC)); + //@formatter:on final Collection docsFromShopsWithVerificationRequired = CollectionUtils .emptyIfNull(documentGroups.get(true)); @@ -97,36 +95,36 @@ public List extractProofOfIdentityAndBusinessSellerD if (!CollectionUtils.isEmpty(docsFromShopsWithVerificationRequired)) { //@formatter:off - log.info("Shops with KYC seller verification required: [{}]", - docsFromShopsWithVerificationRequired.stream() - .map(KYCDocumentSellerInfoModel::getClientUserId) - .collect(Collectors.joining(LoggingConstantsUtil.LIST_LOGGING_SEPARATOR))); - //@formatter:on + log.info("Shops with KYC seller verification required: [{}]", + docsFromShopsWithVerificationRequired.stream() + .map(KYCDocumentSellerInfoModel::getClientUserId) + .collect(Collectors.joining(LoggingConstantsUtil.LIST_LOGGING_SEPARATOR))); + //@formatter:on } if (!CollectionUtils.isEmpty(docsFromShopsWithoutVerificationRequired)) { //@formatter:off - log.info("Shops without KYC seller verification required: [{}]", - docsFromShopsWithoutVerificationRequired.stream() - .map(KYCDocumentSellerInfoModel::getClientUserId) - .collect(Collectors.joining(LoggingConstantsUtil.LIST_LOGGING_SEPARATOR))); - //@formatter:on + log.info("Shops without KYC seller verification required: [{}]", + docsFromShopsWithoutVerificationRequired.stream() + .map(KYCDocumentSellerInfoModel::getClientUserId) + .collect(Collectors.joining(LoggingConstantsUtil.LIST_LOGGING_SEPARATOR))); + //@formatter:on } skipShopsWithNonSelectedDocuments(docsFromShopsWithVerificationRequired); //@formatter:off - final List shopsWithSelectedVerificationDocuments = docsFromShopsWithVerificationRequired.stream() - .filter(KYCDocumentSellerInfoModel::hasSelectedDocumentControlFields) - .collect(Collectors.toList()); - //@formatter:on + final List shopsWithSelectedVerificationDocuments = docsFromShopsWithVerificationRequired.stream() + .filter(KYCDocumentSellerInfoModel::hasSelectedDocumentControlFields) + .collect(Collectors.toList()); + //@formatter:on //@formatter:off - return shopsWithSelectedVerificationDocuments.stream() - .filter(kycDocumentInfoModel -> !ObjectUtils.isEmpty(kycDocumentInfoModel.getUserToken())) - .map(miraklSellerDocumentDownloadExtractService::getDocumentsSelectedBySeller) - .collect(Collectors.toList()); - //@formatter:on + return shopsWithSelectedVerificationDocuments.stream() + .filter(kycDocumentInfoModel -> !ObjectUtils.isEmpty(kycDocumentInfoModel.getUserToken())) + .map(miraklSellerDocumentDownloadExtractService::getDocumentsSelectedBySeller) + .collect(Collectors.toList()); + //@formatter:on } protected Optional extractMiraklShop(final String shopId) { @@ -143,12 +141,10 @@ protected Optional extractMiraklShop(final String shopId) { * {@inheritDoc} */ @Override - public Optional setFlagToPushProofOfIdentityAndBusinessSellerDocumentsToFalse( - final List successfullyPushedListOfDocuments) { - final List shopIdToUpdateList = successfullyPushedListOfDocuments.stream() - .map(KYCDocumentSellerInfoModel::getClientUserId).collect(Collectors.toList()); + public void setFlagToPushProofOfIdentityAndBusinessSellerDocumentsToFalse( + final KYCDocumentSellerInfoModel successfullyPushedListOfDocument) { - return miraklUpdateShopCall(shopIdToUpdateList); + miraklUpdateShopCall(successfullyPushedListOfDocument.getClientUserId()); } /** @@ -166,10 +162,10 @@ private void skipShopsWithNonSelectedDocuments( final Collection shopsWithVerificationRequired) { //@formatter:off - final List shopsWithNonSelectedVerificationDocuments = shopsWithVerificationRequired.stream() - .filter(Predicate.not(KYCDocumentSellerInfoModel::hasSelectedDocumentControlFields)) - .collect(Collectors.toList()); - //@formatter:on + final List shopsWithNonSelectedVerificationDocuments = shopsWithVerificationRequired.stream() + .filter(Predicate.not(KYCDocumentSellerInfoModel::hasSelectedDocumentControlFields)) + .collect(Collectors.toList()); + //@formatter:on if (!CollectionUtils.isEmpty(shopsWithNonSelectedVerificationDocuments)) { log.warn("Skipping shops for seller with non selected documents to push to hyperwallet: [{}]", @@ -178,41 +174,41 @@ private void skipShopsWithNonSelectedDocuments( } } - private Optional miraklUpdateShopCall(final List shopIdList) { - if (CollectionUtils.isEmpty(shopIdList)) { - return Optional.empty(); - } + private void miraklUpdateShopCall(final String shopId) { + + final MiraklUpdateShop miraklUpdateShop = new MiraklUpdateShop(); + miraklUpdateShop.setShopId(Long.valueOf(shopId)); + miraklUpdateShop.setAdditionalFieldValues( + List.of(new MiraklRequestAdditionalFieldValue.MiraklSimpleRequestAdditionalFieldValue( + KYCConstants.HYPERWALLET_KYC_REQUIRED_PROOF_IDENTITY_BUSINESS_FIELD, + Boolean.FALSE.toString().toLowerCase()))); + + final MiraklUpdateShopsRequest miraklUpdateShopRequest = new MiraklUpdateShopsRequest( + List.of(miraklUpdateShop)); - final List shopsToUpdate = shopIdList.stream().map(Long::valueOf).map(shopId -> { - final MiraklUpdateShop miraklUpdateShop = new MiraklUpdateShop(); - miraklUpdateShop.setShopId(shopId); - miraklUpdateShop.setAdditionalFieldValues( - List.of(new MiraklRequestAdditionalFieldValue.MiraklSimpleRequestAdditionalFieldValue( - KYCConstants.HYPERWALLET_KYC_REQUIRED_PROOF_IDENTITY_BUSINESS_FIELD, - Boolean.FALSE.toString().toLowerCase()))); - return miraklUpdateShop; - }).collect(Collectors.toList()); - - final MiraklUpdateShopsRequest miraklUpdateShopRequest = new MiraklUpdateShopsRequest(shopsToUpdate); try { final MiraklUpdatedShops miraklUpdatedShops = miraklOperatorClient.updateShops(miraklUpdateShopRequest); - //@formatter:on - log.info("Setting required KYC flag for shops with ids [{}] to false", - miraklUpdatedShops.getShopReturns().stream().map(MiraklUpdatedShopReturn::getShopUpdated) - .map(MiraklShop::getId) - .collect(Collectors.joining(LoggingConstantsUtil.LIST_LOGGING_SEPARATOR))); - return Optional.of(miraklUpdatedShops); - //@formatter:off - } catch (final MiraklException e) { - log.error("Something went wrong when removing flag to retrieve documents for shops [{}]", String.join(",", shopIdList)); - kycMailNotificationUtil.sendPlainTextEmail("Issue setting push document flags to false in Mirakl", - String.format("Something went wrong setting push document flag to false in Mirakl for shop Id [%s]%n%s", - String.join(",", shopIdList), - MiraklLoggingErrorsUtil.stringify(e))); + logUpdatedShops(miraklUpdatedShops); + } + catch (final MiraklException e) { + + log.error("Something went wrong when removing flag to retrieve documents for shop [{}]", shopId); + + reportError("Shop Id " + shopId, e); - return Optional.empty(); + throw new HMCMiraklAPIException(e); + } } + private void logUpdatedShops(final MiraklUpdatedShops miraklUpdatedShops) { + //@formatter:on + log.info("Setting required KYC flag for shops with ids [{}] to false", + miraklUpdatedShops.getShopReturns().stream().map(MiraklUpdatedShopReturn::getShopUpdated) + .map(MiraklShop::getId) + .collect(Collectors.joining(LoggingConstantsUtil.LIST_LOGGING_SEPARATOR))); + //@formatter:off + } + } diff --git a/kyc/src/main/java/com/paypal/kyc/service/impl/DocumentsExtractServiceImpl.java b/kyc/src/main/java/com/paypal/kyc/service/impl/DocumentsExtractServiceImpl.java deleted file mode 100644 index 324e24a4..00000000 --- a/kyc/src/main/java/com/paypal/kyc/service/impl/DocumentsExtractServiceImpl.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.paypal.kyc.service.impl; - -import com.paypal.kyc.model.KYCDocumentBusinessStakeHolderInfoModel; -import com.paypal.kyc.model.KYCDocumentInfoModel; -import com.paypal.kyc.model.KYCDocumentModel; -import com.paypal.kyc.model.KYCDocumentSellerInfoModel; -import com.paypal.kyc.service.DocumentsExtractService; -import com.paypal.kyc.service.documents.files.hyperwallet.HyperwalletBusinessStakeholderExtractService; -import com.paypal.kyc.service.documents.files.hyperwallet.HyperwalletSellerExtractService; -import com.paypal.kyc.service.documents.files.mirakl.MiraklBusinessStakeholderDocumentsExtractService; -import com.paypal.kyc.service.documents.files.mirakl.MiraklSellerDocumentsExtractService; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.CollectionUtils; -import org.springframework.stereotype.Service; - -import java.io.File; -import java.util.Collection; -import java.util.Date; -import java.util.List; -import java.util.Objects; - -/** - * Implementation of interface {@link DocumentsExtractService} - */ -@Slf4j -@Service -public class DocumentsExtractServiceImpl implements DocumentsExtractService { - - private final MiraklSellerDocumentsExtractService miraklSellerDocumentsExtractService; - - private final MiraklBusinessStakeholderDocumentsExtractService miraklBusinessStakeholderDocumentsExtractService; - - private final HyperwalletSellerExtractService hyperwalletSellerExtractService; - - private final HyperwalletBusinessStakeholderExtractService hyperwalletBusinessStakeholderExtractService; - - public DocumentsExtractServiceImpl(final MiraklSellerDocumentsExtractService miraklSellerDocumentsExtractService, - final MiraklBusinessStakeholderDocumentsExtractService miraklBusinessStakeholderDocumentsExtractService, - final HyperwalletSellerExtractService hyperwalletSellerExtractService, - final HyperwalletBusinessStakeholderExtractService hyperwalletBusinessStakeholderExtractService) { - this.miraklSellerDocumentsExtractService = miraklSellerDocumentsExtractService; - this.miraklBusinessStakeholderDocumentsExtractService = miraklBusinessStakeholderDocumentsExtractService; - this.hyperwalletSellerExtractService = hyperwalletSellerExtractService; - this.hyperwalletBusinessStakeholderExtractService = hyperwalletBusinessStakeholderExtractService; - } - - /** - * {@inheritDoc} - */ - @Override - public List extractProofOfIdentityAndBusinessSellerDocuments(final Date delta) { - final List kycDocumentSellerInfoModels = miraklSellerDocumentsExtractService - .extractProofOfIdentityAndBusinessSellerDocuments(delta); - final List correctlySentDocuments = hyperwalletSellerExtractService - .pushProofOfIdentityAndBusinessSellerDocuments(kycDocumentSellerInfoModels); - miraklSellerDocumentsExtractService - .setFlagToPushProofOfIdentityAndBusinessSellerDocumentsToFalse(correctlySentDocuments); - - return correctlySentDocuments; - } - - /** - * {@inheritDoc} - */ - @Override - public Collection extractBusinessStakeholderDocuments(final Date delta) { - final List kycBusinessStakeHolderInfoModels = miraklBusinessStakeholderDocumentsExtractService - .extractBusinessStakeholderDocuments(delta); - final List correctlySentDocuments = hyperwalletBusinessStakeholderExtractService - .pushBusinessStakeholderDocuments(kycBusinessStakeHolderInfoModels); - miraklBusinessStakeholderDocumentsExtractService - .setBusinessStakeholderFlagKYCToPushBusinessStakeholderDocumentsToFalse(correctlySentDocuments); - - return correctlySentDocuments; - } - - /** - * {@inheritDoc} - */ - @Override - @SuppressWarnings("java:S3864") - public void cleanUpDocumentsFiles(final List successFullPushedListOfDocuments) { - log.info("Cleaning up files from disk..."); - //@formatter:off - CollectionUtils.emptyIfNull(successFullPushedListOfDocuments).stream() - .map(T::getDocuments) - .filter(Objects::nonNull) - .flatMap(Collection::stream) - .map(KYCDocumentModel::getFile) - .filter(Objects::nonNull) - .peek(file -> log.info("File selected to be deleted [{}]", file.getAbsolutePath())) - .forEach(File::delete); - //@formatter:on - log.info("Cleaning up done successfully!"); - } - -} diff --git a/kyc/src/main/java/com/paypal/kyc/service/impl/KYCReadyForReviewServiceImpl.java b/kyc/src/main/java/com/paypal/kyc/service/impl/KYCReadyForReviewServiceImpl.java index 181288f9..762f89d9 100644 --- a/kyc/src/main/java/com/paypal/kyc/service/impl/KYCReadyForReviewServiceImpl.java +++ b/kyc/src/main/java/com/paypal/kyc/service/impl/KYCReadyForReviewServiceImpl.java @@ -3,6 +3,7 @@ import com.hyperwallet.clientsdk.Hyperwallet; import com.hyperwallet.clientsdk.HyperwalletException; import com.hyperwallet.clientsdk.model.HyperwalletUser; +import com.paypal.infrastructure.exceptions.HMCHyperwalletAPIException; import com.paypal.infrastructure.mail.MailNotificationUtil; import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; import com.paypal.kyc.model.KYCDocumentInfoModel; @@ -41,77 +42,40 @@ public KYCReadyForReviewServiceImpl(final HyperwalletSDKService hyperwalletSDKSe } @Override - public void notifyReadyForReview(final List documentsTriedToBeSent) { - //@formatter:off - final Map> bstkGroupedByClientId = documentsTriedToBeSent.stream() - .collect(Collectors.groupingBy(KYCDocumentInfoModel::getUserToken)); - - final Map> userWithBstkToBeNotified = bstkGroupedByClientId.entrySet().stream() - .filter(entry -> entry.getValue().stream() - .allMatch(KYCDocumentInfoModel::isSentToHyperwallet)) - .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); - - userWithBstkToBeNotified.entrySet() - .forEach(this::notifyBstkReadyForReview); - //@formatter:on - } - - protected void notifyBstkReadyForReview(final Map.Entry> entry) { - final String token = entry.getKey(); + public void notifyReadyForReview(KYCDocumentInfoModel kycDocumentInfoModel) { + final String token = kycDocumentInfoModel.getUserToken(); final HyperwalletUser user = new HyperwalletUser(); user.setToken(token); user.setBusinessStakeholderVerificationStatus( HyperwalletUser.BusinessStakeholderVerificationStatus.READY_FOR_REVIEW); try { - final Optional hyperwalletProgramOptional = getHyperwalletProgram(entry.getValue()); - if (hyperwalletProgramOptional.isPresent()) { - final String hyperwalletProgram = hyperwalletProgramOptional.get(); + final String hyperwalletProgram = kycDocumentInfoModel.getHyperwalletProgram(); + if (StringUtils.isNotEmpty(hyperwalletProgram)) { final Hyperwallet hyperwallet = hyperwalletSDKService.getHyperwalletInstance(hyperwalletProgram); final HyperwalletUser hyperwalletUser = hyperwallet.updateUser(user); log.info("Seller with id [{}] has been set as Ready for review", hyperwalletUser.getClientUserId()); } else { - log.error("Seller with shop Id [{}] has no Hyperwallet Program", getClientId(entry.getValue())); + log.error("Seller with shop Id [{}] has no Hyperwallet Program", + kycDocumentInfoModel.getClientUserId()); } } catch (final HyperwalletException e) { - //@formatter:off - final String clientUserId = CollectionUtils.emptyIfNull(entry.getValue()) - .stream() - .map(KYCDocumentInfoModel::getClientUserId) - .findAny() - .orElse("undefined"); - //@formatter:on - log.error("Error notifying to Hyperwallet that all documents were sent: [{}]", - HyperwalletLoggingErrorsUtil.stringify(e)); - kycMailNotificationUtil.sendPlainTextEmail("Issue in Hyperwallet status notification", String.format( - "There was an error notifying Hyperwallet all documents were sent for shop Id [%s], so Hyperwallet will not be notified about this new situation%n%s", - clientUserId, HyperwalletLoggingErrorsUtil.stringify(e))); + reportHyperwalletAPIError(kycDocumentInfoModel, e); + + throw new HMCHyperwalletAPIException(e); } } - private Optional getHyperwalletProgram(final List documentInfoList) { - //@formatter:off - return CollectionUtils.emptyIfNull(documentInfoList) - .stream() - .filter(Objects::nonNull) - .map(KYCDocumentInfoModel::getHyperwalletProgram) - .filter(StringUtils::isNotEmpty) - .findAny(); - //@formatter:off - } + private void reportHyperwalletAPIError(KYCDocumentInfoModel kycDocumentInfoModel, HyperwalletException e) { + log.error("Error notifying to Hyperwallet that all documents were sent: [{}]", + HyperwalletLoggingErrorsUtil.stringify(e)); - private String getClientId(final List documentInfoList) { - //@formatter:off - return CollectionUtils.emptyIfNull(documentInfoList) - .stream() - .filter(Objects::nonNull) - .map(KYCDocumentInfoModel::getClientUserId) - .findAny() - .orElse(null); - //@formatter:on + kycMailNotificationUtil.sendPlainTextEmail("Issue in Hyperwallet status notification", String.format( + "There was an error notifying Hyperwallet all documents were sent for shop Id [%s], so Hyperwallet will not be notified about this new situation%n%s", + kycDocumentInfoModel.getClientUserId(), HyperwalletLoggingErrorsUtil.stringify(e))); } } diff --git a/kyc/src/main/java/com/paypal/kyc/service/impl/KYCReadyForReviewServiceMockImpl.java b/kyc/src/main/java/com/paypal/kyc/service/impl/KYCReadyForReviewServiceMockImpl.java index 03b50c47..16e49a54 100644 --- a/kyc/src/main/java/com/paypal/kyc/service/impl/KYCReadyForReviewServiceMockImpl.java +++ b/kyc/src/main/java/com/paypal/kyc/service/impl/KYCReadyForReviewServiceMockImpl.java @@ -3,9 +3,9 @@ import com.google.gson.Gson; import com.hyperwallet.clientsdk.HyperwalletException; import com.hyperwallet.clientsdk.model.HyperwalletUser; +import com.paypal.infrastructure.exceptions.HMCHyperwalletAPIException; import com.paypal.infrastructure.mail.MailNotificationUtil; import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; -import com.paypal.kyc.model.KYCDocumentBusinessStakeHolderInfoModel; import com.paypal.kyc.model.KYCDocumentInfoModel; import com.paypal.kyc.service.HyperwalletSDKService; import lombok.extern.slf4j.Slf4j; @@ -14,10 +14,6 @@ import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; -import java.util.List; -import java.util.Map; -import java.util.Optional; - /** * Implementation of {@link KYCReadyForReviewServiceImpl} for mocking purposes */ @@ -41,8 +37,8 @@ public KYCReadyForReviewServiceMockImpl(@Value("${mockserver.url}") final String } @Override - protected void notifyBstkReadyForReview(final Map.Entry> entry) { - final String token = entry.getKey(); + public void notifyReadyForReview(KYCDocumentInfoModel kycDocumentInfoModel) { + final String token = kycDocumentInfoModel.getUserToken(); final HyperwalletUser user = new HyperwalletUser(); user.setToken(token); user.setBusinessStakeholderVerificationStatus( @@ -53,17 +49,18 @@ protected void notifyBstkReadyForReview(final Map.Entry result = testObj.getItems(DELTA); + + assertThat(result.stream().map(BusinessStakeholdersDocumentsExtractBatchJobItem::getItem) + .collect(Collectors.toList())).containsExactlyInAnyOrder(kycDocumentBusinessStakeHolderInfoModelMock1, + kycDocumentBusinessStakeHolderInfoModelMock2); + } + +} diff --git a/kyc/src/test/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobItemProcessorTest.java b/kyc/src/test/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobItemProcessorTest.java new file mode 100644 index 00000000..bbb62e98 --- /dev/null +++ b/kyc/src/test/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobItemProcessorTest.java @@ -0,0 +1,110 @@ +package com.paypal.kyc.batchjobs.businessstakeholders; + +import com.callibrity.logging.test.LogTracker; +import com.callibrity.logging.test.LogTrackerStub; +import com.paypal.infrastructure.batchjob.BatchJobContext; +import com.paypal.kyc.batchjobs.AbstractDocumentsBatchJobItemProcessor; +import com.paypal.kyc.model.KYCDocumentBusinessStakeHolderInfoModel; +import com.paypal.kyc.model.KYCDocumentModel; +import com.paypal.kyc.service.KYCReadyForReviewService; +import com.paypal.kyc.service.documents.files.hyperwallet.HyperwalletBusinessStakeholderExtractService; +import com.paypal.kyc.service.documents.files.mirakl.MiraklBusinessStakeholderDocumentsExtractService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.io.File; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class BusinessStakeholdersDocumentsExtractBatchJobItemProcessorTest { + + public static final String FILE_PATH = "PATH"; + + @InjectMocks + private BusinessStakeholdersDocumentsExtractBatchJobItemProcessor testObj; + + @Mock + private MiraklBusinessStakeholderDocumentsExtractService miraklBusinessStakeholderDocumentsExtractServiceMock; + + @Mock + private HyperwalletBusinessStakeholderExtractService hyperwalletBusinessStakeholderExtractServiceMock; + + @Mock + private KYCReadyForReviewService kycReadyForReviewServiceMock; + + @Mock + private KYCDocumentBusinessStakeHolderInfoModel kycDocumentBusinessStakeHolderInfoModelMock; + + @Mock + private BusinessStakeholdersDocumentsExtractBatchJobItem businessStakeholdersDocumentsExtractBatchJobItemMock; + + @Mock + private KYCDocumentModel kycDocumentModelMock; + + @Mock + private File fileMock; + + @Mock + private BatchJobContext batchJobContextMock; + + @RegisterExtension + LogTrackerStub logTrackerStub = LogTrackerStub.create().recordForLevel(LogTracker.LogLevel.INFO) + .recordForType(AbstractDocumentsBatchJobItemProcessor.class); + + @BeforeEach + void setUp() { + when(businessStakeholdersDocumentsExtractBatchJobItemMock.getItem()) + .thenReturn(kycDocumentBusinessStakeHolderInfoModelMock); + when(kycDocumentBusinessStakeHolderInfoModelMock.getDocuments()).thenReturn(List.of(kycDocumentModelMock)); + when(kycDocumentModelMock.getFile()).thenReturn(fileMock); + when(fileMock.getAbsolutePath()).thenReturn(FILE_PATH); + } + + @Test + void processItem_shouldPushFlagNotifyAndCleanDocuments_whenDocumentsCanBePushed() { + + when(hyperwalletBusinessStakeholderExtractServiceMock + .pushDocuments(kycDocumentBusinessStakeHolderInfoModelMock)).thenReturn(true); + + testObj.processItem(batchJobContextMock, businessStakeholdersDocumentsExtractBatchJobItemMock); + + verify(hyperwalletBusinessStakeholderExtractServiceMock) + .pushDocuments(kycDocumentBusinessStakeHolderInfoModelMock); + verify(miraklBusinessStakeholderDocumentsExtractServiceMock) + .setBusinessStakeholderFlagKYCToPushBusinessStakeholderDocumentsToFalse( + kycDocumentBusinessStakeHolderInfoModelMock); + verify(kycReadyForReviewServiceMock).notifyReadyForReview(kycDocumentBusinessStakeHolderInfoModelMock); + verify(fileMock).delete(); + + assertThat(logTrackerStub.contains("File selected to be deleted [%s]".formatted(FILE_PATH))).isTrue(); + } + + @Test + void processItem_shouldNotNotifyAndCleanDocuments_whenDocumentsCanNotBePushed() { + + when(hyperwalletBusinessStakeholderExtractServiceMock + .pushDocuments(kycDocumentBusinessStakeHolderInfoModelMock)).thenReturn(false); + + testObj.processItem(batchJobContextMock, businessStakeholdersDocumentsExtractBatchJobItemMock); + + verify(hyperwalletBusinessStakeholderExtractServiceMock) + .pushDocuments(kycDocumentBusinessStakeHolderInfoModelMock); + verify(miraklBusinessStakeholderDocumentsExtractServiceMock, times(0)) + .setBusinessStakeholderFlagKYCToPushBusinessStakeholderDocumentsToFalse( + kycDocumentBusinessStakeHolderInfoModelMock); + verify(kycReadyForReviewServiceMock, times(0)) + .notifyReadyForReview(kycDocumentBusinessStakeHolderInfoModelMock); + verify(fileMock).delete(); + + assertThat(logTrackerStub.contains("File selected to be deleted [%s]".formatted(FILE_PATH))).isTrue(); + } + +} diff --git a/kyc/src/test/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobItemTest.java b/kyc/src/test/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobItemTest.java new file mode 100644 index 00000000..b1aa611c --- /dev/null +++ b/kyc/src/test/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobItemTest.java @@ -0,0 +1,44 @@ +package com.paypal.kyc.batchjobs.businessstakeholders; + +import com.paypal.kyc.model.KYCDocumentBusinessStakeHolderInfoModel; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class BusinessStakeholdersDocumentsExtractBatchJobItemTest { + + private static final String CLIENT_USER_ID = "clientUserId"; + + private static final String BUSINESSSTAKEHOLDER_TOKEN = "BusinessStakeholderToken"; + + private static final Integer BUSINESSSTAKEHOLDER_NUMBER = 0; + + private static final String SELLER_DOCUMENT = "BusinessStakeholderDocument"; + + @Test + void getItemId_ShouldReturnItemId() { + + final KYCDocumentBusinessStakeHolderInfoModel kycDocumentSellerInfoModel = KYCDocumentBusinessStakeHolderInfoModel + .builder().clientUserId(CLIENT_USER_ID).businessStakeholderMiraklNumber(BUSINESSSTAKEHOLDER_NUMBER) + .token(BUSINESSSTAKEHOLDER_TOKEN).build(); + + final BusinessStakeholdersDocumentsExtractBatchJobItem testObj = new BusinessStakeholdersDocumentsExtractBatchJobItem( + kycDocumentSellerInfoModel); + + assertThat(testObj.getItemId()) + .isEqualTo(CLIENT_USER_ID + "-" + BUSINESSSTAKEHOLDER_NUMBER + "-" + BUSINESSSTAKEHOLDER_TOKEN); + } + + @Test + void getItemType_ShouldReturnItemType() { + + final KYCDocumentBusinessStakeHolderInfoModel kycDocumentSellerInfoModel = KYCDocumentBusinessStakeHolderInfoModel + .builder().clientUserId(CLIENT_USER_ID).build(); + + final BusinessStakeholdersDocumentsExtractBatchJobItem testObj = new BusinessStakeholdersDocumentsExtractBatchJobItem( + kycDocumentSellerInfoModel); + + assertThat(testObj.getItemType()).isEqualTo(SELLER_DOCUMENT); + } + +} diff --git a/kyc/src/test/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobTest.java b/kyc/src/test/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobTest.java new file mode 100644 index 00000000..d406ad57 --- /dev/null +++ b/kyc/src/test/java/com/paypal/kyc/batchjobs/businessstakeholders/BusinessStakeholdersDocumentsExtractBatchJobTest.java @@ -0,0 +1,44 @@ +package com.paypal.kyc.batchjobs.businessstakeholders; + +import com.paypal.infrastructure.batchjob.BatchJobContext; +import com.paypal.infrastructure.batchjob.BatchJobItemProcessor; +import com.paypal.infrastructure.batchjob.BatchJobItemsExtractor; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(MockitoExtension.class) +class BusinessStakeholdersDocumentsExtractBatchJobTest { + + @InjectMocks + private BusinessStakeholdersDocumentsExtractBatchJob testObj; + + @Mock + private BusinessStakeholdersDocumentsExtractBatchJobItemProcessor businessStakeholdersDocumentsExtractBatchJobItemProcessor; + + @Mock + private BusinessStakeholdersDocumentsExtractBatchJobItemExtractor businessStakeholdersDocumentsExtractBatchJobItemExtractor; + + @Test + void getBatchJobItemProcessor_ShouldReturnBusinessStakeholdersDocumentExtractBatchJobItemProcessor() { + + final BatchJobItemProcessor result = testObj + .getBatchJobItemProcessor(); + + assertThat(result).isEqualTo(businessStakeholdersDocumentsExtractBatchJobItemProcessor); + } + + @Test + void getBatchJobItemsExtractor_ShouldReturnBusinessStakeholdersDocumentExtractBatchJobItemsExtractor() { + + final BatchJobItemsExtractor result = testObj + .getBatchJobItemsExtractor(); + + assertThat(result).isEqualTo(businessStakeholdersDocumentsExtractBatchJobItemExtractor); + } + +} diff --git a/kyc/src/test/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItemExtractorTest.java b/kyc/src/test/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItemExtractorTest.java new file mode 100644 index 00000000..c17518da --- /dev/null +++ b/kyc/src/test/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItemExtractorTest.java @@ -0,0 +1,44 @@ +package com.paypal.kyc.batchjobs.sellers; + +import com.paypal.kyc.model.KYCDocumentSellerInfoModel; +import com.paypal.kyc.service.documents.files.mirakl.MiraklSellerDocumentsExtractService; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Collection; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class SellersDocumentsExtractBatchJobItemExtractorTest { + + private static final Date DELTA = new Date(); + + @InjectMocks + private SellersDocumentsExtractBatchJobItemExtractor testObj; + + @Mock + private MiraklSellerDocumentsExtractService miraklSellerDocumentsExtractServiceMock; + + @Mock + private KYCDocumentSellerInfoModel kycDocumentSellerInfoModelMock1, kycDocumentSellerInfoModelMock2; + + @Test + void getItems_ShouldReturnAllSellerDocumentsForAGivenDelta() { + when(miraklSellerDocumentsExtractServiceMock.extractProofOfIdentityAndBusinessSellerDocuments(DELTA)) + .thenReturn(List.of(kycDocumentSellerInfoModelMock1, kycDocumentSellerInfoModelMock2)); + + final Collection result = testObj.getItems(DELTA); + + assertThat(result.stream().map(SellersDocumentsExtractBatchJobItem::getItem).collect(Collectors.toList())) + .containsExactlyInAnyOrder(kycDocumentSellerInfoModelMock1, kycDocumentSellerInfoModelMock2); + } + +} diff --git a/kyc/src/test/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItemProcessorTest.java b/kyc/src/test/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItemProcessorTest.java new file mode 100644 index 00000000..5df3297c --- /dev/null +++ b/kyc/src/test/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItemProcessorTest.java @@ -0,0 +1,97 @@ +package com.paypal.kyc.batchjobs.sellers; + +import com.callibrity.logging.test.LogTracker; +import com.callibrity.logging.test.LogTrackerStub; +import com.paypal.infrastructure.batchjob.BatchJobContext; +import com.paypal.kyc.batchjobs.AbstractDocumentsBatchJobItemProcessor; +import com.paypal.kyc.model.KYCDocumentModel; +import com.paypal.kyc.model.KYCDocumentSellerInfoModel; +import com.paypal.kyc.service.KYCReadyForReviewService; +import com.paypal.kyc.service.documents.files.hyperwallet.HyperwalletSellerExtractService; +import com.paypal.kyc.service.documents.files.mirakl.MiraklSellerDocumentsExtractService; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.io.File; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class SellersDocumentsExtractBatchJobItemProcessorTest { + + public static final String FILE_PATH = "PATH"; + + @InjectMocks + private SellersDocumentsExtractBatchJobItemProcessor testObj; + + @Mock + private MiraklSellerDocumentsExtractService miraklSellerDocumentsExtractServiceMock; + + @Mock + private HyperwalletSellerExtractService hyperwalletSellerExtractServiceMock; + + @Mock + private KYCReadyForReviewService kycReadyForReviewServiceMock; + + @Mock + private KYCDocumentSellerInfoModel kycDocumentSellerInfoModelMock; + + @Mock + private SellersDocumentsExtractBatchJobItem sellersDocumentsExtractBatchJobItemMock; + + @Mock + private KYCDocumentModel kycDocumentModelMock; + + @Mock + private File fileMock; + + @Mock + private BatchJobContext batchJobContextMock; + + @RegisterExtension + LogTrackerStub logTrackerStub = LogTrackerStub.create().recordForLevel(LogTracker.LogLevel.INFO) + .recordForType(AbstractDocumentsBatchJobItemProcessor.class); + + @Test + void processItem_shouldPushFlagNotifyAndCleanDocuments_whenDocumentsCanBePushed() { + when(sellersDocumentsExtractBatchJobItemMock.getItem()).thenReturn(kycDocumentSellerInfoModelMock); + when(kycDocumentSellerInfoModelMock.getDocuments()).thenReturn(List.of(kycDocumentModelMock)); + when(kycDocumentModelMock.getFile()).thenReturn(fileMock); + when(fileMock.getAbsolutePath()).thenReturn(FILE_PATH); + when(hyperwalletSellerExtractServiceMock.pushDocuments(kycDocumentSellerInfoModelMock)).thenReturn(true); + + testObj.processItem(batchJobContextMock, sellersDocumentsExtractBatchJobItemMock); + verify(hyperwalletSellerExtractServiceMock).pushDocuments(kycDocumentSellerInfoModelMock); + verify(miraklSellerDocumentsExtractServiceMock) + .setFlagToPushProofOfIdentityAndBusinessSellerDocumentsToFalse(kycDocumentSellerInfoModelMock); + verify(kycReadyForReviewServiceMock).notifyReadyForReview(kycDocumentSellerInfoModelMock); + verify(fileMock).delete(); + + assertThat(logTrackerStub.contains("File selected to be deleted [%s]".formatted(FILE_PATH))).isTrue(); + } + + @Test + void processItem_shouldNotNotifyAndCleanDocuments_whenDocumentsCanNotBePushed() { + when(sellersDocumentsExtractBatchJobItemMock.getItem()).thenReturn(kycDocumentSellerInfoModelMock); + when(kycDocumentSellerInfoModelMock.getDocuments()).thenReturn(List.of(kycDocumentModelMock)); + when(kycDocumentModelMock.getFile()).thenReturn(fileMock); + when(fileMock.getAbsolutePath()).thenReturn(FILE_PATH); + when(hyperwalletSellerExtractServiceMock.pushDocuments(kycDocumentSellerInfoModelMock)).thenReturn(false); + + testObj.processItem(batchJobContextMock, sellersDocumentsExtractBatchJobItemMock); + verify(hyperwalletSellerExtractServiceMock).pushDocuments(kycDocumentSellerInfoModelMock); + verify(miraklSellerDocumentsExtractServiceMock, times(0)) + .setFlagToPushProofOfIdentityAndBusinessSellerDocumentsToFalse(kycDocumentSellerInfoModelMock); + verify(kycReadyForReviewServiceMock, times(0)).notifyReadyForReview(kycDocumentSellerInfoModelMock); + verify(fileMock).delete(); + + assertThat(logTrackerStub.contains("File selected to be deleted [%s]".formatted(FILE_PATH))).isTrue(); + } + +} diff --git a/kyc/src/test/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItemTest.java b/kyc/src/test/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItemTest.java new file mode 100644 index 00000000..f3693ba5 --- /dev/null +++ b/kyc/src/test/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobItemTest.java @@ -0,0 +1,38 @@ +package com.paypal.kyc.batchjobs.sellers; + +import com.paypal.kyc.model.KYCDocumentSellerInfoModel; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +class SellersDocumentsExtractBatchJobItemTest { + + private static final String CLIENT_USER_ID = "clientUserId"; + + private static final String SELLER_DOCUMENT = "SellerDocument"; + + @Test + void getItemId_ShouldReturnItemId() { + + final KYCDocumentSellerInfoModel kycDocumentSellerInfoModel = KYCDocumentSellerInfoModel.builder() + .clientUserId(CLIENT_USER_ID).build(); + + final SellersDocumentsExtractBatchJobItem testObj = new SellersDocumentsExtractBatchJobItem( + kycDocumentSellerInfoModel); + + assertThat(testObj.getItemId()).isEqualTo(CLIENT_USER_ID); + } + + @Test + void getItemType_ShouldReturnItemType() { + + final KYCDocumentSellerInfoModel kycDocumentSellerInfoModel = KYCDocumentSellerInfoModel.builder() + .clientUserId(CLIENT_USER_ID).build(); + + final SellersDocumentsExtractBatchJobItem testObj = new SellersDocumentsExtractBatchJobItem( + kycDocumentSellerInfoModel); + + assertThat(testObj.getItemType()).isEqualTo(SELLER_DOCUMENT); + } + +} diff --git a/kyc/src/test/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobTest.java b/kyc/src/test/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobTest.java new file mode 100644 index 00000000..6f83e343 --- /dev/null +++ b/kyc/src/test/java/com/paypal/kyc/batchjobs/sellers/SellersDocumentsExtractBatchJobTest.java @@ -0,0 +1,44 @@ +package com.paypal.kyc.batchjobs.sellers; + +import com.paypal.infrastructure.batchjob.BatchJobContext; +import com.paypal.infrastructure.batchjob.BatchJobItemProcessor; +import com.paypal.infrastructure.batchjob.BatchJobItemsExtractor; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.assertj.core.api.Assertions.assertThat; + +@ExtendWith(MockitoExtension.class) +class SellersDocumentsExtractBatchJobTest { + + @InjectMocks + private SellersDocumentsExtractBatchJob testObj; + + @Mock + private SellersDocumentsExtractBatchJobItemProcessor sellersDocumentsExtractBatchJobItemProcessorMock; + + @Mock + private SellersDocumentsExtractBatchJobItemExtractor sellersDocumentsExtractBatchJobItemExtractorMock; + + @Test + void getBatchJobItemProcessor_ShouldReturnSellersDocumentExtractBatchJobItemProcessor() { + + final BatchJobItemProcessor result = testObj + .getBatchJobItemProcessor(); + + assertThat(result).isEqualTo(sellersDocumentsExtractBatchJobItemProcessorMock); + } + + @Test + void getBatchJobItemsExtractor_ShouldReturnSellersDocumentExtractBatchJobItemsExtractor() { + + final BatchJobItemsExtractor result = testObj + .getBatchJobItemsExtractor(); + + assertThat(result).isEqualTo(sellersDocumentsExtractBatchJobItemExtractorMock); + } + +} diff --git a/kyc/src/test/java/com/paypal/kyc/jobs/DocumentsExtractJobTest.java b/kyc/src/test/java/com/paypal/kyc/jobs/DocumentsExtractJobTest.java index 7420f086..1ea215fb 100644 --- a/kyc/src/test/java/com/paypal/kyc/jobs/DocumentsExtractJobTest.java +++ b/kyc/src/test/java/com/paypal/kyc/jobs/DocumentsExtractJobTest.java @@ -1,127 +1,38 @@ package com.paypal.kyc.jobs; -import com.paypal.infrastructure.repository.JobExecutionInformationRepository; -import com.paypal.kyc.model.KYCDocumentBusinessStakeHolderInfoModel; -import com.paypal.kyc.model.KYCDocumentInfoModel; -import com.paypal.kyc.model.KYCDocumentSellerInfoModel; -import com.paypal.kyc.service.DocumentsExtractService; -import com.paypal.kyc.service.KYCReadyForReviewService; +import com.paypal.kyc.batchjobs.businessstakeholders.BusinessStakeholdersDocumentsExtractBatchJob; +import com.paypal.kyc.batchjobs.sellers.SellersDocumentsExtractBatchJob; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.*; +import org.mockito.InjectMocks; +import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.quartz.Job; -import org.quartz.JobBuilder; -import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; +import org.quartz.JobExecutionException; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Map; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.verify; @ExtendWith(MockitoExtension.class) class DocumentsExtractJobTest { - private static final String DELTA = "delta"; - - private static final String JOB_NAME = "jobName"; - @InjectMocks private DocumentsExtractJob testObj; @Mock - private DocumentsExtractService documentsExtractServiceMock; - - @Mock - private KYCReadyForReviewService KYCReadyForReviewServiceMock; + private SellersDocumentsExtractBatchJob sellersDocumentsExtractBatchJobMock; @Mock - private JobExecutionInformationRepository jobExecutionInformationRepositoryMock; + private BusinessStakeholdersDocumentsExtractBatchJob businessStakeholdersDocumentsExtractBatchJobMock; @Mock private JobExecutionContext contextMock; - @Mock - private KYCDocumentSellerInfoModel documentSellerInfoModelMock; - - @Mock - private KYCDocumentBusinessStakeHolderInfoModel documentBusinessStakeHolderInfoModelMock; - - @Captor - private ArgumentCaptor dateArgumentCaptor; - - @Captor - private ArgumentCaptor> documentInfoCaptor; - - @Test - void execute_whenNoDeltaKeyIsFound_shouldCallDocumentsExtractServiceWithDeltaAsNull_andNotifyDocumentsSent_andCleanUpDocuments() { - when(contextMock.getJobDetail()).thenReturn(JobBuilder.newJob(MyJob.class).withIdentity(JOB_NAME).build()); - when(documentsExtractServiceMock.extractProofOfIdentityAndBusinessSellerDocuments(null)) - .thenReturn(Collections.singletonList(documentSellerInfoModelMock)); - when(documentsExtractServiceMock.extractBusinessStakeholderDocuments(null)) - .thenReturn(Collections.singletonList(documentBusinessStakeHolderInfoModelMock)); - - testObj.execute(contextMock); - - final InOrder inOrder = inOrder(documentsExtractServiceMock, KYCReadyForReviewServiceMock); - - inOrder.verify(documentsExtractServiceMock).extractProofOfIdentityAndBusinessSellerDocuments(null); - inOrder.verify(documentsExtractServiceMock).extractBusinessStakeholderDocuments(null); - inOrder.verify(KYCReadyForReviewServiceMock).notifyReadyForReview(documentInfoCaptor.capture()); - final List documents = documentInfoCaptor.getValue(); - assertThat(documents).containsExactlyInAnyOrder(documentSellerInfoModelMock, - documentBusinessStakeHolderInfoModelMock); - inOrder.verify(documentsExtractServiceMock).cleanUpDocumentsFiles(documents); - } - @Test - void execute_whenDeltaKeyIsFound_shouldCallMiraklDocumentsExtractServiceWithDeltaAsNull_andNotifyDocumentsSent_andCleanUpDocuments() { - final Date expectedDate = new Date(); - when(contextMock.getJobDetail()).thenReturn(JobBuilder.newJob(MyJob.class) - .usingJobData(new JobDataMap(Map.of(DELTA, expectedDate))).withIdentity(JOB_NAME).build()); - when(documentsExtractServiceMock.extractProofOfIdentityAndBusinessSellerDocuments(expectedDate)) - .thenReturn(Collections.singletonList(documentSellerInfoModelMock)); - when(documentsExtractServiceMock.extractBusinessStakeholderDocuments(expectedDate)) - .thenReturn(Collections.singletonList(documentBusinessStakeHolderInfoModelMock)); - + void execute_ShouldCallBusinessStakeholderAndSellersDocumentExtractBatchJob() throws JobExecutionException { testObj.execute(contextMock); - verify(documentsExtractServiceMock) - .extractProofOfIdentityAndBusinessSellerDocuments(dateArgumentCaptor.capture()); - assertThat(dateArgumentCaptor.getValue()).isEqualTo(expectedDate); - verify(documentsExtractServiceMock).extractProofOfIdentityAndBusinessSellerDocuments(expectedDate); - - final InOrder inOrder = inOrder(documentsExtractServiceMock, KYCReadyForReviewServiceMock); - - inOrder.verify(documentsExtractServiceMock).extractProofOfIdentityAndBusinessSellerDocuments(expectedDate); - inOrder.verify(documentsExtractServiceMock).extractBusinessStakeholderDocuments(expectedDate); - inOrder.verify(KYCReadyForReviewServiceMock).notifyReadyForReview(documentInfoCaptor.capture()); - final List documents = documentInfoCaptor.getValue(); - assertThat(documents).containsExactlyInAnyOrder(documentSellerInfoModelMock, - documentBusinessStakeHolderInfoModelMock); - inOrder.verify(documentsExtractServiceMock).cleanUpDocumentsFiles(documents); - } - - @Test - void createJobDataMap_shouldReturnMapWithDateAsDeltaValue() { - final Date expectedDate = new Date(); - - final JobDataMap result = DocumentsExtractJob.createJobDataMap(expectedDate); - - assertThat(result).containsEntry(DELTA, expectedDate); - } - - private static class MyJob implements Job { - - @Override - public void execute(final JobExecutionContext context) { - // doNothing - } - + verify(sellersDocumentsExtractBatchJobMock).execute(contextMock); + verify(businessStakeholdersDocumentsExtractBatchJobMock).execute(contextMock); } } diff --git a/kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletBusinessStakeholderExtractServiceImplTest.java b/kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletBusinessStakeholderExtractServiceImplTest.java index 3de7768d..a3a2d1d3 100644 --- a/kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletBusinessStakeholderExtractServiceImplTest.java +++ b/kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletBusinessStakeholderExtractServiceImplTest.java @@ -1,29 +1,20 @@ package com.paypal.kyc.service.documents.files.hyperwallet.impl; -import com.callibrity.logging.test.LogTracker; -import com.callibrity.logging.test.LogTrackerStub; import com.hyperwallet.clientsdk.Hyperwallet; -import com.hyperwallet.clientsdk.HyperwalletException; import com.hyperwallet.clientsdk.model.HyperwalletBusinessStakeholder; import com.hyperwallet.clientsdk.model.HyperwalletList; import com.hyperwallet.clientsdk.model.HyperwalletVerificationDocument; -import com.paypal.infrastructure.mail.MailNotificationUtil; -import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; import com.paypal.kyc.model.KYCDocumentBusinessStakeHolderInfoModel; -import com.paypal.kyc.model.KYCDocumentModel; -import com.paypal.kyc.model.KYCProofOfIdentityEnum; import com.paypal.kyc.service.HyperwalletSDKService; +import com.paypal.kyc.service.documents.files.hyperwallet.HyperwalletDocumentUploadService; import com.paypal.kyc.strategies.documents.files.hyperwallet.businessstakeholder.impl.KYCBusinessStakeholderDocumentInfoModelToHWVerificationDocumentExecutor; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.api.extension.RegisterExtension; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; -import java.io.File; import java.util.Collections; import java.util.List; @@ -39,12 +30,6 @@ class HyperwalletBusinessStakeholderExtractServiceImplTest { private static final String HYPERWALLET_PROGRAM = "hyperwalletProgram"; - private static final String PROOF_OF_IDENTITY_BACK_BSH1 = "hw-bsh1-proof-identity-back"; - - private static final String PROOF_OF_IDENTITY_FRONT_BSH1 = "hw-bsh1-proof-identity-front"; - - private static final String PROOF_OF_IDENTITY_FRONT_BSH3 = "hw-bsh3-proof-identity-front"; - private static final String BUSINESS_STAKE_HOLDER_ONE_TOKEN = "businessStakeHolderOneToken"; @Spy @@ -61,26 +46,20 @@ class HyperwalletBusinessStakeholderExtractServiceImplTest { private KYCBusinessStakeholderDocumentInfoModelToHWVerificationDocumentExecutor businessStakeholderDocumentInfoModelToHWVerificationDocumentMultipleStrategyExecutorMock; @Mock - private MailNotificationUtil kycMailNotificationUtilMock; + private HyperwalletDocumentUploadService hyperwalletDocumentUploadServiceMock; @Mock private HyperwalletList businessStakeholders; @Mock - private File usrOneBstkOneFileFrontMock, userOneBstkThreeFileFrontMock, usrOneBstkOneFileBackMock, - userTwoBstkThreeFileFrontMock; + private KYCDocumentBusinessStakeHolderInfoModel kycDocumentBusinessStakeHolderInfoModelMock; @Mock - private HyperwalletVerificationDocument usrOneBstOneFilesOneDataMock, usrOneBstThreeFilesDataMock, - usrTwoBstThreeFilesDataMock; + private HyperwalletVerificationDocument usrOneBstOneFilesOneDataMock; @Mock private HyperwalletBusinessStakeholder businessStakeHolderRequiredVerificationMock, businessStakeHolderVerifiedMock; - @RegisterExtension - final LogTrackerStub logTrackerStub = LogTrackerStub.create().recordForLevel(LogTracker.LogLevel.ERROR) - .recordForType(HyperwalletBusinessStakeholderExtractServiceImpl.class); - @Test void getKYCRequiredVerificationBusinessStakeHolders_whenNoBusinessStakeholdersAreReceived_shouldReturnEmptyList() { when(hyperwalletSDKServiceMock.getHyperwalletInstance(HYPERWALLET_PROGRAM)) @@ -141,332 +120,25 @@ void getKYCRequiredVerificationBusinessStakeHolders_shouldReturnRequiredVerifica } @Test - void pushBusinessStakeholderDocuments_whenAllDocumentsAreFulfilledByBusinessStakeholder_shouldPushDocumentsForBusinessStakeholders() { - //@formatter:off - final KYCDocumentModel userOneBstkOneFrontDocument = KYCDocumentModel.builder() - .documentFieldName(PROOF_OF_IDENTITY_FRONT_BSH1) - .file(usrOneBstkOneFileFrontMock) - .build(); - //@formatter:on - - //@formatter:off - final KYCDocumentModel userOneBstkOneBackDocument = KYCDocumentModel.builder() - .documentFieldName(PROOF_OF_IDENTITY_BACK_BSH1) - .file(usrOneBstkOneFileBackMock) - .build(); - //@formatter:on - - //@formatter:off - final KYCDocumentModel userOneBstkThreeFrontDocument = KYCDocumentModel.builder() - .documentFieldName(PROOF_OF_IDENTITY_FRONT_BSH3) - .file(userOneBstkThreeFileFrontMock) - .build(); - //@formatter:on - - //@formatter:off - final KYCDocumentModel userTwoBstkOneFrontDocument = KYCDocumentModel.builder() - .documentFieldName(PROOF_OF_IDENTITY_FRONT_BSH1) - .file(userTwoBstkThreeFileFrontMock) - .build(); - //@formatter:on - - //@formatter:off - final KYCDocumentBusinessStakeHolderInfoModel userOneBstkOne = Mockito.spy(KYCDocumentBusinessStakeHolderInfoModel - .builder() - .hyperwalletProgram(HYPERWALLET_PROGRAM) - .businessStakeholderMiraklNumber(1) - .token("stk-1") - .requiresKYC(true) - .userToken("usr-1") - .clientUserId("2000") - .proofOfIdentity(KYCProofOfIdentityEnum.GOVERNMENT_ID) - .documents(List.of(userOneBstkOneFrontDocument, userOneBstkOneBackDocument)) - .build()); - //@formatter:on - - final KYCDocumentBusinessStakeHolderInfoModel userOneBstkOneSentToHW = userOneBstkOne.toBuilder() - .sentToHyperwallet(Boolean.TRUE).build(); - - //@formatter:off - final KYCDocumentBusinessStakeHolderInfoModel userOneBstkThree = Mockito.spy(KYCDocumentBusinessStakeHolderInfoModel - .builder() - .hyperwalletProgram(HYPERWALLET_PROGRAM) - .businessStakeholderMiraklNumber(3) - .token("stk-3") - .requiresKYC(true) - .userToken("usr-1") - .clientUserId("2000") - .proofOfIdentity(KYCProofOfIdentityEnum.PASSPORT) - .documents(List.of(userOneBstkThreeFrontDocument)) - .build()); - //@formatter:on - - final KYCDocumentBusinessStakeHolderInfoModel userOneBstkThreeSentToHW = userOneBstkThree.toBuilder() - .sentToHyperwallet(Boolean.TRUE).build(); - - //@formatter:off - final KYCDocumentBusinessStakeHolderInfoModel userTwoBstkThree = Mockito.spy(KYCDocumentBusinessStakeHolderInfoModel - .builder() - .hyperwalletProgram(HYPERWALLET_PROGRAM) - .businessStakeholderMiraklNumber(3) - .token("stk-3") - .requiresKYC(true) - .userToken("usr-2") - .clientUserId("2001") - .proofOfIdentity(KYCProofOfIdentityEnum.PASSPORT) - .documents(List - .of(userTwoBstkOneFrontDocument)) - .build()); - //@formatter:on - - final KYCDocumentBusinessStakeHolderInfoModel userTwoBstkThreeSentToHW = userTwoBstkThree.toBuilder() - .sentToHyperwallet(Boolean.TRUE).build(); - - when(userOneBstkOne.areDocumentsFilled()).thenReturn(true); - when(userOneBstkThree.areDocumentsFilled()).thenReturn(true); - when(userTwoBstkThree.areDocumentsFilled()).thenReturn(true); + void pushDocuments_whenAllDocumentsAreFulfilledByBusinessStakeholder_shouldPushDocumentsForBusinessStakeholder() { + when(kycDocumentBusinessStakeHolderInfoModelMock.areDocumentsFilled()).thenReturn(true); final List usrOneBstOneFilesOneDataList = List .of(usrOneBstOneFilesOneDataMock); when(businessStakeholderDocumentInfoModelToHWVerificationDocumentMultipleStrategyExecutorMock - .execute(userOneBstkOne)).thenReturn(usrOneBstOneFilesOneDataList); - final List usrOneBstThreeFilesDataList = List.of(usrOneBstThreeFilesDataMock); - when(businessStakeholderDocumentInfoModelToHWVerificationDocumentMultipleStrategyExecutorMock - .execute(userOneBstkThree)).thenReturn(usrOneBstThreeFilesDataList); - final List usrTwoBstOneFilesDataList = List.of(usrTwoBstThreeFilesDataMock); - when(businessStakeholderDocumentInfoModelToHWVerificationDocumentMultipleStrategyExecutorMock - .execute(userTwoBstkThree)).thenReturn(usrTwoBstOneFilesDataList); - when(hyperwalletSDKServiceMock.getHyperwalletInstance(HYPERWALLET_PROGRAM)) - .thenReturn(hyperwalletApiClientMock); - - final List result = testObj - .pushBusinessStakeholderDocuments(List.of(userOneBstkOne, userOneBstkThree, userTwoBstkThree)); - - verify(hyperwalletApiClientMock).uploadStakeholderDocuments("usr-1", "stk-1", usrOneBstOneFilesOneDataList); - verify(hyperwalletApiClientMock).uploadStakeholderDocuments("usr-1", "stk-3", usrOneBstThreeFilesDataList); - verify(hyperwalletApiClientMock).uploadStakeholderDocuments("usr-2", "stk-3", usrTwoBstOneFilesDataList); + .execute(kycDocumentBusinessStakeHolderInfoModelMock)).thenReturn(usrOneBstOneFilesOneDataList); + testObj.pushDocuments(kycDocumentBusinessStakeHolderInfoModelMock); - assertThat(result).containsExactlyInAnyOrder(userOneBstkOneSentToHW, userOneBstkThreeSentToHW, - userTwoBstkThreeSentToHW); + verify(hyperwalletDocumentUploadServiceMock).uploadDocument(kycDocumentBusinessStakeHolderInfoModelMock, + usrOneBstOneFilesOneDataList); } @Test - void pushBusinessStakeholderDocuments_whenEmptyListIsProvided_shouldReturnAnEmptyList() { - final List result = testObj - .pushBusinessStakeholderDocuments(List.of()); - - assertThat(result).isEmpty(); - verifyNoInteractions(hyperwalletApiClientMock); - verifyNoInteractions(businessStakeholderDocumentInfoModelToHWVerificationDocumentMultipleStrategyExecutorMock); - } - - @Test - void pushBusinessStakeholderDocuments_shouldSkipBusinessStakeholdersWithNotAllDocumentsFulfilled() { - //@formatter:off - final KYCDocumentModel userOneBstkOneFrontDocument = KYCDocumentModel.builder() - .documentFieldName(PROOF_OF_IDENTITY_FRONT_BSH1) - .file(usrOneBstkOneFileFrontMock) - .build(); - //@formatter:on - - //@formatter:off - final KYCDocumentModel userOneBstkOneBackDocument = KYCDocumentModel.builder() - .documentFieldName(PROOF_OF_IDENTITY_BACK_BSH1) - .file(usrOneBstkOneFileBackMock) - .build(); - //@formatter:on - - //@formatter:off - final KYCDocumentModel userOneBstkThreeFrontDocument = KYCDocumentModel.builder() - .documentFieldName(PROOF_OF_IDENTITY_FRONT_BSH3) - .file(userOneBstkThreeFileFrontMock) - .build(); - //@formatter:on - - //@formatter:off - final KYCDocumentBusinessStakeHolderInfoModel userOneBstkOne = Mockito.spy(KYCDocumentBusinessStakeHolderInfoModel - .builder() - .hyperwalletProgram(HYPERWALLET_PROGRAM) - .businessStakeholderMiraklNumber(1) - .token("stk-1") - .requiresKYC(true) - .userToken("usr-1") - .clientUserId("2000") - .proofOfIdentity(KYCProofOfIdentityEnum.GOVERNMENT_ID) - .documents(List.of(userOneBstkOneFrontDocument, userOneBstkOneBackDocument)) - .build()); - //@formatter:on - - final KYCDocumentBusinessStakeHolderInfoModel userOneBstkOneSentToHW = userOneBstkOne.toBuilder() - .sentToHyperwallet(Boolean.TRUE).build(); - - //@formatter:off - final KYCDocumentBusinessStakeHolderInfoModel userOneBstkThree = Mockito.spy(KYCDocumentBusinessStakeHolderInfoModel - .builder() - .hyperwalletProgram(HYPERWALLET_PROGRAM) - .businessStakeholderMiraklNumber(3) - .token("stk-3") - .requiresKYC(true) - .userToken("usr-1") - .clientUserId("2000") - .proofOfIdentity(KYCProofOfIdentityEnum.PASSPORT) - .documents(List.of(userOneBstkThreeFrontDocument)) - .build()); - //@formatter:on - - final KYCDocumentBusinessStakeHolderInfoModel userOneBstkThreeSentToHW = userOneBstkThree.toBuilder() - .sentToHyperwallet(Boolean.TRUE).build(); - - //@formatter:off - final KYCDocumentBusinessStakeHolderInfoModel userTwoBstkThree = Mockito.spy(KYCDocumentBusinessStakeHolderInfoModel - .builder() - .hyperwalletProgram(HYPERWALLET_PROGRAM) - .businessStakeholderMiraklNumber(3) - .token("stk-3") - .requiresKYC(true) - .userToken("usr-2") - .clientUserId("2001") - .proofOfIdentity(KYCProofOfIdentityEnum.PASSPORT) - .build()); - //@formatter:on - - when(userOneBstkOne.areDocumentsFilled()).thenReturn(true); - when(userOneBstkThree.areDocumentsFilled()).thenReturn(true); - when(userTwoBstkThree.areDocumentsFilled()).thenReturn(false); - - final List usrOneBstOneFilesOneDataList = List - .of(usrOneBstOneFilesOneDataMock); - when(businessStakeholderDocumentInfoModelToHWVerificationDocumentMultipleStrategyExecutorMock - .execute(userOneBstkOne)).thenReturn(usrOneBstOneFilesOneDataList); - final List usrOneBstThreeFilesDataList = List.of(usrOneBstThreeFilesDataMock); - when(businessStakeholderDocumentInfoModelToHWVerificationDocumentMultipleStrategyExecutorMock - .execute(userOneBstkThree)).thenReturn(usrOneBstThreeFilesDataList); - when(hyperwalletSDKServiceMock.getHyperwalletInstance(HYPERWALLET_PROGRAM)) - .thenReturn(hyperwalletApiClientMock); - - final List result = testObj - .pushBusinessStakeholderDocuments(List.of(userOneBstkOne, userOneBstkThree, userTwoBstkThree)); - - verify(hyperwalletApiClientMock).uploadStakeholderDocuments("usr-1", "stk-1", usrOneBstOneFilesOneDataList); - verify(hyperwalletApiClientMock).uploadStakeholderDocuments("usr-1", "stk-3", usrOneBstThreeFilesDataList); - - assertThat(result).containsExactlyInAnyOrder(userOneBstkOneSentToHW, userOneBstkThreeSentToHW); - } - - @Test - void pushBusinessStakeholderDocuments_whenHyperwalletAPIFailsWithOneSpecificBstkFile_shouldFailGracefully() { - //@formatter:off - final KYCDocumentModel userOneBstkOneFrontDocument = KYCDocumentModel.builder() - .documentFieldName(PROOF_OF_IDENTITY_FRONT_BSH1) - .file(usrOneBstkOneFileFrontMock) - .build(); - //@formatter:on - - //@formatter:off - final KYCDocumentModel userOneBstkOneBackDocument = KYCDocumentModel.builder() - .documentFieldName(PROOF_OF_IDENTITY_BACK_BSH1) - .file(usrOneBstkOneFileBackMock) - .build(); - //@formatter:on - - //@formatter:off - final KYCDocumentModel userOneBstkThreeFrontDocument = KYCDocumentModel.builder() - .documentFieldName(PROOF_OF_IDENTITY_FRONT_BSH3) - .file(userOneBstkThreeFileFrontMock) - .build(); - //@formatter:on - - //@formatter:off - final KYCDocumentModel userTwoBstkOneFrontDocument = KYCDocumentModel.builder() - .documentFieldName(PROOF_OF_IDENTITY_FRONT_BSH1) - .file(userTwoBstkThreeFileFrontMock) - .build(); - //@formatter:on - - //@formatter:off - final KYCDocumentBusinessStakeHolderInfoModel userOneBstkOne = Mockito.spy(KYCDocumentBusinessStakeHolderInfoModel - .builder() - .hyperwalletProgram(HYPERWALLET_PROGRAM) - .businessStakeholderMiraklNumber(1) - .token("stk-1") - .requiresKYC(true) - .userToken("usr-1") - .clientUserId("2000") - .proofOfIdentity(KYCProofOfIdentityEnum.GOVERNMENT_ID) - .documents(List.of(userOneBstkOneFrontDocument, userOneBstkOneBackDocument)) - .build()); - //@formatter:on - - final KYCDocumentBusinessStakeHolderInfoModel userOneBstkOneSentToHW = userOneBstkOne.toBuilder() - .sentToHyperwallet(Boolean.TRUE).build(); - - //@formatter:off - final KYCDocumentBusinessStakeHolderInfoModel userOneBstkThree = Mockito.spy(KYCDocumentBusinessStakeHolderInfoModel - .builder() - .hyperwalletProgram(HYPERWALLET_PROGRAM) - .businessStakeholderMiraklNumber(3) - .token("stk-3") - .requiresKYC(true) - .userToken("usr-1") - .clientUserId("2000") - .proofOfIdentity(KYCProofOfIdentityEnum.PASSPORT) - .documents(List.of(userOneBstkThreeFrontDocument)) - .build()); - //@formatter:on - - //@formatter:off - final KYCDocumentBusinessStakeHolderInfoModel userTwoBstkThree = Mockito.spy(KYCDocumentBusinessStakeHolderInfoModel - .builder() - .hyperwalletProgram(HYPERWALLET_PROGRAM) - .businessStakeholderMiraklNumber(3) - .token("stk-3") - .requiresKYC(true) - .userToken("usr-2") - .clientUserId("2001") - .proofOfIdentity(KYCProofOfIdentityEnum.PASSPORT) - .documents(List - .of(userTwoBstkOneFrontDocument)) - .build()); - - final KYCDocumentBusinessStakeHolderInfoModel userTwoBstkThreeSentToHW = userTwoBstkThree.toBuilder() - .sentToHyperwallet(Boolean.TRUE).build(); - //@formatter:on - - when(userOneBstkOne.areDocumentsFilled()).thenReturn(true); - when(userOneBstkThree.areDocumentsFilled()).thenReturn(true); - when(userTwoBstkThree.areDocumentsFilled()).thenReturn(true); - - final List usrOneBstOneFilesOneDataList = List - .of(usrOneBstOneFilesOneDataMock); - when(businessStakeholderDocumentInfoModelToHWVerificationDocumentMultipleStrategyExecutorMock - .execute(userOneBstkOne)).thenReturn(usrOneBstOneFilesOneDataList); - final List usrOneBstThreeFilesDataList = List.of(usrOneBstThreeFilesDataMock); - when(businessStakeholderDocumentInfoModelToHWVerificationDocumentMultipleStrategyExecutorMock - .execute(userOneBstkThree)).thenReturn(usrOneBstThreeFilesDataList); - final List usrTwoBstOneFilesDataList = List.of(usrTwoBstThreeFilesDataMock); - when(businessStakeholderDocumentInfoModelToHWVerificationDocumentMultipleStrategyExecutorMock - .execute(userTwoBstkThree)).thenReturn(usrTwoBstOneFilesDataList); - when(hyperwalletSDKServiceMock.getHyperwalletInstance(HYPERWALLET_PROGRAM)) - .thenReturn(hyperwalletApiClientMock); - - final HyperwalletException expectedException = new HyperwalletException("Something went wrong"); - lenient().when( - hyperwalletApiClientMock.uploadStakeholderDocuments("usr-1", "stk-3", usrOneBstThreeFilesDataList)) - .thenThrow(expectedException); - - final List result = testObj - .pushBusinessStakeholderDocuments(List.of(userOneBstkOne, userOneBstkThree, userTwoBstkThree)); - - verify(hyperwalletApiClientMock).uploadStakeholderDocuments("usr-1", "stk-1", usrOneBstOneFilesOneDataList); - verify(hyperwalletApiClientMock).uploadStakeholderDocuments("usr-1", "stk-3", usrOneBstThreeFilesDataList); - verify(hyperwalletApiClientMock).uploadStakeholderDocuments("usr-2", "stk-3", usrTwoBstOneFilesDataList); - verify(kycMailNotificationUtilMock).sendPlainTextEmail("Issue detected pushing documents into Hyperwallet", - String.format( - "Something went wrong pushing documents to Hyperwallet for shop Id [2000] and business stakeholder number [3]%n%s", - HyperwalletLoggingErrorsUtil.stringify(expectedException))); + void pushDocuments_shouldSkipBusinessStakeholdersWithNotAllDocumentsFulfilled() { + when(kycDocumentBusinessStakeHolderInfoModelMock.areDocumentsFilled()).thenReturn(false); + testObj.pushDocuments(kycDocumentBusinessStakeHolderInfoModelMock); - assertThat(result).containsExactlyInAnyOrder(userOneBstkOneSentToHW, userOneBstkThree, - userTwoBstkThreeSentToHW); + verify(hyperwalletDocumentUploadServiceMock, times(0)).uploadDocument(any(), any()); } } diff --git a/kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletBusinessStakeholderExtractServiceMockImplTest.java b/kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletBusinessStakeholderExtractServiceMockImplTest.java deleted file mode 100644 index 0938501f..00000000 --- a/kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletBusinessStakeholderExtractServiceMockImplTest.java +++ /dev/null @@ -1,118 +0,0 @@ -package com.paypal.kyc.service.documents.files.hyperwallet.impl; - -import com.hyperwallet.clientsdk.HyperwalletException; -import com.hyperwallet.clientsdk.model.HyperwalletVerificationDocument; -import com.mirakl.client.mmp.domain.common.MiraklAdditionalFieldValue; -import com.paypal.infrastructure.mail.MailNotificationUtil; -import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; -import com.paypal.kyc.model.KYCConstants; -import com.paypal.kyc.model.KYCDocumentBusinessStakeHolderInfoModel; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.Spy; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.web.client.RestTemplate; - -import java.util.List; -import java.util.Map; - -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@ExtendWith(MockitoExtension.class) -class HyperwalletBusinessStakeholderExtractServiceMockImplTest { - - private static final String SHOP_ID = "2000"; - - private static final String USER_TOKEN = "userToken"; - - private static final int BUSINESS_STAKEHOLDER_NUMBER = 1; - - private static final String BUSINESS_STAKEHOLDER_TOKEN = "bstToken"; - - private static final String MOCK_SERVER_URL = "https://mockserver.aws.e2y.io"; - - private static final String HYPERWALLET_PUSH_DOCUMENTS = "/hyperwallet/v4/userToken/bstToken/documents"; - - private static final String HW_STAKEHOLDER_PROOF_IDENTITY_TYPE_1 = "hw-stakeholder-proof-identity-type-1"; - - @Spy - @InjectMocks - private HyperwalletBusinessStakeholderExtractServiceMockImpl testObj; - - @Mock - private RestTemplate restTemplateMock; - - @Mock - private MailNotificationUtil mailNotificationUtilMock; - - @Test - void execute_shouldRunPushDocumentsToMockServer() { - //@formatter:off - final KYCDocumentBusinessStakeHolderInfoModel kycDocumentOne = KYCDocumentBusinessStakeHolderInfoModel.builder() - .clientUserId(SHOP_ID) - .token(BUSINESS_STAKEHOLDER_TOKEN) - .userToken(List.of(new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue( - KYCConstants.HYPERWALLET_USER_TOKEN_FIELD, USER_TOKEN))) - .businessStakeholderMiraklNumber(BUSINESS_STAKEHOLDER_NUMBER) - .proofOfIdentity( - List.of(new MiraklAdditionalFieldValue.MiraklValueListAdditionalFieldValue( - HW_STAKEHOLDER_PROOF_IDENTITY_TYPE_1, "GOVERNMENT_ID")), - BUSINESS_STAKEHOLDER_NUMBER) - .build(); - //@formatter:on - - HyperwalletVerificationDocument hyperwalletVerificationDocument = new HyperwalletVerificationDocument(); - hyperwalletVerificationDocument.setCategory("category"); - hyperwalletVerificationDocument.setCountry("ES"); - hyperwalletVerificationDocument.setType("type"); - hyperwalletVerificationDocument.setUploadFiles(Map.of("key1", "value1")); - - when(testObj.getMockServerUrl()).thenReturn(MOCK_SERVER_URL); - - final Map> kycDocumentOne1 = Map - .of(kycDocumentOne, List.of(hyperwalletVerificationDocument)); - - testObj.callHyperwalletAPI(kycDocumentOne1.entrySet().iterator().next()); - - verify(restTemplateMock).postForObject(eq(MOCK_SERVER_URL + HYPERWALLET_PUSH_DOCUMENTS), Mockito.any(), - eq(Object.class)); - } - - @Test - void execute_shouldSendEmailNotificationWhenFailingFilesAreIncluded() { - final KYCDocumentBusinessStakeHolderInfoModel kycDocumentOne = KYCDocumentBusinessStakeHolderInfoModel.builder() - .clientUserId(SHOP_ID).token(BUSINESS_STAKEHOLDER_TOKEN) - .userToken(List.of(new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue( - KYCConstants.HYPERWALLET_USER_TOKEN_FIELD, USER_TOKEN))) - .businessStakeholderMiraklNumber(BUSINESS_STAKEHOLDER_NUMBER) - .proofOfIdentity(List.of(new MiraklAdditionalFieldValue.MiraklValueListAdditionalFieldValue( - HW_STAKEHOLDER_PROOF_IDENTITY_TYPE_1, "GOVERNMENT_ID")), BUSINESS_STAKEHOLDER_NUMBER) - .build(); - - HyperwalletVerificationDocument hyperwalletVerificationDocument = new HyperwalletVerificationDocument(); - hyperwalletVerificationDocument.setCategory("category"); - hyperwalletVerificationDocument.setCountry("ES"); - hyperwalletVerificationDocument.setType("type"); - hyperwalletVerificationDocument.setUploadFiles(Map.of("key1", "value1", "fail", "failFile")); - - final Map> kycDocumentOne1 = Map - .of(kycDocumentOne, List.of(hyperwalletVerificationDocument)); - - final Map.Entry> entry = kycDocumentOne1 - .entrySet().stream().findAny().get(); - - testObj.callHyperwalletAPI(entry); - - verify(mailNotificationUtilMock).sendPlainTextEmail("Issue detected pushing documents into Hyperwallet", - String.format( - "Something went wrong pushing documents to Hyperwallet for shop Id [%s] and business stakeholder number [%s]%n%s", - SHOP_ID, BUSINESS_STAKEHOLDER_NUMBER, - HyperwalletLoggingErrorsUtil.stringify(new HyperwalletException("Something bad happened")))); - } - -} diff --git a/kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletDocumentUploadServiceImplTest.java b/kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletDocumentUploadServiceImplTest.java new file mode 100644 index 00000000..3d9b7fae --- /dev/null +++ b/kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletDocumentUploadServiceImplTest.java @@ -0,0 +1,176 @@ +package com.paypal.kyc.service.documents.files.hyperwallet.impl; + +import com.callibrity.logging.test.LogTracker; +import com.callibrity.logging.test.LogTrackerStub; +import com.hyperwallet.clientsdk.Hyperwallet; +import com.hyperwallet.clientsdk.HyperwalletException; +import com.hyperwallet.clientsdk.model.HyperwalletVerificationDocument; +import com.mirakl.client.mmp.domain.common.MiraklAdditionalFieldValue; +import com.paypal.infrastructure.exceptions.HMCHyperwalletAPIException; +import com.paypal.infrastructure.mail.MailNotificationUtil; +import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; +import com.paypal.kyc.model.*; +import com.paypal.kyc.service.HyperwalletSDKService; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.RegisterExtension; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.io.File; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class HyperwalletDocumentUploadServiceImplTest { + + private static final String USR_TOKEN_ONE = "usr-1234564780"; + + private static final String BSTK_TOKEN_ONE = "bstk-1234564780"; + + private static final String CLIENT_USER_ID_ONE = "2000"; + + private static final String HYPERWALLET_PROGRAM = "hyperwalletProgram"; + + private static final String PROOF_OF_IDENTITY_BACK_BSH1 = "hw-bsh1-proof-identity-back"; + + private static final String PROOF_OF_IDENTITY_FRONT_BSH1 = "hw-bsh1-proof-identity-front"; + + @InjectMocks + private HyperwalletDocumentUploadServiceImpl testObj; + + @Mock + private HyperwalletSDKService hyperwalletSDKServiceMock; + + @Mock + private MailNotificationUtil kycMailNotificationUtilMock; + + @Mock + private Hyperwallet hyperwalletApiClientMock; + + @Mock + private File usrOneBstkOneFileFrontMock, usrOneBstkOneFileBackMock; + + @Mock + private HyperwalletVerificationDocument usrOneBstOneFilesOneDataMock; + + @RegisterExtension + final LogTrackerStub logTrackerStub = LogTrackerStub.create().recordForLevel(LogTracker.LogLevel.ERROR) + .recordForType(HyperwalletBusinessStakeholderExtractServiceImpl.class); + + @Test + void uploadDocuments_shouldPushDocuments_whenBusinessStakeholderIsPassed() { + //@formatter:off + final KYCDocumentModel userOneBstkOneFrontDocument = KYCDocumentModel.builder() + .documentFieldName(PROOF_OF_IDENTITY_FRONT_BSH1) + .file(usrOneBstkOneFileFrontMock) + .build(); + //@formatter:on + + //@formatter:off + final KYCDocumentModel userOneBstkOneBackDocument = KYCDocumentModel.builder() + .documentFieldName(PROOF_OF_IDENTITY_BACK_BSH1) + .file(usrOneBstkOneFileBackMock) + .build(); + //@formatter:on + + //@formatter:off + final KYCDocumentBusinessStakeHolderInfoModel userOneBstkOne = Mockito.spy(KYCDocumentBusinessStakeHolderInfoModel + .builder() + .hyperwalletProgram(HYPERWALLET_PROGRAM) + .businessStakeholderMiraklNumber(1) + .token(BSTK_TOKEN_ONE) + .requiresKYC(true) + .userToken(USR_TOKEN_ONE) + .clientUserId(CLIENT_USER_ID_ONE) + .proofOfIdentity(KYCProofOfIdentityEnum.GOVERNMENT_ID) + .documents(List.of(userOneBstkOneFrontDocument, userOneBstkOneBackDocument)) + .build()); + //@formatter:on + + final List usrOneBstOneFilesOneDataList = List + .of(usrOneBstOneFilesOneDataMock); + when(hyperwalletSDKServiceMock.getHyperwalletInstance(HYPERWALLET_PROGRAM)) + .thenReturn(hyperwalletApiClientMock); + + testObj.uploadDocument(userOneBstkOne, usrOneBstOneFilesOneDataList); + + verify(hyperwalletApiClientMock).uploadStakeholderDocuments(USR_TOKEN_ONE, BSTK_TOKEN_ONE, + usrOneBstOneFilesOneDataList); + } + + @Test + void uploadDocuments_shouldPushDocuments_whenSellerIsPassed() { + final KYCDocumentSellerInfoModel kycDocumentSellerInfoModelOneStub = spy( + KYCDocumentSellerInfoModel.builder().clientUserId(CLIENT_USER_ID_ONE) + .userToken(List.of(new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue( + KYCConstants.HYPERWALLET_USER_TOKEN_FIELD, USR_TOKEN_ONE))) + .hyperwalletProgram(List.of(new MiraklAdditionalFieldValue.MiraklValueListAdditionalFieldValue( + KYCConstants.HW_PROGRAM, HYPERWALLET_PROGRAM))) + .build()); + //@formatter:on + + final List sellerOneBstOneFilesOneDataList = List + .of(usrOneBstOneFilesOneDataMock); + when(hyperwalletSDKServiceMock.getHyperwalletInstance(HYPERWALLET_PROGRAM)) + .thenReturn(hyperwalletApiClientMock); + + testObj.uploadDocument(kycDocumentSellerInfoModelOneStub, sellerOneBstOneFilesOneDataList); + + verify(hyperwalletApiClientMock).uploadUserDocuments(USR_TOKEN_ONE, sellerOneBstOneFilesOneDataList); + } + + @Test + void uploadDocumentsDocuments_whenHyperwalletAPIFails_shouldThrowException() { + //@formatter:off + final KYCDocumentModel userOneBstkOneFrontDocument = KYCDocumentModel.builder() + .documentFieldName(PROOF_OF_IDENTITY_FRONT_BSH1) + .file(usrOneBstkOneFileFrontMock) + .build(); + //@formatter:on + + //@formatter:off + final KYCDocumentModel userOneBstkOneBackDocument = KYCDocumentModel.builder() + .documentFieldName(PROOF_OF_IDENTITY_BACK_BSH1) + .file(usrOneBstkOneFileBackMock) + .build(); + //@formatter:on + + //@formatter:off + final KYCDocumentBusinessStakeHolderInfoModel userOneBstkOne = Mockito.spy(KYCDocumentBusinessStakeHolderInfoModel + .builder() + .hyperwalletProgram(HYPERWALLET_PROGRAM) + .businessStakeholderMiraklNumber(1) + .token("stk-1") + .requiresKYC(true) + .userToken("usr-1") + .clientUserId("2000") + .proofOfIdentity(KYCProofOfIdentityEnum.GOVERNMENT_ID) + .documents(List.of(userOneBstkOneFrontDocument, userOneBstkOneBackDocument)) + .build()); + //@formatter:on + + final List usrOneBstOneFilesOneDataList = List + .of(usrOneBstOneFilesOneDataMock); + when(hyperwalletSDKServiceMock.getHyperwalletInstance(HYPERWALLET_PROGRAM)) + .thenReturn(hyperwalletApiClientMock); + + final HyperwalletException expectedException = new HyperwalletException("Something went wrong"); + when(hyperwalletApiClientMock.uploadStakeholderDocuments("usr-1", "stk-1", usrOneBstOneFilesOneDataList)) + .thenThrow(expectedException); + + assertThatThrownBy(() -> testObj.uploadDocument(userOneBstkOne, usrOneBstOneFilesOneDataList)) + .isInstanceOf(HMCHyperwalletAPIException.class); + + verify(hyperwalletApiClientMock).uploadStakeholderDocuments("usr-1", "stk-1", usrOneBstOneFilesOneDataList); + verify(kycMailNotificationUtilMock).sendPlainTextEmail("Issue detected pushing documents into Hyperwallet", + String.format( + "Something went wrong pushing documents to Hyperwallet for Shop Id [2000] and Business Stakeholder number [1]%n%s", + HyperwalletLoggingErrorsUtil.stringify(expectedException))); + } + +} diff --git a/kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletDocumentUploadServiceMockImplTest.java b/kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletDocumentUploadServiceMockImplTest.java new file mode 100644 index 00000000..13fb9467 --- /dev/null +++ b/kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletDocumentUploadServiceMockImplTest.java @@ -0,0 +1,116 @@ +package com.paypal.kyc.service.documents.files.hyperwallet.impl; + +import com.hyperwallet.clientsdk.model.HyperwalletVerificationDocument; +import com.paypal.infrastructure.exceptions.HMCHyperwalletAPIException; +import com.paypal.infrastructure.mail.MailNotificationUtil; +import com.paypal.kyc.model.KYCDocumentBusinessStakeHolderInfoModel; +import com.paypal.kyc.model.KYCDocumentSellerInfoModel; +import com.paypal.kyc.service.HyperwalletSDKService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.web.client.RestTemplate; + +import java.util.List; +import java.util.Map; + +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class HyperwalletDocumentUploadServiceMockImplTest { + + private static final String MOCK_SERVER_URL = "mockServerUrl"; + + private static final String HYPERWALLET_PUSH_DOCUMENTS_BSTK = "/hyperwallet/v4/{userToken}/{bstToken}/documents"; + + private static final String HYPERWALLET_PUSH_DOCUMENTS_SELLER = "/hyperwallet/v4/{userToken}/documents"; + + private static final String BST_USER_TOKEN = "BSTUserToken"; + + private static final String BST_TOKEN = "BSTToken"; + + private static final String SELLER_USER_TOKEN = "SellerUserToken"; + + private static final String FAILED_FILE = "failedFile"; + + private static final String NOT_FAILED_FILE = "file"; + + private static final String FAILED_FILE_NAME = "failFileName"; + + private static final String NOT_FAILED_FILE_NAME = "fileName"; + + public static final String DOCUMENTS_REQUEST = "[{\"uploadFiles\":{\"file\":\"fileName\"}}]"; + + @InjectMocks + private HyperwalletDocumentUploadServiceMockImpl testObj; + + @Mock + private RestTemplate restTemplatemock; + + @Mock + private HyperwalletSDKService hyperwalletSDKServiceMock; + + @Mock + private MailNotificationUtil kycMailNotificationUtilMock; + + @Mock + private KYCDocumentBusinessStakeHolderInfoModel kycDocumentBusinessStakeHolderInfoModelMock; + + @Mock + private KYCDocumentSellerInfoModel kycDocumentSellerInfoModelMock; + + private static List hyperwalletVerificationDocuments; + + @BeforeEach + void setUp() { + + testObj = new HyperwalletDocumentUploadServiceMockImpl(hyperwalletSDKServiceMock, kycMailNotificationUtilMock, + MOCK_SERVER_URL, restTemplatemock); + lenient().when(kycDocumentBusinessStakeHolderInfoModelMock.getUserToken()).thenReturn(BST_USER_TOKEN); + lenient().when(kycDocumentBusinessStakeHolderInfoModelMock.getToken()).thenReturn(BST_TOKEN); + lenient().when(kycDocumentSellerInfoModelMock.getUserToken()).thenReturn(SELLER_USER_TOKEN); + + final HyperwalletVerificationDocument hyperwalletVerificationDocument = new HyperwalletVerificationDocument(); + hyperwalletVerificationDocument.setUploadFiles(Map.of(NOT_FAILED_FILE, NOT_FAILED_FILE_NAME)); + hyperwalletVerificationDocuments = List.of(hyperwalletVerificationDocument); + } + + @Test + void invokeHyperwalletAPI_ShouldThrowAnHMCHyperwalletAPIException_WhenThereAreFailingFiles() { + + final HyperwalletVerificationDocument hyperwalletVerificationDocument = new HyperwalletVerificationDocument(); + hyperwalletVerificationDocument.setUploadFiles(Map.of(FAILED_FILE, FAILED_FILE_NAME)); + final List hyperwalletVerificationDocuments = List + .of(hyperwalletVerificationDocument); + + assertThatThrownBy(() -> testObj.uploadDocument(kycDocumentBusinessStakeHolderInfoModelMock, + hyperwalletVerificationDocuments)).isInstanceOf(HMCHyperwalletAPIException.class); + + verifyNoInteractions(restTemplatemock); + } + + @Test + void invokeHyperwalletAPI_ShouldCallRestTemplateWithBSTUrl_WhenKYCDocumentInfoModelIsAKYCDocumentBusinessStakeHolderInfoModel() { + + testObj.uploadDocument(kycDocumentBusinessStakeHolderInfoModelMock, hyperwalletVerificationDocuments); + + verify(restTemplatemock).postForObject(MOCK_SERVER_URL + HYPERWALLET_PUSH_DOCUMENTS_BSTK + .replace("{userToken}", BST_USER_TOKEN).replace("{bstToken}", BST_TOKEN), DOCUMENTS_REQUEST, + Object.class); + } + + @Test + void invokeHyperwalletAPI_ShouldCallRestTemplateWithSellerUrl_WhenKYCDocumentInfoModelIsAKYCDocumentSellerInfoModel() { + + testObj.uploadDocument(kycDocumentSellerInfoModelMock, hyperwalletVerificationDocuments); + + verify(restTemplatemock).postForObject( + MOCK_SERVER_URL + HYPERWALLET_PUSH_DOCUMENTS_SELLER.replace("{userToken}", SELLER_USER_TOKEN), + DOCUMENTS_REQUEST, Object.class); + } + +} diff --git a/kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletSellerExtractServiceImplTest.java b/kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletSellerExtractServiceImplTest.java index 42465925..1c1d6808 100644 --- a/kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletSellerExtractServiceImplTest.java +++ b/kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletSellerExtractServiceImplTest.java @@ -1,202 +1,41 @@ package com.paypal.kyc.service.documents.files.hyperwallet.impl; -import com.hyperwallet.clientsdk.Hyperwallet; -import com.hyperwallet.clientsdk.HyperwalletException; -import com.hyperwallet.clientsdk.model.HyperwalletUser; -import com.hyperwallet.clientsdk.model.HyperwalletVerificationDocument; -import com.mirakl.client.mmp.domain.common.MiraklAdditionalFieldValue; -import com.paypal.infrastructure.mail.MailNotificationUtil; -import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; -import com.paypal.kyc.model.KYCConstants; import com.paypal.kyc.model.KYCDocumentSellerInfoModel; import com.paypal.kyc.service.HyperwalletSDKService; +import com.paypal.kyc.service.documents.files.hyperwallet.HyperwalletDocumentUploadService; import com.paypal.kyc.strategies.documents.files.hyperwallet.seller.impl.KYCDocumentInfoToHWVerificationDocumentExecutor; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.verify; @ExtendWith(MockitoExtension.class) class HyperwalletSellerExtractServiceImplTest { - private static final String USR_TOKEN_ONE = "usr-1234564780"; - - private static final String USR_TOKEN_TWO = "usr-1234564789"; - - private static final String CLIENT_USER_ID_ONE = "2001"; - - private static final String CLIENT_USER_ID_TWO = "2002"; - - private static final String EUROPE_HYPERWALLET_PROGRAM = "EUROPE"; - @InjectMocks private HyperwalletSellerExtractServiceImpl testObj; - @Mock - private Hyperwallet hyperwalletClientMock; - - @Mock - private MailNotificationUtil mailNotificationUtilMock; - @Mock private HyperwalletSDKService hyperwalletSDKServiceMock; @Mock - private HyperwalletVerificationDocument uploadDataOneMock, uploadDataTwoMock; + private HyperwalletDocumentUploadService hyperwalletDocumentUploadServiceMock; @Mock private KYCDocumentInfoToHWVerificationDocumentExecutor kycDocumentInfoToHWVerificationDocumentExecutorMock; - @Test - void pushDocuments_shouldReturnAllKYCDocumentInfoModelWhenAllMiraklAPICallsAreSuccessful() { - final KYCDocumentSellerInfoModel kycDocumentSellerInfoModelOneStub = spy( - KYCDocumentSellerInfoModel.builder().clientUserId(CLIENT_USER_ID_ONE) - .userToken(List.of(new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue( - KYCConstants.HYPERWALLET_USER_TOKEN_FIELD, USR_TOKEN_ONE))) - .hyperwalletProgram(List.of(new MiraklAdditionalFieldValue.MiraklValueListAdditionalFieldValue( - KYCConstants.HW_PROGRAM, EUROPE_HYPERWALLET_PROGRAM))) - .build()); - - final KYCDocumentSellerInfoModel kycDocumentSellerInfoModelTwoStub = Mockito - .spy(KYCDocumentSellerInfoModel.builder().clientUserId(CLIENT_USER_ID_TWO) - .userToken(List.of(new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue( - KYCConstants.HYPERWALLET_USER_TOKEN_FIELD, USR_TOKEN_TWO))) - .hyperwalletProgram(List.of(new MiraklAdditionalFieldValue.MiraklValueListAdditionalFieldValue( - KYCConstants.HW_PROGRAM, EUROPE_HYPERWALLET_PROGRAM))) - .build()); - - when(kycDocumentSellerInfoModelOneStub.areDocumentsFilled()).thenReturn(true); - when(kycDocumentSellerInfoModelTwoStub.areDocumentsFilled()).thenReturn(true); - when(kycDocumentInfoToHWVerificationDocumentExecutorMock.execute(kycDocumentSellerInfoModelOneStub)) - .thenReturn(List.of(uploadDataOneMock)); - when(kycDocumentInfoToHWVerificationDocumentExecutorMock.execute(kycDocumentSellerInfoModelTwoStub)) - .thenReturn(List.of(uploadDataTwoMock)); - - when(hyperwalletSDKServiceMock.getHyperwalletInstance(Mockito.anyString())).thenReturn(hyperwalletClientMock); - - final List result = testObj.pushProofOfIdentityAndBusinessSellerDocuments( - List.of(kycDocumentSellerInfoModelOneStub, kycDocumentSellerInfoModelTwoStub)); - - verify(hyperwalletClientMock).uploadUserDocuments(USR_TOKEN_ONE, List.of(uploadDataOneMock)); - verify(hyperwalletClientMock).uploadUserDocuments(USR_TOKEN_TWO, List.of(uploadDataTwoMock)); - - assertThat(result).containsExactlyInAnyOrder(markInfoAsSentToHyperwallet(kycDocumentSellerInfoModelOneStub), - markInfoAsSentToHyperwallet(kycDocumentSellerInfoModelTwoStub)); - } - - @Test - void pushDocuments_shouldDoNothingForKYCDocumentsInfoWithDocumentsNonFilled() { - final KYCDocumentSellerInfoModel kycDocumentSellerInfoModelOneStub = Mockito - .spy(KYCDocumentSellerInfoModel.builder().clientUserId(CLIENT_USER_ID_ONE) - .userToken(List.of(new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue( - KYCConstants.HYPERWALLET_USER_TOKEN_FIELD, USR_TOKEN_ONE))) - .hyperwalletProgram(List.of(new MiraklAdditionalFieldValue.MiraklValueListAdditionalFieldValue( - KYCConstants.HW_PROGRAM, EUROPE_HYPERWALLET_PROGRAM))) - .build()); - - final KYCDocumentSellerInfoModel kycDocumentSellerInfoModelTwoStub = Mockito - .spy(KYCDocumentSellerInfoModel.builder().clientUserId(CLIENT_USER_ID_TWO) - .userToken(List.of(new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue( - KYCConstants.HYPERWALLET_USER_TOKEN_FIELD, USR_TOKEN_TWO))) - .hyperwalletProgram(List.of(new MiraklAdditionalFieldValue.MiraklValueListAdditionalFieldValue( - KYCConstants.HW_PROGRAM, EUROPE_HYPERWALLET_PROGRAM))) - .build()); - - when(kycDocumentSellerInfoModelOneStub.areDocumentsFilled()).thenReturn(true); - when(kycDocumentSellerInfoModelTwoStub.areDocumentsFilled()).thenReturn(false); - when(kycDocumentInfoToHWVerificationDocumentExecutorMock.execute(kycDocumentSellerInfoModelOneStub)) - .thenReturn(List.of(uploadDataOneMock)); - - when(hyperwalletSDKServiceMock.getHyperwalletInstance(Mockito.anyString())).thenReturn(hyperwalletClientMock); - - final List result = testObj.pushProofOfIdentityAndBusinessSellerDocuments( - List.of(kycDocumentSellerInfoModelOneStub, kycDocumentSellerInfoModelTwoStub)); - - verify(hyperwalletClientMock).uploadUserDocuments(USR_TOKEN_ONE, List.of(uploadDataOneMock)); - verify(hyperwalletClientMock, never()).uploadUserDocuments(USR_TOKEN_TWO, List.of(uploadDataTwoMock)); - - assertThat(result).containsExactly(markInfoAsSentToHyperwallet(kycDocumentSellerInfoModelOneStub)); - } - - @Test - void pushDocuments_shouldReturnOnlySuccessfulKYCDocumentInfoModelAPICalls() { - final KYCDocumentSellerInfoModel kycDocumentSellerInfoModelOKStub = Mockito - .spy(KYCDocumentSellerInfoModel.builder().clientUserId(CLIENT_USER_ID_ONE) - .userToken(List.of(new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue( - KYCConstants.HYPERWALLET_USER_TOKEN_FIELD, USR_TOKEN_ONE))) - .hyperwalletProgram(List.of(new MiraklAdditionalFieldValue.MiraklValueListAdditionalFieldValue( - KYCConstants.HW_PROGRAM, EUROPE_HYPERWALLET_PROGRAM))) - .build()); - - final KYCDocumentSellerInfoModel kycDocumentSellerInfoModelKOStub = Mockito - .spy(KYCDocumentSellerInfoModel.builder().clientUserId(CLIENT_USER_ID_TWO) - .userToken(List.of(new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue( - KYCConstants.HYPERWALLET_USER_TOKEN_FIELD, USR_TOKEN_TWO))) - .hyperwalletProgram(List.of(new MiraklAdditionalFieldValue.MiraklValueListAdditionalFieldValue( - KYCConstants.HW_PROGRAM, EUROPE_HYPERWALLET_PROGRAM))) - .build()); - - when(kycDocumentSellerInfoModelOKStub.areDocumentsFilled()).thenReturn(true); - when(kycDocumentSellerInfoModelKOStub.areDocumentsFilled()).thenReturn(true); - - when(kycDocumentInfoToHWVerificationDocumentExecutorMock.execute(kycDocumentSellerInfoModelOKStub)) - .thenReturn(List.of(uploadDataOneMock)); - when(kycDocumentInfoToHWVerificationDocumentExecutorMock.execute(kycDocumentSellerInfoModelKOStub)) - .thenReturn(List.of(uploadDataTwoMock)); - - when(hyperwalletSDKServiceMock.getHyperwalletInstance(Mockito.anyString())).thenReturn(hyperwalletClientMock); - - doReturn(new HyperwalletUser()).when(hyperwalletClientMock).uploadUserDocuments(USR_TOKEN_ONE, - List.of(uploadDataOneMock)); - doThrow(new HyperwalletException("Something went wrong")).when(hyperwalletClientMock) - .uploadUserDocuments(USR_TOKEN_TWO, List.of(uploadDataTwoMock)); - - final List result = testObj.pushProofOfIdentityAndBusinessSellerDocuments( - List.of(kycDocumentSellerInfoModelOKStub, kycDocumentSellerInfoModelKOStub)); - - verify(hyperwalletClientMock).uploadUserDocuments(USR_TOKEN_ONE, List.of(uploadDataOneMock)); - verify(hyperwalletClientMock).uploadUserDocuments(USR_TOKEN_TWO, List.of(uploadDataTwoMock)); - - assertThat(result).containsExactly(markInfoAsSentToHyperwallet(kycDocumentSellerInfoModelOKStub)); - } + @Mock + private KYCDocumentSellerInfoModel kycDocumentSellerInfoModelMock; @Test - void pushDocuments_shouldSendEmailNotificationWhenHyperWalletExceptionIsThrown() { - final KYCDocumentSellerInfoModel kycDocumentSellerInfoModelKOStub = Mockito - .spy(KYCDocumentSellerInfoModel.builder().clientUserId(CLIENT_USER_ID_TWO) - .userToken(List.of(new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue( - KYCConstants.HYPERWALLET_USER_TOKEN_FIELD, USR_TOKEN_TWO))) - .hyperwalletProgram(List.of(new MiraklAdditionalFieldValue.MiraklValueListAdditionalFieldValue( - KYCConstants.HW_PROGRAM, EUROPE_HYPERWALLET_PROGRAM))) - .build()); + void getHyperwalletVerificationDocuments_ShouldExecuteKycDocumentInfoToHWVerificationDocumentExecutor() { - when(kycDocumentSellerInfoModelKOStub.areDocumentsFilled()).thenReturn(true); - when(kycDocumentInfoToHWVerificationDocumentExecutorMock.execute(kycDocumentSellerInfoModelKOStub)) - .thenReturn(List.of(uploadDataTwoMock)); - - when(hyperwalletSDKServiceMock.getHyperwalletInstance(Mockito.anyString())).thenReturn(hyperwalletClientMock); - - HyperwalletException hyperwalletException = new HyperwalletException("Something went wrong"); - doThrow(hyperwalletException).when(hyperwalletClientMock).uploadUserDocuments(USR_TOKEN_TWO, - List.of(uploadDataTwoMock)); - - testObj.pushProofOfIdentityAndBusinessSellerDocuments(List.of(kycDocumentSellerInfoModelKOStub)); - - verify(mailNotificationUtilMock).sendPlainTextEmail("Issue detected pushing documents into Hyperwallet", - String.format("Something went wrong pushing documents to Hyperwallet for shop Id [%s]%n%s", - String.join(",", kycDocumentSellerInfoModelKOStub.getClientUserId()), - HyperwalletLoggingErrorsUtil.stringify(hyperwalletException))); - } + testObj.getHyperwalletVerificationDocuments(kycDocumentSellerInfoModelMock); - private KYCDocumentSellerInfoModel markInfoAsSentToHyperwallet(final KYCDocumentSellerInfoModel sellerInfo) { - return sellerInfo.toBuilder().sentToHyperwallet(true).build(); + verify(kycDocumentInfoToHWVerificationDocumentExecutorMock).execute(kycDocumentSellerInfoModelMock); } } diff --git a/kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletSellerExtractServiceMockImplTest.java b/kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletSellerExtractServiceMockImplTest.java deleted file mode 100644 index 651100c5..00000000 --- a/kyc/src/test/java/com/paypal/kyc/service/documents/files/hyperwallet/impl/HyperwalletSellerExtractServiceMockImplTest.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.paypal.kyc.service.documents.files.hyperwallet.impl; - -import com.hyperwallet.clientsdk.HyperwalletException; -import com.hyperwallet.clientsdk.model.HyperwalletVerificationDocument; -import com.mirakl.client.mmp.domain.common.MiraklAdditionalFieldValue; -import com.paypal.infrastructure.mail.MailNotificationUtil; -import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; -import com.paypal.kyc.model.KYCConstants; -import com.paypal.kyc.model.KYCDocumentSellerInfoModel; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.Spy; -import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.web.client.RestTemplate; - -import java.util.List; -import java.util.Map; - -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -class HyperwalletSellerExtractServiceMockImplTest { - - @Spy - @InjectMocks - private HyperwalletSellerExtractServiceMockImpl testObj; - - @Mock - private RestTemplate restTemplateMock; - - @Mock - private MailNotificationUtil mailNotificationUtilMock; - - private static final String MOCK_SERVER_URL = "https://mockserver.aws.e2y.io"; - - private static final String HYPERWALLET_PUSH_DOCUMENTS = "/hyperwallet/v4/userToken/documents"; - - private static final String USER_TOKEN = "userToken"; - - private static final String SHOP_ID = "2000"; - - @Test - void execute_shouldRunPushDocumentsToMockServer() { - final KYCDocumentSellerInfoModel kycDocumentOne = KYCDocumentSellerInfoModel.builder() - .userToken(List.of(new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue( - KYCConstants.HYPERWALLET_USER_TOKEN_FIELD, USER_TOKEN))) - .proofOfAddress(List.of(new MiraklAdditionalFieldValue.MiraklValueListAdditionalFieldValue( - KYCConstants.HYPERWALLET_KYC_IND_PROOF_OF_ADDRESS_FIELD, "BANK_STATEMENT"))) - .build(); - - HyperwalletVerificationDocument hyperwalletVerificationDocument = new HyperwalletVerificationDocument(); - hyperwalletVerificationDocument.setCategory("category"); - hyperwalletVerificationDocument.setCountry("ES"); - hyperwalletVerificationDocument.setType("type"); - hyperwalletVerificationDocument.setUploadFiles(Map.of("key1", "value1")); - - when(testObj.getMockServerUrl()).thenReturn(MOCK_SERVER_URL); - - final Map> kycDocumentOne1 = Map - .of(kycDocumentOne, List.of(hyperwalletVerificationDocument)); - - testObj.callHyperwalletAPI(kycDocumentOne1.entrySet().iterator().next()); - - verify(restTemplateMock).postForObject(eq(MOCK_SERVER_URL + HYPERWALLET_PUSH_DOCUMENTS), Mockito.any(), - eq(Object.class)); - } - - @Test - void execute_shouldSendEmailNotificationWhenFailingFilesAreIncluded() { - final KYCDocumentSellerInfoModel kycDocumentOne = KYCDocumentSellerInfoModel.builder() - .userToken(List.of(new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue( - KYCConstants.HYPERWALLET_USER_TOKEN_FIELD, USER_TOKEN))) - .clientUserId(SHOP_ID) - .proofOfAddress(List.of(new MiraklAdditionalFieldValue.MiraklValueListAdditionalFieldValue( - KYCConstants.HYPERWALLET_KYC_IND_PROOF_OF_ADDRESS_FIELD, "BANK_STATEMENT"))) - .build(); - - HyperwalletVerificationDocument hyperwalletVerificationDocument = new HyperwalletVerificationDocument(); - hyperwalletVerificationDocument.setCategory("category"); - hyperwalletVerificationDocument.setCountry("ES"); - hyperwalletVerificationDocument.setType("type"); - hyperwalletVerificationDocument.setUploadFiles(Map.of("key1", "value1", "fail", "failFile")); - - final Map> kycDocumentOne1 = Map - .of(kycDocumentOne, List.of(hyperwalletVerificationDocument)); - - final Map.Entry> entry = kycDocumentOne1 - .entrySet().stream().findAny().get(); - - testObj.callHyperwalletAPI(entry); - - verify(mailNotificationUtilMock).sendPlainTextEmail("Issue detected pushing documents into Hyperwallet", - String.format("Something went wrong pushing documents to Hyperwallet for shop Id [%s]%n%s", - String.join(",", SHOP_ID), - HyperwalletLoggingErrorsUtil.stringify(new HyperwalletException("Something bad happened")))); - } - -} diff --git a/kyc/src/test/java/com/paypal/kyc/service/documents/files/mirakl/impl/AbstractMiraklDocumentExtractServiceImplTest.java b/kyc/src/test/java/com/paypal/kyc/service/documents/files/mirakl/impl/AbstractMiraklDocumentExtractServiceImplTest.java index 72925f7f..f04e3557 100644 --- a/kyc/src/test/java/com/paypal/kyc/service/documents/files/mirakl/impl/AbstractMiraklDocumentExtractServiceImplTest.java +++ b/kyc/src/test/java/com/paypal/kyc/service/documents/files/mirakl/impl/AbstractMiraklDocumentExtractServiceImplTest.java @@ -3,6 +3,7 @@ import com.mirakl.client.mmp.domain.shop.document.MiraklShopDocument; import com.mirakl.client.mmp.operator.core.MiraklMarketplacePlatformOperatorApiClient; import com.mirakl.client.mmp.request.shop.document.MiraklDeleteShopDocumentRequest; +import com.paypal.infrastructure.mail.MailNotificationUtil; import com.paypal.kyc.model.KYCDocumentInfoModel; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -73,8 +74,9 @@ void deleteDocuments_whenThereAreDocuments_shouldCallMirakl() { public static class MyAbstractMiraklDocumentExtractServiceImpl extends AbstractMiraklDocumentExtractServiceImpl { protected MyAbstractMiraklDocumentExtractServiceImpl( - final MiraklMarketplacePlatformOperatorApiClient miraklOperatorClient) { - super(miraklOperatorClient); + final MiraklMarketplacePlatformOperatorApiClient miraklOperatorClient, + final MailNotificationUtil mailNotificationUtil) { + super(miraklOperatorClient, mailNotificationUtil); } } diff --git a/kyc/src/test/java/com/paypal/kyc/service/documents/files/mirakl/impl/MiraklBusinessStakeholderDocumentsExtractServiceImplTest.java b/kyc/src/test/java/com/paypal/kyc/service/documents/files/mirakl/impl/MiraklBusinessStakeholderDocumentsExtractServiceImplTest.java index 0c8254fd..65323b6b 100644 --- a/kyc/src/test/java/com/paypal/kyc/service/documents/files/mirakl/impl/MiraklBusinessStakeholderDocumentsExtractServiceImplTest.java +++ b/kyc/src/test/java/com/paypal/kyc/service/documents/files/mirakl/impl/MiraklBusinessStakeholderDocumentsExtractServiceImplTest.java @@ -11,6 +11,7 @@ import com.mirakl.client.mmp.request.additionalfield.MiraklRequestAdditionalFieldValue; import com.mirakl.client.mmp.request.shop.MiraklGetShopsRequest; import com.paypal.infrastructure.converter.Converter; +import com.paypal.infrastructure.exceptions.HMCMiraklAPIException; import com.paypal.infrastructure.mail.MailNotificationUtil; import com.paypal.infrastructure.util.MiraklLoggingErrorsUtil; import com.paypal.kyc.converter.KYCBusinessStakeHolderConverter; @@ -25,6 +26,7 @@ import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) @@ -265,43 +267,21 @@ void extractBusinessStakeholderDocuments_whenNoShopsHasBeenUpdatedSinceDelta_sho @Test void setBusinessStakeholderFlagToPushBusinessStakeholderDocumentsToFalse_shouldCallMiraklWithTheClientUsersIdPassedAsParam() { - //@formatter:off - final KYCDocumentBusinessStakeHolderInfoModel kycUserOneBstOne = KYCDocumentBusinessStakeHolderInfoModel.builder() - .clientUserId("2000") - .businessStakeholderMiraklNumber(1) - .requiresKYC(Boolean.TRUE) - .sentToHyperwallet(Boolean.TRUE) - .build(); - //@formatter:on - - //@formatter:off - final KYCDocumentBusinessStakeHolderInfoModel kycUserTwoBstOne = KYCDocumentBusinessStakeHolderInfoModel.builder() - .clientUserId("2001") - .businessStakeholderMiraklNumber(1) - .requiresKYC(Boolean.TRUE) - .sentToHyperwallet(Boolean.TRUE) - .build(); - //@formatter:on //@formatter:off - final KYCDocumentBusinessStakeHolderInfoModel kycUserThreeBstOne = KYCDocumentBusinessStakeHolderInfoModel.builder() - .clientUserId("2002") - .businessStakeholderMiraklNumber(1) - .requiresKYC(Boolean.TRUE) - .sentToHyperwallet(Boolean.TRUE) - .requiresLetterOfAuthorization(Boolean.TRUE) - .build(); - //@formatter:on - - final List successfullyPushedDocumentsList = List.of(kycUserOneBstOne, - kycUserThreeBstOne, kycUserTwoBstOne); + final KYCDocumentBusinessStakeHolderInfoModel kycDocumentBusinessStakeHolderInfoModel = KYCDocumentBusinessStakeHolderInfoModel.builder() + .clientUserId("2002") + .businessStakeholderMiraklNumber(1) + .requiresKYC(Boolean.TRUE) + .requiresLetterOfAuthorization(Boolean.TRUE) + .build(); + //@formatter:on when(miraklMarketplacePlatformOperatorApiClientMock.updateShops(any(MiraklUpdateShopsRequest.class))) .thenReturn(miraklUpdateShopsMock); - final Optional result = testObj - .setBusinessStakeholderFlagKYCToPushBusinessStakeholderDocumentsToFalse( - successfullyPushedDocumentsList); + testObj.setBusinessStakeholderFlagKYCToPushBusinessStakeholderDocumentsToFalse( + kycDocumentBusinessStakeHolderInfoModel); verify(miraklMarketplacePlatformOperatorApiClientMock).updateShops(miraklUpdateShopArgumentCaptor.capture()); @@ -309,66 +289,34 @@ void setBusinessStakeholderFlagToPushBusinessStakeholderDocumentsToFalse_shouldC final List updatedSellerIdList = miraklUpdateShopRequest.getShops().stream() .map(MiraklUpdateShop::getShopId).collect(Collectors.toList()); - assertThat(updatedSellerIdList).containsExactlyInAnyOrder(2000L, 2001L, 2002L); - assertThat(getUpdatedFlagValuesForShop(miraklUpdateShopRequest, 2000L)) - .containsExactlyEntriesOf(Map.of(BUSINESS_STAKEHOLDER_PROOF_IDENTITY_CODE, "false")); - assertThat(getUpdatedFlagValuesForShop(miraklUpdateShopRequest, 2001L)) - .containsExactlyEntriesOf(Map.of(BUSINESS_STAKEHOLDER_PROOF_IDENTITY_CODE, "false")); + assertThat(updatedSellerIdList).containsOnly(2002L); assertThat(getUpdatedFlagValuesForShop(miraklUpdateShopRequest, 2002L)).containsAllEntriesOf(Map .of(BUSINESS_STAKEHOLDER_PROOF_IDENTITY_CODE, "false", BUSINESS_STAKEHOLDER_PROOF_AUTH_CODE, "false")); - - assertThat(result).hasValue(miraklUpdateShopsMock); - } - - @Test - void setBusinessStakeholderFlagKYCToPushBusinessStakeholderDocumentsToFalse_whenNoShopsAreNeededForUpdate_shouldDoNothing() { - //@formatter:off - final KYCDocumentBusinessStakeHolderInfoModel kycUserOneBstOne = KYCDocumentBusinessStakeHolderInfoModel.builder() - .clientUserId("2000") - .businessStakeholderMiraklNumber(1) - .sentToHyperwallet(Boolean.FALSE) - .build(); - //@formatter:on - - final Optional result = testObj - .setBusinessStakeholderFlagKYCToPushBusinessStakeholderDocumentsToFalse( - Collections.singletonList(kycUserOneBstOne)); - - assertThat(result).isEmpty(); - - verifyNoInteractions(miraklMarketplacePlatformOperatorApiClientMock); - } - - @Test - void setBusinessStakeholderFlagKYCToPushBusinessStakeholderDocumentsToFalse_whenAnEmptyListIsPassedAsParam_shouldDoNothing() { - testObj.setBusinessStakeholderFlagKYCToPushBusinessStakeholderDocumentsToFalse(List.of()); - - verifyNoInteractions(miraklMarketplacePlatformOperatorApiClientMock); } @Test void setBusinessStakeholderFlagKYCToPushBusinessStakeholderDocumentsToFalse_whenMiraklExceptionIsThrown_shouldSendEmailNotification() { //@formatter:off - final KYCDocumentBusinessStakeHolderInfoModel kycDocumentOne = KYCDocumentBusinessStakeHolderInfoModel.builder() - .clientUserId("2000") - .businessStakeholderMiraklNumber(1) - .requiresKYC(Boolean.TRUE) - .sentToHyperwallet(Boolean.TRUE) - .build(); - final List successfullyPushedDocumentsList = List.of(kycDocumentOne); - //@formatter:on + final KYCDocumentBusinessStakeHolderInfoModel kycDocumentOne = KYCDocumentBusinessStakeHolderInfoModel.builder() + .clientUserId("2000") + .businessStakeholderMiraklNumber(1) + .requiresKYC(Boolean.TRUE) + .build(); + //@formatter:on final MiraklException miraklException = new MiraklException("Something went wrong"); doThrow(miraklException).when(miraklMarketplacePlatformOperatorApiClientMock) .updateShops(any(MiraklUpdateShopsRequest.class)); - testObj.setBusinessStakeholderFlagKYCToPushBusinessStakeholderDocumentsToFalse(successfullyPushedDocumentsList); + assertThatThrownBy( + () -> testObj.setBusinessStakeholderFlagKYCToPushBusinessStakeholderDocumentsToFalse(kycDocumentOne)) + .isInstanceOf(HMCMiraklAPIException.class); verify(kycMailNotificationUtilMock).sendPlainTextEmail("Issue setting push document flags to false in Mirakl", String.format( - "Something went wrong setting push document flag to false in Mirakl for shop Id [2000]%n%s", - String.join(",", MiraklLoggingErrorsUtil.stringify(miraklException)))); + "Something went wrong setting push document flag to false in Mirakl for Shop Id [2000] and Business Stakeholder number [1]%n%s", + MiraklLoggingErrorsUtil.stringify(miraklException))); } private Map getUpdatedFlagValuesForShop(final MiraklUpdateShopsRequest miraklUpdateShopRequest, diff --git a/kyc/src/test/java/com/paypal/kyc/service/documents/files/mirakl/impl/MiraklSellerDocumentsExtractServiceImplTest.java b/kyc/src/test/java/com/paypal/kyc/service/documents/files/mirakl/impl/MiraklSellerDocumentsExtractServiceImplTest.java index 22726a61..4592b56a 100644 --- a/kyc/src/test/java/com/paypal/kyc/service/documents/files/mirakl/impl/MiraklSellerDocumentsExtractServiceImplTest.java +++ b/kyc/src/test/java/com/paypal/kyc/service/documents/files/mirakl/impl/MiraklSellerDocumentsExtractServiceImplTest.java @@ -10,6 +10,8 @@ import com.mirakl.client.mmp.request.additionalfield.MiraklRequestAdditionalFieldValue; import com.mirakl.client.mmp.request.shop.MiraklGetShopsRequest; import com.paypal.infrastructure.converter.Converter; +import com.paypal.infrastructure.exceptions.HMCHyperwalletAPIException; +import com.paypal.infrastructure.exceptions.HMCMiraklAPIException; import com.paypal.infrastructure.mail.MailNotificationUtil; import com.paypal.infrastructure.util.MiraklLoggingErrorsUtil; import com.paypal.kyc.model.KYCDocumentInfoModel; @@ -28,6 +30,7 @@ import java.util.stream.Collectors; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) @@ -153,16 +156,11 @@ void extractProofOfIdentityAndBusinessSellerDocuments_shouldReturnAnEmptyListWhe void setFlagToPushSellerDocumentsToFalse_shouldCallMiraklWithTheClientUsersIdPassedAsParam() { final KYCDocumentSellerInfoModel kycDocumentOne = KYCDocumentSellerInfoModel.builder().clientUserId("2000") .build(); - final KYCDocumentSellerInfoModel kycDocumentTwo = KYCDocumentSellerInfoModel.builder().clientUserId("2001") - .build(); - final List successfullyPushedDocumentsList = List.of(kycDocumentOne, - kycDocumentTwo); when(miraklMarketplacePlatformOperatorApiClientMock.updateShops(any(MiraklUpdateShopsRequest.class))) .thenReturn(miraklUpdateShopsMock); - final Optional result = testObj - .setFlagToPushProofOfIdentityAndBusinessSellerDocumentsToFalse(successfullyPushedDocumentsList); + testObj.setFlagToPushProofOfIdentityAndBusinessSellerDocumentsToFalse(kycDocumentOne); verify(miraklMarketplacePlatformOperatorApiClientMock).updateShops(miraklUpdateShopArgumentCaptor.capture()); @@ -184,38 +182,27 @@ void setFlagToPushSellerDocumentsToFalse_shouldCallMiraklWithTheClientUsersIdPas .map(MiraklRequestAdditionalFieldValue.MiraklSimpleRequestAdditionalFieldValue::getCode) .collect(Collectors.toList()); - assertThat(updatedSellerIdList).containsExactlyInAnyOrder(2000L, 2001L); - assertThat(updatedFlagValueList).containsExactlyInAnyOrder("false", "false"); - assertThat(updatedFlagCodeList).containsExactlyInAnyOrder( - HYPERWALLET_KYC_REQUIRED_PROOF_IDENTITY_BUSINESS_FIELD, - HYPERWALLET_KYC_REQUIRED_PROOF_IDENTITY_BUSINESS_FIELD); - - assertThat(result).hasValue(miraklUpdateShopsMock); - } - - @Test - void setFlagToPushSellerDocumentsToFalse_shouldDoNothingWhenAnEmptyListIsPassedAsParam() { - testObj.setFlagToPushProofOfIdentityAndBusinessSellerDocumentsToFalse(List.of()); - verifyNoInteractions(miraklMarketplacePlatformOperatorApiClientMock); + assertThat(updatedSellerIdList).containsOnly(2000L); + assertThat(updatedFlagValueList).containsExactly("false"); + assertThat(updatedFlagCodeList).containsExactly(HYPERWALLET_KYC_REQUIRED_PROOF_IDENTITY_BUSINESS_FIELD); } @Test void setFlagToPushSellerDocumentsToFalse_shouldSendEmailNotificationWhenMiraklExceptionIsThrown() { final KYCDocumentSellerInfoModel kycDocumentOne = KYCDocumentSellerInfoModel.builder().clientUserId("2000") .build(); - final List successfullyPushedDocumentsList = List.of(kycDocumentOne); final MiraklException miraklException = new MiraklException("Something went wrong"); doThrow(miraklException).when(miraklMarketplacePlatformOperatorApiClientMock) .updateShops(any(MiraklUpdateShopsRequest.class)); - testObj.setFlagToPushProofOfIdentityAndBusinessSellerDocumentsToFalse(successfullyPushedDocumentsList); + assertThatThrownBy(() -> testObj.setFlagToPushProofOfIdentityAndBusinessSellerDocumentsToFalse(kycDocumentOne)) + .isInstanceOf(HMCMiraklAPIException.class); verify(kycMailNotificationUtilMock).sendPlainTextEmail("Issue setting push document flags to false in Mirakl", - String.format( - "Something went wrong setting push document flag to false in Mirakl for shop Id [2000]%n%s", - String.join(",", MiraklLoggingErrorsUtil.stringify(miraklException)))); + String.format("Something went wrong setting push document flag to false in Mirakl for Shop Id 2000%n%s", + MiraklLoggingErrorsUtil.stringify(miraklException))); } @Test diff --git a/kyc/src/test/java/com/paypal/kyc/service/impl/DocumentsExtractServiceImplTest.java b/kyc/src/test/java/com/paypal/kyc/service/impl/DocumentsExtractServiceImplTest.java deleted file mode 100644 index b54329a5..00000000 --- a/kyc/src/test/java/com/paypal/kyc/service/impl/DocumentsExtractServiceImplTest.java +++ /dev/null @@ -1,128 +0,0 @@ -package com.paypal.kyc.service.impl; - -import com.callibrity.logging.test.LogTracker; -import com.callibrity.logging.test.LogTrackerStub; -import com.paypal.kyc.model.KYCDocumentBusinessStakeHolderInfoModel; -import com.paypal.kyc.model.KYCDocumentModel; -import com.paypal.kyc.model.KYCDocumentSellerInfoModel; -import com.paypal.kyc.service.documents.files.hyperwallet.HyperwalletBusinessStakeholderExtractService; -import com.paypal.kyc.service.documents.files.hyperwallet.HyperwalletSellerExtractService; -import com.paypal.kyc.service.documents.files.mirakl.MiraklBusinessStakeholderDocumentsExtractService; -import com.paypal.kyc.service.documents.files.mirakl.MiraklSellerDocumentsExtractService; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.api.extension.RegisterExtension; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.io.File; -import java.util.Date; -import java.util.List; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -@ExtendWith(MockitoExtension.class) -class DocumentsExtractServiceImplTest { - - @InjectMocks - private DocumentsExtractServiceImpl testObj; - - @Mock - private HyperwalletSellerExtractService hyperwalletSellerExtractServiceMock; - - @Mock - private MiraklSellerDocumentsExtractService miraklSellerDocumentsExtractServiceMock; - - @Mock - private HyperwalletBusinessStakeholderExtractService hyperwalletBusinessStakeholderExtractServiceMock; - - @Mock - private MiraklBusinessStakeholderDocumentsExtractService miraklBusinessStakeholderDocumentsExtractServiceMock; - - @Mock - private Date deltaMock; - - @Mock - private File fileOneMock, fileTwoMock; - - @Mock - private KYCDocumentSellerInfoModel kycDocumentSellerInfoModelOneMock, kycDocumentSellerInfoModelEmptyMock; - - @Mock - private KYCDocumentBusinessStakeHolderInfoModel kycDocumentBusinessStakeHolderInfoModelOneMock, - kycDocumentBusinessStakeHolderInfoModelEmptyMock; - - @RegisterExtension - LogTrackerStub logTrackerStub = LogTrackerStub.create().recordForLevel(LogTracker.LogLevel.INFO) - .recordForType(DocumentsExtractServiceImpl.class); - - @Test - void extractProofOfIdentityAndBusinessSellerDocuments_shouldRetrieveAllKYCSellerInfoModelFromMiraklAndPushThemIntoHyperwalletAndSetDocumentFlagToFalseBasedOnPushDocumentsResponse() { - final List kycDocumentSellerInfoModelList = List - .of(kycDocumentSellerInfoModelOneMock, kycDocumentSellerInfoModelEmptyMock); - when(miraklSellerDocumentsExtractServiceMock.extractProofOfIdentityAndBusinessSellerDocuments(deltaMock)) - .thenReturn(kycDocumentSellerInfoModelList); - final List successFullPushedListOfDocuments = List - .of(kycDocumentSellerInfoModelOneMock); - when(hyperwalletSellerExtractServiceMock - .pushProofOfIdentityAndBusinessSellerDocuments(kycDocumentSellerInfoModelList)) - .thenReturn(successFullPushedListOfDocuments); - - testObj.extractProofOfIdentityAndBusinessSellerDocuments(deltaMock); - - verify(miraklSellerDocumentsExtractServiceMock).extractProofOfIdentityAndBusinessSellerDocuments(deltaMock); - verify(hyperwalletSellerExtractServiceMock) - .pushProofOfIdentityAndBusinessSellerDocuments(kycDocumentSellerInfoModelList); - verify(miraklSellerDocumentsExtractServiceMock) - .setFlagToPushProofOfIdentityAndBusinessSellerDocumentsToFalse(successFullPushedListOfDocuments); - } - - @Test - void extractBusinessStakeholderDocuments_shouldRetrieveAllKYCBusinessStakeholderInfoModelFromMiraklAndSetDocumentFlagToFalseBasedOnPushDocumentsResponse() { - final List kycDocumentBusinessStakeholderInfoModelList = List - .of(kycDocumentBusinessStakeHolderInfoModelOneMock, kycDocumentBusinessStakeHolderInfoModelEmptyMock); - when(miraklBusinessStakeholderDocumentsExtractServiceMock.extractBusinessStakeholderDocuments(deltaMock)) - .thenReturn(kycDocumentBusinessStakeholderInfoModelList); - final List successFullPushedListOfDocuments = List - .of(kycDocumentBusinessStakeHolderInfoModelOneMock); - when(hyperwalletBusinessStakeholderExtractServiceMock - .pushBusinessStakeholderDocuments(kycDocumentBusinessStakeholderInfoModelList)) - .thenReturn(successFullPushedListOfDocuments); - - testObj.extractBusinessStakeholderDocuments(deltaMock); - - verify(miraklBusinessStakeholderDocumentsExtractServiceMock).extractBusinessStakeholderDocuments(deltaMock); - verify(hyperwalletBusinessStakeholderExtractServiceMock) - .pushBusinessStakeholderDocuments(kycDocumentBusinessStakeholderInfoModelList); - verify(miraklBusinessStakeholderDocumentsExtractServiceMock) - .setBusinessStakeholderFlagKYCToPushBusinessStakeholderDocumentsToFalse( - successFullPushedListOfDocuments); - } - - @Test - void cleanUpFiles_shouldRemoveFilesReceivedAsParameter() { - - final KYCDocumentModel kycDocumentModelOne = KYCDocumentModel.builder().file(fileOneMock).build(); - final KYCDocumentModel kycDocumentModelTwo = KYCDocumentModel.builder().file(fileTwoMock).build(); - final KYCDocumentSellerInfoModel kycDocumentOne = KYCDocumentSellerInfoModel.builder().clientUserId("2000") - .documents(List.of(kycDocumentModelOne, kycDocumentModelTwo)).build(); - final List successfullyPushedDocumentsList = List.of(kycDocumentOne); - - testObj.cleanUpDocumentsFiles(successfullyPushedDocumentsList); - - verify(fileOneMock).delete(); - verify(fileTwoMock).delete(); - assertThat(logTrackerStub.contains("Cleaning up done successfully!")).isTrue(); - } - - @Test - void cleanUpFiles_shouldNotDoAnythingWhenNullParameterIsReceived() { - - testObj.cleanUpDocumentsFiles(null); - assertThat(logTrackerStub.contains("Cleaning up done successfully!")).isTrue(); - } - -} diff --git a/kyc/src/test/java/com/paypal/kyc/service/impl/KYCReadyForReviewServiceImplTest.java b/kyc/src/test/java/com/paypal/kyc/service/impl/KYCReadyForReviewServiceImplTest.java index dcff7f72..1a5d2a21 100644 --- a/kyc/src/test/java/com/paypal/kyc/service/impl/KYCReadyForReviewServiceImplTest.java +++ b/kyc/src/test/java/com/paypal/kyc/service/impl/KYCReadyForReviewServiceImplTest.java @@ -6,6 +6,7 @@ import com.hyperwallet.clientsdk.HyperwalletException; import com.hyperwallet.clientsdk.model.HyperwalletUser; import com.mirakl.client.mmp.domain.common.MiraklAdditionalFieldValue; +import com.paypal.infrastructure.exceptions.HMCHyperwalletAPIException; import com.paypal.infrastructure.mail.MailNotificationUtil; import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; import com.paypal.kyc.model.KYCConstants; @@ -21,6 +22,7 @@ import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) @@ -58,35 +60,7 @@ class KYCReadyForReviewServiceImplTest { .recordForType(KYCReadyForReviewServiceImpl.class); @Test - void notifyDocumentsSent_whenDocumentsWereSentToHyperwallet_shouldNotifyBstkReadyForReview() { - //@formatter:off - final KYCDocumentBusinessStakeHolderInfoModel kycDocumentSent = KYCDocumentBusinessStakeHolderInfoModel.builder() - .userToken(List.of(new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue( - KYCConstants.HYPERWALLET_USER_TOKEN_FIELD, USER_TOKEN_1))) - .hyperwalletProgram(HYPERWALLET_PROGRAM) - .sentToHyperwallet(Boolean.TRUE) - .build(); - //@formatter:on - - //@formatter:off - final KYCDocumentBusinessStakeHolderInfoModel kycDocumentNotSent = KYCDocumentBusinessStakeHolderInfoModel.builder() - .userToken(List.of(new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue( - KYCConstants.HYPERWALLET_USER_TOKEN_FIELD, USER_TOKEN_2))) - .hyperwalletProgram(HYPERWALLET_PROGRAM) - .sentToHyperwallet(Boolean.FALSE) - .build(); - //@formatter:on - - doNothing().when(testObj).notifyBstkReadyForReview(Map.entry(USER_TOKEN_1, List.of(kycDocumentSent))); - - testObj.notifyReadyForReview(List.of(kycDocumentSent, kycDocumentNotSent)); - - verify(testObj).notifyBstkReadyForReview(Map.entry(USER_TOKEN_1, List.of(kycDocumentSent))); - verify(testObj, never()).notifyBstkReadyForReview(Map.entry(USER_TOKEN_2, List.of(kycDocumentNotSent))); - } - - @Test - void notifyBstkReadyForReview_shouldRunNotifyBusinessStakeholderToHW() { + void notifyReadyForReview_shouldRunNotifyBusinessStakeholderToHW() { //@formatter:off final KYCDocumentBusinessStakeHolderInfoModel kycDocumentOne = KYCDocumentBusinessStakeHolderInfoModel.builder() .hyperwalletProgram(HYPERWALLET_PROGRAM) @@ -100,7 +74,7 @@ void notifyBstkReadyForReview_shouldRunNotifyBusinessStakeholderToHW() { when(hyperwalletSDKServiceMock.getHyperwalletInstance(HYPERWALLET_PROGRAM)) .thenReturn(hyperwalletApiClientMock); - testObj.notifyBstkReadyForReview(Map.entry(USER_TOKEN_1, List.of(kycDocumentOne))); + testObj.notifyReadyForReview(kycDocumentOne); verify(hyperwalletApiClientMock).updateUser(hyperwalletUserCaptor.capture()); @@ -127,11 +101,12 @@ void notifyBstkReadyForReview_shouldSendAnEmailWhenThereIsAnErrorNotifyingToHW() HyperwalletException hwException = new HyperwalletException("Something bad happened"); doThrow(hwException).when(hyperwalletApiClientMock).updateUser(Mockito.any(HyperwalletUser.class)); - testObj.notifyBstkReadyForReview(Map.entry(USER_TOKEN_1, List.of(kycDocumentSent))); + assertThatThrownBy(() -> testObj.notifyReadyForReview(kycDocumentSent)) + .isInstanceOf(HMCHyperwalletAPIException.class); verify(hyperwalletSDKServiceMock).getHyperwalletInstance(HYPERWALLET_PROGRAM); verify(hyperwalletApiClientMock).updateUser(hyperwalletUserCaptor.capture()); - verify(testObj).notifyBstkReadyForReview(Map.entry(USER_TOKEN_1, List.of(kycDocumentSent))); + verify(testObj).notifyReadyForReview(kycDocumentSent); verify(kycMailNotificationUtilMock).sendPlainTextEmail("Issue in Hyperwallet status notification", String.format( "There was an error notifying Hyperwallet all documents were sent for shop Id [2000], so Hyperwallet will not be notified about this new situation%n%s", @@ -150,7 +125,7 @@ void notifyBstk_shouldShowLogSayingClientIdHasNoHyperwalletProgramAssigned() { .build(); //@formatter:on - testObj.notifyBstkReadyForReview(Map.entry(USER_TOKEN_1, List.of(kycDocumentOne))); + testObj.notifyReadyForReview(kycDocumentOne); assertThat(logTrackerStub.contains("Seller with shop Id [2000] has no Hyperwallet Program")).isTrue(); } diff --git a/kyc/src/test/java/com/paypal/kyc/service/impl/KYCReadyForReviewServiceMockImplTest.java b/kyc/src/test/java/com/paypal/kyc/service/impl/KYCReadyForReviewServiceMockImplTest.java index d274ed30..db8ea304 100644 --- a/kyc/src/test/java/com/paypal/kyc/service/impl/KYCReadyForReviewServiceMockImplTest.java +++ b/kyc/src/test/java/com/paypal/kyc/service/impl/KYCReadyForReviewServiceMockImplTest.java @@ -4,6 +4,7 @@ import com.callibrity.logging.test.LogTrackerStub; import com.hyperwallet.clientsdk.HyperwalletException; import com.mirakl.client.mmp.domain.common.MiraklAdditionalFieldValue; +import com.paypal.infrastructure.exceptions.HMCHyperwalletAPIException; import com.paypal.infrastructure.mail.MailNotificationUtil; import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; import com.paypal.kyc.model.KYCConstants; @@ -21,6 +22,7 @@ import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; @@ -59,14 +61,13 @@ void notifyReadyForReview_whenBusinessStakeholderIsCorrectlyFilled_shouldCallToN .userToken(List.of(new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue( KYCConstants.HYPERWALLET_USER_TOKEN_FIELD, USER_TOKEN))) .hyperwalletProgram(HYPERWALLET_PROGRAM) - .sentToHyperwallet(Boolean.TRUE) .build(); - doNothing().when(testObj).notifyBstkReadyForReview(Map.entry(USER_TOKEN, List.of(kycDocumentOne))); + doNothing().when(testObj).notifyReadyForReview(kycDocumentOne); - testObj.notifyReadyForReview(List.of(kycDocumentOne)); + testObj.notifyReadyForReview(kycDocumentOne); - verify(testObj).notifyBstkReadyForReview(Map.entry(USER_TOKEN, List.of(kycDocumentOne))); + verify(testObj).notifyReadyForReview(kycDocumentOne); } @Test @@ -81,7 +82,7 @@ void notifyBstkReadyForReview_shouldRunNotifyBusinessStakeholderToMockServer() { when(testObj.getMockServerUrl()).thenReturn(MOCK_SERVER_URL); - testObj.notifyBstkReadyForReview(Map.entry(USER_TOKEN, List.of(kycDocumentOne))); + testObj.notifyReadyForReview(kycDocumentOne); verify(restTemplateMock).put(eq(MOCK_SERVER_URL + HYPERWALLET_NOTIFY_USER), any(), eq(Object.class)); } @@ -99,7 +100,8 @@ void notifyBstkReadyForReview_whenThereIsAnErrorNotifyingToHW_shouldSendAnEmail( HyperwalletException hwException = new HyperwalletException("Something bad happened"); doThrow(hwException).when(restTemplateMock).put(any(String.class), any(String.class), any(Object.class)); - testObj.notifyBstkReadyForReview(Map.entry(USER_TOKEN, List.of(kycDocumentOne))); + assertThatThrownBy(() -> testObj.notifyReadyForReview(kycDocumentOne)) + .isInstanceOf(HMCHyperwalletAPIException.class); verify(mailNotificationUtilMock).sendPlainTextEmail("Issue in Hyperwallet status notification", String.format( "There was an error notifying Hyperwallet all documents were sent for shop Id [2000], so Hyperwallet will not be notified about this new situation%n%s", diff --git a/notifications/src/main/java/com/paypal/notifications/NotificationsSpringContextConfiguration.java b/notifications/src/main/java/com/paypal/notifications/NotificationsSpringContextConfiguration.java index 4e4a054c..09843eea 100644 --- a/notifications/src/main/java/com/paypal/notifications/NotificationsSpringContextConfiguration.java +++ b/notifications/src/main/java/com/paypal/notifications/NotificationsSpringContextConfiguration.java @@ -1,18 +1,13 @@ package com.paypal.notifications; import com.paypal.infrastructure.InfrastructureConnectorApplication; -import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.PropertySource; -@SpringBootApplication +@ComponentScan @PropertySource({ "classpath:notifications.properties" }) @ImportAutoConfiguration({ InfrastructureConnectorApplication.class }) public class NotificationsSpringContextConfiguration { - public static void main(final String[] args) { - SpringApplication.run(NotificationsSpringContextConfiguration.class, args); - } - } diff --git a/reports/src/main/java/com/paypal/reports/ReportsSpringContextConfiguration.java b/reports/src/main/java/com/paypal/reports/ReportsSpringContextConfiguration.java index 04d74c50..e1425929 100644 --- a/reports/src/main/java/com/paypal/reports/ReportsSpringContextConfiguration.java +++ b/reports/src/main/java/com/paypal/reports/ReportsSpringContextConfiguration.java @@ -2,20 +2,15 @@ import com.paypal.infrastructure.InfrastructureConnectorApplication; import com.paypal.reports.infraestructure.configuration.ReportsMiraklApiConfig; -import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.ImportAutoConfiguration; -import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Profile; -@SpringBootApplication +@ComponentScan @EnableConfigurationProperties({ ReportsMiraklApiConfig.class }) @ImportAutoConfiguration({ InfrastructureConnectorApplication.class }) @Profile("financial-report") public class ReportsSpringContextConfiguration { - public static void main(final String[] args) { - SpringApplication.run(ReportsSpringContextConfiguration.class, args); - } - } diff --git a/sellers/src/main/java/com/paypal/sellers/SellersSpringContextConfiguration.java b/sellers/src/main/java/com/paypal/sellers/SellersSpringContextConfiguration.java index 9c5ba36f..31bf68ec 100644 --- a/sellers/src/main/java/com/paypal/sellers/SellersSpringContextConfiguration.java +++ b/sellers/src/main/java/com/paypal/sellers/SellersSpringContextConfiguration.java @@ -1,16 +1,11 @@ package com.paypal.sellers; import com.paypal.sellers.infrastructure.configuration.SellersMiraklApiConfig; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.ComponentScan; -@SpringBootApplication +@ComponentScan @EnableConfigurationProperties({ SellersMiraklApiConfig.class }) public class SellersSpringContextConfiguration { - public static void main(final String[] args) { - SpringApplication.run(SellersSpringContextConfiguration.class, args); - } - } diff --git a/sellers/src/main/java/com/paypal/sellers/bankaccountextract/model/ABABankAccountModel.java b/sellers/src/main/java/com/paypal/sellers/bankaccountextract/model/ABABankAccountModel.java index 03eeb74a..e2a7d0f2 100644 --- a/sellers/src/main/java/com/paypal/sellers/bankaccountextract/model/ABABankAccountModel.java +++ b/sellers/src/main/java/com/paypal/sellers/bankaccountextract/model/ABABankAccountModel.java @@ -24,6 +24,31 @@ public static Builder builder() { return new Builder(); } + @Override + public Builder toBuilder() { + //@formatter:off + return ABABankAccountModel.builder() + .buildTransferMethodCountry(transferMethodCountry) + .buildTransferMethodCurrency(transferMethodCurrency) + .transferType(transferType) + .type(type) + .bankAccountNumber(bankAccountNumber) + .businessName(businessName) + .firstName(firstName) + .lastName(lastName) + .buildCountry(country) + .addressLine1(addressLine1) + .addressLine2(addressLine2) + .city(city) + .stateProvince(stateProvince) + .postalCode(postalCode) + .token(token) + .hyperwalletProgram(hyperwalletProgram) + .branchId(branchId) + .bankAccountPurpose(bankAccountPurpose); + //@formatter:on + } + public static class Builder extends BankAccountModel.Builder { private String branchId; diff --git a/sellers/src/main/java/com/paypal/sellers/bankaccountextract/model/BankAccountModel.java b/sellers/src/main/java/com/paypal/sellers/bankaccountextract/model/BankAccountModel.java index 72ef7a97..5de1f377 100644 --- a/sellers/src/main/java/com/paypal/sellers/bankaccountextract/model/BankAccountModel.java +++ b/sellers/src/main/java/com/paypal/sellers/bankaccountextract/model/BankAccountModel.java @@ -21,37 +21,37 @@ @Getter public class BankAccountModel { - private final String transferMethodCountry; + protected final String transferMethodCountry; - private final String transferMethodCurrency; + protected final String transferMethodCurrency; - private final TransferType transferType; + protected final TransferType transferType; - private final BankAccountType type; + protected final BankAccountType type; - private final String bankAccountNumber; + protected final String bankAccountNumber; - private final String businessName; + protected final String businessName; - private final String firstName; + protected final String firstName; - private final String lastName; + protected final String lastName; - private final String country; + protected final String country; - private final String addressLine1; + protected final String addressLine1; - private final String addressLine2; + protected final String addressLine2; - private final String city; + protected final String city; - private final String stateProvince; + protected final String stateProvince; - private final String postalCode; + protected final String postalCode; - private final String token; + protected final String token; - private final String hyperwalletProgram; + protected final String hyperwalletProgram; protected BankAccountModel(final Builder builder) { transferMethodCountry = builder.transferMethodCountry; @@ -107,6 +107,29 @@ public int hashCode() { getAddressLine1(), getAddressLine2(), getCity(), getStateProvince(), getPostalCode(), getToken()); } + @SuppressWarnings("java:S3740") + public Builder toBuilder() { + //@formatter:off + return BankAccountModel.builder() + .buildTransferMethodCountry(transferMethodCountry) + .buildTransferMethodCurrency(transferMethodCurrency) + .transferType(transferType) + .type(type) + .bankAccountNumber(bankAccountNumber) + .businessName(businessName) + .firstName(firstName) + .lastName(lastName) + .buildCountry(country) + .addressLine1(addressLine1) + .addressLine2(addressLine2) + .city(city) + .stateProvince(stateProvince) + .postalCode(postalCode) + .token(token) + .hyperwalletProgram(hyperwalletProgram); + //@formatter:on + } + @SuppressWarnings("java:S3740") public static Builder builder() { return new Builder() { @@ -162,6 +185,11 @@ public T transferMethodCountry(final String transferMethodCountry) { return getThis(); } + protected T buildTransferMethodCountry(final String transferMethodCountry) { + this.transferMethodCountry = transferMethodCountry; + return getThis(); + } + public T transferMethodCurrency(final String transferMethodCurrency) { try { Optional.of(Monetary.getCurrency(transferMethodCurrency)) @@ -175,6 +203,11 @@ public T transferMethodCurrency(final String transferMethodCurrency) { return getThis(); } + protected T buildTransferMethodCurrency(final String transferMethodCurrency) { + this.transferMethodCurrency = transferMethodCurrency; + return getThis(); + } + public T transferType(final TransferType type) { transferType = type; return getThis(); @@ -213,6 +246,11 @@ public T country(final String country) { return getThis(); } + protected T buildCountry(final String country) { + this.country = country; + return getThis(); + } + public T addressLine1(final String addressLine1) { this.addressLine1 = addressLine1; return getThis(); @@ -233,6 +271,11 @@ public T stateProvince(final List fieldValues) { return getThis(); } + public T stateProvince(final String stateProvince) { + this.stateProvince = stateProvince; + return getThis(); + } + public T postalCode(final String postalCode) { this.postalCode = postalCode; return getThis(); @@ -244,6 +287,11 @@ public T token(final List fieldValues) { return getThis(); } + public T token(final String token) { + this.token = token; + return getThis(); + } + public T hyperwalletProgram(final String hyperwalletProgram) { this.hyperwalletProgram = hyperwalletProgram; return getThis(); diff --git a/sellers/src/main/java/com/paypal/sellers/bankaccountextract/model/CanadianBankAccountModel.java b/sellers/src/main/java/com/paypal/sellers/bankaccountextract/model/CanadianBankAccountModel.java index fe2411ed..4b79a853 100644 --- a/sellers/src/main/java/com/paypal/sellers/bankaccountextract/model/CanadianBankAccountModel.java +++ b/sellers/src/main/java/com/paypal/sellers/bankaccountextract/model/CanadianBankAccountModel.java @@ -22,6 +22,31 @@ public static CanadianBankAccountModel.Builder builder() { return new CanadianBankAccountModel.Builder(); } + @Override + public Builder toBuilder() { + //@formatter:off + return CanadianBankAccountModel.builder() + .buildTransferMethodCountry(transferMethodCountry) + .buildTransferMethodCurrency(transferMethodCurrency) + .transferType(transferType) + .type(type) + .bankAccountNumber(bankAccountNumber) + .businessName(businessName) + .firstName(firstName) + .lastName(lastName) + .buildCountry(country) + .addressLine1(addressLine1) + .addressLine2(addressLine2) + .city(city) + .stateProvince(stateProvince) + .postalCode(postalCode) + .token(token) + .hyperwalletProgram(hyperwalletProgram) + .bankId(bankId) + .branchId(branchId); + //@formatter:on + } + public static class Builder extends BankAccountModel.Builder { private String bankId; diff --git a/sellers/src/main/java/com/paypal/sellers/bankaccountextract/model/IBANBankAccountModel.java b/sellers/src/main/java/com/paypal/sellers/bankaccountextract/model/IBANBankAccountModel.java index e810d2bf..447d3308 100644 --- a/sellers/src/main/java/com/paypal/sellers/bankaccountextract/model/IBANBankAccountModel.java +++ b/sellers/src/main/java/com/paypal/sellers/bankaccountextract/model/IBANBankAccountModel.java @@ -19,6 +19,30 @@ public static Builder builder() { return new Builder(); } + @Override + public Builder toBuilder() { + //@formatter:off + return IBANBankAccountModel.builder() + .buildTransferMethodCountry(transferMethodCountry) + .buildTransferMethodCurrency(transferMethodCurrency) + .transferType(transferType) + .type(type) + .bankAccountNumber(bankAccountNumber) + .businessName(businessName) + .firstName(firstName) + .lastName(lastName) + .buildCountry(country) + .addressLine1(addressLine1) + .addressLine2(addressLine2) + .city(city) + .stateProvince(stateProvince) + .postalCode(postalCode) + .token(token) + .hyperwalletProgram(hyperwalletProgram) + .bankBic(bankBic); + //@formatter:on + } + public static class Builder extends BankAccountModel.Builder { private String bankBic; diff --git a/sellers/src/main/java/com/paypal/sellers/bankaccountextract/model/UKBankAccountModel.java b/sellers/src/main/java/com/paypal/sellers/bankaccountextract/model/UKBankAccountModel.java index 165f2b9e..8c5b42f8 100644 --- a/sellers/src/main/java/com/paypal/sellers/bankaccountextract/model/UKBankAccountModel.java +++ b/sellers/src/main/java/com/paypal/sellers/bankaccountextract/model/UKBankAccountModel.java @@ -20,6 +20,30 @@ public static UKBankAccountModel.Builder builder() { return new UKBankAccountModel.Builder(); } + @Override + public Builder toBuilder() { + //@formatter:off + return UKBankAccountModel.builder() + .buildTransferMethodCountry(transferMethodCountry) + .buildTransferMethodCurrency(transferMethodCurrency) + .transferType(transferType) + .type(type) + .bankAccountNumber(bankAccountNumber) + .businessName(businessName) + .firstName(firstName) + .lastName(lastName) + .buildCountry(country) + .addressLine1(addressLine1) + .addressLine2(addressLine2) + .city(city) + .stateProvince(stateProvince) + .postalCode(postalCode) + .token(token) + .hyperwalletProgram(hyperwalletProgram) + .bankAccountId(bankAccountId); + //@formatter:on + } + public static class Builder extends BankAccountModel.Builder { private String bankAccountId; diff --git a/sellers/src/main/java/com/paypal/sellers/bankaccountextract/service/impl/BankAccountTokenSynchronizationServiceImpl.java b/sellers/src/main/java/com/paypal/sellers/bankaccountextract/service/impl/BankAccountTokenSynchronizationServiceImpl.java new file mode 100644 index 00000000..d910c5b1 --- /dev/null +++ b/sellers/src/main/java/com/paypal/sellers/bankaccountextract/service/impl/BankAccountTokenSynchronizationServiceImpl.java @@ -0,0 +1,147 @@ +package com.paypal.sellers.bankaccountextract.service.impl; + +import com.hyperwallet.clientsdk.Hyperwallet; +import com.hyperwallet.clientsdk.HyperwalletException; +import com.hyperwallet.clientsdk.model.HyperwalletBankAccount; +import com.hyperwallet.clientsdk.model.HyperwalletList; +import com.mirakl.client.core.exception.MiraklApiException; +import com.paypal.infrastructure.exceptions.HMCHyperwalletAPIException; +import com.paypal.infrastructure.exceptions.HMCMiraklAPIException; +import com.paypal.infrastructure.service.TokenSynchronizationService; +import com.paypal.sellers.bankaccountextract.model.BankAccountModel; +import com.paypal.sellers.bankaccountextract.service.MiraklBankAccountExtractService; +import com.paypal.sellers.sellersextract.model.SellerModel; +import com.paypal.sellers.service.HyperwalletSDKService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.Objects; +import java.util.Optional; + +/** + * Class that implements the {@link TokenSynchronizationService} interface for the + * synchronization of tokens for bank accounts + */ +@Slf4j +@Service("bankAccountTokenSynchronizationService") +public class BankAccountTokenSynchronizationServiceImpl implements TokenSynchronizationService { + + private final HyperwalletSDKService hyperwalletSDKService; + + private final MiraklBankAccountExtractService miraklBankAccountExtractService; + + public BankAccountTokenSynchronizationServiceImpl(final HyperwalletSDKService hyperwalletSDKService, + final MiraklBankAccountExtractService miraklBankAccountExtractService) { + + this.hyperwalletSDKService = hyperwalletSDKService; + this.miraklBankAccountExtractService = miraklBankAccountExtractService; + } + + /** + * Ensures the bank account token between Hyperwallet and Mirakl is synchronized + * @param sellerModel that contains the seller bank account item to be synchronized + * @return the seller with the bank account token synchronized + */ + @Override + public SellerModel synchronizeToken(final SellerModel sellerModel) { + + final BankAccountModel bankAccountModel = sellerModel.getBankAccountDetails(); + + if (Objects.isNull(bankAccountModel)) { + + log.debug("Not bank account for client user id [{}], synchronization not needed", + sellerModel.getClientUserId()); + + return sellerModel; + } + + if (StringUtils.isNotBlank(bankAccountModel.getToken())) { + + log.debug("Hyperwallet token already exists for bank account number [{}], synchronization not needed", + bankAccountModel.getBankAccountNumber()); + + return sellerModel; + } + + final Optional hyperwalletBankAccount = getHwBankAccount(sellerModel); + + if (hyperwalletBankAccount.isPresent()) { + + updateMiraklBankAccount(sellerModel, hyperwalletBankAccount.get()); + + return updateSellerBankAccountWithHyperwalletToken(sellerModel, hyperwalletBankAccount.get()); + + } + else { + + return sellerModel; + } + } + + private Optional getHwBankAccount(final SellerModel sellerModel) { + + final HyperwalletList hyperwalletBankAccounts = getHwBankAccountByClientUserId( + sellerModel); + + if (CollectionUtils.isEmpty(hyperwalletBankAccounts.getData())) { + + log.debug("Hyperwallet bank account for client user id [{}] not found", sellerModel.getClientUserId()); + + return Optional.empty(); + + } + else { + + log.debug("Hyperwallet bank account for client user id [{}] found", sellerModel.getClientUserId()); + + return Optional.of(hyperwalletBankAccounts.getData().get(0)); + } + } + + private HyperwalletList getHwBankAccountByClientUserId(final SellerModel sellerModel) { + + final Hyperwallet hyperwalletSDK = hyperwalletSDKService + .getHyperwalletInstanceByProgramToken(sellerModel.getProgramToken()); + + try { + + return hyperwalletSDK.listBankAccounts(sellerModel.getToken()); + + } + catch (final HyperwalletException exception) { + + log.error("Error while getting Hyperwallet bank account by clientUserId [{}]", + sellerModel.getClientUserId(), exception); + + throw new HMCHyperwalletAPIException(exception); + } + } + + private void updateMiraklBankAccount(final SellerModel sellerModel, + final HyperwalletBankAccount hyperwalletBankAccount) { + + try { + + miraklBankAccountExtractService.updateBankAccountToken(sellerModel, hyperwalletBankAccount); + + } + catch (final MiraklApiException exception) { + + log.error("Error while updating Mirakl bank account by clientUserId [{}]", sellerModel.getClientUserId(), + exception); + + throw new HMCMiraklAPIException(exception); + } + } + + private SellerModel updateSellerBankAccountWithHyperwalletToken(final SellerModel sellerModel, + final HyperwalletBankAccount hyperwalletBankAccount) { + + return sellerModel.toBuilder().bankAccountDetails( + sellerModel.getBankAccountDetails().toBuilder().token(hyperwalletBankAccount.getToken()).build()) + .build(); + } + +} diff --git a/sellers/src/main/java/com/paypal/sellers/bankaccountextract/service/strategies/AbstractHyperwalletBankAccountRetryApiStrategy.java b/sellers/src/main/java/com/paypal/sellers/bankaccountextract/service/strategies/AbstractHyperwalletBankAccountRetryApiStrategy.java index ecf260d8..c4c2e68d 100644 --- a/sellers/src/main/java/com/paypal/sellers/bankaccountextract/service/strategies/AbstractHyperwalletBankAccountRetryApiStrategy.java +++ b/sellers/src/main/java/com/paypal/sellers/bankaccountextract/service/strategies/AbstractHyperwalletBankAccountRetryApiStrategy.java @@ -2,24 +2,23 @@ import com.hyperwallet.clientsdk.HyperwalletException; import com.hyperwallet.clientsdk.model.HyperwalletBankAccount; +import com.mirakl.client.core.exception.MiraklApiException; +import com.paypal.infrastructure.exceptions.HMCHyperwalletAPIException; +import com.paypal.infrastructure.exceptions.HMCMiraklAPIException; import com.paypal.infrastructure.mail.MailNotificationUtil; import com.paypal.infrastructure.strategy.Strategy; import com.paypal.infrastructure.strategy.StrategyExecutor; import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; -import com.paypal.sellers.entity.FailedBankAccountInformation; +import com.paypal.infrastructure.util.MiraklLoggingErrorsUtil; import com.paypal.sellers.sellersextract.model.SellerModel; -import com.paypal.sellers.service.AbstractHyperwalletRetryAPIStrategy; -import com.paypal.sellers.service.FailedEntityInformationService; import com.paypal.sellers.service.HyperwalletSDKService; import lombok.extern.slf4j.Slf4j; -import java.io.IOException; import java.util.Objects; import java.util.Optional; @Slf4j public abstract class AbstractHyperwalletBankAccountRetryApiStrategy - extends AbstractHyperwalletRetryAPIStrategy implements Strategy> { protected final StrategyExecutor sellerModelToHyperwalletBankAccountStrategyExecutor; @@ -32,10 +31,8 @@ public abstract class AbstractHyperwalletBankAccountRetryApiStrategy + "information:\n"; protected AbstractHyperwalletBankAccountRetryApiStrategy( - final FailedEntityInformationService failedEntityInformationService, final StrategyExecutor sellerModelToHyperwalletBankAccountStrategyExecutor, final HyperwalletSDKService hyperwalletSDKService, final MailNotificationUtil mailNotificationUtil) { - super(failedEntityInformationService); this.sellerModelToHyperwalletBankAccountStrategyExecutor = sellerModelToHyperwalletBankAccountStrategyExecutor; this.hyperwalletSDKService = hyperwalletSDKService; this.mailNotificationUtil = mailNotificationUtil; @@ -46,7 +43,6 @@ protected AbstractHyperwalletBankAccountRetryApiStrategy( */ @Override public Optional execute(final SellerModel seller) { - boolean includedAsFailed = false; HyperwalletBankAccount hwCreatedBankAccount = null; final HyperwalletBankAccount hwBankAccountRequest = sellerModelToHyperwalletBankAccountStrategyExecutor .execute(seller); @@ -56,9 +52,7 @@ public Optional execute(final SellerModel seller) { log.info("Bank account created or updated for seller with clientId [{}]", seller.getClientUserId()); } catch (final HyperwalletException e) { - if (e.getCause() instanceof IOException) { - includedAsFailed = true; - } + mailNotificationUtil .sendPlainTextEmail("Issue detected when creating or updating bank account in Hyperwallet", String.format(ERROR_MESSAGE_PREFIX @@ -67,9 +61,18 @@ public Optional execute(final SellerModel seller) { log.error("Bank account not created or updated for seller with clientId [{}]", seller.getClientUserId()); log.error(HyperwalletLoggingErrorsUtil.stringify(e)); + + throw new HMCHyperwalletAPIException(e); + } - finally { - callToIncludeIntoRetryProcess(seller, includedAsFailed); + + catch (final MiraklApiException e) { + + log.error("Error while updating Mirakl bank account by clientUserId [{}]", seller.getClientUserId(), e); + + log.error(MiraklLoggingErrorsUtil.stringify(e)); + + throw new HMCMiraklAPIException(e); } } return Optional.ofNullable(hwCreatedBankAccount); @@ -78,8 +81,4 @@ public Optional execute(final SellerModel seller) { protected abstract HyperwalletBankAccount callHyperwalletAPI(final String hyperwalletProgram, HyperwalletBankAccount hyperwalletBankAccount); - protected void callToIncludeIntoRetryProcess(final SellerModel sellerModel, final boolean include) { - executeRetryProcess(sellerModel.getClientUserId(), include); - } - } diff --git a/sellers/src/main/java/com/paypal/sellers/bankaccountextract/service/strategies/HyperWalletCreateBankAccountServiceStrategyBankAccount.java b/sellers/src/main/java/com/paypal/sellers/bankaccountextract/service/strategies/HyperWalletCreateBankAccountServiceStrategyBankAccount.java index fbeb1b73..3ebf5548 100644 --- a/sellers/src/main/java/com/paypal/sellers/bankaccountextract/service/strategies/HyperWalletCreateBankAccountServiceStrategyBankAccount.java +++ b/sellers/src/main/java/com/paypal/sellers/bankaccountextract/service/strategies/HyperWalletCreateBankAccountServiceStrategyBankAccount.java @@ -5,9 +5,7 @@ import com.paypal.infrastructure.mail.MailNotificationUtil; import com.paypal.infrastructure.strategy.StrategyExecutor; import com.paypal.sellers.bankaccountextract.service.MiraklBankAccountExtractService; -import com.paypal.sellers.entity.FailedBankAccountInformation; import com.paypal.sellers.sellersextract.model.SellerModel; -import com.paypal.sellers.service.FailedEntityInformationService; import com.paypal.sellers.service.HyperwalletSDKService; import org.springframework.stereotype.Service; @@ -25,12 +23,10 @@ public class HyperWalletCreateBankAccountServiceStrategyBankAccount private final MiraklBankAccountExtractService miraklBankAccountExtractService; protected HyperWalletCreateBankAccountServiceStrategyBankAccount( - final FailedEntityInformationService failedEntityInformationService, final StrategyExecutor sellerModelToHyperwalletBankAccountStrategyExecutor, final MiraklBankAccountExtractService miraklBankAccountExtractService, final HyperwalletSDKService hyperwalletSDKService, final MailNotificationUtil mailNotificationUtil) { - super(failedEntityInformationService, sellerModelToHyperwalletBankAccountStrategyExecutor, - hyperwalletSDKService, mailNotificationUtil); + super(sellerModelToHyperwalletBankAccountStrategyExecutor, hyperwalletSDKService, mailNotificationUtil); this.miraklBankAccountExtractService = miraklBankAccountExtractService; } diff --git a/sellers/src/main/java/com/paypal/sellers/bankaccountextract/service/strategies/HyperWalletUpdateBankAccountServiceStrategyBankAccount.java b/sellers/src/main/java/com/paypal/sellers/bankaccountextract/service/strategies/HyperWalletUpdateBankAccountServiceStrategyBankAccount.java index 8b0248a3..3bccbabe 100644 --- a/sellers/src/main/java/com/paypal/sellers/bankaccountextract/service/strategies/HyperWalletUpdateBankAccountServiceStrategyBankAccount.java +++ b/sellers/src/main/java/com/paypal/sellers/bankaccountextract/service/strategies/HyperWalletUpdateBankAccountServiceStrategyBankAccount.java @@ -4,9 +4,7 @@ import com.hyperwallet.clientsdk.model.HyperwalletBankAccount; import com.paypal.infrastructure.mail.MailNotificationUtil; import com.paypal.infrastructure.strategy.StrategyExecutor; -import com.paypal.sellers.entity.FailedBankAccountInformation; import com.paypal.sellers.sellersextract.model.SellerModel; -import com.paypal.sellers.service.FailedEntityInformationService; import com.paypal.sellers.service.HyperwalletSDKService; import org.springframework.stereotype.Service; @@ -20,11 +18,9 @@ public class HyperWalletUpdateBankAccountServiceStrategyBankAccount extends AbstractHyperwalletBankAccountRetryApiStrategy { protected HyperWalletUpdateBankAccountServiceStrategyBankAccount( - final FailedEntityInformationService failedEntityInformationService, final StrategyExecutor sellerModelToHyperwalletBankAccountStrategyExecutor, final HyperwalletSDKService hyperwalletSDKService, final MailNotificationUtil mailNotificationUtil) { - super(failedEntityInformationService, sellerModelToHyperwalletBankAccountStrategyExecutor, - hyperwalletSDKService, mailNotificationUtil); + super(sellerModelToHyperwalletBankAccountStrategyExecutor, hyperwalletSDKService, mailNotificationUtil); } /** diff --git a/sellers/src/main/java/com/paypal/sellers/batchjobs/bankaccount/BankAccountExtractBatchJob.java b/sellers/src/main/java/com/paypal/sellers/batchjobs/bankaccount/BankAccountExtractBatchJob.java index c874a024..fcae252f 100644 --- a/sellers/src/main/java/com/paypal/sellers/batchjobs/bankaccount/BankAccountExtractBatchJob.java +++ b/sellers/src/main/java/com/paypal/sellers/batchjobs/bankaccount/BankAccountExtractBatchJob.java @@ -1,9 +1,6 @@ package com.paypal.sellers.batchjobs.bankaccount; -import com.paypal.infrastructure.batchjob.AbstractBatchJob; -import com.paypal.infrastructure.batchjob.BatchJobContext; -import com.paypal.infrastructure.batchjob.BatchJobItemProcessor; -import com.paypal.infrastructure.batchjob.BatchJobItemsExtractor; +import com.paypal.infrastructure.batchjob.*; import org.springframework.stereotype.Service; /** @@ -11,7 +8,8 @@ * HyperWallet as users */ @Service -public class BankAccountExtractBatchJob extends AbstractBatchJob { +public class BankAccountExtractBatchJob extends AbstractBatchJob + implements BatchJob { private final BankAccountExtractBatchJobItemProcessor bankAccountExtractBatchJobItemProcessor; diff --git a/sellers/src/main/java/com/paypal/sellers/batchjobs/bankaccount/BankAccountExtractBatchJobItemProcessor.java b/sellers/src/main/java/com/paypal/sellers/batchjobs/bankaccount/BankAccountExtractBatchJobItemProcessor.java index 432b5bab..8a55ebcc 100644 --- a/sellers/src/main/java/com/paypal/sellers/batchjobs/bankaccount/BankAccountExtractBatchJobItemProcessor.java +++ b/sellers/src/main/java/com/paypal/sellers/batchjobs/bankaccount/BankAccountExtractBatchJobItemProcessor.java @@ -2,7 +2,10 @@ import com.paypal.infrastructure.batchjob.BatchJobContext; import com.paypal.infrastructure.batchjob.BatchJobItemProcessor; +import com.paypal.infrastructure.service.TokenSynchronizationService; import com.paypal.sellers.bankaccountextract.service.strategies.HyperWalletBankAccountStrategyExecutor; +import com.paypal.sellers.sellersextract.model.SellerModel; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; /** @@ -14,9 +17,13 @@ public class BankAccountExtractBatchJobItemProcessor private final HyperWalletBankAccountStrategyExecutor hyperWalletBankAccountStrategyExecutor; + private final TokenSynchronizationService bankAccountTokenSynchronizationService; + public BankAccountExtractBatchJobItemProcessor( - final HyperWalletBankAccountStrategyExecutor hyperWalletBankAccountStrategyExecutor) { + HyperWalletBankAccountStrategyExecutor hyperWalletBankAccountStrategyExecutor, + TokenSynchronizationService bankAccountTokenSynchronizationService) { this.hyperWalletBankAccountStrategyExecutor = hyperWalletBankAccountStrategyExecutor; + this.bankAccountTokenSynchronizationService = bankAccountTokenSynchronizationService; } /** @@ -27,7 +34,9 @@ public BankAccountExtractBatchJobItemProcessor( */ @Override public void processItem(final BatchJobContext ctx, final BankAccountExtractJobItem jobItem) { - hyperWalletBankAccountStrategyExecutor.execute(jobItem.getItem()); + final SellerModel synchronizedSellerModel = bankAccountTokenSynchronizationService + .synchronizeToken(jobItem.getItem()); + hyperWalletBankAccountStrategyExecutor.execute(synchronizedSellerModel); } } diff --git a/sellers/src/main/java/com/paypal/sellers/batchjobs/bankaccount/BankAccountExtractBatchJobItemsExtractor.java b/sellers/src/main/java/com/paypal/sellers/batchjobs/bankaccount/BankAccountExtractBatchJobItemsExtractor.java index f7d24aae..eec73547 100644 --- a/sellers/src/main/java/com/paypal/sellers/batchjobs/bankaccount/BankAccountExtractBatchJobItemsExtractor.java +++ b/sellers/src/main/java/com/paypal/sellers/batchjobs/bankaccount/BankAccountExtractBatchJobItemsExtractor.java @@ -8,6 +8,7 @@ import java.util.Collection; import java.util.Date; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * The extractor class for retrieving all the sellers within a delta time from mirakl @@ -30,7 +31,12 @@ public BankAccountExtractBatchJobItemsExtractor(final MiraklSellersExtractServic */ @Override protected Collection getItems(Date delta) { - return miraklSellersExtractService.extractIndividuals(delta).stream().map(BankAccountExtractJobItem::new) + Collection individualBankAccounts = miraklSellersExtractService + .extractIndividuals(delta).stream().map(BankAccountExtractJobItem::new).collect(Collectors.toList()); + Collection professionalBankAccounts = miraklSellersExtractService + .extractProfessionals(delta).stream().map(BankAccountExtractJobItem::new).collect(Collectors.toList()); + + return Stream.concat(individualBankAccounts.stream(), professionalBankAccounts.stream()) .collect(Collectors.toList()); } diff --git a/sellers/src/main/java/com/paypal/sellers/batchjobs/bstk/BusinessStakeholdersExtractBatchJob.java b/sellers/src/main/java/com/paypal/sellers/batchjobs/bstk/BusinessStakeholdersExtractBatchJob.java index b2215061..85073f65 100644 --- a/sellers/src/main/java/com/paypal/sellers/batchjobs/bstk/BusinessStakeholdersExtractBatchJob.java +++ b/sellers/src/main/java/com/paypal/sellers/batchjobs/bstk/BusinessStakeholdersExtractBatchJob.java @@ -1,9 +1,6 @@ package com.paypal.sellers.batchjobs.bstk; -import com.paypal.infrastructure.batchjob.AbstractBatchJob; -import com.paypal.infrastructure.batchjob.BatchJobContext; -import com.paypal.infrastructure.batchjob.BatchJobItemProcessor; -import com.paypal.infrastructure.batchjob.BatchJobItemsExtractor; +import com.paypal.infrastructure.batchjob.*; import org.springframework.stereotype.Service; /** @@ -12,7 +9,7 @@ */ @Service public class BusinessStakeholdersExtractBatchJob - extends AbstractBatchJob { + extends AbstractBatchJob implements BatchJob { private final BusinessStakeholdersExtractBatchJobItemsExtractor professionalSellersExtractBatchJobItemsExtractor; diff --git a/sellers/src/main/java/com/paypal/sellers/batchjobs/individuals/IndividualSellersExtractBatchJob.java b/sellers/src/main/java/com/paypal/sellers/batchjobs/individuals/IndividualSellersExtractBatchJob.java index 7ec17c86..12dbe94a 100644 --- a/sellers/src/main/java/com/paypal/sellers/batchjobs/individuals/IndividualSellersExtractBatchJob.java +++ b/sellers/src/main/java/com/paypal/sellers/batchjobs/individuals/IndividualSellersExtractBatchJob.java @@ -1,9 +1,6 @@ package com.paypal.sellers.batchjobs.individuals; -import com.paypal.infrastructure.batchjob.AbstractBatchJob; -import com.paypal.infrastructure.batchjob.BatchJobContext; -import com.paypal.infrastructure.batchjob.BatchJobItemProcessor; -import com.paypal.infrastructure.batchjob.BatchJobItemsExtractor; +import com.paypal.infrastructure.batchjob.*; import org.springframework.stereotype.Service; import javax.annotation.Resource; @@ -13,8 +10,8 @@ * HyperWallet as users */ @Service -public class IndividualSellersExtractBatchJob - extends AbstractBatchJob { +public class IndividualSellersExtractBatchJob extends AbstractBatchJob + implements BatchJob { @Resource private IndividualSellersExtractBatchJobItemProcessor individualSellersExtractBatchJobItemProcessor; diff --git a/sellers/src/main/java/com/paypal/sellers/batchjobs/individuals/IndividualSellersExtractBatchJobItemProcessor.java b/sellers/src/main/java/com/paypal/sellers/batchjobs/individuals/IndividualSellersExtractBatchJobItemProcessor.java index a7615894..1f16a5a4 100644 --- a/sellers/src/main/java/com/paypal/sellers/batchjobs/individuals/IndividualSellersExtractBatchJobItemProcessor.java +++ b/sellers/src/main/java/com/paypal/sellers/batchjobs/individuals/IndividualSellersExtractBatchJobItemProcessor.java @@ -2,7 +2,10 @@ import com.paypal.infrastructure.batchjob.BatchJobContext; import com.paypal.infrastructure.batchjob.BatchJobItemProcessor; +import com.paypal.infrastructure.service.TokenSynchronizationService; +import com.paypal.sellers.sellersextract.model.SellerModel; import com.paypal.sellers.sellersextract.service.strategies.HyperWalletUserServiceStrategyExecutor; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; /** @@ -14,9 +17,13 @@ public class IndividualSellersExtractBatchJobItemProcessor private final HyperWalletUserServiceStrategyExecutor hyperWalletUserServiceStrategyExecutor; + private final TokenSynchronizationService sellersTokenSynchronizationService; + public IndividualSellersExtractBatchJobItemProcessor( - final HyperWalletUserServiceStrategyExecutor hyperWalletUserServiceStrategyExecutor) { + final HyperWalletUserServiceStrategyExecutor hyperWalletUserServiceStrategyExecutor, + final TokenSynchronizationService sellersTokenSynchronizationService) { this.hyperWalletUserServiceStrategyExecutor = hyperWalletUserServiceStrategyExecutor; + this.sellersTokenSynchronizationService = sellersTokenSynchronizationService; } /** @@ -27,7 +34,8 @@ public IndividualSellersExtractBatchJobItemProcessor( */ @Override public void processItem(final BatchJobContext ctx, final IndividualSellerExtractJobItem jobItem) { - hyperWalletUserServiceStrategyExecutor.execute(jobItem.getItem()); + final SellerModel sellerModel = sellersTokenSynchronizationService.synchronizeToken(jobItem.getItem()); + hyperWalletUserServiceStrategyExecutor.execute(sellerModel); } } diff --git a/sellers/src/main/java/com/paypal/sellers/batchjobs/professionals/ProfessionalSellersExtractBatchJob.java b/sellers/src/main/java/com/paypal/sellers/batchjobs/professionals/ProfessionalSellersExtractBatchJob.java index dc5b1c32..87e1635f 100644 --- a/sellers/src/main/java/com/paypal/sellers/batchjobs/professionals/ProfessionalSellersExtractBatchJob.java +++ b/sellers/src/main/java/com/paypal/sellers/batchjobs/professionals/ProfessionalSellersExtractBatchJob.java @@ -1,9 +1,6 @@ package com.paypal.sellers.batchjobs.professionals; -import com.paypal.infrastructure.batchjob.AbstractBatchJob; -import com.paypal.infrastructure.batchjob.BatchJobContext; -import com.paypal.infrastructure.batchjob.BatchJobItemProcessor; -import com.paypal.infrastructure.batchjob.BatchJobItemsExtractor; +import com.paypal.infrastructure.batchjob.*; import org.springframework.stereotype.Service; /** @@ -12,7 +9,7 @@ */ @Service public class ProfessionalSellersExtractBatchJob - extends AbstractBatchJob { + extends AbstractBatchJob implements BatchJob { private final ProfessionalSellersExtractBatchJobItemProcessor professionalSellersExtractBatchJobItemProcessor; diff --git a/sellers/src/main/java/com/paypal/sellers/batchjobs/professionals/ProfessionalSellersExtractBatchJobItemProcessor.java b/sellers/src/main/java/com/paypal/sellers/batchjobs/professionals/ProfessionalSellersExtractBatchJobItemProcessor.java index efa93643..b66d396e 100644 --- a/sellers/src/main/java/com/paypal/sellers/batchjobs/professionals/ProfessionalSellersExtractBatchJobItemProcessor.java +++ b/sellers/src/main/java/com/paypal/sellers/batchjobs/professionals/ProfessionalSellersExtractBatchJobItemProcessor.java @@ -2,7 +2,10 @@ import com.paypal.infrastructure.batchjob.BatchJobContext; import com.paypal.infrastructure.batchjob.BatchJobItemProcessor; +import com.paypal.infrastructure.service.TokenSynchronizationService; +import com.paypal.sellers.sellersextract.model.SellerModel; import com.paypal.sellers.sellersextract.service.strategies.HyperWalletUserServiceStrategyExecutor; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Service; /** @@ -14,9 +17,13 @@ public class ProfessionalSellersExtractBatchJobItemProcessor private final HyperWalletUserServiceStrategyExecutor hyperWalletUserServiceStrategyExecutor; + private final TokenSynchronizationService sellersTokenSynchronizationService; + public ProfessionalSellersExtractBatchJobItemProcessor( - final HyperWalletUserServiceStrategyExecutor hyperWalletUserServiceStrategyExecutor) { + final HyperWalletUserServiceStrategyExecutor hyperWalletUserServiceStrategyExecutor, + final TokenSynchronizationService sellersTokenSynchronizationService) { this.hyperWalletUserServiceStrategyExecutor = hyperWalletUserServiceStrategyExecutor; + this.sellersTokenSynchronizationService = sellersTokenSynchronizationService; } /** @@ -27,7 +34,8 @@ public ProfessionalSellersExtractBatchJobItemProcessor( */ @Override public void processItem(final BatchJobContext ctx, final ProfessionalSellerExtractJobItem jobItem) { - hyperWalletUserServiceStrategyExecutor.execute(jobItem.getItem()); + final SellerModel sellerModel = sellersTokenSynchronizationService.synchronizeToken(jobItem.getItem()); + hyperWalletUserServiceStrategyExecutor.execute(sellerModel); } } diff --git a/sellers/src/main/java/com/paypal/sellers/sellersextract/service/impl/MiraklSellersExtractServiceImpl.java b/sellers/src/main/java/com/paypal/sellers/sellersextract/service/impl/MiraklSellersExtractServiceImpl.java index 487c5b50..265d9946 100644 --- a/sellers/src/main/java/com/paypal/sellers/sellersextract/service/impl/MiraklSellersExtractServiceImpl.java +++ b/sellers/src/main/java/com/paypal/sellers/sellersextract/service/impl/MiraklSellersExtractServiceImpl.java @@ -140,22 +140,21 @@ public List extractSellers(@Nullable final Date delta) { @Override public void updateUserToken(final HyperwalletUser hyperwalletUser) { final MiraklUpdateShop miraklUpdateShop = new MiraklUpdateShop(); - final String shopId = hyperwalletUser.getClientUserId(); - miraklUpdateShop.setShopId(Long.valueOf(shopId)); + miraklUpdateShop.setShopId(Long.valueOf(hyperwalletUser.getClientUserId())); final MiraklSimpleRequestAdditionalFieldValue userTokenCustomField = new MiraklSimpleRequestAdditionalFieldValue(); userTokenCustomField.setCode(HYPERWALLET_USER_TOKEN); userTokenCustomField.setValue(hyperwalletUser.getToken()); miraklUpdateShop.setAdditionalFieldValues(List.of(userTokenCustomField)); final MiraklUpdateShopsRequest request = new MiraklUpdateShopsRequest(List.of(miraklUpdateShop)); - log.info("Updating token for shop [{}] to [{}]", shopId, hyperwalletUser.getToken()); + log.info("Updating token for shop [{}] to [{}]", hyperwalletUser.getClientUserId(), hyperwalletUser.getToken()); try { miraklOperatorClient.updateShops(request); } catch (final MiraklApiException ex) { - log.error("Something went wrong getting information of shop [{}]", shopId); + log.error("Something went wrong getting information of shop [{}]", hyperwalletUser.getClientUserId()); sellerMailNotificationUtil.sendPlainTextEmail(EMAIL_SUBJECT_MESSAGE, String.format(ERROR_MESSAGE_PREFIX + "Something went wrong getting information of shop [%s]%n%s", - shopId, MiraklLoggingErrorsUtil.stringify(ex))); + hyperwalletUser.getClientUserId(), MiraklLoggingErrorsUtil.stringify(ex))); } } diff --git a/sellers/src/main/java/com/paypal/sellers/sellersextract/service/impl/SellersTokenSynchronizationServiceImpl.java b/sellers/src/main/java/com/paypal/sellers/sellersextract/service/impl/SellersTokenSynchronizationServiceImpl.java new file mode 100644 index 00000000..faa8920d --- /dev/null +++ b/sellers/src/main/java/com/paypal/sellers/sellersextract/service/impl/SellersTokenSynchronizationServiceImpl.java @@ -0,0 +1,108 @@ +package com.paypal.sellers.sellersextract.service.impl; + +import com.hyperwallet.clientsdk.Hyperwallet; +import com.hyperwallet.clientsdk.HyperwalletException; +import com.hyperwallet.clientsdk.model.HyperwalletList; +import com.hyperwallet.clientsdk.model.HyperwalletUser; +import com.hyperwallet.clientsdk.model.HyperwalletUsersListPaginationOptions; +import com.mirakl.client.core.exception.MiraklException; +import com.paypal.infrastructure.exceptions.HMCHyperwalletAPIException; +import com.paypal.infrastructure.exceptions.HMCMiraklAPIException; +import com.paypal.infrastructure.service.TokenSynchronizationService; +import com.paypal.sellers.sellersextract.model.SellerModel; +import com.paypal.sellers.sellersextract.service.MiraklSellersExtractService; +import com.paypal.sellers.service.HyperwalletSDKService; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.util.Optional; + +/** + * Class that implements the {@link TokenSynchronizationService} interface for the + * synchronization of tokens for sellers + */ +@Slf4j +@Service("sellersTokenSynchronizationService") +public class SellersTokenSynchronizationServiceImpl implements TokenSynchronizationService { + + private final HyperwalletSDKService hyperwalletSDKService; + + private final MiraklSellersExtractService miraklSellersExtractService; + + public SellersTokenSynchronizationServiceImpl(final HyperwalletSDKService hyperwalletSDKService, + final MiraklSellersExtractService miraklSellersExtractService) { + this.hyperwalletSDKService = hyperwalletSDKService; + this.miraklSellersExtractService = miraklSellersExtractService; + } + + /** + * Ensures the seller's token between Hyperwallet and Mirakl is synchronized + * @param sellerModel that contains the seller item to be synchronized + * @return the seller with the seller's token synchronized + */ + @Override + public SellerModel synchronizeToken(final SellerModel sellerModel) { + if (StringUtils.isNotBlank(sellerModel.getToken())) { + log.debug("Hyperwallet token already exists for client user id [{}], synchronization not needed", + sellerModel.getClientUserId()); + + return sellerModel; + } + + final Optional hyperwalletUser = getHwUser(sellerModel); + + if (hyperwalletUser.isPresent()) { + updateTokenInMirakl(hyperwalletUser.get()); + + return updateSellerWithHyperwalletToken(sellerModel, hyperwalletUser.get()); + } + else { + return sellerModel; + } + } + + private void updateTokenInMirakl(final HyperwalletUser hyperwalletUser) { + try { + miraklSellersExtractService.updateUserToken(hyperwalletUser); + } + catch (final MiraklException e) { + log.error("Error while updating Mirakl user by clientUserId [{}]", hyperwalletUser.getClientUserId(), e); + throw new HMCMiraklAPIException(e); + } + } + + private Optional getHwUser(final SellerModel sellerModel) { + final HyperwalletList hyperwalletUserHyperwalletList = getHwUserByClientUserId(sellerModel); + if (CollectionUtils.isEmpty(hyperwalletUserHyperwalletList.getData())) { + log.debug("Hyperwallet user with client user id [{}] not found", sellerModel.getClientUserId()); + return Optional.empty(); + } + else { + log.debug("Hyperwallet user with client user id [{}] found", sellerModel.getClientUserId()); + return Optional.of(hyperwalletUserHyperwalletList.getData().get(0)); + } + } + + private HyperwalletList getHwUserByClientUserId(final SellerModel sellerModel) { + final Hyperwallet hyperwalletSDK = hyperwalletSDKService + .getHyperwalletInstanceByProgramToken(sellerModel.getProgramToken()); + final HyperwalletUsersListPaginationOptions paginationOptions = new HyperwalletUsersListPaginationOptions(); + paginationOptions.setClientUserId(sellerModel.getClientUserId()); + try { + return hyperwalletSDK.listUsers(paginationOptions); + } + catch (final HyperwalletException e) { + log.error("Error while getting Hyperwallet user by clientUserId [{}]", sellerModel.getClientUserId(), e); + + throw new HMCHyperwalletAPIException(e); + } + } + + private SellerModel updateSellerWithHyperwalletToken(final SellerModel sellerModel, + final HyperwalletUser hyperwalletUser) { + return sellerModel.toBuilder().token(hyperwalletUser.getToken()).build(); + } + +} diff --git a/sellers/src/main/java/com/paypal/sellers/sellersextract/service/strategies/AbstractHyperwalletSellerRetryApiStrategy.java b/sellers/src/main/java/com/paypal/sellers/sellersextract/service/strategies/AbstractHyperwalletSellerRetryApiStrategy.java deleted file mode 100644 index 48542d08..00000000 --- a/sellers/src/main/java/com/paypal/sellers/sellersextract/service/strategies/AbstractHyperwalletSellerRetryApiStrategy.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.paypal.sellers.sellersextract.service.strategies; - -import com.hyperwallet.clientsdk.HyperwalletException; -import com.hyperwallet.clientsdk.model.HyperwalletUser; -import com.paypal.infrastructure.converter.Converter; -import com.paypal.infrastructure.mail.MailNotificationUtil; -import com.paypal.infrastructure.strategy.Strategy; -import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; -import com.paypal.sellers.entity.FailedSellersInformation; -import com.paypal.sellers.sellersextract.model.SellerModel; -import com.paypal.sellers.service.AbstractHyperwalletRetryAPIStrategy; -import com.paypal.sellers.service.FailedEntityInformationService; -import com.paypal.sellers.service.HyperwalletSDKService; -import lombok.extern.slf4j.Slf4j; - -import java.io.IOException; - -/** - * Abstract Strategy class that covers API errors or possible retries when - * creating/updating sellers into Hyperwallet - */ -@Slf4j -public abstract class AbstractHyperwalletSellerRetryApiStrategy - extends AbstractHyperwalletRetryAPIStrategy - implements Strategy { - - protected final Converter sellerModelHyperwalletUserConverter; - - protected final HyperwalletSDKService hyperwalletSDKService; - - protected final MailNotificationUtil mailNotificationUtil; - - protected static final String ERROR_MESSAGE_PREFIX = "There was an error, please check the logs for further " - + "information:\n"; - - protected AbstractHyperwalletSellerRetryApiStrategy( - final FailedEntityInformationService failedEntityInformationService, - final Converter sellerModelHyperwalletUserConverter, - final HyperwalletSDKService hyperwalletSDKService, final MailNotificationUtil mailNotificationUtil) { - super(failedEntityInformationService); - this.sellerModelHyperwalletUserConverter = sellerModelHyperwalletUserConverter; - this.hyperwalletSDKService = hyperwalletSDKService; - this.mailNotificationUtil = mailNotificationUtil; - } - - /** - * {@inheritDoc} - */ - @Override - public HyperwalletUser execute(final SellerModel seller) { - boolean includedAsFailed = false; - HyperwalletUser hyperwalletUser = null; - final HyperwalletUser hwUserRequest = sellerModelHyperwalletUserConverter.convert(seller); - try { - hyperwalletUser = createOrUpdateUserOnHyperWalletAndUpdateItsTokenOnMirakl(hwUserRequest); - log.info("Seller created or updated for seller with clientId [{}]", seller.getClientUserId()); - } - catch (final HyperwalletException e) { - if (e.getCause() instanceof IOException) { - includedAsFailed = true; - } - mailNotificationUtil.sendPlainTextEmail("Issue detected when creating or updating seller in Hyperwallet", - String.format(ERROR_MESSAGE_PREFIX + "Seller not created or updated with clientId [%s]%n%s", - seller.getClientUserId(), HyperwalletLoggingErrorsUtil.stringify(e))); - log.error("Seller not created or updated with clientId [{}]", seller.getClientUserId()); - log.error(HyperwalletLoggingErrorsUtil.stringify(e)); - } - finally { - callToIncludeIntoRetryProcess(seller, includedAsFailed); - } - - return hyperwalletUser; - } - - protected abstract HyperwalletUser createOrUpdateUserOnHyperWalletAndUpdateItsTokenOnMirakl( - HyperwalletUser hyperwalletUser); - - protected void callToIncludeIntoRetryProcess(final SellerModel sellerModel, final boolean include) { - executeRetryProcess(sellerModel.getClientUserId(), include); - } - -} diff --git a/sellers/src/main/java/com/paypal/sellers/sellersextract/service/strategies/AbstractHyperwalletSellerServiceStrategy.java b/sellers/src/main/java/com/paypal/sellers/sellersextract/service/strategies/AbstractHyperwalletSellerServiceStrategy.java new file mode 100644 index 00000000..e748bc5d --- /dev/null +++ b/sellers/src/main/java/com/paypal/sellers/sellersextract/service/strategies/AbstractHyperwalletSellerServiceStrategy.java @@ -0,0 +1,59 @@ +package com.paypal.sellers.sellersextract.service.strategies; + +import com.hyperwallet.clientsdk.model.HyperwalletUser; +import com.paypal.infrastructure.converter.Converter; +import com.paypal.infrastructure.mail.MailNotificationUtil; +import com.paypal.infrastructure.strategy.Strategy; +import com.paypal.sellers.sellersextract.model.SellerModel; +import com.paypal.sellers.service.HyperwalletSDKService; +import org.slf4j.Logger; + +public abstract class AbstractHyperwalletSellerServiceStrategy implements Strategy { + + protected final Converter sellerModelHyperwalletUserConverter; + + protected final HyperwalletSDKService hyperwalletSDKService; + + protected final MailNotificationUtil mailNotificationUtil; + + protected static final String ERROR_MESSAGE_PREFIX = "There was an error, please check the logs for further " + + "information:\n"; + + protected AbstractHyperwalletSellerServiceStrategy( + final Converter sellerModelHyperwalletUserConverter, + final HyperwalletSDKService hyperwalletSDKService, final MailNotificationUtil mailNotificationUtil) { + this.sellerModelHyperwalletUserConverter = sellerModelHyperwalletUserConverter; + this.hyperwalletSDKService = hyperwalletSDKService; + this.mailNotificationUtil = mailNotificationUtil; + } + + /** + * {@inheritDoc} + */ + @Override + public SellerModel execute(final SellerModel seller) { + final HyperwalletUser hwUserRequest = sellerModelHyperwalletUserConverter.convert(seller); + final HyperwalletUser hyperwalletUser = pushToHyperwallet(hwUserRequest); + + return updateSellerToken(seller, hyperwalletUser); + } + + private SellerModel updateSellerToken(final SellerModel seller, final HyperwalletUser hyperwalletUser) { + //@formatter:off + return seller.toBuilder() + .token(hyperwalletUser.getToken()) + .build(); + //@formatter:on + } + + protected abstract HyperwalletUser pushToHyperwallet(HyperwalletUser hyperwalletUser); + + protected void logErrors(final String message, final Exception e, final Logger log) { + log.error(message, e); + } + + protected void reportError(final String subject, final String message) { + mailNotificationUtil.sendPlainTextEmail(subject, message); + } + +} diff --git a/sellers/src/main/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletCreateSellerServiceStrategy.java b/sellers/src/main/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletCreateSellerServiceStrategy.java index fc9e6749..99640f27 100644 --- a/sellers/src/main/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletCreateSellerServiceStrategy.java +++ b/sellers/src/main/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletCreateSellerServiceStrategy.java @@ -1,13 +1,17 @@ package com.paypal.sellers.sellersextract.service.strategies; import com.hyperwallet.clientsdk.Hyperwallet; +import com.hyperwallet.clientsdk.HyperwalletException; import com.hyperwallet.clientsdk.model.HyperwalletUser; +import com.mirakl.client.core.exception.MiraklException; import com.paypal.infrastructure.converter.Converter; +import com.paypal.infrastructure.exceptions.HMCHyperwalletAPIException; +import com.paypal.infrastructure.exceptions.HMCMiraklAPIException; import com.paypal.infrastructure.mail.MailNotificationUtil; -import com.paypal.sellers.entity.FailedSellersInformation; +import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; +import com.paypal.infrastructure.util.MiraklLoggingErrorsUtil; import com.paypal.sellers.sellersextract.model.SellerModel; import com.paypal.sellers.sellersextract.service.MiraklSellersExtractService; -import com.paypal.sellers.service.FailedEntityInformationService; import com.paypal.sellers.service.HyperwalletSDKService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -19,39 +23,58 @@ */ @Slf4j @Service -public class HyperWalletCreateSellerServiceStrategy extends AbstractHyperwalletSellerRetryApiStrategy { +public class HyperWalletCreateSellerServiceStrategy extends AbstractHyperwalletSellerServiceStrategy { private final MiraklSellersExtractService miraklSellersExtractService; protected HyperWalletCreateSellerServiceStrategy( - final FailedEntityInformationService failedEntityInformationService, final Converter sellerModelHyperwalletUserConverter, final HyperwalletSDKService hyperwalletSDKService, final MailNotificationUtil mailNotificationUtil, final MiraklSellersExtractService miraklSellersExtractService) { - super(failedEntityInformationService, sellerModelHyperwalletUserConverter, hyperwalletSDKService, - mailNotificationUtil); + super(sellerModelHyperwalletUserConverter, hyperwalletSDKService, mailNotificationUtil); this.miraklSellersExtractService = miraklSellersExtractService; } /** - * It creates the user on HyperWallet side, then it updates the user information on - * Mirakl accordingly with the response received on user creation by HyperWallet + * It creates the user on HyperWallet side and updates the token in Mirakl * @param hyperwalletUser The User to be created * @return The created HyperWallet user */ @Override - protected HyperwalletUser createOrUpdateUserOnHyperWalletAndUpdateItsTokenOnMirakl( - final HyperwalletUser hyperwalletUser) { + protected HyperwalletUser pushToHyperwallet(final HyperwalletUser hyperwalletUser) { final Hyperwallet hyperwallet = hyperwalletSDKService .getHyperwalletInstanceByProgramToken(hyperwalletUser.getProgramToken()); - final HyperwalletUser hwUser = hyperwallet.createUser(hyperwalletUser); - miraklSellersExtractService.updateUserToken(hwUser); - log.info("Seller created for seller with clientUserId [{}]", hyperwalletUser.getClientUserId()); - return hwUser; + try { + final HyperwalletUser hwUser = hyperwallet.createUser(hyperwalletUser); + + log.info("Seller created for seller with clientUserId [{}]", hyperwalletUser.getClientUserId()); + + miraklSellersExtractService.updateUserToken(hwUser); + + return hwUser; + } + catch (final HyperwalletException e) { + logErrors(String.format("Error creating seller in hyperwallet with clientUserId [%s]: [{}]", + hyperwalletUser.getClientUserId()), e, log); + reportError("Issue detected when creating seller in Hyperwallet", + String.format(ERROR_MESSAGE_PREFIX + "Seller not created with clientId [%s]%n%s", + hyperwalletUser.getClientUserId(), HyperwalletLoggingErrorsUtil.stringify(e))); + + throw new HMCHyperwalletAPIException(e); + } + catch (final MiraklException e) { + logErrors(String.format("Error updating token in mirakl with clientUserId [%s]: [{}]", + hyperwalletUser.getClientUserId()), e, log); + reportError("Issue detected when updating seller in Mirakl", + String.format(ERROR_MESSAGE_PREFIX + "Seller token not updated with clientId [%s]%n%s", + hyperwalletUser.getClientUserId(), MiraklLoggingErrorsUtil.stringify(e))); + throw new HMCMiraklAPIException(e); + } } /** - * Checks whether the strategy must be executed based on the {@code seller} + * Checks whether the strategy must be executed based on the not existence of the + * {@code seller} * @param seller the seller object * @return returns whether the strategy is applicable or not */ diff --git a/sellers/src/main/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletUpdateSellerServiceStrategy.java b/sellers/src/main/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletUpdateSellerServiceStrategy.java index 59b145f8..d9b53d05 100644 --- a/sellers/src/main/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletUpdateSellerServiceStrategy.java +++ b/sellers/src/main/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletUpdateSellerServiceStrategy.java @@ -1,12 +1,13 @@ package com.paypal.sellers.sellersextract.service.strategies; import com.hyperwallet.clientsdk.Hyperwallet; +import com.hyperwallet.clientsdk.HyperwalletException; import com.hyperwallet.clientsdk.model.HyperwalletUser; import com.paypal.infrastructure.converter.Converter; +import com.paypal.infrastructure.exceptions.HMCHyperwalletAPIException; import com.paypal.infrastructure.mail.MailNotificationUtil; -import com.paypal.sellers.entity.FailedSellersInformation; +import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; import com.paypal.sellers.sellersextract.model.SellerModel; -import com.paypal.sellers.service.FailedEntityInformationService; import com.paypal.sellers.service.HyperwalletSDKService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -18,24 +19,36 @@ */ @Slf4j @Service -public class HyperWalletUpdateSellerServiceStrategy extends AbstractHyperwalletSellerRetryApiStrategy { +public class HyperWalletUpdateSellerServiceStrategy extends AbstractHyperwalletSellerServiceStrategy { protected HyperWalletUpdateSellerServiceStrategy( - final FailedEntityInformationService failedEntityInformationService, final Converter sellerModelHyperwalletUserConverter, final HyperwalletSDKService hyperwalletSDKService, final MailNotificationUtil mailNotificationUtil) { - super(failedEntityInformationService, sellerModelHyperwalletUserConverter, hyperwalletSDKService, - mailNotificationUtil); + super(sellerModelHyperwalletUserConverter, hyperwalletSDKService, mailNotificationUtil); } @Override - protected HyperwalletUser createOrUpdateUserOnHyperWalletAndUpdateItsTokenOnMirakl( - final HyperwalletUser hyperwalletUser) { - final Hyperwallet hyperwallet = hyperwalletSDKService - .getHyperwalletInstanceByProgramToken(hyperwalletUser.getProgramToken()); - final HyperwalletUser updatedUser = hyperwallet.updateUser(hyperwalletUser); - log.info("Seller updated for seller with clientUserId [{}]", hyperwalletUser.getClientUserId()); - return updatedUser; + protected HyperwalletUser pushToHyperwallet(final HyperwalletUser hyperwalletUser) { + + try { + final Hyperwallet hyperwallet = hyperwalletSDKService + .getHyperwalletInstanceByProgramToken(hyperwalletUser.getProgramToken()); + final HyperwalletUser updatedUser = hyperwallet.updateUser(hyperwalletUser); + + log.info("Seller updated for seller with clientUserId [{}]", hyperwalletUser.getClientUserId()); + + return updatedUser; + } + catch (final HyperwalletException e) { + logErrors(String.format("Error updating seller in hyperwallet with clientUserId [%s]: [{}]", + hyperwalletUser.getClientUserId()), e, log); + + reportError("Issue detected when updating seller in Hyperwallet", + String.format(ERROR_MESSAGE_PREFIX + "Seller not updated with clientId [%s]%n%s", + hyperwalletUser.getClientUserId(), HyperwalletLoggingErrorsUtil.stringify(e))); + + throw new HMCHyperwalletAPIException(e); + } } /** diff --git a/sellers/src/main/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletUserServiceStrategyExecutor.java b/sellers/src/main/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletUserServiceStrategyExecutor.java index c04dfa1b..b702e015 100644 --- a/sellers/src/main/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletUserServiceStrategyExecutor.java +++ b/sellers/src/main/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletUserServiceStrategyExecutor.java @@ -1,6 +1,5 @@ package com.paypal.sellers.sellersextract.service.strategies; -import com.hyperwallet.clientsdk.model.HyperwalletUser; import com.paypal.infrastructure.strategy.SingleAbstractStrategyExecutor; import com.paypal.infrastructure.strategy.Strategy; import com.paypal.sellers.sellersextract.model.SellerModel; @@ -15,17 +14,16 @@ */ @Slf4j @Service -public class HyperWalletUserServiceStrategyExecutor - extends SingleAbstractStrategyExecutor { +public class HyperWalletUserServiceStrategyExecutor extends SingleAbstractStrategyExecutor { - private final Set> strategies; + private final Set> strategies; - public HyperWalletUserServiceStrategyExecutor(final Set> strategies) { + public HyperWalletUserServiceStrategyExecutor(final Set> strategies) { this.strategies = strategies; } @Override - protected Set> getStrategies() { + protected Set> getStrategies() { return strategies; } diff --git a/sellers/src/main/java/com/paypal/sellers/service/AbstractHyperwalletRetryAPIStrategy.java b/sellers/src/main/java/com/paypal/sellers/service/AbstractHyperwalletRetryAPIStrategy.java deleted file mode 100644 index b27bc645..00000000 --- a/sellers/src/main/java/com/paypal/sellers/service/AbstractHyperwalletRetryAPIStrategy.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.paypal.sellers.service; - -import com.paypal.sellers.entity.AbstractFailedShopInformation; -import lombok.extern.slf4j.Slf4j; -import org.apache.commons.collections4.CollectionUtils; - -import java.util.List; - -/** - * Abstract class that saves or deletes id shops in retry system - * - * @param extends {@link AbstractFailedShopInformation} - */ -@Slf4j -public abstract class AbstractHyperwalletRetryAPIStrategy { - - protected final FailedEntityInformationService failedEntityInformationService; - - protected AbstractHyperwalletRetryAPIStrategy( - final FailedEntityInformationService failedEntityInformationService) { - this.failedEntityInformationService = failedEntityInformationService; - } - - protected void executeRetryProcess(final String shopId, final boolean includedAsFailed) { - if (includedAsFailed) { - final List entityInformation = failedEntityInformationService.findByShopId(shopId); - if (CollectionUtils.isEmpty(entityInformation)) { - failedEntityInformationService.save(shopId); - } - } - else { - failedEntityInformationService.deleteByShopId(shopId); - } - } - -} diff --git a/sellers/src/test/java/com/paypal/sellers/bankaccountextract/model/ABABankAccountModelTest.java b/sellers/src/test/java/com/paypal/sellers/bankaccountextract/model/ABABankAccountModelTest.java index e7c68f75..de48da18 100644 --- a/sellers/src/test/java/com/paypal/sellers/bankaccountextract/model/ABABankAccountModelTest.java +++ b/sellers/src/test/java/com/paypal/sellers/bankaccountextract/model/ABABankAccountModelTest.java @@ -1,15 +1,23 @@ package com.paypal.sellers.bankaccountextract.model; +import com.mirakl.client.mmp.domain.common.MiraklAdditionalFieldValue; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; +import java.util.List; + +import static com.paypal.sellers.sellersextract.model.SellerModelConstants.*; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @ExtendWith(MockitoExtension.class) class ABABankAccountModelTest { + private static final String TOKEN_VALUE_1 = "token1"; + + private static final String TOKEN_VALUE_2 = "token2"; + @Test void setCountry_shouldConvertTo2LettersWhenCountry3IsocodeExists() { final ABABankAccountModel testObj = ABABankAccountModel.builder().country("USA").build(); @@ -53,4 +61,60 @@ void setTransferMethodCurrency_shouldThrowAnExceptionWhenCurrencyIsInvalid() { .hasMessage("Transfer method currency with code: [INVALID_CURRENCY] not valid"); } + @Test + void toBuild_ShouldReturnCopyOABABankAccountModel() { + + final ABABankAccountModel bankAccountModel = createABABankAccountModelObject(TOKEN_VALUE_1); + final ABABankAccountModel copyBankAccountModel = bankAccountModel.toBuilder().build(); + + assertThat(bankAccountModel).isEqualTo(copyBankAccountModel); + } + + @Test + void toBuild_ShouldReturnCopyOfABABankAccountModelWithTheUpdatedToken() { + + final ABABankAccountModel bankAccountModel1 = createABABankAccountModelObject(TOKEN_VALUE_1); + final ABABankAccountModel bankAccountModel2 = createABABankAccountModelObject(TOKEN_VALUE_2); + final ABABankAccountModel copyBankAccountModel = bankAccountModel1.toBuilder().token(TOKEN_VALUE_2).build(); + + assertThat(bankAccountModel2).isEqualTo(copyBankAccountModel); + } + + private ABABankAccountModel createABABankAccountModelObject(final String token) { + final MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue tokenBankAccountField = new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue(); + tokenBankAccountField.setCode(HYPERWALLET_BANK_ACCOUNT_TOKEN); + tokenBankAccountField.setValue(token); + + final MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue stateProvinceBusinessStakeHolderField = new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue(); + stateProvinceBusinessStakeHolderField.setCode(HYPERWALLET_BANK_ACCOUNT_STATE); + stateProvinceBusinessStakeHolderField.setValue("stateProvince"); + + final MiraklAdditionalFieldValue.MiraklValueListAdditionalFieldValue hyperwalletProgramAccountField = new MiraklAdditionalFieldValue.MiraklValueListAdditionalFieldValue(); + hyperwalletProgramAccountField.setCode(HYPERWALLET_PROGRAM); + hyperwalletProgramAccountField.setValue("hyperwalletProgram"); + + //@formatter:off + return ABABankAccountModel.builder() + .transferMethodCountry("USA") + .transferMethodCurrency("EUR") + .transferType(TransferType.BANK_ACCOUNT) + .type(BankAccountType.ABA) + .bankAccountNumber("111") + .businessName("businessName") + .firstName("firstName") + .lastName("lastName") + .country("USA") + .addressLine1("addressLine1") + .addressLine2("addressLine2") + .city("city") + .stateProvince(List.of(stateProvinceBusinessStakeHolderField)) + .postalCode("2222") + .token(List.of(tokenBankAccountField)) + .hyperwalletProgram(List.of(hyperwalletProgramAccountField)) + .branchId("branchId") + .bankAccountPurpose("bankAccountPurpose") + .build(); + //@formatter:on + } + } diff --git a/sellers/src/test/java/com/paypal/sellers/bankaccountextract/model/BankAccountModelTest.java b/sellers/src/test/java/com/paypal/sellers/bankaccountextract/model/BankAccountModelTest.java index 0a225650..c397a174 100644 --- a/sellers/src/test/java/com/paypal/sellers/bankaccountextract/model/BankAccountModelTest.java +++ b/sellers/src/test/java/com/paypal/sellers/bankaccountextract/model/BankAccountModelTest.java @@ -13,10 +13,14 @@ @ExtendWith(MockitoExtension.class) class BankAccountModelTest { + private static final String TOKEN_VALUE_1 = "token1"; + + private static final String TOKEN_VALUE_2 = "token2"; + @Test void equals_shouldReturnTrueWhenBothAreEquals() { - final BankAccountModel bankAccountModelOne = createBankAccountModelObject(); - final BankAccountModel bankAccountModelTwo = createBankAccountModelObject(); + final BankAccountModel bankAccountModelOne = createBankAccountModelObject(TOKEN_VALUE_1); + final BankAccountModel bankAccountModelTwo = createBankAccountModelObject(TOKEN_VALUE_1); final boolean result = bankAccountModelOne.equals(bankAccountModelTwo); @@ -25,7 +29,7 @@ void equals_shouldReturnTrueWhenBothAreEquals() { @Test void equals_shouldReturnFalseWhenBothAreNotEquals() { - final BankAccountModel bankAccountModelOne = createBankAccountModelObject(); + final BankAccountModel bankAccountModelOne = createBankAccountModelObject(TOKEN_VALUE_1); final BankAccountModel bankAccountModelTwo = createAnotherBankAccountModelObject(); final boolean result = bankAccountModelOne.equals(bankAccountModelTwo); @@ -35,7 +39,7 @@ void equals_shouldReturnFalseWhenBothAreNotEquals() { @Test void equals_shouldReturnTrueWhenSameObjectIsCompared() { - final BankAccountModel bankAccountModelOne = createBankAccountModelObject(); + final BankAccountModel bankAccountModelOne = createBankAccountModelObject(TOKEN_VALUE_1); final boolean result = bankAccountModelOne.equals(bankAccountModelOne); @@ -44,7 +48,7 @@ void equals_shouldReturnTrueWhenSameObjectIsCompared() { @Test void equals_shouldReturnFalseWhenComparedWithAnotherInstanceObject() { - final BankAccountModel bankAccountModelOne = createBankAccountModelObject(); + final BankAccountModel bankAccountModelOne = createBankAccountModelObject(TOKEN_VALUE_1); final Object o = new Object(); @@ -53,10 +57,29 @@ void equals_shouldReturnFalseWhenComparedWithAnotherInstanceObject() { assertThat(result).isFalse(); } - private BankAccountModel createBankAccountModelObject() { + @Test + void toBuild_ShouldReturnCopyOfBankAccountModel() { + + final BankAccountModel bankAccountModel = createBankAccountModelObject(TOKEN_VALUE_1); + final BankAccountModel copyBankAccountModel = bankAccountModel.toBuilder().build(); + + assertThat(bankAccountModel).isEqualTo(copyBankAccountModel); + } + + @Test + void toBuild_ShouldReturnCopyOfBankAccountModelWithTheUpdatedToken() { + + final BankAccountModel bankAccountModel1 = createBankAccountModelObject(TOKEN_VALUE_1); + final BankAccountModel bankAccountModel2 = createBankAccountModelObject(TOKEN_VALUE_2); + final BankAccountModel copyBankAccountModel = bankAccountModel1.toBuilder().token(TOKEN_VALUE_2).build(); + + assertThat(bankAccountModel2).isEqualTo(copyBankAccountModel); + } + + private BankAccountModel createBankAccountModelObject(final String token) { final MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue tokenBankAccountField = new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue(); tokenBankAccountField.setCode(HYPERWALLET_BANK_ACCOUNT_TOKEN); - tokenBankAccountField.setValue("token"); + tokenBankAccountField.setValue(token); final MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue stateProvinceBusinessStakeHolderField = new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue(); stateProvinceBusinessStakeHolderField.setCode(HYPERWALLET_BANK_ACCOUNT_STATE); diff --git a/sellers/src/test/java/com/paypal/sellers/bankaccountextract/model/CanadianBankAccountModelTest.java b/sellers/src/test/java/com/paypal/sellers/bankaccountextract/model/CanadianBankAccountModelTest.java index ce8b680d..6d809e37 100644 --- a/sellers/src/test/java/com/paypal/sellers/bankaccountextract/model/CanadianBankAccountModelTest.java +++ b/sellers/src/test/java/com/paypal/sellers/bankaccountextract/model/CanadianBankAccountModelTest.java @@ -1,15 +1,23 @@ package com.paypal.sellers.bankaccountextract.model; +import com.mirakl.client.mmp.domain.common.MiraklAdditionalFieldValue; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; +import java.util.List; + +import static com.paypal.sellers.sellersextract.model.SellerModelConstants.*; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @ExtendWith(MockitoExtension.class) class CanadianBankAccountModelTest { + private static final String TOKEN_VALUE_1 = "token1"; + + private static final String TOKEN_VALUE_2 = "token2"; + @Test void setCountry_shouldConvertTo2LettersWhenCountry3IsocodeExists() { final CanadianBankAccountModel testObj = CanadianBankAccountModel.builder().country("USA").build(); @@ -55,4 +63,61 @@ void setTransferMethodCurrency_shouldThrowAnExceptionWhenCurrencyIsInvalid() { .hasMessage("Transfer method currency with code: [INVALID_CURRENCY] not valid"); } + @Test + void toBuild_ShouldReturnCopyOfCanadianBankAccountModel() { + + final CanadianBankAccountModel bankAccountModel = createCanadianBankAccountModelObject(TOKEN_VALUE_1); + final CanadianBankAccountModel copyBankAccountModel = bankAccountModel.toBuilder().build(); + + assertThat(bankAccountModel).isEqualTo(copyBankAccountModel); + } + + @Test + void toBuild_ShouldReturnCopyOfCanadianBankAccountModelWithTheUpdatedToken() { + + final CanadianBankAccountModel bankAccountModel1 = createCanadianBankAccountModelObject(TOKEN_VALUE_1); + final CanadianBankAccountModel bankAccountModel2 = createCanadianBankAccountModelObject(TOKEN_VALUE_2); + final CanadianBankAccountModel copyBankAccountModel = bankAccountModel1.toBuilder().token(TOKEN_VALUE_2) + .build(); + + assertThat(bankAccountModel2).isEqualTo(copyBankAccountModel); + } + + private CanadianBankAccountModel createCanadianBankAccountModelObject(final String token) { + final MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue tokenBankAccountField = new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue(); + tokenBankAccountField.setCode(HYPERWALLET_BANK_ACCOUNT_TOKEN); + tokenBankAccountField.setValue(token); + + final MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue stateProvinceBusinessStakeHolderField = new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue(); + stateProvinceBusinessStakeHolderField.setCode(HYPERWALLET_BANK_ACCOUNT_STATE); + stateProvinceBusinessStakeHolderField.setValue("stateProvince"); + + final MiraklAdditionalFieldValue.MiraklValueListAdditionalFieldValue hyperwalletProgramAccountField = new MiraklAdditionalFieldValue.MiraklValueListAdditionalFieldValue(); + hyperwalletProgramAccountField.setCode(HYPERWALLET_PROGRAM); + hyperwalletProgramAccountField.setValue("hyperwalletProgram"); + + //@formatter:off + return CanadianBankAccountModel.builder() + .transferMethodCountry("USA") + .transferMethodCurrency("EUR") + .transferType(TransferType.BANK_ACCOUNT) + .type(BankAccountType.ABA) + .bankAccountNumber("111") + .businessName("businessName") + .firstName("firstName") + .lastName("lastName") + .country("USA") + .addressLine1("addressLine1") + .addressLine2("addressLine2") + .city("city") + .stateProvince(List.of(stateProvinceBusinessStakeHolderField)) + .postalCode("2222") + .token(List.of(tokenBankAccountField)) + .hyperwalletProgram(List.of(hyperwalletProgramAccountField)) + .bankId("bankId") + .branchId("branchId") + .build(); + //@formatter:on + } + } diff --git a/sellers/src/test/java/com/paypal/sellers/bankaccountextract/model/IBANBankAccountModelTest.java b/sellers/src/test/java/com/paypal/sellers/bankaccountextract/model/IBANBankAccountModelTest.java index bea8973c..ddd53a79 100644 --- a/sellers/src/test/java/com/paypal/sellers/bankaccountextract/model/IBANBankAccountModelTest.java +++ b/sellers/src/test/java/com/paypal/sellers/bankaccountextract/model/IBANBankAccountModelTest.java @@ -1,12 +1,20 @@ package com.paypal.sellers.bankaccountextract.model; +import com.mirakl.client.mmp.domain.common.MiraklAdditionalFieldValue; import org.junit.jupiter.api.Test; +import java.util.List; + +import static com.paypal.sellers.sellersextract.model.SellerModelConstants.*; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; class IBANBankAccountModelTest { + private static final String TOKEN_VALUE_1 = "token1"; + + private static final String TOKEN_VALUE_2 = "token2"; + @Test void setCountry_shouldConvertTo2LettersWhenCountry3IsocodeExists() { final IBANBankAccountModel testObj = IBANBankAccountModel.builder().country("USA").build(); @@ -50,4 +58,59 @@ void setTransferMethodCurrency_shouldThrowAnExceptionWhenCurrencyIsInvalid() { .hasMessage("Transfer method currency with code: [INVALID_CURRENCY] not valid"); } + @Test + void toBuild_ShouldReturnCopyOfIBANBankAccountModel() { + + final IBANBankAccountModel bankAccountModel = createIBANBankAccountModelObject(TOKEN_VALUE_1); + final IBANBankAccountModel copyBankAccountModel = bankAccountModel.toBuilder().build(); + + assertThat(bankAccountModel).isEqualTo(copyBankAccountModel); + } + + @Test + void toBuild_ShouldReturnCopyOfIBANBankAccountModelWithTheUpdatedToken() { + + final IBANBankAccountModel bankAccountModel1 = createIBANBankAccountModelObject(TOKEN_VALUE_1); + final IBANBankAccountModel bankAccountModel2 = createIBANBankAccountModelObject(TOKEN_VALUE_2); + final IBANBankAccountModel copyBankAccountModel = bankAccountModel1.toBuilder().token(TOKEN_VALUE_2).build(); + + assertThat(bankAccountModel2).isEqualTo(copyBankAccountModel); + } + + private IBANBankAccountModel createIBANBankAccountModelObject(final String token) { + final MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue tokenBankAccountField = new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue(); + tokenBankAccountField.setCode(HYPERWALLET_BANK_ACCOUNT_TOKEN); + tokenBankAccountField.setValue(token); + + final MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue stateProvinceBusinessStakeHolderField = new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue(); + stateProvinceBusinessStakeHolderField.setCode(HYPERWALLET_BANK_ACCOUNT_STATE); + stateProvinceBusinessStakeHolderField.setValue("stateProvince"); + + final MiraklAdditionalFieldValue.MiraklValueListAdditionalFieldValue hyperwalletProgramAccountField = new MiraklAdditionalFieldValue.MiraklValueListAdditionalFieldValue(); + hyperwalletProgramAccountField.setCode(HYPERWALLET_PROGRAM); + hyperwalletProgramAccountField.setValue("hyperwalletProgram"); + + //@formatter:off + return IBANBankAccountModel.builder() + .transferMethodCountry("USA") + .transferMethodCurrency("EUR") + .transferType(TransferType.BANK_ACCOUNT) + .type(BankAccountType.ABA) + .bankAccountNumber("111") + .businessName("businessName") + .firstName("firstName") + .lastName("lastName") + .country("USA") + .addressLine1("addressLine1") + .addressLine2("addressLine2") + .city("city") + .stateProvince(List.of(stateProvinceBusinessStakeHolderField)) + .postalCode("2222") + .token(List.of(tokenBankAccountField)) + .hyperwalletProgram(List.of(hyperwalletProgramAccountField)) + .bankBic("bankBic") + .build(); + //@formatter:on + } + } diff --git a/sellers/src/test/java/com/paypal/sellers/bankaccountextract/model/UKBankAccountModelTest.java b/sellers/src/test/java/com/paypal/sellers/bankaccountextract/model/UKBankAccountModelTest.java index e15e696a..0aacaba2 100644 --- a/sellers/src/test/java/com/paypal/sellers/bankaccountextract/model/UKBankAccountModelTest.java +++ b/sellers/src/test/java/com/paypal/sellers/bankaccountextract/model/UKBankAccountModelTest.java @@ -1,15 +1,24 @@ package com.paypal.sellers.bankaccountextract.model; +import com.mirakl.client.mmp.domain.common.MiraklAdditionalFieldValue; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.junit.jupiter.MockitoExtension; +import java.util.List; + +import static com.paypal.sellers.sellersextract.model.SellerModelConstants.*; +import static com.paypal.sellers.sellersextract.model.SellerModelConstants.HYPERWALLET_PROGRAM; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @ExtendWith(MockitoExtension.class) class UKBankAccountModelTest { + private static final String TOKEN_VALUE_1 = "token1"; + + private static final String TOKEN_VALUE_2 = "token2"; + @Test void setCountry_shouldConvertTo2LettersWhenCountry3IsocodeExists() { final UKBankAccountModel testObj = UKBankAccountModel.builder().country("USA").build(); @@ -60,4 +69,59 @@ void setTransferMethodCurrency_shouldThrowAnExceptionWhenCurrencyIsInvalid() { .hasMessage("Transfer method currency with code: [INVALID_CURRENCY] not valid"); } + @Test + void toBuild_ShouldReturnCopyOfUKBankAccountModel() { + + final UKBankAccountModel bankAccountModel = createUKBankAccountModelObject(TOKEN_VALUE_1); + final UKBankAccountModel copyBankAccountModel = bankAccountModel.toBuilder().build(); + + assertThat(bankAccountModel).isEqualTo(copyBankAccountModel); + } + + @Test + void toBuild_ShouldReturnCopyOfUKBankAccountModelWithTheUpdatedToken() { + + final UKBankAccountModel bankAccountModel1 = createUKBankAccountModelObject(TOKEN_VALUE_1); + final UKBankAccountModel bankAccountModel2 = createUKBankAccountModelObject(TOKEN_VALUE_2); + final UKBankAccountModel copyBankAccountModel = bankAccountModel1.toBuilder().token(TOKEN_VALUE_2).build(); + + assertThat(bankAccountModel2).isEqualTo(copyBankAccountModel); + } + + private UKBankAccountModel createUKBankAccountModelObject(final String token) { + final MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue tokenBankAccountField = new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue(); + tokenBankAccountField.setCode(HYPERWALLET_BANK_ACCOUNT_TOKEN); + tokenBankAccountField.setValue(token); + + final MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue stateProvinceBusinessStakeHolderField = new MiraklAdditionalFieldValue.MiraklStringAdditionalFieldValue(); + stateProvinceBusinessStakeHolderField.setCode(HYPERWALLET_BANK_ACCOUNT_STATE); + stateProvinceBusinessStakeHolderField.setValue("stateProvince"); + + final MiraklAdditionalFieldValue.MiraklValueListAdditionalFieldValue hyperwalletProgramAccountField = new MiraklAdditionalFieldValue.MiraklValueListAdditionalFieldValue(); + hyperwalletProgramAccountField.setCode(HYPERWALLET_PROGRAM); + hyperwalletProgramAccountField.setValue("hyperwalletProgram"); + + //@formatter:off + return UKBankAccountModel.builder() + .transferMethodCountry("USA") + .transferMethodCurrency("EUR") + .transferType(TransferType.BANK_ACCOUNT) + .type(BankAccountType.ABA) + .bankAccountNumber("111") + .businessName("businessName") + .firstName("firstName") + .lastName("lastName") + .country("USA") + .addressLine1("addressLine1") + .addressLine2("addressLine2") + .city("city") + .stateProvince(List.of(stateProvinceBusinessStakeHolderField)) + .postalCode("2222") + .token(List.of(tokenBankAccountField)) + .hyperwalletProgram(List.of(hyperwalletProgramAccountField)) + .bankAccountId("bankAccountId") + .build(); + //@formatter:on + } + } diff --git a/sellers/src/test/java/com/paypal/sellers/bankaccountextract/service/impl/BankAccountTokenSynchronizationServiceImplTest.java b/sellers/src/test/java/com/paypal/sellers/bankaccountextract/service/impl/BankAccountTokenSynchronizationServiceImplTest.java new file mode 100644 index 00000000..b9da2798 --- /dev/null +++ b/sellers/src/test/java/com/paypal/sellers/bankaccountextract/service/impl/BankAccountTokenSynchronizationServiceImplTest.java @@ -0,0 +1,146 @@ +package com.paypal.sellers.bankaccountextract.service.impl; + +import com.hyperwallet.clientsdk.Hyperwallet; +import com.hyperwallet.clientsdk.HyperwalletException; +import com.hyperwallet.clientsdk.model.HyperwalletBankAccount; +import com.hyperwallet.clientsdk.model.HyperwalletList; +import com.hyperwallet.clientsdk.model.HyperwalletUser; +import com.hyperwallet.clientsdk.model.HyperwalletUsersListPaginationOptions; +import com.mirakl.client.core.exception.MiraklApiException; +import com.paypal.infrastructure.exceptions.HMCHyperwalletAPIException; +import com.paypal.infrastructure.exceptions.HMCMiraklAPIException; +import com.paypal.sellers.bankaccountextract.model.BankAccountModel; +import com.paypal.sellers.bankaccountextract.service.MiraklBankAccountExtractService; +import com.paypal.sellers.sellersextract.model.SellerModel; +import com.paypal.sellers.service.HyperwalletSDKService; +import org.assertj.core.api.AssertionsForClassTypes; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class BankAccountTokenSynchronizationServiceImplTest { + + private static final String BANK_ACCOUNT_TOKEN_VALUE = "bankToken"; + + private static final String SELLER_TOKEN_VALUE = "sellerToken"; + + private static final String PROGRAM_TOKEN = "programToken"; + + @InjectMocks + private BankAccountTokenSynchronizationServiceImpl testObj; + + @Mock + private HyperwalletSDKService hyperwalletSDKServiceMock; + + @Mock + private MiraklBankAccountExtractService miraklBankAccountExtractServiceMock; + + @Mock + private Hyperwallet hyperwalletSDKMock; + + @Test + void synchronizeToken_ShouldReturnCurrentSellerModel_WhenSellerBankAccountDetailsAreNull() { + + final SellerModel originalSellerModel = SellerModel.builder().build(); + + final SellerModel result = testObj.synchronizeToken(originalSellerModel); + + assertThat(result).isEqualTo(originalSellerModel); + } + + @Test + void synchronizeToken_ShouldReturnCurrentSellerModel_WhenSellerBankAccountDetailsTokenIsNotNull() { + + final SellerModel originalSellerModel = SellerModel.builder() + .bankAccountDetails(BankAccountModel.builder().token(BANK_ACCOUNT_TOKEN_VALUE).build()).build(); + + final SellerModel result = testObj.synchronizeToken(originalSellerModel); + + assertThat(result).isEqualTo(originalSellerModel); + } + + @Test + void synchronizeToken_ShouldReturnCurrentSellerModel_WhenSellerBankAccountDetailsTokenIsBlankAndBankAccountDoesNotExistInHW() { + + final SellerModel originalSellerModel = SellerModel.builder() + .bankAccountDetails(BankAccountModel.builder().token(BANK_ACCOUNT_TOKEN_VALUE).build()).build(); + + final SellerModel result = testObj.synchronizeToken(originalSellerModel); + + assertThat(result).isEqualTo(originalSellerModel); + } + + @Test + void synchronizeToken_ShouldThrowHMCHyperwalletAPIException_WhenHWRequestThrowAHyperwalletException() { + + when(hyperwalletSDKServiceMock.getHyperwalletInstanceByProgramToken(PROGRAM_TOKEN)) + .thenReturn(hyperwalletSDKMock); + final SellerModel originalSellerModel = SellerModel.builder().token(SELLER_TOKEN_VALUE) + .programToken(PROGRAM_TOKEN).bankAccountDetails(BankAccountModel.builder().build()).build(); + + when(hyperwalletSDKMock.listBankAccounts(SELLER_TOKEN_VALUE)) + .thenThrow(new HyperwalletException("Something went wrong")); + + AssertionsForClassTypes.assertThatThrownBy(() -> testObj.synchronizeToken(originalSellerModel)) + .isInstanceOf(HMCHyperwalletAPIException.class) + .hasMessageContaining("An error has occurred while invoking Hyperwallet API"); + } + + @Test + void synchronizeToken_ShouldThrowHMCMiraklAPIException_WhenMiraklRequestThrowAMiraklApiException() { + + final HyperwalletList bankAccountHyperwalletList = new HyperwalletList<>(); + final HyperwalletBankAccount bankAccount = new HyperwalletBankAccount(); + bankAccount.setToken(BANK_ACCOUNT_TOKEN_VALUE); + bankAccountHyperwalletList.setData(List.of(bankAccount)); + + when(hyperwalletSDKServiceMock.getHyperwalletInstanceByProgramToken(PROGRAM_TOKEN)) + .thenReturn(hyperwalletSDKMock); + when(hyperwalletSDKMock.listBankAccounts(SELLER_TOKEN_VALUE)).thenReturn(bankAccountHyperwalletList); + + final SellerModel originalSellerModel = SellerModel.builder().token(SELLER_TOKEN_VALUE) + .programToken(PROGRAM_TOKEN).bankAccountDetails(BankAccountModel.builder().build()).build(); + + doThrow(MiraklApiException.class).when(miraklBankAccountExtractServiceMock) + .updateBankAccountToken(originalSellerModel, bankAccount); + + AssertionsForClassTypes.assertThatThrownBy(() -> testObj.synchronizeToken(originalSellerModel)) + .isInstanceOf(HMCMiraklAPIException.class) + .hasMessageContaining("An error has occurred while invoking Mirakl API"); + } + + @Test + void synchronizeToken_ShouldReturnASynchronizedBankAccount_WhenSellerBankAccountDetailsTokenIsBlankAndBankAccountDoesExistInHW() { + + final HyperwalletList bankAccountHyperwalletList = new HyperwalletList<>(); + final HyperwalletBankAccount bankAccount = new HyperwalletBankAccount(); + bankAccount.setToken(BANK_ACCOUNT_TOKEN_VALUE); + bankAccountHyperwalletList.setData(List.of(bankAccount)); + + when(hyperwalletSDKServiceMock.getHyperwalletInstanceByProgramToken(PROGRAM_TOKEN)) + .thenReturn(hyperwalletSDKMock); + when(hyperwalletSDKMock.listBankAccounts(SELLER_TOKEN_VALUE)).thenReturn(bankAccountHyperwalletList); + + final SellerModel originalSellerModel = SellerModel.builder().token(SELLER_TOKEN_VALUE) + .programToken(PROGRAM_TOKEN).bankAccountDetails(BankAccountModel.builder().build()).build(); + + final SellerModel result = testObj.synchronizeToken(originalSellerModel); + + verify(miraklBankAccountExtractServiceMock).updateBankAccountToken(originalSellerModel, bankAccount); + assertThat(result.getBankAccountDetails().getToken()).isEqualTo(BANK_ACCOUNT_TOKEN_VALUE); + assertThat(result.getToken()).isEqualTo(SELLER_TOKEN_VALUE); + assertThat(result.getProgramToken()).isEqualTo(PROGRAM_TOKEN); + } + +} diff --git a/sellers/src/test/java/com/paypal/sellers/bankaccountextract/service/strategies/AbstractHyperwalletBankAccountRetryApiStrategyTest.java b/sellers/src/test/java/com/paypal/sellers/bankaccountextract/service/strategies/AbstractHyperwalletBankAccountRetryApiStrategyTest.java index 3d4abf85..22418c5b 100644 --- a/sellers/src/test/java/com/paypal/sellers/bankaccountextract/service/strategies/AbstractHyperwalletBankAccountRetryApiStrategyTest.java +++ b/sellers/src/test/java/com/paypal/sellers/bankaccountextract/service/strategies/AbstractHyperwalletBankAccountRetryApiStrategyTest.java @@ -2,6 +2,9 @@ import com.hyperwallet.clientsdk.HyperwalletException; import com.hyperwallet.clientsdk.model.HyperwalletBankAccount; +import com.mirakl.client.core.exception.MiraklApiException; +import com.paypal.infrastructure.exceptions.HMCHyperwalletAPIException; +import com.paypal.infrastructure.exceptions.HMCMiraklAPIException; import com.paypal.infrastructure.mail.MailNotificationUtil; import com.paypal.infrastructure.strategy.StrategyExecutor; import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; @@ -9,6 +12,7 @@ import com.paypal.sellers.sellersextract.model.SellerModel; import com.paypal.sellers.service.FailedEntityInformationService; import com.paypal.sellers.service.HyperwalletSDKService; +import org.assertj.core.api.AssertionsForClassTypes; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -16,8 +20,6 @@ import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; -import java.io.IOException; - import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) @@ -41,9 +43,6 @@ class AbstractHyperwalletBankAccountRetryApiStrategyTest { @Mock private MailNotificationUtil mailNotificationUtilMock; - @Mock - private IOException ioExceptionMock; - @Mock private HyperwalletException hyperwalletExceptionMock; @@ -55,7 +54,6 @@ void execute_shouldCallHyperwalletAPI() { when(sellerModelToHyperwalletBankAccountStrategyExecutorMock.execute(sellerModelMock)) .thenReturn(hyperwalletBankAccountMock); when(sellerModelMock.getHyperwalletProgram()).thenReturn(HYPERWALLET_PROGRAM); - doNothing().when(testObj).callToIncludeIntoRetryProcess(sellerModelMock, Boolean.FALSE); testObj.execute(sellerModelMock); verify(sellerModelToHyperwalletBankAccountStrategyExecutorMock).execute(sellerModelMock); @@ -69,33 +67,31 @@ void execute_shouldSendEmailNotificationHyperwalletExceptionIsThrown() { when(sellerModelMock.getHyperwalletProgram()).thenReturn(HYPERWALLET_PROGRAM); when(sellerModelToHyperwalletBankAccountStrategyExecutorMock.execute(sellerModelMock)) .thenReturn(hyperwalletBankAccountMock); - doNothing().when(testObj).callToIncludeIntoRetryProcess(sellerModelMock, Boolean.FALSE); doThrow(hyperwalletException).when(testObj).callHyperwalletAPI(HYPERWALLET_PROGRAM, hyperwalletBankAccountMock); - testObj.execute(sellerModelMock); + AssertionsForClassTypes.assertThatThrownBy(() -> testObj.execute(sellerModelMock)) + .isInstanceOf(HMCHyperwalletAPIException.class) + .hasMessageContaining("An error has occurred while invoking Hyperwallet API"); verify(mailNotificationUtilMock).sendPlainTextEmail( "Issue detected when creating or updating bank account in Hyperwallet", String.format( ERROR_MESSAGE_PREFIX + "Bank account not created or updated for seller with clientId [%s]%n%s", "2001", HyperwalletLoggingErrorsUtil.stringify(hyperwalletException))); - verify(testObj).callToIncludeIntoRetryProcess(sellerModelMock, Boolean.FALSE); } @Test - void execute_shouldSendEmailNotificationAndIncludeSellerIntoRetryProcessWhenIOExceptionIsThrown() { - when(hyperwalletExceptionMock.getCause()).thenReturn(ioExceptionMock); + void execute_ShouldThrowMiraklApiException_WhenMiraklRequestThrowsAnHMCMiraklAPIException() { when(sellerModelMock.getClientUserId()).thenReturn("2001"); when(sellerModelMock.getHyperwalletProgram()).thenReturn(HYPERWALLET_PROGRAM); when(sellerModelToHyperwalletBankAccountStrategyExecutorMock.execute(sellerModelMock)) .thenReturn(hyperwalletBankAccountMock); - doThrow(hyperwalletExceptionMock).when(testObj).callHyperwalletAPI(HYPERWALLET_PROGRAM, + doThrow(MiraklApiException.class).when(testObj).callHyperwalletAPI(HYPERWALLET_PROGRAM, hyperwalletBankAccountMock); - doNothing().when(testObj).callToIncludeIntoRetryProcess(sellerModelMock, Boolean.TRUE); - - testObj.execute(sellerModelMock); - verify(testObj).callToIncludeIntoRetryProcess(sellerModelMock, Boolean.TRUE); + AssertionsForClassTypes.assertThatThrownBy(() -> testObj.execute(sellerModelMock)) + .isInstanceOf(HMCMiraklAPIException.class) + .hasMessageContaining("An error has occurred while invoking Mirakl API"); } private static class MyAbstractHyperwalletBankAccountRetryApiStrategy @@ -105,8 +101,7 @@ public MyAbstractHyperwalletBankAccountRetryApiStrategy( final FailedEntityInformationService failedEntityInformationService, final StrategyExecutor sellerModelToHyperwalletBankAccountStrategyExecutor, final HyperwalletSDKService hyperwalletSDKService, final MailNotificationUtil mailNotificationUtil) { - super(failedEntityInformationService, sellerModelToHyperwalletBankAccountStrategyExecutor, - hyperwalletSDKService, mailNotificationUtil); + super(sellerModelToHyperwalletBankAccountStrategyExecutor, hyperwalletSDKService, mailNotificationUtil); } @Override diff --git a/sellers/src/test/java/com/paypal/sellers/batchjobs/bankaccount/BankAccountExtractBatchJobItemProcessorTest.java b/sellers/src/test/java/com/paypal/sellers/batchjobs/bankaccount/BankAccountExtractBatchJobItemProcessorTest.java index 9e680c6c..cb1fdad9 100644 --- a/sellers/src/test/java/com/paypal/sellers/batchjobs/bankaccount/BankAccountExtractBatchJobItemProcessorTest.java +++ b/sellers/src/test/java/com/paypal/sellers/batchjobs/bankaccount/BankAccountExtractBatchJobItemProcessorTest.java @@ -1,6 +1,7 @@ package com.paypal.sellers.batchjobs.bankaccount; import com.paypal.infrastructure.batchjob.BatchJobContext; +import com.paypal.sellers.bankaccountextract.service.impl.BankAccountTokenSynchronizationServiceImpl; import com.paypal.sellers.bankaccountextract.service.strategies.HyperWalletBankAccountStrategyExecutor; import com.paypal.sellers.sellersextract.model.SellerModel; import org.junit.jupiter.api.Test; @@ -10,6 +11,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class BankAccountExtractBatchJobItemProcessorTest { @@ -20,6 +22,9 @@ class BankAccountExtractBatchJobItemProcessorTest { @Mock private HyperWalletBankAccountStrategyExecutor hyperWalletBankAccountStrategyExecutorMock; + @Mock + private BankAccountTokenSynchronizationServiceImpl bankAccountTokenSynchronizationServiceMock; + @Mock private BatchJobContext batchJobContextMock; @@ -29,9 +34,14 @@ void processItem_ShouldExecuteHyperWalletBankAccountServiceExecutor() { final SellerModel sellerModel = SellerModel.builder().build(); final BankAccountExtractJobItem bankAccountExtractJobItem = new BankAccountExtractJobItem(sellerModel); + final SellerModel synchronizedSellerModel = SellerModel.builder().build(); + + when(bankAccountTokenSynchronizationServiceMock.synchronizeToken(sellerModel)) + .thenReturn(synchronizedSellerModel); + testObj.processItem(batchJobContextMock, bankAccountExtractJobItem); - verify(hyperWalletBankAccountStrategyExecutorMock).execute(sellerModel); + verify(hyperWalletBankAccountStrategyExecutorMock).execute(synchronizedSellerModel); } } diff --git a/sellers/src/test/java/com/paypal/sellers/batchjobs/bankaccount/BankAccountExtractBatchJobItemsExtractorTest.java b/sellers/src/test/java/com/paypal/sellers/batchjobs/bankaccount/BankAccountExtractBatchJobItemsExtractorTest.java index b01a3834..26616c69 100644 --- a/sellers/src/test/java/com/paypal/sellers/batchjobs/bankaccount/BankAccountExtractBatchJobItemsExtractorTest.java +++ b/sellers/src/test/java/com/paypal/sellers/batchjobs/bankaccount/BankAccountExtractBatchJobItemsExtractorTest.java @@ -27,18 +27,20 @@ class BankAccountExtractBatchJobItemsExtractorTest { private MiraklSellersExtractService miraklSellersExtractServiceMock; @Mock - private SellerModel sellerModelMock1, sellerModelMock2; + private SellerModel sellerModelMock1, sellerModelMock2, sellerModelMock3, sellerModelMock4; @Test void getItems_ShouldRetrieveAllBankAccountExtractJobItemForTheGivenDelta() { when(miraklSellersExtractServiceMock.extractIndividuals(DELTA)) .thenReturn(List.of(sellerModelMock1, sellerModelMock2)); + when(miraklSellersExtractServiceMock.extractProfessionals(DELTA)) + .thenReturn(List.of(sellerModelMock3, sellerModelMock4)); final Collection result = testObj.getItems(DELTA); assertThat(result.stream().map(BankAccountExtractJobItem::getItem)).containsExactlyInAnyOrder(sellerModelMock1, - sellerModelMock2); + sellerModelMock2, sellerModelMock3, sellerModelMock4); } } diff --git a/sellers/src/test/java/com/paypal/sellers/batchjobs/individuals/IndividualSellersExtractBatchJobItemProcessorTest.java b/sellers/src/test/java/com/paypal/sellers/batchjobs/individuals/IndividualSellersExtractBatchJobItemProcessorTest.java index 12cef6a1..d811247e 100644 --- a/sellers/src/test/java/com/paypal/sellers/batchjobs/individuals/IndividualSellersExtractBatchJobItemProcessorTest.java +++ b/sellers/src/test/java/com/paypal/sellers/batchjobs/individuals/IndividualSellersExtractBatchJobItemProcessorTest.java @@ -1,8 +1,10 @@ package com.paypal.sellers.batchjobs.individuals; import com.paypal.infrastructure.batchjob.BatchJobContext; +import com.paypal.infrastructure.service.TokenSynchronizationService; import com.paypal.sellers.sellersextract.model.SellerModel; import com.paypal.sellers.sellersextract.service.strategies.HyperWalletUserServiceStrategyExecutor; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -10,6 +12,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class IndividualSellersExtractBatchJobItemProcessorTest { @@ -20,19 +23,39 @@ class IndividualSellersExtractBatchJobItemProcessorTest { @Mock private HyperWalletUserServiceStrategyExecutor hyperWalletUserServiceStrategyExecutorMock; + @Mock + private TokenSynchronizationService tokenSynchronizationServiceMock; + @Mock private BatchJobContext batchJobContextMock; - @Test - void processItem_ShouldExecuteHyperWalletUserServiceStrategyExecutor() { + private SellerModel sellerModel; + + private IndividualSellerExtractJobItem individualSellerExtractJobItem; - final SellerModel sellerModel = SellerModel.builder().build(); - final IndividualSellerExtractJobItem individualSellerExtractJobItem = new IndividualSellerExtractJobItem( - sellerModel); + @BeforeEach + void setUp() { + sellerModel = SellerModel.builder().build(); + individualSellerExtractJobItem = new IndividualSellerExtractJobItem(sellerModel); + when(tokenSynchronizationServiceMock.synchronizeToken(sellerModel)).thenReturn(sellerModel); + } + + @Test + void processItem_ShouldAlwaysExecuteHyperWalletUserServiceStrategyExecutor() { + when(hyperWalletUserServiceStrategyExecutorMock.execute(sellerModel)).thenReturn(sellerModel); testObj.processItem(batchJobContextMock, individualSellerExtractJobItem); verify(hyperWalletUserServiceStrategyExecutorMock).execute(sellerModel); } + @Test + void processItem_shouldSynchronizeSellerBetweenHyperwalletAndMirakl() { + when(hyperWalletUserServiceStrategyExecutorMock.execute(sellerModel)).thenReturn(sellerModel); + + testObj.processItem(batchJobContextMock, individualSellerExtractJobItem); + + verify(tokenSynchronizationServiceMock).synchronizeToken(sellerModel); + } + } diff --git a/sellers/src/test/java/com/paypal/sellers/batchjobs/professionals/ProfessionalSellersExtractBatchJobItemProcessorTest.java b/sellers/src/test/java/com/paypal/sellers/batchjobs/professionals/ProfessionalSellersExtractBatchJobItemProcessorTest.java index efff8cbf..f155f762 100644 --- a/sellers/src/test/java/com/paypal/sellers/batchjobs/professionals/ProfessionalSellersExtractBatchJobItemProcessorTest.java +++ b/sellers/src/test/java/com/paypal/sellers/batchjobs/professionals/ProfessionalSellersExtractBatchJobItemProcessorTest.java @@ -1,8 +1,11 @@ package com.paypal.sellers.batchjobs.professionals; import com.paypal.infrastructure.batchjob.BatchJobContext; +import com.paypal.infrastructure.service.TokenSynchronizationService; import com.paypal.sellers.sellersextract.model.SellerModel; +import com.paypal.sellers.sellersextract.service.MiraklSellersExtractService; import com.paypal.sellers.sellersextract.service.strategies.HyperWalletUserServiceStrategyExecutor; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; @@ -10,6 +13,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; @ExtendWith(MockitoExtension.class) class ProfessionalSellersExtractBatchJobItemProcessorTest { @@ -20,19 +24,42 @@ class ProfessionalSellersExtractBatchJobItemProcessorTest { @Mock private HyperWalletUserServiceStrategyExecutor hyperWalletUserServiceStrategyExecutorMock; + @Mock + private MiraklSellersExtractService miraklSellersExtractServiceMock; + + @Mock + private TokenSynchronizationService tokenSynchronizationServiceMock; + @Mock private BatchJobContext batchJobContextMock; - @Test - void processItem_ShouldProcessItem() { + private SellerModel sellerModel; + + private ProfessionalSellerExtractJobItem professionalSellerExtractJobItem; - final SellerModel sellerModel = SellerModel.builder().build(); - final ProfessionalSellerExtractJobItem professionalSellerExtractJobItem = new ProfessionalSellerExtractJobItem( - sellerModel); + @BeforeEach + void setUp() { + sellerModel = SellerModel.builder().build(); + professionalSellerExtractJobItem = new ProfessionalSellerExtractJobItem(sellerModel); + when(tokenSynchronizationServiceMock.synchronizeToken(sellerModel)).thenReturn(sellerModel); + } + + @Test + void processItem_ShouldAlwaysExecuteHyperWalletUserServiceStrategyExecutor() { + when(hyperWalletUserServiceStrategyExecutorMock.execute(sellerModel)).thenReturn(sellerModel); testObj.processItem(batchJobContextMock, professionalSellerExtractJobItem); verify(hyperWalletUserServiceStrategyExecutorMock).execute(sellerModel); } + @Test + void processItem_shouldSynchronizeSellerBetweenHyperwalletAndMirakl() { + when(hyperWalletUserServiceStrategyExecutorMock.execute(sellerModel)).thenReturn(sellerModel); + + testObj.processItem(batchJobContextMock, professionalSellerExtractJobItem); + + verify(tokenSynchronizationServiceMock).synchronizeToken(sellerModel); + } + } diff --git a/sellers/src/test/java/com/paypal/sellers/sellersextract/service/impl/SellersTokenSynchronizationServiceImplTest.java b/sellers/src/test/java/com/paypal/sellers/sellersextract/service/impl/SellersTokenSynchronizationServiceImplTest.java new file mode 100644 index 00000000..41b53eae --- /dev/null +++ b/sellers/src/test/java/com/paypal/sellers/sellersextract/service/impl/SellersTokenSynchronizationServiceImplTest.java @@ -0,0 +1,184 @@ +package com.paypal.sellers.sellersextract.service.impl; + +import com.hyperwallet.clientsdk.Hyperwallet; +import com.hyperwallet.clientsdk.HyperwalletException; +import com.hyperwallet.clientsdk.model.HyperwalletList; +import com.hyperwallet.clientsdk.model.HyperwalletUser; +import com.hyperwallet.clientsdk.model.HyperwalletUsersListPaginationOptions; +import com.mirakl.client.core.exception.MiraklException; +import com.paypal.infrastructure.exceptions.HMCHyperwalletAPIException; +import com.paypal.infrastructure.exceptions.HMCMiraklAPIException; +import com.paypal.sellers.sellersextract.model.SellerModel; +import com.paypal.sellers.sellersextract.service.MiraklSellersExtractService; +import com.paypal.sellers.service.HyperwalletSDKService; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.ArgumentMatcher; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.List; +import java.util.Objects; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.assertj.core.api.AssertionsForClassTypes.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.*; + +@ExtendWith(MockitoExtension.class) +class SellersTokenSynchronizationServiceImplTest { + + public static final String USR_TOKEN = "usr-1291289283"; + + @InjectMocks + private SellersTokenSynchronizationServiceImpl testObj; + + @Mock + private HyperwalletSDKService hyperwalletSDKServiceMock; + + @Mock + private MiraklSellersExtractService miraklSellersExtractServiceMock; + + @Mock + private Hyperwallet hyperwalletMock; + + private SellerModel sellerModelStub; + + private HyperwalletUser hyperwalletUser; + + @BeforeEach + void setUp() { + hyperwalletUser = new HyperwalletUser(); + hyperwalletUser.setToken(USR_TOKEN); + } + + @Test + void synchronizeToken_shouldDoNothingAndReturnTheSellerWhenTokenExists() { + createSellerWithTokenAndClientUserId("prg-12312222", "usr-1291289283", "2000"); + + final SellerModel result = testObj.synchronizeToken(sellerModelStub); + + assertThat(result).isEqualTo(sellerModelStub); + } + + @Test + void synchronizeToken_shouldReturnSameSellerWhenSellerDoesNotExistsOnHyperwallet() { + createSellerWithTokenAndClientUserId("prg-12312222", null, "2000"); + prepareHyperwalletSDKInstance(sellerModelStub); + hyperwalletAPIReturnsAnEmptyListForClientUserId("2000"); + + final SellerModel result = testObj.synchronizeToken(sellerModelStub); + + assertThat(result).isEqualTo(sellerModelStub); + } + + @Test + void synchronizeToken_shouldReturnTheSellerWithTheTokenRetrievedFromHyperwalletWhenSellerExistsOnHyperwalletAndTheTokenDoesNotExistOnTheSeller() { + createSellerWithTokenAndClientUserId("prg-12312222", null, "2000"); + prepareHyperwalletSDKInstance(sellerModelStub); + hyperwalletAPIReturnsAListWithOneUserForClientUserId("2000"); + + final SellerModel result = testObj.synchronizeToken(sellerModelStub); + + assertThat(result.getToken()).isEqualTo(USR_TOKEN); + } + + @Test + void synchronizeToken_shouldThrowAnHMCHyperwalletAPIExceptionWhenHyperwalletSDKReturnsAnHyperwalletException() { + createSellerWithTokenAndClientUserId("prg-12312222", null, "2000"); + prepareHyperwalletSDKInstance(sellerModelStub); + hyperwalletSDKThrowsAnException(); + + assertThatThrownBy(() -> testObj.synchronizeToken(sellerModelStub)) + .isInstanceOf(HMCHyperwalletAPIException.class) + .hasMessageContaining("An error has occurred while invoking Hyperwallet API"); + } + + @Test + void synchronizeToken_shouldSetOnMiraklTheHyperwalletTokenWhenSellersExistsOnHyperwalletAndTheTokenDoesNotExistsOnTheSeller() { + createSellerWithTokenAndClientUserId("prg-12312222", null, "2000"); + prepareHyperwalletSDKInstance(sellerModelStub); + hyperwalletAPIReturnsAListWithOneUserForClientUserId("2000"); + + testObj.synchronizeToken(sellerModelStub); + + verify(miraklSellersExtractServiceMock).updateUserToken(hyperwalletUser); + } + + @Test + void synchronizeToken_shouldThrowAnHMCMiraklApiExceptionWhenMiraklReturnsAnMiraklException() { + createSellerWithTokenAndClientUserId("prg-12312222", null, "2000"); + prepareHyperwalletSDKInstance(sellerModelStub); + hyperwalletAPIReturnsAListWithOneUserForClientUserId("2000"); + miraklSDKThrowsAnException(); + + assertThatThrownBy(() -> testObj.synchronizeToken(sellerModelStub)).isInstanceOf(HMCMiraklAPIException.class) + .hasMessageContaining("An error has occurred while invoking Mirakl API"); + } + + @NotNull + private void createSellerWithTokenAndClientUserId(final String programToken, final String userToken, + final String clientUserId) { + sellerModelStub = SellerModel.builder().programToken(programToken).token(userToken).clientUserId(clientUserId) + .build(); + } + + private void hyperwalletAPIReturnsAnEmptyListForClientUserId(final String clientUserId) { + final HyperwalletUsersListPaginationOptions options = new HyperwalletUsersListPaginationOptions(); + options.setClientUserId(clientUserId); + when(hyperwalletMock.listUsers(argThat(new HyperwalletUsersListPaginationOptionsMatcher(options)))) + .thenReturn(new HyperwalletList<>()); + } + + private void hyperwalletAPIReturnsAListWithOneUserForClientUserId(final String clientUserId) { + final HyperwalletUsersListPaginationOptions options = new HyperwalletUsersListPaginationOptions(); + options.setClientUserId(clientUserId); + + final HyperwalletList userHyperwalletList = new HyperwalletList<>(); + userHyperwalletList.setData(List.of(hyperwalletUser)); + when(hyperwalletMock.listUsers(argThat(new HyperwalletUsersListPaginationOptionsMatcher(options)))) + .thenReturn(userHyperwalletList); + } + + private void hyperwalletSDKThrowsAnException() { + doThrow(new HyperwalletException("Something went wrong")).when(hyperwalletMock) + .listUsers(any(HyperwalletUsersListPaginationOptions.class)); + + } + + private void miraklSDKThrowsAnException() { + doThrow(new MiraklException("Something went wrong")).when(miraklSellersExtractServiceMock) + .updateUserToken(any(HyperwalletUser.class)); + + } + + private void prepareHyperwalletSDKInstance(final SellerModel sellerModel) { + when(hyperwalletSDKServiceMock.getHyperwalletInstanceByProgramToken(sellerModel.getProgramToken())) + .thenReturn(hyperwalletMock); + } + + public class HyperwalletUsersListPaginationOptionsMatcher + implements ArgumentMatcher { + + private final HyperwalletUsersListPaginationOptions left; + + public HyperwalletUsersListPaginationOptionsMatcher(final HyperwalletUsersListPaginationOptions options) { + this.left = options; + } + + @Override + public boolean matches(final HyperwalletUsersListPaginationOptions right) { + return Objects.equals(left.getClientUserId(), right.getClientUserId()) + && Objects.equals(left.getProgramToken(), right.getProgramToken()) + && Objects.equals(left.getEmail(), right.getEmail()) + && Objects.equals(left.getStatus(), right.getStatus()) + && Objects.equals(left.getVerificationStatus(), right.getVerificationStatus()); + } + + } + +} diff --git a/sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/AbstractHyperwalletSellerRetryApiStrategyTest.java b/sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/AbstractHyperwalletSellerRetryApiStrategyTest.java deleted file mode 100644 index 42b8e8bf..00000000 --- a/sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/AbstractHyperwalletSellerRetryApiStrategyTest.java +++ /dev/null @@ -1,117 +0,0 @@ -package com.paypal.sellers.sellersextract.service.strategies; - -import com.hyperwallet.clientsdk.HyperwalletException; -import com.hyperwallet.clientsdk.model.HyperwalletUser; -import com.paypal.infrastructure.converter.Converter; -import com.paypal.infrastructure.mail.MailNotificationUtil; -import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; -import com.paypal.sellers.entity.FailedSellersInformation; -import com.paypal.sellers.sellersextract.model.SellerModel; -import com.paypal.sellers.service.FailedEntityInformationService; -import com.paypal.sellers.service.HyperwalletSDKService; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Spy; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.io.IOException; - -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -class AbstractHyperwalletSellerRetryApiStrategyTest { - - @Spy - @InjectMocks - private MyAbstractHyperwalletSellerRetryApiStrategy testObj; - - @Mock - private Converter sellerModelHyperwalletUserConverterMock; - - @Mock - private SellerModel sellerModelMock; - - @Mock - private IOException ioExceptionMock; - - @Mock - private HyperwalletUser hyperwalletUserMock; - - @Mock - private MailNotificationUtil mailNotificationUtilMock; - - @Mock - private HyperwalletException hyperwalletExceptionMock; - - private static final String ERROR_MESSAGE_PREFIX = "There was an error, please check the logs for further " - + "information:\n"; - - @Test - void execute_shouldCallMiraklAPI() { - when(sellerModelHyperwalletUserConverterMock.convert(sellerModelMock)).thenReturn(hyperwalletUserMock); - doNothing().when(testObj).callToIncludeIntoRetryProcess(sellerModelMock, Boolean.FALSE); - - testObj.execute(sellerModelMock); - - verify(sellerModelHyperwalletUserConverterMock).convert(sellerModelMock); - verify(testObj).createOrUpdateUserOnHyperWalletAndUpdateItsTokenOnMirakl(hyperwalletUserMock); - } - - @Test - void execute_shouldSendEmailNotificationHyperwalletExceptionIsThrown() { - final HyperwalletException hyperwalletException = new HyperwalletException("Something went wrong"); - when(sellerModelMock.getClientUserId()).thenReturn("2001"); - when(sellerModelHyperwalletUserConverterMock.convert(sellerModelMock)).thenReturn(hyperwalletUserMock); - doNothing().when(testObj).callToIncludeIntoRetryProcess(sellerModelMock, Boolean.FALSE); - doThrow(hyperwalletException).when(testObj) - .createOrUpdateUserOnHyperWalletAndUpdateItsTokenOnMirakl(hyperwalletUserMock); - - testObj.execute(sellerModelMock); - - verify(mailNotificationUtilMock).sendPlainTextEmail( - "Issue detected when creating or updating seller in Hyperwallet", - String.format(ERROR_MESSAGE_PREFIX + "Seller not created or updated with clientId [%s]%n%s", "2001", - HyperwalletLoggingErrorsUtil.stringify(hyperwalletException))); - verify(testObj).callToIncludeIntoRetryProcess(sellerModelMock, Boolean.FALSE); - } - - @Test - void execute_shouldSendEmailNotificationAndIncludeSellerIntoRetryProcessWhenIOExceptionIsThrown() { - when(hyperwalletExceptionMock.getCause()).thenReturn(ioExceptionMock); - when(sellerModelMock.getClientUserId()).thenReturn("2001"); - when(sellerModelHyperwalletUserConverterMock.convert(sellerModelMock)).thenReturn(hyperwalletUserMock); - doThrow(hyperwalletExceptionMock).when(testObj) - .createOrUpdateUserOnHyperWalletAndUpdateItsTokenOnMirakl(hyperwalletUserMock); - doNothing().when(testObj).callToIncludeIntoRetryProcess(sellerModelMock, Boolean.TRUE); - - testObj.execute(sellerModelMock); - - verify(testObj).callToIncludeIntoRetryProcess(sellerModelMock, Boolean.TRUE); - } - - private static class MyAbstractHyperwalletSellerRetryApiStrategy extends AbstractHyperwalletSellerRetryApiStrategy { - - protected MyAbstractHyperwalletSellerRetryApiStrategy( - final FailedEntityInformationService failedEntityInformationService, - final Converter sellerModelHyperwalletUserConverter, - final HyperwalletSDKService hyperwalletSDKService, final MailNotificationUtil mailNotificationUtil) { - super(failedEntityInformationService, sellerModelHyperwalletUserConverter, hyperwalletSDKService, - mailNotificationUtil); - } - - @Override - protected HyperwalletUser createOrUpdateUserOnHyperWalletAndUpdateItsTokenOnMirakl( - final HyperwalletUser hyperwalletUser) { - return null; - } - - @Override - public boolean isApplicable(final SellerModel source) { - return false; - } - - } - -} diff --git a/sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/AbstractHyperwalletSellerServiceStrategyTest.java b/sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/AbstractHyperwalletSellerServiceStrategyTest.java new file mode 100644 index 00000000..93eb9e38 --- /dev/null +++ b/sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/AbstractHyperwalletSellerServiceStrategyTest.java @@ -0,0 +1,75 @@ +package com.paypal.sellers.sellersextract.service.strategies; + +import com.hyperwallet.clientsdk.model.HyperwalletUser; +import com.paypal.infrastructure.converter.Converter; +import com.paypal.infrastructure.mail.MailNotificationUtil; +import com.paypal.sellers.sellersextract.model.SellerModel; +import com.paypal.sellers.service.HyperwalletSDKService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.jupiter.MockitoExtension; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@ExtendWith(MockitoExtension.class) +class AbstractHyperwalletSellerServiceStrategyTest { + + public static final String USR_TOKEN = "usr-1200210"; + + @Spy + @InjectMocks + private MyAbstractHyperwalletSellerServiceStrategy testObj; + + @Mock + private Converter sellerModelHyperwalletUserConverterMock; + + private SellerModel sellerModelStub; + + @Mock + private HyperwalletUser hyperwalletUserStub; + + @BeforeEach + void setUp() { + sellerModelStub = SellerModel.builder().clientUserId("2000").build(); + hyperwalletUserStub = new HyperwalletUser(); + hyperwalletUserStub.setToken(USR_TOKEN); + } + + @Test + void execute_shouldConvertTheSellerModelIntoHyperwalletUserCallHyperwalletAndReturnAnUpdatedSellerModelWithTheTokenFromHyperwalletCall() { + when(sellerModelHyperwalletUserConverterMock.convert(sellerModelStub)).thenReturn(hyperwalletUserStub); + when(testObj.pushToHyperwallet(hyperwalletUserStub)).thenReturn(hyperwalletUserStub); + + final SellerModel result = testObj.execute(sellerModelStub); + + verify(testObj).pushToHyperwallet(hyperwalletUserStub); + assertThat(result.getToken()).isEqualTo(USR_TOKEN); + } + + private static class MyAbstractHyperwalletSellerServiceStrategy extends AbstractHyperwalletSellerServiceStrategy { + + protected MyAbstractHyperwalletSellerServiceStrategy( + final Converter sellerModelHyperwalletUserConverter, + final HyperwalletSDKService hyperwalletSDKService, final MailNotificationUtil mailNotificationUtil) { + super(sellerModelHyperwalletUserConverter, hyperwalletSDKService, mailNotificationUtil); + } + + @Override + protected HyperwalletUser pushToHyperwallet(final HyperwalletUser hyperwalletUser) { + return null; + } + + @Override + public boolean isApplicable(final SellerModel source) { + return false; + } + + } + +} diff --git a/sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletCreateSellerServiceStrategyTest.java b/sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletCreateSellerServiceStrategyTest.java index 804eab1f..06288ed2 100644 --- a/sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletCreateSellerServiceStrategyTest.java +++ b/sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletCreateSellerServiceStrategyTest.java @@ -1,57 +1,131 @@ package com.paypal.sellers.sellersextract.service.strategies; -import com.hyperwallet.clientsdk.Hyperwallet; import com.hyperwallet.clientsdk.model.HyperwalletUser; -import com.paypal.sellers.sellersextract.model.SellerModel; +import com.paypal.infrastructure.exceptions.HMCHyperwalletAPIException; +import com.paypal.infrastructure.exceptions.HMCMiraklAPIException; +import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; +import com.paypal.infrastructure.util.MiraklLoggingErrorsUtil; import com.paypal.sellers.sellersextract.service.MiraklSellersExtractService; -import com.paypal.sellers.service.HyperwalletSDKService; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; +import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; +import org.slf4j.Logger; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) -class HyperWalletCreateSellerServiceStrategyTest { - - private static final String TOKEN = "token"; - - private static final String PROGRAM_TOKEN_VALUE = "programTokenValue"; +class HyperWalletCreateSellerServiceStrategyTest extends HyperwalletSellerServiceStrategyTest { + @Spy @InjectMocks private HyperWalletCreateSellerServiceStrategy testObj; @Mock - private SellerModel sellerModelMock; + private MiraklSellersExtractService miraklSellersExtractServiceMock; - @Mock - private HyperwalletUser hyperwalletUserRequestMock, hyperwalletUserResponseMock; + @Test + void pushToHyperwallet_shouldCreateUserInHyperwallet() { + prepareHyperwalletSDKInstance(); + when(hyperwalletMock.createUser(hyperwalletUserRequestMock)).thenReturn(hyperwalletUserResponseMock); - @Mock - private HyperwalletSDKService hyperwalletSDKServiceMock; + final HyperwalletUser result = testObj.pushToHyperwallet(hyperwalletUserRequestMock); - @Mock - private Hyperwallet hyperwalletMock; + verify(hyperwalletMock).createUser(hyperwalletUserRequestMock); + assertThat(result).isEqualTo(hyperwalletUserResponseMock); + } - @Mock - private MiraklSellersExtractService miraklSellersExtractServiceMock; + @Test + void pushToHyperwallet_shouldThrowHMCHyperwalletAPIExceptionWhenHyperwalletSDKFails() { + doNothing().when(testObj).reportError(anyString(), anyString()); + prepareHyperwalletSDKInstance(); + ensureHyperwalletSDKThrowsAnHMCException(); + + assertThatThrownBy(() -> testObj.pushToHyperwallet(hyperwalletUserRequestMock)) + .isInstanceOf(HMCHyperwalletAPIException.class); + } + + @Test + void pushToHyperwallet_shouldSendAnEmailWhenHyperwalletSDKFails() { + doNothing().when(testObj).reportError(anyString(), anyString()); + prepareHyperwalletSDKInstance(); + ensureHyperwalletSDKThrowsAnHMCException(); + + assertThatThrownBy(() -> testObj.pushToHyperwallet(hyperwalletUserRequestMock)) + .isInstanceOf(HMCHyperwalletAPIException.class); + + verify(testObj).reportError("Issue detected when creating seller in Hyperwallet", + String.format(ERROR_MESSAGE_PREFIX + "Seller not created with clientId [%s]%n%s", CLIENT_USER_ID, + HyperwalletLoggingErrorsUtil.stringify(hyperwalletException))); + } + + @Test + void pushToHyperwallet_shouldLogTheExceptionWhenHyperwalletSDKFails() { + doNothing().when(testObj).reportError(anyString(), anyString()); + prepareHyperwalletSDKInstance(); + ensureHyperwalletSDKThrowsAnHMCException(); + + assertThatThrownBy(() -> testObj.pushToHyperwallet(hyperwalletUserRequestMock)) + .isInstanceOf(HMCHyperwalletAPIException.class); + + verify(testObj).logErrors( + eq(String.format("Error creating seller in hyperwallet with clientUserId [%s]: [{}]", CLIENT_USER_ID)), + eq(hyperwalletException), any(Logger.class)); + } @Test - void createOrUpdateUserOnHyperWalletAndUpdateItsTokenOnMirakl_shouldCreateUserAndUpdateToken() { - when(hyperwalletSDKServiceMock.getHyperwalletInstanceByProgramToken(PROGRAM_TOKEN_VALUE)) - .thenReturn(hyperwalletMock); + void pushToHyperwallet_shouldUpdateTheTokenInMiraklAfterAnUserIsSuccessfullyCreatedInHw() { + prepareHyperwalletSDKInstance(); when(hyperwalletMock.createUser(hyperwalletUserRequestMock)).thenReturn(hyperwalletUserResponseMock); - when(hyperwalletUserRequestMock.getProgramToken()).thenReturn(PROGRAM_TOKEN_VALUE); - final HyperwalletUser result = testObj - .createOrUpdateUserOnHyperWalletAndUpdateItsTokenOnMirakl(hyperwalletUserRequestMock); - verify(hyperwalletMock).createUser(hyperwalletUserRequestMock); + testObj.pushToHyperwallet(hyperwalletUserRequestMock); + verify(miraklSellersExtractServiceMock).updateUserToken(hyperwalletUserResponseMock); - assertThat(result).isEqualTo(hyperwalletUserResponseMock); + } + + @Test + void pushToHyperwallet_shouldThrowHMCMiraklAPIExceptionWhenMiraklSDKFails() { + doNothing().when(testObj).reportError(anyString(), anyString()); + prepareHyperwalletSDKInstance(); + when(hyperwalletMock.createUser(hyperwalletUserRequestMock)).thenReturn(hyperwalletUserResponseMock); + ensureMiraklSDKThrowsAnHMCException(); + + assertThatThrownBy(() -> testObj.pushToHyperwallet(hyperwalletUserRequestMock)) + .isInstanceOf(HMCMiraklAPIException.class); + } + + @Test + void pushToHyperwallet_shouldSendAnEmailWhenMiraklSDKFails() { + doNothing().when(testObj).reportError(anyString(), anyString()); + prepareHyperwalletSDKInstance(); + when(hyperwalletMock.createUser(hyperwalletUserRequestMock)).thenReturn(hyperwalletUserResponseMock); + ensureMiraklSDKThrowsAnHMCException(); + + assertThatThrownBy(() -> testObj.pushToHyperwallet(hyperwalletUserRequestMock)) + .isInstanceOf(HMCMiraklAPIException.class); + + verify(testObj).reportError("Issue detected when updating seller in Mirakl", + String.format(ERROR_MESSAGE_PREFIX + "Seller token not updated with clientId [%s]%n%s", CLIENT_USER_ID, + MiraklLoggingErrorsUtil.stringify(miraklException))); + } + + @Test + void pushToHyperwallet_shouldLogTheExceptionWhenMiraklSDKFails() { + doNothing().when(testObj).reportError(anyString(), anyString()); + prepareHyperwalletSDKInstance(); + when(hyperwalletMock.createUser(hyperwalletUserRequestMock)).thenReturn(hyperwalletUserResponseMock); + ensureMiraklSDKThrowsAnHMCException(); + + assertThatThrownBy(() -> testObj.pushToHyperwallet(hyperwalletUserRequestMock)) + .isInstanceOf(HMCMiraklAPIException.class); + + verify(testObj).logErrors( + eq(String.format("Error updating token in mirakl with clientUserId [%s]: [{}]", CLIENT_USER_ID)), + eq(miraklException), any(Logger.class)); } @Test @@ -72,4 +146,12 @@ void isApplicable_shouldReturnFalseWhenTokenIsNull() { assertThat(result).isFalse(); } + private void ensureHyperwalletSDKThrowsAnHMCException() { + doThrow(hyperwalletException).when(hyperwalletMock).createUser(hyperwalletUserRequestMock); + } + + private void ensureMiraklSDKThrowsAnHMCException() { + doThrow(miraklException).when(miraklSellersExtractServiceMock).updateUserToken(hyperwalletUserResponseMock); + } + } diff --git a/sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletUpdateSellerServiceStrategyTest.java b/sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletUpdateSellerServiceStrategyTest.java index 143cf8d4..4a8649ba 100644 --- a/sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletUpdateSellerServiceStrategyTest.java +++ b/sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletUpdateSellerServiceStrategyTest.java @@ -1,53 +1,74 @@ package com.paypal.sellers.sellersextract.service.strategies; -import com.hyperwallet.clientsdk.Hyperwallet; import com.hyperwallet.clientsdk.model.HyperwalletUser; -import com.paypal.sellers.sellersextract.model.SellerModel; -import com.paypal.sellers.service.HyperwalletSDKService; +import com.paypal.infrastructure.exceptions.HMCHyperwalletAPIException; +import com.paypal.infrastructure.util.HyperwalletLoggingErrorsUtil; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; -import org.mockito.Mock; +import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; +import org.slf4j.Logger; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) -class HyperWalletUpdateSellerServiceStrategyTest { +class HyperWalletUpdateSellerServiceStrategyTest extends HyperwalletSellerServiceStrategyTest { + @Spy @InjectMocks private HyperWalletUpdateSellerServiceStrategy testObj; - @Mock - private SellerModel sellerModelMock; + @Test + void callHyperwallet_shouldUpdateUserInHyperwallet() { + prepareHyperwalletSDKInstance(); + when(hyperwalletMock.updateUser(hyperwalletUserRequestMock)).thenReturn(hyperwalletUserResponseMock); + + final HyperwalletUser result = testObj.pushToHyperwallet(hyperwalletUserRequestMock); - @Mock - private HyperwalletUser hyperWalletUserRequestMock, hyperWalletUserResponseMock; + verify(hyperwalletMock).updateUser(hyperwalletUserRequestMock); + assertThat(result).isEqualTo(hyperwalletUserResponseMock); + } + + @Test + void callHyperwallet_shouldThrowHMCHyperwalletAPIExceptionWhenHyperwalletSDKFails() { + doNothing().when(testObj).reportError(anyString(), anyString()); + prepareHyperwalletSDKInstance(); + ensureHyperwalletSDKThrowsAnHMCException(); - @Mock - private HyperwalletSDKService hyperwalletSDKServiceMock; + assertThatThrownBy(() -> testObj.pushToHyperwallet(hyperwalletUserRequestMock)) + .isInstanceOf(HMCHyperwalletAPIException.class); + } - @Mock - private Hyperwallet hyperwalletMock; + @Test + void callHyperwallet_shouldSendAnEmailWhenHyperwalletSDKFails() { + doNothing().when(testObj).reportError(anyString(), anyString()); + prepareHyperwalletSDKInstance(); + ensureHyperwalletSDKThrowsAnHMCException(); - private static final String TOKEN = "token"; + assertThatThrownBy(() -> testObj.pushToHyperwallet(hyperwalletUserRequestMock)) + .isInstanceOf(HMCHyperwalletAPIException.class); - private static final String PROGRAM_TOKEN_VALUE = "programTokenValue"; + verify(testObj).reportError("Issue detected when updating seller in Hyperwallet", + String.format(ERROR_MESSAGE_PREFIX + "Seller not updated with clientId [%s]%n%s", CLIENT_USER_ID, + HyperwalletLoggingErrorsUtil.stringify(hyperwalletException))); + } @Test - void createOrUpdateUserOnHyperWalletAndUpdateItsTokenOnMirakl_shouldUpdateUser() { - when(hyperwalletSDKServiceMock.getHyperwalletInstanceByProgramToken(PROGRAM_TOKEN_VALUE)) - .thenReturn(hyperwalletMock); - when(hyperWalletUserRequestMock.getProgramToken()).thenReturn(PROGRAM_TOKEN_VALUE); - when(hyperwalletMock.updateUser(hyperWalletUserRequestMock)).thenReturn(hyperWalletUserResponseMock); + void callHyperwallet_shouldLogTheExceptionWhenHyperwalletSDKFails() { + doNothing().when(testObj).reportError(anyString(), anyString()); + prepareHyperwalletSDKInstance(); + ensureHyperwalletSDKThrowsAnHMCException(); - final HyperwalletUser result = testObj - .createOrUpdateUserOnHyperWalletAndUpdateItsTokenOnMirakl(hyperWalletUserRequestMock); + assertThatThrownBy(() -> testObj.pushToHyperwallet(hyperwalletUserRequestMock)) + .isInstanceOf(HMCHyperwalletAPIException.class); - verify(hyperwalletMock).updateUser(hyperWalletUserRequestMock); - assertThat(result).isEqualTo(hyperWalletUserResponseMock); + verify(testObj).logErrors( + eq(String.format("Error updating seller in hyperwallet with clientUserId [%s]: [{}]", CLIENT_USER_ID)), + eq(hyperwalletException), any(Logger.class)); } @Test @@ -68,4 +89,8 @@ void isApplicable_shouldReturnTrueWhenSellerTokenIsNotEmpty() { assertThat(result).isTrue(); } + private void ensureHyperwalletSDKThrowsAnHMCException() { + doThrow(hyperwalletException).when(hyperwalletMock).updateUser(hyperwalletUserRequestMock); + } + } diff --git a/sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletUserServiceStrategyExecutorSingleTest.java b/sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletUserServiceStrategyExecutorSingleTest.java index cf85354c..8c33f2a5 100644 --- a/sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletUserServiceStrategyExecutorSingleTest.java +++ b/sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/HyperWalletUserServiceStrategyExecutorSingleTest.java @@ -1,6 +1,5 @@ package com.paypal.sellers.sellersextract.service.strategies; -import com.hyperwallet.clientsdk.model.HyperwalletUser; import com.paypal.infrastructure.strategy.Strategy; import com.paypal.sellers.sellersextract.model.SellerModel; import org.junit.jupiter.api.BeforeEach; @@ -21,7 +20,7 @@ class HyperWalletUserServiceStrategyExecutorSingleTest { private HyperWalletUserServiceStrategyExecutor testObj; @Mock - private Strategy strategyMock; + private Strategy strategyMock; @BeforeEach void setUp() { @@ -30,7 +29,7 @@ void setUp() { @Test void getStrategies_shouldReturnConverterStrategyMock() { - final Set> result = testObj.getStrategies(); + final Set> result = testObj.getStrategies(); assertThat(result).containsExactly(strategyMock); } diff --git a/sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/HyperwalletSellerServiceStrategyTest.java b/sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/HyperwalletSellerServiceStrategyTest.java new file mode 100644 index 00000000..a217f16b --- /dev/null +++ b/sellers/src/test/java/com/paypal/sellers/sellersextract/service/strategies/HyperwalletSellerServiceStrategyTest.java @@ -0,0 +1,48 @@ +package com.paypal.sellers.sellersextract.service.strategies; + +import com.hyperwallet.clientsdk.Hyperwallet; +import com.hyperwallet.clientsdk.HyperwalletException; +import com.hyperwallet.clientsdk.model.HyperwalletUser; +import com.mirakl.client.core.exception.MiraklException; +import com.paypal.sellers.sellersextract.model.SellerModel; +import com.paypal.sellers.service.HyperwalletSDKService; +import org.mockito.Mock; + +import static org.mockito.Mockito.when; + +public abstract class HyperwalletSellerServiceStrategyTest { + + protected static final String TOKEN = "token"; + + protected static final String PROGRAM_TOKEN_VALUE = "programTokenValue"; + + protected static final String ERROR_MESSAGE_PREFIX = "There was an error, please check the logs for further " + + "information:\n"; + + public static final String CLIENT_USER_ID = "2000"; + + @SuppressWarnings("java:S5979") + @Mock + protected SellerModel sellerModelMock; + + @Mock + protected HyperwalletUser hyperwalletUserRequestMock, hyperwalletUserResponseMock; + + @Mock + protected HyperwalletSDKService hyperwalletSDKServiceMock; + + @Mock + protected Hyperwallet hyperwalletMock; + + protected HyperwalletException hyperwalletException = new HyperwalletException("Test exception"); + + protected MiraklException miraklException = new MiraklException("Test exception"); + + protected void prepareHyperwalletSDKInstance() { + when(hyperwalletUserRequestMock.getClientUserId()).thenReturn(CLIENT_USER_ID); + when(hyperwalletUserRequestMock.getProgramToken()).thenReturn(PROGRAM_TOKEN_VALUE); + when(hyperwalletSDKServiceMock.getHyperwalletInstanceByProgramToken(PROGRAM_TOKEN_VALUE)) + .thenReturn(hyperwalletMock); + } + +} diff --git a/sellers/src/test/java/com/paypal/sellers/service/AbstractHyperwalletRetryAPIStrategyTest.java b/sellers/src/test/java/com/paypal/sellers/service/AbstractHyperwalletRetryAPIStrategyTest.java deleted file mode 100644 index 76119319..00000000 --- a/sellers/src/test/java/com/paypal/sellers/service/AbstractHyperwalletRetryAPIStrategyTest.java +++ /dev/null @@ -1,62 +0,0 @@ -package com.paypal.sellers.service; - -import com.paypal.sellers.entity.AbstractFailedShopInformation; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; - -import java.util.Collections; -import java.util.List; - -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -class AbstractHyperwalletRetryAPIStrategyTest { - - private static final String SHOP_ID = "2001"; - - @InjectMocks - private MyAbstractHyperwalletRetryAPIStrategy testObj; - - @Mock - private FailedEntityInformationService failedEntityInformationService; - - @Mock - private AbstractFailedShopInformation abstractFailedShopInformationMock; - - @Test - void includeIntoRetryProcess_shouldSaveShopIdWhenTrueIsReceivedAsParameter() { - when(failedEntityInformationService.findByShopId(SHOP_ID)).thenReturn(Collections.emptyList()); - testObj.executeRetryProcess(SHOP_ID, true); - - verify(failedEntityInformationService).save(SHOP_ID); - } - - @Test - void includeIntoRetryProcess_shouldNotSaveShopIdWhenTrueIsReceivedAsParameterAndShopIdExistsInRetryProcess() { - when(failedEntityInformationService.findByShopId(SHOP_ID)) - .thenReturn(List.of(abstractFailedShopInformationMock)); - testObj.executeRetryProcess(SHOP_ID, true); - - verify(failedEntityInformationService, never()).save(SHOP_ID); - } - - @Test - void includeIntoRetryProcess_shouldDeleteShopIdWhenFalseIsReceivedAsParameter() { - testObj.executeRetryProcess(SHOP_ID, false); - - verify(failedEntityInformationService).deleteByShopId(SHOP_ID); - } - - private static class MyAbstractHyperwalletRetryAPIStrategy extends AbstractHyperwalletRetryAPIStrategy { - - protected MyAbstractHyperwalletRetryAPIStrategy( - final FailedEntityInformationService failedEntityInformationService) { - super(failedEntityInformationService); - } - - } - -}