From 4e6099ff5cb343cb1cf369032e1dcd5fbef08f17 Mon Sep 17 00:00:00 2001 From: Zeeshaun Date: Fri, 13 Mar 2026 09:28:55 -0500 Subject: [PATCH] Adding --- LCU.Api.Internal.DataCleanUp/.dockerignore | 17 + LCU.Api.Internal.DataCleanUp/.gitignore | 369 +++++++++ LCU.Api.Internal.DataCleanUp/Dockerfile | 39 + .../LCU.Api.Internal.DataCleanUp.sln | 43 + .../CoreApiWrapperConfiguration.cs | 44 ++ .../Configuration/DataCleanUpConfiguration.cs | 11 + .../Configuration/DataCleanupDefaults.cs | 17 + .../Configuration/EnvironmentView.cs | 35 + .../Configuration/FannieMaeConfiguration.cs | 12 + .../Configuration/FeatureFlags.cs | 5 + .../FileOperationsConfiguration.cs | 9 + .../Configuration/FundingCoreRequests.cs | 9 + .../Configuration/FundsDefaults.cs | 10 + .../Configuration/FundsToAccountDefault.cs | 12 + .../Configuration/IEnvironmentView.cs | 10 + .../IndirectSavingsRequirementsDefaults.cs | 8 + .../Configuration/NcoaConfiguration.cs | 15 + .../NotificationsApiConfiguration.cs | 6 + .../Configuration/SavingsDefaults.cs | 16 + .../SavingsMissingRequirementsDefaults.cs | 7 + .../Consumers/DataCleanUpConsumer.cs | 34 + .../Controllers/QueueDataCleanUpController.cs | 392 ++++++++++ .../Controllers/StatusController.cs | 33 + .../DataAccess/CoreApiWrapperDao.cs | 365 +++++++++ .../DataAccess/FileOperationsDao.cs | 45 ++ .../DataAccess/ICoreApiWrapperDao.cs | 62 ++ .../DataAccess/IFileOperationsDao.cs | 10 + .../DataAccess/INotificationsDao.cs | 13 + .../DataAccess/NotificationsDao.cs | 35 + .../LCU.Api.Internal.DataCleanUp.csproj | 50 ++ .../Models/AccountCreditReportType.cs | 17 + .../Models/AccountNickname.cs | 21 + .../Models/BatchAddFundsToVipAccounts.cs | 49 ++ .../BatchAddFundsToVipAccountsSummary.cs | 73 ++ .../Models/CheckHoldsUserFieldValue.cs | 119 +++ .../Models/FannieMaeMortgage.cs | 35 + .../Models/FannieMaeTotalBatchSummary.cs | 20 + .../Models/FannieMaeUpdateResult.cs | 24 + .../Models/IndirectSavingsAccount.cs | 13 + .../Models/IndirectSavingsAccountResult.cs | 7 + .../Models/IndirectSavingsAccountsSummary.cs | 34 + .../Models/MissingBatchSavings.cs | 58 ++ .../Models/MissingBatchSavingsSummary.cs | 67 ++ .../Models/ParserModels/NcoaRecord.cs | 76 ++ .../Models/PmiCancel.cs | 26 + .../Models/UpdatePmiCancelSummary.cs | 37 + .../LCU.Api.Internal.DataCleanUp/Program.cs | 28 + .../Properties/launchSettings.json | 52 ++ ...ddFundsToIndirectSavingsAccountsService.cs | 189 +++++ .../AddFundsToVipSavingsAccountsService.cs | 70 ++ ...atchAddFundsToVipSavingsAccountsService.cs | 146 ++++ .../CloseCustodialVruAgreementsService.cs | 92 +++ .../Services/CoreApiWrapperService.cs | 712 +++++++++++++++++ .../Services/DataCleanUpService.cs | 109 +++ .../DeactivateCustodialEAgreementsService.cs | 134 ++++ .../Emailers/INotificationsApiService.cs | 6 + .../Emailers/NotificationsApiService.cs | 48 ++ .../Services/FileOperationsService.cs | 87 +++ .../HyphenatedUserIdCleanUpService.cs | 95 +++ ...ddFundsToIndirectSavingsAccountsService.cs | 6 + .../IAddFundsToVipSavingsAccountsService.cs | 7 + ...atchAddFundsToVipSavingsAccountsService.cs | 6 + .../ICloseCustodialVruAgreementsService.cs | 7 + .../Services/ICoreApiWrapperService.cs | 63 ++ .../Services/IDataCleanUpService.cs | 7 + .../IDeactivateCustodialEAgreementsService.cs | 13 + .../Services/IFileOperationsService.cs | 13 + .../IHyphenatedUserIdCleanUpService.cs | 11 + ...actionExternalDescriptionWithSsnService.cs | 8 + .../Services/IQueueDataCleanUpService.cs | 23 + .../IUpdateAccountCreditReportTypeService.cs | 7 + .../IUpdateAccountGroupForAnalysisService.cs | 7 + .../IUpdateAccountLoanToValueService.cs | 7 + .../Services/IUpdateAccountNicknameService.cs | 11 + .../IUpdateAccountPmiCancelService.cs | 9 + ...eAdminBranchCodesByAccountNumberService.cs | 7 + .../IUpdateFannieMaeMortgageService.cs | 8 + .../IUpdateMissingBatchSavingsService.cs | 7 + .../Services/IUpdateNcoaProcessService.cs | 8 + .../IUpdatePersonForAtmHoldsService.cs | 10 + ...actionExternalDescriptionWithSsnService.cs | 106 +++ .../Services/QueueDataCleanUpService.cs | 281 +++++++ .../UpdateAccountCreditReportTypeService.cs | 77 ++ .../UpdateAccountGroupForAnalysisService.cs | 66 ++ .../UpdateAccountLoanToValueService.cs | 70 ++ .../Services/UpdateAccountNicknameService.cs | 79 ++ .../Services/UpdateAccountPmiCancelService.cs | 157 ++++ ...eAdminBranchCodesByAccountNumberService.cs | 66 ++ .../UpdateFannieMaeMortgageService.cs | 285 +++++++ .../UpdateMissingBatchSavingsService.cs | 243 ++++++ .../Services/UpdateNcoaProcessService.cs | 430 ++++++++++ .../UpdatePersonForAtmHoldsService.cs | 125 +++ .../Validation/INcoaValidationService.cs | 16 + .../Validation/NcoaValidationService.cs | 70 ++ .../LCU.Api.Internal.DataCleanUp/Startup.cs | 185 +++++ .../Templates/ErrorMonitoringTemplate.html | 55 ++ .../Templates/ErrorRowTemplate.html | 3 + .../appsettings.json | 187 +++++ .../QueryableExcludeMinorAccountType.cs | 19 + .../LCU.Api.Internal.DataCleanUpLib.csproj | 18 + .../Persistence/AppDbContext.cs | 18 + .../Repositories/BaseRepository.cs | 14 + .../Repositories/ILtvDataCleanUpRepository.cs | 11 + .../Repositories/LtvDataCleanUpRepository.cs | 19 + .../DataAccess/CoreApiWrapperDaoTest.cs | 430 ++++++++++ .../DataAccess/FileOperationsDaoTest.cs | 112 +++ .../LCU.Api.Internal.DataCleanUpTest.csproj | 46 ++ .../Repositories/DbContextFromJson.cs | 70 ++ .../UpdateAccountLoanToValueRepositoryTest.cs | 41 + .../Repositories/loanToValue_repo.json | 14 + ...ndsToIndirectSavingsAccountsServiceTest.cs | 272 +++++++ ...AddFundsToVipSavingsAccountsServiceTest.cs | 157 ++++ ...AddFundsToVipSavingsAccountsServiceTest.cs | 126 +++ .../CloseCustodialVruAgreementsServiceTest.cs | 157 ++++ ...activateCustodialEAgreementsServiceTest.cs | 735 ++++++++++++++++++ .../HyphenatedUserIdCleanUpServiceTest.cs | 591 ++++++++++++++ ...onExternalDescriptionWithSsnServiceTest.cs | 250 ++++++ ...pdateAccountCreditReportTypeServiceTest.cs | 99 +++ ...pdateAccountGroupForAnalysisServiceTest.cs | 83 ++ .../UpdateAccountLoanToValueServiceTest.cs | 135 ++++ .../UpdateAccountPmiCancelServiceTest.cs | 90 +++ .../UpdateFannieMaeMortgageServiceTest.cs | 337 ++++++++ .../UpdateMissingSavingsAccountServiceTest.cs | 454 +++++++++++ .../Services/UpdateNcoaProcessServiceTest.cs | 586 ++++++++++++++ .../UpdatePersonForAtmHoldsServiceTest.cs | 539 +++++++++++++ .../Validation/NcoaValidationServiceTest.cs | 347 +++++++++ .../Utilities/HttpUtilitiesTest.cs | 156 ++++ .../Entities/Ltv_DataCleanUp.cs | 14 + .../Enum/CleanUpTypes.cs | 23 + ...U.Library.Internal.DataCleanUpModel.csproj | 48 ++ .../Models/CreditReportTypeUpdateRequest.cs | 9 + .../Models/DataCleanUpRequest.cs | 11 + .../Models/DataCleanUpResult.cs | 20 + .../Models/FannieMaeMortgageUpdateRequest.cs | 35 + .../Models/IndirectFundingRequest.cs | 14 + .../Models/NcoaUpdateRequest.cs | 40 + .../Models/UpdatePersonForCheckHoldRequest.cs | 23 + LCU.Api.Internal.DataCleanUp/README.md | 2 + .../install_dependencies.ps1 | 1 + .../_kube_local_testing/kind.cluster.config | 7 + .../_kube_local_testing/setup_and_deploy.ps1 | 15 + .../_kube_local_testing/teardown.ps1 | 1 + .../azdo_pipelines/azure-k8s-pipeline.yaml | 55 ++ .../azure-pipelines-feature-branches.yaml | 10 + .../azdo_pipelines/azure-pipelines-prd.yaml | 9 + .../azdo_pipelines/azure-pipelines-qa.yaml | 9 + .../azdo_pipelines/azure-pipelines-uat.yaml | 9 + .../config-files/prd-pvars.yaml | 9 + .../azdo_pipelines/config-files/qa-pvars.yaml | 9 + .../config-files/uat-pvars.yaml | 9 + LCU.Api.Internal.DataCleanUp/cleanbuildrun.sh | 16 + .../kustomize/base/Deployment.yaml | 92 +++ .../kustomize/base/Service.yaml | 11 + .../kustomize/base/kustomization.yaml | 5 + .../base/secrets-provider-class.yaml | 45 ++ .../kustomize/base/virtual-service.yaml | 18 + .../overlays/local/common/kustomization.yaml | 8 + .../common/set_appsettings_deployment.yaml | 12 + .../common/set_secrets_provider_class.yaml | 9 + .../overlays/local/kustomization.yaml | 2 + .../overlays/local/normal/configmap.yaml | 38 + .../overlays/local/normal/kustomization.yaml | 5 + .../local/normal/set_virtual_service.yaml | 8 + .../overlays/prd/common/kustomization.yaml | 8 + .../common/set_appsettings_deployment.yaml | 12 + .../common/set_secrets_provider_class.yaml | 9 + .../kustomize/overlays/prd/kustomization.yaml | 2 + .../overlays/prd/normal/configmap.yaml | 42 + .../overlays/prd/normal/kustomization.yaml | 5 + .../prd/normal/set_virtual_service.yaml | 8 + .../overlays/qa/common/kustomization.yaml | 8 + .../qa/common/set_appsettings_deployment.yaml | 12 + .../qa/common/set_secrets_provider_class.yaml | 9 + .../kustomize/overlays/qa/kustomization.yaml | 2 + .../overlays/qa/normal/configmap.yaml | 41 + .../overlays/qa/normal/kustomization.yaml | 5 + .../qa/normal/set_virtual_service.yaml | 8 + .../overlays/uat/common/kustomization.yaml | 8 + .../common/set_appsettings_deployment.yaml | 12 + .../common/set_secrets_provider_class.yaml | 9 + .../kustomize/overlays/uat/kustomization.yaml | 2 + .../overlays/uat/normal/configmap.yaml | 41 + .../overlays/uat/normal/kustomization.yaml | 5 + .../uat/normal/set_virtual_service.yaml | 8 + 184 files changed, 13756 insertions(+) create mode 100644 LCU.Api.Internal.DataCleanUp/.dockerignore create mode 100644 LCU.Api.Internal.DataCleanUp/.gitignore create mode 100644 LCU.Api.Internal.DataCleanUp/Dockerfile create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp.sln create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/CoreApiWrapperConfiguration.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/DataCleanUpConfiguration.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/DataCleanupDefaults.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/EnvironmentView.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FannieMaeConfiguration.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FeatureFlags.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FileOperationsConfiguration.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FundingCoreRequests.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FundsDefaults.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FundsToAccountDefault.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/IEnvironmentView.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/IndirectSavingsRequirementsDefaults.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/NcoaConfiguration.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/NotificationsApiConfiguration.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/SavingsDefaults.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/SavingsMissingRequirementsDefaults.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Consumers/DataCleanUpConsumer.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Controllers/QueueDataCleanUpController.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Controllers/StatusController.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/CoreApiWrapperDao.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/FileOperationsDao.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/ICoreApiWrapperDao.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/IFileOperationsDao.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/INotificationsDao.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/NotificationsDao.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp.csproj create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/AccountCreditReportType.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/AccountNickname.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/BatchAddFundsToVipAccounts.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/BatchAddFundsToVipAccountsSummary.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/CheckHoldsUserFieldValue.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/FannieMaeMortgage.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/FannieMaeTotalBatchSummary.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/FannieMaeUpdateResult.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/IndirectSavingsAccount.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/IndirectSavingsAccountResult.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/IndirectSavingsAccountsSummary.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/MissingBatchSavings.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/MissingBatchSavingsSummary.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/ParserModels/NcoaRecord.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/PmiCancel.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/UpdatePmiCancelSummary.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Program.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Properties/launchSettings.json create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/AddFundsToIndirectSavingsAccountsService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/AddFundsToVipSavingsAccountsService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/BatchAddFundsToVipSavingsAccountsService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/CloseCustodialVruAgreementsService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/CoreApiWrapperService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/DataCleanUpService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/DeactivateCustodialEAgreementsService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/Emailers/INotificationsApiService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/Emailers/NotificationsApiService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/FileOperationsService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/HyphenatedUserIdCleanUpService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IAddFundsToIndirectSavingsAccountsService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IAddFundsToVipSavingsAccountsService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IBatchAddFundsToVipSavingsAccountsService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/ICloseCustodialVruAgreementsService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/ICoreApiWrapperService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IDataCleanUpService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IDeactivateCustodialEAgreementsService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IFileOperationsService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IHyphenatedUserIdCleanUpService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IMaskTransactionExternalDescriptionWithSsnService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IQueueDataCleanUpService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAccountCreditReportTypeService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAccountGroupForAnalysisService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAccountLoanToValueService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAccountNicknameService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAccountPmiCancelService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAdminBranchCodesByAccountNumberService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateFannieMaeMortgageService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateMissingBatchSavingsService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateNcoaProcessService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdatePersonForAtmHoldsService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/MaskTransactionExternalDescriptionWithSsnService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/QueueDataCleanUpService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAccountCreditReportTypeService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAccountGroupForAnalysisService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAccountLoanToValueService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAccountNicknameService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAccountPmiCancelService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAdminBranchCodesByAccountNumberService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateFannieMaeMortgageService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateMissingBatchSavingsService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateNcoaProcessService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdatePersonForAtmHoldsService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/Validation/INcoaValidationService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/Validation/NcoaValidationService.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Startup.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Templates/ErrorMonitoringTemplate.html create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Templates/ErrorRowTemplate.html create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/appsettings.json create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/Extensions/QueryableExcludeMinorAccountType.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/LCU.Api.Internal.DataCleanUpLib.csproj create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/Persistence/AppDbContext.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/Repositories/BaseRepository.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/Repositories/ILtvDataCleanUpRepository.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/Repositories/LtvDataCleanUpRepository.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/DataAccess/CoreApiWrapperDaoTest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/DataAccess/FileOperationsDaoTest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/LCU.Api.Internal.DataCleanUpTest.csproj create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Repositories/DbContextFromJson.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Repositories/UpdateAccountLoanToValueRepositoryTest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Repositories/loanToValue_repo.json create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/AddFundsToIndirectSavingsAccountsServiceTest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/AddFundsToVipSavingsAccountsServiceTest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/BatchAddFundsToVipSavingsAccountsServiceTest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/CloseCustodialVruAgreementsServiceTest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/DeactivateCustodialEAgreementsServiceTest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/HyphenatedUserIdCleanUpServiceTest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/MaskTransactionExternalDescriptionWithSsnServiceTest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateAccountCreditReportTypeServiceTest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateAccountGroupForAnalysisServiceTest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateAccountLoanToValueServiceTest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateAccountPmiCancelServiceTest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateFannieMaeMortgageServiceTest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateMissingSavingsAccountServiceTest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateNcoaProcessServiceTest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdatePersonForAtmHoldsServiceTest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/Validation/NcoaValidationServiceTest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Utilities/HttpUtilitiesTest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Entities/Ltv_DataCleanUp.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Enum/CleanUpTypes.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/LCU.Library.Internal.DataCleanUpModel.csproj create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/CreditReportTypeUpdateRequest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/DataCleanUpRequest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/DataCleanUpResult.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/FannieMaeMortgageUpdateRequest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/IndirectFundingRequest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/NcoaUpdateRequest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/UpdatePersonForCheckHoldRequest.cs create mode 100644 LCU.Api.Internal.DataCleanUp/README.md create mode 100644 LCU.Api.Internal.DataCleanUp/_kube_local_testing/install_dependencies.ps1 create mode 100644 LCU.Api.Internal.DataCleanUp/_kube_local_testing/kind.cluster.config create mode 100644 LCU.Api.Internal.DataCleanUp/_kube_local_testing/setup_and_deploy.ps1 create mode 100644 LCU.Api.Internal.DataCleanUp/_kube_local_testing/teardown.ps1 create mode 100644 LCU.Api.Internal.DataCleanUp/azdo_pipelines/azure-k8s-pipeline.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/azdo_pipelines/azure-pipelines-feature-branches.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/azdo_pipelines/azure-pipelines-prd.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/azdo_pipelines/azure-pipelines-qa.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/azdo_pipelines/azure-pipelines-uat.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/azdo_pipelines/config-files/prd-pvars.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/azdo_pipelines/config-files/qa-pvars.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/azdo_pipelines/config-files/uat-pvars.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/cleanbuildrun.sh create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/base/Deployment.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/base/Service.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/base/kustomization.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/base/secrets-provider-class.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/base/virtual-service.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/common/kustomization.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/common/set_appsettings_deployment.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/common/set_secrets_provider_class.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/kustomization.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/normal/configmap.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/normal/kustomization.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/normal/set_virtual_service.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/common/kustomization.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/common/set_appsettings_deployment.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/common/set_secrets_provider_class.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/kustomization.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/normal/configmap.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/normal/kustomization.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/normal/set_virtual_service.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/common/kustomization.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/common/set_appsettings_deployment.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/common/set_secrets_provider_class.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/kustomization.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/normal/configmap.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/normal/kustomization.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/normal/set_virtual_service.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/common/kustomization.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/common/set_appsettings_deployment.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/common/set_secrets_provider_class.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/kustomization.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/normal/configmap.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/normal/kustomization.yaml create mode 100644 LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/normal/set_virtual_service.yaml diff --git a/LCU.Api.Internal.DataCleanUp/.dockerignore b/LCU.Api.Internal.DataCleanUp/.dockerignore new file mode 100644 index 0000000..8b63706 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/.dockerignore @@ -0,0 +1,17 @@ +**/*.bat +**/*.log +**/*.md +**/*.yml +**/.dockerignore +**/.editorconfig +**/.git +**/.gitattributes +**/.gitignore +**/.vs +**/.vscode +**/bin +**/dist +**/dockerfile +**/node_modules +**/obj +**/package-lock.json \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/.gitignore b/LCU.Api.Internal.DataCleanUp/.gitignore new file mode 100644 index 0000000..83862b9 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/.gitignore @@ -0,0 +1,369 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + +# CodeRush +.cr/ + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd diff --git a/LCU.Api.Internal.DataCleanUp/Dockerfile b/LCU.Api.Internal.DataCleanUp/Dockerfile new file mode 100644 index 0000000..3b56da1 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/Dockerfile @@ -0,0 +1,39 @@ +# .NET Core SDK +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS aspnetcore-build + +# Copy Projects +COPY LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp.csproj ./source/LCU.Api.Internal.DataCleanUp/ +COPY LCU.Library.Internal.DataCleanUpModel/LCU.Library.Internal.DataCleanUpModel.csproj ./source/LCU.Library.Internal.DataCleanUpModel/ + +# Install Credential Provider and set env variables to enable Nuget restore with auth +ARG PAT=bh2lq3jibktw67b2wdbqyfln7cd3je6lk52kijntpj43v6kimpgq +RUN curl -L https://raw.githubusercontent.com/Microsoft/artifacts-credprovider/master/helpers/installcredprovider.sh | sh +#RUN wget -qO- https://raw.githubusercontent.com/Microsoft/artifacts-credprovider/master/helpers/installcredprovider.sh | bash +ENV NUGET_CREDENTIALPROVIDER_SESSIONTOKENCACHE_ENABLED true +ENV VSS_NUGET_EXTERNAL_FEED_ENDPOINTS "{\"endpointCredentials\": [{\"endpoint\":\"https://landmarkcu.pkgs.visualstudio.com/_packaging/LCU-Internal/nuget/v3/index.json\", \"password\":\"${PAT}\"}]}" + +# .NET Core Restore, use auth'd feed +RUN dotnet restore -s "https://landmarkcu.pkgs.visualstudio.com/_packaging/LCU-Internal/nuget/v3/index.json" -s "https://api.nuget.org/v3/index.json" ./source/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp.csproj + +# Copy All Files +COPY . ./source/ + +FROM aspnetcore-build AS test +LABEL test=true +COPY LCU.Api.Internal.DataCleanUpTest/LCU.Api.Internal.DataCleanUpTest.csproj ./source/LCU.Api.Internal.DataCleanUpTest/ +RUN dotnet restore ./source/LCU.Api.Internal.DataCleanUpTest/LCU.Api.Internal.DataCleanUpTest.csproj +RUN dotnet test -c Release --results-directory /testresults --logger "trx;LogFileName=test_results.trx" ./source/LCU.Api.Internal.DataCleanUpTest/LCU.Api.Internal.DataCleanUpTest.csproj + +# .NET Core Publish +FROM aspnetcore-build as publish +RUN dotnet publish ./source/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp.csproj -c Release -o /dist + +# ASP.NET Core +FROM mcr.microsoft.com/dotnet/aspnet:8.0 +#RUN apk add --no-cache icu-libs +ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false +ENV ASPNETCORE_ENVIRONMENT=Development + +WORKDIR /app +COPY --from=publish /dist . +ENTRYPOINT ["dotnet", "LCU.Api.Internal.DataCleanUp.dll"] diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp.sln b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp.sln new file mode 100644 index 0000000..332c461 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.31903.59 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCU.Api.Internal.DataCleanUp", "LCU.Api.Internal.DataCleanUp\LCU.Api.Internal.DataCleanUp.csproj", "{F99AB4C0-B967-4368-A313-9751428D403E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCU.Library.Internal.DataCleanUpModel", "LCU.Library.Internal.DataCleanUpModel\LCU.Library.Internal.DataCleanUpModel.csproj", "{264F8A9D-6544-4D36-ACE5-04B0DF457DF6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCU.Api.Internal.DataCleanUpTest", "LCU.Api.Internal.DataCleanUpTest\LCU.Api.Internal.DataCleanUpTest.csproj", "{BAC900C2-55C7-4DA5-949E-2A5923C9CF37}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LCU.Api.Internal.DataCleanUpLib", "LCU.Api.Internal.DataCleanUpLib\LCU.Api.Internal.DataCleanUpLib.csproj", "{2CA97F85-1B3D-45C7-9FD8-A3613220F566}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F99AB4C0-B967-4368-A313-9751428D403E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F99AB4C0-B967-4368-A313-9751428D403E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F99AB4C0-B967-4368-A313-9751428D403E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F99AB4C0-B967-4368-A313-9751428D403E}.Release|Any CPU.Build.0 = Release|Any CPU + {264F8A9D-6544-4D36-ACE5-04B0DF457DF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {264F8A9D-6544-4D36-ACE5-04B0DF457DF6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {264F8A9D-6544-4D36-ACE5-04B0DF457DF6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {264F8A9D-6544-4D36-ACE5-04B0DF457DF6}.Release|Any CPU.Build.0 = Release|Any CPU + {BAC900C2-55C7-4DA5-949E-2A5923C9CF37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BAC900C2-55C7-4DA5-949E-2A5923C9CF37}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BAC900C2-55C7-4DA5-949E-2A5923C9CF37}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BAC900C2-55C7-4DA5-949E-2A5923C9CF37}.Release|Any CPU.Build.0 = Release|Any CPU + {2CA97F85-1B3D-45C7-9FD8-A3613220F566}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2CA97F85-1B3D-45C7-9FD8-A3613220F566}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2CA97F85-1B3D-45C7-9FD8-A3613220F566}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2CA97F85-1B3D-45C7-9FD8-A3613220F566}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {8BCD4B79-66E0-4EEE-880A-D70808A224D1} + EndGlobalSection +EndGlobal diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/CoreApiWrapperConfiguration.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/CoreApiWrapperConfiguration.cs new file mode 100644 index 0000000..4ea6d87 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/CoreApiWrapperConfiguration.cs @@ -0,0 +1,44 @@ +namespace LCU.Api.Internal.DataCleanUp.Configuration; + +public class CoreApiWrapperConfiguration +{ + public int CoreApiTimeout { get; set; } + public int RetryGetAccessChannelPersonIncludes { get; set; } + public string CoreApiWrapperUrl { get; set; } + public string GetAgreePersonsWithHyphenatedUserId { get; set; } + public string GetActiveCustodialAgreePersonNumbers { get; set; } + public string GetActiveCustodialVruCardAgreementAgreePersons { get; set; } + public string GetVipSavingsToFund { get; set; } + public string GetAdminBranchCodeChangeAccountNumbers { get; set; } + public string GetAccountsForGroupAnalysis { get; set; } + public string GetPersonsForAtmCheckHolds { get; set; } + public string AccessChannelPersons { get; set; } + public string AccessType { get; set; } + public string AccesschannelPersonWithIncludes { get; set; } + public string GetAccountsByMajorMinorBranchAndStatus { get; set; } + public string PutPersonAgreementDetailTypes { get; set; } + public string GetTransactionExternalDescriptionsWithSsn { get; set; } + public string PutTransactionExternalDescription { get; set; } + public string PostFundsToAccount { get; set; } + public string PutAccountBranchCode { get; set; } + public string PutAccountLoanToValue { get; set; } + public string PutAccountAnalysisGroup { get; set; } + public string PutPersonUserFieldForAtmCheckHolds { get; set; } + public string PostPersonUserFieldForAtmCheckHolds { get; set; } + public string PostPersonAccount { get; set; } + public string PostOrganizationAccount { get; set; } + public string PutOrganizationMaintenanceRequest { get; set; } + public string PutAccountNickNameUpdateRequest { get; set; } + public string GetAgreementByUserId { get; set; } + public string GetPersonPostalAddressByPersonNumber { get; set; } + public string PutAddrLineByPersonNumber { get; set; } + public string PutAccountCreditReportType { get; set; } + public string GetPropertyNumberByAccountNumber { get; set; } + public string GetAccountByAccountNumber { get; set; } + public string PutPersonUserField { get; set; } + public string PropertyUserField { get; set; } + public string PostPropertyUserField { get; set; } + public string PutPropertyUserField { get; set; } + public string PersonUserField { get; set; } + public string AccountUserField { get; set; } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/DataCleanUpConfiguration.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/DataCleanUpConfiguration.cs new file mode 100644 index 0000000..9ea5a62 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/DataCleanUpConfiguration.cs @@ -0,0 +1,11 @@ +namespace LCU.Api.Internal.DataCleanUp.Configuration; + +public class DataCleanUpConfiguration +{ + public string AppName { get; set; } + public string SeqUrl { get; set; } + public string TimeZone { get; set; } + public string SeqApiKey { get; set; } + public string[] CorsAllowedOrigins { get; set; } + public FeatureFlags FeatureFlags { get; set; } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/DataCleanupDefaults.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/DataCleanupDefaults.cs new file mode 100644 index 0000000..e38611c --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/DataCleanupDefaults.cs @@ -0,0 +1,17 @@ +namespace LCU.Api.Internal.DataCleanUp.Configuration; + +public class DataCleanupDefaults +{ + public string DigitalBankingBranchCode { get; set; } + public string MemberCheckHoldsUserFieldCode { get; set; } + public int MemberCheckHoldsDays { get; set; } + public List LtvExcludedMinorAccountTypes { get; set; } + public string BatchAddFunds { get; set; } + public string BatchAddFundsSummarySourcePath { get; set; } + public string BatchSavingsSourcePath { get; set; } + public string BatchSavingsSummarySourcePath { get; set; } + public string AccountNicknameSourcePath { get; set; } + public string PmiCancelSourcePath { get; set; } + public string PmiCancelSummaryPath { get; set; } +} + diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/EnvironmentView.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/EnvironmentView.cs new file mode 100644 index 0000000..a533ab1 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/EnvironmentView.cs @@ -0,0 +1,35 @@ +using System.Reflection; + +namespace LCU.Api.Internal.DataCleanUp.Configuration; + +public class EnvironmentView : IEnvironmentView +{ + public string Application => _env.ApplicationName; + public DateTime CurrentDate => DateTime.Now; + public string BuildVersion => AssembleBuildVersion(); + public DateTime BuildDate => AssemblyBuildDate(); + public string Environment => _env.EnvironmentName; + private readonly IWebHostEnvironment _env; + + public EnvironmentView(IWebHostEnvironment env) + { + _env = env; + } + + public static DateTime AssemblyBuildDate() + { + //https://stackoverflow.com/a/804310/266594 + Assembly assembly = Assembly.GetExecutingAssembly(); + FileInfo fileInfo = new FileInfo(assembly.Location); + DateTime lastModified = fileInfo.LastWriteTime; + + return lastModified; + } + + public static string AssembleBuildVersion() + { + var version = Assembly.GetExecutingAssembly().GetName().Version; + return version == null ? "-.-.-" : version.ToString(); ; + } + +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FannieMaeConfiguration.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FannieMaeConfiguration.cs new file mode 100644 index 0000000..3a1517a --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FannieMaeConfiguration.cs @@ -0,0 +1,12 @@ +namespace LCU.Api.Internal.DataCleanUp.Configuration; + +public class FannieMaeConfiguration +{ + public string PersonNumberLabel { get; set; } + public string ErrorFileDefaultName { get; set; } + public string SummaryEmailSubject { get; set; } + public string FileDateFormat { get; set; } + public string DnaDateFormat { get; set; } + public string PoolDateUserFieldId { get; set; } + public string PoolNbrUserFieldId { get; set; } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FeatureFlags.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FeatureFlags.cs new file mode 100644 index 0000000..f183b46 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FeatureFlags.cs @@ -0,0 +1,5 @@ +namespace LCU.Api.Internal.DataCleanUp.Configuration; +public class FeatureFlags +{ + public bool RunDataCleanUpConsumer { get; set; } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FileOperationsConfiguration.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FileOperationsConfiguration.cs new file mode 100644 index 0000000..e645361 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FileOperationsConfiguration.cs @@ -0,0 +1,9 @@ +namespace LCU.Api.Internal.DataCleanUp.Configuration; + +public class FileOperationsConfiguration +{ + public string FileOperationsUrl { get; set; } + public string GetFile { get; set; } + public string WriteFile { get; set; } + public string BuildDynamicFileList { get; set; } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FundingCoreRequests.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FundingCoreRequests.cs new file mode 100644 index 0000000..9a4898b --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FundingCoreRequests.cs @@ -0,0 +1,9 @@ +namespace LCU.Api.Internal.DataCleanUp.Configuration; + +public class FundingCoreRequests +{ + public List MajorAccountTypes { get; set; } + public List MinorAccountTypes { get; set; } + public List AccountStatusTypes { get; set; } + public List BranchCodeTypes { get; set; } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FundsDefaults.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FundsDefaults.cs new file mode 100644 index 0000000..e813c14 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FundsDefaults.cs @@ -0,0 +1,10 @@ +namespace LCU.Api.Internal.DataCleanUp.Configuration; + +public class FundsDefaults +{ + public string ClearingCategoryCode { get; set; } + public double FundAmount { get; set; } + public string FundTypeCode { get; set; } + public string FundTypeDetailCode { get; set; } +} + diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FundsToAccountDefault.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FundsToAccountDefault.cs new file mode 100644 index 0000000..753ee25 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/FundsToAccountDefault.cs @@ -0,0 +1,12 @@ +namespace LCU.Api.Internal.DataCleanUp.Configuration; + +public class FundsToAccountDefaults +{ + public string Description { get; set; } + public double TransactionAmount { get; set; } + public string TransactionTypeCode { get; set; } + public string GLAccountNumber { get; set; } + public string TransactionTypeCodeGL { get; set; } + public string TransactionTypeCodeDeposit { get; set; } + public FundsDefaults FundsDefaults { get; set; } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/IEnvironmentView.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/IEnvironmentView.cs new file mode 100644 index 0000000..1503063 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/IEnvironmentView.cs @@ -0,0 +1,10 @@ +namespace LCU.Api.Internal.DataCleanUp.Configuration; + +public interface IEnvironmentView +{ + string Application { get; } + DateTime CurrentDate { get; } + string BuildVersion { get; } + DateTime BuildDate { get; } + string Environment { get; } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/IndirectSavingsRequirementsDefaults.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/IndirectSavingsRequirementsDefaults.cs new file mode 100644 index 0000000..be11e9d --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/IndirectSavingsRequirementsDefaults.cs @@ -0,0 +1,8 @@ +using LCU.Library.Internal.DataCleanUpModel.Models; + +namespace LCU.Api.Internal.DataCleanUp.Configuration; + +public class IndirectSavingsRequirementsDefaults : FundsToAccountDefaults +{ + public FundingCoreRequests FundingCoreRequests { get; set; } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/NcoaConfiguration.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/NcoaConfiguration.cs new file mode 100644 index 0000000..45c5017 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/NcoaConfiguration.cs @@ -0,0 +1,15 @@ +namespace LCU.Api.Internal.DataCleanUp.Configuration; + +public class NcoaConfiguration +{ + public string PrimaryAddressLabel { get; set; } + public string StreetTypeLabel { get; set; } + public string UsaLabel { get; set; } + public string UrlBase { get; set; } + public string PersonNumberLabel { get; set; } + public string PoBoxLabel { get; set; } + public string PoBoxAddressTypeLabel { get; set; } + public string ErrorFileDefaultName { get; set; } + public string SummaryEmailSubject { get; set; } + public char ExclusionListDelimiter { get; set; } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/NotificationsApiConfiguration.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/NotificationsApiConfiguration.cs new file mode 100644 index 0000000..66a4ead --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/NotificationsApiConfiguration.cs @@ -0,0 +1,6 @@ +namespace LCU.Api.Internal.DataCleanUp.Configuration; + +public class NotificationsApiConfiguration +{ + public string EmailEndpoint { get; set; } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/SavingsDefaults.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/SavingsDefaults.cs new file mode 100644 index 0000000..ee42b66 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/SavingsDefaults.cs @@ -0,0 +1,16 @@ +namespace LCU.Api.Internal.DataCleanUp.Configuration; + +public class SavingsDefaults +{ + public string BatchAccountDescription { get; set; } + public string AccountDescription { get; set; } + public string BankOrganizationNumber { get; set; } + public string CurrentMinorAccountTypeCode { get; set; } + public string DeliveryMethodCode { get; set; } + public string MajorAccountTypeCode { get; set; } + public string OwnershipCode { get; set; } + public bool IsTaxReportedForSigner { get; set; } + public bool IsTaxReportedForOwner { get; set; } + public bool IsValid { get; set; } + public string CurrentAccountStatusCode { get; set; } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/SavingsMissingRequirementsDefaults.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/SavingsMissingRequirementsDefaults.cs new file mode 100644 index 0000000..895dfad --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Configuration/SavingsMissingRequirementsDefaults.cs @@ -0,0 +1,7 @@ +namespace LCU.Api.Internal.DataCleanUp.Configuration; + +public class SavingsMissingRequirementsDefaults +{ + public SavingsDefaults SavingDefaults { get; set; } + public FundsToAccountDefaults FundsToAccountDefaults { get; set; } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Consumers/DataCleanUpConsumer.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Consumers/DataCleanUpConsumer.cs new file mode 100644 index 0000000..4d04a9b --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Consumers/DataCleanUpConsumer.cs @@ -0,0 +1,34 @@ +using Serilog; +using MassTransit; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Api.Internal.DataCleanUp.Services; +using LCU.Library.Internal.Exceptions; +namespace LCU.Api.Internal.DataCleanUp.Consumers; + +public class DataCleanUpConsumer : IConsumer +{ + private readonly IServiceScopeFactory _scopeFactory; + + public DataCleanUpConsumer(IServiceScopeFactory scopeFactory) + { + _scopeFactory = scopeFactory; + } + + public async Task Consume(ConsumeContext context) + { + try + { + using var scope = _scopeFactory.CreateScope(); + await Task.Run(() => scope.ServiceProvider.GetRequiredService().DetermineCleanUp(context.Message)); + } + catch (ServiceException) + { + throw; + } + catch (Exception exception) + { + Log.Fatal(exception, $"Unexpected Failure"); + throw; + } + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Controllers/QueueDataCleanUpController.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Controllers/QueueDataCleanUpController.cs new file mode 100644 index 0000000..7579e9e --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Controllers/QueueDataCleanUpController.cs @@ -0,0 +1,392 @@ +using Microsoft.AspNetCore.Mvc; +using Serilog; +using LCU.Api.Internal.DataCleanUp.Services; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Library.Internal.DataCleanUpModel.Enum; +using LCU.Library.Internal.ApiResponse.Models; + +namespace LCU.Api.Internal.DataCleanUp.Controllers; + +[ApiController] +[Route("[controller]")] +public class QueueDataCleanUpController : ControllerBase +{ + private readonly IQueueDataCleanUpService _queueDataCleanUpService; + + public QueueDataCleanUpController(IQueueDataCleanUpService queueDataCleanUpService) + { + _queueDataCleanUpService = queueDataCleanUpService; + } + + [HttpPost("QueueDataCleanUp")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public IActionResult QueueDataCleanUp([FromBody] DataCleanUpRequest request) + { + try + { + _queueDataCleanUpService.QueueDataCleanUp(request); + return Accepted(); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("QueueHyphenatedUserIdCleanUp")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public IActionResult QueueHyphenatedUserIdCleanUp() + { + try + { + _queueDataCleanUpService.QueueHyphenatedUserIdCleanUp(); + return Accepted(); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("QueueAccountNickname")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public async Task QueueAccountNicknameAsync() + { + try + { + await _queueDataCleanUpService.QueueUpdateAccountNickname(); + return Accepted(); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("QueuePmiCancel")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public async Task QueuePmiCancelAccountUpdateAsync() + { + try + { + await _queueDataCleanUpService.QueuePmiCancelUpdate(); + return Accepted(); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("QueueDeactivateCustodialEAgreements")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public IActionResult QueueDeactivateCustodialEAgreements() + { + try + { + _queueDataCleanUpService.QueueDeactivateCustodialEAgreements(); + return Accepted(); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("QueueCloseCustodialVruAgreements")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public IActionResult QueueCloseCustodialVruAgreements() + { + try + { + _queueDataCleanUpService.QueueCloseCustodialVruAgreements(); + return Accepted(); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("QueueMaskTransactionExternalDescriptionWithSsn")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public IActionResult QueueMaskTransactionExternalDescriptionWithSsn() + { + try + { + _queueDataCleanUpService.QueueMaskTransactionExternalDescriptionWithSsn(); + return Accepted(); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("QueueAddFundsToVipSavingsAccounts")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public IActionResult QueueAddFundsToVipSavingsAccounts() + { + try + { + _queueDataCleanUpService.QueueAddFundsToVipSavingsAccounts(); + return Accepted(); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("QueueBatchAddFundsToVipSavingsAccounts")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public IActionResult QueueBatchAddFundsToVipSavingsAccounts() + { + try + { + _queueDataCleanUpService.QueueBatchAddFundsToVipSavingsAccounts(); + return Accepted(); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("QueueUpdateAdminBranchCodesByAccountNumber")] + public IActionResult QueueUpdateAdminBranchCodesByAccountNumber() + { + try + { + _queueDataCleanUpService.QueueUpdateAdminBranchCodesByAccountNumber(); + return Ok(); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("QueueUpdateAccountLoanToValue")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public IActionResult QueueUpdateAccountLoanToValue() + { + try + { + _queueDataCleanUpService.QueueUpdateAccountLoanToValue(); + return Accepted(); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("QueueUpdateAccountGroupForAnalysis")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public IActionResult QueueUpdateAccountGroupForAnalysis() + { + try + { + _queueDataCleanUpService.QueueUpdateAccountGroupForAnalysis(); + return Accepted(); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("QueueUpdatePersonForCheckHolds")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public async Task QueueUpdatePersonForCheckHolds([FromBody] UpdatePersonForCheckHoldRequest request) + { + try + { + await _queueDataCleanUpService.QueueDataCleanUpWithPayload(request, CleanUpTypes.UpdatePersonForCheckHolds); + return Accepted(); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("QueueUpdateNcoaProcess")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public async Task QueueUpdateNcoaProcess([FromBody] NcoaUpdateRequest request) + { + try + { + await _queueDataCleanUpService.QueueDataCleanUpWithPayload(request, CleanUpTypes.UpdateNcoaProcess); + return Accepted(); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("QueueUpdateAccountCreditReportType")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public IActionResult QueueUpdateAccountCreditReportType([FromBody] CreditReportTypeRequest request) + { + try + { + _queueDataCleanUpService.QueueDataCleanUpWithPayload(request, CleanUpTypes.UpdateAccountCreditReportType); + return Accepted(); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("QueueUpdateFannieMaeMortgage")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public async Task QueueUpdateFannieMaeMortgage([FromBody] FannieMaeMortgageRequest request) + { + try + { + await _queueDataCleanUpService.QueueDataCleanUpWithPayload(request, CleanUpTypes.UpdateFannieMaeMortgage); + return Accepted(); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("QueueIndirectFunding")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public async Task QueueIndirectFunding([FromBody] IndirectFundingRequest request) + { + try + { + await _queueDataCleanUpService.QueueDataCleanUpWithPayload(request, CleanUpTypes.AddFundsToIndirectSavingsAccounts); + return Accepted(); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Controllers/StatusController.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Controllers/StatusController.cs new file mode 100644 index 0000000..ff427dc --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Controllers/StatusController.cs @@ -0,0 +1,33 @@ +using LCU.Api.Internal.DataCleanUp.Configuration; +using Microsoft.AspNetCore.Mvc; +using Serilog; +namespace LCU.Api.Internal.DataCleanUp.Controllers; + +[Route("api/[controller]")] +[ApiController] +public class StatusController : ControllerBase +{ + private readonly IEnvironmentView _environmentView; + + public StatusController(IEnvironmentView environmentView) + { + _environmentView = environmentView; + } + + [HttpGet] + [ProducesResponseType(200)] + [ProducesResponseType(500)] + public IActionResult Get() + { + try + { + Log.Verbose($"{_environmentView.Application}"); + return Ok(_environmentView); + } + catch (Exception ex) + { + Log.Error(ex, "Failure to return status"); + return StatusCode((int)System.Net.HttpStatusCode.InternalServerError); + } + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/CoreApiWrapperDao.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/CoreApiWrapperDao.cs new file mode 100644 index 0000000..918dfa1 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/CoreApiWrapperDao.cs @@ -0,0 +1,365 @@ +using System.Net; +using LCU.Api.Internal.DataCleanUp.Configuration; +using LCU.Library.Internal.ApiSecurity.Models; +using LCU.Library.Internal.ApiSecurity.Enums; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessChannelPersons; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessTypes; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapRequests; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Transaction; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Persons; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Properties; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapResponses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.PostalAddresses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts; +using LCU.Library.Internal.LcuHttpClient.HttpRequest; +using LCU.Library.Internal.LcuHttpClient.Utilities; + +namespace LCU.Api.Internal.DataCleanUp.DataAccess; + +public class CoreApiWrapperDao : ICoreApiWrapperDao +{ + private readonly ApiSecurityConfiguration _apiSecurityConfiguration; + private readonly CoreApiWrapperConfiguration _coreApiWrapperConfiguration; + private readonly IPostRequest _postRequest; + private readonly IPutRequest _putRequest; + private readonly IGetRequest _getRequest; + + private const string ClientKeyValue = "DataCleanUp"; + private const string UpdateKeyParameterKey = "updateKey"; + private const string IncludesParameterKey = "includes"; + private const string AccountNoParameterKey = "accountNumber"; + private const string PersonNumberParameterKey = "personNumber"; + private const string PropertyNumberParameterKey = "propertyNumber"; + + public CoreApiWrapperDao( + ApiSecurityConfiguration apiSecurityConfiguration, + CoreApiWrapperConfiguration coreApiWrapperConfiguration, + IPostRequest postRequest, + IPutRequest putRequest, + IGetRequest getRequest + ) + { + _apiSecurityConfiguration = apiSecurityConfiguration; + _coreApiWrapperConfiguration = coreApiWrapperConfiguration; + _postRequest = postRequest; + _putRequest = putRequest; + _getRequest = getRequest; + } + + public async Task> GetAgreePersonsWithHyphenatedUserIds() + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetAgreePersonsWithHyphenatedUserId}"; + var response = await _getRequest.Async>(path, 0); + return response; + } + + public async Task> GetActiveCustodialAgreePersonNumbers() + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetActiveCustodialAgreePersonNumbers}"; + var response = await _getRequest.Async>(path, 0); + return response; + } + + public async Task> GetActiveCustodialVruCardAgreementAgreePersons() + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetActiveCustodialVruCardAgreementAgreePersons}"; + return await _getRequest.Async>(path, 0); + } + + public async Task> GetVipSavingsToFund() + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetVipSavingsToFund}"; + return await _getRequest.Async>(path, 0); + } + + public async Task>> GetCoreApiMessageAccessChannelPersons( + AccessChannelPersonsByPersonRequest request + ) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.AccessChannelPersons}"; + return await _getRequest.Async>>(HttpUtilities.BuildEndPointWithQueryParams(path, request), 0); + } + + public async Task>> GetCoreApiMessageAccessChannelPersons( + AccessChannelPersonsByPersonRequest request, + List includes + ) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.AccesschannelPersonWithIncludes}"; + var dictionaryOfParameters = HttpUtilities.BuildDictionaryValues(request); + foreach (var includedString in includes) + { + dictionaryOfParameters.Add(IncludesParameterKey, includedString); + } + return await _getRequest.AsyncWithNewton>>(HttpUtilities.BuildEndPointWithQueryParams(path, dictionaryOfParameters), + null, _coreApiWrapperConfiguration.RetryGetAccessChannelPersonIncludes); + } + + public async Task> GetTransactionsExternalDescriptionsWithSsn() + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetTransactionExternalDescriptionsWithSsn}"; + return await _getRequest.Async>(path, 0); + } + + public async Task> GetBranchCodeChangeAccountNumbers() + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetAdminBranchCodeChangeAccountNumbers}"; + return await _getRequest.Async>(path, 0); + } + + public async Task GetAgreementByUserId(string userId) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetAgreementByUserId}"; + var finalPath = path.Replace("{userId}", userId); + return await _getRequest.Async(finalPath, 0); + } + + public async Task> GetPersonPostalAddressByPersonNumber(int personNumber) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetPersonPostalAddressByPersonNumber}?personNumber={personNumber}"; + var coreMessage = await _getRequest.AsyncWithNewton>>(path); + return coreMessage.MessageBody; + } + + public async Task> GetGroupUpdateForAnalysisAccountNumbers() + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetAccountsForGroupAnalysis}"; + return await _getRequest.Async>(path, 0); + } + + public async Task> GetAtmCheckHoldsForPersonNumbers(DateTime? resetStartDate, DateTime? resetEndDate, int? fetchSize) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetPersonsForAtmCheckHolds}" + + $"?currentDate={resetStartDate}&checkholdEndDate={resetEndDate}&fetchSize={fetchSize}"; + return await _getRequest.Async>(path, 0, _coreApiWrapperConfiguration.CoreApiTimeout); + } + + public async Task> GetPropertyNumberByAccountNumber(long accountNumber) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetPropertyNumberByAccountNumber}" + + $"?{AccountNoParameterKey}={accountNumber}"; + return await _getRequest.Async>(path, 0); + } + + public async Task GetAccountByAccountNumber(long accountNumber) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetAccountByAccountNumber}" + + $"?{AccountNoParameterKey}={accountNumber}"; + return await _getRequest.Async(path, 0); + } + + public async Task> GetPropertyUserField(long propertyNumber) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PropertyUserField}?{PropertyNumberParameterKey}={propertyNumber}"; + var message = await _getRequest.AsyncWithNewton>>(path); + return message.MessageBody; + } + + public async Task> GetAccountUserField(long accountNumber) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.AccountUserField}?{AccountNoParameterKey}={accountNumber}"; + var message = await _getRequest.AsyncWithNewton>>(path); + return message.MessageBody; + } + + public async Task> GetAccountsByMajorMinorBranchAndStatus(AccountsByMajorMinorBranchAndStatusRequest request) + { + var httpStatusCodes = new List() { HttpStatusCode.NoContent }; + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetAccountsByMajorMinorBranchAndStatus}"; + return await _getRequest.Async> (HttpUtilities.BuildEndPointWithKeyValuePairs(path, request), httpStatusCodes); + } + + public async Task UpdateAddrLineByPersonNumber(PersonAddrLine ncoaRequest) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutAddrLineByPersonNumber}"; + var uri = new Uri(path); + var response = await _putRequest.Async(uri, ncoaRequest, HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0); + return response; + } + + public async Task UpdateAccessChannelPersons(AccessChannelPerson request, long updateKey) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.AccessChannelPersons}?{UpdateKeyParameterKey}={updateKey}"; + var uri = new Uri(path); + var response = await _putRequest.Async(uri, request, HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0); + return response; + } + + public async Task UpdateAccessType(AccessTypeUpdateRequest request) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.AccessType}"; + var uri = new Uri(path); + var response = await _putRequest.Async(uri, request, HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0); + return response; + } + + public async Task UpdatePersonAgreementDetailTypes(PersonAgreementDetailTypeRequest request) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutPersonAgreementDetailTypes}"; + var uri = new Uri(path); + return await _putRequest.Async(uri, request, HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0); + } + + public async Task UpdateTransactionsExternalDescriptions(ExternalDescription request) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutTransactionExternalDescription}"; + var uri = new Uri(path); + return await _putRequest.Async(uri, request, HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0); + } + + public async Task> PostFundsToAccount(List requests) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PostFundsToAccount}"; + var uri = new Uri(path); + return await _postRequest.Async, List>(uri, requests, + HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0); + } + + public async Task UpdateBranchCodesForAccountNumbers(AccountBranchUpdateRequest request) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutAccountBranchCode}"; + var uri = new Uri(path); + return await _putRequest.Async(uri, request, + HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0); + } + + public async Task UpdateAccountLoanToValue(AccountLtvUpdateRequest request) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutAccountLoanToValue}"; + var uri = new Uri(path); + + var result = await _putRequest.Async(uri, request, + HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0); + return result; + } + + public async Task UpdateAccountGroupForAnalysis(AccountAnalysisGroupMaintenanceRequest request) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutAccountAnalysisGroup}"; + var uri = new Uri(path); + return await _putRequest.Async(uri, request, + HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0); + } + + public async Task UpdateAtmCheckHoldsForPersonNumbers(PersonUserFieldRequest request) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutPersonUserFieldForAtmCheckHolds}"; + var uri = new Uri(path); + return await _putRequest.Async(uri, request, + HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0); + } + + public async Task AddAtmCheckHoldsForPersonNumbers(PersonUserFieldRequest request) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PostPersonUserFieldForAtmCheckHolds}"; + var uri = new Uri(path); + return await _postRequest.Async(uri, request, + HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0); + } + + public async Task PostOrganizationAccount(CreateOrganizationAccountRequest request) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PostOrganizationAccount}"; + var uri = new Uri(path); + return await _postRequest.Async(uri, request, + HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0); + } + + public async Task PostPersonAccount(CreatePersonAccountRequest request) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PostPersonAccount}"; + var uri = new Uri(path); + return await _postRequest.Async(uri, request, + HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0); + } + + public async Task PutOrganizationMaintenanceRequest(OrganizationMaintenanceRequest request) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutOrganizationMaintenanceRequest}"; + var uri = new Uri(path); + return await _putRequest.Async(uri, request, + HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0); + } + + public async Task PutAccountNicknameUpdateRequest(AccountNickNameUpdateRequest request) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutAccountNickNameUpdateRequest}"; + var uri = new Uri(path); + return await _putRequest.Async(uri, request, + HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0); + } + + public async Task UpdateAccountCreditReportType(AccountCreditReportTypeUpdateRequest request) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutAccountCreditReportType}"; + var uri = new Uri(path); + return await _putRequest.Async(uri, request, + HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0); + } + + public async Task PutPersonUserField(PersonUserField personUserField) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutPersonUserField}"; + var uri = new Uri(path); + return await _putRequest.Async(uri, personUserField, + HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0); + } + + public async Task PostPropertyUserField(PropertyUserField propertyUserField) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PostPropertyUserField}"; + var uri = new Uri(path); + return await _postRequest.Async(uri, propertyUserField, + HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0); + } + + public async Task PutPropertyUserField(PropertyUserField propertyUserField) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PutPropertyUserField}"; + var uri = new Uri(path); + return await _putRequest.Async(uri, propertyUserField, + HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0); + } + + public async Task> PostAccountUserField(List accountUserField) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.AccountUserField}"; + var uri = new Uri(path); + return await _postRequest.Async, IEnumerable>(uri, accountUserField, + HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0); + } + + public async Task> PutAccountUserField(List accountUserField) + { + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.AccountUserField}"; + var uri = new Uri(path); + return await _putRequest.Async, IEnumerable>(uri, accountUserField, + HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfiguration.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)), 0); + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/FileOperationsDao.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/FileOperationsDao.cs new file mode 100644 index 0000000..c463c6f --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/FileOperationsDao.cs @@ -0,0 +1,45 @@ +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.Api.Internal.DataCleanUp.Configuration; +using LCU.Library.Internal.LcuHttpClient.HttpRequest; + +namespace LCU.Api.Internal.DataCleanUp.DataAccess; + +public class FileOperationsDao : IFileOperationsDao +{ + private readonly FileOperationsConfiguration _fileOperationsConfiguration; + private readonly IPostRequest _postRequest; + private readonly IGetRequest _getRequest; + + private const string ClientKeyValue = "DataCleanUp"; + + public FileOperationsDao( + FileOperationsConfiguration fileOperationsConfiguration, + IPostRequest postRequest, + IGetRequest getRequest + ) + { + _fileOperationsConfiguration = fileOperationsConfiguration; + _postRequest = postRequest; + _getRequest = getRequest; + } + + public async Task GetFileContent(string finalFilePath) + { + var uri = new Uri($"{_fileOperationsConfiguration.FileOperationsUrl}{finalFilePath}"); + return await _getRequest.StringResponseAsync(uri, 0); + } + + public async Task> WriteFile(WriteFileRequest writeFileRequest) + { + var path = $"{_fileOperationsConfiguration.FileOperationsUrl}{_fileOperationsConfiguration.WriteFile}"; + var uri = new Uri(path); + return await _postRequest.AsyncWithNewton>(uri, writeFileRequest, 0); + } + + public async Task> BuildDynamicFileList(DynamicFileListRequest fileRequest) + { + var path = $"{_fileOperationsConfiguration.FileOperationsUrl}{_fileOperationsConfiguration.BuildDynamicFileList}"; + var uri = new Uri(path); + return await _postRequest.Async>(uri, fileRequest, 0); + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/ICoreApiWrapperDao.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/ICoreApiWrapperDao.cs new file mode 100644 index 0000000..783b0e2 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/ICoreApiWrapperDao.cs @@ -0,0 +1,62 @@ +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessChannelPersons; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessTypes; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapRequests; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapResponses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Persons; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.PostalAddresses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Properties; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Transaction; +using LCU.Library.Internal.DataCleanUpModel.Models; +using Microsoft.AspNetCore.Mvc; + +namespace LCU.Api.Internal.DataCleanUp.DataAccess; + +public interface ICoreApiWrapperDao +{ + Task> GetAgreePersonsWithHyphenatedUserIds(); + Task> GetActiveCustodialAgreePersonNumbers(); + Task> GetActiveCustodialVruCardAgreementAgreePersons(); + Task> GetVipSavingsToFund(); + Task>> GetCoreApiMessageAccessChannelPersons( + AccessChannelPersonsByPersonRequest request); + Task>> GetCoreApiMessageAccessChannelPersons( + AccessChannelPersonsByPersonRequest request, List includes); + Task> GetTransactionsExternalDescriptionsWithSsn(); + Task> GetBranchCodeChangeAccountNumbers(); + Task> GetGroupUpdateForAnalysisAccountNumbers(); + Task GetAgreementByUserId(string userId); + Task> GetPersonPostalAddressByPersonNumber(int personNumber); + Task> GetAccountsByMajorMinorBranchAndStatus(AccountsByMajorMinorBranchAndStatusRequest request); + Task UpdateAddrLineByPersonNumber(PersonAddrLine ncoaRequest); + Task> GetAtmCheckHoldsForPersonNumbers(DateTime? resetStartDate, DateTime? resetEndDate, int? fetchSize); + Task UpdateAccessChannelPersons(AccessChannelPerson request, long updateKey); + Task UpdateAccessType(AccessTypeUpdateRequest request); + Task UpdatePersonAgreementDetailTypes(PersonAgreementDetailTypeRequest request); + Task UpdateTransactionsExternalDescriptions(ExternalDescription request); + Task> PostFundsToAccount(List requests); + Task UpdateBranchCodesForAccountNumbers(AccountBranchUpdateRequest request); + Task UpdateAccountLoanToValue(AccountLtvUpdateRequest request); + Task UpdateAccountGroupForAnalysis(AccountAnalysisGroupMaintenanceRequest request); + Task UpdateAtmCheckHoldsForPersonNumbers(PersonUserFieldRequest request); + Task AddAtmCheckHoldsForPersonNumbers(PersonUserFieldRequest request); + Task PostOrganizationAccount(CreateOrganizationAccountRequest request); + Task PostPersonAccount(CreatePersonAccountRequest request); + Task PutOrganizationMaintenanceRequest(OrganizationMaintenanceRequest request); + Task PutAccountNicknameUpdateRequest(AccountNickNameUpdateRequest request); + Task> GetPropertyNumberByAccountNumber(long accountNumber); + Task PutPersonUserField(PersonUserField personUserField); + Task PostPropertyUserField(PropertyUserField personUserField); + Task PutPropertyUserField(PropertyUserField personUserField); + Task> GetPropertyUserField(long accountNumber); + Task GetAccountByAccountNumber(long accountNumber); + Task UpdateAccountCreditReportType(AccountCreditReportTypeUpdateRequest request); + Task> PostAccountUserField(List accountUserField); + Task> PutAccountUserField(List accountUserField); + Task> GetAccountUserField(long accountNumber); +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/IFileOperationsDao.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/IFileOperationsDao.cs new file mode 100644 index 0000000..6d4feea --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/IFileOperationsDao.cs @@ -0,0 +1,10 @@ +using LCU.Library.Internal.FileOperationsModels.Models; + +namespace LCU.Api.Internal.DataCleanUp.DataAccess; + +public interface IFileOperationsDao +{ + Task GetFileContent(string finalFilePath); + Task> WriteFile(WriteFileRequest request); + Task> BuildDynamicFileList(DynamicFileListRequest request); +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/INotificationsDao.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/INotificationsDao.cs new file mode 100644 index 0000000..44371af --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/INotificationsDao.cs @@ -0,0 +1,13 @@ +using LCU.Library.Internal.NotificationsModels.Models; +using System; +using System.Collections.Generic; +using System.Net.Http; +using System.Text; + +namespace LCU.Api.Internal.DataCleanUp.DataAccess +{ + public interface INotificationsDao + { + public HttpResponseMessage SendEmail(EmailRequest emailRequest); + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/NotificationsDao.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/NotificationsDao.cs new file mode 100644 index 0000000..de5b9bd --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/DataAccess/NotificationsDao.cs @@ -0,0 +1,35 @@ +using LCU.Api.Internal.DataCleanUp.Configuration; +using LCU.Library.Internal.NotificationsModels.Models; +using LCU.Library.Internal.LcuHttpClient; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Text; +using LCU.Library.Internal.LcuHttpClient.HttpRequest; + +namespace LCU.Api.Internal.DataCleanUp.DataAccess +{ + public class NotificationsDao : INotificationsDao + { + private readonly NotificationsApiConfiguration _notificationsApiConfiguration; + private readonly ILcuHttpClient _lcuHttpClient; + + public NotificationsDao(ILcuHttpClient lcuHttpClient, NotificationsApiConfiguration emailConfiguration) + { + _lcuHttpClient = lcuHttpClient; + _notificationsApiConfiguration = emailConfiguration; + } + + public HttpResponseMessage SendEmail(EmailRequest emailRequest) + { + var encoded = JsonConvert.SerializeObject(emailRequest); + Uri uri = new Uri(_notificationsApiConfiguration.EmailEndpoint); + + var client = _lcuHttpClient.CreateClient(uri); + var c = new StringContent(encoded, Encoding.UTF8, "application/json"); + HttpResponseMessage httpResponse = client.PostAsync(_notificationsApiConfiguration.EmailEndpoint, c).Result; + + return httpResponse; + } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp.csproj b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp.csproj new file mode 100644 index 0000000..47a67ee --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp.csproj @@ -0,0 +1,50 @@ + + + + net8.0 + enable + enable + True + + + + 4 + 1701;1702;8618;1591;8605 + + + + 4 + 1701;1702;8618;1591;8605 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/AccountCreditReportType.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/AccountCreditReportType.cs new file mode 100644 index 0000000..a1ac919 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/AccountCreditReportType.cs @@ -0,0 +1,17 @@ +using CsvHelper.Configuration.Attributes; + +namespace LCU.Api.Internal.DataCleanUp.Models +{ + public class AccountCreditReportType + { + [Index(0)] + public long AccountNumber { get; set; } + + [Index(1)] + public string BorrowerName { get; set; } + + [Index(2)] + public decimal Balance { get; set; } + + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/AccountNickname.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/AccountNickname.cs new file mode 100644 index 0000000..7087dd0 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/AccountNickname.cs @@ -0,0 +1,21 @@ +using CsvHelper.Configuration.Attributes; + +namespace LCU.Api.Internal.DataCleanUp.Models; + +public class AccountNickname +{ + [Index(0)] + public int CustomerNumber { get; set; } + + [Index(1)] + public long AccountNumber { get; set; } + + [Index(2)] + public string AccountType { get; set; } + + [Index(3)] + public string BusinessName { get; set; } + + [Index(4)] + public string Nickname { get; set; } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/BatchAddFundsToVipAccounts.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/BatchAddFundsToVipAccounts.cs new file mode 100644 index 0000000..011f8d8 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/BatchAddFundsToVipAccounts.cs @@ -0,0 +1,49 @@ +using CsvHelper.Configuration.Attributes; + +namespace LCU.Api.Internal.DataCleanUp.Models +{ + public class BatchAddFundsToVipAccounts + { + [Index(0)] + public string NeedToFund { get; set; } + + [Index(1)] + public string AccountNumber { get; set; } + + [Index(2)] + public string MemberNumber { get; set; } + + [Index(3)] + public string MemberName { get; set; } + + [Index(4)] + public string NewMember { get; set; } + + [Index(5)] + public string MajorCode { get; set; } + + [Index(6)] + public string MinorCode { get; set; } + + [Index(7)] + public string MinorDescription { get; set; } + + [Index(8)] + public string AccountCreatedDate { get; set; } + + [Index(9)] + public string InitialFundingDate { get; set; } + + [Index(10)] + public string FundingAmount { get; set; } + + [Index(11)] + public string FundingType { get; set; } + + [Index(12)] + public string TransactinDescription { get; set; } + + [Index(13)] + public string PromoCode { get; set; } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/BatchAddFundsToVipAccountsSummary.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/BatchAddFundsToVipAccountsSummary.cs new file mode 100644 index 0000000..922fbdc --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/BatchAddFundsToVipAccountsSummary.cs @@ -0,0 +1,73 @@ +using CsvHelper.Configuration.Attributes; + +namespace LCU.Api.Internal.DataCleanUp.Models; +public class BatchAddFundsToVipAccountsSummary +{ + [Index(0)] + public string Funded { get; set; } + [Index(1)] + public string AmountFunded { get; set; } + + [Index(2)] + public string AccountNumber { get; set; } + + [Index(3)] + public string MemberNumber { get; set; } + + [Index(4)] + public string MemberName { get; set; } + + [Index(5)] + public string NewMember { get; set; } + + [Index(6)] + public string MajorCode { get; set; } + + [Index(7)] + public string MinorCode { get; set; } + + [Index(8)] + public string MinorDescription { get; set; } + + [Index(9)] + public string AccountCreatedDate { get; set; } + + [Index(10)] + public string InitialFundingDate { get; set; } + + [Index(11)] + public string FundingAmount { get; set; } + + [Index(12)] + public string FundingType { get; set; } + + [Index(13)] + public string TransactinDescription { get; set; } + + [Index(14)] + public string PromoCode { get; set; } + + public BatchAddFundsToVipAccountsSummary TransformNewSummary(bool funded, BatchAddFundsToVipAccounts vipAccount, double amountFunded) + { + var result = new BatchAddFundsToVipAccountsSummary() + { + Funded = funded ? "Yes" : "No", + AmountFunded = funded ? "$"+amountFunded.ToString() : "$0.00", + AccountNumber = vipAccount.AccountNumber, + MemberNumber = vipAccount.MemberNumber, + MemberName = vipAccount.MemberName, + NewMember = vipAccount.NewMember, + MajorCode = vipAccount.MajorCode, + MinorCode = vipAccount.MinorCode, + MinorDescription = vipAccount.MinorDescription, + AccountCreatedDate = vipAccount.AccountCreatedDate, + InitialFundingDate = vipAccount.InitialFundingDate, + FundingAmount = vipAccount.FundingAmount, + FundingType = vipAccount.FundingType, + TransactinDescription = vipAccount.TransactinDescription, + PromoCode = vipAccount.PromoCode + }; + + return result; + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/CheckHoldsUserFieldValue.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/CheckHoldsUserFieldValue.cs new file mode 100644 index 0000000..b97b8be --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/CheckHoldsUserFieldValue.cs @@ -0,0 +1,119 @@ +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Persons; +using System.ComponentModel.DataAnnotations.Schema; + +namespace LCU.Api.Internal.DataCleanUp.Models; + +public class CheckHoldsUserFieldValue +{ + public CheckHoldsUserFieldValue() + { + + } + public CheckHoldsUserFieldValue(PersonCheckHoldsUserField personUserField, DateTime checkHoldEndDate) + { + PersonCheckHoldsUser = personUserField; + CheckHoldEndDate = checkHoldEndDate; + } + + public PersonCheckHoldsUserField PersonCheckHoldsUser { get; set; } + public DateTime CheckHoldEndDate { get; set; } + + [NotMapped] + public bool NoAccounts_YesValue + { + get + { + //this person does not have any accounts + var value = !PersonCheckHoldsUser.OldestActiveEffectiveDate.HasValue == true && !PersonCheckHoldsUser.RecentClosedEffectiveDate.HasValue == true; + return value == true; + } + } + + [NotMapped] + public bool NoClosedInvalidActive_YesValue + { + get + { + //this person does not have any active accounts within valid check hold timeframe and no valid closed accounts + var value = PersonCheckHoldsUser.OldestActiveEffectiveDate.HasValue == true && !PersonCheckHoldsUser.RecentClosedEffectiveDate.HasValue == true && PersonCheckHoldsUser.OldestActiveEffectiveDate > CheckHoldEndDate; + return value; + } + } + + [NotMapped] + public bool NoActiveInvalidClosed_YesValue + { + get + { + //this person does not have any active accounts within valid check hold timeframe and no closed accounts within valid check hold timeframe + var value = !PersonCheckHoldsUser.OldestActiveEffectiveDate.HasValue == true && PersonCheckHoldsUser.RecentClosedEffectiveDate.HasValue == true && PersonCheckHoldsUser.RecentClosedEffectiveDate <= CheckHoldEndDate; + return value; + } + } + + [NotMapped] + public bool NoActiveClosedValid_NoValue + { + get + { + //this person does not have any valid active accounts and their closed account is within valid check hold timeframe + var value = !PersonCheckHoldsUser.OldestActiveEffectiveDate.HasValue == true && PersonCheckHoldsUser.RecentClosedEffectiveDate.HasValue == true && PersonCheckHoldsUser.RecentClosedEffectiveDate >= CheckHoldEndDate; + return value; + } + } + + [NotMapped] + public bool NoClosedActiveValid_NoValue + { + get + { + //this person does have active accounts within valid check hold timeframe and no valid closed accounts + var value = PersonCheckHoldsUser.OldestActiveEffectiveDate <= CheckHoldEndDate && !PersonCheckHoldsUser.RecentClosedEffectiveDate.HasValue == true; + return value; + } + } + + [NotMapped] + public bool ActiveClosedValid_NoValue + { + get + { + //this person does have active accounts within valid check hold timeframe and closed accounts within valid check hold timeframe + var value = PersonCheckHoldsUser.OldestActiveEffectiveDate <= CheckHoldEndDate && PersonCheckHoldsUser.RecentClosedEffectiveDate >= CheckHoldEndDate; + return value; + } + } + + [NotMapped] + public bool ActiveInValidClosedValid_NoValue + { + get + { + //this person does not have active accounts within valid check hold timeframe and has closed accounts within valid check hold timeframe + var value = PersonCheckHoldsUser.OldestActiveEffectiveDate >= CheckHoldEndDate && PersonCheckHoldsUser.RecentClosedEffectiveDate > CheckHoldEndDate; + return value; + } + } + + [NotMapped] + public bool ActiveValidClosedInValid_NoValue + { + get + { + //this person does have active accounts within valid check hold timeframe and closed accounts not within valid check hold timeframe + var value = PersonCheckHoldsUser.OldestActiveEffectiveDate <= CheckHoldEndDate && PersonCheckHoldsUser.RecentClosedEffectiveDate <= CheckHoldEndDate; + return value; + } + } + + [NotMapped] + public bool ActiveInValidClosedInValid_YesValue + { + get + { + //this person does not have active accounts within valid check hold timeframe and closed accounts not within valid check hold timeframe + var value = PersonCheckHoldsUser.OldestActiveEffectiveDate >= CheckHoldEndDate && PersonCheckHoldsUser.RecentClosedEffectiveDate <= CheckHoldEndDate; + return value; + } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/FannieMaeMortgage.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/FannieMaeMortgage.cs new file mode 100644 index 0000000..ec0f7cc --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/FannieMaeMortgage.cs @@ -0,0 +1,35 @@ +using FileHelpers; + +namespace LCU.Api.Internal.DataCleanUp.Models; + +[DelimitedRecord(",")] +[IgnoreEmptyLines] +[IgnoreFirst(1)] + +public class FannieMaeMortgage +{ + public string ServicerNumber { get; set; } + + [FieldConverter(ConverterKind.Int64)] + public long? FannieMaeLoanNumber { get; set; } + + public string PoolIssueDate { get; set; } + + public string ServicerName { get; set; } + + [FieldConverter(ConverterKind.Int64)] + public long? ServicerLoanNumber { get; set; } + + public string PropertyStreetAddress { get; set; } + + public string PropertyCity { get; set; } + + public string PropertyState { get; set; } + + public string PropertyZipCode { get; set; } + + public string PoolNumber { get; set; } + + public string PfpStatus { get; set; } + +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/FannieMaeTotalBatchSummary.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/FannieMaeTotalBatchSummary.cs new file mode 100644 index 0000000..488988a --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/FannieMaeTotalBatchSummary.cs @@ -0,0 +1,20 @@ +namespace LCU.Api.Internal.DataCleanUp.Models +{ + public class FannieMaeTotalBatchSummary + { + public List UpdateResults { get; set; } + public int TotalRecordsFound { get; set; } + public int TotalRecordsUpdated { get; set; } + public int TotalErrorRecords { get; set; } + public bool ErrorFileCreated { get; set; } = false; + + public FannieMaeTotalBatchSummary(List updateResults, bool errorFileCreationSuccess) + { + UpdateResults = updateResults; + TotalErrorRecords = 0; + TotalRecordsUpdated = 0; + TotalRecordsFound = 0; + ErrorFileCreated = errorFileCreationSuccess; + } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/FannieMaeUpdateResult.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/FannieMaeUpdateResult.cs new file mode 100644 index 0000000..67be31b --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/FannieMaeUpdateResult.cs @@ -0,0 +1,24 @@ +namespace LCU.Api.Internal.DataCleanUp.Models; + +public class FannieMaeUpdateResult +{ + public List UpdateList { get; set; } + public List ErrorList { get; set; } + public int TotalRecordsFound { get; set; } + public string Filename { get; set; } + + public FannieMaeUpdateResult(string filename) + { + ErrorList = new List(); + UpdateList = new List(); + TotalRecordsFound = 0; + Filename = filename; + } + + public void AddStringToErrorList(FannieMaeMortgage record, string errorMessage) + { + var errorRecord = $"{record.ServicerLoanNumber}|{record.PoolNumber}|{record.PoolIssueDate}|{errorMessage}\n"; + ErrorList.Add(errorRecord); + } + +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/IndirectSavingsAccount.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/IndirectSavingsAccount.cs new file mode 100644 index 0000000..b12bb00 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/IndirectSavingsAccount.cs @@ -0,0 +1,13 @@ +namespace LCU.Api.Internal.DataCleanUp.Models; + +public class IndirectSavingsAccount +{ + public long SavingsAccountNumber { get; set; } + + public string MinorAccountType { get; set; } + + public long BranchCode { get; set; } + + public string TaxOwnerName { get; set; } + +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/IndirectSavingsAccountResult.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/IndirectSavingsAccountResult.cs new file mode 100644 index 0000000..b7bb99e --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/IndirectSavingsAccountResult.cs @@ -0,0 +1,7 @@ +namespace LCU.Api.Internal.DataCleanUp.Models; + +public class IndirectSavingsAccountResult +{ + public string TotalAccountsFunded { get; set; } + public string TotalAccountsNotFunded { get; set; } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/IndirectSavingsAccountsSummary.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/IndirectSavingsAccountsSummary.cs new file mode 100644 index 0000000..93eafff --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/IndirectSavingsAccountsSummary.cs @@ -0,0 +1,34 @@ +using CsvHelper.Configuration.Attributes; +namespace LCU.Api.Internal.DataCleanUp.Models; + +public class IndirectSavingsAccountsSummary +{ + [Index(0)] + public string AccountNumber { get; set; } + + [Index(1)] + public string AmountFunded { get; set; } + + [Index(2)] + public string BranchCode { get; set; } + + [Index(3)] + public string Name { get; set; } + + [Index(4)] + public string ErrorMessage { get; set; } + + public IndirectSavingsAccountsSummary TransformNewSummary(long accountNumber, double amountFunded, + long branchCode, string name, string errorMessage) + { + var result = new IndirectSavingsAccountsSummary() + { + AccountNumber = accountNumber.ToString(), + AmountFunded = errorMessage == string.Empty ? amountFunded.ToString() : "0", + BranchCode = branchCode.ToString(), + Name = name.ToString(), + ErrorMessage = errorMessage + }; + return result; + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/MissingBatchSavings.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/MissingBatchSavings.cs new file mode 100644 index 0000000..d4d97b9 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/MissingBatchSavings.cs @@ -0,0 +1,58 @@ +using CsvHelper.Configuration.Attributes; + +namespace LCU.Api.Internal.DataCleanUp.Models; + +public class MissingBatchSavings +{ + [Index(0)] + public int CustomerNumber { get; set; } + + [Index(1)] + public string FirstName { get; set; } + + [Index(2)] + public string LastName { get; set; } + + [Index(3)] + public string CustomerType { get; set; } + + [Index(4)] + public string OrganizationName { get; set; } + + [Index(5)] + public int CoreSavingsAccount { get; set; } + + [Index(6)] + public string SavingsAccountNumber { get; set; } + + [Index(7)] + public decimal SavingsAccountBalance { get; set; } + + [Index(8)] + public int BranchCode { get; set; } + + [Index(9)] + public int ControlPerson { get; set; } + + [Index(10)] + public string ControlPersonNeeded { get; set; } + + [Index(11)] + public string CustomerAddress1 { get; set; } + + [Index(12)] + public string CustomerAddress2 { get; set; } + + [Index(13)] + public string CustomerCity { get; set; } + + [Index(14)] + public string CustomerState { get; set; } + + [Index(15)] + public string CustomerZip { get; set; } + + [Index(16)] + public string ControlPersonAssigned { get; set; } + +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/MissingBatchSavingsSummary.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/MissingBatchSavingsSummary.cs new file mode 100644 index 0000000..efc6624 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/MissingBatchSavingsSummary.cs @@ -0,0 +1,67 @@ +using CsvHelper.Configuration.Attributes; + +namespace LCU.Api.Internal.DataCleanUp.Models; + +public class MissingBatchSavingsSummary +{ + [Index(0)] + public int CustomerNumber { get; set; } + + [Index(1)] + public string FirstName { get; set; } + + [Index(2)] + public string LastName { get; set; } + + [Index(3)] + public string CustomerType { get; set; } + + [Index(4)] + public string OrganizationName { get; set; } + + [Index(5)] + public string SavingsAccountNumber { get; set; } + + [Index(6)] + public double AmountFunded { get; set; } + + [Index(7)] + public int BranchCode { get; set; } + + [Index(8)] + public string CustomerAddress1 { get; set; } + + [Index(9)] + public string CustomerAddress2 { get; set; } + + [Index(10)] + public string CustomerCity { get; set; } + + [Index(11)] + public string CustomerState { get; set; } + + [Index(12)] + public string CustomerZip { get; set; } + + public MissingBatchSavingsSummary TransformNewSummary(MissingBatchSavings savingsRecord, double amountFunded, string savingsAccount) + { + var result = new MissingBatchSavingsSummary() + { + CustomerNumber = savingsRecord.CustomerNumber, + CustomerType = savingsRecord.CustomerType, + FirstName = savingsRecord.FirstName, + LastName = savingsRecord.LastName, + OrganizationName = savingsRecord.OrganizationName, + CustomerAddress1 = savingsRecord.CustomerAddress1, + CustomerAddress2 = savingsRecord.CustomerAddress2, + CustomerCity = savingsRecord.CustomerCity, + CustomerState = savingsRecord.CustomerState, + CustomerZip = savingsRecord.CustomerZip, + BranchCode = savingsRecord.BranchCode, + SavingsAccountNumber = savingsAccount, + AmountFunded = amountFunded + }; + + return result; + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/ParserModels/NcoaRecord.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/ParserModels/NcoaRecord.cs new file mode 100644 index 0000000..12e25b7 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/ParserModels/NcoaRecord.cs @@ -0,0 +1,76 @@ +using FileHelpers; + +namespace LCU.Api.Internal.DataCleanUp.Models.ParserModels; + +[FixedLengthRecord()] +public class NcoaRecord +{ + [FieldFixedLength(20)] + [FieldTrim(TrimMode.Right)] + public string UserId { get; set; } + + [FieldFixedLength(1)] + public string NcoaType { get; set; } + + [FieldFixedLength(6)] + public string ChangeDate { get; set; } + + [FieldFixedLength(60)] + [FieldTrim(TrimMode.Right)] + public string PrimaryName { get; set; } + + [FieldFixedLength(60)] + [FieldTrim(TrimMode.Right)] + public string CurrentAddressOne { get; set; } + + [FieldFixedLength(60)] + [FieldTrim(TrimMode.Right)] + public string CurrentAddressTwo { get; set; } + + [FieldFixedLength(60)] + [FieldTrim(TrimMode.Right)] + public string CurrentAddressThree { get; set; } + + [FieldFixedLength(60)] + [FieldTrim(TrimMode.Right)] + public string CurrentAddressFour { get; set; } + + [FieldFixedLength(60)] + [FieldTrim(TrimMode.Right)] + public string CurrentAddressFive { get; set; } + + [FieldFixedLength(60)] + [FieldTrim(TrimMode.Right)] + public string SecondaryName { get; set; } + + [FieldFixedLength(60)] + [FieldTrim(TrimMode.Right)] + public string BusinessName { get; set; } + + [FieldFixedLength(60)] + [FieldTrim(TrimMode.Right)] + public string NewAddressLine { get; set; } + + [FieldFixedLength(60)] + [FieldTrim(TrimMode.Right)] + public string City { get; set; } + + [FieldFixedLength(2)] + public string StateCode { get; set; } + + [FieldFixedLength(5)] + [FieldTrim(TrimMode.Right)] + public string ZipCode { get; set; } + + [FieldFixedLength(5)] + [FieldTrim(TrimMode.Right)] + public string ZipSuffix { get; set; } + + [FieldFixedLength(70)] + [FieldTrim(TrimMode.Both)] + public string UserIdTwo { get; set; } + + [FieldFixedLength(60)] + [FieldTrim(TrimMode.Right)] + public string StatementCode { get; set; } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/PmiCancel.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/PmiCancel.cs new file mode 100644 index 0000000..7766e74 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/PmiCancel.cs @@ -0,0 +1,26 @@ +using CsvHelper.Configuration.Attributes; + +namespace LCU.Api.Internal.DataCleanUp.Models +{ + public class PmiCancel + { + [Index(0)] + public long LoanId { get; set; } + [Index(1)] + public string MemberName { get; set; } + [Index(2)] + public string LTVCancelDate { get; set; } + [Index(3)] + public string Midpoint { get; set; } + [Index(4)] + public string LoanCompanyName { get; set; } + [Ignore] + public string CurrentStatusCode { get; set; } + [Ignore] + public string CurrentStatus { get; set; } + [Ignore] + public long PropertyNumber { get; set; } + [Ignore] + public bool IsSuccessful { get; set; } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/UpdatePmiCancelSummary.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/UpdatePmiCancelSummary.cs new file mode 100644 index 0000000..bda5103 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Models/UpdatePmiCancelSummary.cs @@ -0,0 +1,37 @@ +using CsvHelper.Configuration.Attributes; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts; +using LCU.Library.Internal.DataCleanUpModel.Models; + +namespace LCU.Api.Internal.DataCleanUp.Models +{ + public class UpdatePmiCancelSummary + { + [Index(0)] + public long LoanId { get; set; } + [Index(1)] + public string MemberName { get; set; } + [Index(2)] + public long PropertyNumber { get; set; } + [Index(3)] + public string UpdatedDate { get; set; } + [Index(4)] + public string CurrentAccountStatus { get; set; } + [Index(5)] + public string SuccessOrFailMessage { get; set; } + + public UpdatePmiCancelSummary TransformNewSummary(PmiCancel pmiCancel, string message) + { + var result = new UpdatePmiCancelSummary() + { + LoanId = pmiCancel.LoanId, + MemberName = pmiCancel.MemberName, + PropertyNumber = pmiCancel.PropertyNumber, + UpdatedDate = pmiCancel.LTVCancelDate, + CurrentAccountStatus = pmiCancel.CurrentStatus, + SuccessOrFailMessage = message + }; + + return result; + } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Program.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Program.cs new file mode 100644 index 0000000..f4d5a9b --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Program.cs @@ -0,0 +1,28 @@ +using Serilog; + +namespace LCU.Api.Internal.DataCleanUp; + +class Program +{ + static void Main(string[] args) + { + CreateHostBuilder(args).Build().Run(); + } + + public static IHostBuilder CreateHostBuilder(string[] args) => + Host.CreateDefaultBuilder(args) + .ConfigureAppConfiguration((hostingcontext, config) => + { + config.AddJsonFile("/app/config/mapped-appsettings/primary.json", optional: true, reloadOnChange: true); + config.AddJsonFile("/vault/secrets/data-clean-up-api-security-configuration-internal-api-key-sets.json", optional: true, reloadOnChange: true); + config.AddJsonFile("/vault/secrets/data-clean-up-database-connection.json", optional: true, reloadOnChange: true); + config.AddJsonFile("/vault/secrets/data-clean-up-seq-api-key.json", optional: true, reloadOnChange: true); + config.AddJsonFile("/vault/secrets/data-clean-up-connection-configuration-queue-user-name.json", optional: true, reloadOnChange: true); + config.AddJsonFile("/vault/secrets/data-clean-up-connection-configuration-queue-password.json", optional: true, reloadOnChange: true); + config.AddJsonFile("/vault/secrets/data-clean-up-saving-missing-requirements-defaults-funds-to-account-defaults-gl-account-number.json", optional: true, reloadOnChange: true); + config.AddJsonFile("/vault/secrets/data-clean-up-indirect-savings-requirements-defaults-funds-to-account-defaults-indirect-gl-account-number.json", optional: true, reloadOnChange: true); + config.AddJsonFile("/vault/secrets/data-clean-up-indirect-savings-requirements-defaults-funds-to-account-defaults-funds-defaults-fund-amount-indirect-fund-amount.json", optional: true, reloadOnChange: true); + }) + .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup(); }) + .UseSerilog(); +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Properties/launchSettings.json b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Properties/launchSettings.json new file mode 100644 index 0000000..2bea25a --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Properties/launchSettings.json @@ -0,0 +1,52 @@ +{ + "profiles": { + + "IIS Express": { + + "commandName": "IISExpress", + + "launchBrowser": true, + + "environmentVariables": { + + "ASPNETCORE_ENVIRONMENT": "Development" + + } + + }, + + "LCU.Api.Internal.DataCleanUp": { + + "commandName": "Project", + + "launchBrowser": true, + + "environmentVariables": { + + "ASPNETCORE_ENVIRONMENT": "Development" + + }, + + "applicationUrl": "https://localhost:5001;http://localhost:5000" + + } + + }, + + "iisSettings": { + + "windowsAuthentication": true, + + "anonymousAuthentication": false, + + "iisExpress": { + + "applicationUrl": "http://localhost:63864/", + + "sslPort": 0 + + } + + } + +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/AddFundsToIndirectSavingsAccountsService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/AddFundsToIndirectSavingsAccountsService.cs new file mode 100644 index 0000000..d077cf5 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/AddFundsToIndirectSavingsAccountsService.cs @@ -0,0 +1,189 @@ +using Serilog; +using CsvHelper; +using CsvHelper.Configuration; +using Newtonsoft.Json; +using System.Text; +using System.Globalization; +using TimeZoneConverter; +using LCU.Api.Internal.DataCleanUp.Models; +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Api.Internal.DataCleanUp.Configuration; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts; + +namespace LCU.Api.Internal.DataCleanUp.Services +{ + public class AddFundsToIndirectSavingsAccountsService : IAddFundsToIndirectSavingsAccountsService + { + private readonly ICoreApiWrapperService _coreApiWrapperService; + private readonly IFileOperationsService _fileOperationsService; + private readonly IndirectSavingsRequirementsDefaults _indirectSavingsDefaults; + private DataCleanUpConfiguration _dataCleanUpConfiguration; + private List _addFundsToIndirectAccountsSummaries = new List(); + + public AddFundsToIndirectSavingsAccountsService(ICoreApiWrapperService coreApiWrapperService, IFileOperationsService fileOperationsService, IndirectSavingsRequirementsDefaults indirectSavingsDefaults, DataCleanUpConfiguration dataCleanUpConfiguration) + { + _coreApiWrapperService = coreApiWrapperService; + _fileOperationsService = fileOperationsService; + _indirectSavingsDefaults = indirectSavingsDefaults; + _dataCleanUpConfiguration = dataCleanUpConfiguration; + } + + public async Task CleanUp(DataCleanUpRequest dataCleanUpRequest) + { + Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List()); + var indirectFundRequest = JsonConvert.DeserializeObject(dataCleanUpRequest.DataCleanUpPayload); + ArgumentNullException.ThrowIfNull(indirectFundRequest); + + try + { + var request = BuildRequestForAccountsToFund(); + + var accountsToFundList = await _coreApiWrapperService.GetAccountsByMajorMinorBranchAndStatus(request); + + if (accountsToFundList != null) + { + Log.Information($"Data CleanUp # of Indirect Accounts To Be Funded {accountsToFundList.Count()} at {DateTime.Now}"); + + foreach (var accountToFund in accountsToFundList) + { + cleanUpResult = await HandleSavingsToFundsRequest(cleanUpResult, accountToFund); + } + } + + await HandleExportResultsAddFundsToSavingsAccounts(indirectFundRequest); + } + catch (Exception exception) + { + Log.Error(exception, "Error while Handling Indirect Savings Account to Funds."); + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while Handling Indirect Savings Account to Funds. " + + $"Exception:{exception}"); + } + + Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + return cleanUpResult; + } + + public async Task HandleSavingsToFundsRequest(DataCleanUpResult cleanUpResult, AccountsByMajorMinorBranchAndStatusResponse accountToBeFunded) + { + try + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack = new List(); + + var listFundsToAccountsRequest = _coreApiWrapperService.BuildFundsToAccountRequests(accountToBeFunded.AccountNumber.ToString(), _indirectSavingsDefaults.GLAccountNumber, _indirectSavingsDefaults); + var basicResponse = await _coreApiWrapperService.PostFundsToAccount(listFundsToAccountsRequest); + ArgumentNullException.ThrowIfNull(basicResponse); + + foreach (var response in basicResponse) + { + cleanUpResult.Successful = response.Success; + cleanUpResult.ResponseStack.AddRange(response.Errors); + } + + var addFundstoAccountsSummary = HandleCreatingAccountSummary(accountToBeFunded, cleanUpResult); + _addFundsToIndirectAccountsSummaries.Add(addFundstoAccountsSummary); + + } + catch (Exception exception) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while Handling Indirect Savings Account to Funds. " + + $"AccountNumber: {accountToBeFunded.AccountNumber}, " + + $"Exception:{exception}" + "
"); + + var addFundstoAccountsSummary = HandleCreatingAccountSummary(accountToBeFunded, cleanUpResult); + _addFundsToIndirectAccountsSummaries.Add(addFundstoAccountsSummary); + } + return cleanUpResult; + } + + public AccountsByMajorMinorBranchAndStatusRequest BuildRequestForAccountsToFund() + { + var coreRequests = _indirectSavingsDefaults.FundingCoreRequests; + + var request = new AccountsByMajorMinorBranchAndStatusRequest() + { + MajorTypes = coreRequests.MajorAccountTypes, + MinorTypes = coreRequests.MinorAccountTypes, + AccountStatuses = coreRequests.AccountStatusTypes, + BranchCodes = coreRequests.BranchCodeTypes + }; + + return request; + } + + public IndirectSavingsAccountsSummary HandleCreatingAccountSummary(AccountsByMajorMinorBranchAndStatusResponse accountToBeFunded, DataCleanUpResult cleanUpResult) + { + var addFundstoAccountsSummary = new IndirectSavingsAccountsSummary(); + return addFundstoAccountsSummary.TransformNewSummary(accountToBeFunded.AccountNumber, _indirectSavingsDefaults.FundsDefaults.FundAmount, + accountToBeFunded.BranchCode, accountToBeFunded.Name, + string.Join(";", cleanUpResult.ResponseStack.ToArray())); + } + + public async Task HandleExportResultsAddFundsToSavingsAccounts(IndirectFundingRequest request) + { + try + { + var summaryTotal = new List() + { + new IndirectSavingsAccountResult + { + TotalAccountsFunded = _addFundsToIndirectAccountsSummaries.Where(x => x.AmountFunded != "0").Count().ToString(), + TotalAccountsNotFunded = _addFundsToIndirectAccountsSummaries.Where(x => x.AmountFunded == "0").Count().ToString() + } + }; + + var csvConfig = new CsvConfiguration(CultureInfo.CurrentCulture) + { + HasHeaderRecord = true, + Delimiter = ",", + Encoding = Encoding.UTF8 + }; + + var mem = new MemoryStream(); + var writer = new StreamWriter(mem); + var csvWriter = new CsvWriter(writer, csvConfig); + ArgumentNullException.ThrowIfNull(csvWriter); + + csvWriter.WriteHeader(); + csvWriter.NextRecord(); + csvWriter.WriteRecords(_addFundsToIndirectAccountsSummaries); + csvWriter.NextRecord(); + csvWriter.WriteHeader(); + csvWriter.NextRecord(); + csvWriter.WriteRecords(summaryTotal); + writer.Flush(); + var result = Encoding.UTF8.GetString(mem.ToArray()); + + var dateString = GetCurrentDateTimeString("yyyy-MM-dd-HHmmss"); + + var writeFileRequest = new WriteFileRequest() + { + DestinationPath = request.SummaryFileDestinationPath, + FileName = string.Join("-", request.Filename, dateString), + Overwrite = false, + Extension = "csv", + FileData = result, + }; + + await _fileOperationsService.WriteFile(writeFileRequest); + } + catch (Exception exception) + { + throw new Exception($"Export Add Funds Summary Error, {exception.Message}"); + } + } + + public string GetCurrentDateTimeString(string format) + { + var assumedTimezone = TZConvert.GetTimeZoneInfo(_dataCleanUpConfiguration.TimeZone); + var currentDateTime = TimeZoneInfo.ConvertTime(DateTime.Now, assumedTimezone); + + return currentDateTime.ToString(format); + } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/AddFundsToVipSavingsAccountsService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/AddFundsToVipSavingsAccountsService.cs new file mode 100644 index 0000000..e31cdee --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/AddFundsToVipSavingsAccountsService.cs @@ -0,0 +1,70 @@ +using Serilog; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Api.Internal.DataCleanUp.Configuration; + +namespace LCU.Api.Internal.DataCleanUp.Services; + +public class AddFundsToVipSavingsAccountsService : IAddFundsToVipSavingsAccountsService +{ + private readonly ICoreApiWrapperService _coreApiWrapperService; + private readonly FundsToAccountDefaults _savingsFundsDefaults; + + public AddFundsToVipSavingsAccountsService(ICoreApiWrapperService coreApiWrapperService, SavingsMissingRequirementsDefaults savingsFundsDefaults) + { + _coreApiWrapperService = coreApiWrapperService; + _savingsFundsDefaults = savingsFundsDefaults.FundsToAccountDefaults; + } + + public async Task CleanUp(DataCleanUpRequest dataCleanUpRequest) + { + Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List()); + + try + { + var accountNumbers = await _coreApiWrapperService.GetVipSavingsToFund(); + ArgumentNullException.ThrowIfNull(accountNumbers); + Log.Information($"Data CleanUp # of Accounts {accountNumbers.Count()} at {DateTime.Now}"); + foreach (var accountNumber in accountNumbers) + { + cleanUpResult = await HandleVipSavingsToFundsRequest(cleanUpResult, accountNumber); + } + } + catch (Exception exception) + { + Log.Error(exception, "Error while Handling Vip Savings Account to Funds."); + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while Handling Vip Savings Account to Funds. " + + $"Exception:{exception}"); + } + + Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + return cleanUpResult; + } + + public async Task HandleVipSavingsToFundsRequest(DataCleanUpResult cleanUpResult, string accountNumber) + { + try + { + var basicResponse = await _coreApiWrapperService.PostFundsToAccount(accountNumber, _savingsFundsDefaults.FundsDefaults.FundAmount); + ArgumentNullException.ThrowIfNull(basicResponse); + foreach (var response in basicResponse) + { + if (!response.Success) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.AddRange(response.Errors); + } + } + } + catch (Exception exception) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while Handling Vip Savings Account to Funds. " + + $"AccountNumber: {accountNumber}, " + + $"Exception:{exception}" + "
"); + } + + return cleanUpResult; + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/BatchAddFundsToVipSavingsAccountsService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/BatchAddFundsToVipSavingsAccountsService.cs new file mode 100644 index 0000000..8b8cea9 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/BatchAddFundsToVipSavingsAccountsService.cs @@ -0,0 +1,146 @@ +using Serilog; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Api.Internal.DataCleanUp.Configuration; +using CsvHelper; +using LCU.Api.Internal.DataCleanUp.Models; +using System.Globalization; +using CsvHelper.Configuration; +using LCU.Library.Internal.FileOperationsModels.Models; +using System.Text; + +namespace LCU.Api.Internal.DataCleanUp.Services +{ + public class BatchAddFundsToVipSavingsAccountsService : IBatchAddFundsToVipSavingsAccountsService + { + private readonly ICoreApiWrapperService _coreApiWrapperService; + private readonly IFileOperationsService _fileOperationsService; + private readonly DataCleanupDefaults _dataCleanupDefaults; + private readonly FundsToAccountDefaults _savingsFundsDefaults; + private List _batchAddFundsToVipAccountsSummaries = new List(); + + + public BatchAddFundsToVipSavingsAccountsService(ICoreApiWrapperService coreApiWrapperService, IFileOperationsService fileOperationsService, DataCleanupDefaults dataCleanupDefaults, SavingsMissingRequirementsDefaults savingsFundsDefaults) + { + _coreApiWrapperService = coreApiWrapperService; + _fileOperationsService = fileOperationsService; + _dataCleanupDefaults = dataCleanupDefaults; + _savingsFundsDefaults = savingsFundsDefaults.FundsToAccountDefaults; + + } + + public async Task CleanUp(DataCleanUpRequest dataCleanUpRequest) + { + Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List()); + + try + { + var batchAddFundsFileData = await _fileOperationsService.GetContentData(_dataCleanupDefaults.BatchAddFunds); + ArgumentNullException.ThrowIfNull(batchAddFundsFileData); + + var textReader = new StringReader(batchAddFundsFileData); + ArgumentNullException.ThrowIfNull(textReader); + + var csvReader = new CsvReader(textReader, CultureInfo.InvariantCulture); + var batchAddFundsCleanupList = csvReader.GetRecords().ToList(); + ArgumentNullException.ThrowIfNull(batchAddFundsCleanupList); + + foreach (var accountToBeFunded in batchAddFundsCleanupList) + { + cleanUpResult = await HandleVipSavingsToFundsRequest(cleanUpResult, accountToBeFunded); + } + + await HandleExportResultsBatchAddFundsToVipSavingsAccounts(); + + } + catch (Exception exception) + { + Log.Error(exception, "Error while Handling Batch Vip Savings Account to Funds."); + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while Handling Vip Savings Account to Funds. " + + $"Exception:{exception}"); + } + + Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + return cleanUpResult; + } + + public async Task HandleVipSavingsToFundsRequest(DataCleanUpResult cleanUpResult, BatchAddFundsToVipAccounts accountToBeFunded) + { + try + { + bool fundsPostedSuccess = true; + + var basicResponse = await _coreApiWrapperService.PostFundsToAccount(accountToBeFunded.AccountNumber, _savingsFundsDefaults.FundsDefaults.FundAmount); + ArgumentNullException.ThrowIfNull(basicResponse); + foreach (var response in basicResponse) + { + fundsPostedSuccess = fundsPostedSuccess && response.Success; + if (!response.Success) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.AddRange(response.Errors); + } + } + + // Generate Summary Entry + var addFundstoVipAccountsSummary = new BatchAddFundsToVipAccountsSummary(); + _batchAddFundsToVipAccountsSummaries.Add(addFundstoVipAccountsSummary.TransformNewSummary(fundsPostedSuccess, accountToBeFunded, _savingsFundsDefaults.FundsDefaults.FundAmount)); + } + catch (Exception exception) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while Handling Batch Vip Savings Account to Funds. " + + $"AccountNumber: {accountToBeFunded.AccountNumber}, " + + $"Exception:{exception}" + "
"); + + var addFundstoVipAccountsSummary = new BatchAddFundsToVipAccountsSummary(); + _batchAddFundsToVipAccountsSummaries.Add(addFundstoVipAccountsSummary.TransformNewSummary(false, accountToBeFunded, _savingsFundsDefaults.FundsDefaults.FundAmount)); + + } + + + return cleanUpResult; + } + + public async Task HandleExportResultsBatchAddFundsToVipSavingsAccounts() + { + try + { + var csvConfig = new CsvConfiguration(CultureInfo.CurrentCulture) + { + HasHeaderRecord = true, + Delimiter = ",", + Encoding = Encoding.UTF8 + }; + + var mem = new MemoryStream(); + var writer = new StreamWriter(mem); + var csvWriter = new CsvWriter(writer, csvConfig); + ArgumentNullException.ThrowIfNull(csvWriter); + + csvWriter.WriteHeader(); + csvWriter.NextRecord(); + csvWriter.WriteRecords(_batchAddFundsToVipAccountsSummaries); + + writer.Flush(); + var result = Encoding.UTF8.GetString(mem.ToArray()); + + var writeFileRequest = new WriteFileRequest() + { + DestinationPath = _dataCleanupDefaults.BatchAddFundsSummarySourcePath, + FileName = "BatchNeedToBeFundedSummary", + Overwrite = true, + Extension = "csv", + FileData = result, + }; + + await _fileOperationsService.WriteFile(writeFileRequest); + } + catch (Exception exception) + { + throw new Exception($"Export Batch Add Funds Summary Error, {exception.Message}"); + } + } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/CloseCustodialVruAgreementsService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/CloseCustodialVruAgreementsService.cs new file mode 100644 index 0000000..d0a99a6 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/CloseCustodialVruAgreementsService.cs @@ -0,0 +1,92 @@ +using Serilog; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements; +using LCU.Api.Internal.DataCleanUp.DataAccess; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapRequests; + +namespace LCU.Api.Internal.DataCleanUp.Services; + +public class CloseCustodialVruAgreementsService : ICloseCustodialVruAgreementsService +{ + private readonly ICoreApiWrapperService _coreApiWrapperService; + private const string NewStatusCode = "NEWSTATCD"; + private const string CloseStatusValue = "CLOS"; + private const string NewStatusReason = "NEWSTATREAS"; + private const string VruAgreeTypeCode = "VRU"; + private const string AutomatedSystemCleanupReason = "Automated System Cleanup"; + + public CloseCustodialVruAgreementsService(ICoreApiWrapperService coreApiWrapperService) + { + _coreApiWrapperService = coreApiWrapperService; + } + + public async Task CleanUp(DataCleanUpRequest dataCleanUpRequest) + { + Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List()); + + try + { + var agreePerons = await _coreApiWrapperService.GetActiveCustodialVruCardAgreementAgreePersons(); + ArgumentNullException.ThrowIfNull(agreePerons); + foreach (var agreePerson in agreePerons) + { + await HandleClosingCustodialVruAgreements(cleanUpResult, agreePerson); + } + } + catch (Exception exception) + { + Log.Error(exception, "Error while Closing Custodial Vru Agreements."); + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while Closing Custodial Vru Agreements. " + + $"Exception:{exception}"); + } + + Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + return cleanUpResult; + } + + public async Task HandleClosingCustodialVruAgreements(DataCleanUpResult cleanUpResult, AgreePerson agreePerson) + { + try + { + var detailTypes = new List() + { + new DetailType() + { + DetailTypeCode = NewStatusCode, + DetailValue = CloseStatusValue + }, + new DetailType() + { + DetailTypeCode = NewStatusReason, + DetailValue = AutomatedSystemCleanupReason + } + }; + + var personAgreementDetailTypeRequest = new PersonAgreementDetailTypeRequest() + { + PersonNumber = agreePerson.PersonNumber, + AgreeNumber = agreePerson.AgreeNumber, + AgreeTypeCode = VruAgreeTypeCode, + DetailTypes = detailTypes + }; + var result = await _coreApiWrapperService.UpdatePersonAgreementDetailTypes(personAgreementDetailTypeRequest); + + ArgumentNullException.ThrowIfNull(result); + if (!result.Success) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.AddRange(result.Errors); + } + } + catch(Exception exception) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while Closing Custodial Vru Agreements. " + + $"PersonNumber: {agreePerson.PersonNumber}, " + + $"AgreeNumber: {agreePerson.AgreeNumber}, " + + $"Exception:{exception}"); + } + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/CoreApiWrapperService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/CoreApiWrapperService.cs new file mode 100644 index 0000000..a216803 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/CoreApiWrapperService.cs @@ -0,0 +1,712 @@ +using Serilog; +using System.Text.Json; +using LCU.Api.Internal.DataCleanUp.DataAccess; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Persons; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Transaction; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapRequests; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessChannelPersons; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessTypes; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapResponses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Properties; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.PostalAddresses; +using LCU.Api.Internal.DataCleanUp.Configuration; +using LCU.Api.Internal.DataCleanUp.Models; + +namespace LCU.Api.Internal.DataCleanUp.Services; + +public class CoreApiWrapperService : ICoreApiWrapperService +{ + private readonly ICoreApiWrapperDao _coreApiWrapperDao; + private readonly FundsToAccountDefaults _fundsToAccountDefaults; + private readonly DataCleanupDefaults _dataCleanupDefaults; + + public CoreApiWrapperService(ICoreApiWrapperDao coreApiWrapperDao, SavingsMissingRequirementsDefaults savingsMissingRequirementsDefaults, DataCleanupDefaults dataCleanupDefaults) + { + _coreApiWrapperDao = coreApiWrapperDao; + _fundsToAccountDefaults = savingsMissingRequirementsDefaults.FundsToAccountDefaults; + _dataCleanupDefaults = dataCleanupDefaults; + } + + public async Task> GetVipSavingsToFund() + { + try + { + var accountNumbers = await _coreApiWrapperDao.GetVipSavingsToFund(); + return accountNumbers; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Get Vip Savings for Funding."); + throw; + } + } + + public async Task> GetAccountsByMajorMinorBranchAndStatus(AccountsByMajorMinorBranchAndStatusRequest request) + { + try + { + var response = await _coreApiWrapperDao.GetAccountsByMajorMinorBranchAndStatus(request); + return response; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Get Accounts by MajorMinorBranchAndStatus."); + throw; + } + } + + public async Task> GetAgreePersonsWithHyphenatedUserIds() + { + try + { + var response = await _coreApiWrapperDao.GetAgreePersonsWithHyphenatedUserIds(); + return response; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to get Agree Persons With Hyphenated UserIds"); + throw; + } + } + + public async Task> GetActiveCustodialAgreePersonNumbers() + { + try + { + var response = await _coreApiWrapperDao.GetActiveCustodialAgreePersonNumbers(); + return response; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to get active custodial agree person numbers"); + throw; + } + } + + public async Task> GetTransactionsExternalDescriptionsWithSsn() + { + try + { + var externalDescriptionList = await _coreApiWrapperDao.GetTransactionsExternalDescriptionsWithSsn(); + return externalDescriptionList; + + } + catch (Exception exception) + { + Log.Error(exception, "Failure to get Transactions External Descriptions with SSN"); + throw; + } + } + + public async Task> GetActiveCustodialVruCardAgreementAgreePersons() + { + try + { + var response = await _coreApiWrapperDao.GetActiveCustodialVruCardAgreementAgreePersons(); + return response; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Get Active Custodial Vru Card Agreement AgreePersons"); + throw; + } + } + + public async Task GetAgreementByUserId(string userId) + { + try + { + var response = await _coreApiWrapperDao.GetAgreementByUserId(userId); + return response; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure to Get Agreement by UserId, UserId: {userId}"); + return null; + } + } + + public async Task> GetPersonPostalAddressByPersonNumber(int personNumber) + { + try + { + var response = await _coreApiWrapperDao.GetPersonPostalAddressByPersonNumber(personNumber); + return response; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Get PersonPostalAddress by PersonNumber"); + throw; + } + } + + public async Task UpdateAddrLineByPersonNumber(PersonAddrLine ncoaRequest) + { + try + { + var response = await _coreApiWrapperDao.UpdateAddrLineByPersonNumber(ncoaRequest); + return response; + } + catch(Exception exception) + { + Log.Error("Failed to update AddrLine by PersonNumber"); + throw exception; + } + } + + public async Task>> GetCoreApiMessageAccessChannelPersons( + AccessChannelPersonsByPersonRequest request + ) + { + try + { + var response = await _coreApiWrapperDao.GetCoreApiMessageAccessChannelPersons(request); + return response; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to get Access Channel Person"); + throw; + } + } + + public async Task>> GetCoreApiMessageAccessChannelPersons( + AccessChannelPersonsByPersonRequest request, + List includes + ) + { + try + { + var response = await _coreApiWrapperDao.GetCoreApiMessageAccessChannelPersons(request, includes); + return response; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to get Access Channel Person with Includes"); + throw; + } + } + + public async Task UpdateAccessType(AccessTypeUpdateRequest request) + { + try + { + var response = await _coreApiWrapperDao.UpdateAccessType(request); + return response; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to update AccessType"); + throw; + } + } + + public async Task UpdateAccessChannelPersons(AccessChannelPerson request, long updateKey) + { + try + { + var response = await _coreApiWrapperDao.UpdateAccessChannelPersons(request, updateKey); + return response; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to update Access Channel Person"); + throw; + } + } + + public async Task UpdatePersonAgreementDetailTypes(PersonAgreementDetailTypeRequest request) + { + try + { + var response = await _coreApiWrapperDao.UpdatePersonAgreementDetailTypes(request); + return response; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Update Person Agreement Detail Types"); + throw; + } + } + + public async Task UpdateTransactionsExternalDescriptions(ExternalDescription request) + { + try + { + var response = await _coreApiWrapperDao.UpdateTransactionsExternalDescriptions(request); + return response; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Update Transactions External Descriptions"); + throw; + } + } + + public List BuildFundsToAccountRequests(string accountNumber, double fundAmount) + { + var listFundsRequest = new List() + { + new FundsToAccountRequest() + { + AccountNumber = long.Parse(_fundsToAccountDefaults.GLAccountNumber), + Description = _fundsToAccountDefaults.Description, + TransactionAmount = fundAmount * -1, + TransactionTypeCode = _fundsToAccountDefaults.TransactionTypeCodeGL, + FundRequests = BuildFundRequests((double)(fundAmount * -1)) + }, + + new FundsToAccountRequest() + { + AccountNumber = long.Parse(accountNumber), + Description = _fundsToAccountDefaults.Description, + TransactionAmount = fundAmount, + TransactionTypeCode = _fundsToAccountDefaults.TransactionTypeCodeDeposit, + FundRequests = BuildFundRequests((double)fundAmount) + } + }; + + return listFundsRequest; + } + + public List BuildFundsToAccountRequests(string accountNumber, string glAccountNumber, FundsToAccountDefaults fundsToAccountDefaults) + { + var listFundsRequest = new List() + { + new FundsToAccountRequest() + { + AccountNumber = long.Parse(glAccountNumber), + Description = fundsToAccountDefaults.Description, + TransactionAmount = fundsToAccountDefaults.FundsDefaults.FundAmount * -1, + TransactionTypeCode = _fundsToAccountDefaults.TransactionTypeCodeGL, + FundRequests = BuildFundRequests((double)(fundsToAccountDefaults.FundsDefaults.FundAmount * -1)) + }, + + new FundsToAccountRequest() + { + AccountNumber = long.Parse(accountNumber), + Description = _fundsToAccountDefaults.Description, + TransactionAmount = fundsToAccountDefaults.FundsDefaults.FundAmount, + TransactionTypeCode = _fundsToAccountDefaults.TransactionTypeCodeDeposit, + FundRequests = BuildFundRequests((double)fundsToAccountDefaults.FundsDefaults.FundAmount) + } + }; + + return listFundsRequest; + } + + public List BuildFundRequests(double fundAmount) + { + return new List() + { + new FundRequest() + { + ClearingCategoryCode = _fundsToAccountDefaults.FundsDefaults.ClearingCategoryCode, + FundAmount = fundAmount, + FundTypeCode = _fundsToAccountDefaults.FundsDefaults.FundTypeCode, + FundTypeDetailCode = _fundsToAccountDefaults.FundsDefaults.FundTypeDetailCode + } + }; + } + + public async Task> GetBranchCodeChangeAccountNumbers() + { + try + { + var accountNumbers = await _coreApiWrapperDao.GetBranchCodeChangeAccountNumbers(); + return accountNumbers; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Get Accounts for Branch Codes."); + throw; + } + } + + public async Task UpdateBranchCodesForAccountNumbers(string accountNumber, string branchCode) + { + try + { + var accountBranchCodeUpdateRequest = new AccountBranchUpdateRequest() + { + AccountNumber = long.Parse(accountNumber), + BranchOrganizationNumber = branchCode + }; + var basicResponse = await _coreApiWrapperDao.UpdateBranchCodesForAccountNumbers(accountBranchCodeUpdateRequest); + return basicResponse; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Update Account with Branch Code."); + throw; + } + } + + public async Task UpdateAccountLoanToValue(string accountNumber, double loanToValue) + { + try + { + var accountLtvUpdateRequest = new AccountLtvUpdateRequest() + { + AccountNumber = long.Parse(accountNumber), + LoanToValue = loanToValue + }; + var basicResponse = await _coreApiWrapperDao.UpdateAccountLoanToValue(accountLtvUpdateRequest); + return basicResponse; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Update Account Loan to Value."); + throw; + } + } + + public async Task> GetGroupUpdateForAnalysisAccountNumbers() + { + try + { + var accountNumbers = await _coreApiWrapperDao.GetGroupUpdateForAnalysisAccountNumbers(); + return accountNumbers; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Get Accounts for Group Update."); + throw; + } + } + + public async Task> GetAtmCheckHoldsForPersonNumbers(DateTime? resetStartDate, DateTime? resetEndDate, int? fetchSize) + { + try + { + var personsForUserFieldList = await _coreApiWrapperDao.GetAtmCheckHoldsForPersonNumbers(resetStartDate, resetEndDate, fetchSize); + return personsForUserFieldList; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Get Person for Atm Check Holds."); + throw; + } + } + + public async Task AddAtmCheckHoldsForPersonNumbers(int personNumber, string userFieldValue) + { + try + { + var request = new PersonUserFieldRequest() + { + PersonNumber = personNumber, + UserFieldCode = _dataCleanupDefaults.MemberCheckHoldsUserFieldCode, + Value = userFieldValue + }; + return await _coreApiWrapperDao.AddAtmCheckHoldsForPersonNumbers(request); + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Add Person for Atm Check Holds."); + throw; + } + } + + public async Task UpdateAtmCheckHoldsForPersonNumbers(int personNumber, string userFieldValue) + { + try + { + var request = new PersonUserFieldRequest() + { + PersonNumber = personNumber, + UserFieldCode = _dataCleanupDefaults.MemberCheckHoldsUserFieldCode, + Value = userFieldValue + }; + + return await _coreApiWrapperDao.UpdateAtmCheckHoldsForPersonNumbers(request); + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Add Person for Atm Check Holds."); + throw; + } + } + + public async Task UpdateAccountGroupForAnalysis(string accountNumber) + { + try + { + var accountGroupForAnalysisUpdateRequest = new AccountAnalysisGroupMaintenanceRequest() + { + AccountNumber = long.Parse(accountNumber), + IsGenerateAnalysisStatement = true, + IsPrintAnalysisStatement = true, + IsUseForServiceCharge = true + }; + var basicResponse = await _coreApiWrapperDao.UpdateAccountGroupForAnalysis(accountGroupForAnalysisUpdateRequest); + return basicResponse; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Update Account Group for Analysis."); + throw; + } + } + + public async Task CreatePersonAccount(CreatePersonAccountRequest request) + { + try + { + var basicResponse = await _coreApiWrapperDao.PostPersonAccount(request); + return basicResponse; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Update Missing Savings For Person."); + throw; + } + } + + public async Task CreateOrganizationAccount(CreateOrganizationAccountRequest request) + { + try + { + var json = JsonSerializer.Serialize(request); + var basicResponse = await _coreApiWrapperDao.PostOrganizationAccount(request); + return basicResponse; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Update Missing Savings For Org."); + throw; + } + } + + public async Task AddControllingPersonOrganizationMaintenance(OrganizationMaintenanceRequest request) + { + try + { + var basicResponse = await _coreApiWrapperDao.PutOrganizationMaintenanceRequest(request); + return basicResponse; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Add Controlling Person For Org Maintenance."); + throw; + } + } + + public async Task> PostFundsToAccount(List requests) + { + var basicResponse = await _coreApiWrapperDao.PostFundsToAccount(requests); + return basicResponse; + } + + public async Task> PostFundsToAccount(string accountNumber, double fundAmount) + { + try + { + var fundsToAccountRequests = BuildFundsToAccountRequests(accountNumber, fundAmount); + var response = await PostFundsToAccount(fundsToAccountRequests); + return response; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Post Funds to Account."); + throw; + } + } + + public async Task UpdateAccountNickname(long accountNumber, string accountDescription) + { + try + { + var request = new AccountNickNameUpdateRequest() + { + AccountNumber = accountNumber, + AccountDescription = accountDescription + }; + var basicResponse = await _coreApiWrapperDao.PutAccountNicknameUpdateRequest(request); + return basicResponse; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Update Account Nickname."); + throw; + } + } + + public async Task UpdateAccountCreditReportType(long accountNumber, string creditReportType) + { + try + { + var request = new AccountCreditReportTypeUpdateRequest() + { + AccountNumber = accountNumber, + CreditReportType = creditReportType + }; + var basicResponse = await _coreApiWrapperDao.UpdateAccountCreditReportType(request); + return basicResponse; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Update Account Credit Report Type."); + throw; + } + } + + public async Task GetPropertyNumber(PmiCancel pmiCancel) + { + try + { + if(pmiCancel == null) + { + Log.Error("PMI Cancel Object cannot be null"); + throw new Exception("PMI Cancel Object cannot be null"); + } + + var account = await GetPropertyNumber(pmiCancel.LoanId); + + if (account == null) + { + Log.Error("Account cannot be found"); + throw new Exception("Account cannot be found"); + } + var propertyInfo = await _coreApiWrapperDao.GetPropertyNumberByAccountNumber(pmiCancel.LoanId); + var propInfo = propertyInfo.ToList(); + var pmiCancelResponse = new PmiCancel() + { + PropertyNumber = propInfo[0].PropertyNumber, + CurrentStatusCode = account.CurrentAccountStatusCode, + CurrentStatus = account.CurrentAccountStatusDescription, + }; + return pmiCancelResponse; + } + catch(Exception exception) + { + Log.Error(exception, "Failure to get Property Information for PMI Cancel"); + throw; + } + } + + public async Task GetPropertyNumber(long accountNumber) + { + return await _coreApiWrapperDao.GetAccountByAccountNumber(accountNumber); + } + + public async Task AddAccountPmiCancel(PmiCancel pmiCancel) + { + try + { + var propertyUserField = new PropertyUserField() + { + PropertyNumber = pmiCancel.PropertyNumber, + UserFieldCode = "PMIU", + Value = pmiCancel.LTVCancelDate + }; + var basicResponse = await _coreApiWrapperDao.PostPropertyUserField(propertyUserField); + return basicResponse; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Add Account PMI Cancel Date"); + throw; + } + } + + public async Task UpdateAccountPmiCancel(PmiCancel pmiCancel) + { + try + { + var propertyUserField = new PropertyUserField() + { + PropertyNumber = pmiCancel.PropertyNumber, + UserFieldCode = "PMIU", + Value = pmiCancel.LTVCancelDate + }; + var basicResponse = await _coreApiWrapperDao.PutPropertyUserField(propertyUserField); + return basicResponse; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to Update Account PMI Cancel Date"); + throw; + } + } + + public async Task> GetPropertyUserField(long propertyNumber) + { + try + { + var result = await _coreApiWrapperDao.GetPropertyUserField(propertyNumber); + return result; + } + catch (Exception exception) + { + Log.Error(exception, "Failure to find Person User Field"); + throw; + } + } + + public async Task> GetAccountUserField(long accountNumber) + { + try + { + var response = await _coreApiWrapperDao.GetAccountUserField(accountNumber); + return response; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure to Get Account User Field Code for {accountNumber}"); + throw; + } + } + + public async Task> AddAccountUserField(long accountNumber, string userFieldCode, string value) + { + try + { + var accountUserField = new List() + { + new AccountUserField() + { + AccountNumber = accountNumber, + UserFieldCode = userFieldCode, + Value = value + } + }; + var response = await _coreApiWrapperDao.PostAccountUserField(accountUserField); + return response; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure to Add Account User Field {userFieldCode} for {accountNumber}"); + throw; + } + } + + public async Task> UpdateAccountUserField(long accountNumber, string userFieldCode, string value) + { + try + { + var accountUserField = new List() + { + new AccountUserField() + { + AccountNumber = accountNumber, + UserFieldCode = userFieldCode, + Value = value + } + }; + var response = await _coreApiWrapperDao.PutAccountUserField(accountUserField); + return response; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure to Update Account User Field {userFieldCode} for {accountNumber}"); + throw; + } + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/DataCleanUpService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/DataCleanUpService.cs new file mode 100644 index 0000000..8e29e35 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/DataCleanUpService.cs @@ -0,0 +1,109 @@ +using Serilog; +using Newtonsoft.Json; +using LCU.Library.Internal.DataCleanUpModel.Enum; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Library.Internal.ApiResponse.Services; +using LCU.Api.Internal.MaidBotLib.Models; + +namespace LCU.Api.Internal.DataCleanUp.Services; + +public class DataCleanUpService : IDataCleanUpService +{ + private readonly IHyphenatedUserIdCleanUpService _hyphenatedUserIdCleanUpService; + private readonly IDeactivateCustodialEAgreementsService _deactivateCustodialEAgreementsService; + private readonly ICloseCustodialVruAgreementsService _closeCustodialVruAgreementsService; + private readonly IMaskTransactionExternalDescriptionWithSsnService _maskTransactionExternalDescriptionWithSsnService; + private readonly IAddFundsToVipSavingsAccountsService _addFundsToVipSavingsAccountsService; + private readonly IBatchAddFundsToVipSavingsAccountsService _batchAddFundsToVipSavingsAccountsService; + private readonly IUpdateAdminBranchCodesByAccountNumberService _updateAdminBranchCodesByAccountNumberService; + private readonly IUpdateAccountLoanToValueService _updateAccountLoanToValueService; + private readonly IUpdateAccountGroupForAnalysisService _updateAccountGroupForAnalysisService; + private readonly IUpdatePersonForAtmHoldsService _updatePersonForAtmHoldsService; + private readonly IUpdateMissingBatchSavingsService _updateMissingBatchSavingsService; + private readonly IUpdateAccountNicknameService _updateAccountNicknameService; + private readonly IUpdateNcoaProcessService _updateNcoaProcessService; + private readonly IUpdateAccountCreditReportTypeService _updateAccountCreditReportTypeService; + private readonly IUpdateAccountPmiCancelService _updateAccountPmiCancelService; + private readonly IUpdateFannieMaeMortgageService _updateFannieMaeMortgageService; + private readonly IAddFundsToIndirectSavingsAccountsService _addFundsToIndirectSavingsAccountsService; + + public DataCleanUpService(IHyphenatedUserIdCleanUpService hyphenatedUserIdCleanUpService, + IDeactivateCustodialEAgreementsService deactivateCustodialEAgreementsService, + ICloseCustodialVruAgreementsService closeCustodialVruAgreementsService, + IMaskTransactionExternalDescriptionWithSsnService maskTransactionExternalDescriptionWithSsnService, + IAddFundsToVipSavingsAccountsService addFundsToVipSavingsAccountsService, + IBatchAddFundsToVipSavingsAccountsService batchAddFundsToVipSavingsAccountsService, + IUpdateAdminBranchCodesByAccountNumberService updateAdminBranchCodesByAccountNumberService, + IUpdateAccountLoanToValueService updateAccountLoanToValueService, + IUpdateAccountGroupForAnalysisService updateAccountGroupForAnalysisService, + IUpdatePersonForAtmHoldsService updatePersonForAtmHoldsService, + IUpdateMissingBatchSavingsService updateMissingBatchSavingsService, + IUpdateAccountNicknameService updateAccountNicknameService, + IUpdateNcoaProcessService updateNcoaProcessService, + IUpdateAccountCreditReportTypeService updateAccountCreditReportTypeService, + IUpdateAccountPmiCancelService updateAccountPmiCancelService, + IUpdateFannieMaeMortgageService updateFannieMaeMortgageService, + IAddFundsToIndirectSavingsAccountsService addFundsToIndirectSavingsAccountsService) + + { + _hyphenatedUserIdCleanUpService = hyphenatedUserIdCleanUpService; + _deactivateCustodialEAgreementsService = deactivateCustodialEAgreementsService; + _closeCustodialVruAgreementsService = closeCustodialVruAgreementsService; + _maskTransactionExternalDescriptionWithSsnService = maskTransactionExternalDescriptionWithSsnService; + _addFundsToVipSavingsAccountsService = addFundsToVipSavingsAccountsService; + _batchAddFundsToVipSavingsAccountsService = batchAddFundsToVipSavingsAccountsService; + _updateAdminBranchCodesByAccountNumberService = updateAdminBranchCodesByAccountNumberService; + _updateAccountLoanToValueService = updateAccountLoanToValueService; + _updateAccountGroupForAnalysisService = updateAccountGroupForAnalysisService; + _updatePersonForAtmHoldsService = updatePersonForAtmHoldsService; + _updateMissingBatchSavingsService = updateMissingBatchSavingsService; + _updateAccountNicknameService = updateAccountNicknameService; + _updateAccountPmiCancelService = updateAccountPmiCancelService; + _updateNcoaProcessService = updateNcoaProcessService; + _updateAccountCreditReportTypeService = updateAccountCreditReportTypeService; + _updateFannieMaeMortgageService = updateFannieMaeMortgageService; + _addFundsToIndirectSavingsAccountsService = addFundsToIndirectSavingsAccountsService; + } + + public void DetermineCleanUp(DataCleanUpRequest request) + { + try + { + var result = request.CleanUpType switch + { + CleanUpTypes.HyphenatedUserId => _hyphenatedUserIdCleanUpService.CleanUp(request).Result, + CleanUpTypes.DeactivateCustodialEAgreements => _deactivateCustodialEAgreementsService.CleanUp(request).Result, + CleanUpTypes.CloseCustodialVruAgreements => _closeCustodialVruAgreementsService.CleanUp(request).Result, + CleanUpTypes.MaskTransactionExternalDescriptionWithSsn => _maskTransactionExternalDescriptionWithSsnService.CleanUp(request).Result, + CleanUpTypes.AddFundsToVipSavingsAccounts => _addFundsToVipSavingsAccountsService.CleanUp(request).Result, + CleanUpTypes.BatchAddFundsToVipSavingsAccounts => _batchAddFundsToVipSavingsAccountsService.CleanUp(request).Result, + CleanUpTypes.UpdateAdminBranchCodesByAccountNumber => _updateAdminBranchCodesByAccountNumberService.CleanUp(request).Result, + CleanUpTypes.UpdateAccountLoanToValue => _updateAccountLoanToValueService.CleanUp(request).Result, + CleanUpTypes.UpdateAccountGroupForAnalysis => _updateAccountGroupForAnalysisService.CleanUp(request).Result, + CleanUpTypes.UpdatePersonForCheckHolds => _updatePersonForAtmHoldsService.CleanUp(request).Result, + CleanUpTypes.UpdateMissingBatchSavings => _updateMissingBatchSavingsService.CleanUp(request).Result, + CleanUpTypes.UpdateAccountNickname => _updateAccountNicknameService.CleanUp(request).Result, + CleanUpTypes.UpdateNcoaProcess => _updateNcoaProcessService.CleanUp(request).Result, + CleanUpTypes.UpdateAccountCreditReportType => _updateAccountCreditReportTypeService.CleanUp(request).Result, + CleanUpTypes.UpdateAccountPmiCancel => _updateAccountPmiCancelService.CleanUp(request).Result, + CleanUpTypes.UpdateFannieMaeMortgage => _updateFannieMaeMortgageService.CleanUp(request).Result, + CleanUpTypes.AddFundsToIndirectSavingsAccounts => _addFundsToIndirectSavingsAccountsService.CleanUp(request).Result, + _ => throw new Exception("Error while Determining CleanUp") + }; + + ArgumentNullException.ThrowIfNull(result); + if (!result.Successful) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error($"Error while processing a Data Cleanup. Errors: {JsonConvert.SerializeObject(result.ResponseStack)}"); + } + + QueueReturnResponse.QueueResponse(request, result.Successful, result.ResponseStack); + } + catch (Exception exception) + { + Log.Error(exception, "Failure in DeterminCleanUp"); + } + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/DeactivateCustodialEAgreementsService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/DeactivateCustodialEAgreementsService.cs new file mode 100644 index 0000000..29e8f0e --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/DeactivateCustodialEAgreementsService.cs @@ -0,0 +1,134 @@ +using Serilog; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; +using LCU.Library.Internal.CoreApiWrapperModel.Constants; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessChannelPersons; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessTypes; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels; + +namespace LCU.Api.Internal.DataCleanUp.Services; + +public class DeactivateCustodialEAgreementsService : IDeactivateCustodialEAgreementsService +{ + private readonly ICoreApiWrapperService _coreApiWrapperService; + private const string AccessTypeEAgreeementId = "WWW"; + + public DeactivateCustodialEAgreementsService(ICoreApiWrapperService coreApiWrapperService) + { + _coreApiWrapperService = coreApiWrapperService; + } + + public async Task CleanUp(DataCleanUpRequest dataCleanUpRequest) + { + Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List()); + + try + { + var activeCustodialAgreePersonNumbers = await _coreApiWrapperService.GetActiveCustodialAgreePersonNumbers(); + foreach (var personNumber in activeCustodialAgreePersonNumbers) + { + cleanUpResult = await HandleUpdateDeactivateCustodialEAgreement(cleanUpResult, personNumber); + } + } + catch (Exception exception) + { + Log.Error(exception, "Error while Deactivate Custodial Agreement CleanUp."); + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while Deactivate Custodial EAgreement CleanUp. " + + $"Exception:{exception}"); + } + + Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + return cleanUpResult; + } + + public async Task HandleUpdateDeactivateCustodialEAgreement(DataCleanUpResult cleanUpResult, string personNumber) + { + try + { + var accessTypeUpdateRequest = await SetUpAccessTypeUpdateRequest(personNumber); + if (accessTypeUpdateRequest != null) + { + + var updatedAccessType = await _coreApiWrapperService.UpdateAccessType(accessTypeUpdateRequest); + ArgumentNullException.ThrowIfNull(updatedAccessType); + + if (updatedAccessType.IsActive) + { + throw new Exception($"AccessType has not been updated. Expected False but IsActive was true. " + + $"PersonNumber: {personNumber}"); + } + } + } + catch (Exception exception) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Failure to Deactivate Custodial EAgreement. " + + $"PersonNumber:{personNumber} " + + $"Exception Message:{exception.Message}"); + } + + return cleanUpResult; + } + + public async Task SetUpAccessTypeUpdateRequest(string personNumber) + { + var coreApiMessage = await GetAccessChannelPersons(personNumber); + ArgumentNullException.ThrowIfNull(coreApiMessage.MessageBody); + + var accessChannelPersons = coreApiMessage.MessageBody.ToList(); + ArgumentNullException.ThrowIfNull(coreApiMessage?.MessageHeader?.UpdateKey); + + AccessChannelPerson? accessChannelPerson = null; + AccessType? accessType = null; + foreach (var channelPerson in accessChannelPersons.ToList()) + { + if (channelPerson.AccessTypes != null && channelPerson.AccessTypes.Any(accessType => accessType.Id == AccessTypeEAgreeementId && accessType.IsActive == true)) + { + accessChannelPerson = channelPerson; + accessType = channelPerson.AccessTypes.FirstOrDefault(accessType => accessType.Id == AccessTypeEAgreeementId && accessType.IsActive == true); + } + } + + if (accessType == null || accessChannelPerson == null) + { + return null; + } + + accessType.IsActive = false; + accessType.UserId = null; + var accessTypeUpdateRequest = new AccessTypeUpdateRequest() + { + AccessType = accessType, + AccessChannelPersonId = accessChannelPerson.Id, + UpdateKey = (long)coreApiMessage.MessageHeader.UpdateKey + }; + + return accessTypeUpdateRequest; +} + +public async Task>> GetAccessChannelPersons(string personNumber) + { + long parsedPersonNumber; + if (!long.TryParse(personNumber, out parsedPersonNumber)) + { + throw new Exception($"Person number was not able to be parsed to long. " + + $"PersonNumber:{personNumber}"); + } + + var request = new AccessChannelPersonsByPersonRequest() + { + PersonNumber = parsedPersonNumber, + ActiveOnly = true, + IncludeCards = false + }; + var includes = new List() + { + RequestIncludeConstants.AccessTypes + }; + var coreApiMessage = await _coreApiWrapperService.GetCoreApiMessageAccessChannelPersons(request, includes); + + return coreApiMessage; + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/Emailers/INotificationsApiService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/Emailers/INotificationsApiService.cs new file mode 100644 index 0000000..7b1bc8a --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/Emailers/INotificationsApiService.cs @@ -0,0 +1,6 @@ +namespace LCU.Api.Internal.DataCleanUp.Services.Emailers; + +public interface INotificationsApiService +{ + bool SendEmail(List emailRecipients, string subject, string emailText); +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/Emailers/NotificationsApiService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/Emailers/NotificationsApiService.cs new file mode 100644 index 0000000..1002744 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/Emailers/NotificationsApiService.cs @@ -0,0 +1,48 @@ +using LCU.Api.Internal.DataCleanUp.Configuration; +using LCU.Api.Internal.DataCleanUp.DataAccess; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.Library.Internal.NotificationsModels.Models; +using Newtonsoft.Json; +using Serilog; +using System.Text; + +namespace LCU.Api.Internal.DataCleanUp.Services.Emailers; + +public class NotificationsApiService : INotificationsApiService +{ + private readonly NotificationsApiConfiguration _notificationsApiConfiguration; + private readonly INotificationsDao _notificationsDao; + + public NotificationsApiService(NotificationsApiConfiguration emailConfiguration, INotificationsDao notificationsDao) + { + _notificationsApiConfiguration = emailConfiguration; + _notificationsDao = notificationsDao; + } + + public bool SendEmail(List emailRecipients, string subject, string emailText) + { + try + { + var emailRequest = new EmailRequest + { + Recipient = emailRecipients, + Subject = subject, + Body = emailText + }; + + var httpResponse = _notificationsDao.SendEmail(emailRequest); + + httpResponse.EnsureSuccessStatusCode(); + } + catch (Exception ex) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error(ex, $"An exception was caught trying to send an email via Notifications API. Email Subject: {subject}"); + + return false; + } + + return true; + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/FileOperationsService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/FileOperationsService.cs new file mode 100644 index 0000000..19a60bb --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/FileOperationsService.cs @@ -0,0 +1,87 @@ +using LCU.Api.Internal.DataCleanUp.Configuration; +using LCU.Api.Internal.DataCleanUp.DataAccess; +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.Library.Internal.DataCleanUpModel.Models; + +namespace LCU.Api.Internal.DataCleanUp.Services; + +public class FileOperationsService : IFileOperationsService +{ + private readonly IFileOperationsDao _fileOperationsDao; + private readonly FileOperationsConfiguration _fileOperationsConfiguration; + + public FileOperationsService(IFileOperationsDao fileOperationsDao, + FileOperationsConfiguration fileOperationsConfiguration) + { + _fileOperationsDao = fileOperationsDao; + _fileOperationsConfiguration = fileOperationsConfiguration; + } + + public async Task GetContentData(string filePath) + { + try + { + var filename = filePath.Replace("\\", "%5C"); + var finalFilePath = new string($"{_fileOperationsConfiguration.GetFile}{filename}"); + + var response = await _fileOperationsDao.GetFileContent(finalFilePath); + return response; + } + catch (Exception exception) + { + throw new Exception($"Get Content Data Error, {exception.Message}"); + } + } + + public async Task> WriteFile(WriteFileRequest request) + { + try + { + var response = await _fileOperationsDao.WriteFile(request); + return response; + } + catch (Exception exception) + { + throw new Exception($"Write File Error, {exception.Message}"); + } + } + + public Task> BuildDynamicFileList(DynamicFileListRequest request) + { + try + { + var files = _fileOperationsDao.BuildDynamicFileList(request); + return files; + } + catch (Exception exception) + { + throw new Exception($"BuildDynamicFileList Error: {exception.Message}"); + } + } + + public DynamicFileListRequest BuildDynamicFileListRequest(NcoaUpdateRequest ncoaProcessRequest) + { + + var request = new DynamicFileListRequest() + { + Path = ncoaProcessRequest.SourcePath, + Filename = ncoaProcessRequest.Filename, + DynamicFileSettings = ncoaProcessRequest.DynamicFileSettings, + }; + + return request; + } + + public DynamicFileListRequest BuildDynamicFileListRequest(FannieMaeMortgageRequest fannieMaeMortgageRequest) + { + + var request = new DynamicFileListRequest() + { + Path = fannieMaeMortgageRequest.SourcePath, + Filename = fannieMaeMortgageRequest.Filename, + DynamicFileSettings = fannieMaeMortgageRequest.DynamicFileSettings, + }; + + return request; + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/HyphenatedUserIdCleanUpService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/HyphenatedUserIdCleanUpService.cs new file mode 100644 index 0000000..6645a09 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/HyphenatedUserIdCleanUpService.cs @@ -0,0 +1,95 @@ +using Serilog; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessChannelPersons; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements; +using LCU.Api.Internal.DataCleanUp.DataAccess; +namespace LCU.Api.Internal.DataCleanUp.Services; + +public class HyphenatedUserIdCleanUpService : IHyphenatedUserIdCleanUpService +{ + private readonly ICoreApiWrapperService _coreApiWrapperService; + private const string HyphenReplacement = "C"; + + public HyphenatedUserIdCleanUpService(ICoreApiWrapperService coreApiWrapperService) + { + _coreApiWrapperService = coreApiWrapperService; + } + + public async Task CleanUp(DataCleanUpRequest dataCleanUpRequest) + { + Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List()); + + try + { + var agreePersonsWithHyphenatedUserIds = await _coreApiWrapperService.GetAgreePersonsWithHyphenatedUserIds(); + foreach (var agreePerson in agreePersonsWithHyphenatedUserIds) + { + cleanUpResult = await HandleUpdateOfHyphenatedUserId(cleanUpResult, agreePerson); + } + } + catch (Exception exception) + { + Log.Error(exception, "Error while Hyphenated UserId CleanUp."); + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while Hyphenated UserId CleanUp. Exception:{exception}"); + } + + Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + return cleanUpResult; + } + + public async Task HandleUpdateOfHyphenatedUserId(DataCleanUpResult cleanUpResult, AgreePerson agreePerson) + { + try + { + var accessChannelPersonUpdateDetails = await DetermineAccessChannelPersonUpdateDetails(agreePerson); + + var newUserId = accessChannelPersonUpdateDetails.accessChannelPerson.UserId.Replace("-", HyphenReplacement); + accessChannelPersonUpdateDetails.accessChannelPerson.UserId = newUserId; + var updatedAccessChannelPerson = await _coreApiWrapperService + .UpdateAccessChannelPersons(accessChannelPersonUpdateDetails.accessChannelPerson, + accessChannelPersonUpdateDetails.updateKey); + + ArgumentNullException.ThrowIfNull(updatedAccessChannelPerson); + if (updatedAccessChannelPerson.UserId != newUserId) + { + throw new Exception($"UserId has not been updated. " + + $"Expected UserId:{newUserId}, " + + $"Returned UserId:{updatedAccessChannelPerson.UserId}"); + } + } + catch (Exception exception) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Failure to Update HyphenatedUserId. " + + $"PersonNumber:{agreePerson.PersonNumber} " + + $"UserId:{agreePerson.UserId}" + + $"Exception Message:{exception.Message}"); + } + + return cleanUpResult; + } + + public async Task<(AccessChannelPerson accessChannelPerson, long updateKey)> DetermineAccessChannelPersonUpdateDetails(AgreePerson agreePerson) + { + var request = new AccessChannelPersonsByPersonRequest() + { + PersonNumber = agreePerson.PersonNumber, + ActiveOnly = true, + IncludeCards = false + }; + var coreApiMessage = await _coreApiWrapperService.GetCoreApiMessageAccessChannelPersons(request); + + ArgumentNullException.ThrowIfNull(coreApiMessage?.MessageHeader?.UpdateKey); + ArgumentNullException.ThrowIfNull(coreApiMessage.MessageBody); + var accessChannelPersons = coreApiMessage.MessageBody; + var accessChannelWithHyphenatedUserId = accessChannelPersons.FirstOrDefault(accessChannelPerson => + accessChannelPerson.PersonNumber == agreePerson.PersonNumber && + accessChannelPerson.UserId == agreePerson.UserId); + + ArgumentNullException.ThrowIfNull(accessChannelWithHyphenatedUserId); + return (accessChannelWithHyphenatedUserId, (long)coreApiMessage.MessageHeader.UpdateKey); + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IAddFundsToIndirectSavingsAccountsService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IAddFundsToIndirectSavingsAccountsService.cs new file mode 100644 index 0000000..c5db49f --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IAddFundsToIndirectSavingsAccountsService.cs @@ -0,0 +1,6 @@ +using LCU.Library.Internal.DataCleanUpModel.Models; +namespace LCU.Api.Internal.DataCleanUp.Services; +public interface IAddFundsToIndirectSavingsAccountsService +{ + Task CleanUp(DataCleanUpRequest dataCleanUpRequest); +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IAddFundsToVipSavingsAccountsService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IAddFundsToVipSavingsAccountsService.cs new file mode 100644 index 0000000..4ebdb42 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IAddFundsToVipSavingsAccountsService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.DataCleanUpModel.Models; +namespace LCU.Api.Internal.DataCleanUp.Services; + +public interface IAddFundsToVipSavingsAccountsService +{ + Task CleanUp(DataCleanUpRequest dataCleanUpRequest); +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IBatchAddFundsToVipSavingsAccountsService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IBatchAddFundsToVipSavingsAccountsService.cs new file mode 100644 index 0000000..7f998b3 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IBatchAddFundsToVipSavingsAccountsService.cs @@ -0,0 +1,6 @@ +using LCU.Library.Internal.DataCleanUpModel.Models; +namespace LCU.Api.Internal.DataCleanUp.Services; +public interface IBatchAddFundsToVipSavingsAccountsService +{ + Task CleanUp(DataCleanUpRequest dataCleanUpRequest); +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/ICloseCustodialVruAgreementsService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/ICloseCustodialVruAgreementsService.cs new file mode 100644 index 0000000..8c82894 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/ICloseCustodialVruAgreementsService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.DataCleanUpModel.Models; +namespace LCU.Api.Internal.DataCleanUp.Services; + +public interface ICloseCustodialVruAgreementsService +{ + Task CleanUp(DataCleanUpRequest dataCleanUpRequest); +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/ICoreApiWrapperService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/ICoreApiWrapperService.cs new file mode 100644 index 0000000..203f0fe --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/ICoreApiWrapperService.cs @@ -0,0 +1,63 @@ +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessChannelPersons; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessTypes; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapRequests; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Persons; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Transaction; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapResponses; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.PostalAddresses; +using LCU.Api.Internal.DataCleanUp.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Properties; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts; +using LCU.Api.Internal.DataCleanUp.Configuration; + +namespace LCU.Api.Internal.DataCleanUp.Services; + +public interface ICoreApiWrapperService +{ + public Task> GetVipSavingsToFund(); + public Task> GetAgreePersonsWithHyphenatedUserIds(); + public Task> GetActiveCustodialAgreePersonNumbers(); + Task>> GetCoreApiMessageAccessChannelPersons( + AccessChannelPersonsByPersonRequest request); + Task>> GetCoreApiMessageAccessChannelPersons( + AccessChannelPersonsByPersonRequest request, List includes); + public Task> GetTransactionsExternalDescriptionsWithSsn(); + Task> GetActiveCustodialVruCardAgreementAgreePersons(); + public Task> GetBranchCodeChangeAccountNumbers(); + public Task> GetGroupUpdateForAnalysisAccountNumbers(); + public Task> GetAtmCheckHoldsForPersonNumbers(DateTime? resetStartDate, DateTime? resetEndDate, int? fetchSize); + public Task GetAgreementByUserId(string userId); + public Task> GetPersonPostalAddressByPersonNumber(int personNumber); + public Task> GetAccountsByMajorMinorBranchAndStatus(AccountsByMajorMinorBranchAndStatusRequest request); + public Task UpdateAddrLineByPersonNumber(PersonAddrLine ncoaRequest); + public Task UpdateAccessChannelPersons(AccessChannelPerson request, long updateKey); + public Task UpdateAccessType(AccessTypeUpdateRequest request); + public Task UpdateBranchCodesForAccountNumbers(string accountNumber, string branchCode); + public Task UpdateAccountLoanToValue(string accountNumber, double loanToValue); + public Task UpdateAccountGroupForAnalysis(string accountNumber); + public Task AddAtmCheckHoldsForPersonNumbers(int personNumber, string userFieldValue); + public Task UpdateAtmCheckHoldsForPersonNumbers(int personNumber, string userFieldValue); + public Task UpdateTransactionsExternalDescriptions(ExternalDescription request); + public Task UpdatePersonAgreementDetailTypes(PersonAgreementDetailTypeRequest request); + public Task CreatePersonAccount(CreatePersonAccountRequest request); + public Task CreateOrganizationAccount(CreateOrganizationAccountRequest request); + public Task AddControllingPersonOrganizationMaintenance(OrganizationMaintenanceRequest request); + public Task> PostFundsToAccount(string accountNumber, double fundAmount); + public Task> PostFundsToAccount(List requests); + public List BuildFundsToAccountRequests(string accountNumber, string glAccountNumber, FundsToAccountDefaults fundsToAccountDefaults); + public Task UpdateAccountNickname(long accountNumber, string accountDescription); + public Task GetPropertyNumber(PmiCancel pmiCancel); + public Task AddAccountPmiCancel(PmiCancel pmiCancel); + Task UpdateAccountPmiCancel(PmiCancel pmiCancel); + public Task> GetPropertyUserField(long propertyNumber); + public Task UpdateAccountCreditReportType(long accountNumber, string creditReportType); + public Task> GetAccountUserField(long accountNumber); + public Task> AddAccountUserField(long accountNumber, string userFieldCode, string value); + public Task> UpdateAccountUserField(long accountNumber, string userFieldCode, string value); +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IDataCleanUpService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IDataCleanUpService.cs new file mode 100644 index 0000000..c64a0da --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IDataCleanUpService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.DataCleanUpModel.Models; +namespace LCU.Api.Internal.DataCleanUp.Services; + +public interface IDataCleanUpService +{ + void DetermineCleanUp(DataCleanUpRequest request); +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IDeactivateCustodialEAgreementsService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IDeactivateCustodialEAgreementsService.cs new file mode 100644 index 0000000..7456c33 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IDeactivateCustodialEAgreementsService.cs @@ -0,0 +1,13 @@ +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessChannelPersons; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; +using LCU.Library.Internal.DataCleanUpModel.Models; +namespace LCU.Api.Internal.DataCleanUp.Services; + +public interface IDeactivateCustodialEAgreementsService +{ + Task CleanUp(DataCleanUpRequest dataCleanUpRequest); + Task HandleUpdateDeactivateCustodialEAgreement(DataCleanUpResult cleanUpResult, string personNumber); + Task SetUpAccessTypeUpdateRequest(string personNumber); + Task>> GetAccessChannelPersons(string personNumber); +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IFileOperationsService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IFileOperationsService.cs new file mode 100644 index 0000000..4f7b10c --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IFileOperationsService.cs @@ -0,0 +1,13 @@ +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.Library.Internal.DataCleanUpModel.Models; + +namespace LCU.Api.Internal.DataCleanUp.Services; + +public interface IFileOperationsService +{ + public Task GetContentData(string finalFilePath); + public Task> WriteFile(WriteFileRequest request); + public Task> BuildDynamicFileList(DynamicFileListRequest request); + public DynamicFileListRequest BuildDynamicFileListRequest(NcoaUpdateRequest ncoaProcessRequest); + public DynamicFileListRequest BuildDynamicFileListRequest(FannieMaeMortgageRequest fanniMaeMortgageRequest); +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IHyphenatedUserIdCleanUpService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IHyphenatedUserIdCleanUpService.cs new file mode 100644 index 0000000..d43bad1 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IHyphenatedUserIdCleanUpService.cs @@ -0,0 +1,11 @@ +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessChannelPersons; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements; +using LCU.Library.Internal.DataCleanUpModel.Models; +namespace LCU.Api.Internal.DataCleanUp.Services; + +public interface IHyphenatedUserIdCleanUpService +{ + Task CleanUp(DataCleanUpRequest dataCleanUpRequest); + Task HandleUpdateOfHyphenatedUserId(DataCleanUpResult cleanUpResult, AgreePerson agreePerson); + Task<(AccessChannelPerson accessChannelPerson, long updateKey)> DetermineAccessChannelPersonUpdateDetails(AgreePerson agreePerson); +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IMaskTransactionExternalDescriptionWithSsnService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IMaskTransactionExternalDescriptionWithSsnService.cs new file mode 100644 index 0000000..c8c6123 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IMaskTransactionExternalDescriptionWithSsnService.cs @@ -0,0 +1,8 @@ +using LCU.Library.Internal.DataCleanUpModel.Models; +namespace LCU.Api.Internal.DataCleanUp.Services; + +public interface IMaskTransactionExternalDescriptionWithSsnService +{ + Task CleanUp(DataCleanUpRequest dataCleanUpRequest); + string MaskSsn(string descriptionWithSsn); +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IQueueDataCleanUpService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IQueueDataCleanUpService.cs new file mode 100644 index 0000000..5929752 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IQueueDataCleanUpService.cs @@ -0,0 +1,23 @@ +using LCU.Library.Internal.ApiResponse.Models; +using LCU.Library.Internal.DataCleanUpModel.Enum; +using LCU.Library.Internal.DataCleanUpModel.Models; + +namespace LCU.Api.Internal.DataCleanUp.Services; + +public interface IQueueDataCleanUpService +{ + Task QueueDataCleanUp(DataCleanUpRequest dataCleanUpRequest); + Task QueueDataCleanUpWithPayload(TRequest request, CleanUpTypes cleanUpType) where TRequest : ReturnResponse; + Task QueueHyphenatedUserIdCleanUp(); + Task QueueDeactivateCustodialEAgreements(); + Task QueueCloseCustodialVruAgreements(); + Task QueueMaskTransactionExternalDescriptionWithSsn(); + Task QueueAddFundsToVipSavingsAccounts(); + Task QueueBatchAddFundsToVipSavingsAccounts(); + Task QueueUpdateAdminBranchCodesByAccountNumber(); + Task QueueUpdateAccountLoanToValue(); + Task QueueUpdateAccountGroupForAnalysis(); + Task QueueUpdateAccountNickname(); + Task QueueUpdateAccountCreditReportType(); + Task QueuePmiCancelUpdate(); +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAccountCreditReportTypeService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAccountCreditReportTypeService.cs new file mode 100644 index 0000000..8c155a2 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAccountCreditReportTypeService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.DataCleanUpModel.Models; +namespace LCU.Api.Internal.DataCleanUp.Services; + +public interface IUpdateAccountCreditReportTypeService +{ + Task CleanUp(DataCleanUpRequest dataCleanUpRequest); +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAccountGroupForAnalysisService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAccountGroupForAnalysisService.cs new file mode 100644 index 0000000..26302df --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAccountGroupForAnalysisService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.DataCleanUpModel.Models; +namespace LCU.Api.Internal.DataCleanUp.Services; + +public interface IUpdateAccountGroupForAnalysisService +{ + Task CleanUp(DataCleanUpRequest dataCleanUpRequest); +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAccountLoanToValueService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAccountLoanToValueService.cs new file mode 100644 index 0000000..be064d5 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAccountLoanToValueService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.DataCleanUpModel.Models; +namespace LCU.Api.Internal.DataCleanUp.Services; + +public interface IUpdateAccountLoanToValueService +{ + Task CleanUp(DataCleanUpRequest dataCleanUpRequest); +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAccountNicknameService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAccountNicknameService.cs new file mode 100644 index 0000000..f0edae5 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAccountNicknameService.cs @@ -0,0 +1,11 @@ + +using LCU.Library.Internal.DataCleanUpModel.Models; + +namespace LCU.Api.Internal.DataCleanUp.Services +{ + public interface IUpdateAccountNicknameService + { + Task CleanUp(DataCleanUpRequest dataCleanUpRequest); + + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAccountPmiCancelService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAccountPmiCancelService.cs new file mode 100644 index 0000000..f5e1c0e --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAccountPmiCancelService.cs @@ -0,0 +1,9 @@ +using LCU.Library.Internal.DataCleanUpModel.Models; + +namespace LCU.Api.Internal.DataCleanUp.Services +{ + public interface IUpdateAccountPmiCancelService + { + Task CleanUp(DataCleanUpRequest dataCleanUpRequest); + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAdminBranchCodesByAccountNumberService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAdminBranchCodesByAccountNumberService.cs new file mode 100644 index 0000000..3c7ec41 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateAdminBranchCodesByAccountNumberService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.DataCleanUpModel.Models; +namespace LCU.Api.Internal.DataCleanUp.Services; + +public interface IUpdateAdminBranchCodesByAccountNumberService +{ + Task CleanUp(DataCleanUpRequest dataCleanUpRequest); +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateFannieMaeMortgageService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateFannieMaeMortgageService.cs new file mode 100644 index 0000000..bffb346 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateFannieMaeMortgageService.cs @@ -0,0 +1,8 @@ +using LCU.Library.Internal.DataCleanUpModel.Models; + +namespace LCU.Api.Internal.DataCleanUp.Services; + +public interface IUpdateFannieMaeMortgageService +{ + Task CleanUp(DataCleanUpRequest dataCleanUpRequest); +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateMissingBatchSavingsService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateMissingBatchSavingsService.cs new file mode 100644 index 0000000..4d7ff6c --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateMissingBatchSavingsService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.DataCleanUpModel.Models; +namespace LCU.Api.Internal.DataCleanUp.Services; + +public interface IUpdateMissingBatchSavingsService +{ + Task CleanUp(DataCleanUpRequest dataCleanUpRequest); +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateNcoaProcessService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateNcoaProcessService.cs new file mode 100644 index 0000000..dc9f199 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdateNcoaProcessService.cs @@ -0,0 +1,8 @@ +using LCU.Library.Internal.DataCleanUpModel.Models; + +namespace LCU.Api.Internal.DataCleanUp.Services; + +public interface IUpdateNcoaProcessService +{ + Task CleanUp(DataCleanUpRequest dataCleanUpRequest); +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdatePersonForAtmHoldsService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdatePersonForAtmHoldsService.cs new file mode 100644 index 0000000..95fd02d --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/IUpdatePersonForAtmHoldsService.cs @@ -0,0 +1,10 @@ +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Persons; +using LCU.Library.Internal.DataCleanUpModel.Models; +namespace LCU.Api.Internal.DataCleanUp.Services; + +public interface IUpdatePersonForAtmHoldsService +{ + Task CleanUp(DataCleanUpRequest dataCleanUpRequest); + Task HandlePersonForCheckHolds(DataCleanUpResult cleanUpResult, PersonCheckHoldsUserField person); + string DeterminePersonUserFieldValue(PersonCheckHoldsUserField person); +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/MaskTransactionExternalDescriptionWithSsnService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/MaskTransactionExternalDescriptionWithSsnService.cs new file mode 100644 index 0000000..96865c9 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/MaskTransactionExternalDescriptionWithSsnService.cs @@ -0,0 +1,106 @@ +using Serilog; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Transaction; +using LCU.Api.Internal.DataCleanUp.DataAccess; +namespace LCU.Api.Internal.DataCleanUp.Services; + +public class MaskTransactionExternalDescriptionWithSsnService : IMaskTransactionExternalDescriptionWithSsnService +{ + private readonly ICoreApiWrapperService _coreApiWrapperService; + private const char DescriptionSplicer = '*'; + private const int SplicedDescriptionLength = 5; + private const int SsnDescriptionIndex = 2; + private const int SsnEndSubStringIndex = 5; + private const string SsnMask = "XXXXX"; + private const int SsnLength = 9; + + public MaskTransactionExternalDescriptionWithSsnService(ICoreApiWrapperService coreApiWrapperService) + { + _coreApiWrapperService = coreApiWrapperService; + } + + public async Task CleanUp(DataCleanUpRequest dataCleanUpRequest) + { + Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List()); + + try + { + var externalDescriptions = await _coreApiWrapperService.GetTransactionsExternalDescriptionsWithSsn(); + ArgumentNullException.ThrowIfNull(externalDescriptions); + foreach (var externalDescription in externalDescriptions) + { + cleanUpResult = await HandleMaskingTransactionExternalDescriptionWithSsn(cleanUpResult, externalDescription); + } + } + catch (Exception exception) + { + Log.Error(exception, "Error while Masking SSN from Transaction External Description."); + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while Masking SSN from Transaction External Description. " + + $"Exception:{exception}"); + } + + Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + return cleanUpResult; + } + + public async Task HandleMaskingTransactionExternalDescriptionWithSsn(DataCleanUpResult cleanUpResult, ExternalDescription externalDescription) + { + try + { + externalDescription.ExternalDescriptionText = MaskSsn(externalDescription.ExternalDescriptionText); + var basicResponse = await _coreApiWrapperService.UpdateTransactionsExternalDescriptions(externalDescription); + ArgumentNullException.ThrowIfNull(basicResponse); + if (!basicResponse.Success) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.AddRange(basicResponse.Errors); + } + } + catch(Exception exception) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while Masking SSN from Transaction External Description. " + + $"ExternalDescriptionNumber: {externalDescription.ExternalDescriptionNumber}, " + + $"Exception:{exception}"); + } + + return cleanUpResult; + } + + /// + /// If the description does not match the following pattern, the + /// SSN is not at the proper location, or if the SSN is formated differently then expected. + /// We will throw an exception and it will be logged as a fail for this transaction description. + /// + /// Pattern: State of Wisc - SSI [Account Number] *[State of WI Tracking Number]*[SSN]*[MEMBER'S LAST NAME] [MEMBER'S FIRST NAME] *[SomeOtherNumber]\ + /// + /// + /// + /// + public string MaskSsn(string descriptionWithSsn) + { + var descriptionSections = descriptionWithSsn.Split(DescriptionSplicer); + if(descriptionSections.Length != SplicedDescriptionLength) + { + throw new Exception($"Transaction External Description does not meet the pattern. " + + $"Was expecting {SplicedDescriptionLength} sections split by {DescriptionSplicer} " + + $"but there were {descriptionSections.Length} sections."); + } + + var ssn = descriptionSections[SsnDescriptionIndex]; + ArgumentNullException.ThrowIfNull(ssn); + if(ssn.Length != SsnLength) + { + throw new Exception($"The SSN pulled from the Transaction External Description does not meet the pattern." + + $"Was expecting SSN to be a lenght of {SsnLength} but it was {ssn.Length}."); + } + + var newMaskSsn = ssn.Replace(ssn, $"{SsnMask}{ssn.Substring(SsnEndSubStringIndex)}" ); + descriptionSections[SsnDescriptionIndex] = newMaskSsn; + var newDescription = string.Join(DescriptionSplicer, descriptionSections); + + return newDescription; + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/QueueDataCleanUpService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/QueueDataCleanUpService.cs new file mode 100644 index 0000000..f604c52 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/QueueDataCleanUpService.cs @@ -0,0 +1,281 @@ +using Serilog; +using MassTransit; +using Newtonsoft.Json; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Library.Internal.DataCleanUpModel.Enum; +using LCU.Library.Internal.LcuMassTransitModels; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.ApiResponse.Models; +using System; + +namespace LCU.Api.Internal.DataCleanUp.Services; + +public class QueueDataCleanUpService : IQueueDataCleanUpService +{ + private readonly ISendEndpoint _sendEndpoint; + private readonly ReceiveEndpointConfiguration _receiveEndpointConfiguration; + + public QueueDataCleanUpService(IBusControl busControl, + ReceiveEndpointConfiguration receiveEndpointConfiguration) + { + _receiveEndpointConfiguration = receiveEndpointConfiguration; + _sendEndpoint = busControl.GetSendEndpoint(_receiveEndpointConfiguration.ReceiveEndpointUri).Result; + } + + public async Task QueueDataCleanUp(DataCleanUpRequest dataCleanUpRequest) + { + try + { + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await _sendEndpoint.Send(dataCleanUpRequest, cancellationTokenSource.Token); + } + catch (Exception exception) + { + var message = "Failed to Queue {dataCleanUpRequest.CleanUpType} Data Clean Up Request"; + Log.Error($"{message}, Exception Message: {exception.Message}"); + throw new ServiceException($"{message}, Exception Message: {exception.Message}"); + } + } + + public async Task QueueHyphenatedUserIdCleanUp() + { + try + { + var dataCleanUpRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.HyphenatedUserId + }; + + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await _sendEndpoint.Send(dataCleanUpRequest, cancellationTokenSource.Token); + } + catch (Exception exception) + { + Log.Error(exception, "Failed to Queue Hyphenated UserId Data Clean Up Request"); + throw new ServiceException("Failed to Queue Hyphenated UserId Data Clean Up Request"); + } + } + + public async Task QueueDeactivateCustodialEAgreements() + { + try + { + var dataCleanUpRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.DeactivateCustodialEAgreements + }; + + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await _sendEndpoint.Send(dataCleanUpRequest, cancellationTokenSource.Token); + } + catch (Exception exception) + { + Log.Error(exception, "Failed to Queue Deactivate Custodial EAgreements Request"); + throw new ServiceException("Failed to Queue Deactivate Custodial EAgreements Request"); + } + } + + public async Task QueueCloseCustodialVruAgreements() + { + try + { + var dataCleanUpRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.CloseCustodialVruAgreements + }; + + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await _sendEndpoint.Send(dataCleanUpRequest, cancellationTokenSource.Token); + } + catch (Exception exception) + { + Log.Error(exception, "Failed to Queue Close Custodial Vru Agreements Request"); + throw new ServiceException("Failed to Queue Close Custodial Vru Agreements Request"); + } + } + + public async Task QueueMaskTransactionExternalDescriptionWithSsn() + { + try + { + var dataCleanUpRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.MaskTransactionExternalDescriptionWithSsn + }; + + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await _sendEndpoint.Send(dataCleanUpRequest, cancellationTokenSource.Token); + } + catch (Exception exception) + { + Log.Error(exception, "Failed to Queue Mask Transaction External Description with SSN"); + throw new ServiceException("Failed to Queue Mask Transaction External Description with SSN"); + } + } + + public async Task QueueAddFundsToVipSavingsAccounts() + { + try + { + var dataCleanUpRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.AddFundsToVipSavingsAccounts + }; + + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await _sendEndpoint.Send(dataCleanUpRequest, cancellationTokenSource.Token); + } + catch (Exception exception) + { + Log.Error(exception, "Failed to Queue Add Funds To Vip Savings"); + throw new ServiceException("Failed to Queue Add Funds To Vip Savings"); + } + } + + public async Task QueueBatchAddFundsToVipSavingsAccounts() + { + try + { + var dataCleanUpRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.BatchAddFundsToVipSavingsAccounts + }; + + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await _sendEndpoint.Send(dataCleanUpRequest, cancellationTokenSource.Token); + } + catch (Exception exception) + { + Log.Error(exception, "Failed to Queue Batch Add Funds To Vip Savings"); + throw new ServiceException("Failed to Queue Batch Add Funds To Vip Savings"); + } + } + + public async Task QueueUpdateAdminBranchCodesByAccountNumber() + { + try + { + var dataCleanUpRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateAdminBranchCodesByAccountNumber + }; + + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await _sendEndpoint.Send(dataCleanUpRequest, cancellationTokenSource.Token); + } + catch (Exception exception) + { + Log.Error(exception, "Failed to Queue AdminBranchCodeChanges for Account Numbers"); + throw new ServiceException("Failed to Queue AdminBranchCodeChanges for Account Numbers"); + } + } + + public async Task QueueUpdateAccountLoanToValue() + { + try + { + var dataCleanUpRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateAccountLoanToValue + }; + + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await _sendEndpoint.Send(dataCleanUpRequest, cancellationTokenSource.Token); + } + catch (Exception exception) + { + Log.Error(exception, "Failed to Queue UpdateAccountLoanToValue for Account Numbers"); + throw new ServiceException("Failed to Queue UpdateAccountLoanToValue for Account Numbers"); + } + } + + public async Task QueueUpdateAccountGroupForAnalysis() + { + try + { + var dataCleanUpRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateAccountGroupForAnalysis + }; + + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await _sendEndpoint.Send(dataCleanUpRequest, cancellationTokenSource.Token); + } + catch (Exception exception) + { + Log.Error(exception, "Failed to Queue UpdateAccountGroupForAnalysis for Account Numbers"); + throw new ServiceException("Failed to Queue UpdateAccountGroupForAnalysis for Account Numbers"); + } + } + + public async Task QueueUpdateAccountNickname() + { + try + { + var dataCleanUpRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateAccountNickname + }; + await QueueDataCleanUp(dataCleanUpRequest); + } + catch (Exception ex) + { + Log.Error(ex, "Failed to Queue UpdateAccountNickname for Account Numbers"); + throw new ServiceException("Failed to Queue UpdateAccountNickname for Account Numbers"); + } + } + + public async Task QueuePmiCancelUpdate() + { + try + { + var dataCleanUpRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateAccountPmiCancel + }; + await QueueDataCleanUp(dataCleanUpRequest); + } + catch (Exception ex) + { + Log.Error(ex, "Failed to Queue UpdatePmiCancel for Account Numbers"); + throw new ServiceException("Failed to Queue UpdatePmiCancel for Account Numbers"); + } + } + + public async Task QueueDataCleanUpWithPayload(TRequest request, CleanUpTypes cleanUpType) where TRequest : ReturnResponse + { + try + { + ArgumentNullException.ThrowIfNull(request); + var queueRequest = new DataCleanUpRequest + { + CleanUpType = cleanUpType, + DataCleanUpPayload = JsonConvert.SerializeObject(request), + ResponseItems = request.ResponseItems + }; + await QueueDataCleanUp(queueRequest); + } + catch (Exception ex) + { + Log.Error(ex, $"Failed to Queue Data Cleanup Type: {cleanUpType}"); + throw new ServiceException($"Failed to Queue Data Cleanup Type: {cleanUpType}"); + } + } + + public async Task QueueUpdateAccountCreditReportType() + { + try + { + var dataCleanUpRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateAccountCreditReportType + }; + await QueueDataCleanUp(dataCleanUpRequest); + } + catch (Exception ex) + { + Log.Error(ex, "Failed to Queue UpdateAccountCreditReportType for Account Numbers"); + throw new ServiceException("Failed to Queue UpdateAccountCreditReportType for Account Numbers"); + } + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAccountCreditReportTypeService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAccountCreditReportTypeService.cs new file mode 100644 index 0000000..5da76f6 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAccountCreditReportTypeService.cs @@ -0,0 +1,77 @@ +using CsvHelper; +using Newtonsoft.Json; +using Serilog; +using System.Globalization; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Api.Internal.DataCleanUp.Models; + +namespace LCU.Api.Internal.DataCleanUp.Services; + +public class UpdateAccountCreditReportTypeService : IUpdateAccountCreditReportTypeService +{ + private readonly ICoreApiWrapperService _coreApiWrapperService; + private readonly IFileOperationsService _fileOperationsService; + private const string CreditReportType = "EXCL"; + + public UpdateAccountCreditReportTypeService(ICoreApiWrapperService coreApiWrapperService, + IFileOperationsService fileOperationsService) + { + _coreApiWrapperService = coreApiWrapperService; + _fileOperationsService = fileOperationsService; + } + public async Task CleanUp(DataCleanUpRequest dataCleanUpRequest) + { + Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List()); + var creditTypeRequest = JsonConvert.DeserializeObject(dataCleanUpRequest.DataCleanUpPayload); + try + { + var accountData = await _fileOperationsService.GetContentData(creditTypeRequest.SourcePath); + ArgumentNullException.ThrowIfNull(accountData); + + var textReader = new StringReader(accountData); + ArgumentNullException.ThrowIfNull(textReader); + + var csvReader = new CsvReader(textReader, CultureInfo.InvariantCulture); + var accountCreditReportTypeList = csvReader.GetRecords().ToList(); + ArgumentNullException.ThrowIfNull(accountCreditReportTypeList); + + Log.Information($"Data CleanUp # of Accounts {accountCreditReportTypeList.Count()} at {DateTime.Now}"); + + foreach (var account in accountCreditReportTypeList) + { + cleanUpResult = await HandleAccountCreditReportType(cleanUpResult, account); + } + } + catch (Exception exception) + { + Log.Error(exception, "Error while updating Account Credit Report Type."); + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while updating Account Credit Report Type. " + + $"Exception:{exception}"); + } + + Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + return cleanUpResult; + } + + public async Task HandleAccountCreditReportType(DataCleanUpResult cleanUpResult, AccountCreditReportType account) + { + cleanUpResult.Successful = true; + try + { + var response = await _coreApiWrapperService.UpdateAccountCreditReportType(account.AccountNumber, CreditReportType); + if (!response.Success) + { + throw new Exception("Account Credit Report Type not updated."); + } + } + catch (Exception exception) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while while updating Account Credit Report Type. " + + $"Exception:{exception}"); + } + return cleanUpResult; + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAccountGroupForAnalysisService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAccountGroupForAnalysisService.cs new file mode 100644 index 0000000..e2eab74 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAccountGroupForAnalysisService.cs @@ -0,0 +1,66 @@ +using Serilog; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Api.Internal.DataCleanUp.Configuration; + +namespace LCU.Api.Internal.DataCleanUp.Services; + +public class UpdateAccountGroupForAnalysisService : IUpdateAccountGroupForAnalysisService +{ + private readonly ICoreApiWrapperService _coreApiWrapperService; + private readonly DataCleanupDefaults _dataCleanupDefaults; + + public UpdateAccountGroupForAnalysisService(ICoreApiWrapperService coreApiWrapperService, DataCleanupDefaults dataCleanupDefaults) + { + _coreApiWrapperService = coreApiWrapperService; + _dataCleanupDefaults = dataCleanupDefaults; + } + + public async Task CleanUp(DataCleanUpRequest dataCleanUpRequest) + { + Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List()); + + try + { + var accountNumbers = await _coreApiWrapperService.GetGroupUpdateForAnalysisAccountNumbers(); + ArgumentNullException.ThrowIfNull(accountNumbers); + Log.Information($"Data CleanUp # of Accounts {accountNumbers.Count()} at {DateTime.Now}"); + foreach (var accountNumber in accountNumbers) + { + cleanUpResult = await HandleAccountGroupForAnalysis(cleanUpResult, accountNumber); + } + } + catch (Exception exception) + { + Log.Error(exception, "Error while updating Account for Group Analysis."); + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while updating Account for Group Analysis. " + + $"Exception:{exception}"); + } + + Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + return cleanUpResult; + } + + public async Task HandleAccountGroupForAnalysis(DataCleanUpResult cleanUpResult, string accountNumber) + { + try + { + var basicResponse = await _coreApiWrapperService.UpdateAccountGroupForAnalysis(accountNumber); + ArgumentNullException.ThrowIfNull(basicResponse); + if (!basicResponse.Success) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.AddRange(basicResponse.Errors); + } + } + catch(Exception exception) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while updating Account for Group Analysis. " + + $"Exception:{exception}"); + } + + return cleanUpResult; + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAccountLoanToValueService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAccountLoanToValueService.cs new file mode 100644 index 0000000..52b40d4 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAccountLoanToValueService.cs @@ -0,0 +1,70 @@ +using Serilog; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Api.Internal.DataCleanUpLib.Repositories; +using LCU.Library.Internal.DataCleanUpModel.Entities; +using LCU.Api.Internal.DataCleanUp.Configuration; + +namespace LCU.Api.Internal.DataCleanUp.Services; + +public class UpdateAccountLoanToValueService : IUpdateAccountLoanToValueService +{ + private readonly ICoreApiWrapperService _coreApiWrapperService; + private readonly DataCleanupDefaults _dataCleanupDefaults; + private readonly ILtvDataCleanUpRepository _ltvDataCleanUpRepository; + + public UpdateAccountLoanToValueService(ICoreApiWrapperService coreApiWrapperService, ILtvDataCleanUpRepository ltvDataCleanUpRepository, DataCleanupDefaults dataCleanupDefaults) + { + _coreApiWrapperService = coreApiWrapperService; + _ltvDataCleanUpRepository = ltvDataCleanUpRepository; + _dataCleanupDefaults = dataCleanupDefaults; + } + + public async Task CleanUp(DataCleanUpRequest dataCleanUpRequest) + { + Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List()); + + try + { + var ltvDataCleanUpList = await _ltvDataCleanUpRepository.ListMinorAccountTypeAsync(_dataCleanupDefaults.LtvExcludedMinorAccountTypes); + ArgumentNullException.ThrowIfNull(ltvDataCleanUpList); + Log.Information($"Data CleanUp # of Accounts {ltvDataCleanUpList.Count()} at {DateTime.Now}"); + foreach (var ltvDataCleanUp in ltvDataCleanUpList) + { + cleanUpResult = await HandleAccountLoanToValue(cleanUpResult, ltvDataCleanUp); + } + } + catch (Exception exception) + { + Log.Error(exception, "Error while updating Account Loan To Value."); + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while updating Account Loan To Value. " + + $"Exception:{exception}"); + } + + Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + return cleanUpResult; + } + + public async Task HandleAccountLoanToValue(DataCleanUpResult cleanUpResult, Ltv_DataCleanUp ltvDataCleanUp) + { + try + { + var basicResponse = await _coreApiWrapperService.UpdateAccountLoanToValue(ltvDataCleanUp.AccountNumber, ltvDataCleanUp.Ltv); + ArgumentNullException.ThrowIfNull(basicResponse); + if (!basicResponse.Success) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.AddRange(basicResponse.Errors); + } + } + catch(Exception exception) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while while updating Account Loan To Value. " + + $"Exception:{exception}"); + } + + return cleanUpResult; + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAccountNicknameService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAccountNicknameService.cs new file mode 100644 index 0000000..41cabdf --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAccountNicknameService.cs @@ -0,0 +1,79 @@ +using Serilog; +using CsvHelper; +using System.Globalization; +using LCU.Api.Internal.DataCleanUp.Configuration; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Api.Internal.DataCleanUp.Models; + +namespace LCU.Api.Internal.DataCleanUp.Services +{ + public class UpdateAccountNicknameService : IUpdateAccountNicknameService + { + private readonly ICoreApiWrapperService _coreApiWrapperService; + private readonly IFileOperationsService _fileOperationsService; + private readonly DataCleanupDefaults _dataCleanupDefaults; + + public UpdateAccountNicknameService(ICoreApiWrapperService coreApiWrapperService, + IFileOperationsService fileOperationsService, + DataCleanupDefaults dataCleanupDefaults) + { + _coreApiWrapperService = coreApiWrapperService; + _fileOperationsService = fileOperationsService; + _dataCleanupDefaults = dataCleanupDefaults; + } + public async Task CleanUp(DataCleanUpRequest dataCleanUpRequest) + { + Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List()); + try + { + var accountData = await _fileOperationsService.GetContentData(_dataCleanupDefaults.AccountNicknameSourcePath); + ArgumentNullException.ThrowIfNull(accountData); + + var textReader = new StringReader(accountData); + ArgumentNullException.ThrowIfNull(textReader); + + var csvReader = new CsvReader(textReader, CultureInfo.InvariantCulture); + var accountNicknameCleanupList = csvReader.GetRecords().ToList(); + ArgumentNullException.ThrowIfNull(accountNicknameCleanupList); + + Log.Information($"Data CleanUp # of Accounts {accountNicknameCleanupList.Count()} at {DateTime.Now}"); + + foreach (var account in accountNicknameCleanupList) + { + cleanUpResult = await HandleAccountNickname(cleanUpResult, account); + } + } + catch (Exception exception) + { + Log.Error(exception, "Error while updating Account Nickname."); + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while updating Missing Savings. " + + $"Exception:{exception}"); + } + + Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + return cleanUpResult; + } + + public async Task HandleAccountNickname(DataCleanUpResult cleanUpResult, AccountNickname account) + { + cleanUpResult.Successful = true; + try + { + var response = await _coreApiWrapperService.UpdateAccountNickname(account.AccountNumber, account.Nickname); + if (!response.Success) + { + throw new Exception("Account Nickname not updated."); + } + } + catch (Exception exception) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while while updating Account Nickname. " + + $"Exception:{exception}"); + } + return cleanUpResult; + } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAccountPmiCancelService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAccountPmiCancelService.cs new file mode 100644 index 0000000..e82b891 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAccountPmiCancelService.cs @@ -0,0 +1,157 @@ +using CsvHelper; +using CsvHelper.Configuration; +using LCU.Api.Internal.DataCleanUp.Configuration; +using LCU.Api.Internal.DataCleanUp.Models; +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses; +using LCU.Library.Internal.DataCleanUpModel.Models; +using Newtonsoft.Json; +using Serilog; +using System.Globalization; +using System.Text; + +namespace LCU.Api.Internal.DataCleanUp.Services +{ + public class UpdateAccountPmiCancelService : IUpdateAccountPmiCancelService + { + private readonly ICoreApiWrapperService _coreApiWrapperService; + private readonly IFileOperationsService _fileOperationsService; + private readonly DataCleanupDefaults _dataCleanupDefaults; + private readonly string closedStatus = "CLS"; + private readonly string pmiustatus = "PMIU"; + private readonly string success = "Account Successfully Updated"; + private readonly string failure = "Not Updated. Account in Closed Status"; + private List _updatePmiCancelSummary = new List(); + + public UpdateAccountPmiCancelService(ICoreApiWrapperService coreApiWrapperService, + IFileOperationsService fileOperationsService, + DataCleanupDefaults dataCleanupDefaults + ) + { + _coreApiWrapperService = coreApiWrapperService; + _fileOperationsService = fileOperationsService; + _dataCleanupDefaults = dataCleanupDefaults; + } + + public async Task CleanUp(DataCleanUpRequest dataCleanUpRequest) + { + Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List()); + try + { + var accountData = await _fileOperationsService.GetContentData(_dataCleanupDefaults.PmiCancelSourcePath); + ArgumentNullException.ThrowIfNull(accountData); + + var textReader = new StringReader(accountData); + ArgumentNullException.ThrowIfNull(textReader); + + var csvReader = new CsvReader(textReader, CultureInfo.InvariantCulture); + var accountPmiCancelList = csvReader.GetRecords().ToList(); + ArgumentNullException.ThrowIfNull(accountPmiCancelList); + + Log.Information($"Data CleanUp # of Accounts {accountPmiCancelList.Count()} at {DateTime.Now}"); + + foreach (var account in accountPmiCancelList) + { + PmiCancel pmiCancel = new PmiCancel(); + pmiCancel = await _coreApiWrapperService.GetPropertyNumber(account); + account.PropertyNumber = pmiCancel.PropertyNumber; + account.CurrentStatusCode = pmiCancel.CurrentStatusCode; + account.CurrentStatus = pmiCancel.CurrentStatus; + cleanUpResult = await HandleAccountPmiCancel(cleanUpResult, account); + } + await HandleExportResultsPmiCancelUpdate(); + } + catch (Exception exception) + { + Log.Error(exception, "Error while updating Account PMI Cancel Date."); + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while updating Account PMI Cancel Date. " + + $"Exception:{exception}"); + } + + Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + return cleanUpResult; + } + + public async Task HandleAccountPmiCancel(DataCleanUpResult cleanUpResult, PmiCancel account) + { + cleanUpResult.Successful = true; + UpdatePmiCancelSummary summary = new UpdatePmiCancelSummary(); + BasicResponse response = null; + try + { + if (!account.CurrentStatusCode.Equals(closedStatus)) + { + var result = await _coreApiWrapperService.GetPropertyUserField(account.PropertyNumber); + if (result != null && result.Any(c => c.UserFieldCode == pmiustatus)) + { + response = await _coreApiWrapperService.UpdateAccountPmiCancel(account); + } + else + { + response = await _coreApiWrapperService.AddAccountPmiCancel(account); + } + if (!response.Success) + { + throw new Exception("Failure to Add or Update PMI Cancel Date"); + + } + _updatePmiCancelSummary.Add(summary.TransformNewSummary(account, success)); + } + else + { + _updatePmiCancelSummary.Add(summary.TransformNewSummary(account, failure)); + } + + } + catch (Exception exception) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while while updating or adding Account Pmi Cancel Date. " + + $"Exception:{exception}"); + } + return cleanUpResult; + } + + public async Task HandleExportResultsPmiCancelUpdate() + { + try + { + var csvConfig = new CsvConfiguration(CultureInfo.CurrentCulture) + { + HasHeaderRecord = true, + Delimiter = ",", + Encoding = Encoding.UTF8 + }; + + var mem = new MemoryStream(); + var writer = new StreamWriter(mem); + var csvWriter = new CsvWriter(writer, csvConfig); + ArgumentNullException.ThrowIfNull(csvWriter); + + csvWriter.WriteHeader(); + csvWriter.NextRecord(); + csvWriter.WriteRecords(_updatePmiCancelSummary); + + writer.Flush(); + var result = Encoding.UTF8.GetString(mem.ToArray()); + + var writeFileRequest = new WriteFileRequest() + { + DestinationPath = _dataCleanupDefaults.PmiCancelSummaryPath, + FileName = "UpdatePmiCancelSummary", + Overwrite = true, + Extension = "csv", + FileData = result, + }; + + await _fileOperationsService.WriteFile(writeFileRequest); + } + catch (Exception exception) + { + throw new Exception($"Export Pmi Cancel Update Error, {exception.Message}"); + } + } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAdminBranchCodesByAccountNumberService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAdminBranchCodesByAccountNumberService.cs new file mode 100644 index 0000000..288208f --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateAdminBranchCodesByAccountNumberService.cs @@ -0,0 +1,66 @@ +using Serilog; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Api.Internal.DataCleanUp.Configuration; + +namespace LCU.Api.Internal.DataCleanUp.Services; + +public class UpdateAdminBranchCodesByAccountNumberService : IUpdateAdminBranchCodesByAccountNumberService +{ + private readonly ICoreApiWrapperService _coreApiWrapperService; + private readonly DataCleanupDefaults _dataCleanupDefaults; + + public UpdateAdminBranchCodesByAccountNumberService(ICoreApiWrapperService coreApiWrapperService, DataCleanupDefaults dataCleanupDefaults) + { + _coreApiWrapperService = coreApiWrapperService; + _dataCleanupDefaults = dataCleanupDefaults; + } + + public async Task CleanUp(DataCleanUpRequest dataCleanUpRequest) + { + Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List()); + + try + { + var accountNumbers = await _coreApiWrapperService.GetBranchCodeChangeAccountNumbers(); + ArgumentNullException.ThrowIfNull(accountNumbers); + Log.Information($"Data CleanUp # of Accounts {accountNumbers.Count()} at {DateTime.Now}"); + foreach (var accountNumber in accountNumbers) + { + cleanUpResult = await HandleAdminBranchCodeChangeAccountNumbers(cleanUpResult, accountNumber); + } + } + catch (Exception exception) + { + Log.Error(exception, "Error while changing Admin Account Branch Codes."); + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while changing Admin Account Branch Codes. " + + $"Exception:{exception}"); + } + + Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + return cleanUpResult; + } + + public async Task HandleAdminBranchCodeChangeAccountNumbers(DataCleanUpResult cleanUpResult, string accountNumber) + { + try + { + var basicResponse = await _coreApiWrapperService.UpdateBranchCodesForAccountNumbers(accountNumber, _dataCleanupDefaults.DigitalBankingBranchCode); + ArgumentNullException.ThrowIfNull(basicResponse); + if (!basicResponse.Success) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.AddRange(basicResponse.Errors); + } + } + catch(Exception exception) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while changing Admin Account Branch Codes. " + + $"Exception:{exception}"); + } + + return cleanUpResult; + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateFannieMaeMortgageService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateFannieMaeMortgageService.cs new file mode 100644 index 0000000..1235b60 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateFannieMaeMortgageService.cs @@ -0,0 +1,285 @@ +using FileHelpers; +using MassTransit; +using Newtonsoft.Json; +using Serilog; +using System.Globalization; +using TimeZoneConverter; +using LCU.Api.Internal.DataCleanUp.Configuration; +using LCU.Api.Internal.DataCleanUp.Models; +using LCU.Api.Internal.DataCleanUp.Services.Emailers; +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts; + +namespace LCU.Api.Internal.DataCleanUp.Services; + +public class UpdateFannieMaeMortgageService : IUpdateFannieMaeMortgageService +{ + private readonly ICoreApiWrapperService _coreApiWrapperService; + private readonly IFileOperationsService _fileOperationsService; + private readonly INotificationsApiService _notificationsApiService; + private readonly FannieMaeConfiguration _fannieMaeConfiguration; + private readonly DataCleanUpConfiguration _dataCleanUpConfiguration; + + private readonly string _errorFileHeader = "DnaAccountNumber|InvestorPoolNumber|InvestorPoolDate\n"; + private const string NoFilesMessage = "No files found for Update Fannie Mae Mortgage"; + + public UpdateFannieMaeMortgageService(ICoreApiWrapperService coreApiWrapperService, + IFileOperationsService fileOperationsService, + FannieMaeConfiguration fannieMaeConfiguration, + DataCleanUpConfiguration dataCleanUpConfiguration, + INotificationsApiService notificationsApiService) + { + _coreApiWrapperService = coreApiWrapperService; + _fileOperationsService = fileOperationsService; + _fannieMaeConfiguration = fannieMaeConfiguration; + _dataCleanUpConfiguration = dataCleanUpConfiguration; + _notificationsApiService = notificationsApiService; + } + + public async Task CleanUp(DataCleanUpRequest dataCleanUpRequest) + { + Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List()); + var fannieMaeUpdateRequest = JsonConvert.DeserializeObject(dataCleanUpRequest.DataCleanUpPayload); + var fannieMaeUpdateResultList = new List(); + + try + { + var reader = new FileHelperEngine(); + + var fileRequest = _fileOperationsService.BuildDynamicFileListRequest(fannieMaeUpdateRequest); + var fileList = await _fileOperationsService.BuildDynamicFileList(fileRequest); + + if (!fileList.Any()) + { + cleanUpResult.ResponseStack.Add(NoFilesMessage); + var emailSuccess = _notificationsApiService.SendEmail(fannieMaeUpdateRequest.EmailSummaryRecipients, _fannieMaeConfiguration.SummaryEmailSubject, NoFilesMessage); + Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + return cleanUpResult; + } + + foreach (var filename in fileList) + { + var updateResult = await HandleFileUpdate(filename, fannieMaeUpdateRequest, reader); + fannieMaeUpdateResultList.Add(updateResult); + } + + cleanUpResult = await HandleBatchCompletion(fannieMaeUpdateResultList, cleanUpResult, fannieMaeUpdateRequest); + } + catch (Exception ex) + { + Log.Error(ex, "Error while updating Fannie Mae Mortgage."); + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while updating Fannie Mae Mortgage." + + $"Exception:{ex}"); + } + + Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + return cleanUpResult; + } + + public async Task ProcessFannieMaeRecord(FannieMaeMortgage entry, FannieMaeUpdateResult updateResult, string userFieldId, string userFieldValue) + { + try + { + if (await DetermineIfUserFieldExists((long)entry.ServicerLoanNumber!, userFieldId)) + { + var updateResponse = await _coreApiWrapperService.UpdateAccountUserField((long)entry.ServicerLoanNumber, userFieldId, userFieldValue); + updateResult = HandleUserFieldResponse(updateResponse, updateResult, entry); + } + else + { + var addResponse = await _coreApiWrapperService.AddAccountUserField((long)entry.ServicerLoanNumber, userFieldId, userFieldValue); + updateResult = HandleUserFieldResponse(addResponse, updateResult, entry); + } + } + catch (Exception ex) + { + updateResult.AddStringToErrorList(entry, "Error while updating Account User Field " + userFieldId); + return updateResult; + } + + return updateResult; + } + + public async Task DetermineIfUserFieldExists(long serviceNumber, string userFieldCode) + { + var response = await _coreApiWrapperService.GetAccountUserField(serviceNumber); + return response.Any(c => c.UserFieldCode == userFieldCode); + } + + private FannieMaeUpdateResult HandleUserFieldResponse(IEnumerable response, FannieMaeUpdateResult updateResult, FannieMaeMortgage entry) + { + if (response.Any()) + { + updateResult.UpdateList.Add(entry); + } + else + { + var error = $"Fannie Mae Loan Record Failed: {entry.ServicerLoanNumber}"; + updateResult.ErrorList = new List() { error }; + } + return updateResult; + } + + #region "BatchFileCreation" + public async Task HandleBatchCompletion(List fannieMaeUpdateResultList, + DataCleanUpResult cleanUpResult, FannieMaeMortgageRequest fanniMaeMortgageRequest) + { + var errorFileCreated = await CreateErrorFile(fannieMaeUpdateResultList, fanniMaeMortgageRequest.ErrorDestinationPath); + + var totalBatchSummary = BuildTotalBatchSummary(fannieMaeUpdateResultList, errorFileCreated); + var batchResultSummaryText = CreateTotalBatchSummaryString(totalBatchSummary, fanniMaeMortgageRequest.ErrorDestinationPath); + + foreach (var updateResult in totalBatchSummary.UpdateResults) + { + batchResultSummaryText += BuildFileUpdateSummary(updateResult); + } + + var emailSuccess = _notificationsApiService.SendEmail(fanniMaeMortgageRequest.EmailSummaryRecipients, _fannieMaeConfiguration.SummaryEmailSubject, batchResultSummaryText); + batchResultSummaryText += $"Summary Email Request Successful: {emailSuccess}"; + + Log.Information(batchResultSummaryText); + cleanUpResult.ResponseStack.Add(batchResultSummaryText); + + return cleanUpResult; + } + + public async Task CreateErrorFile(List updateResultList, string fileDestinationPath) + { + try + { + var data = _errorFileHeader; + foreach (var updateResult in updateResultList) + { + foreach (var error in updateResult.ErrorList) + { + data += error; + } + } + + if (data != _errorFileHeader) + { + var dateString = GetCurrentDateTimeString("yyyy-MM-dd-HHmmss"); + + var writeFileRequest = new WriteFileRequest() + { + DestinationPath = fileDestinationPath, + FileName = dateString + _fannieMaeConfiguration.ErrorFileDefaultName, + Extension = ".csv", + FileData = data, + Overwrite = false + }; + + await _fileOperationsService.WriteFile(writeFileRequest); + return true; + } + } + catch (Exception ex) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error($"Error while writing Fannie Mae Error Record file. {ex.Message}"); + Log.Error(ex, "Exception while trying to write Fannie Mae Error file"); + return false; + } + return false; + } + + public string BuildFileUpdateSummary(FannieMaeUpdateResult updateResult) + { + return $"--------------

Fannie Mae File In Batch Summary:

Filename: {updateResult.Filename}" + + $"

Total Records Received: {updateResult.TotalRecordsFound}

Total Records Updated: {updateResult.UpdateList.Count}" + + $"

Total Error Records: {updateResult.ErrorList.Count}

Total Records Processed: " + + $"{updateResult.UpdateList.Count + updateResult.ErrorList.Count}

"; + } + + public async Task HandleFileUpdate(string filename, FannieMaeMortgageRequest fannieMaeMortgageRequest, FileHelperEngine reader) + { + string formattedDate = string.Empty; + var updateResult = new FannieMaeUpdateResult(filename); + var fileData = await _fileOperationsService.GetContentData($"{fannieMaeMortgageRequest.FinalSourcePath}{filename}"); + var fanniMaeUpdates = reader.ReadString(fileData); + updateResult.TotalRecordsFound = fanniMaeUpdates.Length; + + foreach (var entry in fanniMaeUpdates) + { + if (!string.IsNullOrWhiteSpace(entry.PoolIssueDate)) + { + DateTime date = DateTime.ParseExact(entry.PoolIssueDate, _fannieMaeConfiguration.FileDateFormat, CultureInfo.InvariantCulture); + formattedDate = date.ToString(_fannieMaeConfiguration.DnaDateFormat); + } + await ProcessFannieMaeRecord(entry, updateResult, _fannieMaeConfiguration.PoolDateUserFieldId, formattedDate); + await ProcessFannieMaeRecord(entry, updateResult, _fannieMaeConfiguration.PoolNbrUserFieldId, entry.PoolNumber); + } + + return updateResult; + } + + public async Task WriteFannieMaeErrorFile(string data, string destination) + { + try + { + var dateString = GetCurrentDateTimeString("yyyy-MM-dd-HHmmss"); + + var writeFileRequest = new WriteFileRequest() + { + DestinationPath = destination, + FileName = dateString + _fannieMaeConfiguration.ErrorFileDefaultName, + Extension = ".csv", + FileData = data, + Overwrite = false + }; + + await _fileOperationsService.WriteFile(writeFileRequest); + return true; + } + catch (Exception ex) + { + Log.Error(ex, "Exception while trying to write Fannie Mae Error file"); + return false; + } + } + #endregion + + #region "EmailBatchSummary" + public string CreateTotalBatchSummaryString(FannieMaeTotalBatchSummary summary, string errorFileLocation = "") + { + return summary.ErrorFileCreated ? + $"Fannie Mae Update Total Batch Summary:

Total Files in Batch: {summary.UpdateResults.Count}

Total Records Received: " + + $"{summary.TotalRecordsFound}

Total Records Updated: {summary.TotalRecordsUpdated}

Total Error Records: " + + $"{summary.TotalErrorRecords}

Total Records Processed: {summary.TotalRecordsUpdated + summary.TotalErrorRecords}

" + + $"Error File Created: {summary.ErrorFileCreated}

Error File Location: {errorFileLocation}

" + : + $"Fannie Mae Update Total Batch Summary:

Total Files in Batch: {summary.UpdateResults.Count}

Total Records Received: " + + $"{summary.TotalRecordsFound}

Total Records Updated: {summary.TotalRecordsUpdated}

Total Error Records: " + + $"{summary.TotalErrorRecords}

Total Records Processed: {summary.TotalRecordsUpdated + summary.TotalErrorRecords}

" + + $"Error File Created: {summary.ErrorFileCreated}

"; + } + + public FannieMaeTotalBatchSummary BuildTotalBatchSummary(List updateResults, bool errorFileCreationSuccess) + { + var totalBatchSummary = new FannieMaeTotalBatchSummary(updateResults, errorFileCreationSuccess); + + foreach (var updateResult in totalBatchSummary.UpdateResults) + { + totalBatchSummary.TotalRecordsFound += updateResult.TotalRecordsFound; + totalBatchSummary.TotalRecordsUpdated += updateResult.UpdateList.Count; + totalBatchSummary.TotalErrorRecords += updateResult.ErrorList.Count; + } + + return totalBatchSummary; + } + #endregion + + public string GetCurrentDateTimeString(string format) + { + var assumedTimezone = TZConvert.GetTimeZoneInfo(_dataCleanUpConfiguration.TimeZone); + var currentDateTime = TimeZoneInfo.ConvertTime(DateTime.Now, assumedTimezone); + + return currentDateTime.ToString(format); + } + +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateMissingBatchSavingsService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateMissingBatchSavingsService.cs new file mode 100644 index 0000000..e0074d8 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateMissingBatchSavingsService.cs @@ -0,0 +1,243 @@ +using Serilog; +using System.Globalization; +using System.Text; +using CsvHelper; +using CsvHelper.Configuration; +using LCU.Api.Internal.DataCleanUp.Models; +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapResponses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; +using LCU.Api.Internal.DataCleanUp.Configuration; +using Newtonsoft.Json; + +namespace LCU.Api.Internal.DataCleanUp.Services; + +public class UpdateMissingBatchSavingsService : IUpdateMissingBatchSavingsService +{ + private readonly ICoreApiWrapperService _coreApiWrapperService; + private readonly IFileOperationsService _fileOperationsService; + private readonly DataCleanupDefaults _dataCleanupDefaults; + private readonly SavingsDefaults _savingsDefaults; + private List _missingBatchSavingsSummaryList = new List(); + + public UpdateMissingBatchSavingsService(ICoreApiWrapperService coreApiWrapperService, IFileOperationsService fileOperationsService, DataCleanupDefaults dataCleanupDefaults, SavingsMissingRequirementsDefaults savingsDefaults) + { + _coreApiWrapperService = coreApiWrapperService; + _fileOperationsService = fileOperationsService; + _dataCleanupDefaults = dataCleanupDefaults; + _savingsDefaults = savingsDefaults.SavingDefaults; + } + + public async Task CleanUp(DataCleanUpRequest dataCleanUpRequest) + { + Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List()); + + try + { + var missingSavingsFileData = await _fileOperationsService.GetContentData(_dataCleanupDefaults.BatchSavingsSourcePath); + ArgumentNullException.ThrowIfNull(missingSavingsFileData); + + var textReader = new StringReader(missingSavingsFileData); + ArgumentNullException.ThrowIfNull(textReader); + + var csvReader = new CsvReader(textReader, CultureInfo.InvariantCulture); + var missingSavingsCleanupList = csvReader.GetRecords().ToList(); + ArgumentNullException.ThrowIfNull(missingSavingsCleanupList); + + Log.Information($"Data CleanUp # of Accounts {missingSavingsCleanupList.Count()} at {DateTime.Now}"); + + foreach (var missingAccount in missingSavingsCleanupList) + { + cleanUpResult = await HandleMissingSavingsAccounts(cleanUpResult, missingAccount); + } + + await HandleExportResultsBatchSavingsAccounts(); + } + catch (Exception exception) + { + Log.Error(exception, "Error while updating Missing Savings."); + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while updating Missing Savings. " + + $"Exception:{exception}"); + } + + Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + return cleanUpResult; + } + + public async Task HandleMissingSavingsAccounts(DataCleanUpResult cleanUpResult, MissingBatchSavings missingAccount) + { + cleanUpResult.Successful = true; + CreatedAccountResponse createdAccountResponse = new CreatedAccountResponse(); + + try + { + if (missingAccount.CoreSavingsAccount == 0) + { + switch (missingAccount.CustomerType) + { + case "Person": + createdAccountResponse = await HandleUpdatingPersonSavingsAccounts(missingAccount); + break; + case "Organization": + createdAccountResponse = await HandleUpdatingOrganzationSavingsAccounts(missingAccount); + break; + default: + throw new Exception("Invalid Customer Type"); + } + } + ArgumentNullException.ThrowIfNull(createdAccountResponse); + + if (createdAccountResponse.BasicResponse != null && !createdAccountResponse.BasicResponse.Success) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.AddRange(createdAccountResponse.BasicResponse.Errors); + } + + //Fund the account with either the new savings account number or the valid existing account from data + var fundAmount = Convert.ToDouble(5 - missingAccount.SavingsAccountBalance); + var accountNumberToFund = createdAccountResponse.AccountNumber == null ? missingAccount.SavingsAccountNumber : createdAccountResponse.AccountNumber.ToString(); + ArgumentNullException.ThrowIfNull(accountNumberToFund); + + var basicResponse = await HandleFundingBatchSavingsAccounts(accountNumberToFund, fundAmount); + ArgumentNullException.ThrowIfNull(basicResponse); + + foreach (var response in basicResponse) + { + if (!response.Success) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.AddRange(response.Errors); + } + } + var missingBatchResult = new MissingBatchSavingsSummary(); + + //Transform to Summary for Export + var missingSavingsSummary = new MissingBatchSavingsSummary(); + _missingBatchSavingsSummaryList.Add(missingSavingsSummary.TransformNewSummary(missingAccount, fundAmount, accountNumberToFund)); + } + catch (Exception exception) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while while updating Missing Savings Account. " + + $"Exception:{exception}"); + } + + return cleanUpResult; + } + + public async Task HandleUpdatingPersonSavingsAccounts(MissingBatchSavings missingSavings) + { + var request = new CreatePersonAccountRequest() + { + AccountDescription = _savingsDefaults.BatchAccountDescription, + BankOrganizationNumber = Convert.ToInt32(_savingsDefaults.BankOrganizationNumber), + CurrentAccountStatusCode = _savingsDefaults.CurrentAccountStatusCode, + CurrentMinorAccountTypeCode = _savingsDefaults.CurrentMinorAccountTypeCode, + DeliveryMethodCode = _savingsDefaults.DeliveryMethodCode, + OwnershipCode = _savingsDefaults.OwnershipCode, + IsTaxReportedForOwner = _savingsDefaults.IsTaxReportedForOwner, + IsTaxReportedForSigner = _savingsDefaults.IsTaxReportedForSigner, + IsValid = _savingsDefaults.IsValid, + MajorAccountTypeCode = _savingsDefaults.MajorAccountTypeCode, + PersonNumber = missingSavings.CustomerNumber, + FirstName = missingSavings.FirstName, + LastName = missingSavings.LastName, + BranchOrganizationNumber = missingSavings.BranchCode + }; + return await _coreApiWrapperService.CreatePersonAccount(request); + } + + public async Task HandleUpdatingOrganzationSavingsAccounts(MissingBatchSavings missingSavings) + { + var request = new CreateOrganizationAccountRequest() + { + AccountDescription = _savingsDefaults.BatchAccountDescription, + BankOrganizationNumber = Convert.ToInt32(_savingsDefaults.BankOrganizationNumber), + CurrentAccountStatusCode = _savingsDefaults.CurrentAccountStatusCode, + CurrentMinorAccountTypeCode = _savingsDefaults.CurrentMinorAccountTypeCode, + DeliveryMethodCode = _savingsDefaults.DeliveryMethodCode, + OwnershipCode = _savingsDefaults.OwnershipCode, + IsTaxReportedForOwner = _savingsDefaults.IsTaxReportedForOwner, + IsTaxReportedForSigner = _savingsDefaults.IsTaxReportedForSigner, + IsValid = _savingsDefaults.IsValid, + MajorAccountTypeCode = _savingsDefaults.MajorAccountTypeCode, + BranchOrganizationNumber = missingSavings.BranchCode, + OrganizationNumber = missingSavings.CustomerNumber, + }; + + //If there is a control person to assign from data and the org table does not have it assigned already, assign it + if (missingSavings.ControlPersonNeeded == "Y" && missingSavings.ControlPerson != 0) + { + var basicResponse = await HandleAddControllingPerson(missingSavings); + if (!basicResponse.Success) + { + throw new Exception($"Successful:{basicResponse.Success}, " + + $"ResponseStack: {string.Join("; ", basicResponse.Errors.ToArray())}"); + } + } + + return await _coreApiWrapperService.CreateOrganizationAccount(request); + } + + public async Task HandleAddControllingPerson(MissingBatchSavings missingSavings) + { + var request = new OrganizationMaintenanceRequest() + { + ControllingPersonNumber = missingSavings.ControlPerson, + OrganizationNumber = missingSavings.CustomerNumber + }; + + BasicResponse basicResponse = await _coreApiWrapperService.AddControllingPersonOrganizationMaintenance(request); + ArgumentNullException.ThrowIfNull(basicResponse); + return basicResponse; + } + + public async Task> HandleFundingBatchSavingsAccounts(string accountNumberToFund, double fundAmount) + { + return await _coreApiWrapperService.PostFundsToAccount(accountNumberToFund, fundAmount); + } + + public async Task HandleExportResultsBatchSavingsAccounts() + { + try + { + var csvConfig = new CsvConfiguration(CultureInfo.CurrentCulture) + { + HasHeaderRecord = true, + Delimiter = ",", + Encoding = Encoding.UTF8 + }; + + var mem = new MemoryStream(); + var writer = new StreamWriter(mem); + var csvWriter = new CsvWriter(writer, csvConfig); + ArgumentNullException.ThrowIfNull(csvWriter); + + csvWriter.WriteHeader(); + csvWriter.NextRecord(); + csvWriter.WriteRecords(_missingBatchSavingsSummaryList); + + writer.Flush(); + var result = Encoding.UTF8.GetString(mem.ToArray()); + + var writeFileRequest = new WriteFileRequest() + { + DestinationPath = _dataCleanupDefaults.BatchSavingsSummarySourcePath, + FileName = "MissingBatchSavingsSummary", + Overwrite = true, + Extension = "csv", + FileData = result, + }; + + await _fileOperationsService.WriteFile(writeFileRequest); + } + catch (Exception exception) + { + throw new Exception($"Export Missing Savings Error, {exception.Message}"); + } + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateNcoaProcessService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateNcoaProcessService.cs new file mode 100644 index 0000000..c4be42b --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdateNcoaProcessService.cs @@ -0,0 +1,430 @@ +using FileHelpers; +using LCU.Api.Internal.DataCleanUp.Configuration; +using LCU.Api.Internal.DataCleanUp.Models.ParserModels; +using LCU.Api.Internal.DataCleanUp.Services.Emailers; +using LCU.Api.Internal.DataCleanUp.Services.Validation; +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.PostalAddresses; +using LCU.Library.Internal.DataCleanUpModel.Models; +using Newtonsoft.Json; +using Serilog; +using System.Globalization; +using System.Text.RegularExpressions; +using TimeZoneConverter; + +namespace LCU.Api.Internal.DataCleanUp.Services; + +public class UpdateNcoaProcessService : IUpdateNcoaProcessService +{ + private readonly ICoreApiWrapperService _coreApiWrapperService; + private readonly IFileOperationsService _fileOperationsService; + private readonly NcoaConfiguration _ncoaConfiguration; + private readonly DataCleanUpConfiguration _dataCleanUpConfiguration; + private readonly INcoaValidationService _ncoaValidationService; + private readonly INotificationsApiService _notificationsApiService; + private readonly string _errorFileHeader = "ChangeDate|UserId|PersonNumber|Name|CurrentAddress1|CurrentAddress2|CurrentAddress3|CurrentAddress4|CurrentAddress5" + + "|New Address|City|State|Zip|ZipSuffix|ErrorMessage\n"; + + public UpdateNcoaProcessService(ICoreApiWrapperService coreApiWrapperService, + IFileOperationsService fileOperationsService, + NcoaConfiguration ncoaConfiguration, + DataCleanUpConfiguration dataCleanUpConfiguration, + INcoaValidationService ncoaValidationService, + INotificationsApiService notificationsApiService) + { + _coreApiWrapperService = coreApiWrapperService; + _fileOperationsService = fileOperationsService; + _ncoaConfiguration = ncoaConfiguration; + _dataCleanUpConfiguration = dataCleanUpConfiguration; + _ncoaValidationService = ncoaValidationService; + _notificationsApiService = notificationsApiService; + } + + public async Task CleanUp(DataCleanUpRequest dataCleanUpRequest) + { + Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List()); + var ncoaProcessRequest = JsonConvert.DeserializeObject(dataCleanUpRequest.DataCleanUpPayload); + var ncoaUpdateResultList = new List(); + var exclusionList = new List(); + + try + { + var reader = new FileHelperEngine(); + + var fileRequest = _fileOperationsService.BuildDynamicFileListRequest(ncoaProcessRequest); + var fileList = await _fileOperationsService.BuildDynamicFileList(fileRequest); + + if (!fileList.Any()) + { + var noFilesFound = "No files found for Update NCOA Process"; + cleanUpResult.ResponseStack.Add(noFilesFound); + var emailSuccess = _notificationsApiService.SendEmail(ncoaProcessRequest.EmailSummaryRecipients, _ncoaConfiguration.SummaryEmailSubject, noFilesFound); + Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + return cleanUpResult; + } + + exclusionList = await GetExclusionList(ncoaProcessRequest.ExclusionFilePath); + + foreach (var filename in fileList) + { + var updateResult = await HandleFileUpdate(filename, ncoaProcessRequest, reader, exclusionList); + + ncoaUpdateResultList.Add(updateResult); + } + + cleanUpResult = await HandleBatchCompletion(ncoaUpdateResultList, cleanUpResult, ncoaProcessRequest); + } + catch (Exception ex) + { + Log.Error(ex, "Error while updating NCOA Process."); + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while updating NCOA Process. " + + $"Exception:{ex}"); + } + + Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + return cleanUpResult; + } + + public PersonAddrLine CheckForPoBoxAddressLineType(PersonAddrLine request) + { + if (request.AddressLine1.Contains(_ncoaConfiguration.PoBoxLabel)) + { + request.AddressLineTypeCode1 = _ncoaConfiguration.PoBoxAddressTypeLabel; + } + + return request; + } + + public PersonAddrLine MapPersonAddrLine(int personNumber, PersonPostalAddress currentAddress, NcoaRecord ncoaRecord) + { + var currentDateTime = GetCurrentDateTimeString("yyyy-MM-ddTHH:mm:ss.fffK"); + + var coreNcoaRequest = new PersonAddrLine() + { + PersonNumber = personNumber, + Id = _ncoaConfiguration.PrimaryAddressLabel, + AddressUseCode = _ncoaConfiguration.PrimaryAddressLabel, + AddressNumber = currentAddress.AddressNumber, + AddressLine1 = ncoaRecord.NewAddressLine, + AddressLineTypeCode1 = _ncoaConfiguration.StreetTypeLabel, + AddressLine2 = null, + AddressLineTypeCode2 = null, + AddressLine3 = null, + AddressLineTypeCode3 = null, + CityName = ConvertToTitleCase(ncoaRecord.City.ToLower()), + CountrySubdivisionCode = ncoaRecord.StateCode, + PostalCode = ncoaRecord.ZipCode, + ZipPlus = ncoaRecord.ZipSuffix.Replace("-", ""), + CountryCode = _ncoaConfiguration.UsaLabel, + Url = _ncoaConfiguration.UrlBase.Replace(_ncoaConfiguration.PersonNumberLabel, personNumber.ToString()), + IsPerformIRSCorrection = false, + EffectiveDate = GetCurrentDateTimeString("yyyy-MM-dd") + }; + + coreNcoaRequest = CheckForPoBoxAddressLineType(coreNcoaRequest); + + return coreNcoaRequest; + } + + public async Task WriteNcoaErrorFile(string data, string destination) + { + try + { + var dateString = GetCurrentDateTimeString("yyyyMMdd"); + + var writeFileRequest = new WriteFileRequest() + { + DestinationPath = destination, + FileName = dateString + _ncoaConfiguration.ErrorFileDefaultName, + Extension = ".csv", + FileData = data, + Overwrite = false + }; + + await _fileOperationsService.WriteFile(writeFileRequest); + return true; + } + catch (Exception ex) + { + Log.Error(ex, "Exception while trying to WriteNCOA Error file"); + return false; + } + } + + public string GetCurrentDateTimeString(string format) + { + var assumedTimezone = TZConvert.GetTimeZoneInfo(_dataCleanUpConfiguration.TimeZone); + + var currentDateTime = TimeZoneInfo.ConvertTime(DateTime.Now, assumedTimezone).Date; + + return currentDateTime.ToString(format); + } + + public string ConvertToTitleCase(string entry) + { + var textinfo = new CultureInfo("en-US", false).TextInfo; + + return textinfo.ToTitleCase(entry); + } + + public async Task<(DataCleanUpResult cleanUpResult, bool errorFileCreationSuccess)> CreateErrorFile(List updateResultList, string fileDestinationPath, DataCleanUpResult cleanUpResult) + { + var errorFileCreationSuccess = false; + var data = _errorFileHeader; + try + { + foreach (var updateResult in updateResultList) + { + if (updateResult.ErrorList.Count < 1) + { + cleanUpResult.ResponseStack.Add($"0 Error Records for file: {updateResult.Filename}"); + continue; + } + + foreach (var error in updateResult.ErrorList) + { + data += error; + } + } + + errorFileCreationSuccess = await WriteNcoaErrorFile(data, fileDestinationPath); + + if (!errorFileCreationSuccess) + { + throw new Exception("Affected Records: " + data); + } + } + catch (Exception ex) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error($"Error while writing NCOAError Record file. {ex.Message}"); + cleanUpResult.ResponseStack.Add($"Error while writing {_ncoaConfiguration.ErrorFileDefaultName} file. Error file not produced. Data available in Logs."); + } + + return (cleanUpResult, errorFileCreationSuccess); + } + + public async Task ProcessNcoaRecord(NcoaRecord entry, NcoaUpdateResult updateResult, + NcoaUpdateRequest ncoaProcessRequest, List exclusionList) + { + if (_ncoaValidationService.IsBusinessRecord(entry)) + { + updateResult.AddStringToErrorList(entry, "Record appears to be a business account"); + return updateResult; + } + + var currentAgreement = await _coreApiWrapperService.GetAgreementByUserId(entry.UserId); + + var personNumber = _ncoaValidationService.ParsePersonNumber(currentAgreement); + + if (personNumber <= 0) + { + updateResult.AddStringToErrorList(entry, "Unable to parse or find PersonNumber from UserId"); + return updateResult; + } + + if (_ncoaValidationService.AgreementHasOrgNumber(currentAgreement)) + { + updateResult.AddStringToErrorList(entry, "Record has an OrgNumber in Agreement from DNA"); + return updateResult; + } + + var personPostalAddressList = await _coreApiWrapperService.GetPersonPostalAddressByPersonNumber(personNumber); + + var primaryAddress = _ncoaValidationService.IsAddrUseCodeFound(personPostalAddressList, _ncoaConfiguration.PrimaryAddressLabel); + + if (primaryAddress == null) + { + updateResult.AddStringToErrorList(entry, "Unable to find a primary address by PersonNumber", personNumber.ToString()); + return updateResult; + } + + if (_ncoaValidationService.IsAddressUpdatedRecently(primaryAddress, ncoaProcessRequest.ExclusionDays, GetCurrentDateTimeString("yyyy-MM-dd"))) + { + updateResult.AddStringToErrorList(entry, $"Primary Address has been updated within the last " + + $"{Math.Abs(ncoaProcessRequest.ExclusionDays).ToString()} days.", personNumber.ToString()); + return updateResult; + } + + var coreNcoaRequest = MapPersonAddrLine(personNumber, primaryAddress, entry); + + if (_ncoaValidationService.IsAddrLineTooLong(coreNcoaRequest.AddressLine1)) + { + updateResult.AddStringToErrorList(entry, "New Address Record is greater than 40 characters. Requires manual line split", personNumber.ToString()); + return updateResult; + } + + if(_ncoaValidationService.IsOnExclusionList(coreNcoaRequest.PersonNumber, exclusionList)) + { + updateResult.AddStringToErrorList(entry, "Record matches an entry in exclusion list", personNumber.ToString()); + return updateResult; + } + + try + { + var CoreResult = await _coreApiWrapperService.UpdateAddrLineByPersonNumber(coreNcoaRequest); + } + catch (Exception ex) + { + updateResult.AddStringToErrorList(entry, "Error while upating address in CoreApi", coreNcoaRequest.PersonNumber.ToString()); + return updateResult; + } + + updateResult.AddPersonAddrLineToUpdateList(coreNcoaRequest); + return updateResult; + } + + public async Task HandleBatchCompletion(List ncoaUpdateResultList, + DataCleanUpResult cleanUpResult, NcoaUpdateRequest ncoaProcessRequest) + { + var errorFileResult = await CreateErrorFile(ncoaUpdateResultList, ncoaProcessRequest.ErrorDestinationPath, cleanUpResult); + cleanUpResult = errorFileResult.cleanUpResult; + + var totalBatchSummary = BuildTotalBatchSummary(ncoaUpdateResultList, errorFileResult.errorFileCreationSuccess); + + var batchResultSummaryText = CreateTotalBatchSummaryString(totalBatchSummary, ncoaProcessRequest.ErrorDestinationPath); + + foreach(var updateResult in totalBatchSummary.UpdateResults) + { + batchResultSummaryText += BuildFileUpdateSummary(updateResult); + } + + var emailSuccess = _notificationsApiService.SendEmail(ncoaProcessRequest.EmailSummaryRecipients, _ncoaConfiguration.SummaryEmailSubject, batchResultSummaryText); + batchResultSummaryText += $"Summary Email Request Successful: {emailSuccess}"; + + Log.Information(batchResultSummaryText); + + cleanUpResult.ResponseStack.Add(batchResultSummaryText); + return cleanUpResult; + } + + public string CreateTotalBatchSummaryString(NcoaTotalBatchSummary summary, string errorFileLocation = "") + { + return summary.ErrorFileCreated ? + $"NCOA Update Total Batch Summary:

Total Files in Batch: {summary.UpdateResults.Count}

Total Records Received: " + + $"{summary.TotalRecordsFound}

Total Records Updated: {summary.TotalRecordsUpdated}

Total Error Records: " + + $"{summary.TotalErrorRecords}

Total Records Processed: {summary.TotalRecordsUpdated + summary.TotalErrorRecords}

" + + $"Error File Created: {summary.ErrorFileCreated}

Error File Location: {errorFileLocation}

" + : + $"NCOA Update Total Batch Summary:

Total Files in Batch: {summary.UpdateResults.Count}

Total Records Received: " + + $"{summary.TotalRecordsFound}

Total Records Updated: {summary.TotalRecordsUpdated}

Total Error Records: " + + $"{summary.TotalErrorRecords}

Total Records Processed: {summary.TotalRecordsUpdated + summary.TotalErrorRecords}

" + + $"Error File Created: {summary.ErrorFileCreated}

"; + } + + public NcoaTotalBatchSummary BuildTotalBatchSummary(List updateResults, bool errorFileCreationSuccess) + { + var totalBatchSummary = new NcoaTotalBatchSummary(updateResults, errorFileCreationSuccess); + + foreach(var updateResult in totalBatchSummary.UpdateResults) + { + totalBatchSummary.TotalRecordsFound += updateResult.TotalRecordsFound; + totalBatchSummary.TotalRecordsUpdated += updateResult.UpdateList.Count; + totalBatchSummary.TotalErrorRecords += updateResult.ErrorList.Count; + } + + return totalBatchSummary; + } + + public string BuildFileUpdateSummary(NcoaUpdateResult updateResult) + { + return $"--------------

NCOA File In Batch Summary:

Filename: {updateResult.Filename}" + + $"

Total Records Received: {updateResult.TotalRecordsFound}

Total Records Updated: {updateResult.UpdateList.Count}" + + $"

Total Error Records: {updateResult.ErrorList.Count}

Total Records Processed: " + + $"{updateResult.UpdateList.Count + updateResult.ErrorList.Count}

"; + } + + public async Task HandleFileUpdate(string filename, NcoaUpdateRequest ncoaProcessRequest, FileHelperEngine reader, List exclusionList) + { + var updateResult = new NcoaUpdateResult(filename); + var fileData = await _fileOperationsService.GetContentData($"{ncoaProcessRequest.FinalSourcePath}{filename}"); + var ncoaUpdates = reader.ReadString(fileData); + updateResult.TotalRecordsFound = ncoaUpdates.Length; + + foreach (var entry in ncoaUpdates) + { + updateResult = await ProcessNcoaRecord(entry, updateResult, ncoaProcessRequest, exclusionList); + } + + return updateResult; + } + + public async Task> GetExclusionList(string filepath) + { + var exclusionList = new List(); + try + { + var exclusionListFileData = await _fileOperationsService.GetContentData(filepath); + if (!string.IsNullOrWhiteSpace(exclusionListFileData)) + { + exclusionList = exclusionListFileData.Split(_ncoaConfiguration.ExclusionListDelimiter).ToList(); + } + + return exclusionList; + } + catch (Exception ex) + { + throw new Exception($"Error while trying to retrieve or split ExclusionList. Exception: {ex.Message}"); + } + } + + public struct NcoaUpdateResult + { + public List UpdateList { get; set; } + public List ErrorList { get; set; } + public int TotalRecordsFound { get; set; } + public string Filename { get; set; } + + public NcoaUpdateResult() + { + ErrorList = new List(); + UpdateList = new List(); + TotalRecordsFound = 0; + Filename = null; + } + + public NcoaUpdateResult(string filename) + { + ErrorList = new List(); + UpdateList = new List(); + TotalRecordsFound = 0; + Filename = filename; + } + + public void AddPersonAddrLineToUpdateList(PersonAddrLine entry) + { + UpdateList.Add(entry); + } + + public void AddStringToErrorList(NcoaRecord record, string errorMessage, string personNumber = "") + { + var errorRecord = $"{record.ChangeDate}|{record.UserId}|{personNumber}|{record.PrimaryName}|{record.CurrentAddressOne}|" + + $"{record.CurrentAddressTwo}|{record.CurrentAddressThree}|{record.CurrentAddressFour}|{record.CurrentAddressFive}|" + + $"{record.NewAddressLine}|{record.City}|{record.StateCode}|{record.ZipCode}|{record.ZipSuffix.Replace("-", "")}|{errorMessage}\n"; + + ErrorList.Add(errorRecord); + } + } + + public struct NcoaTotalBatchSummary + { + public List UpdateResults { get; set; } + public int TotalRecordsFound { get; set; } + public int TotalRecordsUpdated { get; set; } + public int TotalErrorRecords { get; set; } + public bool ErrorFileCreated { get; set; } = false; + + public NcoaTotalBatchSummary(List updateResults, bool errorFileCreationSuccess) + { + UpdateResults = updateResults; + TotalErrorRecords = 0; + TotalRecordsUpdated = 0; + TotalRecordsFound = 0; + ErrorFileCreated = errorFileCreationSuccess; + } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdatePersonForAtmHoldsService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdatePersonForAtmHoldsService.cs new file mode 100644 index 0000000..9f5814f --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/UpdatePersonForAtmHoldsService.cs @@ -0,0 +1,125 @@ +using Serilog; +using TimeZoneConverter; +using Newtonsoft.Json; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Api.Internal.DataCleanUp.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Persons; +using LCU.Api.Internal.DataCleanUp.Configuration; + +namespace LCU.Api.Internal.DataCleanUp.Services; + +public class UpdatePersonForAtmHoldsService : IUpdatePersonForAtmHoldsService +{ + private readonly ICoreApiWrapperService _coreApiWrapperService; + private readonly DataCleanupDefaults _dataCleanupDefaults; + private readonly DataCleanUpConfiguration _dataCleanUpConfiguration; + + public UpdatePersonForAtmHoldsService(ICoreApiWrapperService coreApiWrapperService, DataCleanupDefaults dataCleanupDefaults, DataCleanUpConfiguration dataCleanUpConfiguration) + { + _coreApiWrapperService = coreApiWrapperService; + _dataCleanupDefaults = dataCleanupDefaults; + _dataCleanUpConfiguration = dataCleanUpConfiguration; + } + + public async Task CleanUp(DataCleanUpRequest dataCleanUpRequest) + { + Log.Information($"Starting Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + + var cleanUpResult = new DataCleanUpResult(dataCleanUpRequest, true, new List()); + + try + { + var result = JsonConvert.DeserializeObject(dataCleanUpRequest.DataCleanUpPayload); + var assumedTimezone = TZConvert.GetTimeZoneInfo(_dataCleanUpConfiguration.TimeZone); + + DateTime? resetStartDate = result.ResetStartDate.HasValue ? TimeZoneInfo.ConvertTime((DateTime)result.ResetStartDate, assumedTimezone) : null; + DateTime? resetEndDate = result.ResetEndDate.HasValue ? TimeZoneInfo.ConvertTime((DateTime)result.ResetEndDate, assumedTimezone) : null; + + var personsForUserFieldList = await _coreApiWrapperService.GetAtmCheckHoldsForPersonNumbers(resetStartDate, resetEndDate, result.FetchSize); + ArgumentNullException.ThrowIfNull(personsForUserFieldList); + Log.Information($"Data CleanUp # of Persons {personsForUserFieldList.Count()} at {DateTime.Now}"); + foreach (var person in personsForUserFieldList) + { + cleanUpResult = await HandlePersonForCheckHolds(cleanUpResult, person); + } + } + catch (Exception exception) + { + Log.Error(exception, "Error while updating Person for Atm Check Holds."); + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while updating Person for Atm Check Holds. " + + $"Exception:{exception}"); + } + + Log.Information($"Ending Data CleanUp {dataCleanUpRequest.CleanUpType} at {DateTime.Now}"); + return cleanUpResult; + } + + public async Task HandlePersonForCheckHolds(DataCleanUpResult cleanUpResult, PersonCheckHoldsUserField person) + { + try + { + var personNumber = (int)person.PersonNumber; + var response = new PersonUserField(); + var personValue = DeterminePersonUserFieldValue(person); + + if (person.UserFieldExists) + { + response = await _coreApiWrapperService.UpdateAtmCheckHoldsForPersonNumbers(personNumber, personValue); + } + else + { + response = await _coreApiWrapperService.AddAtmCheckHoldsForPersonNumbers(personNumber, personValue); + } + + if (response == null) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while updating Person { person.PersonNumber } for Atm Check Holds."); + } + } + catch(Exception exception) + { + cleanUpResult.Successful = false; + cleanUpResult.ResponseStack.Add($"Error while updating Person { person.PersonNumber } for Atm Check Holds. " + + $"Exception:{exception}"); + } + + return cleanUpResult; + } + + public string DeterminePersonUserFieldValue(PersonCheckHoldsUserField person) + { + string personUserFieldValue = ""; + var assumedTimezone = TZConvert.GetTimeZoneInfo(_dataCleanUpConfiguration.TimeZone); + DateTime checkHoldEndDateToConvert = Convert.ToDateTime(DateTime.Now.AddDays(-_dataCleanupDefaults.MemberCheckHoldsDays)); + var checkHoldEndDate = TimeZoneInfo.ConvertTime(checkHoldEndDateToConvert, assumedTimezone).Date; + + person.OldestActiveEffectiveDate = person.OldestActiveEffectiveDate.HasValue ? person.OldestActiveEffectiveDate.Value.Date : null; + person.RecentClosedEffectiveDate = person.RecentClosedEffectiveDate.HasValue ? person.RecentClosedEffectiveDate.Value.Date : null; + + var checkHoldsUserFieldValue = new CheckHoldsUserFieldValue(person, checkHoldEndDate); + + foreach (var propertyInfo in checkHoldsUserFieldValue.GetType().GetProperties()) + { + if (propertyInfo.PropertyType == typeof(bool)) + { + bool value = (bool)propertyInfo.GetValue(checkHoldsUserFieldValue, null); + + if (value == true && propertyInfo.Name.Contains("NoValue")) + { + personUserFieldValue = "N"; + break; + + } + else if (value == true && propertyInfo.Name.Contains("YesValue")) + { + personUserFieldValue = "Y"; + break; + }; + } + } + + return personUserFieldValue; + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/Validation/INcoaValidationService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/Validation/INcoaValidationService.cs new file mode 100644 index 0000000..039cab9 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/Validation/INcoaValidationService.cs @@ -0,0 +1,16 @@ +using LCU.Api.Internal.DataCleanUp.Models.ParserModels; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.PostalAddresses; + +namespace LCU.Api.Internal.DataCleanUp.Services.Validation; + +public interface INcoaValidationService +{ + bool IsBusinessRecord(NcoaRecord record); + int ParsePersonNumber(Agreement agreement); + bool AgreementHasOrgNumber(Agreement agreement); + PersonPostalAddress IsAddrUseCodeFound(IReadOnlyCollection addresses, string addrUseCode); + bool IsAddrLineTooLong(string addrLine); + bool IsAddressUpdatedRecently(PersonPostalAddress primaryAddress, int exclusionDays, string currentDateString); + bool IsOnExclusionList(int personNumber, List exclusionList); +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/Validation/NcoaValidationService.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/Validation/NcoaValidationService.cs new file mode 100644 index 0000000..f308dd3 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Services/Validation/NcoaValidationService.cs @@ -0,0 +1,70 @@ +using LCU.Api.Internal.DataCleanUp.Models.ParserModels; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.PostalAddresses; + +namespace LCU.Api.Internal.DataCleanUp.Services.Validation; + +public class NcoaValidationService : INcoaValidationService +{ + public bool IsBusinessRecord(NcoaRecord record) + { + return !string.IsNullOrWhiteSpace(record.BusinessName); + } + + public int ParsePersonNumber(Agreement agreement) + { + int personNumber; + + if (agreement == null) + { + return -1; + } + var parseResult = Int32.TryParse(agreement.PersonNumber.ToString(), out personNumber); + + if (!parseResult) + { + return -1; + } + + return personNumber; + } + + public bool AgreementHasOrgNumber(Agreement currentAgreement) + { + return currentAgreement.ByOrgNbr > 0; + } + + public PersonPostalAddress IsAddrUseCodeFound(IReadOnlyCollection addresses, string addrUseCode) + { + var selectedAddr = addresses.FirstOrDefault(address => addrUseCode.Equals(address.AddressUseCode)); + + return selectedAddr; + } + + public bool IsAddrLineTooLong(string addrLine) + { + return addrLine.Length >= 40; + } + + public bool IsAddressUpdatedRecently(PersonPostalAddress primaryAddress, int exclusionDays, string currentDateString) + { + var currentDate = new DateTime(); + + DateTime.TryParse(currentDateString, out currentDate); + + return currentDate.AddDays(exclusionDays).CompareTo(primaryAddress.LastMaintained) < 1; + } + + public bool IsOnExclusionList(int personNumber, List exclusionList) + { + foreach (var exclusion in exclusionList) + { + if(exclusion.Equals(personNumber.ToString())) + { + return true; + } + } + + return false; + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Startup.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Startup.cs new file mode 100644 index 0000000..b03d080 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Startup.cs @@ -0,0 +1,185 @@ +using System.Text.Json.Serialization; +using Newtonsoft.Json; +using Microsoft.OpenApi.Models; +using Microsoft.EntityFrameworkCore; +using Serilog; +using MassTransit; +using LCU.Library.Internal.Logging.Models; +using LCU.Library.Internal.Logging; +using LCU.Library.Internal.Logging.Middleware; +using LCU.Api.Internal.DataCleanUp.Services; +using LCU.Api.Internal.DataCleanUp.DataAccess; +using LCU.Library.Internal.LcuMassTransit; +using LCU.Library.Internal.LcuMassTransitModels; +using LCU.Api.Internal.DataCleanUp.Consumers; +using LCU.Api.Internal.DataCleanUpLib.Repositories; +using LCU.Library.Internal.ApiSecurity; +using LCU.Library.Internal.Configuration; +using LCU.Api.Internal.DataCleanUp.Services.Validation; +using LCU.Api.Internal.DataCleanUp.Configuration; +using LCU.Api.Internal.DataCleanUp.Services.Emailers; +using LCU.Api.Internal.DataCleanUpLib.Persistence; +using LCU.Library.Internal.LcuHttpClient; + +namespace LCU.Api.Internal.DataCleanUp; + +public class Startup +{ + public Startup(IConfiguration configuration) + { + Configuration = configuration; + } + public IConfiguration Configuration { get; } + readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins"; + + // This method gets called by the runtime. Use this method to add services to the container. + public void ConfigureServices(IServiceCollection services) + { + services.AddControllers(); + services.AddHttpClient(); + services.AddLCUHttpServices(); + + services.AddDbContext(options => + { + options.UseSqlServer(Configuration.GetSection("Primary").GetSection("Connections").GetSection("SQL").GetSection("LtvDb").Value); + }, ServiceLifetime.Transient); + + var dataCleanUpConfiguration = Configuration.Bind(services, "Primary"); + Configuration.Bind(services); + Configuration.Bind(services); + Configuration.Bind(services); + Configuration.Bind(services); + Configuration.Bind(services); + Configuration.Bind(services); + Configuration.Bind(services); + Configuration.Bind(services); + + services.AddApiKeySecurity(Configuration); + + var loggerConfiguration = new LoggingConfiguration(dataCleanUpConfiguration.AppName, dataCleanUpConfiguration.SeqApiKey, dataCleanUpConfiguration.SeqUrl); + var lcuLogging = new LcuLogging(loggerConfiguration); + lcuLogging.UseLcuLogging(); + + services.AddCors(options => + { + options.AddPolicy(MyAllowSpecificOrigins, + builder => + { + builder.WithOrigins( + dataCleanUpConfiguration.CorsAllowedOrigins + ).AllowAnyHeader().AllowAnyMethod(); + }); + }); + + var connectionConfiguration = MassTransitConfigurationSetUp.AddConnectionConfiguration(ref services, Configuration); + //debugging + Console.WriteLine(JsonConvert.SerializeObject(connectionConfiguration)); + var receiveEndpointConfiguration = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(Configuration, + "DataCleanUpReceiveEndpoint"); + services.AddSingleton(receiveEndpointConfiguration); + //debugging + Console.WriteLine(JsonConvert.SerializeObject(receiveEndpointConfiguration)); + AddMassTransitServices(ref services, connectionConfiguration, receiveEndpointConfiguration,dataCleanUpConfiguration); + + services.AddScoped(); + AddDataCleanUpServices(ref services); + AddDataCleanUpDataAccess(ref services); + + services.AddControllers().AddJsonOptions(options => options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter())); + services.AddSwaggerGen(c => { c.SwaggerDoc("v1", new OpenApiInfo { Title = $"{dataCleanUpConfiguration.AppName}", Version = "v1" }); }); + } + + public void AddDataCleanUpServices(ref IServiceCollection services) + { + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + + //Emailers + services.AddScoped(); + + //Validation + services.AddScoped(); + + //Repository + services.AddScoped(); + } + + public void AddDataCleanUpDataAccess(ref IServiceCollection services) + { + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + } + + public void AddMassTransitServices(ref IServiceCollection services, + ConnectionConfiguration connectionConfiguration, + ReceiveEndpointConfiguration receiveEndpointConfiguration, + DataCleanUpConfiguration dataCleanUpConfig) + { + services.AddMassTransit(x => + { + x.AddConsumer(); + + x.UsingRabbitMq((context, cfg) => + { + cfg.Host(connectionConfiguration.HostUrl, "/", host => + { + host.Username(connectionConfiguration.UserName); + host.Password(connectionConfiguration.Password); + }); + + if (dataCleanUpConfig.FeatureFlags.RunDataCleanUpConsumer) + { + cfg.ReceiveEndpoint(receiveEndpointConfiguration.ReceiveEndpoint, e => + { + e.ConfigureConsumer(context); + e.PrefetchCount = receiveEndpointConfiguration.PrefetchLimit; + e.SetQuorumQueue(); + }); + } + }); + }); + services.AddMassTransitHostedService(); + } + + // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. + public void Configure(IApplicationBuilder app, IWebHostEnvironment env) + { + if (env.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + app.UseSwagger(); + app.UseSwaggerUI(c => c.SwaggerEndpoint("v1/swagger.json", "LCU.Api.Internal.DataCleanUp v1")); + app.UseMiddleware(); + app.UseSerilogRequestLogging(options => + { + options.EnrichDiagnosticContext = RequestResponseLoggingMiddleware.RequestDataParser.EnrichFromRequest; + }); + + app.UseRouting(); + app.UseCors(MyAllowSpecificOrigins); + app.UseAuthorization(); + + app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Templates/ErrorMonitoringTemplate.html b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Templates/ErrorMonitoringTemplate.html new file mode 100644 index 0000000..bd9e94c --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Templates/ErrorMonitoringTemplate.html @@ -0,0 +1,55 @@ + + + + + + + Data Cleanup: Error Monitoring + + +

Data Cleanup: Error Monitoring

+ + + + + + + + {TableRows} + +
Error
+ + + \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Templates/ErrorRowTemplate.html b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Templates/ErrorRowTemplate.html new file mode 100644 index 0000000..917d4d8 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/Templates/ErrorRowTemplate.html @@ -0,0 +1,3 @@ + + {Error} + \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/appsettings.json b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/appsettings.json new file mode 100644 index 0000000..782114b --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUp/appsettings.json @@ -0,0 +1,187 @@ +{ + "Primary": { + "AppName": "Data CleanUp Api", + "TimeZone": "America/Chicago", + "SeqUrl": "http://localhost:5080", + "SeqApiKey": "9MQu0vLDwQ1LCFzGixZM", + "CorsAllowedOrigins": [ + "http://localhost:3000", + "http://lcu-internal.com", + "https://lcu-internal.com", + "https://qa-api.lcu-internal.com", + "https://uat-api.lcu-internal.com", + "https://api.lcu-internal.com" + ], + "Connections": { + "SQL": { + "LtvDb": "data source=bietlq;initial catalog=ETL;Integrated Security=SSPI;MultipleActiveResultSets=True;App=EntityFramework" + } + }, + "FeatureFlags": { + "RunDataCleanUpConsumer": true + } + }, + "CoreApiWrapperConfiguration": { + "CoreApiTimeout": 120, + "RetryGetAccessChannelPersonIncludes": 3, + "CoreApiWrapperUrl": "http://localhost:44355", + "GetAgreePersonsWithHyphenatedUserId": "/api/core/agreeperson/GetAgreePersonsWithHyphenatedUserId", + "GetActiveCustodialAgreePersonNumbers": "/api/core/agreeperson/GetActiveCustodialAgreePersonNumbers", + "GetActiveCustodialVruCardAgreementAgreePersons": "/api/core/agreeperson/GetActiveCustodialVruCardAgreementAgreePersons", + "GetPersonsForAtmCheckHolds": "/api/core/PersonUserField/GetPersonsForAtmCheckHolds", + "AccessChannelPersons": "/api/core/AccessChannelPersons", + "AccessType": "/api/core/AccessType", + "AccesschannelPersonWithIncludes": "/api/core/AccessChannelPersons/GetWithIncludes", + "PutPersonAgreementDetailTypes": "/api/core/agreeperson/PutPersonAgreementDetailTypes", + "GetTransactionExternalDescriptionsWithSsn": "/api/core/Transaction/GetExternalDescriptionsWithSsn", + "PutTransactionExternalDescription": "/api/core/Transaction/PutExternalDescription", + "PostFundsToAccount": "/api/core/Transaction/PostFundsToAccount", + "GetVipSavingsToFund": "/api/core/Account/GetVipSavingsToFund", + "GetAccountsByMajorMinorBranchAndStatus": "/api/core/Account/GetAccountsByMajorMinorBranchAndStatus", + "GetAdminBranchCodeChangeAccountNumbers": "/api/core/Account/GetAdminBranchCodeChangeAccountNumbers", + "GetAccountsForGroupAnalysis": "/api/core/Account/GetAccountsForGroupAnalysis", + "PutAccountBranchCode": "/api/core/Account/PutAccountBranchCode", + "PutAccountLoanToValue": "/api/core/Account/PutAccountLoanToValue", + "PutAccountAnalysisGroup": "/api/core/Account/PutAccountAnalysisGroup", + "PutPersonUserFieldForAtmCheckHolds": "/api/core/PersonUserField/PutPersonUserFieldForAtmCheckHolds", + "PostPersonUserFieldForAtmCheckHolds": "/api/core/PersonUserField/PostPersonUserFieldForAtmCheckHolds", + "PostOrganizationAccount": "/api/core/Account/PostOrganizationAccount", + "PostPersonAccount": "/api/core/Account/PostPersonAccount", + "PutOrganizationMaintenanceRequest": "/api/core/Account/PutOrganizationMaintenanceRequest", + "PutAccountNickNameUpdateRequest": "/api/core/Account/PutAccountNickNameUpdateRequest", + "GetAgreementByUserId": "/api/core/Agree/AgreementByUserId/{userId}", + "GetPersonPostalAddressByPersonNumber": "/api/core/Address/GetByPersonNumber", + "PutAddrLineByPersonNumber": "/api/core/Address/UpdatePersonAddrLine", + "PutAccountCreditReportType": "/api/core/Account/PutAccountCreditReportType", + "GetPropertyNumberByAccountNumber": "/api/core/Loan/GetPropertyInformation", + "GetAccountByAccountNumber": "/api/core/Account/GetAccountByAccountNumber", + "PropertyUserField": "/api/core/PropertyUserField", + "PostPropertyUserField": "/api/core/PropertyUserField/PostPropertyUserField", + "PutPropertyUserField": "/api/core/PropertyUserField/PutPropertyUserField", + "PutPersonUserField": "/api/core/PersonUserField/PutPersonUserField", + "PostPersonUserField": "/api/core/PersonUserField/PostPersonUserField", + "PersonUserField": "/api/core/PersonUserField", + "AccountUserField": "/api/core/AccountUserField" + }, + "FileOperationsConfiguration": { + "FileOperationsUrl": "https://qa-fileoperationsapi.lcu-internal.com", + "GetFile": "/api/FileOperations/", + "WriteFile": "/api/FileOperations/WriteFileData", + "BuildDynamicFileList": "/DynamicFile/BuildDynamicFileList" + }, + "ConnectionConfiguration": { + "HostUrl": "localhost", + "UserName": "guest", + "Password": "guest" + }, + "DataCleanUpReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DataCleanUp", + "ReceiveEndpointType": "exchange", + "PrefetchLimit": 1 + }, + "SavingsMissingRequirementsDefaults": { + "SavingDefaults": { + "AccountDescription": "VIP SAVINGS", + "BatchAccountDescription": "SV01", + "BankOrganizationNumber": 1, + "CurrentMinorAccountTypeCode": "SV01", + "DeliveryMethodCode": "PRNT", + "MajorAccountTypeCode": "SAV", + "OwnershipCode": "S", + "IsTaxReportedForOwner": true, + "IsTaxReportedForSigner": true, + "IsValid": true, + "CurrentAccountStatusCode": "APPR" + }, + "FundsToAccountDefaults": { + "Description": "Opening Deposit", + "GLAccountNumber": 19619869597, + "TransactionTypeCodeGL": "GLD", + "TransactionTypeCodeDeposit": "DEP", + "FundsDefaults": { + "ClearingCategoryCode": "IMED", + "FundAmount": 5.00, + "FundTypeCode": "EL", + "FundTypeDetailCode": "INTR" + } + } + }, + "IndirectSavingsRequirementsDefaults": { + "Description": "Opening Deposit", + "GLAccountNumber": 19617806783, + "TransactionTypeCodeGL": "GLD", + "TransactionTypeCodeDeposit": "DEP", + "FundsDefaults": { + "ClearingCategoryCode": "IMED", + "FundAmount": 5.00, + "FundTypeCode": "EL", + "FundTypeDetailCode": "INTR" + }, + "FundingCoreRequests": { + "MajorAccountTypes": [ "SAV" ], + "MinorAccountTypes": [ "SV01", "BS01" ], + "BranchCodeTypes": [ "1310" ], + "AccountStatusTypes": [ "APPR" ] + } + }, + "DataCleanUpDefaults": { + "DigitalBankingBranchCode": "1210", + "MemberCheckHoldsUserFieldCode": "MBRH", + "MemberCheckHoldsDays": 29, + "BatchAddFunds": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchAddFunds\\NeedToFund.csv", + "BatchAddFundsSummarySourcePath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchAddFunds\\", + "BatchSavingsSourcePath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchSavings\\MissingBatchSavings.csv", + "BatchSavingsSummarySourcePath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchSavings\\", + "AccountNicknameSourcePath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchSavings\\Nickname update.csv", + "PmiCancelSourcePath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\PMICancel\\PMI Cancel.csv", + "PmiCancelSummaryPath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\PMICancel\\", + "LtvExcludedMinorAccountTypes": [ + "DL01", + "DL02", + "DL03", + "DL04", + "DL05", + "DL06", + "DL07", + "DL08", + "DL09", + "DL10", + "DL11", + "DL12", + "DL13", + "DL14", + "DL15", + "DL16" + ] + }, + "NcoaConfiguration": { + "PrimaryAddressLabel": "PRI", + "StreetTypeLabel": "ST", + "UrlBase": "/Persons/{personNumber}/PostalAddresses/PRI", + "UsaLabel": "USA", + "PoBoxLabel": "PO BOX", + "PoBoxAddressTypeLabel": "POBN", + "ErrorFileDefaultName": "NCOAErrorRecord", + "PersonNumberLabel": "{personNumber}", + "SummaryEmailSubject": "NCOA Process Summary Email", + "ExclusionListDelimiter": "|" + }, + "FannieMaeConfiguration": { + "ErrorFileDefaultName": "FannieMaeErrorRecord", + "SummaryEmailSubject": "Fannie Mae Mortgage Summary Email", + "FileDateFormat": "M/d/yyyy", + "DnaDateFormat": "yyyy-MM-dd", + "PoolDateUserFieldId": "PLDT", + "PoolNbrUserFieldId": "PLNB" + }, + "NotificationsApiConfiguration": { + "EmailEndpoint": "https://qa-notifications-api.apps.azure.lcu-internal.com/api/Email" + }, + "ApiSecurityConfiguration": { + "ApiKeyAuthenticationFailureBehavior": "Error", + "InternalApiKeySet": { + "DataCleanUp": "772e2926-78b5-4884-88da-73e2c23fad71" + }, + "ExternalApiKeySet": {} + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/Extensions/QueryableExcludeMinorAccountType.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/Extensions/QueryableExcludeMinorAccountType.cs new file mode 100644 index 0000000..8e48666 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/Extensions/QueryableExcludeMinorAccountType.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Linq; +using LCU.Library.Internal.DataCleanUpModel.Entities; + +namespace LCU.Api.Internal.DataCleanUpLib.Extensions +{ + public static class QueryableExcludeMinorAccountType + { + public static IQueryable ExcludeMinorAccountType(this IQueryable queryable, List listExcludedMinorAccountTypes) + { + if (listExcludedMinorAccountTypes == null || !listExcludedMinorAccountTypes.Any()) + { + return queryable; + } + + return queryable.Where(ltv_DataCleanUp => !listExcludedMinorAccountTypes.Contains(ltv_DataCleanUp.MinorType)); + } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/LCU.Api.Internal.DataCleanUpLib.csproj b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/LCU.Api.Internal.DataCleanUpLib.csproj new file mode 100644 index 0000000..5a42fe8 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/LCU.Api.Internal.DataCleanUpLib.csproj @@ -0,0 +1,18 @@ + + + + net8.0 + + + + + + + + + + + + + + diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/Persistence/AppDbContext.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/Persistence/AppDbContext.cs new file mode 100644 index 0000000..b476b90 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/Persistence/AppDbContext.cs @@ -0,0 +1,18 @@ +using LCU.Library.Internal.DataCleanUpModel.Entities; +using Microsoft.EntityFrameworkCore; + +namespace LCU.Api.Internal.DataCleanUpLib.Persistence +{ + public class AppDbContext : DbContext + { + public DbSet LtvDataCleanUp { get; set; } + + public AppDbContext(DbContextOptions options) : base(options) { } + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + builder.Entity().ToTable("LTV_DataCleanUp"); + } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/Repositories/BaseRepository.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/Repositories/BaseRepository.cs new file mode 100644 index 0000000..7bb3171 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/Repositories/BaseRepository.cs @@ -0,0 +1,14 @@ +using LCU.Api.Internal.DataCleanUpLib.Persistence; + +namespace LCU.Api.Internal.DataCleanUpLib.Repositories +{ + public abstract class BaseRepository + { + protected readonly AppDbContext _context; + + public BaseRepository(AppDbContext context) + { + _context = context; + } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/Repositories/ILtvDataCleanUpRepository.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/Repositories/ILtvDataCleanUpRepository.cs new file mode 100644 index 0000000..ea7a9a7 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/Repositories/ILtvDataCleanUpRepository.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.Library.Internal.DataCleanUpModel.Entities; + +namespace LCU.Api.Internal.DataCleanUpLib.Repositories +{ + public interface ILtvDataCleanUpRepository + { + Task> ListMinorAccountTypeAsync(List listExcludedMinorTypes); + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/Repositories/LtvDataCleanUpRepository.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/Repositories/LtvDataCleanUpRepository.cs new file mode 100644 index 0000000..8259416 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpLib/Repositories/LtvDataCleanUpRepository.cs @@ -0,0 +1,19 @@ +using Microsoft.EntityFrameworkCore; +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.Api.Internal.DataCleanUpLib.Extensions; +using LCU.Library.Internal.DataCleanUpModel.Entities; +using LCU.Api.Internal.DataCleanUpLib.Persistence; + +namespace LCU.Api.Internal.DataCleanUpLib.Repositories +{ + public class LtvDataCleanUpRepository : BaseRepository, ILtvDataCleanUpRepository + { + public LtvDataCleanUpRepository(AppDbContext context) : base(context) { } + + public async Task> ListMinorAccountTypeAsync(List listExcludedMinorAccountTypes) + { + return await _context.LtvDataCleanUp.ExcludeMinorAccountType(listExcludedMinorAccountTypes).ToListAsync(); + } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/DataAccess/CoreApiWrapperDaoTest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/DataAccess/CoreApiWrapperDaoTest.cs new file mode 100644 index 0000000..8bb644a --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/DataAccess/CoreApiWrapperDaoTest.cs @@ -0,0 +1,430 @@ +using Moq; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq; +using TestTool = Microsoft.VisualStudio.TestTools.UnitTesting; +using LCU.Api.Internal.DataCleanUp.Configuration; +using LCU.Api.Internal.DataCleanUp.DataAccess; +using LCU.Library.Internal.ApiSecurity.Enums; +using LCU.Library.Internal.ApiSecurity.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; +using LCU.Library.Internal.LcuHttpClient.HttpRequest; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessChannelPersons; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessTypes; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts; + +namespace LCU.Api.Internal.DataCleanUpTest.DataAccess; + +public class CoreApiWrapperDaoTest +{ + private const string ClientKeyValue = "DataCleanUp"; + private Mock _mockgetRequest; + private Mock _mockpostRequest; + private Mock _mockputRequest; + private CoreApiWrapperDao _coreApiWrapperDaoWithSecurityKey; + private CoreApiWrapperDao _coreApiWrapperDaoWithoutSecurityKey; + + private readonly ApiSecurityConfiguration _apiSecurityConfigurationWithInternalKey = new ApiSecurityConfiguration() + { + ApiKeyAuthenticationFailureBehavior = ApiKeyAuthenticationFailureBehavior.Error, + ExternalApiKeySet = new Dictionary(), + InternalApiKeySet = new Dictionary() + { + { ClientKeyValue, "some_guid-1234-5666" } + } + }; + + private readonly ApiSecurityConfiguration _apiSecurityConfigurationWithoutInternalKey = new ApiSecurityConfiguration() + { + ApiKeyAuthenticationFailureBehavior = ApiKeyAuthenticationFailureBehavior.Error, + ExternalApiKeySet = new Dictionary(), + InternalApiKeySet = new Dictionary() + }; + + private readonly CoreApiWrapperConfiguration _coreApiWrapperConfiguration = new CoreApiWrapperConfiguration() + { + CoreApiWrapperUrl = "https://localhost:44364", + AccessChannelPersons = "/api/core/AccessChannelPersons", + AccesschannelPersonWithIncludes = "/api/core/AccessChannelPersons/GetWithIncludes", + PostFundsToAccount = "/api/core/Transaction/PostFundsToAccount", + PutAccountNickNameUpdateRequest = "/api/core/Account/PutAccountNickNameUpdateRequest", + }; + + [SetUp] + public void Setup() + { + _mockpostRequest = new Mock(); + _mockputRequest = new Mock(); + _mockgetRequest = new Mock(); + _coreApiWrapperDaoWithSecurityKey = new CoreApiWrapperDao(_apiSecurityConfigurationWithInternalKey, _coreApiWrapperConfiguration, _mockpostRequest.Object, _mockputRequest.Object, _mockgetRequest.Object); + _coreApiWrapperDaoWithoutSecurityKey = new CoreApiWrapperDao(_apiSecurityConfigurationWithoutInternalKey, _coreApiWrapperConfiguration, _mockpostRequest.Object, _mockputRequest.Object, _mockgetRequest.Object); + } + + [Test] + public async Task GetRequest_GetCoreApiMessageAccessChannelPersonsWithIncludesSecurityKeys_Success() + { + + var accessChannelPersonsByPersonRequest = new AccessChannelPersonsByPersonRequest() + { + PersonNumber = 145, + ActiveOnly = true, + IncludeCards = false + }; + + var testPersonNumbers = new List() + { + "111111" + }; + + var coreMessageHeader = new CoreMessageHeader() + { + UpdateKey = 12312312323123 + }; + + var testAccessType = new AccessType() + { + Id = "WWW", + IsActive = true + }; + var testAccessChannelPerson = new AccessChannelPerson() + { + Id = "2313213_1", + ChannelNumber = 2313213, + PersonNumber = 1, + UserId = "2312312312", + AccessTypes = new List() + { + testAccessType + } + }; + var testAccessChannelPersons = new List() + { + testAccessChannelPerson , + new AccessChannelPerson() + { + PersonNumber = 1, + UserId= "1C1", + AccessTypes = new List() + { + new AccessType() + { + Id= "VRU", + IsActive = true + } + } + } + }; + + var coreApiMessage = new CoreApiMessage>(coreMessageHeader, testAccessChannelPersons); + _mockgetRequest.Setup(x => x.AsyncWithNewton>>(It.IsAny(), It.IsAny>(),It.IsAny(), It.IsAny())).ReturnsAsync(coreApiMessage).Verifiable(); + + var response = await _coreApiWrapperDaoWithSecurityKey.GetCoreApiMessageAccessChannelPersons(accessChannelPersonsByPersonRequest, testPersonNumbers); + + Assert.IsNotNull(response); + Assert.AreEqual(2, response.MessageBody.Count()); + } + + [Test] + public async Task GetRequest_GetCoreApiMessageAccessChannelPersonsWithIncludesSecurityKeys_NoResponse() + { + + var accessChannelPersonsByPersonRequest = new AccessChannelPersonsByPersonRequest() + { + + }; + + var testPersonNumbers = new List() + { + + }; + + var response = await _coreApiWrapperDaoWithSecurityKey.GetCoreApiMessageAccessChannelPersons(accessChannelPersonsByPersonRequest, testPersonNumbers); + Assert.IsNotNull(_mockgetRequest); + Assert.AreEqual(null, response); + } + + [Test] + public async Task GetRequest_GetCoreApiMessageAccessChannelPersonsWithSecurityKeys_Success() + { + var accessChannelPersonsByPersonRequest = new AccessChannelPersonsByPersonRequest() + { + PersonNumber = 145, + ActiveOnly = true, + IncludeCards = false + }; + + var coreMessageHeader = new CoreMessageHeader() + { + UpdateKey = 12312312323123 + }; + + var testAccessChannelPersons = new List() + { + new AccessChannelPerson() + { + PersonNumber = 1, + UserId= "1C1", + AccessTypes = new List() + { + new AccessType() + { + Id = "WWW", + IsActive = true + } + } + } + }; + + var coreApiMessage = new CoreApiMessage>(coreMessageHeader, testAccessChannelPersons); + _mockgetRequest.Setup(x => x.Async>>(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(coreApiMessage).Verifiable(); + + var response = await _coreApiWrapperDaoWithSecurityKey.GetCoreApiMessageAccessChannelPersons(accessChannelPersonsByPersonRequest); + + Assert.IsNotNull(_mockgetRequest); + Assert.IsNotNull(response); + } + + [Test] + public async Task GetRequest_GetCoreApiMessageAccessChannelPersonsWithKeys_NoResponse() + { + var accessChannelPersonsByPersonRequest = new AccessChannelPersonsByPersonRequest() + { + + }; + + var response = await _coreApiWrapperDaoWithSecurityKey.GetCoreApiMessageAccessChannelPersons(accessChannelPersonsByPersonRequest); + + Assert.IsNotNull(_mockgetRequest); + Assert.AreEqual(null, response); + } + + [Test] + public async Task PostRequest_PostFundsWithSecurityKeys_Success() + { + var listFundsRequest = new List() + { + new FundsToAccountRequest() + { + AccountNumber = 111, + Description = "Test", + TransactionAmount = 4 * -1, + TransactionTypeCode = "MOB", + FundRequests = new List() + { + new FundRequest() + { + ClearingCategoryCode = "Test", + FundAmount = 4 * -1, + FundTypeCode = "Test", + FundTypeDetailCode = "Test" + } + } + }, + + new FundsToAccountRequest() + { + AccountNumber = 222, + Description = "Test2", + TransactionAmount = 4, + TransactionTypeCode = "DEP", + FundRequests = new List() + { + new FundRequest() + { + ClearingCategoryCode = "Test", + FundAmount = 4, + FundTypeCode = "Test", + FundTypeDetailCode = "Test" + } + } + } + }; + + //Set Up Response + var basicResponse = new BasicResponse() + { + Success = true, + Errors = new List() + }; + + var basicResponseList = new List() { basicResponse }; + + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.PostFundsToAccount}"; + var uri = new Uri(path); + + _mockpostRequest.Setup(x => x.Async, List>(It.IsAny(), It.IsAny>(), It.IsAny>(), It.IsAny(), It.IsAny())).ReturnsAsync(basicResponseList).Verifiable(); + + var response = await _coreApiWrapperDaoWithSecurityKey.PostFundsToAccount(listFundsRequest); + + Assert.IsNotNull(_mockpostRequest); + Assert.AreEqual(true, response[0].Success); + } + + [Test] + [TestTool.ExpectedException(typeof(System.Exception), AllowDerivedTypes=true)] + public async Task PostRequest_PostFundsWithOutSecurityKeys_Exception() + { + var listFundsRequest = new List() + { + new FundsToAccountRequest() + { + AccountNumber = 111, + Description = "Test", + TransactionAmount = 4 * -1, + TransactionTypeCode = "MOB", + FundRequests = new List() + { + new FundRequest() + { + ClearingCategoryCode = "Test", + FundAmount = 4 * -1, + FundTypeCode = "Test", + FundTypeDetailCode = "Test" + } + } + }, + + new FundsToAccountRequest() + { + AccountNumber = 222, + Description = "Test2", + TransactionAmount = 4, + TransactionTypeCode = "DEP", + FundRequests = new List() + { + new FundRequest() + { + ClearingCategoryCode = "Test", + FundAmount = 4, + FundTypeCode = "Test", + FundTypeDetailCode = "Test" + } + } + } + }; + + Assert.That(() => _coreApiWrapperDaoWithoutSecurityKey.PostFundsToAccount(listFundsRequest), + Throws.TypeOf()); //Message will be Your Internal Key is Missing + } + + [Test] + public async Task PutRequest_PutAccountNickNameWithSecurityKeys_Success() + { + var request = new AccountNickNameUpdateRequest() + { + AccountDescription = "Test", + AccountNumber = 1, + }; + + //Set Up Response + var basicResponse = new BasicResponse() + { + Success = true, + Errors = new List() + }; + + _mockputRequest.Setup(x => x.Async(It.IsAny(), It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny())).ReturnsAsync(basicResponse).Verifiable(); + + var response = await _coreApiWrapperDaoWithSecurityKey.PutAccountNicknameUpdateRequest(request); + + Assert.IsNotNull(_mockputRequest); + Assert.AreEqual(true, response.Success); + } + + [Test] + public async Task PutRequest_PutAccountUserField_Success() + { + var request = new List() + { + new AccountUserField() + { + UserFieldCode = "PLNB", + AccountNumber = 1, + Value = "CC2233" + } + }; + + var userFieldResponse = new List() + { + new AccountUserField() + { + UserFieldCode = "PLNB", + AccountNumber = 1, + Value = "CC2233" + } + }; + + _mockputRequest.Setup(x => x.Async, IEnumerable>(It.IsAny(), It.IsAny>(), It.IsAny>(), It.IsAny(), It.IsAny())).ReturnsAsync(userFieldResponse).Verifiable(); + + var response = await _coreApiWrapperDaoWithSecurityKey.PutAccountUserField(request); + + Assert.IsNotNull(_mockputRequest); + Assert.AreEqual(1, response.Count()); + } + + [Test] + public async Task PostRequest_PostAccountUserField_Success() + { + var request = new List() + { + new AccountUserField() + { + UserFieldCode = "PLDT", + AccountNumber = 1, + Value = "6/1/2023" + } + }; + + var userFieldResponse = new List() + { + new AccountUserField() + { + UserFieldCode = "PLDT", + AccountNumber = 1, + Value = "6/1/2023" + } + }; + + _mockpostRequest.Setup(x => x.Async, IEnumerable>(It.IsAny(), It.IsAny>(), It.IsAny>(), It.IsAny(), It.IsAny())).ReturnsAsync(userFieldResponse).Verifiable(); + + var response = await _coreApiWrapperDaoWithSecurityKey.PostAccountUserField(request); + + Assert.IsNotNull(_mockpostRequest); + Assert.AreEqual(1, response.Count()); + } + + [Test] + public async Task GetRequest_GetAccountUserField_Success() + { + var acctNbr = 993934933333333; + + var userFieldResponse = new List() + { + new AccountUserField() + { + UserFieldCode = "PLDT", + AccountNumber = 993934933333333, + Value = "6/1/2023" + } + }; + + var coreMessageHeader = new CoreMessageHeader() + { + UpdateKey = 12312312323123 + }; + + var coreApiMessage = new CoreApiMessage>(coreMessageHeader, userFieldResponse); + _mockgetRequest.Setup(x => x.AsyncWithNewton>>(It.IsAny(), It.IsAny>(), It.IsAny(), It.IsAny())).ReturnsAsync(coreApiMessage).Verifiable(); + + var response = await _coreApiWrapperDaoWithSecurityKey.GetAccountUserField(acctNbr); + + Assert.IsNotNull(_mockgetRequest); + Assert.AreEqual(1, response.Count()); + } +} + + diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/DataAccess/FileOperationsDaoTest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/DataAccess/FileOperationsDaoTest.cs new file mode 100644 index 0000000..0ceef92 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/DataAccess/FileOperationsDaoTest.cs @@ -0,0 +1,112 @@ +using Moq; +using NUnit.Framework; +using System.Linq; +using System; +using System.Threading.Tasks; +using System.Collections.Generic; +using LCU.Api.Internal.DataCleanUp.Configuration; +using LCU.Api.Internal.DataCleanUp.DataAccess; +using LCU.Library.Internal.LcuHttpClient.HttpRequest; +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.Library.Internal.FileOperationsModels.Models.NameSettings; +namespace LCU.Api.Internal.DataCleanUpTest.DataAccess; + +public class FileOperationsDaoTest +{ + private Mock _mockgetRequest; + private Mock _mockpostRequest; + private FileOperationsDao _fileOperationsDao; + + private readonly FileOperationsConfiguration _fileOperationsConfiguration = new FileOperationsConfiguration() + { + FileOperationsUrl = "https://localhost:44555", + GetFile = "/api/FileOperations/", + WriteFile = "/api/FileOperations/WriteFileData", + BuildDynamicFileList = "/DynamicFile/BuildDynamicFileList" + }; + + [SetUp] + public void Setup() + { + _mockpostRequest = new Mock(); + _mockgetRequest = new Mock(); + _fileOperationsDao = new FileOperationsDao(_fileOperationsConfiguration, _mockpostRequest.Object, _mockgetRequest.Object); + } + + [Test] + public async Task GetFileContentTest_Success() + { + var filename = "testfile.txt"; + var finalFilePath = new string($"{_fileOperationsConfiguration.GetFile}{filename}"); + var testContents = "This is my file content."; + + _mockgetRequest.Setup(x => x.StringResponseAsync(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(testContents).Verifiable(); + + var response = await _fileOperationsDao.GetFileContent(finalFilePath); + + Assert.IsNotNull(response); + Assert.AreEqual("This is my file content.", response); + } + + [Test] + public async Task WriteFileTest_Success() + { + var writeFileRequest = new WriteFileRequest() + { + DestinationPath = "/testDestination", + FileName = "mytestfile.txt" + }; + + var path = $"{_fileOperationsConfiguration.FileOperationsUrl}{_fileOperationsConfiguration.WriteFile}"; + var uri = new Uri(path); + + var listStringFiles = new List() + { + "Testcleanupfile.csv", + "Testcleanupfile.pdf" + }; + + _mockpostRequest.Setup(x => x.AsyncWithNewton>(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(listStringFiles).Verifiable(); + + var response = await _fileOperationsDao.WriteFile(writeFileRequest); + Assert.IsNotNull(response); + _mockpostRequest.Verify(); + + } + + [Test] + public async Task BuildDynamicFileList_Success() + { + var dynamicFileListRequest = new DynamicFileListRequest() + { + DynamicFileSettings = new DynamicNameSetting + { + DateFormatSettings = null, + DaysFromToday = 0, + RegexSettings = null, + }, + Filename = "mytestfile.txt", + Path = "//network/Test/" + }; + + var listStringFiles = new List() + { + "Testfile.csv", + "Testfile.pdf" + }; + + var path = $"{_fileOperationsConfiguration.FileOperationsUrl}{_fileOperationsConfiguration.BuildDynamicFileList}"; + var uri = new Uri(path); + + _mockpostRequest.Setup(x => x.Async>(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(listStringFiles).Verifiable(); + + var response = await _fileOperationsDao.BuildDynamicFileList(dynamicFileListRequest); + + Assert.IsNotNull(response); + Assert.AreEqual(2, response.Count()); + Assert.AreEqual("Testfile.pdf", response.Last()); + } +} + + + diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/LCU.Api.Internal.DataCleanUpTest.csproj b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/LCU.Api.Internal.DataCleanUpTest.csproj new file mode 100644 index 0000000..8128158 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/LCU.Api.Internal.DataCleanUpTest.csproj @@ -0,0 +1,46 @@ + + + + net8.0 + enable + + false + + + + 1701;1702;8604;8605 + + + + 1701;1702;8604;8605 + + + + + + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + Always + + + + diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Repositories/DbContextFromJson.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Repositories/DbContextFromJson.cs new file mode 100644 index 0000000..b752cd6 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Repositories/DbContextFromJson.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.IO; +using Microsoft.EntityFrameworkCore; +using Newtonsoft.Json.Linq; +using LCU.Library.Internal.DataCleanUpModel.Entities; +using LCU.Api.Internal.DataCleanUpLib.Persistence; + +namespace LCU.Api.Internal.DataCleanUpTest.RepositoryTests; + +public class DbContextTestSet +{ + public IReadOnlyCollection? Ltv_DataCleanUps { get; set; } + +} + +public abstract class DbContextFromJsonTest +{ + private const string RepositoryFolder = "Repositories"; + private const string LtvFileName = "loanToValue_repo"; + public DbContextTestSet GetTestRecords() + { + var testSet = new DbContextTestSet(); + + // Get the absolute path to the JSON file + var basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory); + var path = $"{ basePath}//{RepositoryFolder}//{LtvFileName}.json"; + + if (!File.Exists(path)) + { + throw new ArgumentException($"Could not find file at path: {path}"); + } + + var fileData = File.ReadAllText(path); + var allData = JObject.Parse(fileData); + + var data = allData["Ltv_DataCleanUps"]; + testSet.Ltv_DataCleanUps = data.ToObject>(); + + return testSet; + } + + public AppDbContext GetBlankContext() + { + var options = new DbContextOptionsBuilder() + .UseInMemoryDatabase(Guid.NewGuid().ToString()) + .Options; + return new AppDbContext(options); + } + + public AppDbContext GetContextWithData() + { + var options = new DbContextOptionsBuilder() + .UseInMemoryDatabase(Guid.NewGuid().ToString()) + .Options; + var context = new AppDbContext(options); + + var testData = GetTestRecords(); + AddTo(context.LtvDataCleanUp, testData.Ltv_DataCleanUps); + + context.SaveChanges(); + + return context; + } + + private static void AddTo(DbSet collection, IEnumerable range) where T : class + { + if (range != null) collection.AddRange(range); + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Repositories/UpdateAccountLoanToValueRepositoryTest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Repositories/UpdateAccountLoanToValueRepositoryTest.cs new file mode 100644 index 0000000..b6dd1e2 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Repositories/UpdateAccountLoanToValueRepositoryTest.cs @@ -0,0 +1,41 @@ +using LCU.Api.Internal.DataCleanUpLib.Repositories; +using LCU.Api.Internal.DataCleanUpTest.RepositoryTests; +using Xunit; +using Moq; +using System.Collections.Generic; +using System.Linq; +using LCU.Api.Internal.DataCleanUp.Configuration; + +namespace LCU.Api.Internal.DataCleanUpTest.Repositories; +public class UpdateAccountLoanToValueRepositoryTest : DbContextFromJsonTest +{ + private readonly LtvDataCleanUpRepository _ltvRepository; + private readonly Mock _mockDataCleanupDefaults; + + + public UpdateAccountLoanToValueRepositoryTest() + + { + var dbContext = GetContextWithData(); + _mockDataCleanupDefaults = new Mock(); + _mockDataCleanupDefaults.Object.LtvExcludedMinorAccountTypes = new List () + { + "DL01", "DL02", "DL03", "DL04", "DL05", "DL06", "DL07", "DL08", "DL09", "DL10", "DL11", "DL12", "DL13", "DL14", "DL15", "DL16" + }; + + _ltvRepository = new LtvDataCleanUpRepository(dbContext); + } + + [Fact] + public async void ExcludedListAsync_Return_1() //DL01 minor account type is filtered + { + var resultsBasic = await _ltvRepository.ListMinorAccountTypeAsync(_mockDataCleanupDefaults.Object.LtvExcludedMinorAccountTypes); + + //Assert + Assert.NotNull(resultsBasic); + Assert.Single(resultsBasic); + Assert.Equal("SV01", resultsBasic.First().MinorType); + } + +} + diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Repositories/loanToValue_repo.json b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Repositories/loanToValue_repo.json new file mode 100644 index 0000000..5fa2055 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Repositories/loanToValue_repo.json @@ -0,0 +1,14 @@ +{ + "Ltv_DataCleanUps": [ + { + "AccountNumber": "1111111", + "Ltv": ".1", + "MinorType": "DL01" + }, + { + "AccountNumber": "2222222", + "Ltv": ".2", + "MinorType": "SV01" + } + ] +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/AddFundsToIndirectSavingsAccountsServiceTest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/AddFundsToIndirectSavingsAccountsServiceTest.cs new file mode 100644 index 0000000..578652d --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/AddFundsToIndirectSavingsAccountsServiceTest.cs @@ -0,0 +1,272 @@ +using Moq; +using NUnit.Framework; +using Newtonsoft.Json; +using System.Linq; +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.Api.Internal.DataCleanUp.Configuration; +using LCU.Api.Internal.DataCleanUp.Models; +using LCU.Api.Internal.DataCleanUp.Services; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Library.Internal.DataCleanUpModel.Enum; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; + +namespace LCU.Api.Internal.DataCleanUpTest.Services; + +public class AddFundsToIndirectSavingsAccountsServiceTest +{ + private AddFundsToIndirectSavingsAccountsService _addFundsToIndirectSavingsAccountsService; + private Mock _mockCoreApiWrapperService; + private Mock _mockFileOperationsService; + private DataCleanUpConfiguration _dataCleanUpConfiguration; + private IndirectSavingsRequirementsDefaults _indirectSavingsRequirementsDefaults; + private DataCleanUpResult _dataCleanUpResult; + + [SetUp] + public void Setup() + { + _dataCleanUpConfiguration = new DataCleanUpConfiguration() + { + TimeZone = "America/Chicago" + }; + + _indirectSavingsRequirementsDefaults = new IndirectSavingsRequirementsDefaults() + { + Description = "test", + GLAccountNumber = "123445", + TransactionAmount = 5.00, + TransactionTypeCode = "test", + TransactionTypeCodeDeposit = "test", + TransactionTypeCodeGL = "test", + FundsDefaults = new FundsDefaults() + { + ClearingCategoryCode = "IMED", + FundAmount = 5.00, + FundTypeCode = "EL", + FundTypeDetailCode = "INTR" + }, + FundingCoreRequests = new FundingCoreRequests() + { + AccountStatusTypes = new List() { "APPR" }, + BranchCodeTypes = new List() { 1310 }, + MajorAccountTypes = new List() { "SAV" }, + MinorAccountTypes = new List() { "SV01", "BS01" } + } + }; + + _mockCoreApiWrapperService = new Mock(); + _mockFileOperationsService = new Mock(); + _addFundsToIndirectSavingsAccountsService = new AddFundsToIndirectSavingsAccountsService(_mockCoreApiWrapperService.Object, + _mockFileOperationsService.Object, + _indirectSavingsRequirementsDefaults, + _dataCleanUpConfiguration); + } + + [Test] + public async Task HandleCleanUp_Ok() + { + var indirectRequest = new IndirectFundingRequest() + { + Filename = "Test", + SummaryFileDestinationPath = "Test" + }; + + var dataCleanUpRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.AddFundsToIndirectSavingsAccounts, + DataCleanUpPayload = JsonConvert.SerializeObject(indirectRequest) + }; + + var response = new List() + { + new AccountsByMajorMinorBranchAndStatusResponse() + { + AccountNumber = 1, + BranchCode = 1, + Name = "Test" + } + }; + + var basicResponse = new BasicResponse() + { + Success = true, + Errors = new List() + }; + + var basicResponseList = new List() { basicResponse }; + + _mockCoreApiWrapperService.Setup(x => x.GetAccountsByMajorMinorBranchAndStatus(It.IsAny())) + .ReturnsAsync(response); + + _mockCoreApiWrapperService.Setup(x => x.PostFundsToAccount(It.IsAny>())) + .ReturnsAsync(basicResponseList).Verifiable(); + + var result = await _addFundsToIndirectSavingsAccountsService.CleanUp(dataCleanUpRequest); + + _mockCoreApiWrapperService.Verify(x => x.PostFundsToAccount(It.IsAny>()), Times.Exactly(1)); + + Assert.AreEqual(0, result.ResponseStack.Count()); + Assert.AreEqual(true, result.Successful); + } + + [Test] + public async Task HandleCleanUp_WithError() + { + var accountToBeFunded = new AccountsByMajorMinorBranchAndStatusResponse() + { + BranchCode = 1, + AccountNumber = 1, + Name = "Test" + }; + + var response = new List() + { + new AccountsByMajorMinorBranchAndStatusResponse() + { + AccountNumber = 1, + BranchCode = 1, + Name = "Test" + } + }; + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.AddFundsToIndirectSavingsAccounts, + DataCleanUpPayload = null + }; + + _dataCleanUpResult = new DataCleanUpResult(testRequest, true, new List()); + + _mockCoreApiWrapperService.Setup(x => x.GetAccountsByMajorMinorBranchAndStatus(It.IsAny())) + .ReturnsAsync(response); + + var result = await _addFundsToIndirectSavingsAccountsService.HandleSavingsToFundsRequest(_dataCleanUpResult, accountToBeFunded); + + Assert.AreEqual(1, result.ResponseStack.Count()); + Assert.AreEqual(false, result.Successful); + } + + [Test] + public async Task HandleExportResultsFile_Ok_NoErrors() + { + var indirectRequest = new IndirectFundingRequest() + { + Filename = "Test", + SummaryFileDestinationPath = "Test" + }; + + var indirectSavingsAccountSummaryList = new List + { + new IndirectSavingsAccountsSummary + { + AccountNumber = "1", + BranchCode = "1", + AmountFunded = _indirectSavingsRequirementsDefaults.FundsDefaults.FundAmount.ToString(), + ErrorMessage = string.Empty, + Name = "Test", + } + }; + + var summaryTotalResults = new IndirectSavingsAccountResult + { + TotalAccountsFunded = "1", + TotalAccountsNotFunded = "0" + }; + + await _addFundsToIndirectSavingsAccountsService.HandleExportResultsAddFundsToSavingsAccounts(indirectRequest); + + Assert.AreEqual(0, indirectSavingsAccountSummaryList.Where(x => x.ErrorMessage == null).Count()); + Assert.AreEqual(summaryTotalResults.TotalAccountsFunded, indirectSavingsAccountSummaryList.Count().ToString()); + } + + [Test] + public async Task HandleExportResultsFile_Ok_WithErrors() + { + var indirectRequest = new IndirectFundingRequest() + { + Filename = "Test", + SummaryFileDestinationPath = "Test" + }; + + var indirectSavingsAccountSummaryList = new List + { + new IndirectSavingsAccountsSummary + { + AccountNumber = "1", + BranchCode = "1", + AmountFunded = _indirectSavingsRequirementsDefaults.FundsDefaults.FundAmount.ToString(), + ErrorMessage = "There was a problem funding the account", + Name = "Test", + } + }; + + var summaryTotalResults = new IndirectSavingsAccountResult + { + TotalAccountsFunded = "0", + TotalAccountsNotFunded = "1" + }; + + await _addFundsToIndirectSavingsAccountsService.HandleExportResultsAddFundsToSavingsAccounts(indirectRequest); + + Assert.AreEqual(1, indirectSavingsAccountSummaryList.Where(x => x.ErrorMessage != null).Count()); + Assert.AreEqual(summaryTotalResults.TotalAccountsNotFunded, indirectSavingsAccountSummaryList.Count().ToString()); + } + + [Test] + public async Task HandleCreatingAccountSummary_Ok_NoErrors() + { + var accountToBeFunded = new AccountsByMajorMinorBranchAndStatusResponse() + { + BranchCode = 1, + AccountNumber = 1, + Name = "Test" + }; + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.AddFundsToIndirectSavingsAccounts, + DataCleanUpPayload = null + }; + + _dataCleanUpResult = new DataCleanUpResult(testRequest, true, new List()); + + var result = _addFundsToIndirectSavingsAccountsService.HandleCreatingAccountSummary(accountToBeFunded, _dataCleanUpResult); + + Assert.IsNotNull(result); + Assert.AreEqual(true, _dataCleanUpResult.Successful); + } + + [Test] + public async Task HandleCreatingAccountSummary_Ok_WithErrors() + { + var accountToBeFunded = new AccountsByMajorMinorBranchAndStatusResponse() + { + BranchCode = 1, + AccountNumber = 1, + Name = "Test" + }; + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.AddFundsToIndirectSavingsAccounts, + DataCleanUpPayload = null + }; + + var errorList = new List() + { + "There was an error" + }; + + _dataCleanUpResult = new DataCleanUpResult(testRequest, false, errorList); + + var result = _addFundsToIndirectSavingsAccountsService.HandleCreatingAccountSummary(accountToBeFunded, _dataCleanUpResult); + + Assert.IsNotNull(result); + Assert.AreEqual(false, _dataCleanUpResult.Successful); + Assert.IsNotNull(result.ErrorMessage); + } +} + + diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/AddFundsToVipSavingsAccountsServiceTest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/AddFundsToVipSavingsAccountsServiceTest.cs new file mode 100644 index 0000000..24c2d1e --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/AddFundsToVipSavingsAccountsServiceTest.cs @@ -0,0 +1,157 @@ +using Moq; +using NUnit.Framework; +using LCU.Api.Internal.DataCleanUp.Services; +using LCU.Api.Internal.DataCleanUp.DataAccess; +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.Library.Internal.DataCleanUpModel.Enum; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; +using LCU.Api.Internal.DataCleanUp.Configuration; + +namespace LCU.Api.Internal.DataCleanUpTest.Services; + +public class AddFundsToVipSavingsAccountsServiceTest +{ + private AddFundsToVipSavingsAccountsService _addFundsToVipSavingsAccountsService; + private Mock _mockCoreApiWrapperService; + private Mock _mockCoreApiWrapperDao; + private SavingsMissingRequirementsDefaults _savingsMissingRequirementsDefaults; + + [SetUp] + public void Setup() + { + _savingsMissingRequirementsDefaults = new SavingsMissingRequirementsDefaults() + { + + FundsToAccountDefaults = new FundsToAccountDefaults() + { + Description = "Vip Savings", + TransactionAmount = 5.00, + TransactionTypeCode = "DEP", + FundsDefaults = new FundsDefaults() + { + ClearingCategoryCode = "IMED", + FundAmount = 5.00, + FundTypeCode = "EL", + FundTypeDetailCode = "INTR" + } + } + }; + _mockCoreApiWrapperDao = new Mock(); + _mockCoreApiWrapperService = new Mock(); + _addFundsToVipSavingsAccountsService = new AddFundsToVipSavingsAccountsService(_mockCoreApiWrapperService.Object, _savingsMissingRequirementsDefaults); + } + + [Test] + public async Task CleanUpVipSavings_Success() + { + //Set Up Object + var listAccounts = new List() { "1111111" }; + _mockCoreApiWrapperService.Setup(x => x.GetVipSavingsToFund()).ReturnsAsync(listAccounts); + + //Set Up Response + var basicResponse = new BasicResponse() + { + Success = true, + Errors = new List() + }; + + var basicResponseList = new List() { basicResponse }; + + _mockCoreApiWrapperService.Setup(x => x.PostFundsToAccount(It.IsAny(), It.IsAny())) + .ReturnsAsync(basicResponseList); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.AddFundsToVipSavingsAccounts + }; + var result = await _addFundsToVipSavingsAccountsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.GetVipSavingsToFund(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.PostFundsToAccount(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task CleanUp_GetVipSavings_Null_Fail() + { + //Set Up Object + List listAccounts = null; + _mockCoreApiWrapperService.Setup(x => x.GetVipSavingsToFund()).ReturnsAsync(listAccounts); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.AddFundsToVipSavingsAccounts + }; + var result = await _addFundsToVipSavingsAccountsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count); + _mockCoreApiWrapperService.Verify(x => x.GetVipSavingsToFund(), Times.Once); + _mockCoreApiWrapperDao.Verify(x => x.PostFundsToAccount(It.IsAny>()), Times.Never); + } + + [Test] + public async Task CleanUp_UpdateResult_Null_Fail() + { + //Set Up Objects + var listAccounts = new List(){"1111111"}; + _mockCoreApiWrapperService.Setup(x => x.GetVipSavingsToFund()).ReturnsAsync(listAccounts); + + List? basicResponseList = null; + _mockCoreApiWrapperService.Setup(x => x.PostFundsToAccount(It.IsAny(), It.IsAny())) + .ReturnsAsync(basicResponseList); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.AddFundsToVipSavingsAccounts + }; + var result = await _addFundsToVipSavingsAccountsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count); + _mockCoreApiWrapperService.Verify(x => x.GetVipSavingsToFund(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.PostFundsToAccount(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task CleanUp_BasicResponse_Return_NotSuccessful_Fail() + { + //Set Up Objects + var listAccounts = new List(){"1111111"}; + _mockCoreApiWrapperService.Setup(x => x.GetVipSavingsToFund()).ReturnsAsync(listAccounts); + + var basicResponse = new BasicResponse() + { + Success = false, + Errors = new List() { "Error has occured" } + }; + + var basicResponseList = new List() { basicResponse }; + + _mockCoreApiWrapperService.Setup(x => x.PostFundsToAccount(It.IsAny(), It.IsAny())) + .ReturnsAsync(basicResponseList); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.AddFundsToVipSavingsAccounts + }; + var result = await _addFundsToVipSavingsAccountsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count); + _mockCoreApiWrapperService.Verify(x => x.GetVipSavingsToFund(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.PostFundsToAccount(It.IsAny(), It.IsAny()), Times.Once); + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/BatchAddFundsToVipSavingsAccountsServiceTest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/BatchAddFundsToVipSavingsAccountsServiceTest.cs new file mode 100644 index 0000000..baa34f4 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/BatchAddFundsToVipSavingsAccountsServiceTest.cs @@ -0,0 +1,126 @@ +using Moq; +using NUnit.Framework; +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.Api.Internal.DataCleanUp.Services; +using LCU.Api.Internal.DataCleanUp.DataAccess; +using LCU.Library.Internal.DataCleanUpModel.Enum; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Api.Internal.DataCleanUp.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapResponses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; +using System; +using System.Linq; +using LCU.Api.Internal.DataCleanUp.Configuration; + +namespace LCU.Api.Internal.DataCleanUpTest.Services +{ + internal class BatchAddFundsToVipSavingsAccountsServiceTest + { + private BatchAddFundsToVipSavingsAccountsService _batchAddFundsToVipSavingsAccountsService; + private Mock _mockCoreApiWrapperService; + private Mock _mockFileOperationsService; + private DataCleanupDefaults _dataCleanUpDefaults; + private SavingsMissingRequirementsDefaults _savingsDefaults; + private DataCleanUpConfiguration _dataCleanUpConfiguration; + private FileOperationsConfiguration _fileOperationsConfiguration; + + [SetUp] + public void Setup() + { + _dataCleanUpConfiguration = new DataCleanUpConfiguration() + { + TimeZone = "America/Chicago" + }; + + _dataCleanUpDefaults = new DataCleanupDefaults() + { + MemberCheckHoldsUserFieldCode = "MBRH", + MemberCheckHoldsDays = 30, + BatchAddFunds = "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchAddFunds\\NeedToFund.csv", + BatchAddFundsSummarySourcePath = "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchAddFunds\\" + }; + + _savingsDefaults = new SavingsMissingRequirementsDefaults() + { + FundsToAccountDefaults = new FundsToAccountDefaults() + { + Description = "Vip Savings", + TransactionAmount = 5.00, + TransactionTypeCode = "DEP", + FundsDefaults = new FundsDefaults() + { + ClearingCategoryCode = "IMED", + FundAmount = 5.00, + FundTypeCode = "EL", + FundTypeDetailCode = "INTR" + } + } + + }; + + _mockCoreApiWrapperService = new Mock(); + _mockFileOperationsService = new Mock(); + _batchAddFundsToVipSavingsAccountsService = new + (_mockCoreApiWrapperService.Object, _mockFileOperationsService.Object, _dataCleanUpDefaults, _savingsDefaults); + } + + [Test] + public async Task BatchAddFunds_Success() + { + string strFileData = "NEED TO FUND,Account Number,Member Number,Member Name,New Member,Major Code,Minor Code,Minor Description,Account Created Date,Intial FundingDate,Funding Amount,Funding Type,Trans Description,Promo Code" + "\r\n" + + "Yes,123456,3456789,Test Me,Y,SAV,SV01,VIP Savings,6/1/2022,6/2/2022,$5.00 ,New Account Deposit,," + "\r\n" + + "Yes,126786,376846,Test Me Again,Y,SAV,SV01,VIP Savings,6/1/2022,6/2/2022,$5.00,Deposit,," + "\r\n" + + "Yes,47478,57436868,Test Me Three,Y,SAV,SV01,VIP Savings,6/1/2022,6/2/2022,$5.00,External Deposit,,"; + + string testFilePath = _dataCleanUpDefaults.BatchAddFunds; + + _mockFileOperationsService.Setup(x => x.GetContentData(testFilePath)).ReturnsAsync(strFileData); + + var basicResponse = new BasicResponse() + { + Success = true, + Errors = new List() + }; + + var basicResponseList = new List() { basicResponse }; + + _mockCoreApiWrapperService.Setup(x => x.PostFundsToAccount(It.IsAny(), It.IsAny())) + .ReturnsAsync(basicResponseList); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.BatchAddFundsToVipSavingsAccounts + }; + var result = await _batchAddFundsToVipSavingsAccountsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.PostFundsToAccount(It.IsAny(), It.IsAny()), Times.Exactly(3)); + + } + + [Test] + public async Task BatchAddFunds_Fail_MissingCSV() + { + string testFilePath = _dataCleanUpDefaults.BatchAddFunds; + + _mockFileOperationsService.Setup(x => x.GetContentData(testFilePath)).ThrowsAsync(new Exception("Nope")); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.BatchAddFundsToVipSavingsAccounts + }; + var result = await _batchAddFundsToVipSavingsAccountsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.PostFundsToAccount(It.IsAny(), It.IsAny()), Times.Never); + } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/CloseCustodialVruAgreementsServiceTest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/CloseCustodialVruAgreementsServiceTest.cs new file mode 100644 index 0000000..0d3bd55 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/CloseCustodialVruAgreementsServiceTest.cs @@ -0,0 +1,157 @@ +using Moq; +using NUnit.Framework; +using LCU.Api.Internal.DataCleanUp.Services; +using LCU.Api.Internal.DataCleanUp.DataAccess; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements; +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.Library.Internal.DataCleanUpModel.Enum; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapRequests; + +namespace LCU.Api.Internal.DataCleanUpTest.Services; + +public class CloseCustodialVruAgreementsServiceTest +{ + private CloseCustodialVruAgreementsService _closeCustodialVruAgreementsService; + private Mock _mockCoreApiWrapperService; + + [SetUp] + public void Setup() + { + _mockCoreApiWrapperService = new Mock(); + _closeCustodialVruAgreementsService = new CloseCustodialVruAgreementsService(_mockCoreApiWrapperService.Object); + } + + [Test] + public async Task CleanUp_Success() + { + //Set Up GetActiveCustodialVruCardAgreementAgreePersons + var testAgreePersons = new List() + { + new AgreePerson() + { + PersonNumber = 1, + UserId = "11", + AgreeNumber = 1 + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetActiveCustodialVruCardAgreementAgreePersons()).ReturnsAsync(testAgreePersons); + + //Set Up UpdateAccessChannelPersons + var basicResponse = new BasicResponse() + { + Success = true, + Errors = new List() + }; + _mockCoreApiWrapperService.Setup(x => x.UpdatePersonAgreementDetailTypes(It.IsAny())) + .ReturnsAsync(basicResponse); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.HyphenatedUserId + }; + var result = await _closeCustodialVruAgreementsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.GetActiveCustodialVruCardAgreementAgreePersons(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdatePersonAgreementDetailTypes(It.IsAny()), Times.Once); + } + + [Test] + public async Task CleanUp_AgreePersons_Null_Fail() + { + //Set Up GetActiveCustodialVruCardAgreementAgreePersons + List testAgreePersons = null; + _mockCoreApiWrapperService.Setup(x => x.GetActiveCustodialVruCardAgreementAgreePersons()).ReturnsAsync(testAgreePersons); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.HyphenatedUserId + }; + var result = await _closeCustodialVruAgreementsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count); + _mockCoreApiWrapperService.Verify(x => x.GetActiveCustodialVruCardAgreementAgreePersons(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdatePersonAgreementDetailTypes(It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUp_UpdateResult_Null_Fail() + { + //Set Up GetActiveCustodialVruCardAgreementAgreePersons + var testAgreePersons = new List() + { + new AgreePerson() + { + PersonNumber = 1, + UserId = "11", + AgreeNumber = 1 + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetActiveCustodialVruCardAgreementAgreePersons()).ReturnsAsync(testAgreePersons); + + //Set Up UpdateAccessChannelPersons + BasicResponse? basicResponse = null; + _mockCoreApiWrapperService.Setup(x => x.UpdatePersonAgreementDetailTypes(It.IsAny())) + .ReturnsAsync(basicResponse); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.HyphenatedUserId + }; + var result = await _closeCustodialVruAgreementsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count); + _mockCoreApiWrapperService.Verify(x => x.GetActiveCustodialVruCardAgreementAgreePersons(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdatePersonAgreementDetailTypes(It.IsAny()), Times.Once); + } + + [Test] + public async Task CleanUp_BasicResponse_Return_NotSuccessful_Fail() + { + //Set Up GetActiveCustodialVruCardAgreementAgreePersons + var testAgreePersons = new List() + { + new AgreePerson() + { + PersonNumber = 1, + UserId = "11", + AgreeNumber = 1 + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetActiveCustodialVruCardAgreementAgreePersons()).ReturnsAsync(testAgreePersons); + + //Set Up UpdateAccessChannelPersons + var basicResponse = new BasicResponse() + { + Success = false, + Errors = new List() { "Error has occured" } + }; + _mockCoreApiWrapperService.Setup(x => x.UpdatePersonAgreementDetailTypes(It.IsAny())) + .ReturnsAsync(basicResponse); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.HyphenatedUserId + }; + var result = await _closeCustodialVruAgreementsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count); + _mockCoreApiWrapperService.Verify(x => x.GetActiveCustodialVruCardAgreementAgreePersons(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdatePersonAgreementDetailTypes(It.IsAny()), Times.Once); + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/DeactivateCustodialEAgreementsServiceTest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/DeactivateCustodialEAgreementsServiceTest.cs new file mode 100644 index 0000000..c03810e --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/DeactivateCustodialEAgreementsServiceTest.cs @@ -0,0 +1,735 @@ +using System; +using System.Linq; +using Moq; +using NUnit.Framework; +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessChannelPersons; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements; +using LCU.Library.Internal.DataCleanUpModel.Enum; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Api.Internal.DataCleanUp.Services; +using LCU.Api.Internal.DataCleanUp.DataAccess; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessTypes; + +namespace LCU.Api.Internal.DataCleanUpTest.Services; + +public class DeactivateCustodialEAgreementsServiceTest +{ + private DeactivateCustodialEAgreementsService _deactivateCustodialEAgreementsService; + private Mock _mockCoreApiWrapperService; + + [SetUp] + public void Setup() + { + _mockCoreApiWrapperService = new Mock(); + _deactivateCustodialEAgreementsService = new DeactivateCustodialEAgreementsService(_mockCoreApiWrapperService.Object); + } + + [Test] + public async Task CleanUp_Success() + { + //Set Up GetActiveCustodialAgreePersonNumbers + var testPersonNumbers = new List() + { + "111111" + }; + _mockCoreApiWrapperService.Setup(x => x.GetActiveCustodialAgreePersonNumbers()).ReturnsAsync(testPersonNumbers); + + //Set Up GetCoreApiMessageAccessChannelPersons + var coreMessageHeader = new CoreMessageHeader() + { + UpdateKey = 12312312323123 + }; + + var testAccessType = new AccessType() + { + Id = "WWW", + IsActive = true, + UserId = null + }; + var testAccessChannelPerson = new AccessChannelPerson() + { + Id = "2313213_1", + ChannelNumber = 2313213, + PersonNumber = 1, + UserId = "2312312312", + AccessTypes = new List() + { + testAccessType + } + }; + var testAccessChannelPersons = new List() + { + testAccessChannelPerson , + new AccessChannelPerson() + { + PersonNumber = 1, + UserId= "1C1", + AccessTypes = new List() + { + new AccessType() + { + Id= "VRU", + IsActive = true + } + } + } + }; + var coreApiMessage = new CoreApiMessage>(coreMessageHeader, testAccessChannelPersons); + _mockCoreApiWrapperService.Setup(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>())) + .ReturnsAsync(coreApiMessage); + + //Set Up UpdateAccessChannelPersons + var testUpdatedAccessType = new AccessType() + { + Id = "WWW", + IsActive = false + }; + _mockCoreApiWrapperService.Setup(x => x.UpdateAccessType(It.IsAny())) + .ReturnsAsync(testUpdatedAccessType); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.DeactivateCustodialEAgreements + }; + var result = await _deactivateCustodialEAgreementsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.GetActiveCustodialAgreePersonNumbers(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessType(It.IsAny()), Times.Once); + } + + [Test] + public async Task CleanUp_Success_NoHyphenatedUserIds() + { + //Set Up GetAgreePersonsWithHyphenatedUserIds + var testPersonNumbers = new List() + { + }; + _mockCoreApiWrapperService.Setup(x => x.GetActiveCustodialAgreePersonNumbers()).ReturnsAsync(testPersonNumbers); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.DeactivateCustodialEAgreements + }; + var result = await _deactivateCustodialEAgreementsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.GetActiveCustodialAgreePersonNumbers(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessType(It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUp_Fail_SetUpAccessTypeUpdateRequest_PersonNumber_NotLong() + { + //Set Up GetActiveCustodialAgreePersonNumbers + var testPersonNumbers = new List() + { + "111e111" + }; + _mockCoreApiWrapperService.Setup(x => x.GetActiveCustodialAgreePersonNumbers()).ReturnsAsync(testPersonNumbers); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.DeactivateCustodialEAgreements + }; + var result = await _deactivateCustodialEAgreementsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.GetActiveCustodialAgreePersonNumbers(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessType(It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUp_Fail_SetUpAccessTypeUpdateReques_CoreApiMessage_Null() + { + //Set Up GetActiveCustodialAgreePersonNumbers + var testPersonNumbers = new List() + { + "111111" + }; + _mockCoreApiWrapperService.Setup(x => x.GetActiveCustodialAgreePersonNumbers()).ReturnsAsync(testPersonNumbers); + + //Set Up GetCoreApiMessageAccessChannelPersons + CoreApiMessage>? coreApiMessage = null; + _mockCoreApiWrapperService.Setup(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>())) + .ReturnsAsync(coreApiMessage); + + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.DeactivateCustodialEAgreements + }; + var result = await _deactivateCustodialEAgreementsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.GetActiveCustodialAgreePersonNumbers(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessType(It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUp_Fail_SetUpAccessTypeUpdateReques_CoreApiMessage_MessageHeader_Null() + { + //Set Up GetActiveCustodialAgreePersonNumbers + var testPersonNumbers = new List() + { + "111111" + }; + _mockCoreApiWrapperService.Setup(x => x.GetActiveCustodialAgreePersonNumbers()).ReturnsAsync(testPersonNumbers); + + //Set Up GetCoreApiMessageAccessChannelPersons + CoreMessageHeader? coreMessageHeader = null; + + var testAccessType = new AccessType() + { + Id = "WWW", + IsActive = true + }; + var testAccessChannelPerson = new AccessChannelPerson() + { + Id = "2313213_1", + ChannelNumber = 2313213, + PersonNumber = 1, + UserId = "2312312312", + AccessTypes = new List() + { + testAccessType + } + }; + var testAccessChannelPersons = new List() + { + testAccessChannelPerson , + new AccessChannelPerson() + { + PersonNumber = 1, + UserId= "1C1", + AccessTypes = new List() + { + new AccessType() + { + Id= "VRU", + IsActive = true + } + } + } + }; + var coreApiMessage = new CoreApiMessage>(coreMessageHeader, testAccessChannelPersons); + _mockCoreApiWrapperService.Setup(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>())) + .ReturnsAsync(coreApiMessage); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.DeactivateCustodialEAgreements + }; + var result = await _deactivateCustodialEAgreementsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.GetActiveCustodialAgreePersonNumbers(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessType(It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUp_Fail_SetUpAccessTypeUpdateReques_CoreApiMessage_MessageHeader_UpdateKey_Null() + { + //Set Up GetActiveCustodialAgreePersonNumbers + var testPersonNumbers = new List() + { + "111111" + }; + _mockCoreApiWrapperService.Setup(x => x.GetActiveCustodialAgreePersonNumbers()).ReturnsAsync(testPersonNumbers); + + //Set Up GetCoreApiMessageAccessChannelPersons + var coreMessageHeader = new CoreMessageHeader() + { + UpdateKey = null + }; + + var testAccessType = new AccessType() + { + Id = "WWW", + IsActive = true + }; + var testAccessChannelPerson = new AccessChannelPerson() + { + Id = "2313213_1", + ChannelNumber = 2313213, + PersonNumber = 1, + UserId = "2312312312", + AccessTypes = new List() + { + testAccessType + } + }; + var testAccessChannelPersons = new List() + { + testAccessChannelPerson , + new AccessChannelPerson() + { + PersonNumber = 1, + UserId= "1C1", + AccessTypes = new List() + { + new AccessType() + { + Id= "VRU", + IsActive = true + } + } + } + }; + var coreApiMessage = new CoreApiMessage>(coreMessageHeader, testAccessChannelPersons); + _mockCoreApiWrapperService.Setup(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>())) + .ReturnsAsync(coreApiMessage); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.DeactivateCustodialEAgreements + }; + var result = await _deactivateCustodialEAgreementsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.GetActiveCustodialAgreePersonNumbers(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessType(It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUp_Fail_SetUpAccessTypeUpdateReques_CoreApiMessage_MessageBody_Null() + { + //Set Up GetActiveCustodialAgreePersonNumbers + var testPersonNumbers = new List() + { + "111111" + }; + _mockCoreApiWrapperService.Setup(x => x.GetActiveCustodialAgreePersonNumbers()).ReturnsAsync(testPersonNumbers); + + //Set Up GetCoreApiMessageAccessChannelPersons + var coreMessageHeader = new CoreMessageHeader() + { + UpdateKey = 12312312323123 + }; + List? testAccessChannelPersons = null; + var coreApiMessage = new CoreApiMessage>(coreMessageHeader, testAccessChannelPersons); + _mockCoreApiWrapperService.Setup(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>())) + .ReturnsAsync(coreApiMessage); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.DeactivateCustodialEAgreements + }; + var result = await _deactivateCustodialEAgreementsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.GetActiveCustodialAgreePersonNumbers(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessType(It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUp_Fail_SetUpAccessTypeUpdateReques_AccessChannelPersonsToUpdate_Null() + { + //Set Up GetActiveCustodialAgreePersonNumbers + var testPersonNumbers = new List() + { + "111111" + }; + _mockCoreApiWrapperService.Setup(x => x.GetActiveCustodialAgreePersonNumbers()).ReturnsAsync(testPersonNumbers); + + //Set Up GetCoreApiMessageAccessChannelPersons + var coreMessageHeader = new CoreMessageHeader() + { + UpdateKey = 12312312323123 + }; + var testAccessType = new AccessType() + { + Id = "TTT", + IsActive = true + }; + var testAccessChannelPerson = new AccessChannelPerson() + { + Id = "2313213_1", + ChannelNumber = 2313213, + PersonNumber = 1, + UserId = "2312312312", + AccessTypes = new List() + { + testAccessType + } + }; + var testAccessChannelPersons = new List() + { + testAccessChannelPerson , + new AccessChannelPerson() + { + PersonNumber = 1, + UserId= "1C1", + AccessTypes = new List() + { + new AccessType() + { + Id= "VRU", + IsActive = true + } + } + } + }; + var coreApiMessage = new CoreApiMessage>(coreMessageHeader, testAccessChannelPersons); + _mockCoreApiWrapperService.Setup(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>())) + .ReturnsAsync(coreApiMessage); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.DeactivateCustodialEAgreements + }; + var result = await _deactivateCustodialEAgreementsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.AreEqual(0, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.GetActiveCustodialAgreePersonNumbers(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessType(It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUp_Fail_SetUpAccessTypeUpdateReques_UpdatedAccessType_Null() + { + //Set Up GetActiveCustodialAgreePersonNumbers + var testPersonNumbers = new List() + { + "111111" + }; + _mockCoreApiWrapperService.Setup(x => x.GetActiveCustodialAgreePersonNumbers()).ReturnsAsync(testPersonNumbers); + + //Set Up GetCoreApiMessageAccessChannelPersons + var coreMessageHeader = new CoreMessageHeader() + { + UpdateKey = 12312312323123 + }; + + var testAccessType = new AccessType() + { + Id = "WWW", + IsActive = true, + UserId = null + }; + var testAccessChannelPerson = new AccessChannelPerson() + { + Id = "2313213_1", + ChannelNumber = 2313213, + PersonNumber = 1, + UserId = "2312312312", + AccessTypes = new List() + { + testAccessType + } + }; + var testAccessChannelPersons = new List() + { + testAccessChannelPerson , + new AccessChannelPerson() + { + PersonNumber = 1, + UserId= "1C1", + AccessTypes = new List() + { + new AccessType() + { + Id= "VRU", + IsActive = true, + UserId = null + } + } + } + }; + var coreApiMessage = new CoreApiMessage>(coreMessageHeader, testAccessChannelPersons); + _mockCoreApiWrapperService.Setup(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>())) + .ReturnsAsync(coreApiMessage); + + //Set Up UpdateAccessChannelPersons + AccessType? testUpdatedAccessType = null; + _mockCoreApiWrapperService.Setup(x => x.UpdateAccessType(It.IsAny())) + .ReturnsAsync(testUpdatedAccessType); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.DeactivateCustodialEAgreements + }; + var result = await _deactivateCustodialEAgreementsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.GetActiveCustodialAgreePersonNumbers(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessType(It.IsAny()), Times.Once); + } + + [Test] + public async Task CleanUp_Fail_SetUpAccessTypeUpdateReques_UpdatedAccessType_IsActive_True() + { + //Set Up GetActiveCustodialAgreePersonNumbers + var testPersonNumbers = new List() + { + "111111" + }; + _mockCoreApiWrapperService.Setup(x => x.GetActiveCustodialAgreePersonNumbers()).ReturnsAsync(testPersonNumbers); + + //Set Up GetCoreApiMessageAccessChannelPersons + var coreMessageHeader = new CoreMessageHeader() + { + UpdateKey = 12312312323123 + }; + + var testAccessType = new AccessType() + { + Id = "WWW", + IsActive = true, + UserId = null + }; + var testAccessChannelPerson = new AccessChannelPerson() + { + Id = "2313213_1", + ChannelNumber = 2313213, + PersonNumber = 1, + UserId = "2312312312", + AccessTypes = new List() + { + testAccessType + } + }; + var testAccessChannelPersons = new List() + { + testAccessChannelPerson , + new AccessChannelPerson() + { + PersonNumber = 1, + UserId= "1C1", + AccessTypes = new List() + { + new AccessType() + { + Id= "VRU", + IsActive = true, + UserId = null + } + } + } + }; + var coreApiMessage = new CoreApiMessage>(coreMessageHeader, testAccessChannelPersons); + _mockCoreApiWrapperService.Setup(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>())) + .ReturnsAsync(coreApiMessage); + + //Set Up UpdateAccessChannelPersons + var testUpdatedAccessType = new AccessType() + { + Id = "WWW", + IsActive = true + }; + _mockCoreApiWrapperService.Setup(x => x.UpdateAccessType(It.IsAny())) + .ReturnsAsync(testUpdatedAccessType); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.DeactivateCustodialEAgreements + }; + var result = await _deactivateCustodialEAgreementsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.GetActiveCustodialAgreePersonNumbers(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessType(It.IsAny()), Times.Once); + } + + [Test] + public async Task HandleUpdateDeactivateCustodialEAgreement_Success() + { + //Set Up GetCoreApiMessageAccessChannelPersons + var coreMessageHeader = new CoreMessageHeader() + { + UpdateKey = 12312312323123 + }; + + var testAccessType = new AccessType() + { + Id = "WWW", + IsActive = true, + UserId = null + }; + var testAccessChannelPerson = new AccessChannelPerson() + { + Id = "2313213_1", + ChannelNumber = 2313213, + PersonNumber = 1, + UserId = "2312312312", + AccessTypes = new List() + { + testAccessType + } + }; + var testAccessChannelPersons = new List() + { + testAccessChannelPerson , + new AccessChannelPerson() + { + PersonNumber = 1, + UserId= "1C1", + AccessTypes = new List() + { + new AccessType() + { + Id= "VRU", + IsActive = true + } + } + } + }; + var coreApiMessage = new CoreApiMessage>(coreMessageHeader, testAccessChannelPersons); + _mockCoreApiWrapperService.Setup(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>())) + .ReturnsAsync(coreApiMessage); + + //Set Up UpdateAccessChannelPersons + var testUpdatedAccessType = new AccessType() + { + Id = "WWW", + IsActive = false + }; + _mockCoreApiWrapperService.Setup(x => x.UpdateAccessType(It.IsAny())) + .ReturnsAsync(testUpdatedAccessType); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.DeactivateCustodialEAgreements + }; + var cleanUpResult = new DataCleanUpResult(testRequest, true, new List()); + var result = await _deactivateCustodialEAgreementsService.HandleUpdateDeactivateCustodialEAgreement(cleanUpResult, "111111"); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.GetActiveCustodialAgreePersonNumbers(), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessType(It.IsAny()), Times.Once); + } + + [Test] + public async Task SetUpAccessTypeUpdateRequest_Success() + { + //Set Up GetCoreApiMessageAccessChannelPersons + var coreMessageHeader = new CoreMessageHeader() + { + UpdateKey = 12312312323123 + }; + + var testAccessType = new AccessType() + { + Id = "WWW", + IsActive = true, + UserId = null + }; + var testAccessChannelPerson = new AccessChannelPerson() + { + Id = "2313213_1", + ChannelNumber = 2313213, + PersonNumber = 1, + UserId = "2312312312", + AccessTypes = new List() + { + testAccessType + } + }; + var testAccessChannelPersons = new List() + { + testAccessChannelPerson , + new AccessChannelPerson() + { + PersonNumber = 1, + UserId= "1C1", + AccessTypes = new List() + { + new AccessType() + { + Id= "VRU", + IsActive = true + } + } + } + }; + var coreApiMessage = new CoreApiMessage>(coreMessageHeader, testAccessChannelPersons); + _mockCoreApiWrapperService.Setup(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>())) + .ReturnsAsync(coreApiMessage); + + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.DeactivateCustodialEAgreements + }; + var cleanUpResult = new DataCleanUpResult(testRequest, true, new List()); + var result = await _deactivateCustodialEAgreementsService.SetUpAccessTypeUpdateRequest("111111"); + + Assert.NotNull(result); + Assert.AreEqual(testAccessType, result.AccessType); + Assert.AreEqual(12312312323123, result.UpdateKey); + Assert.AreEqual("2313213_1", result.AccessChannelPersonId); + _mockCoreApiWrapperService.Verify(x => x.GetActiveCustodialAgreePersonNumbers(), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny(), + It.IsAny>()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessType(It.IsAny()), Times.Never); + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/HyphenatedUserIdCleanUpServiceTest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/HyphenatedUserIdCleanUpServiceTest.cs new file mode 100644 index 0000000..35c1dc4 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/HyphenatedUserIdCleanUpServiceTest.cs @@ -0,0 +1,591 @@ +using System; +using System.Linq; +using Moq; +using NUnit.Framework; +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.AccessChannelPersons; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements; +using LCU.Library.Internal.DataCleanUpModel.Enum; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Api.Internal.DataCleanUp.Services; +using LCU.Api.Internal.DataCleanUp.DataAccess; + +namespace LCU.Api.Internal.DataCleanUpTest.Services; + +public class HyphenatedUserIdCleanUpServiceTest +{ + private HyphenatedUserIdCleanUpService _hyphenatedUserIdCleanUpService; + private Mock _mockCoreApiWrapperService; + + [SetUp] + public void Setup() + { + _mockCoreApiWrapperService = new Mock(); + _hyphenatedUserIdCleanUpService = new HyphenatedUserIdCleanUpService(_mockCoreApiWrapperService.Object); + } + + [Test] + public async Task CleanUp_Success() + { + //Set Up GetAgreePersonsWithHyphenatedUserIds + var testAgreePersons = new List() + { + new AgreePerson() + { + PersonNumber = 1, + UserId = "1-1", + AgreeNumber = 1 + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetAgreePersonsWithHyphenatedUserIds()).ReturnsAsync(testAgreePersons); + + //Set Up GetCoreApiMessageAccessChannelPersons + var coreMessageHeader = new CoreMessageHeader() + { + UpdateKey = 12312312323123 + }; + var testAccessChannelPersons = new List() + { + new AccessChannelPerson() + { + PersonNumber = 1, + UserId = "2312312312" + }, + new AccessChannelPerson() + { + PersonNumber = 1, + UserId= "1-1" + } + }; + var coreApiMessage = new CoreApiMessage>(coreMessageHeader, testAccessChannelPersons); + _mockCoreApiWrapperService.Setup(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny())) + .ReturnsAsync(coreApiMessage); + + //Set Up UpdateAccessChannelPersons + var testAccessChannelPerson = new AccessChannelPerson() + { + PersonNumber = 1, + UserId = "1C1" + }; + _mockCoreApiWrapperService.Setup(x => x.UpdateAccessChannelPersons(It.IsAny(), It.IsAny())) + .ReturnsAsync(testAccessChannelPerson); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.HyphenatedUserId + }; + var result = await _hyphenatedUserIdCleanUpService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.GetAgreePersonsWithHyphenatedUserIds(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessChannelPersons(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task CleanUp_Success_NoHyphenatedUserIds() + { + //Set Up GetAgreePersonsWithHyphenatedUserIds + var testAgreePersons = new List() + { + }; + _mockCoreApiWrapperService.Setup(x => x.GetAgreePersonsWithHyphenatedUserIds()).ReturnsAsync(testAgreePersons); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.HyphenatedUserId + }; + var result = await _hyphenatedUserIdCleanUpService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.GetAgreePersonsWithHyphenatedUserIds(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessChannelPersons(It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUp_Result_Fail_DetermineAccessChannelPersonUpdateDetails_ExceptionThrown() + { + //Set Up GetAgreePersonsWithHyphenatedUserIds + _mockCoreApiWrapperService.Setup(x => x.GetAgreePersonsWithHyphenatedUserIds()).ThrowsAsync(new Exception("Oops")); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.HyphenatedUserId + }; + var result = await _hyphenatedUserIdCleanUpService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.GetAgreePersonsWithHyphenatedUserIds(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessChannelPersons(It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUp_Result_Fail_DetermineAccessChannelPersonUpdateDetails_CoreApiMessage_Null() + { + //Set Up GetAgreePersonsWithHyphenatedUserIds + var testAgreePersons = new List() + { + new AgreePerson() + { + PersonNumber = 1, + UserId = "1-1", + AgreeNumber = 1 + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetAgreePersonsWithHyphenatedUserIds()).ReturnsAsync(testAgreePersons); + + //Set Up GetCoreApiMessageAccessChannelPersons + CoreApiMessage>? coreApiMessage = null; + _mockCoreApiWrapperService.Setup(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny())) + .ReturnsAsync(coreApiMessage); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.HyphenatedUserId + }; + var result = await _hyphenatedUserIdCleanUpService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.GetAgreePersonsWithHyphenatedUserIds(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessChannelPersons(It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUp_Result_Fail_DetermineAccessChannelPersonUpdateDetails_CoreApiMessage_MessageHeader_Null() + { + //Set Up GetAgreePersonsWithHyphenatedUserIds + var testAgreePersons = new List() + { + new AgreePerson() + { + PersonNumber = 1, + UserId = "1-1", + AgreeNumber = 1 + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetAgreePersonsWithHyphenatedUserIds()).ReturnsAsync(testAgreePersons); + + //Set Up GetCoreApiMessageAccessChannelPersons + CoreMessageHeader? coreMessageHeader = null; + var testAccessChannelPersons = new List() + { + new AccessChannelPerson() + { + PersonNumber = 1, + UserId = "2312312312" + }, + new AccessChannelPerson() + { + PersonNumber = 1, + UserId= "1-1" + } + }; + var coreApiMessage = new CoreApiMessage>(coreMessageHeader, testAccessChannelPersons); + _mockCoreApiWrapperService.Setup(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny())) + .ReturnsAsync(coreApiMessage); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.HyphenatedUserId + }; + var result = await _hyphenatedUserIdCleanUpService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.GetAgreePersonsWithHyphenatedUserIds(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessChannelPersons(It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUp_Result_Fail_DetermineAccessChannelPersonUpdateDetails_CoreApiMessage_UpdateKey_Null() + { + //Set Up GetAgreePersonsWithHyphenatedUserIds + var testAgreePersons = new List() + { + new AgreePerson() + { + PersonNumber = 1, + UserId = "1-1", + AgreeNumber = 1 + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetAgreePersonsWithHyphenatedUserIds()).ReturnsAsync(testAgreePersons); + + //Set Up GetCoreApiMessageAccessChannelPersons + var coreMessageHeader = new CoreMessageHeader() + { + UpdateKey = null + }; + var testAccessChannelPersons = new List() + { + new AccessChannelPerson() + { + PersonNumber = 1, + UserId = "2312312312" + }, + new AccessChannelPerson() + { + PersonNumber = 1, + UserId= "1-1" + } + }; + var coreApiMessage = new CoreApiMessage>(coreMessageHeader, testAccessChannelPersons); + _mockCoreApiWrapperService.Setup(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny())) + .ReturnsAsync(coreApiMessage); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.HyphenatedUserId + }; + var result = await _hyphenatedUserIdCleanUpService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.GetAgreePersonsWithHyphenatedUserIds(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessChannelPersons(It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUp_Result_Fail_DetermineAccessChannelPersonUpdateDetails_CoreApiMessage_MessageBody_Null() + { + //Set Up GetAgreePersonsWithHyphenatedUserIds + var testAgreePersons = new List() + { + new AgreePerson() + { + PersonNumber = 1, + UserId = "1-1", + AgreeNumber = 1 + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetAgreePersonsWithHyphenatedUserIds()).ReturnsAsync(testAgreePersons); + + //Set Up GetCoreApiMessageAccessChannelPersons + var coreMessageHeader = new CoreMessageHeader() + { + UpdateKey = 12312312323123 + }; + List? testAccessChannelPersons = null; + var coreApiMessage = new CoreApiMessage>(coreMessageHeader, testAccessChannelPersons); + _mockCoreApiWrapperService.Setup(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny())) + .ReturnsAsync(coreApiMessage); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.HyphenatedUserId + }; + var result = await _hyphenatedUserIdCleanUpService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.GetAgreePersonsWithHyphenatedUserIds(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessChannelPersons(It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUp_Result_Fail_DetermineAccessChannelPersonUpdateDetails_AccessChannelWithHypenateduserId_Null() + { + //Set Up GetAgreePersonsWithHyphenatedUserIds + var testAgreePersons = new List() + { + new AgreePerson() + { + PersonNumber = 1, + UserId = "1-1", + AgreeNumber = 1 + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetAgreePersonsWithHyphenatedUserIds()).ReturnsAsync(testAgreePersons); + + //Set Up GetCoreApiMessageAccessChannelPersons + var coreMessageHeader = new CoreMessageHeader() + { + UpdateKey = 12312312323123 + }; + var testAccessChannelPersons = new List() + { + new AccessChannelPerson() + { + PersonNumber = 1, + UserId = "2312312312" + }, + new AccessChannelPerson() + { + PersonNumber = 1, + UserId= "3-3" + } + }; + var coreApiMessage = new CoreApiMessage>(coreMessageHeader, testAccessChannelPersons); + _mockCoreApiWrapperService.Setup(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny())) + .ReturnsAsync(coreApiMessage); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.HyphenatedUserId + }; + var result = await _hyphenatedUserIdCleanUpService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.GetAgreePersonsWithHyphenatedUserIds(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessChannelPersons(It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUp_Result_Fail_HandleUpdateOfHyphenatedUserId_UpdatedAccessChannelPerson_Null() + { + //Set Up GetAgreePersonsWithHyphenatedUserIds + var testAgreePersons = new List() + { + new AgreePerson() + { + PersonNumber = 1, + UserId = "1-1", + AgreeNumber = 1 + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetAgreePersonsWithHyphenatedUserIds()).ReturnsAsync(testAgreePersons); + + //Set Up GetCoreApiMessageAccessChannelPersons + var coreMessageHeader = new CoreMessageHeader() + { + UpdateKey = 12312312323123 + }; + var testAccessChannelPersons = new List() + { + new AccessChannelPerson() + { + PersonNumber = 1, + UserId = "2312312312" + }, + new AccessChannelPerson() + { + PersonNumber = 1, + UserId= "1-1" + } + }; + var coreApiMessage = new CoreApiMessage>(coreMessageHeader, testAccessChannelPersons); + _mockCoreApiWrapperService.Setup(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny())) + .ReturnsAsync(coreApiMessage); + + //Set Up UpdateAccessChannelPersons + AccessChannelPerson? testAccessChannelPerson = null; + _mockCoreApiWrapperService.Setup(x => x.UpdateAccessChannelPersons(It.IsAny(), It.IsAny())) + .ReturnsAsync(testAccessChannelPerson); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.HyphenatedUserId + }; + var result = await _hyphenatedUserIdCleanUpService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.GetAgreePersonsWithHyphenatedUserIds(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessChannelPersons(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task CleanUp_Result_Fail_HandleUpdateOfHyphenatedUserId_UpdatedAccessChannelPerson_UserId_DoesNotMatch_NewUserId() + { + //Set Up GetAgreePersonsWithHyphenatedUserIds + var testAgreePersons = new List() + { + new AgreePerson() + { + PersonNumber = 1, + UserId = "1-1", + AgreeNumber = 1 + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetAgreePersonsWithHyphenatedUserIds()).ReturnsAsync(testAgreePersons); + + //Set Up GetCoreApiMessageAccessChannelPersons + var coreMessageHeader = new CoreMessageHeader() + { + UpdateKey = 12312312323123 + }; + var testAccessChannelPersons = new List() + { + new AccessChannelPerson() + { + PersonNumber = 1, + UserId = "2312312312" + }, + new AccessChannelPerson() + { + PersonNumber = 1, + UserId= "1-1" + } + }; + var coreApiMessage = new CoreApiMessage>(coreMessageHeader, testAccessChannelPersons); + _mockCoreApiWrapperService.Setup(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny())) + .ReturnsAsync(coreApiMessage); + + //Set Up UpdateAccessChannelPersons + var testAccessChannelPerson = new AccessChannelPerson() + { + PersonNumber = 1, + UserId = "1B1" + }; + _mockCoreApiWrapperService.Setup(x => x.UpdateAccessChannelPersons(It.IsAny(), It.IsAny())) + .ReturnsAsync(testAccessChannelPerson); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.HyphenatedUserId + }; + var result = await _hyphenatedUserIdCleanUpService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.GetAgreePersonsWithHyphenatedUserIds(), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessChannelPersons(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task HandleUpdateOfHyphenatedUserId_Success() + { + //Set Up GetCoreApiMessageAccessChannelPersons + var coreMessageHeader = new CoreMessageHeader() + { + UpdateKey = 12312312323123 + }; + var testAccessChannelPersons = new List() + { + new AccessChannelPerson() + { + PersonNumber = 1, + UserId = "2312312312" + }, + new AccessChannelPerson() + { + PersonNumber = 1, + UserId= "1-1" + } + }; + var coreApiMessage = new CoreApiMessage>(coreMessageHeader, testAccessChannelPersons); + _mockCoreApiWrapperService.Setup(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny())) + .ReturnsAsync(coreApiMessage); + + //Set Up UpdateAccessChannelPersons + var testAccessChannelPerson = new AccessChannelPerson() + { + PersonNumber = 1, + UserId = "1C1" + }; + + _mockCoreApiWrapperService.Setup(x => x.UpdateAccessChannelPersons(It.IsAny(), It.IsAny())) + .ReturnsAsync(testAccessChannelPerson); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.HyphenatedUserId + }; + var dataCleanUpResult = new DataCleanUpResult(testRequest, true, new List()); + var testAgreePerson = new AgreePerson() + { + PersonNumber = 1, + UserId = "1-1", + AgreeNumber = 1 + }; + var result = await _hyphenatedUserIdCleanUpService.HandleUpdateOfHyphenatedUserId(dataCleanUpResult, testAgreePerson); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.GetAgreePersonsWithHyphenatedUserIds(), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessChannelPersons(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task DetermineAccessChannelPersonUpdateDetails_Success() + { + //Set Up GetCoreApiMessageAccessChannelPersons + var coreMessageHeader = new CoreMessageHeader() + { + UpdateKey = 12312312323123 + }; + + var accessChannelPersonResult = new AccessChannelPerson() + { + PersonNumber = 1, + UserId = "1-1" + }; + var testAccessChannelPersons = new List() + { + new AccessChannelPerson() + { + PersonNumber = 1, + UserId = "2312312312" + }, + accessChannelPersonResult + }; + var coreApiMessage = new CoreApiMessage>(coreMessageHeader, testAccessChannelPersons); + _mockCoreApiWrapperService.Setup(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny())) + .ReturnsAsync(coreApiMessage); + + //Set Up UpdateAccessChannelPersons + var testAccessChannelPerson = new AccessChannelPerson() + { + PersonNumber = 1, + UserId = "1C1" + }; + + _mockCoreApiWrapperService.Setup(x => x.UpdateAccessChannelPersons(It.IsAny(), It.IsAny())) + .ReturnsAsync(testAccessChannelPerson); + + var testAgreePerson = new AgreePerson() + { + PersonNumber = 1, + UserId = "1-1", + AgreeNumber = 1 + }; + var result = await _hyphenatedUserIdCleanUpService.DetermineAccessChannelPersonUpdateDetails(testAgreePerson); + + Assert.NotNull(result); + Assert.AreEqual(12312312323123, result.updateKey); + Assert.AreEqual(accessChannelPersonResult, result.accessChannelPerson); + _mockCoreApiWrapperService.Verify(x => x.GetAgreePersonsWithHyphenatedUserIds(), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetCoreApiMessageAccessChannelPersons(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccessChannelPersons(It.IsAny(), It.IsAny()), Times.Never); + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/MaskTransactionExternalDescriptionWithSsnServiceTest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/MaskTransactionExternalDescriptionWithSsnServiceTest.cs new file mode 100644 index 0000000..d74c652 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/MaskTransactionExternalDescriptionWithSsnServiceTest.cs @@ -0,0 +1,250 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Moq; +using NUnit.Framework; +using LCU.Api.Internal.DataCleanUp.Services; +using LCU.Api.Internal.DataCleanUp.DataAccess; +using LCU.Library.Internal.DataCleanUpModel.Enum; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Transaction; +namespace LCU.Api.Internal.DataCleanUpTest.Services; + +public class MaskTransactionExternalDescriptionWithSsnServiceTest +{ + private MaskTransactionExternalDescriptionWithSsnService _maskTransactionExternalDescriptionWithSsnService; + private Mock _mockCoreApiWrapperService; + + [SetUp] + public void Setup() + { + _mockCoreApiWrapperService = new Mock(); + _maskTransactionExternalDescriptionWithSsnService = new MaskTransactionExternalDescriptionWithSsnService(_mockCoreApiWrapperService.Object); + } + + [Test] + public async Task CleanUp_Success() + { + //Set Up + var testExternalDescriptions = new List() + { + new ExternalDescription() + { + ExternalDescriptionNumber = 1, + ExternalDescriptionText = "State of Wisc - SSI 44444444444 *0000000000*333664444*Tester Test *120422\\" + }, + new ExternalDescription() + { + ExternalDescriptionNumber = 1, + ExternalDescriptionText = "State of Wisc - SSI 555555555555 *111111111*444775555*TesterB TestB *120422\\" + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetTransactionsExternalDescriptionsWithSsn()) + .ReturnsAsync(testExternalDescriptions); + + var testBasicResponse = new BasicResponse() + { + Success = true, + Errors = new List() + }; + _mockCoreApiWrapperService.Setup(x => x.UpdateTransactionsExternalDescriptions(It.IsAny())) + .ReturnsAsync(testBasicResponse); + + var testDataCleanUpRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.MaskTransactionExternalDescriptionWithSsn + }; + + var result = await _maskTransactionExternalDescriptionWithSsnService + .CleanUp(testDataCleanUpRequest); + + Assert.IsTrue(result.Successful); + Assert.AreEqual(0, result.ResponseStack.Count); + } + + [Test] + public async Task CleanUp_Fail_BadSsns() + { + //Set Up + var testExternalDescriptions = new List() + { + new ExternalDescription() + { + ExternalDescriptionNumber = 1, + ExternalDescriptionText = "State of Wisc - SSI 44444444444 *0000000000*33364444*Tester Test *120422\\" + }, + new ExternalDescription() + { + ExternalDescriptionNumber = 1, + ExternalDescriptionText = "State of Wisc - SSI 555555555555 *111111111*4447755555*TesterB TestB *120422\\" + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetTransactionsExternalDescriptionsWithSsn()) + .ReturnsAsync(testExternalDescriptions); + + var testBasicResponse = new BasicResponse() + { + Success = true, + Errors = new List() + }; + _mockCoreApiWrapperService.Setup(x => x.UpdateTransactionsExternalDescriptions(It.IsAny())) + .ReturnsAsync(testBasicResponse); + + var testDataCleanUpRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.MaskTransactionExternalDescriptionWithSsn + }; + + var result = await _maskTransactionExternalDescriptionWithSsnService + .CleanUp(testDataCleanUpRequest); + + Assert.IsFalse(result.Successful); + Assert.AreEqual(2, result.ResponseStack.Count); + } + + [Test] + public async Task CleanUp_Fail_ExernalDescriptionsNull() + { + //Set Up + List testExternalDescriptions = null; + _mockCoreApiWrapperService.Setup(x => x.GetTransactionsExternalDescriptionsWithSsn()) + .ReturnsAsync(testExternalDescriptions); + + var testBasicResponse = new BasicResponse() + { + Success = true, + Errors = new List() + }; + _mockCoreApiWrapperService.Setup(x => x.UpdateTransactionsExternalDescriptions(It.IsAny())) + .ReturnsAsync(testBasicResponse); + + var testDataCleanUpRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.MaskTransactionExternalDescriptionWithSsn + }; + + var result = await _maskTransactionExternalDescriptionWithSsnService + .CleanUp(testDataCleanUpRequest); + + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count); + } + + [Test] + public async Task HandleMaskingTransactionExternalDescriptionWithSsn_Success() + { + //Set Up + var testBasicResponse = new BasicResponse() + { + Success = true, + Errors = new List() + }; + _mockCoreApiWrapperService.Setup(x => x.UpdateTransactionsExternalDescriptions(It.IsAny())) + .ReturnsAsync(testBasicResponse); + + var testDataCleanUpRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.MaskTransactionExternalDescriptionWithSsn + }; + var testCleanUpResult = new DataCleanUpResult(testDataCleanUpRequest, true, new List()); + var descptionWithSsn = "State of Wisc - SSI 44444444444 *0000000000*333664444*Tester Test *120422\\"; + var testExternalDescription = new ExternalDescription() + { + ExternalDescriptionNumber = 1, + ExternalDescriptionText = descptionWithSsn + }; + + var result = await _maskTransactionExternalDescriptionWithSsnService + .HandleMaskingTransactionExternalDescriptionWithSsn(testCleanUpResult, testExternalDescription); + + Assert.IsTrue(result.Successful); + Assert.AreEqual(0, result.ResponseStack.Count); + } + + [Test] + public async Task HandleMaskingTransactionExternalDescriptionWithSsn_BasicResponseReturnedFail() + { + //Set Up + var testBasicResponse = new BasicResponse() + { + Success = false, + Errors = new List() + { + "Failure" + } + }; + _mockCoreApiWrapperService.Setup(x => x.UpdateTransactionsExternalDescriptions(It.IsAny())) + .ReturnsAsync(testBasicResponse); + + var testDataCleanUpRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.MaskTransactionExternalDescriptionWithSsn + }; + var testCleanUpResult = new DataCleanUpResult(testDataCleanUpRequest, true, new List()); + var descptionWithSsn = "State of Wisc - SSI 44444444444 *0000000000*333664444*Tester Test *120422\\"; + var testExternalDescription = new ExternalDescription() + { + ExternalDescriptionNumber = 1, + ExternalDescriptionText = descptionWithSsn + }; + + var result = await _maskTransactionExternalDescriptionWithSsnService + .HandleMaskingTransactionExternalDescriptionWithSsn(testCleanUpResult, testExternalDescription); + + Assert.IsFalse (result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count); + } + + [Test] + public async Task HandleMaskingTransactionExternalDescriptionWithSsn_Fail_CoreUpdateReturnWasnull() + { + + var testDataCleanUpRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.MaskTransactionExternalDescriptionWithSsn + }; + var testCleanUpResult = new DataCleanUpResult(testDataCleanUpRequest, true, new List()); + var descptionWithSsn = "State of Wisc - SSI 44444444444 *0000000000*333664444*Tester Test *120422\\"; + var testExternalDescription = new ExternalDescription() + { + ExternalDescriptionNumber = 1, + ExternalDescriptionText = descptionWithSsn + }; + + var result = await _maskTransactionExternalDescriptionWithSsnService + .HandleMaskingTransactionExternalDescriptionWithSsn(testCleanUpResult, testExternalDescription); + + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count); + } + + [Test] + public void MaskSsn_Success() + { + var descptionWithSsn = "State of Wisc - SSI 44444444444 *0000000000*333664444*Tester Test *120422\\"; + var result = _maskTransactionExternalDescriptionWithSsnService.MaskSsn(descptionWithSsn); + + Assert.IsNotNull(result); + Assert.AreEqual("State of Wisc - SSI 44444444444 *0000000000*XXXXX4444*Tester Test *120422\\", result); + } + + [Test] + public void MaskSsn_ThrowException_DoesNotMeetPattern() + { + var descptionWithSsn = "State of Wisc - SSI 44444444444 *333664444*Tester Test *120422\\"; + + var ex = Assert.Throws(() => _maskTransactionExternalDescriptionWithSsnService.MaskSsn(descptionWithSsn)); + Assert.That(ex.Message, Is.EqualTo("Transaction External Description does not meet the pattern. Was expecting 5 sections split by * but there were 4 sections.")); + } + + [Test] + public void MaskSsn_ThrowException_SsnPatternContainedHyphens_Length_11() + { + var descptionWithSsn = "State of Wisc - SSI 44444444444 *0000000000*333-66-4444*Tester Test *120422\\"; + + var ex = Assert.Throws(() => _maskTransactionExternalDescriptionWithSsnService.MaskSsn(descptionWithSsn)); + Assert.That(ex.Message, Is.EqualTo("The SSN pulled from the Transaction External Description does not meet the pattern." + + $"Was expecting SSN to be a lenght of 9 but it was 11.")); + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateAccountCreditReportTypeServiceTest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateAccountCreditReportTypeServiceTest.cs new file mode 100644 index 0000000..6f268fe --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateAccountCreditReportTypeServiceTest.cs @@ -0,0 +1,99 @@ +using Moq; +using NUnit.Framework; +using System.Collections.Generic; +using System.Threading.Tasks; +using System; +using System.Linq; +using LCU.Api.Internal.DataCleanUp.Configuration; +using LCU.Api.Internal.DataCleanUp.Services; +using LCU.Api.Internal.DataCleanUp.DataAccess; +using LCU.Library.Internal.DataCleanUpModel.Enum; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses; +using Newtonsoft.Json; + +namespace LCU.Api.Internal.DataCleanUpTest.Services; + +public class UpdateAccountCreditReportTypeServiceTest +{ + private UpdateAccountCreditReportTypeService _updateAccountCreditReportTypeService; + private Mock _mockCoreApiWrapperService; + private Mock _mockFileOperationsService; + + [SetUp] + public void Setup() + { + _mockCoreApiWrapperService = new Mock(); + _mockFileOperationsService = new Mock(); + _updateAccountCreditReportTypeService = new UpdateAccountCreditReportTypeService(_mockCoreApiWrapperService.Object, _mockFileOperationsService.Object); + } + + [Test] + public async Task CleanUpAccountCreditReportTypeService_Success() + { + var creditReportRequest = new CreditReportTypeRequest() + { + SourcePath = "\\\test\\test.csv" + }; + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateAccountCreditReportType, + DataCleanUpPayload = JsonConvert.SerializeObject(creditReportRequest) + }; + + string strFileData = "AccountNumber,BorrowerName,Balance" + "\r\n" + + "111,SOFIA ADAMS,100.50"; + + _mockFileOperationsService.Setup(x => x.GetContentData(creditReportRequest.SourcePath)).ReturnsAsync(strFileData); + + //Set Up Response + var response = new BasicResponse() + { + Success = true, + Errors = new List() + }; + + _mockCoreApiWrapperService.Setup(x => x.UpdateAccountCreditReportType(It.IsAny(), It.IsAny())) + .ReturnsAsync(response); + + //Set Up Response + var basicResponse = new BasicResponse() + { + Success = true, + Errors = new List() + }; + + var result = await _updateAccountCreditReportTypeService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccountCreditReportType(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task CleanUpAccountCreditReportTypeService_Fail() + { + var creditReportRequest = new CreditReportTypeRequest() + { + SourcePath = "\\\test\\test.csv" + }; + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateAccountCreditReportType, + DataCleanUpPayload = JsonConvert.SerializeObject(creditReportRequest) + }; + + _mockFileOperationsService.Setup(x => x.GetContentData(It.IsAny())).ThrowsAsync(new Exception("Nope")); + + var result = await _updateAccountCreditReportTypeService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccountCreditReportType(It.IsAny(), It.IsAny()), Times.Never); + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateAccountGroupForAnalysisServiceTest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateAccountGroupForAnalysisServiceTest.cs new file mode 100644 index 0000000..6c18370 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateAccountGroupForAnalysisServiceTest.cs @@ -0,0 +1,83 @@ +using Moq; +using NUnit.Framework; +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.Api.Internal.DataCleanUp.Services; +using LCU.Api.Internal.DataCleanUp.DataAccess; +using LCU.Library.Internal.DataCleanUpModel.Enum; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; +using LCU.Api.Internal.DataCleanUp.Configuration; + +namespace LCU.Api.Internal.DataCleanUpTest.Services; + +public class UpdateAccountGroupForAnalysisServiceTest +{ + private UpdateAccountGroupForAnalysisService _updateAccountGroupForAnalysisService; + private Mock _mockCoreApiWrapperService; + private Mock _mockCoreApiWrapperDao; + private DataCleanupDefaults _dataCleanUpDefaults; + + [SetUp] + public void Setup() + { + + _dataCleanUpDefaults = new DataCleanupDefaults(); + + _mockCoreApiWrapperDao = new Mock(); + _mockCoreApiWrapperService = new Mock(); + _updateAccountGroupForAnalysisService = new UpdateAccountGroupForAnalysisService(_mockCoreApiWrapperService.Object, _dataCleanUpDefaults); + } + + [Test] + public async Task CleanUpAccountGroups_Success() + { + var listAccounts = new List() { "23" }; + _mockCoreApiWrapperService.Setup(x => x.GetGroupUpdateForAnalysisAccountNumbers()).ReturnsAsync(listAccounts); + + //Set Up Response + var basicResponse = new BasicResponse() + { + Success = true, + Errors = new List() + }; + + _mockCoreApiWrapperService.Setup(x => x.UpdateAccountGroupForAnalysis(It.IsAny())) + .ReturnsAsync(basicResponse); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateAccountGroupForAnalysis + }; + var result = await _updateAccountGroupForAnalysisService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccountGroupForAnalysis(It.IsAny()), Times.Once); + + } + + [Test] + public async Task CleanUpAccountGroups_Fail() + { + //Set Up Object + var basicResponse = new BasicResponse(); + + _mockCoreApiWrapperService.Setup(x => x.UpdateAccountGroupForAnalysis(It.IsAny())) + .ReturnsAsync(basicResponse); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateAccountGroupForAnalysis + }; + var result = await _updateAccountGroupForAnalysisService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.AreEqual(0, result.ResponseStack.Count); + _mockCoreApiWrapperDao.Verify(x => x.UpdateAccountGroupForAnalysis(It.IsAny()), Times.Never); + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateAccountLoanToValueServiceTest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateAccountLoanToValueServiceTest.cs new file mode 100644 index 0000000..35f198b --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateAccountLoanToValueServiceTest.cs @@ -0,0 +1,135 @@ +using Moq; +using NUnit.Framework; +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.Api.Internal.DataCleanUp.Services; +using LCU.Api.Internal.DataCleanUp.DataAccess; +using LCU.Library.Internal.DataCleanUpModel.Enum; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; +using LCU.Library.Internal.DataCleanUpModel.Entities; +using LCU.Api.Internal.DataCleanUpLib.Repositories; +using LCU.Api.Internal.DataCleanUp.Configuration; + +namespace LCU.Api.Internal.DataCleanUpTest.Services; + +public class UpdateAccountLoanToValueServiceTest +{ + private UpdateAccountLoanToValueService _updateAccountLoanToValueService; + private Mock _mockCoreApiWrapperService; + private Mock _mockCoreApiWrapperDao; + private Mock _mockLtvDataCleanUpRepository; + private DataCleanupDefaults _dataCleanUpDefaults; + + + [SetUp] + public void Setup() + { + + _dataCleanUpDefaults = new DataCleanupDefaults() + { + LtvExcludedMinorAccountTypes = new List() { "DL01", "DL02", "DL03", "DL04", "DL05", "DL06", "DL07", "DL08", "DL09", "DL10", "DL11", "DL12", "DL13", "DL14", "DL15", "DL16" } + }; + + _mockCoreApiWrapperDao = new Mock(); + _mockCoreApiWrapperService = new Mock(); + _mockLtvDataCleanUpRepository = new Mock(); + _updateAccountLoanToValueService = new UpdateAccountLoanToValueService(_mockCoreApiWrapperService.Object, _mockLtvDataCleanUpRepository.Object, _dataCleanUpDefaults); + } + + [Test] + public async Task CleanUpLoanToValue_Success() + { + + // Arrange + _mockLtvDataCleanUpRepository.Setup(ltvDataCleanUpRepository => ltvDataCleanUpRepository.ListMinorAccountTypeAsync(_dataCleanUpDefaults.LtvExcludedMinorAccountTypes)).ReturnsAsync( + new List() + { + new Ltv_DataCleanUp() + }); + + //Set Up Response + var basicResponse = new BasicResponse() + { + Success = true, + Errors = new List() + }; + + _mockCoreApiWrapperService.Setup(x => x.UpdateAccountLoanToValue(It.IsAny(), It.IsAny())) + .ReturnsAsync(basicResponse); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateAccountLoanToValue + }; + var result = await _updateAccountLoanToValueService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccountLoanToValue(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task CleanUpLoanToValue_Success_FilterIndirectAccountType() + { + + // Arrange + _mockLtvDataCleanUpRepository.Setup(ltvDataCleanUpRepository => ltvDataCleanUpRepository.ListMinorAccountTypeAsync(_dataCleanUpDefaults.LtvExcludedMinorAccountTypes)).ReturnsAsync( + new List() + { + new Ltv_DataCleanUp() + { + AccountNumber = "1111111", + Ltv = .1, + MinorType = "DL01" + } + }); + + //Set Up Response + var basicResponse = new BasicResponse() + { + Success = true, + Errors = new List() + }; + + _mockCoreApiWrapperService.Setup(x => x.UpdateAccountLoanToValue(It.IsAny(), It.IsAny())) + .ReturnsAsync(basicResponse); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateAccountLoanToValue + }; + var result = await _updateAccountLoanToValueService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.UpdateAccountLoanToValue(It.IsAny(), It.IsAny()), Times.Once); + _mockCoreApiWrapperDao.Verify(x => x.UpdateAccountLoanToValue(It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUp_LoanToValue_Fail() + { + //Set Up Object + var basicResponse = new BasicResponse(); + + _mockCoreApiWrapperService.Setup(x => x.UpdateAccountLoanToValue(It.IsAny(), 0)) + .ReturnsAsync(basicResponse); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateAccountLoanToValue + }; + var result = await _updateAccountLoanToValueService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.AreEqual(0, result.ResponseStack.Count); + _mockCoreApiWrapperDao.Verify(x => x.UpdateAccountLoanToValue(It.IsAny()), Times.Never); + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateAccountPmiCancelServiceTest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateAccountPmiCancelServiceTest.cs new file mode 100644 index 0000000..cf8f2a1 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateAccountPmiCancelServiceTest.cs @@ -0,0 +1,90 @@ +using LCU.Api.Internal.DataCleanUp.Configuration; +using LCU.Api.Internal.DataCleanUp.DataAccess; +using LCU.Api.Internal.DataCleanUp.Models; +using LCU.Api.Internal.DataCleanUp.Services; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Properties; +using LCU.Library.Internal.DataCleanUpModel.Enum; +using LCU.Library.Internal.DataCleanUpModel.Models; +using Moq; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LCU.Api.Internal.DataCleanUpTest.Services +{ + public class UpdateAccountPmiCancelServiceTest + { + private UpdateAccountPmiCancelService _updateAccountPmiCancelService; + private Mock _mockCoreApiWrapperService; + private Mock _mockFileOperationsService; + private DataCleanupDefaults _dataCleanUpDefaults; + + [SetUp] + public void Setup() + { + _dataCleanUpDefaults = new DataCleanupDefaults() + { + PmiCancelSourcePath = "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\PMICancel\\PMI Cancel.csv", + PmiCancelSummaryPath = "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\PMICancel\\" + }; + _mockFileOperationsService = new Mock(); + _mockCoreApiWrapperService = new Mock(); + _updateAccountPmiCancelService = new UpdateAccountPmiCancelService(_mockCoreApiWrapperService.Object, _mockFileOperationsService.Object, _dataCleanUpDefaults); + } + + [Test] + public async Task CleanUpPropertyUserField_Fail() + { + //Set Up Object + var basicResponse = new BasicResponse(); + + _mockCoreApiWrapperService.Setup(x => x.UpdateAccountPmiCancel(It.IsAny())) + .ReturnsAsync(basicResponse); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateAccountPmiCancel + }; + var result = await _updateAccountPmiCancelService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.AreEqual(1, result.ResponseStack.Count); + } + + [Test] + public async Task CleanUpPropertyUserField_Success() + { + var testFilePath = _dataCleanUpDefaults.PmiCancelSourcePath; + string data = "Test"; + _mockFileOperationsService.Setup(x => x.GetContentData(testFilePath)) + .ReturnsAsync(data); + + //Set Up Response + var basicResponse = new BasicResponse() + { + Success = true, + Errors = new List() + }; + + _mockCoreApiWrapperService.Setup(x => x.UpdateAccountPmiCancel(It.IsAny())) + .ReturnsAsync(basicResponse); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateAccountPmiCancel + }; + var result = await _updateAccountPmiCancelService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateFannieMaeMortgageServiceTest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateFannieMaeMortgageServiceTest.cs new file mode 100644 index 0000000..4eb29a1 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateFannieMaeMortgageServiceTest.cs @@ -0,0 +1,337 @@ +using Moq; +using NUnit.Framework; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using LCU.Api.Internal.DataCleanUp.Configuration; +using LCU.Api.Internal.DataCleanUp.Models; +using LCU.Api.Internal.DataCleanUp.Services; +using LCU.Api.Internal.DataCleanUp.Services.Emailers; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts; +using LCU.Library.Internal.DataCleanUpModel.Models; + +namespace LCU.Api.Internal.DataCleanUpTest.Services; + +public class UpdateFannieMaeMortgageServiceTest +{ + private UpdateFannieMaeMortgageService _updateFannieMaeMortgageService; + private Mock _mockCoreApiWrapperService; + private Mock _mockFileOperationsService; + private FannieMaeConfiguration _fannieMaeConfiguration; + private DataCleanUpConfiguration _dataCleanUpConfiguration; + private Mock _mockEmailService; + + [SetUp] + public void Setup() + { + _dataCleanUpConfiguration = new DataCleanUpConfiguration() + { + TimeZone = "America/Chicago" + }; + + _fannieMaeConfiguration = new FannieMaeConfiguration() + { + ErrorFileDefaultName = "FannieMaeErrorRecord", + SummaryEmailSubject = "FannieMaeSummaryEmail", + PoolDateUserFieldId = "PLDT", + PoolNbrUserFieldId = "PLNB", + FileDateFormat = "M/d/yyyy", + DnaDateFormat = "yyyy-MM-dd" + }; + + _mockCoreApiWrapperService = new Mock(); + _mockFileOperationsService = new Mock(); + _mockEmailService = new Mock(); + _updateFannieMaeMortgageService = new UpdateFannieMaeMortgageService(_mockCoreApiWrapperService.Object, + _mockFileOperationsService.Object, + _fannieMaeConfiguration, + _dataCleanUpConfiguration, + _mockEmailService.Object); + } + + [Test] + public async Task ProcessFannieMaeRecordPoolDate_Ok() + { + var request = new FannieMaeMortgageRequest() + { + Filename = "TestFile" + }; + + var updateResult = new FannieMaeUpdateResult(request.Filename); + var fannieMaeList = new List(); + var fannieMaeMortgage1 = new FannieMaeMortgage() + { + FannieMaeLoanNumber = 1, + ServicerLoanNumber = 99998888888800000, + PoolIssueDate = "6/1/2023" + }; + + fannieMaeList.Add(fannieMaeMortgage1); + updateResult.UpdateList = fannieMaeList; + + var accountUserValuesList = new List() + { + new AccountUserField() + { + AccountNumber = 99998888888800000, + Value = "6/1/2023", + UserFieldCode = _fannieMaeConfiguration.PoolDateUserFieldId + } + }; + + _mockCoreApiWrapperService.Setup(x => x.AddAccountUserField(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(accountUserValuesList).Verifiable(); + + var result = await _updateFannieMaeMortgageService.ProcessFannieMaeRecord(fannieMaeMortgage1, updateResult, _fannieMaeConfiguration.PoolDateUserFieldId, fannieMaeMortgage1.PoolIssueDate); + + Assert.AreEqual(0, result.ErrorList.Count()); + Assert.AreEqual(2, result.UpdateList.Count()); + Assert.AreEqual(fannieMaeMortgage1.ServicerLoanNumber, accountUserValuesList[0].AccountNumber); + } + + [Test] + public void ProcessFannieMaeRecordForPoolDate_Error() + { + var request = new FannieMaeMortgageRequest() + { + Filename = "TestFile" + }; + + var updateResult = new FannieMaeUpdateResult(request.Filename); + + var fannieMaeList = new List(); + var fannieMaeMortgage1 = new FannieMaeMortgage() + { + FannieMaeLoanNumber = 1, + ServicerLoanNumber = 99998877778800000, + PoolIssueDate = "6/1/2023" + }; + + fannieMaeList.Add(fannieMaeMortgage1); + updateResult.UpdateList = fannieMaeList; + + var result = _updateFannieMaeMortgageService.ProcessFannieMaeRecord(fannieMaeMortgage1, updateResult, _fannieMaeConfiguration.PoolDateUserFieldId, fannieMaeMortgage1.PoolIssueDate); + + Assert.AreEqual(1, result.Result.ErrorList.Count()); + Assert.AreEqual("Fannie Mae Loan Record Failed: 99998877778800000", result.Result.ErrorList[0]); + } + + [Test] + public async Task ProcessFannieMaeRecordPoolNumber_Ok() + { + var request = new FannieMaeMortgageRequest() + { + Filename = "TestFile" + }; + + var updateResult = new FannieMaeUpdateResult(request.Filename); + var fannieMaeList = new List(); + var fannieMaeMortgage1 = new FannieMaeMortgage() + { + FannieMaeLoanNumber = 1, + ServicerLoanNumber = 99998888888800000, + PoolNumber = "TEST1234" + }; + + fannieMaeList.Add(fannieMaeMortgage1); + updateResult.UpdateList = fannieMaeList; + + var accountUserValuesList = new List() + { + new AccountUserField() + { + AccountNumber = 99998888888800000, + Value = "TEST1234", + UserFieldCode = _fannieMaeConfiguration.PoolNbrUserFieldId + } + }; + + _mockCoreApiWrapperService.Setup(x => x.AddAccountUserField(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(accountUserValuesList).Verifiable(); + + var result = await _updateFannieMaeMortgageService.ProcessFannieMaeRecord(fannieMaeMortgage1, updateResult, _fannieMaeConfiguration.PoolNbrUserFieldId, fannieMaeMortgage1.PoolNumber); + + Assert.AreEqual(0, result.ErrorList.Count()); + Assert.AreEqual(2, result.UpdateList.Count()); + Assert.AreEqual(fannieMaeMortgage1.ServicerLoanNumber, accountUserValuesList[0].AccountNumber); + } + + [Test] + public void ProcessFannieMaeRecordForPoolNumber_Error() + { + var request = new FannieMaeMortgageRequest() + { + Filename = "TestFile" + }; + + var updateResult = new FannieMaeUpdateResult(request.Filename); + + var fannieMaeList = new List(); + var fannieMaeMortgage1 = new FannieMaeMortgage() + { + FannieMaeLoanNumber = 1288, + ServicerLoanNumber = 99998566800000, + PoolNumber = "TEST1234" + }; + + fannieMaeList.Add(fannieMaeMortgage1); + updateResult.UpdateList = fannieMaeList; + + var result = _updateFannieMaeMortgageService.ProcessFannieMaeRecord(fannieMaeMortgage1, updateResult, _fannieMaeConfiguration.PoolNbrUserFieldId, fannieMaeMortgage1.PoolNumber); + + Assert.AreEqual(1, result.Result.ErrorList.Count()); + Assert.AreEqual("Fannie Mae Loan Record Failed: 99998566800000", result.Result.ErrorList[0]); + } + + [Test] + public void BuildTotalBatchSummary_Ok_UpdatesErrors() + { + var request = new FannieMaeMortgageRequest() + { + Filename = "TestFile" + }; + + var updateResults = new List(); + var resultOne = new FannieMaeUpdateResult(request.Filename); + var errorListOne = new List() + { + "errorOne", + "errorTwo", + "errorThree" + }; + + var fannieMaeList = new List(); + var fannieMaeMortgage1 = new FannieMaeMortgage() + { + FannieMaeLoanNumber = 1, + PoolIssueDate = "6/1/2023", + PoolNumber = "XXXZ23443" + }; + var fannieMaeMortgage2 = new FannieMaeMortgage() + { + FannieMaeLoanNumber = 2, + PoolIssueDate = "6/1/2023", + PoolNumber = "DDDZ23443" + }; + + fannieMaeList.Add(fannieMaeMortgage1); + fannieMaeList.Add(fannieMaeMortgage2); + + resultOne.ErrorList = errorListOne; + resultOne.UpdateList = fannieMaeList; + resultOne.TotalRecordsFound = 5; + + updateResults.Add(resultOne); + + var result = _updateFannieMaeMortgageService.BuildTotalBatchSummary(updateResults, true); + + Assert.AreEqual(5, result.TotalRecordsFound); + Assert.AreEqual(3, result.TotalErrorRecords); + Assert.AreEqual(true, result.ErrorFileCreated); + Assert.AreEqual(2, result.TotalRecordsUpdated); + } + + [Test] + public void BuildTotalBatchSummary_Ok_UpdatesNoErrors() + { + var request = new FannieMaeMortgageRequest() + { + Filename = "TestFile" + }; + + var updateResults = new List(); + var resultOne = new FannieMaeUpdateResult(request.Filename); + var errorListOne = new List() + { + + }; + + var fannieMaeList = new List(); + var fannieMaeMortgage1 = new FannieMaeMortgage() + { + FannieMaeLoanNumber = 1, + PoolIssueDate = "6/1/2023", + PoolNumber = "XXXZ23443" + }; + var fannieMaeMortgage2 = new FannieMaeMortgage() + { + FannieMaeLoanNumber = 2, + PoolIssueDate = "6/1/2023", + PoolNumber = "DDDZ23443" + }; + + fannieMaeList.Add(fannieMaeMortgage1); + fannieMaeList.Add(fannieMaeMortgage2); + + resultOne.ErrorList = errorListOne; + resultOne.UpdateList = fannieMaeList; + resultOne.TotalRecordsFound = 2; + + updateResults.Add(resultOne); + + var result = _updateFannieMaeMortgageService.BuildTotalBatchSummary(updateResults, false); + + Assert.AreEqual(2, result.TotalRecordsFound); + Assert.AreEqual(0, result.TotalErrorRecords); + Assert.AreEqual(false, result.ErrorFileCreated); + Assert.AreEqual(2, result.TotalRecordsUpdated); + } + + [Test] + public void BuildTotalBatchSummary_Ok_NoUpdatesNoErrors() + { + var request = new FannieMaeMortgageRequest() + { + Filename = "TestFile" + }; + + var updateResults = new List(); + var resultOne = new FannieMaeUpdateResult(request.Filename); + var errorListOne = new List() + { + + }; + + var fannieMaeList = new List(); + + resultOne.ErrorList = errorListOne; + resultOne.UpdateList = fannieMaeList; + resultOne.TotalRecordsFound = 0; + + updateResults.Add(resultOne); + + var result = _updateFannieMaeMortgageService.BuildTotalBatchSummary(updateResults, false); + + Assert.AreEqual(0, result.TotalRecordsFound); + Assert.AreEqual(0, result.TotalErrorRecords); + Assert.AreEqual(false, result.ErrorFileCreated); + Assert.AreEqual(0, result.TotalRecordsUpdated); + } + + [Test] + public void AddStringToErrorList_Ok() + { + var request = new FannieMaeMortgageRequest() + { + Filename = "TestFile" + }; + + var updateResult = new FannieMaeUpdateResult(request.Filename); + updateResult.ErrorList = new List(); + + var fannieMaeRecord = new FannieMaeMortgage() + { + ServicerLoanNumber = 1, + PoolIssueDate = "6/1/2023", + PoolNumber = "TEST1234" + }; + + var expectedError = "1|TEST1234|6/1/2023|Unit test error message\n"; + updateResult.AddStringToErrorList(fannieMaeRecord, "Unit test error message"); + + Assert.AreEqual(1, updateResult.ErrorList.Count); + Assert.AreEqual(expectedError, updateResult.ErrorList.FirstOrDefault()); + } +} + + diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateMissingSavingsAccountServiceTest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateMissingSavingsAccountServiceTest.cs new file mode 100644 index 0000000..54f7a2c --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateMissingSavingsAccountServiceTest.cs @@ -0,0 +1,454 @@ +using Moq; +using NUnit.Framework; +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.Api.Internal.DataCleanUp.Services; +using LCU.Api.Internal.DataCleanUp.DataAccess; +using LCU.Library.Internal.DataCleanUpModel.Enum; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Api.Internal.DataCleanUp.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreSoapResponses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreResponses; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; +using System; +using System.Linq; +using LCU.Api.Internal.DataCleanUp.Configuration; + +namespace LCU.Api.Internal.DataCleanUpTest.Services; + +public class UpdateMissingSavingsAccountServiceTest +{ + private UpdateMissingBatchSavingsService _updateMissingBatchSavingsService; + private Mock _mockCoreApiWrapperService; + private Mock _mockFileOperationsService; + private DataCleanupDefaults _dataCleanUpDefaults; + private SavingsMissingRequirementsDefaults _savingsDefaults; + private DataCleanUpConfiguration _dataCleanUpConfiguration; + private FileOperationsConfiguration _fileOperationsConfiguration; + + [SetUp] + public void Setup() + { + _dataCleanUpConfiguration = new DataCleanUpConfiguration() + { + TimeZone = "America/Chicago" + }; + + _dataCleanUpDefaults = new DataCleanupDefaults() + { + MemberCheckHoldsUserFieldCode = "MBRH", + MemberCheckHoldsDays = 30, + BatchSavingsSourcePath = "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchSavings\\MissingBatchSavings.csv", + BatchSavingsSummarySourcePath = "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchSavings\\" + }; + + _savingsDefaults = new SavingsMissingRequirementsDefaults() + { + FundsToAccountDefaults = new FundsToAccountDefaults() + { + + }, + SavingDefaults = new SavingsDefaults() + { + BankOrganizationNumber = "1", + BatchAccountDescription = "test", + CurrentAccountStatusCode = "Z", + CurrentMinorAccountTypeCode = "X", + DeliveryMethodCode = "DD", + OwnershipCode = "OW", + IsTaxReportedForOwner = true, + IsTaxReportedForSigner = true, + IsValid = true, + MajorAccountTypeCode = "MM" + } + + }; + + _mockCoreApiWrapperService = new Mock(); + _mockFileOperationsService = new Mock(); + _updateMissingBatchSavingsService = new UpdateMissingBatchSavingsService(_mockCoreApiWrapperService.Object, _mockFileOperationsService.Object, _dataCleanUpDefaults, _savingsDefaults); + } + + [Test] + public async Task CleanUpPersonMissingBatchSavingsUpdate_Success() + { + + string strFileData = "CUSTOMERNUMBER,FIRSTNAME,LASTNAME,CUSTOMERTYPE,ORGANIZATIONNAME,CORESAVINGSCOUNT,SAVINGSACCOUNTNUMBER,SAVINGSACCOUNTBALANCE,BRANCHCODE,CONTROLPERSON,ControlPersonNeeded,CustomerAddress1,CustomerAddress2,CustomerCity,CustomerState,CustomerZip,ControlPersonAssigned" + "\r\n" + + "111,SOFIA,Test,Person,,0,,0,1123,0,N,444 S Zero Pl, ,NOWHERE,WI,55555,Y"; + + var testFilePath = _dataCleanUpDefaults.BatchSavingsSourcePath; + + _mockFileOperationsService.Setup(x => x.GetContentData(testFilePath)).ReturnsAsync(strFileData); + + //Set Up Response + var response = new CreatedAccountResponse() + { + AccountNumber = 1, + BasicResponse = new BasicResponse { Errors = new List(), Success = true } + }; + + _mockCoreApiWrapperService.Setup(x => x.CreatePersonAccount(It.IsAny())) + .ReturnsAsync(response); + + //Set Up Response + var basicResponse = new BasicResponse() + { + Success = true, + Errors = new List() + }; + + var basicResponseList = new List() { basicResponse }; + + _mockCoreApiWrapperService.Setup(x => x.PostFundsToAccount(response.AccountNumber.ToString(), 5)) + .ReturnsAsync(basicResponseList); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateMissingBatchSavings + }; + + var result = await _updateMissingBatchSavingsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.CreatePersonAccount(It.IsAny()), Times.Once); + } + + [Test] + public async Task CleanUpPersonMissingBatchSavingsUpdate_Fail() + { + var testFilePath = _dataCleanUpDefaults.BatchSavingsSourcePath; + _mockFileOperationsService.Setup(x => x.GetContentData(testFilePath)).ThrowsAsync(new Exception("Nope")); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateMissingBatchSavings + }; + + var result = await _updateMissingBatchSavingsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.CreatePersonAccount(It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUpOrganizationMissingBatchSavingsUpdate_Success() + { + string strFileData = "CUSTOMERNUMBER,FIRSTNAME,LASTNAME,CUSTOMERTYPE,ORGANIZATIONNAME,CORESAVINGSCOUNT,SAVINGSACCOUNTNUMBER,SAVINGSACCOUNTBALANCE,BRANCHCODE,CONTROLPERSON,ControlPersonNeeded,CustomerAddress1,CustomerAddress2,CustomerCity,CustomerState,CustomerZip,ControlPersonAssigned" + "\r\n" + + "555,,,Organization,No Company,0,,0,1122,112826,N,Test Ave, ,TestTown,WI,55555,Y"; + + var testFilePath = _dataCleanUpDefaults.BatchSavingsSourcePath; + + _mockFileOperationsService.Setup(x => x.GetContentData(testFilePath)).ReturnsAsync(strFileData); + + //Set Up Response + var response = new CreatedAccountResponse() + { + AccountNumber = 1, + BasicResponse = new BasicResponse { Errors = new List(), Success = true } + }; + + _mockCoreApiWrapperService.Setup(x => x.CreateOrganizationAccount(It.IsAny())) + .ReturnsAsync(response); + + //Set Up Response + var basicResponse = new BasicResponse() + { + Success = true, + Errors = new List() + }; + + var basicResponseList = new List() { basicResponse }; + + _mockCoreApiWrapperService.Setup(x => x.PostFundsToAccount(response.AccountNumber.ToString(), 5)) + .ReturnsAsync(basicResponseList); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateMissingBatchSavings + }; + + var result = await _updateMissingBatchSavingsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.CreateOrganizationAccount(It.IsAny()), Times.Once); + } + + [Test] + public async Task CleanUpOrganizationMissingBatchSavingsUpdate_Fail() + { + var testFilePath = _dataCleanUpDefaults.BatchSavingsSourcePath; + _mockFileOperationsService.Setup(x => x.GetContentData(testFilePath)).ThrowsAsync(new Exception("Nope")); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateMissingBatchSavings + }; + + var result = await _updateMissingBatchSavingsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.CreateOrganizationAccount(It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUpAddControllingPersonToOrganizationUpdate_Success() + { + string strFileData = "CUSTOMERNUMBER,FIRSTNAME,LASTNAME,CUSTOMERTYPE,ORGANIZATIONNAME,CORESAVINGSCOUNT,SAVINGSACCOUNTNUMBER,SAVINGSACCOUNTBALANCE,BRANCHCODE,CONTROLPERSON,ControlPersonNeeded,CustomerAddress1,CustomerAddress2,CustomerCity,CustomerState,CustomerZip,ControlPersonAssigned" + "\r\n" + + "555,,,Organization,No Company,0,,0,1122,112826,Y,Test Ave, ,TestTown,WI,55555,N"; + + var testFilePath = _dataCleanUpDefaults.BatchSavingsSourcePath; + + _mockFileOperationsService.Setup(x => x.GetContentData(testFilePath)).ReturnsAsync(strFileData); + + //Set Up Response + var response = new BasicResponse() + { + Errors = new List(), + Success = true + }; + + _mockCoreApiWrapperService.Setup(x => x.AddControllingPersonOrganizationMaintenance(It.IsAny())) + .ReturnsAsync(response); + + //Set Up Response + var acctresponse = new CreatedAccountResponse() + { + AccountNumber = 1, + BasicResponse = new BasicResponse { Errors = new List(), Success = true } + }; + + _mockCoreApiWrapperService.Setup(x => x.CreateOrganizationAccount(It.IsAny())) + .ReturnsAsync(acctresponse); + + //Set Up Response + var basicResponse = new BasicResponse() + { + Success = true, + Errors = new List() + }; + + var basicResponseList = new List() { basicResponse }; + + _mockCoreApiWrapperService.Setup(x => x.PostFundsToAccount(It.IsAny(), It.IsAny())) + .ReturnsAsync(basicResponseList); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateMissingBatchSavings + }; + + var result = await _updateMissingBatchSavingsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.CreateOrganizationAccount(It.IsAny()), Times.Once); + } + + [Test] + public async Task CleanUpAddControllingPersonToOrganizationUpdate_Fail() + { + var testFilePath = _dataCleanUpDefaults.BatchSavingsSourcePath; + _mockFileOperationsService.Setup(x => x.GetContentData(testFilePath)).ThrowsAsync(new Exception("Nope")); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateMissingBatchSavings + }; + + var result = await _updateMissingBatchSavingsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.CreateOrganizationAccount(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.AddControllingPersonOrganizationMaintenance(It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUpPersonAndAddFundsForMissingBatchSavingsUpdate_Success() + { + string strFileData = "CUSTOMERNUMBER,FIRSTNAME,LASTNAME,CUSTOMERTYPE,ORGANIZATIONNAME,CORESAVINGSCOUNT,SAVINGSACCOUNTNUMBER,SAVINGSACCOUNTBALANCE,BRANCHCODE,CONTROLPERSON,ControlPersonNeeded,CustomerAddress1,CustomerAddress2,CustomerCity,CustomerState,CustomerZip,ControlPersonAssigned" + "\r\n" + + "111,SOFIA,Test,Person,,0,,0,1123,0,N,444 S Zero Pl, ,NOWHERE,WI,55555,Y"; + + var testFilePath = _dataCleanUpDefaults.BatchSavingsSourcePath; + + _mockFileOperationsService.Setup(x => x.GetContentData(testFilePath)).ReturnsAsync(strFileData); + + //Set Up Response + var response = new CreatedAccountResponse() + { + AccountNumber = 1, + BasicResponse = new BasicResponse { Errors = new List(), Success = true } + }; + + _mockCoreApiWrapperService.Setup(x => x.CreatePersonAccount(It.IsAny())) + .ReturnsAsync(response); + + //Set Up Funds Response + var basicResponseFunds = new BasicResponse() + { + Success = true, + Errors = new List() + }; + + var basicResponseList = new List() { basicResponseFunds }; + + _mockCoreApiWrapperService.Setup(x => x.PostFundsToAccount(response.AccountNumber.ToString(), 5)) + .ReturnsAsync(basicResponseList); + + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateMissingBatchSavings + }; + + var result = await _updateMissingBatchSavingsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.CreatePersonAccount(It.IsAny()), Times.Once); + } + + [Test] + public async Task CleanUpPersonAndAddFundsForMissingBatchSavingsUpdateWithBalance_Success() + { + string strFileData = "CUSTOMERNUMBER,FIRSTNAME,LASTNAME,CUSTOMERTYPE,ORGANIZATIONNAME,CORESAVINGSCOUNT,SAVINGSACCOUNTNUMBER,SAVINGSACCOUNTBALANCE,BRANCHCODE,CONTROLPERSON,ControlPersonNeeded,CustomerAddress1,CustomerAddress2,CustomerCity,CustomerState,CustomerZip,ControlPersonAssigned" + "\r\n" + + "111,SOFIA,Test,Person,,1,223344,1.25,1123,0,N,444 S Zero Pl, ,NOWHERE,WI,55555,Y"; + + var testFilePath = _dataCleanUpDefaults.BatchSavingsSourcePath; + + _mockFileOperationsService.Setup(x => x.GetContentData(testFilePath)).ReturnsAsync(strFileData); + + //Set Up Funds Response + var basicResponseFunds = new BasicResponse() + { + Success = true, + Errors = new List() + }; + + var basicResponseList = new List() { basicResponseFunds }; + + _mockCoreApiWrapperService.Setup(x => x.PostFundsToAccount("223344", 3.75)) + .ReturnsAsync(basicResponseList); + + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateMissingBatchSavings + }; + + var result = await _updateMissingBatchSavingsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.PostFundsToAccount(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task CleanUpPersonAndAddFundsForMissingBatchSavingsUpdate_Fail() + { + var testFilePath = _dataCleanUpDefaults.BatchSavingsSourcePath; + _mockFileOperationsService.Setup(x => x.GetContentData(testFilePath)).ThrowsAsync(new Exception("Nope")); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateMissingBatchSavings + }; + + var result = await _updateMissingBatchSavingsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.CreatePersonAccount(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.PostFundsToAccount(It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUpOrganizationAndAddFundsForMissingBatchSavingsUpdate_Success() + { + string strFileData = "CUSTOMERNUMBER,FIRSTNAME,LASTNAME,CUSTOMERTYPE,ORGANIZATIONNAME,CORESAVINGSCOUNT,SAVINGSACCOUNTNUMBER,SAVINGSACCOUNTBALANCE,BRANCHCODE,CONTROLPERSON,ControlPersonNeeded,CustomerAddress1,CustomerAddress2,CustomerCity,CustomerState,CustomerZip,ControlPersonAssigned" + "\r\n" + + "555,,,Organization,No Company,0,,0,1122,112826,N,Test Ave, ,TestTown,WI,55555,Y"; + + var testFilePath = _dataCleanUpDefaults.BatchSavingsSourcePath; + + _mockFileOperationsService.Setup(x => x.GetContentData(testFilePath)).ReturnsAsync(strFileData); + + //Set Up Response + var response = new CreatedAccountResponse() + { + AccountNumber = 1, + BasicResponse = new BasicResponse { Errors = new List(), Success = true } + }; + + _mockCoreApiWrapperService.Setup(x => x.CreateOrganizationAccount(It.IsAny())) + .ReturnsAsync(response); + + //Set Up Funds Response + var basicResponseFunds = new BasicResponse() + { + Success = true, + Errors = new List() + }; + + var basicResponseList = new List() { basicResponseFunds }; + + _mockCoreApiWrapperService.Setup(x => x.PostFundsToAccount(It.IsAny(), It.IsAny())) + .ReturnsAsync(basicResponseList); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateMissingBatchSavings + }; + + var result = await _updateMissingBatchSavingsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.CreateOrganizationAccount(It.IsAny()), Times.Once); + } + + [Test] + public async Task CleanUpOrganizationAndAddFundsForMissingBatchSavingsUpdate_Fail() + { + var testFilePath = _dataCleanUpDefaults.BatchSavingsSourcePath; + _mockFileOperationsService.Setup(x => x.GetContentData(testFilePath)).ThrowsAsync(new Exception("Nope")); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdateMissingBatchSavings + }; + + var result = await _updateMissingBatchSavingsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsFalse(result.Successful); + Assert.AreEqual(1, result.ResponseStack.Count()); + _mockCoreApiWrapperService.Verify(x => x.CreateOrganizationAccount(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.PostFundsToAccount(It.IsAny(), It.IsAny()), Times.Never); + } + +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateNcoaProcessServiceTest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateNcoaProcessServiceTest.cs new file mode 100644 index 0000000..8cefd79 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdateNcoaProcessServiceTest.cs @@ -0,0 +1,586 @@ +using LCU.Api.Internal.DataCleanUp.Configuration; +using LCU.Api.Internal.DataCleanUp.DataAccess; +using LCU.Api.Internal.DataCleanUp.Models.ParserModels; +using LCU.Api.Internal.DataCleanUp.Services; +using LCU.Api.Internal.DataCleanUp.Services.Emailers; +using LCU.Api.Internal.DataCleanUp.Services.Validation; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.PostalAddresses; +using Moq; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LCU.Api.Internal.DataCleanUpTest.Services; + +public class UpdateNcoaProcessServiceTest +{ + private UpdateNcoaProcessService _updateNcoaProcessService; + private Mock _mockCoreApiWrapperService; + private Mock _mockFileOperationsService; + private NcoaConfiguration _ncoaConfiguration; + private DataCleanUpConfiguration _dataCleanUpConfiguration; + private INcoaValidationService _ncoaValidationService; + private Mock _mockEmailService; + + [SetUp] + public void Setup() + { + _dataCleanUpConfiguration = new DataCleanUpConfiguration() + { + TimeZone = "America/Chicago" + }; + + _ncoaConfiguration = new NcoaConfiguration() + { + PrimaryAddressLabel = "PRI", + StreetTypeLabel = "ST", + UrlBase = "/Persons/{personNumber}/PostalAddresses/PRI", + UsaLabel = "USA", + PoBoxLabel = "PO BOX", + PoBoxAddressTypeLabel = "POBN", + ErrorFileDefaultName = "NCOAErrorRecord", + PersonNumberLabel = "{personNumber}" + }; + + _ncoaValidationService = new NcoaValidationService(); + _mockCoreApiWrapperService = new Mock(); + _mockFileOperationsService = new Mock(); + _mockEmailService = new Mock(); + _updateNcoaProcessService = new UpdateNcoaProcessService(_mockCoreApiWrapperService.Object, + _mockFileOperationsService.Object, _ncoaConfiguration, + _dataCleanUpConfiguration, _ncoaValidationService, + _mockEmailService.Object); + } + + [Test] + public async Task MapPersonAddressLine_NoPoBox() + { + //Arrange + var ncoaRecord = new NcoaRecord() + { + UserId = "123456", + NcoaType = "I", + ChangeDate = "202212", + PrimaryName = "Test E Testerson", + CurrentAddressOne = "1 Imaginary Lane", + CurrentAddressTwo = "Apt 13", + CurrentAddressThree = "Additional Address Line", + CurrentAddressFour = "ReallyLongCityName", + CurrentAddressFive = "Wisconsin, 53186", + SecondaryName = "Test Testerson", + BusinessName = "Testerson's Testing", + NewAddressLine = "New Address Line", + City = "New Test City", + StateCode = "WI", + ZipCode = "53022", + ZipSuffix = "-1234", + UserIdTwo = "123456", + StatementCode = "TestStatementCode" + }; + + var currentAddress = new PersonPostalAddress() + { + AddressNumber = 456 + }; + + //Act + var result = _updateNcoaProcessService.MapPersonAddrLine(98765, currentAddress, ncoaRecord); + + //Assert + Assert.AreEqual(98765, result.PersonNumber); + Assert.AreEqual("PRI", result.Id); + Assert.AreEqual("PRI", result.AddressUseCode); + Assert.AreEqual(456, result.AddressNumber); + Assert.AreEqual("New Address Line", result.AddressLine1); + Assert.AreEqual("ST", result.AddressLineTypeCode1); + Assert.Null(result.AddressLine2); + Assert.Null(result.AddressLineTypeCode2); + Assert.Null(result.AddressLine3); + Assert.Null(result.AddressLineTypeCode3); + Assert.AreEqual("New Test City", result.CityName); + Assert.AreEqual("WI", result.CountrySubdivisionCode); + Assert.AreEqual("53022", result.PostalCode); + Assert.AreEqual("1234", result.ZipPlus); + Assert.AreEqual("USA", result.CountryCode); + Assert.AreEqual("/Persons/98765/PostalAddresses/PRI", result.Url); + Assert.False(result.IsPerformIRSCorrection); + } + + [Test] + public async Task MapPersonAddressLine_PoBox() + { + //Arrange + var ncoaRecord = new NcoaRecord() + { + UserId = "123456", + NcoaType = "I", + ChangeDate = "202212", + PrimaryName = "Test E Testerson", + CurrentAddressOne = "1 Imaginary Lane", + CurrentAddressTwo = "Apt 13", + CurrentAddressThree = "Additional Address Line", + CurrentAddressFour = "ReallyLongCityName", + CurrentAddressFive = "Wisconsin, 53186", + SecondaryName = "Test Testerson", + BusinessName = "Testerson's Testing", + NewAddressLine = "New Address Line PO BOX Test", + City = "New Test City", + StateCode = "WI", + ZipCode = "53022", + ZipSuffix = "-1234", + UserIdTwo = "123456", + StatementCode = "TestStatementCode" + }; + + var currentAddress = new PersonPostalAddress() + { + AddressNumber = 456 + }; + + //Act + var result = _updateNcoaProcessService.MapPersonAddrLine(98765, currentAddress, ncoaRecord); + + //Assert + Assert.AreEqual(98765, result.PersonNumber); + Assert.AreEqual("PRI", result.Id); + Assert.AreEqual("PRI", result.AddressUseCode); + Assert.AreEqual(456, result.AddressNumber); + Assert.AreEqual("New Address Line PO BOX Test", result.AddressLine1); + Assert.AreEqual("POBN", result.AddressLineTypeCode1); + Assert.Null(result.AddressLine2); + Assert.Null(result.AddressLineTypeCode2); + Assert.Null(result.AddressLine3); + Assert.Null(result.AddressLineTypeCode3); + Assert.AreEqual("New Test City", result.CityName); + Assert.AreEqual("WI", result.CountrySubdivisionCode); + Assert.AreEqual("53022", result.PostalCode); + Assert.AreEqual("1234", result.ZipPlus); + Assert.AreEqual("USA", result.CountryCode); + Assert.AreEqual("/Persons/98765/PostalAddresses/PRI", result.Url); + Assert.False(result.IsPerformIRSCorrection); + } + + [Test] + public async Task CheckForBoBoxAddressLineType_NoPoBox() + { + //Arrange + var personAddrLine = new PersonAddrLine() + { + AddressLine1 = "Negative Test", + AddressLineTypeCode1 = "ST" + }; + + //Act + var result = _updateNcoaProcessService.CheckForPoBoxAddressLineType(personAddrLine); + + //Assert + Assert.AreEqual("Negative Test", result.AddressLine1); + Assert.AreEqual("ST", result.AddressLineTypeCode1); + } + + [Test] + public async Task CheckForBoBoxAddressLineType_PoBox() + { + //Arrange + var personAddrLine = new PersonAddrLine() + { + AddressLine1 = "Positive Test PO BOX Something", + AddressLineTypeCode1 = "ST" + }; + + //Act + var result = _updateNcoaProcessService.CheckForPoBoxAddressLineType(personAddrLine); + + //Assert + Assert.AreEqual("Positive Test PO BOX Something", result.AddressLine1); + Assert.AreEqual("POBN", result.AddressLineTypeCode1); + } + + [Test] + public async Task CreateErrorrecord_NoPersonNumber() + { + // Arrange + var updateResult = new UpdateNcoaProcessService.NcoaUpdateResult(); + + var ncoaRecord = new NcoaRecord() + { + UserId = "123456", + NcoaType = "I", + ChangeDate = "202212", + PrimaryName = "Test E Testerson", + CurrentAddressOne = "1 Imaginary Lane", + CurrentAddressTwo = "Apt 13", + CurrentAddressThree = "Additional Address Line", + CurrentAddressFour = "ReallyLongCityName", + CurrentAddressFive = "Wisconsin, 53186", + SecondaryName = "Test Testerson", + BusinessName = "Testerson's Testing", + NewAddressLine = "New Address Line PO BOX Test", + City = "New Test City", + StateCode = "WI", + ZipCode = "53022", + ZipSuffix = "1234", + UserIdTwo = "123456", + StatementCode = "TestStatementCode" + }; + + var expectedErrorrecord = "202212|123456||Test E Testerson|1 Imaginary Lane|Apt 13|Additional Address Line|ReallyLongCityName|Wisconsin, 53186" + + "|New Address Line PO BOX Test|New Test City|WI|53022|1234|This is a test error message\n"; + + //Act + updateResult.AddStringToErrorList(ncoaRecord, "This is a test error message"); + + //Assert + Assert.AreEqual(1, updateResult.ErrorList.Count); + Assert.AreEqual(expectedErrorrecord, updateResult.ErrorList.FirstOrDefault()); + } + + [Test] + public async Task CreateErrorrecord_WithPersonNumber() + { + // Arrange + var updateResult = new UpdateNcoaProcessService.NcoaUpdateResult(); + + var ncoaRecord = new NcoaRecord() + { + UserId = "123456", + NcoaType = "I", + ChangeDate = "202212", + PrimaryName = "Test E Testerson", + CurrentAddressOne = "1 Imaginary Lane", + CurrentAddressTwo = "Apt 13", + CurrentAddressThree = "Additional Address Line", + CurrentAddressFour = "ReallyLongCityName", + CurrentAddressFive = "Wisconsin, 53186", + SecondaryName = "Test Testerson", + BusinessName = "Testerson's Testing", + NewAddressLine = "New Address Line PO BOX Test", + City = "New Test City", + StateCode = "WI", + ZipCode = "53022", + ZipSuffix = "1234", + UserIdTwo = "123456", + StatementCode = "TestStatementCode" + }; + + var expectedErrorrecord = "202212|123456|11111|Test E Testerson|1 Imaginary Lane|Apt 13|Additional Address Line|ReallyLongCityName|Wisconsin, 53186" + + "|New Address Line PO BOX Test|New Test City|WI|53022|1234|This is a test error message\n"; + + //Act + updateResult.AddStringToErrorList(ncoaRecord, "This is a test error message", "11111"); + + //Assert + Assert.AreEqual(1, updateResult.ErrorList.Count); + Assert.AreEqual(expectedErrorrecord, updateResult.ErrorList.FirstOrDefault()); + } + + [Test] + public async Task ConvertToTitleCase_FromLower() + { + //Arrange + var textToChange = "milwaukee"; + + //Act + var result = _updateNcoaProcessService.ConvertToTitleCase(textToChange); + + //Assert + Assert.AreEqual("Milwaukee", result); + } + + [Test] + public async Task ConvertToTitleCase_TwoWordCity() + { + //Arrange + var textToChange = "menomonee falls"; + + //Act + var result = _updateNcoaProcessService.ConvertToTitleCase(textToChange); + + //Assert + Assert.AreEqual("Menomonee Falls", result); + } + + [Test] + public async Task BuildTotalBatchSummary_Ok_OneResult() + { + // Arrange + var updateResults = new List(); + var resultOne = new UpdateNcoaProcessService.NcoaUpdateResult(); + var errorListOne = new List() + { + "errorOne", + "errorTwo", + "ErrorThree" + }; + var persAddrLineList = new List(); + var persAddrLineOne = new PersonAddrLine() + { + AddressLine1 = "1234 Some Address", + AddressLineTypeCode1 = "ST" + }; + var persAddrLineTwo = new PersonAddrLine() + { + AddressLine1 = "5678 Some Address", + AddressLineTypeCode1 = "ST" + }; + persAddrLineList.Add(persAddrLineOne); + persAddrLineList.Add(persAddrLineTwo); + + resultOne.ErrorList = errorListOne; + resultOne.UpdateList = persAddrLineList; + resultOne.TotalRecordsFound = 5; + + updateResults.Add(resultOne); + + // Act + var result = _updateNcoaProcessService.BuildTotalBatchSummary(updateResults, true); + + // Assert + Assert.AreEqual(5, result.TotalRecordsFound); + Assert.AreEqual(3, result.TotalErrorRecords); + Assert.AreEqual(2, result.TotalRecordsUpdated); + Assert.True(result.ErrorFileCreated); + } + + [Test] + public async Task BuildTotalBatchSummary_Ok_MultipleResults() + { + // Arrange + var updateResults = new List(); + var resultOne = new UpdateNcoaProcessService.NcoaUpdateResult(); + var errorListOne = new List() + { + "errorOne", + "errorTwo", + "ErrorThree" + }; + var persAddrLineListOne = new List(); + var persAddrLineOne = new PersonAddrLine() + { + AddressLine1 = "1234 Some Address", + AddressLineTypeCode1 = "ST" + }; + var persAddrLineTwo = new PersonAddrLine() + { + AddressLine1 = "5678 Some Address", + AddressLineTypeCode1 = "ST" + }; + persAddrLineListOne.Add(persAddrLineOne); + persAddrLineListOne.Add(persAddrLineTwo); + + resultOne.ErrorList = errorListOne; + resultOne.UpdateList = persAddrLineListOne; + resultOne.TotalRecordsFound = 5; + + var resultTwo = new UpdateNcoaProcessService.NcoaUpdateResult(); + var errorListTwo = new List() + { + "errorOne", + "errorTwo", + }; + + var persAddrLineThree = new PersonAddrLine() + { + AddressLine1 = "Updated Address", + AddressLineTypeCode1 = "ST" + }; + + var persAddrLineListTwo = new List(); + persAddrLineListTwo.Add(persAddrLineThree); + + resultTwo.ErrorList = errorListTwo; + resultTwo.UpdateList = persAddrLineListTwo; + resultTwo.TotalRecordsFound = 3; + + updateResults.Add(resultOne); + updateResults.Add(resultTwo); + + // Act + var result = _updateNcoaProcessService.BuildTotalBatchSummary(updateResults, false); + + // Assert + Assert.AreEqual(8, result.TotalRecordsFound); + Assert.AreEqual(5, result.TotalErrorRecords); + Assert.AreEqual(3, result.TotalRecordsUpdated); + Assert.False(result.ErrorFileCreated); + } + + [Test] + public async Task BuildTotalBatchSummary_Ok_NoResults() + { + // Arrange + var updateResults = new List(); + + // Act + var result = _updateNcoaProcessService.BuildTotalBatchSummary(updateResults, false); + + // Assert + Assert.AreEqual(0, result.TotalRecordsFound); + Assert.AreEqual(0, result.TotalErrorRecords); + Assert.AreEqual(0, result.TotalRecordsUpdated); + Assert.False(result.ErrorFileCreated); + } + + [Test] + public async Task CreateTotalBatchSummaryString_OneResult_WithLocation() + { + // Arrange + var updateResults = new List(); + var resultOne = new UpdateNcoaProcessService.NcoaUpdateResult(); + var errorListOne = new List() + { + "errorOne", + "errorTwo", + "ErrorThree" + }; + var persAddrLineList = new List(); + var persAddrLineOne = new PersonAddrLine() + { + AddressLine1 = "1234 Some Address", + AddressLineTypeCode1 = "ST" + }; + var persAddrLineTwo = new PersonAddrLine() + { + AddressLine1 = "5678 Some Address", + AddressLineTypeCode1 = "ST" + }; + persAddrLineList.Add(persAddrLineOne); + persAddrLineList.Add(persAddrLineTwo); + + resultOne.ErrorList = errorListOne; + resultOne.UpdateList = persAddrLineList; + resultOne.TotalRecordsFound = 5; + + updateResults.Add(resultOne); + + var batchSummary = new UpdateNcoaProcessService.NcoaTotalBatchSummary(updateResults, true); + batchSummary.TotalRecordsFound = 5; + batchSummary.TotalErrorRecords = 3; + batchSummary.TotalRecordsUpdated = 2; + + var expectedResult = $"NCOA Update Total Batch Summary:

Total Files in Batch: 1

Total Records Received: " + + $"5

Total Records Updated: 2

Total Error Records: " + + $"3

Total Records Processed: 5

" + + $"Error File Created: True

Error File Location: Test Location

"; + + // Act + var result = _updateNcoaProcessService.CreateTotalBatchSummaryString(batchSummary, "Test Location"); + + // Assert + Assert.AreEqual(expectedResult, result); + } + + [Test] + public async Task CreateTotalBatchSummaryString_TwoResults_NoLocation() + { + // Arrange + var updateResults = new List(); + var resultOne = new UpdateNcoaProcessService.NcoaUpdateResult(); + var errorListOne = new List() + { + "errorOne", + "errorTwo", + "ErrorThree" + }; + var persAddrLineList = new List(); + var persAddrLineOne = new PersonAddrLine() + { + AddressLine1 = "1234 Some Address", + AddressLineTypeCode1 = "ST" + }; + var persAddrLineTwo = new PersonAddrLine() + { + AddressLine1 = "5678 Some Address", + AddressLineTypeCode1 = "ST" + }; + persAddrLineList.Add(persAddrLineOne); + persAddrLineList.Add(persAddrLineTwo); + + var resultTwo = new UpdateNcoaProcessService.NcoaUpdateResult(); + var errorListTwo = new List() + { + "errorOne", + "errorTwo", + }; + + var persAddrLineThree = new PersonAddrLine() + { + AddressLine1 = "Updated Address", + AddressLineTypeCode1 = "ST" + }; + + var persAddrLineListTwo = new List(); + persAddrLineListTwo.Add(persAddrLineThree); + + resultTwo.ErrorList = errorListTwo; + resultTwo.UpdateList = persAddrLineListTwo; + resultTwo.TotalRecordsFound = 3; + + resultOne.ErrorList = errorListOne; + resultOne.UpdateList = persAddrLineList; + resultOne.TotalRecordsFound = 5; + + updateResults.Add(resultOne); + updateResults.Add(resultTwo); + + var batchSummary = new UpdateNcoaProcessService.NcoaTotalBatchSummary(updateResults, false); + batchSummary.TotalRecordsFound = 8; + batchSummary.TotalErrorRecords = 5; + batchSummary.TotalRecordsUpdated = 3; + + var expectedResult = $"NCOA Update Total Batch Summary:

Total Files in Batch: 2

Total Records Received: " + + $"8

Total Records Updated: 3

Total Error Records: " + + $"5

Total Records Processed: 8

" + + $"Error File Created: False

"; + + // Act + var result = _updateNcoaProcessService.CreateTotalBatchSummaryString(batchSummary, "Test Location"); + + // Assert + Assert.AreEqual(expectedResult, result); + } + + [Test] + public async Task BuildFileUpdateSummary() + { + // Arrange + var updateResult = new UpdateNcoaProcessService.NcoaUpdateResult("Test File Name"); + var errorListOne = new List() + { + "errorOne", + "errorTwo", + "ErrorThree" + }; + var persAddrLineList = new List(); + var persAddrLineOne = new PersonAddrLine() + { + AddressLine1 = "1234 Some Address", + AddressLineTypeCode1 = "ST" + }; + var persAddrLineTwo = new PersonAddrLine() + { + AddressLine1 = "5678 Some Address", + AddressLineTypeCode1 = "ST" + }; + persAddrLineList.Add(persAddrLineOne); + persAddrLineList.Add(persAddrLineTwo); + + updateResult.ErrorList = errorListOne; + updateResult.UpdateList = persAddrLineList; + updateResult.TotalRecordsFound = 5; + + var expectedResult = $"--------------

NCOA File In Batch Summary:

Filename: Test File Name" + + $"

Total Records Received: 5

Total Records Updated: 2" + + $"

Total Error Records: 3

Total Records Processed: " + + $"5

"; + + // Act + var result = _updateNcoaProcessService.BuildFileUpdateSummary(updateResult); + + // Assert + Assert.AreEqual(expectedResult, result); + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdatePersonForAtmHoldsServiceTest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdatePersonForAtmHoldsServiceTest.cs new file mode 100644 index 0000000..4dc1e3b --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/UpdatePersonForAtmHoldsServiceTest.cs @@ -0,0 +1,539 @@ +using Moq; +using NUnit.Framework; +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.Api.Internal.DataCleanUp.Services; +using LCU.Api.Internal.DataCleanUp.DataAccess; +using LCU.Library.Internal.DataCleanUpModel.Enum; +using LCU.Library.Internal.DataCleanUpModel.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; +using System; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Persons; +using TimeZoneConverter; +using LCU.Library.Internal.ApiResponse.Models; +using Newtonsoft.Json; +using LCU.Api.Internal.DataCleanUp.Configuration; + +namespace LCU.Api.Internal.DataCleanUpTest.Services; + +public class UpdatePersonForAtmHoldsServiceTest +{ + private UpdatePersonForAtmHoldsService _updatePersonForAtmHoldsService; + private Mock _mockCoreApiWrapperService; + private Mock _mockCoreApiWrapperDao; + private DataCleanupDefaults _dataCleanUpDefaults; + private DataCleanUpConfiguration _dataCleanUpConfiguration; + + [SetUp] + public void Setup() + { + _dataCleanUpConfiguration = new DataCleanUpConfiguration() + { + TimeZone = "America/Chicago" + }; + + _dataCleanUpDefaults = new DataCleanupDefaults() + { + MemberCheckHoldsUserFieldCode = "MBRH", + MemberCheckHoldsDays = 29 + }; + + _mockCoreApiWrapperDao = new Mock(); + _mockCoreApiWrapperService = new Mock(); + _updatePersonForAtmHoldsService = new UpdatePersonForAtmHoldsService(_mockCoreApiWrapperService.Object, _dataCleanUpDefaults, _dataCleanUpConfiguration); + } + + [Test] + public async Task CleanUpPersonAtmCheckHoldUpdate_Success() + { + var listPersonCheckHoldsUserFields = new List() + { + new PersonCheckHoldsUserField() + { + PersonNumber = 1, + UserFieldExists = true, + OldestActiveEffectiveDate = DateTime.Now, + RecentClosedEffectiveDate = DateTime.Now + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetAtmCheckHoldsForPersonNumbers(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(listPersonCheckHoldsUserFields); + + //Set Up Response + var personUserField = new PersonUserField() + { + PersonNumber = 1, + Value = "N" + }; + + _mockCoreApiWrapperService.Setup(x => x.UpdateAtmCheckHoldsForPersonNumbers(It.IsAny(), It.IsAny())) + .ReturnsAsync(personUserField); + + var newCheckHoldRequest = new UpdatePersonForCheckHoldRequest(); + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdatePersonForCheckHolds, + DataCleanUpPayload = JsonConvert.SerializeObject(newCheckHoldRequest) + }; + + var result = await _updatePersonForAtmHoldsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.UpdateAtmCheckHoldsForPersonNumbers(It.IsAny(), It.IsAny()), Times.Once); + + } + + [Test] + public async Task CleanUpPersonAtmCheckHoldUpdate_Fail() + { + //Set Up Response + var listPersonUserFields = new PersonUserField(); + + _mockCoreApiWrapperService.Setup(x => x.UpdateAtmCheckHoldsForPersonNumbers(It.IsAny(), It.IsAny())) + .ReturnsAsync(listPersonUserFields); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdatePersonForCheckHolds + }; + var result = await _updatePersonForAtmHoldsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.AreEqual(1, result.ResponseStack.Count); + _mockCoreApiWrapperDao.Verify(x => x.UpdateAtmCheckHoldsForPersonNumbers(It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUpPersonAtmCheckHoldAdd_Success() + { + var listPersonCheckHoldsUserFields = new List() + { + new PersonCheckHoldsUserField() + { + PersonNumber = 1, + UserFieldExists = false, + OldestActiveEffectiveDate = DateTime.Now, + RecentClosedEffectiveDate = DateTime.Now + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetAtmCheckHoldsForPersonNumbers(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(listPersonCheckHoldsUserFields); + + //Set Up Response + var personUserField = new PersonUserField() + { + PersonNumber = 1, + Value = "Y" + }; + + _mockCoreApiWrapperService.Setup(x => x.AddAtmCheckHoldsForPersonNumbers(It.IsAny(), It.IsAny())) + .ReturnsAsync(personUserField); + + var newCheckHoldRequest = new UpdatePersonForCheckHoldRequest(); + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdatePersonForCheckHolds, + DataCleanUpPayload = JsonConvert.SerializeObject(newCheckHoldRequest) + }; + var result = await _updatePersonForAtmHoldsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.AddAtmCheckHoldsForPersonNumbers(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task CleanUpPersonAtmCheckHoldAdd_Fail() + { + //Set Up Response + var listPersonUserFields = new PersonUserField(); + + _mockCoreApiWrapperService.Setup(x => x.AddAtmCheckHoldsForPersonNumbers(It.IsAny(), It.IsAny())) + .ReturnsAsync(listPersonUserFields); + + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdatePersonForCheckHolds + }; + var result = await _updatePersonForAtmHoldsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.AreEqual(1, result.ResponseStack.Count); + _mockCoreApiWrapperDao.Verify(x => x.AddAtmCheckHoldsForPersonNumbers(It.IsAny()), Times.Never); + } + + [Test] + public async Task CleanUpPersonAtmCheckHoldAddFetchSize_Success() + { + var listPersonCheckHoldsUserFields = new List() + { + new PersonCheckHoldsUserField() + { + PersonNumber = 1, + UserFieldExists = false, + OldestActiveEffectiveDate = DateTime.Now, + RecentClosedEffectiveDate = DateTime.Now + }, + + new PersonCheckHoldsUserField() + { + PersonNumber = 2, + UserFieldExists = false, + OldestActiveEffectiveDate = DateTime.Now, + RecentClosedEffectiveDate = DateTime.Now + }, + + new PersonCheckHoldsUserField() + { + PersonNumber = 3, + UserFieldExists = false, + OldestActiveEffectiveDate = DateTime.Now, + RecentClosedEffectiveDate = DateTime.Now + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetAtmCheckHoldsForPersonNumbers(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(listPersonCheckHoldsUserFields); + + //Set Up Response + var personUserField = new PersonUserField() + { + PersonNumber = 1, + Value = "Y" + }; + + _mockCoreApiWrapperService.Setup(x => x.AddAtmCheckHoldsForPersonNumbers(It.IsAny(), It.IsAny())) + .ReturnsAsync(personUserField); + + var newCheckHoldRequest = new UpdatePersonForCheckHoldRequest(); + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdatePersonForCheckHolds, + DataCleanUpPayload = JsonConvert.SerializeObject(newCheckHoldRequest) + }; + var result = await _updatePersonForAtmHoldsService.CleanUp(testRequest); + + Assert.NotNull(result); + Assert.AreEqual(testRequest, result.Request); + Assert.IsTrue(result.Successful); + Assert.IsEmpty(result.ResponseStack); + _mockCoreApiWrapperService.Verify(x => x.AddAtmCheckHoldsForPersonNumbers(It.IsAny(), It.IsAny()), Times.Exactly(3)); + } + + [Test] + public async Task CleanUpPersonAtmCheckHoldUpdate_NoAccounts_YesValue_Success() + { + var listPersonCheckHoldsUserFields = new List() + { + new PersonCheckHoldsUserField() + { + PersonNumber = 1, + UserFieldExists = true, + OldestActiveEffectiveDate = null, + RecentClosedEffectiveDate = null + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetAtmCheckHoldsForPersonNumbers(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(listPersonCheckHoldsUserFields); + + var newCheckHoldRequest = new UpdatePersonForCheckHoldRequest(); + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdatePersonForCheckHolds, + DataCleanUpPayload = JsonConvert.SerializeObject(newCheckHoldRequest) + }; + + var dataCleanUpResult = await _updatePersonForAtmHoldsService.CleanUp(testRequest); + var userValueResult = _updatePersonForAtmHoldsService.DeterminePersonUserFieldValue(listPersonCheckHoldsUserFields[0]); + + Assert.NotNull(dataCleanUpResult); + Assert.AreEqual(testRequest, dataCleanUpResult.Request); + Assert.IsTrue(userValueResult.Equals("Y")); + } + + [Test] + public async Task CleanUpPersonAtmCheckHoldUpdate_ActiveInValidClosedInValid_YesValue_Success() + { + var assumedTimezone = TZConvert.GetTimeZoneInfo("America/Chicago"); + DateTime checkHoldDateToConvert = Convert.ToDateTime(DateTime.Now.AddDays(-29)); + var checkHoldDate = TimeZoneInfo.ConvertTime(checkHoldDateToConvert, assumedTimezone).Date; + DateTime oldestActiveDate = checkHoldDate.AddDays(1); + DateTime newestClosedDate = checkHoldDate.AddDays(-1); + + var listPersonCheckHoldsUserFields = new List() + { + new PersonCheckHoldsUserField() + { + PersonNumber = 1, + UserFieldExists = true, + OldestActiveEffectiveDate = oldestActiveDate, //older active account date, invalid check hold timeframe + RecentClosedEffectiveDate = newestClosedDate, //newer closed account date, invalid check hold timeframe + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetAtmCheckHoldsForPersonNumbers(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(listPersonCheckHoldsUserFields); + + var newCheckHoldRequest = new UpdatePersonForCheckHoldRequest(); + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdatePersonForCheckHolds, + DataCleanUpPayload = JsonConvert.SerializeObject(newCheckHoldRequest) + }; + + var dataCleanUpResult = await _updatePersonForAtmHoldsService.CleanUp(testRequest); + var userValueResult = _updatePersonForAtmHoldsService.DeterminePersonUserFieldValue(listPersonCheckHoldsUserFields[0]); + + Assert.NotNull(dataCleanUpResult); + Assert.AreEqual(testRequest, dataCleanUpResult.Request); + Assert.IsTrue(userValueResult.Equals("Y")); + } + + [Test] + public async Task CleanUpPersonAtmCheckHoldUpdate_NoClosedInvalidActive_YesValue_Success() + { + var assumedTimezone = TZConvert.GetTimeZoneInfo("America/Chicago"); + DateTime checkHoldDateToConvert = Convert.ToDateTime(DateTime.Now.AddDays(-28)); + var checkHoldDate = TimeZoneInfo.ConvertTime(checkHoldDateToConvert, assumedTimezone).Date; + DateTime oldestActiveDate = checkHoldDate.AddDays(0); + + var listPersonCheckHoldsUserFields = new List() + { + new PersonCheckHoldsUserField() + { + PersonNumber = 1, + UserFieldExists = true, + OldestActiveEffectiveDate = oldestActiveDate, //more recent active account date, valid check hold timeframe + RecentClosedEffectiveDate = null // no closed account, invalid check hold timeframe + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetAtmCheckHoldsForPersonNumbers(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(listPersonCheckHoldsUserFields); + + var newCheckHoldRequest = new UpdatePersonForCheckHoldRequest(); + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdatePersonForCheckHolds, + DataCleanUpPayload = JsonConvert.SerializeObject(newCheckHoldRequest) + }; + + var dataCleanUpResult = await _updatePersonForAtmHoldsService.CleanUp(testRequest); + var userValueResult = _updatePersonForAtmHoldsService.DeterminePersonUserFieldValue(listPersonCheckHoldsUserFields[0]); + + Assert.NotNull(dataCleanUpResult); + Assert.AreEqual(testRequest, dataCleanUpResult.Request); + Assert.IsTrue(userValueResult.Equals("Y")); + } + + [Test] + public async Task CleanUpPersonAtmCheckHoldUpdate_NoActiveInvalidClosed_YesValue_Success() + { + var assumedTimezone = TZConvert.GetTimeZoneInfo("America/Chicago"); + DateTime checkHoldDateToConvert = Convert.ToDateTime(DateTime.Now.AddDays(-30)); + var checkHoldDate = TimeZoneInfo.ConvertTime(checkHoldDateToConvert, assumedTimezone).Date; + DateTime recentClosedDate = checkHoldDate.AddDays(0); + + var listPersonCheckHoldsUserFields = new List() + { + new PersonCheckHoldsUserField() + { + PersonNumber = 1, + UserFieldExists = true, + OldestActiveEffectiveDate = null, // no active account, invalid check hold timeframe + RecentClosedEffectiveDate = recentClosedDate, //oldest closed account date, invalid check hold timeframe + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetAtmCheckHoldsForPersonNumbers(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(listPersonCheckHoldsUserFields); + + var newCheckHoldRequest = new UpdatePersonForCheckHoldRequest(); + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdatePersonForCheckHolds, + DataCleanUpPayload = JsonConvert.SerializeObject(newCheckHoldRequest) + }; + + var dataCleanUpResult = await _updatePersonForAtmHoldsService.CleanUp(testRequest); + var userValueResult = _updatePersonForAtmHoldsService.DeterminePersonUserFieldValue(listPersonCheckHoldsUserFields[0]); + + Assert.NotNull(dataCleanUpResult); + Assert.AreEqual(testRequest, dataCleanUpResult.Request); + Assert.IsTrue(userValueResult.Equals("Y")); + } + + [Test] + public async Task CleanUpPersonAtmCheckHoldUpdate_NoActiveClosedValid_NoValue_Success() + { + var assumedTimezone = TZConvert.GetTimeZoneInfo("America/Chicago"); + DateTime checkHoldDateToConvert = Convert.ToDateTime(DateTime.Now.AddDays(-28)); + var checkHoldDate = TimeZoneInfo.ConvertTime(checkHoldDateToConvert, assumedTimezone).Date; + DateTime recentClosedDate = checkHoldDate.AddDays(0); + + var listPersonCheckHoldsUserFields = new List() + { + new PersonCheckHoldsUserField() + { + PersonNumber = 1, + UserFieldExists = true, + OldestActiveEffectiveDate = null, //no active account date, invalid check hold timeframe + RecentClosedEffectiveDate = recentClosedDate, //newer closed account date, valid check hold timeframe + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetAtmCheckHoldsForPersonNumbers(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(listPersonCheckHoldsUserFields); + + var newCheckHoldRequest = new UpdatePersonForCheckHoldRequest(); + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdatePersonForCheckHolds, + DataCleanUpPayload = JsonConvert.SerializeObject(newCheckHoldRequest) + }; + + var dataCleanUpResult = await _updatePersonForAtmHoldsService.CleanUp(testRequest); + var userValueResult = _updatePersonForAtmHoldsService.DeterminePersonUserFieldValue(listPersonCheckHoldsUserFields[0]); + + Assert.NotNull(dataCleanUpResult); + Assert.AreEqual(testRequest, dataCleanUpResult.Request); + Assert.IsTrue(userValueResult.Equals("N")); + } + + [Test] + public async Task CleanUpPersonAtmCheckHoldUpdate_NoClosedActiveValid_NoValue_Success() + { + var assumedTimezone = TZConvert.GetTimeZoneInfo("America/Chicago"); + DateTime checkHoldDateToConvert = Convert.ToDateTime(DateTime.Now.AddDays(-29)); + var checkHoldDate = TimeZoneInfo.ConvertTime(checkHoldDateToConvert, assumedTimezone).Date; + DateTime oldestActiveDate = checkHoldDate.AddDays(0); + + var listPersonCheckHoldsUserFields = new List() + { + new PersonCheckHoldsUserField() + { + PersonNumber = 1, + UserFieldExists = true, + OldestActiveEffectiveDate = oldestActiveDate, //older active account date, valid check hold timeframe + RecentClosedEffectiveDate = null, //no closed account date, invalid check hold timeframe + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetAtmCheckHoldsForPersonNumbers(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(listPersonCheckHoldsUserFields); + + var newCheckHoldRequest = new UpdatePersonForCheckHoldRequest(); + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdatePersonForCheckHolds, + DataCleanUpPayload = JsonConvert.SerializeObject(newCheckHoldRequest) + }; + + var dataCleanUpResult = await _updatePersonForAtmHoldsService.CleanUp(testRequest); + var userValueResult = _updatePersonForAtmHoldsService.DeterminePersonUserFieldValue(listPersonCheckHoldsUserFields[0]); + + Assert.NotNull(dataCleanUpResult); + Assert.AreEqual(testRequest, dataCleanUpResult.Request); + Assert.IsTrue(userValueResult.Equals("N")); + } + + [Test] + public async Task CleanUpPersonAtmCheckHoldUpdate_ActiveClosedValid_NoValue_Success() + { + var assumedTimezone = TZConvert.GetTimeZoneInfo("America/Chicago"); + DateTime checkHoldDateToConvert = Convert.ToDateTime(DateTime.Now.AddDays(-29)); + var checkHoldDate = TimeZoneInfo.ConvertTime(checkHoldDateToConvert, assumedTimezone).Date; + DateTime oldestActiveDate = checkHoldDate.AddDays(0); + DateTime newestClosedDate = checkHoldDate.AddDays(0); + + var listPersonCheckHoldsUserFields = new List() + { + new PersonCheckHoldsUserField() + { + PersonNumber = 1, + UserFieldExists = true, + OldestActiveEffectiveDate = oldestActiveDate, //older active account date, valid check hold timeframe + RecentClosedEffectiveDate = newestClosedDate, //newer closed account date, valid check hold timeframe + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetAtmCheckHoldsForPersonNumbers(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(listPersonCheckHoldsUserFields); + + var newCheckHoldRequest = new UpdatePersonForCheckHoldRequest(); + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdatePersonForCheckHolds, + DataCleanUpPayload = JsonConvert.SerializeObject(newCheckHoldRequest) + }; + + var dataCleanUpResult = await _updatePersonForAtmHoldsService.CleanUp(testRequest); + var userValueResult = _updatePersonForAtmHoldsService.DeterminePersonUserFieldValue(listPersonCheckHoldsUserFields[0]); + + Assert.NotNull(dataCleanUpResult); + Assert.AreEqual(testRequest, dataCleanUpResult.Request); + Assert.IsTrue(userValueResult.Equals("N")); + } + + [Test] + public async Task CleanUpPersonAtmCheckHoldUpdate_ActiveInvalidClosedValid_NoValue_Success() + { + var assumedTimezone = TZConvert.GetTimeZoneInfo("America/Chicago"); + DateTime checkHoldDateToConvert = Convert.ToDateTime(DateTime.Now.AddDays(-28)); + var checkHoldDate = TimeZoneInfo.ConvertTime(checkHoldDateToConvert, assumedTimezone).Date; + DateTime olderActiveDate = checkHoldDate.AddDays(28); + DateTime recentClosedDate = checkHoldDate.AddDays(0); + + var listPersonCheckHoldsUserFields = new List() + { + new PersonCheckHoldsUserField() + { + PersonNumber = 1, + UserFieldExists = true, + OldestActiveEffectiveDate = olderActiveDate, //more recent active account date, invalid check hold timeframe + RecentClosedEffectiveDate = recentClosedDate, //newer closed account date, valid check hold timeframe + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetAtmCheckHoldsForPersonNumbers(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(listPersonCheckHoldsUserFields); + + var newCheckHoldRequest = new UpdatePersonForCheckHoldRequest(); + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdatePersonForCheckHolds, + DataCleanUpPayload = JsonConvert.SerializeObject(newCheckHoldRequest) + }; + + var dataCleanUpResult = await _updatePersonForAtmHoldsService.CleanUp(testRequest); + var userValueResult = _updatePersonForAtmHoldsService.DeterminePersonUserFieldValue(listPersonCheckHoldsUserFields[0]); + + Assert.NotNull(dataCleanUpResult); + Assert.AreEqual(testRequest, dataCleanUpResult.Request); + Assert.IsTrue(userValueResult.Equals("N")); + } + + [Test] + public async Task CleanUpPersonAtmCheckHoldUpdate_ActiveValidClosedInValid_NoValue_Success() + { + var assumedTimezone = TZConvert.GetTimeZoneInfo("America/Chicago"); + DateTime checkHoldDateToConvert = Convert.ToDateTime(DateTime.Now.AddDays(-29)); + var checkHoldDate = TimeZoneInfo.ConvertTime(checkHoldDateToConvert, assumedTimezone).Date; + DateTime olderActiveDate = checkHoldDate.AddDays(29); + DateTime recentClosedDate = checkHoldDate.AddDays(29); + + var listPersonCheckHoldsUserFields = new List() + { + new PersonCheckHoldsUserField() + { + PersonNumber = 1, + UserFieldExists = true, + OldestActiveEffectiveDate = olderActiveDate, //more recent active account date, valid check hold timeframe + RecentClosedEffectiveDate = recentClosedDate, //newer closed account date, invalid check hold timeframe + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetAtmCheckHoldsForPersonNumbers(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(listPersonCheckHoldsUserFields); + + var newCheckHoldRequest = new UpdatePersonForCheckHoldRequest(); + var testRequest = new DataCleanUpRequest() + { + CleanUpType = CleanUpTypes.UpdatePersonForCheckHolds, + DataCleanUpPayload = JsonConvert.SerializeObject(newCheckHoldRequest) + }; + + var dataCleanUpResult = await _updatePersonForAtmHoldsService.CleanUp(testRequest); + var userValueResult = _updatePersonForAtmHoldsService.DeterminePersonUserFieldValue(listPersonCheckHoldsUserFields[0]); + + Assert.NotNull(dataCleanUpResult); + Assert.AreEqual(testRequest, dataCleanUpResult.Request); + Assert.IsTrue(userValueResult.Equals("N")); + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/Validation/NcoaValidationServiceTest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/Validation/NcoaValidationServiceTest.cs new file mode 100644 index 0000000..54fadc5 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Services/Validation/NcoaValidationServiceTest.cs @@ -0,0 +1,347 @@ +using LCU.Api.Internal.DataCleanUp.Models.ParserModels; +using LCU.Api.Internal.DataCleanUp.Services.Validation; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.PostalAddresses; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace LCU.Api.Internal.DataCleanUpTest.Services.Validation; + +public class NcoaValidationServiceTest +{ + private readonly NcoaValidationService _ncoaValidationService; + + public NcoaValidationServiceTest() + { + _ncoaValidationService = new NcoaValidationService(); + } + + [Test] + public async Task IsBusinessRecord_True() + { + // Arrange + var ncoaRecord = new NcoaRecord() + { + UserId = "123456", + NcoaType = "I", + ChangeDate = "202212", + PrimaryName = "Test E Testerson", + CurrentAddressOne = "1 Imaginary Lane", + CurrentAddressTwo = "Apt 13", + CurrentAddressThree = "Additional Address Line", + CurrentAddressFour = "ReallyLongCityName", + CurrentAddressFive = "Wisconsin, 53186", + SecondaryName = "Test Testerson", + BusinessName = "Testerson's Testing", + NewAddressLine = "New Address Line PO BOX Test", + City = "New Test City", + StateCode = "WI", + ZipCode = "53022", + ZipSuffix = "1234", + UserIdTwo = "123456", + StatementCode = "TestStatementCode", + }; + + // Act + var result = _ncoaValidationService.IsBusinessRecord(ncoaRecord); + + // Assert + Assert.True(result); + } + + [Test] + public async Task IsBusinessRecord_False_Null() + { + // Arrange + var ncoaRecord = new NcoaRecord() + { + UserId = "123456", + NcoaType = "I", + ChangeDate = "202212", + PrimaryName = "Test E Testerson", + CurrentAddressOne = "1 Imaginary Lane", + CurrentAddressTwo = "Apt 13", + CurrentAddressThree = "Additional Address Line", + CurrentAddressFour = "ReallyLongCityName", + CurrentAddressFive = "Wisconsin, 53186", + SecondaryName = "Test Testerson", + BusinessName = null, + NewAddressLine = "New Address Line PO BOX Test", + City = "New Test City", + StateCode = "WI", + ZipCode = "53022", + ZipSuffix = "1234", + UserIdTwo = "123456", + StatementCode = "TestStatementCode", + }; + + // Act + var result = _ncoaValidationService.IsBusinessRecord(ncoaRecord); + + // Assert + Assert.False(result); + } + + [Test] + public async Task IsBusinessRecord_False_Empty() + { + // Arrange + var ncoaRecord = new NcoaRecord() + { + UserId = "123456", + NcoaType = "I", + ChangeDate = "202212", + PrimaryName = "Test E Testerson", + CurrentAddressOne = "1 Imaginary Lane", + CurrentAddressTwo = "Apt 13", + CurrentAddressThree = "Additional Address Line", + CurrentAddressFour = "ReallyLongCityName", + CurrentAddressFive = "Wisconsin, 53186", + SecondaryName = "Test Testerson", + BusinessName = "", + NewAddressLine = "New Address Line PO BOX Test", + City = "New Test City", + StateCode = "WI", + ZipCode = "53022", + ZipSuffix = "1234", + UserIdTwo = "123456", + StatementCode = "TestStatementCode", + }; + + // Act + var result = _ncoaValidationService.IsBusinessRecord(ncoaRecord); + + // Assert + Assert.False(result); + } + + [Test] + public async Task ParsePersonNumber_Ok() + { + // Arrange + var agreement = new Agreement() + { + PersonNumber = 111 + }; + + // Act + var result = _ncoaValidationService.ParsePersonNumber(agreement); + + // Assert + Assert.AreEqual(111, result); + } + + [Test] + public async Task ParsePersonNumber_FailParse() + { + // Arrange + var agreement = new Agreement() + { + PersonNumber = 11111111111 + }; + + // Act + var result = _ncoaValidationService.ParsePersonNumber(agreement); + + // Assert + Assert.AreEqual(-1, result); + } + + [Test] + public async Task ParsePersonNumber_NullAgreement() + { + // Arrange/Act + var result = _ncoaValidationService.ParsePersonNumber(null); + + // Assert + Assert.AreEqual(-1, result); + } + + [Test] + public async Task IsAddrUseCodeFound_Ok() + { + // Arrange + var addressList = new List(); + var address = new PersonPostalAddress() + { + AddressUseCode = "PRI", + AddressNumber = 111 + }; + addressList.Add(address); + addressList.AsReadOnly(); + + // Act + var result = _ncoaValidationService.IsAddrUseCodeFound(addressList, "PRI"); + + // Assert + Assert.AreEqual(111, result.AddressNumber); + } + + [Test] + public async Task IsAddrUseCodeFound_Null() + { + // Arrange + var addressList = new List(); + var address = new PersonPostalAddress() + { + AddressUseCode = "ALT", + AddressNumber = 111 + }; + addressList.Add(address); + addressList.AsReadOnly(); + + // Act + var result = _ncoaValidationService.IsAddrUseCodeFound(addressList, "PRI"); + + // Assert + Assert.Null(result); + } + + [Test] + public async Task IsAddrLineTooLong_Ok() + { + // Arrange + string addrLine = "Short Address"; + + // Act + var result = _ncoaValidationService.IsAddrLineTooLong(addrLine); + + // Assert + Assert.False(result); + } + + [Test] + public async Task IsAddrLineTooLong_TooLong() + { + // Arrange + string addrLine = "This is a long addrLine that should be more than 40 characters and should fail validation"; + + // Act + var result = _ncoaValidationService.IsAddrLineTooLong(addrLine); + + // Assert + Assert.True(result); + } + + [Test] + public async Task AgreementHasOrgNumber_Ok() + { + // Arrange + var agreement = new Agreement() + { + PersonNumber = 11111111111 + }; + + // Act + var result = _ncoaValidationService.AgreementHasOrgNumber(agreement); + + // Assert + Assert.False(result); + } + + [Test] + public async Task AgreementHasOrgNumber_HasOrgNumber() + { + // Arrange + var agreement = new Agreement() + { + PersonNumber = 11111111111, + ByOrgNbr = 123456 + }; + + // Act + var result = _ncoaValidationService.AgreementHasOrgNumber(agreement); + + // Assert + Assert.True(result); + } + + [Test] + public async Task IsOnExlusionList_OnExclusionList() + { + // Arrange + var exclusionList = new List() + { + "12345", + "6789", + "2468" + }; + + // Act + var result = _ncoaValidationService.IsOnExclusionList(2468, exclusionList); + + // Assert + Assert.True(result); + } + + [Test] + public async Task IsOnExlusionList_NotOnExclusionList() + { + // Arrange + var exclusionList = new List() + { + "12345", + "6789", + "2468" + }; + + // Act + var result = _ncoaValidationService.IsOnExclusionList(13579, exclusionList); + + // Assert + Assert.False(result); + } + + [Test] + public async Task IsAddressUpdatedRecently_UpdatedRecently() + { + // Arrange + var personPostalAddress = new PersonPostalAddress() + { + LastMaintained = DateTime.Now.AddDays(-10) + }; + + // Act + var result = _ncoaValidationService.IsAddressUpdatedRecently(personPostalAddress, -25, DateTime.Now.ToString()); + + // Assert + Assert.True(result); + } + + [Test] + public async Task IsAddressUpdatedRecently_UpdatedRecently_SameAsExclusionDays() + { + // Arrange + var time = DateTime.Now; + var personPostalAddress = new PersonPostalAddress() + { + LastMaintained = time.AddDays(-25) + }; + + // Act + var result = _ncoaValidationService.IsAddressUpdatedRecently(personPostalAddress, -25, time.ToString()); + + // Assert + Assert.True(result); + } + + [Test] + public async Task IsAddressUpdatedRecently_NotUpdatedRecently() + { + // Arrange + var personPostalAddress = new PersonPostalAddress() + { + LastMaintained = DateTime.Now.AddDays(-25) + }; + + // Act + var result = _ncoaValidationService.IsAddressUpdatedRecently(personPostalAddress, -10, DateTime.Now.ToString()); + + // Assert + Assert.False(result); + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Utilities/HttpUtilitiesTest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Utilities/HttpUtilitiesTest.cs new file mode 100644 index 0000000..25c230d --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Api.Internal.DataCleanUpTest/Utilities/HttpUtilitiesTest.cs @@ -0,0 +1,156 @@ +using NUnit.Framework; +using System.Collections.Generic; +using LCU.Api.Internal.DataCleanUp.Configuration; +using LCU.Library.Internal.ApiSecurity.Enums; +using LCU.Library.Internal.ApiSecurity.Models; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.CoreRequests; +using LCU.Library.Internal.LcuHttpClient.Utilities; + +namespace LCU.Api.Internal.DataCleanUpTest.Utilities; + +public class HttpUtilitiesTest +{ + + private const string ClientKeyValue = "DataCleanUp"; + private const string IncludesParameterKey = "includes"; + + private readonly ApiSecurityConfiguration _apiSecurityConfigurationWithInternalKey = new ApiSecurityConfiguration() + { + ApiKeyAuthenticationFailureBehavior = ApiKeyAuthenticationFailureBehavior.Error, + ExternalApiKeySet = new Dictionary(), + InternalApiKeySet = new Dictionary() + { + { ClientKeyValue, "some_guid-1234-5666" } + } + }; + + private readonly ApiSecurityConfiguration _apiSecurityConfigurationWithoutInternalKey = new ApiSecurityConfiguration() + { + ApiKeyAuthenticationFailureBehavior = ApiKeyAuthenticationFailureBehavior.Error, + ExternalApiKeySet = new Dictionary(), + InternalApiKeySet = new Dictionary() + }; + + private readonly CoreApiWrapperConfiguration _coreApiWrapperConfiguration = new CoreApiWrapperConfiguration() + { + CoreApiWrapperUrl = "https://localhost:44364", + AccessChannelPersons = "/api/core/AccessChannelPersons", + AccesschannelPersonWithIncludes = "/api/core/AccessChannelPersons/GetWithIncludes" + }; + + [SetUp] + public void Setup() + { + + } + + [Test] + public void HttpUtilities_GetApiKeyHeaders_Success() + { + var result = HttpUtilities.GetApiKeyHeaders(ClientKeyValue, + _apiSecurityConfigurationWithInternalKey.ExtractApiKey(ClientKeyValue, ApiKeySetName.InternalKeySet)); + + var modelValues = new Dictionary() + { + {"Client", ClientKeyValue }, + {"ApiKey", "some_guid-1234-5666" } + }; + + Assert.IsNotNull(result); + Assert.AreEqual(modelValues, result); + } + + [Test] + public void HttpUtilities_BuildEndPointWithModelParams_Success() + { + var request = new AccessChannelPersonsByPersonRequest() + { + PersonNumber = 145, + ActiveOnly = true, + IncludeCards = false + }; + + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.AccessChannelPersons}"; + + var result = HttpUtilities.BuildEndPointWithQueryParams(path, request); + + Assert.IsNotNull(result); + Assert.AreEqual("https://localhost:44364/api/core/AccessChannelPersons?PersonNumber=145&ActiveOnly=True&IncludeCards=False", result); + } + + [Test] + public void HttpUtilities_BuildEndPointWithDictionaryParams_Success() + { + var request = new AccessChannelPersonsByPersonRequest() + { + PersonNumber = 145, + ActiveOnly = true, + IncludeCards = false + }; + + var testPersonNumbers = new List() + { + "111111" + }; + + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.AccesschannelPersonWithIncludes}"; + var dictionaryOfParameters = HttpUtilities.BuildDictionaryValues(request); + foreach (var includedString in testPersonNumbers) + { + dictionaryOfParameters.Add(IncludesParameterKey, includedString); + } + + var result = HttpUtilities.BuildEndPointWithQueryParams(path, dictionaryOfParameters); + + Assert.IsNotNull(result); + Assert.AreEqual("https://localhost:44364/api/core/AccessChannelPersons/GetWithIncludes?PersonNumber=145&ActiveOnly=True&IncludeCards=False&includes=111111", result); + } + + [Test] + public void HttpUtilities_BuildEndPointWithKeyValuePairModelListPropertyParams_Success() + { + var request = new AccountsByMajorMinorBranchAndStatusRequest() + { + MajorTypes = new List() { "SAV"}, + MinorTypes = new List() { "SV01", "BS01"}, + AccountStatuses = new List() { "APPR"}, + BranchCodes = new List() { 1310 } + }; + + var testPersonNumbers = new List() + { + "111111" + }; + + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.GetAccountsByMajorMinorBranchAndStatus}"; + var keyValuePairs = HttpUtilities.BuildKeyValuePairs(request); + + var result = HttpUtilities.BuildEndPointWithKeyValuePairs(path, keyValuePairs); + + Assert.IsNotNull(result); + Assert.AreEqual("https://localhost:44364?MajorTypes=SAV&MinorTypes=SV01&MinorTypes=BS01&AccountStatuses=APPR&BranchCodes=1310", result); + } + + [Test] + public void HttpUtilities_BuildEndPointWithKeyValuePairModelPropertyParams_Success() + { + + var request = new AccessChannelPersonsByPersonRequest() + { + PersonNumber = 145, + ActiveOnly = true, + IncludeCards = false + }; + + + var path = $"{_coreApiWrapperConfiguration.CoreApiWrapperUrl}{_coreApiWrapperConfiguration.AccessChannelPersons}"; + var keyValuePairs = HttpUtilities.BuildKeyValuePairs(request); + + var result = HttpUtilities.BuildEndPointWithKeyValuePairs(path, keyValuePairs); + + Assert.IsNotNull(result); + Assert.AreEqual("https://localhost:44364/api/core/AccessChannelPersons?PersonNumber=145&ActiveOnly=True&IncludeCards=False", result); + } +} + + diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Entities/Ltv_DataCleanUp.cs b/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Entities/Ltv_DataCleanUp.cs new file mode 100644 index 0000000..c326bf0 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Entities/Ltv_DataCleanUp.cs @@ -0,0 +1,14 @@ + +using System.ComponentModel.DataAnnotations; + +namespace LCU.Library.Internal.DataCleanUpModel.Entities +{ + public class Ltv_DataCleanUp + { + [Key] + public int LoanToValueId { get; set; } + public string AccountNumber { get; set; } + public double Ltv { get; set; } + public string MinorType { get; set; } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Enum/CleanUpTypes.cs b/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Enum/CleanUpTypes.cs new file mode 100644 index 0000000..d42b583 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Enum/CleanUpTypes.cs @@ -0,0 +1,23 @@ +namespace LCU.Library.Internal.DataCleanUpModel.Enum +{ + public enum CleanUpTypes + { + HyphenatedUserId = 0, + DeactivateCustodialEAgreements = 1, + CloseCustodialVruAgreements = 2, + MaskTransactionExternalDescriptionWithSsn = 3, + AddFundsToVipSavingsAccounts = 4, + UpdateAdminBranchCodesByAccountNumber = 5, + UpdateAccountLoanToValue = 6, + UpdateAccountGroupForAnalysis = 7, + UpdatePersonForCheckHolds = 8, + UpdateMissingBatchSavings = 9, + UpdateAccountPmiCancel = 10, + UpdateAccountNickname = 11, + UpdateNcoaProcess = 12, + UpdateAccountCreditReportType = 13, + BatchAddFundsToVipSavingsAccounts = 14, + UpdateFannieMaeMortgage = 15, + AddFundsToIndirectSavingsAccounts = 16 + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/LCU.Library.Internal.DataCleanUpModel.csproj b/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/LCU.Library.Internal.DataCleanUpModel.csproj new file mode 100644 index 0000000..4a36593 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/LCU.Library.Internal.DataCleanUpModel.csproj @@ -0,0 +1,48 @@ + + + + netstandard2.1 + True + 1.0.9 + + 1.0.0 - Initial Creation + 1.0.1 - Updated CleanUp Type + 1.0.2 - Add NcoaUpdateRequest + 1.0.3 - Added CreditReportTypeUpdateRequest + 1.0.4 - Update NcoaUpdateProcess model + 1.0.5 - Update NcoaUpdateProcess model for exclusion + 1.0.6 - Added FannieMae Cleanup Type + 1.0.7 - Added IndirectFundingRequest + 1.0.8 - Edit IndirectFundingRequest + 1.0.9 - Upgraded FileOperations package version + + + 1.0.0 - Initial Creation + 1.0.1 - Updated CleanUp Type + 1.0.2 - Add NcoaUpdateRequest + 1.0.3 - Added CreditReportTypeUpdateRequest + 1.0.4 - Update NcoaUpdateProcess model + 1.0.5 - Update NcoaUpdateProcess model for exclusion + 1.0.6 - Added FannieMae Cleanup Type + 1.0.7 - Added IndirectFundingRequest + 1.0.8 - Edit IndirectFundingRequest + 1.0.9 - Upgraded FileOperations package version + + + + + 1701;1702;8618;8605 + + + + 1701;1702;8618;8605 + + + + + + + + + + diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/CreditReportTypeUpdateRequest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/CreditReportTypeUpdateRequest.cs new file mode 100644 index 0000000..1a1ffa9 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/CreditReportTypeUpdateRequest.cs @@ -0,0 +1,9 @@ +using LCU.Library.Internal.ApiResponse.Models; + +namespace LCU.Library.Internal.DataCleanUpModel.Models +{ + public class CreditReportTypeRequest : ReturnResponse + { + public string SourcePath { get; set; } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/DataCleanUpRequest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/DataCleanUpRequest.cs new file mode 100644 index 0000000..40cb921 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/DataCleanUpRequest.cs @@ -0,0 +1,11 @@ +using LCU.Library.Internal.ApiResponse.Models; +using LCU.Library.Internal.DataCleanUpModel.Enum; + +namespace LCU.Library.Internal.DataCleanUpModel.Models +{ + public class DataCleanUpRequest : ReturnResponse + { + public CleanUpTypes CleanUpType { get; set; } + public string DataCleanUpPayload { get; set; } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/DataCleanUpResult.cs b/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/DataCleanUpResult.cs new file mode 100644 index 0000000..8607674 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/DataCleanUpResult.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; + +namespace LCU.Library.Internal.DataCleanUpModel.Models +{ + public class DataCleanUpResult + { + public DataCleanUpResult(DataCleanUpRequest request, + bool successful, + List responseStack) + { + Request = request; + Successful = successful; + ResponseStack = responseStack; + } + + public DataCleanUpRequest Request { get; set; } + public bool Successful { get; set; } + public List ResponseStack { get; set; } + } +} \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/FannieMaeMortgageUpdateRequest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/FannieMaeMortgageUpdateRequest.cs new file mode 100644 index 0000000..542c9bc --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/FannieMaeMortgageUpdateRequest.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using LCU.Library.Internal.FileOperationsModels.Models.NameSettings; +using LCU.Library.Internal.ApiResponse.Models; + +namespace LCU.Library.Internal.DataCleanUpModel.Models +{ + public class FannieMaeMortgageRequest : ReturnResponse + { + [Required] + public string SourcePath { get; set; } + + [Required] + public string Filename { get; set; } + + public DynamicNameSetting DynamicFileSettings { get; set; } + + [Required] + public string ErrorDestinationPath { get; set; } + + [Required] + public List EmailSummaryRecipients { get; set; } + + [NotMapped] + public string FinalSourcePath + { + get + { + var path = SourcePath.EndsWith("\\") ? $"{SourcePath}" : $"{SourcePath}\\"; + return path; + } + } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/IndirectFundingRequest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/IndirectFundingRequest.cs new file mode 100644 index 0000000..99b9e1e --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/IndirectFundingRequest.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; +using LCU.Library.Internal.ApiResponse.Models; + +namespace LCU.Library.Internal.DataCleanUpModel.Models +{ + public class IndirectFundingRequest : ReturnResponse + { + [Required] + public string Filename { get; set; } + + [Required] + public string SummaryFileDestinationPath { get; set; } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/NcoaUpdateRequest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/NcoaUpdateRequest.cs new file mode 100644 index 0000000..ae9d7cb --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/NcoaUpdateRequest.cs @@ -0,0 +1,40 @@ +using LCU.Library.Internal.FileOperationsModels.Models.NameSettings; +using LCU.Library.Internal.ApiResponse.Models; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Text; + +namespace LCU.Library.Internal.DataCleanUpModel.Models +{ + public class NcoaUpdateRequest : ReturnResponse + { + [Required] + public string SourcePath { get; set; } + [Required] + public string Filename { get; set; } + + public DynamicNameSetting DynamicFileSettings { get; set; } + [Required] + public string ErrorDestinationPath { get; set; } + [Required] + public List EmailSummaryRecipients { get; set; } + [Required] + public string ExclusionFilePath { get; set; } + [Required] + [Range(-1000, 0, ErrorMessage = "Value must be 0 or a negative number. ")] + public int ExclusionDays { get; set; } = -180; + + + [NotMapped] + public string FinalSourcePath + { + get + { + var path = SourcePath.EndsWith("\\") ? $"{SourcePath}" : $"{SourcePath}\\"; + return path; + } + } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/UpdatePersonForCheckHoldRequest.cs b/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/UpdatePersonForCheckHoldRequest.cs new file mode 100644 index 0000000..fa11138 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/LCU.Library.Internal.DataCleanUpModel/Models/UpdatePersonForCheckHoldRequest.cs @@ -0,0 +1,23 @@ +using System; +using LCU.Library.Internal.ApiResponse.Models; + +namespace LCU.Library.Internal.DataCleanUpModel.Models +{ + public class UpdatePersonForCheckHoldRequest : ReturnResponse + { + private int? fetchSize; + public DateTime? ResetStartDate { get; set; } + public DateTime? ResetEndDate { get; set; } + public int? FetchSize + { + get + { + return fetchSize; + } + set + { + fetchSize = value != 0 ? value : null; + } + } + } +} diff --git a/LCU.Api.Internal.DataCleanUp/README.md b/LCU.Api.Internal.DataCleanUp/README.md new file mode 100644 index 0000000..e51a6fd --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/README.md @@ -0,0 +1,2 @@ +# Introduction +DataCleanUp Api was created to help with any required data clean up request. The api uses the queue based architecture. \ No newline at end of file diff --git a/LCU.Api.Internal.DataCleanUp/_kube_local_testing/install_dependencies.ps1 b/LCU.Api.Internal.DataCleanUp/_kube_local_testing/install_dependencies.ps1 new file mode 100644 index 0000000..8b1994d --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/_kube_local_testing/install_dependencies.ps1 @@ -0,0 +1 @@ +cinst -y kind diff --git a/LCU.Api.Internal.DataCleanUp/_kube_local_testing/kind.cluster.config b/LCU.Api.Internal.DataCleanUp/_kube_local_testing/kind.cluster.config new file mode 100644 index 0000000..b33f889 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/_kube_local_testing/kind.cluster.config @@ -0,0 +1,7 @@ +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +nodes: +- role: control-plane + extraPortMappings: + - containerPort: 30000 + hostPort: 80 diff --git a/LCU.Api.Internal.DataCleanUp/_kube_local_testing/setup_and_deploy.ps1 b/LCU.Api.Internal.DataCleanUp/_kube_local_testing/setup_and_deploy.ps1 new file mode 100644 index 0000000..48d3ed7 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/_kube_local_testing/setup_and_deploy.ps1 @@ -0,0 +1,15 @@ +kind create cluster --config kind.cluster.config --wait 300s + +helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx +helm repo update + +helm install my-release ingress-nginx/ingress-nginx ` + --set controller.service.type=LoadBalancer ` + --set controller.service.nodePorts.http=30000 ` + --set controller.service.nodePorts.https=30001 + +docker build -t local/data-cleanup:1.0 .. + +kind load docker-image local/data-cleanup:1.0 + +kubectl apply -k ..\_deploy\overlays\local diff --git a/LCU.Api.Internal.DataCleanUp/_kube_local_testing/teardown.ps1 b/LCU.Api.Internal.DataCleanUp/_kube_local_testing/teardown.ps1 new file mode 100644 index 0000000..64866e8 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/_kube_local_testing/teardown.ps1 @@ -0,0 +1 @@ +kind delete cluster diff --git a/LCU.Api.Internal.DataCleanUp/azdo_pipelines/azure-k8s-pipeline.yaml b/LCU.Api.Internal.DataCleanUp/azdo_pipelines/azure-k8s-pipeline.yaml new file mode 100644 index 0000000..62ca707 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/azdo_pipelines/azure-k8s-pipeline.yaml @@ -0,0 +1,55 @@ +parameters: +- name: target_environment + displayName: Target Environment + type: string + default: qa + values: + - qa + - uat + - prd +- name: k8s_namespace + displayName: K8s Namespace to deploy to + type: string + default: landmarkcu + values: + - landmarkcu +variables: +- template: ./config-files/${{ parameters.target_environment }}-pvars.yaml +- name: source_branch_name + value: $[replace(replace(variables['Build.SourceBranch'], 'refs/heads/', ''), '/', '-')] +- name: docker_container_repository_name + value: landmarkcu/lcu.api.internal.datacleanup-datacleanup +resources: + repositories: + - repository: azdo_pipeline_templates + type: git + name: Infrastructure Platform/azdo-pipeline-templates + ref: main +stages: +# DOTNET BUILD AND NUGET PUSH +- template: dotnet-nuget-build-push.yaml@azdo_pipeline_templates + parameters: + azdo_agent_pool: $(pvar_azdo_agent_pool_nuget) + azure_artifacts_feed: 'LCU-Internal' +# DOCKER BUILD AND PUSH +- template: docker-build-push.yaml@azdo_pipeline_templates + parameters: + azdo_agent_pool: $(pvar_azdo_agent_pool) + docker_registry_service_connection: $(pvar_docker_registry_service_connection) + docker_container_repository_name: $(docker_container_repository_name) + dockerfile_path: ./Dockerfile + docker_image_tags: | + build-$(Build.BuildId) + $(source_branch_name) +# K8S DEPLOY +- template: k8s-deploy.yaml@azdo_pipeline_templates + parameters: + dependsOn: CI + condition: or(eq(variables['Build.SourceBranchName'], 'develop'), eq(variables['Build.SourceBranchName'], 'main')) + azdo_agent_pool: $(pvar_azdo_agent_pool) + kubectl_version: $(pvar_kubectl_version) + k8s_service_connection: $(pvar_k8s_service_connection) + k8s_namespace: ${{ parameters.k8s_namespace }} + k8s_kustomization_path: ./kustomize/overlays/${{ parameters.target_environment }} + docker_registry_service_connection: $(pvar_docker_registry_service_connection) + docker_image_to_deploy: $(docker_container_repository_name):build-$(Build.BuildId) diff --git a/LCU.Api.Internal.DataCleanUp/azdo_pipelines/azure-pipelines-feature-branches.yaml b/LCU.Api.Internal.DataCleanUp/azdo_pipelines/azure-pipelines-feature-branches.yaml new file mode 100644 index 0000000..ee44aef --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/azdo_pipelines/azure-pipelines-feature-branches.yaml @@ -0,0 +1,10 @@ +trigger: + branches: + include: + - '*' + exclude: + - 'main' + - 'develop' +extends: + template: azure-k8s-pipeline.yaml + diff --git a/LCU.Api.Internal.DataCleanUp/azdo_pipelines/azure-pipelines-prd.yaml b/LCU.Api.Internal.DataCleanUp/azdo_pipelines/azure-pipelines-prd.yaml new file mode 100644 index 0000000..7d13684 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/azdo_pipelines/azure-pipelines-prd.yaml @@ -0,0 +1,9 @@ +trigger: + branches: + include: + - 'main' +extends: + template: azure-k8s-pipeline.yaml + parameters: + target_environment: prd + k8s_namespace: landmarkcu diff --git a/LCU.Api.Internal.DataCleanUp/azdo_pipelines/azure-pipelines-qa.yaml b/LCU.Api.Internal.DataCleanUp/azdo_pipelines/azure-pipelines-qa.yaml new file mode 100644 index 0000000..f581dd4 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/azdo_pipelines/azure-pipelines-qa.yaml @@ -0,0 +1,9 @@ +trigger: + branches: + include: + - 'develop' +extends: + template: azure-k8s-pipeline.yaml + parameters: + target_environment: qa + k8s_namespace: landmarkcu diff --git a/LCU.Api.Internal.DataCleanUp/azdo_pipelines/azure-pipelines-uat.yaml b/LCU.Api.Internal.DataCleanUp/azdo_pipelines/azure-pipelines-uat.yaml new file mode 100644 index 0000000..4747234 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/azdo_pipelines/azure-pipelines-uat.yaml @@ -0,0 +1,9 @@ +trigger: + branches: + include: + - 'main' +extends: + template: azure-k8s-pipeline.yaml + parameters: + target_environment: uat + k8s_namespace: landmarkcu diff --git a/LCU.Api.Internal.DataCleanUp/azdo_pipelines/config-files/prd-pvars.yaml b/LCU.Api.Internal.DataCleanUp/azdo_pipelines/config-files/prd-pvars.yaml new file mode 100644 index 0000000..19c41d9 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/azdo_pipelines/config-files/prd-pvars.yaml @@ -0,0 +1,9 @@ +--- +variables: + pvar_azdo_agent_pool: vmss-sub-df-lcu-apps-prd-lz-uscz + pvar_docker_registry_service_connection: Docker Registry LMCU + pvar_k8s_service_connection: svcon-sub-df-lcu-apps-prd-aks-k8s-uscz + pvar_kubectl_version: 1.25.9 + pvar_azdo_agent_pool_nuget: LCUOnPrem + pvar_azdo_agent_pool_db: LCUOnPrem + pvar_azdo_deployment_environment_db: DB-PRD diff --git a/LCU.Api.Internal.DataCleanUp/azdo_pipelines/config-files/qa-pvars.yaml b/LCU.Api.Internal.DataCleanUp/azdo_pipelines/config-files/qa-pvars.yaml new file mode 100644 index 0000000..4c72616 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/azdo_pipelines/config-files/qa-pvars.yaml @@ -0,0 +1,9 @@ +--- +variables: + pvar_azdo_agent_pool: vmss-sub-df-lcu-apps-qa-lz-uscz + pvar_docker_registry_service_connection: Docker Registry LMCU + pvar_k8s_service_connection: svcon-sub-df-lcu-apps-qa-aks-k8s-uscz + pvar_kubectl_version: 1.25.9 + pvar_azdo_agent_pool_nuget: LCUOnPrem + pvar_azdo_agent_pool_db: LCUOnPrem + pvar_azdo_deployment_environment_db: DB-QA diff --git a/LCU.Api.Internal.DataCleanUp/azdo_pipelines/config-files/uat-pvars.yaml b/LCU.Api.Internal.DataCleanUp/azdo_pipelines/config-files/uat-pvars.yaml new file mode 100644 index 0000000..95955c0 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/azdo_pipelines/config-files/uat-pvars.yaml @@ -0,0 +1,9 @@ +--- +variables: + pvar_azdo_agent_pool: vmss-sub-df-lcu-apps-uat-lz-uscz + pvar_docker_registry_service_connection: Docker Registry LMCU + pvar_k8s_service_connection: svcon-sub-df-lcu-apps-uat-aks-k8s-uscz + pvar_kubectl_version: 1.25.9 + pvar_azdo_agent_pool_nuget: LCUOnPrem + pvar_azdo_agent_pool_db: LCUOnPrem + pvar_azdo_deployment_environment_db: DB-UAT diff --git a/LCU.Api.Internal.DataCleanUp/cleanbuildrun.sh b/LCU.Api.Internal.DataCleanUp/cleanbuildrun.sh new file mode 100644 index 0000000..193be9b --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/cleanbuildrun.sh @@ -0,0 +1,16 @@ +#!/bin/bash +echo "Building DataCleanUp Docker Image"; +dotnet clean +rm -rf LCU.Api.Internal.DataCleanUp/bin +rm -rf LCU.Api.Internal.DataCleanUp/obj +rm -rf LCU.Api.Internal.DataCleanUpLib/bin +rm -rf LCU.Api.Internal.DataCleanUpLib/obj +rm -rf LCU.Library.Internal.DataCleanUpModel/bin +rm -rf LCU.Library.Internal.DataCleanUpModel/obj +rm -rf LCU.Api.Internal.DataCleanUpTest/obj +rm -rf LCU.Api.Internal.DataCleanUpTest/bin +docker build -t landmarkcu/datacleanup . +echo "Running DataCleanUp Docker Container"; +docker run -p 8080:80 landmarkcu/datacleanup + + diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/base/Deployment.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/base/Deployment.yaml new file mode 100644 index 0000000..c7e2de7 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/base/Deployment.yaml @@ -0,0 +1,92 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: data-clean-up-api +spec: + replicas: 1 + selector: + matchLabels: + app: data-clean-up-api + strategy: + rollingUpdate: + maxSurge: 25% + maxUnavailable: 25% + type: RollingUpdate + template: + metadata: + labels: + app: data-clean-up-api + spec: + containers: + - name: data-clean-up-api + image: data-clean-up-api + resources: + limits: + memory: "1536Mi" + cpu: "500m" + ports: + - containerPort: 8080 + livenessProbe: + initialDelaySeconds: 5 + periodSeconds: 5 + httpGet: + path: /api/status + port: 8080 + readinessProbe: + initialDelaySeconds: 5 + periodSeconds: 5 + httpGet: + path: /api/status + port: 8080 + volumeMounts: + - name: volume-lcu-internal-cert + mountPath: /etc/ssl/certs/lcu-internal-cert.pem + subPath: lcu-cert-internal.pem + - name: volume-appsettings + mountPath: /app/config/mapped-appsettings + - name: data-clean-up-api-secrets + mountPath: /vault/secrets/data-clean-up-api-security-configuration-internal-api-key-sets.json + subPath: data-clean-up-api-security-configuration-internal-api-key-sets + readOnly: true + - name: data-clean-up-api-secrets + mountPath: /vault/secrets/data-clean-up-database-connection.json + subPath: data-clean-up-database-connection + readOnly: true + - name: data-clean-up-api-secrets + mountPath: /vault/secrets/data-clean-up-seq-api-key.json + subPath: data-clean-up-seq-api-key + readOnly: true + - name: data-clean-up-api-secrets + mountPath: /vault/secrets/data-clean-up-connection-configuration-queue-user-name.json + subPath: data-clean-up-connection-configuration-queue-user-name + readOnly: true + - name: data-clean-up-api-secrets + mountPath: /vault/secrets/data-clean-up-connection-configuration-queue-password.json + subPath: data-clean-up-connection-configuration-queue-password + readOnly: true + - name: data-clean-up-api-secrets + mountPath: /vault/secrets/data-clean-up-saving-missing-requirements-defaults-funds-to-account-defaults-gl-account-number.json + subPath: data-clean-up-saving-missing-requirements-defaults-funds-to-account-defaults-gl-account-number + readOnly: true + - name: data-clean-up-api-secrets + mountPath: /vault/secrets/data-clean-up-indirect-savings-requirements-defaults-funds-to-account-defaults-indirect-gl-account-number.json + subPath: data-clean-up-indirect-savings-requirements-defaults-funds-to-account-defaults-indirect-gl-account-number + readOnly: true + - name: data-clean-up-api-secrets + mountPath: /vault/secrets/data-clean-up-indirect-savings-requirements-defaults-funds-to-account-defaults-funds-defaults-fund-amount-indirect-fund-amount.json + subPath: data-clean-up-indirect-savings-requirements-defaults-funds-to-account-defaults-funds-defaults-fund-amount-indirect-fund-amount + readOnly: true + volumes: + - name: data-clean-up-api-secrets + csi: + driver: secrets-store.csi.k8s.io + readOnly: true + volumeAttributes: + secretProviderClass: data-clean-up-api-csi-key-vault-secrets-provider + - name: volume-lcu-internal-cert + configMap: + name: configmap-lcu-internal-cert + - name: volume-appsettings + configMap: + name: datacleanupapi-configmap diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/base/Service.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/base/Service.yaml new file mode 100644 index 0000000..94fee83 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/base/Service.yaml @@ -0,0 +1,11 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: data-clean-up-api +spec: + selector: + app: data-clean-up-api + ports: + - port: 8080 + targetPort: 8080 diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/base/kustomization.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/base/kustomization.yaml new file mode 100644 index 0000000..9bde637 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/base/kustomization.yaml @@ -0,0 +1,5 @@ +resources: + - Deployment.yaml + - Service.yaml + - virtual-service.yaml + - secrets-provider-class.yaml diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/base/secrets-provider-class.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/base/secrets-provider-class.yaml new file mode 100644 index 0000000..97a33ab --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/base/secrets-provider-class.yaml @@ -0,0 +1,45 @@ +--- +apiVersion: secrets-store.csi.x-k8s.io/v1 +kind: SecretProviderClass +metadata: + name: data-clean-up-api-csi-key-vault-secrets-provider +spec: + provider: azure + parameters: + usePodIdentity: "false" + useVMManagedIdentity: "true" + tenantId: 63cd1554-2783-4a86-ae50-b9e6c21c9499 + objects: | + array: + - | + objectName: data-clean-up-seq-api-key + objectType: secret + objectVersion: "" + - | + objectName: data-clean-up-database-connection + objectType: secret + objectVersion: "" + - | + objectName: data-clean-up-api-security-configuration-internal-api-key-sets + objectType: secret + objectVersion: "" + - | + objectName: data-clean-up-connection-configuration-queue-user-name + objectType: secret + objectVersion: "" + - | + objectName: data-clean-up-connection-configuration-queue-password + objectType: secret + objectVersion: "" + - | + objectName: data-clean-up-saving-missing-requirements-defaults-funds-to-account-defaults-gl-account-number + objectType: secret + objectVersion: "" + - | + objectName: data-clean-up-indirect-savings-requirements-defaults-funds-to-account-defaults-indirect-gl-account-number + objectType: secret + objectVersion: "" + - | + objectName: data-clean-up-indirect-savings-requirements-defaults-funds-to-account-defaults-funds-defaults-fund-amount-indirect-fund-amount + objectType: secret + objectVersion: "" diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/base/virtual-service.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/base/virtual-service.yaml new file mode 100644 index 0000000..710059a --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/base/virtual-service.yaml @@ -0,0 +1,18 @@ +--- +apiVersion: networking.istio.io/v1beta1 +kind: VirtualService +metadata: + name: data-clean-up-api +spec: + gateways: + - istio-system/ingress-gateway + http: + - name: data-clean-up-api + match: + - uri: + prefix: / + route: + - destination: + host: data-clean-up-api + port: + number: 8080 diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/common/kustomization.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/common/kustomization.yaml new file mode 100644 index 0000000..31234e5 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/common/kustomization.yaml @@ -0,0 +1,8 @@ +resources: + - ../../../base +patchesStrategicMerge: + - set_appsettings_deployment.yaml + - set_secrets_provider_class.yaml +images: +- name: data-clean-up-api + newName: landmarkcu/lcu.api.internal.datacleanup-datacleanup diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/common/set_appsettings_deployment.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/common/set_appsettings_deployment.yaml new file mode 100644 index 0000000..4ec1c86 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/common/set_appsettings_deployment.yaml @@ -0,0 +1,12 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: data-clean-up-api +spec: + template: + spec: + containers: + - name: data-clean-up-api + env: + - name: ASPNETCORE_ENVIRONMENT + value: "Development" diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/common/set_secrets_provider_class.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/common/set_secrets_provider_class.yaml new file mode 100644 index 0000000..4c143e5 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/common/set_secrets_provider_class.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: secrets-store.csi.x-k8s.io/v1 +kind: SecretProviderClass +metadata: + name: data-clean-up-api-csi-key-vault-secrets-provider +spec: + parameters: + userAssignedIdentityID: 3286ed9a-f85c-4c50-b742-dbd3c1c3fe1f + keyvaultName: kv-lz-apps-qa-uscz diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/kustomization.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/kustomization.yaml new file mode 100644 index 0000000..25a65b6 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - normal diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/normal/configmap.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/normal/configmap.yaml new file mode 100644 index 0000000..90c6c14 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/normal/configmap.yaml @@ -0,0 +1,38 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: datacleanupapi-configmap +data: + primary.json: | + { + "Primary": { + "seqUrl": "https://qa-seq.lcu-internal.com" + }, + "CoreApiWrapperConfiguration": { + "CoreApiTimeout": 120, + "RetryGetAccessChannelPersonIncludes": 3, + "CoreApiWrapperUrl": "https://qa-api.lcu-internal.com/core-api-wrapper" + }, + "FileOperationsConfiguration": { + "FileOperationsUrl": "https://qa-fileoperationsapi.lcu-internal.com" + }, + "ConnectionConfiguration":{ + "HostUrl": "qa-rabbitmq.lcu-internal.com" + }, + "DataCleanUpDefaults": { + "DigitalBankingBranchCode": "1210", + "MemberCheckHoldsUserFieldCode": "MBRH", + "MemberCheckHoldsDays": 29, + "BatchAddFunds": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchAddFunds\\NeedToFund.csv", + "BatchAddFundsSummarySourcePath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchAddFunds\\", + "BatchSavingsSourcePath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchSavings\\MissingBatchSavings.csv", + "BatchSavingsSummarySourcePath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchSavings\\", + "AccountNicknameSourcePath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\AccountNickNames\\AccountNicknames.csv", + "LtvExcludedMinorAccountTypes": ["DL01","DL02","DL03","DL04","DL05","DL06","DL07","DL08","DL09","DL10","DL11","DL12","DL13","DL14","DL15","DL16"], + "PmiCancelSourcePath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\PMICancel\\PMI Cancel.csv", + "PmiCancelSummaryPath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\PMICancel\\" + }, + "NotificationsApiConfiguration": { + "EmailEndpoint": "https://qa-notificationsapi.lcu-internal.com/api/Email" + } + } diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/normal/kustomization.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/normal/kustomization.yaml new file mode 100644 index 0000000..6dd0c3b --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/normal/kustomization.yaml @@ -0,0 +1,5 @@ +resources: + - configmap.yaml + - ../common +patchesStrategicMerge: + - set_virtual_service.yaml diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/normal/set_virtual_service.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/normal/set_virtual_service.yaml new file mode 100644 index 0000000..075bbac --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/local/normal/set_virtual_service.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: networking.istio.io/v1beta1 +kind: VirtualService +metadata: + name: data-clean-up-api +spec: + hosts: + - qa-data-clean-up-api.apps.azure.lcu-internal.com diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/common/kustomization.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/common/kustomization.yaml new file mode 100644 index 0000000..31234e5 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/common/kustomization.yaml @@ -0,0 +1,8 @@ +resources: + - ../../../base +patchesStrategicMerge: + - set_appsettings_deployment.yaml + - set_secrets_provider_class.yaml +images: +- name: data-clean-up-api + newName: landmarkcu/lcu.api.internal.datacleanup-datacleanup diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/common/set_appsettings_deployment.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/common/set_appsettings_deployment.yaml new file mode 100644 index 0000000..a7924a4 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/common/set_appsettings_deployment.yaml @@ -0,0 +1,12 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: data-clean-up-api +spec: + template: + spec: + containers: + - name: data-clean-up-api + env: + - name: ASPNETCORE_ENVIRONMENT + value: "Production" diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/common/set_secrets_provider_class.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/common/set_secrets_provider_class.yaml new file mode 100644 index 0000000..5a106f8 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/common/set_secrets_provider_class.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: secrets-store.csi.x-k8s.io/v1 +kind: SecretProviderClass +metadata: + name: data-clean-up-api-csi-key-vault-secrets-provider +spec: + parameters: + userAssignedIdentityID: 9eaefc49-e5d3-48d4-a2b9-b42cf2d8ca03 + keyvaultName: kv-lz-apps-prod-uscz diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/kustomization.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/kustomization.yaml new file mode 100644 index 0000000..25a65b6 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - normal diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/normal/configmap.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/normal/configmap.yaml new file mode 100644 index 0000000..0b8a319 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/normal/configmap.yaml @@ -0,0 +1,42 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: datacleanupapi-configmap +data: + primary.json: | + { + "Primary": { + "seqUrl": "https://seq.lcu-internal.com", + "FeatureFlags": { + "RunDataCleanUpConsumer": true + } + }, + "CoreApiWrapperConfiguration": { + "CoreApiTimeout": 120, + "RetryGetAccessChannelPersonIncludes": 3, + "CoreApiWrapperUrl": "https://prd-core-api-wrapper-api.apps.azure.lcu-internal.com" + }, + "FileOperationsConfiguration": { + "FileOperationsUrl": "https://fileoperationsapi.lcu-internal.com" + }, + "ConnectionConfiguration":{ + "HostUrl": "rabbitmq.lcu-internal.com" + }, + "DataCleanUpDefaults": { + "DigitalBankingBranchCode": "1210", + "MemberCheckHoldsUserFieldCode": "MBRH", + "MemberCheckHoldsDays": 29, + "BatchAddFunds": "\\\\zeus\\DataIntegrations\\DataCleanUp\\BatchAddFunds\\NeedToFund.csv", + "BatchAddFundsSummarySourcePath": "\\\\zeus\\DataIntegrations\\DataCleanUp\\BatchAddFunds\\", + "BatchSavingsSourcePath": "\\\\zeus\\DataIntegrations\\DataCleanUp\\BatchSavings\\MissingBatchSavings.csv", + "BatchSavingsSummarySourcePath": "\\\\zeus\\DataIntegrations\\DataCleanUp\\BatchSavings\\", + "AccountNicknameSourcePath": "\\\\zeus\\DataIntegrations\\DataCleanUp\\AccountNickNames\\AccountNicknames.csv", + "LtvExcludedMinorAccountTypes": ["DL01","DL02","DL03","DL04","DL05","DL06","DL07","DL08","DL09","DL10","DL11","DL12","DL13","DL14","DL15","DL16"], + "PmiCancelSourcePath": "\\\\zeus\\DataIntegrations\\DataCleanUp\\PMICancel\\PMI Cancel.csv", + "PmiCancelSummaryPath": "\\\\zeus\\DataIntegrations\\DataCleanUp\\PMICancel\\", + "AccountUserField": "/api/core/AccountUserField" + }, + "NotificationsApiConfiguration": { + "EmailEndpoint": "https://prd-notifications-api.apps.azure.lcu-internal.com/api/Email" + } + } diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/normal/kustomization.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/normal/kustomization.yaml new file mode 100644 index 0000000..6dd0c3b --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/normal/kustomization.yaml @@ -0,0 +1,5 @@ +resources: + - configmap.yaml + - ../common +patchesStrategicMerge: + - set_virtual_service.yaml diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/normal/set_virtual_service.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/normal/set_virtual_service.yaml new file mode 100644 index 0000000..bbb392d --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/prd/normal/set_virtual_service.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: networking.istio.io/v1beta1 +kind: VirtualService +metadata: + name: data-clean-up-api +spec: + hosts: + - prd-data-clean-up-api.apps.azure.lcu-internal.com diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/common/kustomization.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/common/kustomization.yaml new file mode 100644 index 0000000..31234e5 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/common/kustomization.yaml @@ -0,0 +1,8 @@ +resources: + - ../../../base +patchesStrategicMerge: + - set_appsettings_deployment.yaml + - set_secrets_provider_class.yaml +images: +- name: data-clean-up-api + newName: landmarkcu/lcu.api.internal.datacleanup-datacleanup diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/common/set_appsettings_deployment.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/common/set_appsettings_deployment.yaml new file mode 100644 index 0000000..4ec1c86 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/common/set_appsettings_deployment.yaml @@ -0,0 +1,12 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: data-clean-up-api +spec: + template: + spec: + containers: + - name: data-clean-up-api + env: + - name: ASPNETCORE_ENVIRONMENT + value: "Development" diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/common/set_secrets_provider_class.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/common/set_secrets_provider_class.yaml new file mode 100644 index 0000000..4c143e5 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/common/set_secrets_provider_class.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: secrets-store.csi.x-k8s.io/v1 +kind: SecretProviderClass +metadata: + name: data-clean-up-api-csi-key-vault-secrets-provider +spec: + parameters: + userAssignedIdentityID: 3286ed9a-f85c-4c50-b742-dbd3c1c3fe1f + keyvaultName: kv-lz-apps-qa-uscz diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/kustomization.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/kustomization.yaml new file mode 100644 index 0000000..25a65b6 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - normal diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/normal/configmap.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/normal/configmap.yaml new file mode 100644 index 0000000..d0a5eac --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/normal/configmap.yaml @@ -0,0 +1,41 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: datacleanupapi-configmap +data: + primary.json: | + { + "Primary": { + "seqUrl": "https://qa-seq.lcu-internal.com", + "FeatureFlags": { + "RunDataCleanUpConsumer": true + } + }, + "CoreApiWrapperConfiguration": { + "CoreApiTimeout": 120, + "RetryGetAccessChannelPersonIncludes": 3, + "CoreApiWrapperUrl": "https://qa-core-api-wrapper-api.apps.azure.lcu-internal.com" + }, + "FileOperationsConfiguration": { + "FileOperationsUrl": "https://qa-fileoperationsapi.lcu-internal.com" + }, + "ConnectionConfiguration":{ + "HostUrl": "qa-rabbitmq.lcu-internal.com" + }, + "DataCleanUpDefaults": { + "DigitalBankingBranchCode": "1210", + "MemberCheckHoldsUserFieldCode": "MBRH", + "MemberCheckHoldsDays": 29, + "BatchAddFunds": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchAddFunds\\NeedToFund.csv", + "BatchAddFundsSummarySourcePath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchAddFunds\\", + "BatchSavingsSourcePath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchSavings\\MissingBatchSavings.csv", + "BatchSavingsSummarySourcePath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\BatchSavings\\", + "AccountNicknameSourcePath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\AccountNickNames\\AccountNicknames.csv", + "LtvExcludedMinorAccountTypes": ["DL01","DL02","DL03","DL04","DL05","DL06","DL07","DL08","DL09","DL10","DL11","DL12","DL13","DL14","DL15","DL16"], + "PmiCancelSourcePath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\PMICancel\\PMI Cancel.csv", + "PmiCancelSummaryPath": "\\\\zeus\\DataIntegrationsQA\\DataCleanUp\\PMICancel\\" + }, + "NotificationsApiConfiguration": { + "EmailEndpoint": "https://qa-notifications-api.apps.azure.lcu-internal.com/api/Email" + } + } diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/normal/kustomization.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/normal/kustomization.yaml new file mode 100644 index 0000000..6dd0c3b --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/normal/kustomization.yaml @@ -0,0 +1,5 @@ +resources: + - configmap.yaml + - ../common +patchesStrategicMerge: + - set_virtual_service.yaml diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/normal/set_virtual_service.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/normal/set_virtual_service.yaml new file mode 100644 index 0000000..075bbac --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/qa/normal/set_virtual_service.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: networking.istio.io/v1beta1 +kind: VirtualService +metadata: + name: data-clean-up-api +spec: + hosts: + - qa-data-clean-up-api.apps.azure.lcu-internal.com diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/common/kustomization.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/common/kustomization.yaml new file mode 100644 index 0000000..31234e5 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/common/kustomization.yaml @@ -0,0 +1,8 @@ +resources: + - ../../../base +patchesStrategicMerge: + - set_appsettings_deployment.yaml + - set_secrets_provider_class.yaml +images: +- name: data-clean-up-api + newName: landmarkcu/lcu.api.internal.datacleanup-datacleanup diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/common/set_appsettings_deployment.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/common/set_appsettings_deployment.yaml new file mode 100644 index 0000000..6013184 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/common/set_appsettings_deployment.yaml @@ -0,0 +1,12 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: data-clean-up-api +spec: + template: + spec: + containers: + - name: data-clean-up-api + env: + - name: ASPNETCORE_ENVIRONMENT + value: "Staging" diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/common/set_secrets_provider_class.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/common/set_secrets_provider_class.yaml new file mode 100644 index 0000000..ca7ab12 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/common/set_secrets_provider_class.yaml @@ -0,0 +1,9 @@ +--- +apiVersion: secrets-store.csi.x-k8s.io/v1 +kind: SecretProviderClass +metadata: + name: data-clean-up-api-csi-key-vault-secrets-provider +spec: + parameters: + userAssignedIdentityID: 64ba01ed-1ecc-4c9b-b56e-8d618f2b81ce + keyvaultName: kv-lz-apps-uat-uscz diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/kustomization.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/kustomization.yaml new file mode 100644 index 0000000..25a65b6 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/kustomization.yaml @@ -0,0 +1,2 @@ +resources: + - normal diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/normal/configmap.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/normal/configmap.yaml new file mode 100644 index 0000000..76c6c5b --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/normal/configmap.yaml @@ -0,0 +1,41 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: datacleanupapi-configmap +data: + primary.json: | + { + "Primary": { + "seqUrl": "https://uat-seq.lcu-internal.com", + "FeatureFlags": { + "RunDataCleanUpConsumer": true + } + }, + "CoreApiWrapperConfiguration": { + "CoreApiTimeout": 120, + "RetryGetAccessChannelPersonIncludes": 3, + "CoreApiWrapperUrl": "https://uat-core-api-wrapper-api.apps.azure.lcu-internal.com" + }, + "FileOperationsConfiguration": { + "FileOperationsUrl": "https://uat-fileoperationsapi.lcu-internal.com" + }, + "ConnectionConfiguration":{ + "HostUrl": "uat-rabbitmq.lcu-internal.com" + }, + "DataCleanUpDefaults": { + "DigitalBankingBranchCode": "1210", + "MemberCheckHoldsUserFieldCode": "MBRH", + "MemberCheckHoldsDays": 29, + "BatchAddFunds": "\\\\zeus\\DataIntegrationsUAT\\DataCleanUp\\BatchAddFunds\\NeedToFund.csv", + "BatchAddFundsSummarySourcePath": "\\\\zeus\\DataIntegrationsUAT\\DataCleanUp\\BatchAddFunds\\", + "BatchSavingsSourcePath": "\\\\zeus\\DataIntegrationsUAT\\DataCleanUp\\BatchSavings\\MissingBatchSavings.csv", + "BatchSavingsSummarySourcePath": "\\\\zeus\\DataIntegrationsUAT\\DataCleanUp\\BatchSavings\\", + "AccountNicknameSourcePath": "\\\\zeus\\DataIntegrationsUAT\\DataCleanUp\\AccountNickNames\\AccountNicknames.csv", + "LtvExcludedMinorAccountTypes": ["DL01","DL02","DL03","DL04","DL05","DL06","DL07","DL08","DL09","DL10","DL11","DL12","DL13","DL14","DL15","DL16"], + "PmiCancelSourcePath": "\\\\zeus\\DataIntegrationsUAT\\DataCleanUp\\PMICancel\\PMI Cancel.csv", + "PmiCancelSummaryPath": "\\\\zeus\\DataIntegrationsUAT\\DataCleanUp\\PMICancel\\" + }, + "NotificationsApiConfiguration": { + "EmailEndpoint": "https://uat-notifications-api.apps.azure.lcu-internal.com/api/Email" + } + } diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/normal/kustomization.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/normal/kustomization.yaml new file mode 100644 index 0000000..6dd0c3b --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/normal/kustomization.yaml @@ -0,0 +1,5 @@ +resources: + - configmap.yaml + - ../common +patchesStrategicMerge: + - set_virtual_service.yaml diff --git a/LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/normal/set_virtual_service.yaml b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/normal/set_virtual_service.yaml new file mode 100644 index 0000000..2a23016 --- /dev/null +++ b/LCU.Api.Internal.DataCleanUp/kustomize/overlays/uat/normal/set_virtual_service.yaml @@ -0,0 +1,8 @@ +--- +apiVersion: networking.istio.io/v1beta1 +kind: VirtualService +metadata: + name: data-clean-up-api +spec: + hosts: + - uat-data-clean-up-api.apps.azure.lcu-internal.com