From b690921fd733b6eb4faeb6e6637d469a9fe38e4c Mon Sep 17 00:00:00 2001 From: Zeeshaun Date: Wed, 25 Mar 2026 14:50:13 -0500 Subject: [PATCH] Adding --- LCU.API.Internal.DocumentIngestor/.gitignore | 363 ++++++ LCU.API.Internal.DocumentIngestor/Dockerfile | 41 + .../LCU.API.Internal.DocumentIngestor.sln | 71 ++ .../Configurations/ApiConfiguration.cs | 25 + .../CoreApiWrapperConfiguration.cs | 58 + .../DigitalBankingConfiguration.cs | 19 + .../DispatcherJobCreationConfiguration.cs | 8 + .../DocumentCodeDetailCacheConfiguration.cs | 8 + .../DocumentTypeRetrieverConfiguration.cs | 26 + .../DocumentTypeUploaderConfiguration.cs | 38 + .../Configurations/FeatureFlags.cs | 19 + .../FileOperationsApiConfiguration.cs | 64 ++ .../MemberPreferencesApiConfiguration.cs | 25 + .../NotificationApiConfiguration.cs | 12 + .../Configurations/Notifications.cs | 6 + .../ReceiveEndpointConfigurations.cs | 19 + .../SqlConnectionConfiguration.cs | 8 + .../Consumers/BatchIngestionConsumer.cs | 44 + ...tchUpdateMemberNotificationDataConsumer.cs | 53 + .../GatherMemberNotificationInfoConsumer.cs | 45 + .../IngestionFolderCleanUpConsumer.cs | 43 + .../Consumers/IngestorCompletionConsumer.cs | 52 + .../Consumers/IngestorIndexConsumer.cs | 44 + .../Consumers/IngestorProcessingConsumer.cs | 50 + .../MemberDocumentNotifierConsumer.cs | 44 + .../MemberNotificationCompletionConsumer.cs | 44 + .../PdfPartitionerCompletionConsumer.cs | 44 + .../Consumers/PdfPartitionerConsumer.cs | 44 + .../ProcessStatusTypeEmailConsumer.cs | 35 + .../Consumers/UploadCompletionConsumer.cs | 61 + .../Controllers/BatchIngestionController.cs | 40 + .../Controllers/DocumentIngestorController.cs | 41 + .../DocumentProcessingInfoController.cs | 292 +++++ .../DocumentReprocessingController.cs | 111 ++ ...DocumentTypeArchiveDeleteInfoController.cs | 159 +++ .../IngestionFolderCleanUpController.cs | 48 + .../Controllers/IngestorRunInfoController.cs | 118 ++ .../MemberDocumentNotifierController.cs | 40 + .../MemberNotificationInfoController.cs | 330 ++++++ .../Controllers/OsgPreprocessorController.cs | 44 + .../Controllers/PdfPartitionerController.cs | 40 + .../PdfPartitionerLogController.cs | 150 +++ .../PdfPartitionerRunInfoController.cs | 118 ++ .../Controllers/ProcessingLogController.cs | 185 +++ .../QueueProcessStatusTypeEmailController.cs | 51 + .../Controllers/StatusController.cs | 37 + .../UploadCompletionReprocessingController.cs | 82 ++ .../DataAccess/CoreApiWrapperDao.cs | 95 ++ .../DataAccess/DocumentTypeRetrieverDao.cs | 122 ++ .../DataAccess/DocumentTypeUploaderApiDao.cs | 38 + .../DataAccess/FileOperationsApiDao.cs | 118 ++ .../DataAccess/ICoreApiWrapperDao.cs | 26 + .../DataAccess/IDocumentTypeRetrieverDao.cs | 14 + .../DataAccess/IDocumentTypeUploaderApiDao.cs | 11 + .../DataAccess/IFileOperationsApiDao.cs | 21 + .../DataAccess/IMemberPreferencesApiDao.cs | 10 + .../DataAccess/INotificationApiDao.cs | 9 + .../DataAccess/MemberPreferencesApiDao.cs | 64 ++ .../DataAccess/NotificationApiDao.cs | 22 + .../CloudRoleNameTelemetryInitializer.cs | 12 + .../LCU.API.Internal.DocumentIngestor.csproj | 62 + .../MemberOptInAgreementInformation.cs | 8 + .../MemberOptInInformation.cs | 7 + .../MemberOptInSettings.cs | 28 + .../Program.cs | 650 +++++++++++ .../Properties/launchSettings.json | 31 + .../Security/GroupMembershipRequirement.cs | 13 + .../GroupMembershipRequirementHandler.cs | 20 + .../Security/ITRolePolicy.cs | 11 + .../Security/SecurityConfiguration.cs | 6 + .../SetDocumentNotificationStatusPolicy.cs | 11 + .../AccountOwnerDeterminingService.cs | 189 ++++ .../BaseOwnerDeterminingService.cs | 42 + .../IAccountOwnerDeterminingService.cs | 18 + .../IPrimaryOwnerDeterminingService.cs | 28 + .../PrimaryOwnerDeterminingService.cs | 418 +++++++ .../Services/DocumentProcessingInfoService.cs | 638 +++++++++++ .../DocumentProcessingService.cs | 11 + .../FosDnaDocumentProcessingService.cs | 257 +++++ .../FosLoanStatementProcessingService.cs | 128 +++ .../FosTaxStatementProcessingService.cs | 161 +++ .../IDocumentProcessingService.cs | 9 + .../OsgDnaNoticeSplitProcessingService.cs | 126 +++ .../OsgDnaNoticesProcessingService.cs | 187 +++ .../OsgHistoricalDocumentProcessingService.cs | 134 +++ .../OsgTaxStatementProcessingService.cs | 173 +++ .../OsgTemenosNoticeProcessingService.cs | 131 +++ ...OsgVehicleTaxStatementProcessingService.cs | 126 +++ .../OsgWeilandStatementProcessingService.cs | 137 +++ .../XdiActionNoticesProcessingService.cs | 105 ++ .../XdiDnaNoticeDocumentProcessingService.cs | 131 +++ .../Services/DocumentReprocessingService.cs | 132 +++ .../DocumentTypeArchiveDeleteInfoService.cs | 134 +++ .../IDocumentProcessingInfoService.cs | 69 ++ .../Services/IDocumentReprocessingService.cs | 10 + .../IDocumentTypeArchiveDeleteInfoService.cs | 12 + .../Services/IIngestorRunInfoService.cs | 12 + .../IMemberNotificationInfoService.cs | 22 + .../Services/IOsgPreprocessorInfoService.cs | 17 + .../Services/IOwnerOverrideInfoService.cs | 12 + .../Services/IPdfPartitionerLogService.cs | 12 + .../Services/IPdfPartitionerRunInfoService.cs | 11 + .../Services/IProcessingLogService.cs | 13 + .../IUploadCompletionReprocessingService.cs | 7 + .../FosDnaDocumentIndexService.cs | 83 ++ .../FosLoanStatementIndexService.cs | 98 ++ .../FosTaxStatementIndexService.cs | 82 ++ .../IIndexParserService.cs | 10 + .../IPdfIndexParserService.cs | 9 + .../IndexParserServices/IndexParserService.cs | 11 + .../OsgDnaNoticeSplitIndexService.cs | 82 ++ .../OsgDnaNoticesIndexService.cs | 94 ++ .../OsgHistoricalDocumentIndexService.cs | 94 ++ .../OsgTaxStatementIndexService.cs | 82 ++ .../OsgTemenosNoticeIndexService.cs | 80 ++ .../OsgVehicleTaxStatementIndexService.cs | 82 ++ .../OsgWeilandStatementIndexService.cs | 79 ++ .../XdiActionNoticeDocumentIndexService.cs | 81 ++ .../XdiDnaNoticeDocumentIndexService.cs | 80 ++ .../BatchIngestionService.cs | 199 ++++ ...atchUpdateMemberNotificationDataService.cs | 126 +++ .../CompletionService.cs | 159 +++ .../DocumentProcessorService.cs | 148 +++ .../GatherMemberNotificationInfoService.cs | 57 + .../IBatchIngestionService.cs | 9 + ...atchUpdateMemberNotificationDataService.cs | 8 + .../ICompletionService.cs | 7 + .../IDocumentProcessorService.cs | 8 + .../IGatherMemberNotificationInfoService.cs | 8 + .../IIndexService.cs | 8 + .../IIngestionFolderCleanUpService.cs | 8 + .../IMemberDocumentNotifierService.cs | 7 + .../IMemberNotificationCompletionService.cs | 7 + .../IOsgPreprocessorService.cs | 7 + .../IPdfPartitionerCompletionService.cs | 8 + .../IPdfPartitionerService.cs | 7 + .../IProcessStatusTypeEmailService.cs | 11 + .../IUploadCompletionService.cs | 7 + .../IndexService.cs | 177 +++ .../IngestionFolderCleanUpService.cs | 329 ++++++ .../MemberDocumentNotifierService.cs | 379 +++++++ .../MemberNotificationCompletionService.cs | 162 +++ .../OsgPreprocessorService.cs | 445 ++++++++ .../PdfPartitionerCompletionService.cs | 61 + .../PdfPartitionerService.cs | 242 ++++ .../ProcessStatusTypeEmailService.cs | 103 ++ .../UploadCompletionService.cs | 259 +++++ .../Services/IngestorRunInfoService.cs | 132 +++ ...countNotificationInfoDeterminingService.cs | 78 ++ ...countNotificationInfoDeterminingService.cs | 7 + ...emberNotificationInfoDeterminingService.cs | 10 + ...imaryNotificationInfoDeterminingService.cs | 9 + ...emberNotificationInfoDeterminingService.cs | 109 ++ ...imaryNotificationInfoDeterminingService.cs | 109 ++ .../Services/MemberNotificationInfoService.cs | 284 +++++ .../MicroApiServices/CoreApiWrapperService.cs | 182 +++ .../DocumentTypeRetrieverService.cs | 156 +++ .../DocumentTypeUploaderApiService.cs | 171 +++ .../FileOperationsApiService.cs | 321 ++++++ .../ICoreApiWrapperService.cs | 25 + .../IDocumentTypeRetrieverService.cs | 16 + .../IDocumentTypeUploaderApiService.cs | 19 + .../IFileOperationsApiService.cs | 28 + .../IMemberPreferencesApiService.cs | 9 + .../INotificationApiService.cs | 10 + .../MemberPreferencesApiService.cs | 65 ++ .../NotificationApiService.cs | 29 + .../Services/OsgPreprocessorInfoService.cs | 230 ++++ .../Services/OwnerOverrideInfoService.cs | 97 ++ .../FosLoanStatementPdfService.cs | 135 +++ .../PdfParserServices/IPdfParserService.cs | 11 + .../OsgDnaNoticesPdfService.cs | 136 +++ .../OsgHistoricalDocumentPdfService.cs | 136 +++ .../PdfParserServices/PdfParserService.cs | 11 + .../Services/PdfPartitionerLogService.cs | 118 ++ .../Services/PdfPartitionerRunInfoService.cs | 140 +++ .../Services/ProcessingLogService.cs | 147 +++ .../IQueueBatchIngestionService.cs | 7 + ...atchUpdateMemberNotificationDataService.cs | 8 + .../QueueServices/IQueueCompletionService.cs | 7 + .../IQueueDocumentIngestorService.cs | 7 + .../IQueueDocumentProcessingService.cs | 7 + ...ueueGatherMemberNotificationInfoService.cs | 8 + .../IQueueIngestionFolderCleanUpService.cs | 7 + .../IQueueMemberDocumentNotifierService.cs | 7 + ...ueueMemberNotificationCompletionService.cs | 7 + .../IQueuePdfPartitionerCompletionService.cs | 7 + .../IQueuePdfPartitionerService.cs | 7 + .../IQueueProcessStatusTypeEmailService.cs | 8 + .../Services/QueueServices/IResponseQueue.cs | 8 + .../QueueBatchIngestionService.cs | 35 + ...atchUpdateMemberNotificationDataService.cs | 34 + .../QueueServices/QueueCompletionService.cs | 56 + .../QueueDocumentIngestorService.cs | 35 + .../QueueDocumentProcessingService.cs | 35 + ...ueueGatherMemberNotificationInfoService.cs | 35 + .../QueueIngestionFolderCleanUpService.cs | 34 + .../QueueMemberDocumentNotifierService.cs | 35 + ...ueueMemberNotificationCompletionService.cs | 44 + .../QueuePdfPartitionerCompletionService.cs | 43 + .../QueuePdfPartitionerService.cs | 35 + .../QueueProcessStatusTypeEmailService.cs | 35 + .../Services/QueueServices/ResponseQueue.cs | 10 + .../UploadCompletionReprocessingService.cs | 166 +++ .../NotificationEmailRowTemplate.html | 3 + .../Templates/NotificationEmailTemplate.html | 107 ++ .../Utilities/HttpUtilities.cs | 307 +++++ .../Utilities/SpecialCharacters.cs | 33 + .../Utilities/ToDetailStringExtension.cs | 32 + .../appsettings.json | 392 +++++++ .../Exceptions/ArchiveException.cs | 15 + .../FilterNullsAndZerosOrDefaultExtension.cs | 19 + ...umentProcessingInfoCreatedDateQueryable.cs | 32 + ...tProcessingInfoDocBusinessNameQueryable.cs | 20 + .../DocumentProcessingInfoDocTypeQueryable.cs | 23 + ...mentProcessingInfoIndexJsonEqualsFilter.cs | 23 + ...mentProcessingInfoIndexJsonLikeOrFilter.cs | 37 + ...rocessingInfoIngestorRunInfoIdQueryable.cs | 20 + ...ocessingInfoNotificationStatusQueryable.cs | 18 + ...cumentProcessingInfoStatusTypeQueryable.cs | 28 + .../Queryables/IncludeAllQueryable.cs | 16 + .../Queryables/IncludeFiltersQueryable.cs | 21 + .../Queryables/SortableFieldsQueryable.cs | 29 + .../Extensions/TimeZoneDateTime.cs | 14 + ...CU.API.Internal.DocumentIngestorLib.csproj | 22 + .../Persistence/AppDbContext.cs | 45 + .../Repositories/BaseRepository.cs | 17 + .../DocumentProcessingInfoRepository.cs | 134 +++ ...DocumentTypeArchiveDeleteInfoRepository.cs | 40 + .../IDocumentProcessingInfoRepository.cs | 29 + ...DocumentTypeArchiveDeleteInfoRepository.cs | 15 + .../IIngestorRunInfoRepository.cs | 17 + .../IMemberNotificationInfoRepository.cs | 25 + .../IOsgPreprocessorInfoRepository.cs | 20 + .../IOwnerOverrideInfoRepository.cs | 16 + .../IPdfPartitionerLogRepository.cs | 17 + .../IPdfPartitionerRunInfoRepository.cs | 14 + .../Repositories/IProcessingLogRepository.cs | 17 + .../Repositories/IUnitOfWork.cs | 10 + .../Repositories/IngestorRunInfoRepository.cs | 47 + .../MemberNotificationInfoRepository.cs | 109 ++ .../OsgPreprocessorInfoRepository.cs | 73 ++ .../OwnerOverrideInfoRepository.cs | 48 + .../PdfPartitionerLogRepository.cs | 49 + .../PdfPartitionerRunInfoRepository.cs | 34 + .../Repositories/ProcessingLogRepository.cs | 53 + .../Repositories/UnitOfWork.cs | 25 + ...lterNullsAndZerosOrDefaultExtensionTest.cs | 25 + ...singInfoNotificationStatusQueryableTest.cs | 131 +++ ...I.Internal.DocumentIngestorLibTests.csproj | 35 + .../DocumentProcessingInfoRepositoryTest.cs | 821 ++++++++++++++ .../MemberNotificationInfoRepositoryTest.cs | 133 +++ .../ProcessingLogRepositoryTest.cs | 120 ++ .../SqlServerDbContextFactory.cs | 138 +++ .../SqliteAppDbContextFactory.cs | 35 + .../Usings.cs | 1 + .../DocumentProcessingInfo.sql | 25 + .../DocumentTypeArchiveDeleteInfo.sql | 8 + .../IngestorRunInfo.sql | 12 + ...I.Internal.DocumentIngestorSql.refactorlog | 178 +++ ...U.API.Internal.DocumentIngestorSql.sqlproj | 74 ++ .../MemberNotificationInfo.sql | 15 + .../OsgPreprocessorInfo.sql | 15 + .../OwnerOverrideInfo.sql | 9 + .../PdfPartitionerLog.sql | 8 + .../PdfPartitionerRunInfo.sql | 11 + .../ProcessingLog.sql | 9 + .../BatchIngestionControllerTest.cs | 86 ++ .../DocumentIngestorControllerTest.cs | 75 ++ .../DocumentProcessingInfoControllerTest.cs | 573 ++++++++++ .../DocumentReprocessingControllerTest.cs | 226 ++++ ...mentTypeArchiveDeleteInfoControllerTest.cs | 323 ++++++ .../IngestorRunInfoControllerTest.cs | 221 ++++ .../MemberDocumentNotifierControllerTest.cs | 79 ++ .../MemberNotificationInfoControllerTest.cs | 633 +++++++++++ .../OsgPreprocessorControllerTest.cs | 91 ++ .../PdfPartitionerControllerTest.cs | 96 ++ .../PdfPartitionerLogControllerTest.cs | 306 +++++ .../PdfPartitionerRunInfoControllerTest.cs | 221 ++++ .../ProcessingLogControllerTest.cs | 361 ++++++ ...oadCompletionReprocessingControllerTest.cs | 169 +++ ....API.Internal.DocumentIngestorTests.csproj | 52 + .../Models/ProcessResultTest.cs | 57 + .../Validations/MetaDataValidationTests.cs | 131 +++ .../GroupMembershipRequirementHandlerTest.cs | 103 ++ .../AccountOwnerDeterminingServiceTest.cs | 613 ++++++++++ .../PrimaryOwnerDeterminingServiceTest.cs | 1006 +++++++++++++++++ .../DocumentProcessingInfoServiceTest.cs | 957 ++++++++++++++++ .../FosDnaDocumentProcessingServiceTest.cs | 608 ++++++++++ .../FosLoanStatementProcessingServiceTest.cs | 426 +++++++ .../FosTaxStatementProcessingServiceTest.cs | 473 ++++++++ .../OsgDnaNoticeSplitProcessingServiceTest.cs | 166 +++ .../OsgDnaNoticesProcessingServiceTest.cs | 467 ++++++++ ...HistoricalDocumentProcessingServiceTest.cs | 485 ++++++++ .../OsgTaxStatementProcessingServiceTest.cs | 478 ++++++++ ...tionNoticeDocumentProcessingServiceTest.cs | 242 ++++ ...iDnaNoticeDocumentProcessingServiceTest.cs | 343 ++++++ .../DocumentReprocessingServiceTest.cs | 537 +++++++++ ...ocumentTypeArchiveDeleteInfoServiceTest.cs | 289 +++++ .../FosDnaDocumentIndexServiceTest.cs | 132 +++ .../FosLoanStatementIndexServiceTest.cs | 153 +++ .../FosTaxStatementIndexServiceTest.cs | 122 ++ .../OsgDnaNoticeSplitIndexServiceTest.cs | 123 ++ .../OsgDnaNoticesIndexServiceTest.cs | 153 +++ .../OsgHistoricalDocumentIndexServiceTest.cs | 153 +++ .../OsgTaxStatementIndexServiceTest.cs | 123 ++ ...XdiActionNoticeDocumentIndexServiceTest.cs | 112 ++ .../XdiDnaNoticeDocumentIndexServiceTest.cs | 112 ++ .../BatchIngestionServiceTest.cs | 173 +++ .../CompletionServiceTest.cs | 242 ++++ .../DocumentProcessorServiceTest.cs | 196 ++++ .../IndexServiceTest.cs | 633 +++++++++++ .../IngestionFolderCleanUpTest.cs | 731 ++++++++++++ .../MemberDocumentNotifierServiceTest.cs | 606 ++++++++++ ...MemberNotificationCompletionServiceTest.cs | 340 ++++++ .../OsgPreprocessorServiceTest.cs | 773 +++++++++++++ .../PdfPartitionerCompletionServiceTest.cs | 198 ++++ .../PdfPartitionerServiceTest.cs | 579 ++++++++++ .../ProcessStatusTypeEmailServiceTest.cs | 104 ++ .../UploadCompletionServiceTest.cs | 154 +++ .../Services/IngestorRunInfoServiceTest.cs | 173 +++ ...tNotificationInfoDeterminingServiceTest.cs | 105 ++ ...rNotificationInfoDeterminingServiceTest.cs | 386 +++++++ ...yNotificationInfoDeterminingServiceTest.cs | 166 +++ .../MemberNotificationInfoServiceTest.cs | 627 ++++++++++ .../CoreApiWrapperServiceTest.cs | 293 +++++ .../DocumentTypeRetrieverApiServiceTest.cs | 106 ++ .../DocumentTypeUploaderApiServiceTest.cs | 116 ++ .../FileOperationsApiServiceTest.cs | 358 ++++++ .../MemberPreferencesApiServiceTest.cs | 103 ++ .../NotificationApiServiceTest.cs | 57 + .../OsgPreprocessorInfoServiceTest.cs | 366 ++++++ .../Services/OwnerOverrideInfoServiceTest.cs | 197 ++++ .../FosLoanStatementPdfServiceTest.cs | 188 +++ .../OsgDnaNoticesPdfServiceTest.cs | 182 +++ .../OsgHistoricalDocumentPdfServiceTest.cs | 182 +++ .../Services/PdfPartitionerLogServiceTest.cs | 196 ++++ .../PdfPartitionerRunInfoServiceTest.cs | 209 ++++ .../Services/ProcessingLogServiceTest.cs | 304 +++++ ...UploadCompletionReprocessingServiceTest.cs | 251 ++++ .../Test_OSG_Index_File.XML | 8 + .../Test_OSG_Index_File_1099_MISC.XML | 8 + .../Utilities/ToDetailStringExtensionTest.cs | 142 +++ .../DocumentProcessingInfoSortableFields.cs | 20 + .../Constants/Users.cs | 7 + .../Constants/ValidationMessages.cs | 13 + .../Entities/DocumentCodeDetailInfo.cs | 7 + .../Entities/DocumentProcessingInfo.cs | 55 + .../Entities/DocumentTypeArchiveDeleteInfo.cs | 26 + .../Entities/IngestorRunInfo.cs | 41 + .../Entities/MemberNotificationInfo.cs | 18 + .../Entities/OsgPreprocessorInfo.cs | 18 + .../Entities/OwnerOverrideInfo.cs | 48 + .../Entities/PdfPartitionerLog.cs | 23 + .../Entities/PdfPartitionerRunInfo.cs | 57 + .../Entities/ProcessingLog.cs | 25 + .../Enums/DeliveryMethod.cs | 12 + .../Enums/DocumentOwnerTypes.cs | 8 + .../Enums/EntityTypes.cs | 9 + .../Enums/IngestorTypes.cs | 18 + .../Enums/NotificationStatusTypes.cs | 11 + .../Enums/PdfParserTypes.cs | 9 + .../Enums/ProcessStatusTypes.cs | 14 + ...ary.Internal.DocumentIngestorModels.csproj | 146 +++ .../Models/BatchIngestionRequest.cs | 54 + .../Models/BatchIngestionResult.cs | 36 + ...atchUpdateMemberNotificationDataRequest.cs | 18 + .../Models/BatchUploadCompletionRequest.cs | 11 + .../Models/BulkNotificationStatusRequest.cs | 38 + .../Models/CompletionProcessingData.cs | 9 + .../Models/CompletionRequest.cs | 9 + .../DocumentProcessingInfoStatusRequest.cs | 46 + .../Models/DynamicIngestionDate.cs | 10 + .../Models/EntityUnknownRequest.cs | 34 + .../Models/ErrorCaptureResult.cs | 31 + .../GatherMemberNotificationInfoRequest.cs | 6 + .../IndexFileDocuments/FosDnaDocument.cs | 18 + .../IndexFileDocuments/FosLoanStatement.cs | 24 + .../FosTaxStatementDocument.cs | 24 + .../IndexFileDocuments/OsgDnaNoticeSplit.cs | 40 + .../OsgDnaNoticesDocument.cs | 28 + .../OsgHistoricalDocument.cs | 28 + .../IndexFileDocuments/OsgTaxStatement.cs | 40 + .../OsgTemenosNoticesDocument.cs | 31 + .../IndexFileDocuments/OsgWeilandStatement.cs | 28 + .../XdiActionNoticesDocument.cs | 28 + .../XdiDnaNoticesDocument.cs | 31 + .../Models/IngestionFolderCleanUpRequest.cs | 35 + .../Models/IngestionFolderCleanUpResult.cs | 24 + .../Models/IngestorRequest.cs | 44 + .../Models/IngestorResult.cs | 23 + .../MemberDocumentNotificationRequest.cs | 7 + .../MemberDocumentNotificationResult.cs | 34 + .../MemberNotificationCompletionRequest.cs | 8 + .../Models/MemberNotificationInfoRequest.cs | 10 + .../Models/OsgPreprocessorRequest.cs | 54 + .../Models/OsgPreprocessorResult.cs | 18 + .../Models/OsgPreprocessorRunInfo.cs | 52 + .../Models/PdfPartitionerRequest.cs | 57 + .../Models/PdfPartitionerResult.cs | 27 + .../Models/ProcessResult.cs | 78 ++ .../Models/ProcessStatusTypeEmailRequest.cs | 35 + .../Models/ProcessingRequest.cs | 17 + .../QueueResult/QueueCompletionResult.cs | 7 + ...QueueGatherMemberNotificationInfoResult.cs | 7 + .../Models/UploadCompletionRequest.cs | 16 + .../XmlParser/XmlOsgHistoricalDocuments.cs | 55 + .../Pagination/Filter.cs | 50 + .../Pagination/PagedResponse.cs | 32 + .../Pagination/PagedResult.cs | 10 + .../Pagination/SortableField.cs | 9 + .../Pagination/StatusFilter.cs | 11 + .../Validations/MetaDataValidation.cs | 84 ++ LCU.API.Internal.DocumentIngestor/README.md | 224 ++++ .../_kube_local_testing/kind.cluster.config | 7 + .../linux/setup_and_deploy.sh | 29 + .../_kube_local_testing/linux/teardown.sh | 5 + .../_kube_local_testing/linux/update_pod.sh | 2 + .../windows/install_dependencies.ps1 | 2 + .../windows/setup_and_deploy.ps1 | 19 + .../_kube_local_testing/windows/teardown.ps1 | 2 + .../azdo_pipelines/azure-k8s-pipeline.yaml | 78 ++ .../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 | 13 + .../azdo_pipelines/config-files/qa-pvars.yaml | 13 + .../config-files/uat-pvars.yaml | 13 + .../cleanbuildrun.sh | 16 + .../kustomize/base/Deployment.yaml | 44 + .../kustomize/base/Service.yaml | 11 + .../kustomize/base/kustomization.yaml | 9 + .../base/secrets-provider-class.yaml | 11 + .../kustomize/base/virtual-service.yaml | 19 + .../keyvaults/historical/kustomization.yaml | 10 + .../historical/set_secrets_deployment.yaml | 89 ++ .../historical/set_secrets_provider.yaml | 44 + .../keyvaults/normal/kustomization.yaml | 10 + .../normal/set_secrets_deployment.yaml | 89 ++ .../normal/set_secrets_provider.yaml | 44 + .../appsettings/appsettings.json | 57 + .../kustomization.yaml | 40 + .../set_appsettings_deployment.yaml | 12 + .../appsettings/appsettings.json | 57 + .../historical-completion/kustomization.yaml | 40 + .../set_appsettings_deployment.yaml | 12 + .../appsettings/appsettings.json | 57 + .../kustomization.yaml | 44 + .../set_appsettings_deployment.yaml | 12 + .../set_deployment_replicas.yaml | 3 + .../appsettings/appsettings.json | 57 + .../historical-indexer/kustomization.yaml | 40 + .../set_appsettings_deployment.yaml | 12 + .../appsettings/appsettings.json | 57 + .../historical-processor/kustomization.yaml | 44 + .../set_appsettings_deployment.yaml | 12 + .../set_deployment_replicas.yaml | 3 + .../appsettings/appsettings.json | 57 + .../kustomization.yaml | 40 + .../set_appsettings_deployment.yaml | 12 + .../historical/appsettings/appsettings.json | 57 + .../workloads/historical/kustomization.yaml | 40 + .../set_appsettings_deployment.yaml | 12 + .../appsettings/appsettings.json | 21 + .../kustomization.yaml | 40 + .../set_appsettings_deployment.yaml | 12 + .../appsettings/appsettings.json | 21 + .../normal-completion/kustomization.yaml | 40 + .../set_appsettings_deployment.yaml | 12 + .../appsettings/appsettings.json | 21 + .../kustomization.yaml | 44 + .../set_appsettings_deployment.yaml | 12 + .../set_deployment_replicas.yaml | 3 + .../appsettings/appsettings.json | 21 + .../normal-indexer/kustomization.yaml | 40 + .../set_appsettings_deployment.yaml | 12 + .../appsettings/appsettings.json | 21 + .../normal-processor/kustomization.yaml | 43 + .../set_appsettings_deployment.yaml | 12 + .../set_deployment_replicas.yaml | 3 + .../normal-prod/appsettings/appsettings.json | 21 + .../workloads/normal-prod/kustomization.yaml | 40 + .../set_appsettings_deployment.yaml | 12 + .../appsettings/appsettings.json | 21 + .../kustomization.yaml | 40 + .../set_appsettings_deployment.yaml | 12 + .../normal/appsettings/appsettings.json | 21 + .../workloads/normal/kustomization.yaml | 40 + .../normal/set_appsettings_deployment.yaml | 12 + .../overlays/prd/appsettings/appsettings.json | 68 ++ .../overlays/prd/component/kustomization.yaml | 10 + .../component/set_appsettings_deployment.yaml | 5 + .../component/set_secrets_provider_class.yaml | 7 + .../kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../historical-completion/kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../prd/historical-indexer/kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../historical-processor/kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../prd/historical/kustomization.yaml | 12 + .../prd/historical/set_virtual_service.yaml | 3 + .../kustomize/overlays/prd/kustomization.yaml | 27 + .../kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../prd/normal-completion/kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../prd/normal-indexer/kustomization.yaml | 12 + .../normal-indexer/set_virtual_service.yaml | 3 + .../prd/normal-processor/kustomization.yaml | 12 + .../normal-processor/set_virtual_service.yaml | 3 + .../kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../overlays/prd/normal/kustomization.yaml | 12 + .../prd/normal/set_virtual_service.yaml | 3 + .../prd/set_configmap_deployment.yaml | 12 + .../overlays/qa/appsettings/appsettings.json | 68 ++ .../overlays/qa/component/kustomization.yaml | 10 + .../component/set_appsettings_deployment.yaml | 5 + .../component/set_secrets_provider_class.yaml | 7 + .../kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../historical-completion/kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../qa/historical-indexer/kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../historical-processor/kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../overlays/qa/historical/kustomization.yaml | 12 + .../qa/historical/set_virtual_service.yaml | 3 + .../kustomize/overlays/qa/kustomization.yaml | 27 + .../kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../qa/normal-completion/kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../qa/normal-indexer/kustomization.yaml | 12 + .../normal-indexer/set_virtual_service.yaml | 3 + .../qa/normal-processor/kustomization.yaml | 12 + .../normal-processor/set_virtual_service.yaml | 3 + .../kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../overlays/qa/normal/kustomization.yaml | 12 + .../qa/normal/set_virtual_service.yaml | 3 + .../overlays/qa/set_configmap_deployment.yaml | 12 + .../overlays/uat/appsettings/appsettings.json | 68 ++ .../overlays/uat/component/kustomization.yaml | 10 + .../component/set_appsettings_deployment.yaml | 5 + .../component/set_secrets_provider_class.yaml | 7 + .../kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../historical-completion/kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../uat/historical-indexer/kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../historical-processor/kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../uat/historical/kustomization.yaml | 12 + .../uat/historical/set_virtual_service.yaml | 3 + .../kustomize/overlays/uat/kustomization.yaml | 27 + .../kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../uat/normal-completion/kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../uat/normal-indexer/kustomization.yaml | 12 + .../normal-indexer/set_virtual_service.yaml | 3 + .../uat/normal-processor/kustomization.yaml | 12 + .../normal-processor/set_virtual_service.yaml | 3 + .../kustomization.yaml | 12 + .../set_virtual_service.yaml | 3 + .../overlays/uat/normal/kustomization.yaml | 12 + .../uat/normal/set_virtual_service.yaml | 3 + .../uat/set_configmap_deployment.yaml | 12 + 592 files changed, 46618 insertions(+) create mode 100644 LCU.API.Internal.DocumentIngestor/.gitignore create mode 100644 LCU.API.Internal.DocumentIngestor/Dockerfile create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor.sln create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/ApiConfiguration.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/CoreApiWrapperConfiguration.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/DigitalBankingConfiguration.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/DispatcherJobCreationConfiguration.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/DocumentCodeDetailCacheConfiguration.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/DocumentTypeRetrieverConfiguration.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/DocumentTypeUploaderConfiguration.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/FeatureFlags.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/FileOperationsApiConfiguration.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/MemberPreferencesApiConfiguration.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/NotificationApiConfiguration.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/Notifications.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/ReceiveEndpointConfigurations.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/SqlConnectionConfiguration.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/BatchIngestionConsumer.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/BatchUpdateMemberNotificationDataConsumer.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/GatherMemberNotificationInfoConsumer.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/IngestionFolderCleanUpConsumer.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/IngestorCompletionConsumer.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/IngestorIndexConsumer.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/IngestorProcessingConsumer.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/MemberDocumentNotifierConsumer.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/MemberNotificationCompletionConsumer.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/PdfPartitionerCompletionConsumer.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/PdfPartitionerConsumer.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/ProcessStatusTypeEmailConsumer.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/UploadCompletionConsumer.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/BatchIngestionController.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/DocumentIngestorController.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/DocumentProcessingInfoController.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/DocumentReprocessingController.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/DocumentTypeArchiveDeleteInfoController.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/IngestionFolderCleanUpController.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/IngestorRunInfoController.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/MemberDocumentNotifierController.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/MemberNotificationInfoController.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/OsgPreprocessorController.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/PdfPartitionerController.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/PdfPartitionerLogController.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/PdfPartitionerRunInfoController.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/ProcessingLogController.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/QueueProcessStatusTypeEmailController.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/StatusController.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/UploadCompletionReprocessingController.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/CoreApiWrapperDao.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/DocumentTypeRetrieverDao.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/DocumentTypeUploaderApiDao.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/FileOperationsApiDao.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/ICoreApiWrapperDao.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/IDocumentTypeRetrieverDao.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/IDocumentTypeUploaderApiDao.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/IFileOperationsApiDao.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/IMemberPreferencesApiDao.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/INotificationApiDao.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/MemberPreferencesApiDao.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/NotificationApiDao.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Initializers/CloudRoleNameTelemetryInitializer.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor.csproj create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Models/MemberPreferencesDtos/MemberOptInAgreementInformation.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Models/MemberPreferencesDtos/MemberOptInInformation.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Models/MemberPreferencesDtos/MemberOptInSettings.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Program.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Properties/launchSettings.json create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Security/GroupMembershipRequirement.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Security/GroupMembershipRequirementHandler.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Security/ITRolePolicy.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Security/SecurityConfiguration.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Security/SetDocumentNotificationStatusPolicy.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/AttributeDeterminingServices/AccountOwnerDeterminingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/AttributeDeterminingServices/BaseOwnerDeterminingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/AttributeDeterminingServices/IAccountOwnerDeterminingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/AttributeDeterminingServices/IPrimaryOwnerDeterminingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/AttributeDeterminingServices/PrimaryOwnerDeterminingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessingInfoService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/DocumentProcessingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/FosDnaDocumentProcessingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/FosLoanStatementProcessingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/FosTaxStatementProcessingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/IDocumentProcessingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgDnaNoticeSplitProcessingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgDnaNoticesProcessingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgHistoricalDocumentProcessingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgTaxStatementProcessingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgTemenosNoticeProcessingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgVehicleTaxStatementProcessingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgWeilandStatementProcessingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/XdiActionNoticesProcessingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/XdiDnaNoticeDocumentProcessingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentReprocessingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentTypeArchiveDeleteInfoService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IDocumentProcessingInfoService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IDocumentReprocessingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IDocumentTypeArchiveDeleteInfoService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IIngestorRunInfoService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IMemberNotificationInfoService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IOsgPreprocessorInfoService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IOwnerOverrideInfoService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IPdfPartitionerLogService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IPdfPartitionerRunInfoService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IProcessingLogService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IUploadCompletionReprocessingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/FosDnaDocumentIndexService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/FosLoanStatementIndexService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/FosTaxStatementIndexService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/IIndexParserService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/IPdfIndexParserService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/IndexParserService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgDnaNoticeSplitIndexService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgDnaNoticesIndexService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgHistoricalDocumentIndexService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgTaxStatementIndexService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgTemenosNoticeIndexService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgVehicleTaxStatementIndexService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgWeilandStatementIndexService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/XdiActionNoticeDocumentIndexService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/XdiDnaNoticeDocumentIndexService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/BatchIngestionService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/BatchUpdateMemberNotificationDataService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/CompletionService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/DocumentProcessorService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/GatherMemberNotificationInfoService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IBatchIngestionService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IBatchUpdateMemberNotificationDataService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/ICompletionService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IDocumentProcessorService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IGatherMemberNotificationInfoService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IIndexService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IIngestionFolderCleanUpService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IMemberDocumentNotifierService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IMemberNotificationCompletionService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IOsgPreprocessorService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IPdfPartitionerCompletionService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IPdfPartitionerService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IProcessStatusTypeEmailService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IUploadCompletionService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IndexService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IngestionFolderCleanUpService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/MemberDocumentNotifierService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/MemberNotificationCompletionService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/OsgPreprocessorService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/PdfPartitionerCompletionService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/PdfPartitionerService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/ProcessStatusTypeEmailService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/UploadCompletionService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestorRunInfoService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/AccountNotificationInfoDeterminingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/IAccountNotificationInfoDeterminingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/IMemberNotificationInfoDeterminingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/IPrimaryNotificationInfoDeterminingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/MemberNotificationInfoDeterminingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/PrimaryNotificationInfoDeterminingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/CoreApiWrapperService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/DocumentTypeRetrieverService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/DocumentTypeUploaderApiService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/FileOperationsApiService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/ICoreApiWrapperService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/IDocumentTypeRetrieverService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/IDocumentTypeUploaderApiService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/IFileOperationsApiService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/IMemberPreferencesApiService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/INotificationApiService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/MemberPreferencesApiService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/NotificationApiService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/OsgPreprocessorInfoService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/OwnerOverrideInfoService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfParserServices/FosLoanStatementPdfService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfParserServices/IPdfParserService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfParserServices/OsgDnaNoticesPdfService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfParserServices/OsgHistoricalDocumentPdfService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfParserServices/PdfParserService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfPartitionerLogService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfPartitionerRunInfoService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/ProcessingLogService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueBatchIngestionService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueBatchUpdateMemberNotificationDataService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueCompletionService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueDocumentIngestorService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueDocumentProcessingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueGatherMemberNotificationInfoService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueIngestionFolderCleanUpService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueMemberDocumentNotifierService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueMemberNotificationCompletionService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueuePdfPartitionerCompletionService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueuePdfPartitionerService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueProcessStatusTypeEmailService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IResponseQueue.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueBatchIngestionService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueBatchUpdateMemberNotificationDataService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueCompletionService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueDocumentIngestorService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueDocumentProcessingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueGatherMemberNotificationInfoService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueIngestionFolderCleanUpService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueMemberDocumentNotifierService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueMemberNotificationCompletionService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueuePdfPartitionerCompletionService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueuePdfPartitionerService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueProcessStatusTypeEmailService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/ResponseQueue.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/UploadCompletionReprocessingService.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Templates/NotificationEmailRowTemplate.html create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Templates/NotificationEmailTemplate.html create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Utilities/HttpUtilities.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Utilities/SpecialCharacters.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Utilities/ToDetailStringExtension.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/appsettings.json create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Exceptions/ArchiveException.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/FilterNullsAndZerosOrDefaultExtension.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoCreatedDateQueryable.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoDocBusinessNameQueryable.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoDocTypeQueryable.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoIndexJsonEqualsFilter.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoIndexJsonLikeOrFilter.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoIngestorRunInfoIdQueryable.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoNotificationStatusQueryable.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoStatusTypeQueryable.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/IncludeAllQueryable.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/IncludeFiltersQueryable.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/SortableFieldsQueryable.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/TimeZoneDateTime.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/LCU.API.Internal.DocumentIngestorLib.csproj create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Persistence/AppDbContext.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/BaseRepository.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/DocumentProcessingInfoRepository.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/DocumentTypeArchiveDeleteInfoRepository.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IDocumentProcessingInfoRepository.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IDocumentTypeArchiveDeleteInfoRepository.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IIngestorRunInfoRepository.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IMemberNotificationInfoRepository.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IOsgPreprocessorInfoRepository.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IOwnerOverrideInfoRepository.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IPdfPartitionerLogRepository.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IPdfPartitionerRunInfoRepository.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IProcessingLogRepository.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IUnitOfWork.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IngestorRunInfoRepository.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/MemberNotificationInfoRepository.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/OsgPreprocessorInfoRepository.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/OwnerOverrideInfoRepository.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/PdfPartitionerLogRepository.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/PdfPartitionerRunInfoRepository.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/ProcessingLogRepository.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/UnitOfWork.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Extensions/FilterNullsAndZerosOrDefaultExtensionTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Extensions/Queryables/DocumentProcessingInfoNotificationStatusQueryableTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/LCU.API.Internal.DocumentIngestorLibTests.csproj create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Repositories/DocumentProcessingInfoRepositoryTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Repositories/MemberNotificationInfoRepositoryTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Repositories/ProcessingLogRepositoryTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/SqlServerDbContextFactory.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/SqliteAppDbContextFactory.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Usings.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/DocumentProcessingInfo.sql create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/DocumentTypeArchiveDeleteInfo.sql create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/IngestorRunInfo.sql create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/LCU.API.Internal.DocumentIngestorSql.refactorlog create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/LCU.API.Internal.DocumentIngestorSql.sqlproj create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/MemberNotificationInfo.sql create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/OsgPreprocessorInfo.sql create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/OwnerOverrideInfo.sql create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/PdfPartitionerLog.sql create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/PdfPartitionerRunInfo.sql create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/ProcessingLog.sql create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/BatchIngestionControllerTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/DocumentIngestorControllerTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/DocumentProcessingInfoControllerTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/DocumentReprocessingControllerTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/DocumentTypeArchiveDeleteInfoControllerTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/IngestorRunInfoControllerTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/MemberDocumentNotifierControllerTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/MemberNotificationInfoControllerTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/OsgPreprocessorControllerTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/PdfPartitionerControllerTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/PdfPartitionerLogControllerTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/PdfPartitionerRunInfoControllerTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/ProcessingLogControllerTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/UploadCompletionReprocessingControllerTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/LCU.API.Internal.DocumentIngestorTests.csproj create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Models/ProcessResultTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Models/Validations/MetaDataValidationTests.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Security/GroupMembershipRequirementHandlerTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/AttributeDeterminingServices/AccountOwnerDeterminingServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/AttributeDeterminingServices/PrimaryOwnerDeterminingServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessingInfoServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/FosDnaDocumentProcessingServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/FosLoanStatementProcessingServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/FosTaxStatementProcessingServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/OsgDnaNoticeSplitProcessingServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/OsgDnaNoticesProcessingServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/OsgHistoricalDocumentProcessingServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/OsgTaxStatementProcessingServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/XdiActionNoticeDocumentProcessingServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/XdiDnaNoticeDocumentProcessingServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentReprocessingServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentTypeArchiveDeleteInfoServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/FosDnaDocumentIndexServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/FosLoanStatementIndexServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/FosTaxStatementIndexServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/OsgDnaNoticeSplitIndexServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/OsgDnaNoticesIndexServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/OsgHistoricalDocumentIndexServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/OsgTaxStatementIndexServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/XdiActionNoticeDocumentIndexServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/XdiDnaNoticeDocumentIndexServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/BatchIngestionServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/CompletionServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/DocumentProcessorServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/IndexServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/IngestionFolderCleanUpTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/MemberDocumentNotifierServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/MemberNotificationCompletionServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/OsgPreprocessorServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/PdfPartitionerCompletionServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/PdfPartitionerServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/ProcessStatusTypeEmailServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/UploadCompletionServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestorRunInfoServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MemberNotificationInfoDeterminingServices/AccountNotificationInfoDeterminingServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MemberNotificationInfoDeterminingServices/MemberNotificationInfoDeterminingServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MemberNotificationInfoDeterminingServices/PrimaryNotificationInfoDeterminingServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MemberNotificationInfoServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/CoreApiWrapperServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/DocumentTypeRetrieverApiServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/DocumentTypeUploaderApiServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/FileOperationsApiServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/MemberPreferencesApiServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/NotificationApiServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/OsgPreprocessorInfoServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/OwnerOverrideInfoServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/PdfParserServices/FosLoanStatementPdfServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/PdfParserServices/OsgDnaNoticesPdfServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/PdfParserServices/OsgHistoricalDocumentPdfServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/PdfPartitionerLogServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/PdfPartitionerRunInfoServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/ProcessingLogServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/UploadCompletionReprocessingServiceTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/TestContent/Test_OSG_Index_File/Test_OSG_Index_File.XML create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/TestContent/Test_OSG_Index_File/Test_OSG_Index_File_1099_MISC.XML create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Utilities/ToDetailStringExtensionTest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Constants/DocumentProcessingInfoSortableFields.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Constants/Users.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Constants/ValidationMessages.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/DocumentCodeDetailInfo.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/DocumentProcessingInfo.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/DocumentTypeArchiveDeleteInfo.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/IngestorRunInfo.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/MemberNotificationInfo.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/OsgPreprocessorInfo.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/OwnerOverrideInfo.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/PdfPartitionerLog.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/PdfPartitionerRunInfo.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/ProcessingLog.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/DeliveryMethod.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/DocumentOwnerTypes.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/EntityTypes.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/IngestorTypes.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/NotificationStatusTypes.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/PdfParserTypes.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/ProcessStatusTypes.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/LCU.Library.Internal.DocumentIngestorModels.csproj create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/BatchIngestionRequest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/BatchIngestionResult.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/BatchUpdateMemberNotificationDataRequest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/BatchUploadCompletionRequest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/BulkNotificationStatusRequest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/CompletionProcessingData.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/CompletionRequest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/DocumentProcessingInfoStatusRequest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/DynamicIngestionDate.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/EntityUnknownRequest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/ErrorCaptureResult.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/GatherMemberNotificationInfoRequest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/FosDnaDocument.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/FosLoanStatement.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/FosTaxStatementDocument.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgDnaNoticeSplit.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgDnaNoticesDocument.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgHistoricalDocument.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgTaxStatement.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgTemenosNoticesDocument.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgWeilandStatement.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/XdiActionNoticesDocument.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/XdiDnaNoticesDocument.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IngestionFolderCleanUpRequest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IngestionFolderCleanUpResult.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IngestorRequest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IngestorResult.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/MemberDocumentNotificationRequest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/MemberDocumentNotificationResult.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/MemberNotificationCompletionRequest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/MemberNotificationInfoRequest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/OsgPreprocessorRequest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/OsgPreprocessorResult.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/OsgPreprocessorRunInfo.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/PdfPartitionerRequest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/PdfPartitionerResult.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/ProcessResult.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/ProcessStatusTypeEmailRequest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/ProcessingRequest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/QueueResult/QueueCompletionResult.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/QueueResult/QueueGatherMemberNotificationInfoResult.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/UploadCompletionRequest.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/XmlParser/XmlOsgHistoricalDocuments.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Pagination/Filter.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Pagination/PagedResponse.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Pagination/PagedResult.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Pagination/SortableField.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Pagination/StatusFilter.cs create mode 100644 LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Validations/MetaDataValidation.cs create mode 100644 LCU.API.Internal.DocumentIngestor/README.md create mode 100644 LCU.API.Internal.DocumentIngestor/_kube_local_testing/kind.cluster.config create mode 100644 LCU.API.Internal.DocumentIngestor/_kube_local_testing/linux/setup_and_deploy.sh create mode 100644 LCU.API.Internal.DocumentIngestor/_kube_local_testing/linux/teardown.sh create mode 100644 LCU.API.Internal.DocumentIngestor/_kube_local_testing/linux/update_pod.sh create mode 100644 LCU.API.Internal.DocumentIngestor/_kube_local_testing/windows/install_dependencies.ps1 create mode 100644 LCU.API.Internal.DocumentIngestor/_kube_local_testing/windows/setup_and_deploy.ps1 create mode 100644 LCU.API.Internal.DocumentIngestor/_kube_local_testing/windows/teardown.ps1 create mode 100644 LCU.API.Internal.DocumentIngestor/azdo_pipelines/azure-k8s-pipeline.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/azdo_pipelines/azure-pipelines-feature-branches.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/azdo_pipelines/azure-pipelines-prd.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/azdo_pipelines/azure-pipelines-qa.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/azdo_pipelines/azure-pipelines-uat.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/azdo_pipelines/config-files/prd-pvars.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/azdo_pipelines/config-files/qa-pvars.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/azdo_pipelines/config-files/uat-pvars.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/cleanbuildrun.sh create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/base/Deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/base/Service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/base/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/base/secrets-provider-class.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/base/virtual-service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/historical/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/historical/set_secrets_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/historical/set_secrets_provider.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/normal/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/normal/set_secrets_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/normal/set_secrets_provider.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-batchupdatemembernotif/appsettings/appsettings.json create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-batchupdatemembernotif/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-batchupdatemembernotif/set_appsettings_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-completion/appsettings/appsettings.json create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-completion/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-completion/set_appsettings_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-gathermembernotificationinfo/appsettings/appsettings.json create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-gathermembernotificationinfo/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-gathermembernotificationinfo/set_appsettings_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-gathermembernotificationinfo/set_deployment_replicas.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-indexer/appsettings/appsettings.json create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-indexer/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-indexer/set_appsettings_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-processor/appsettings/appsettings.json create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-processor/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-processor/set_appsettings_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-processor/set_deployment_replicas.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-uploadcompletion/appsettings/appsettings.json create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-uploadcompletion/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-uploadcompletion/set_appsettings_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical/appsettings/appsettings.json create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical/set_appsettings_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-batchupdatemembernotif/appsettings/appsettings.json create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-batchupdatemembernotif/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-batchupdatemembernotif/set_appsettings_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-completion/appsettings/appsettings.json create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-completion/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-completion/set_appsettings_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-gathermembernotificationinfo/appsettings/appsettings.json create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-gathermembernotificationinfo/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-gathermembernotificationinfo/set_appsettings_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-gathermembernotificationinfo/set_deployment_replicas.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-indexer/appsettings/appsettings.json create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-indexer/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-indexer/set_appsettings_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-processor/appsettings/appsettings.json create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-processor/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-processor/set_appsettings_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-processor/set_deployment_replicas.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-prod/appsettings/appsettings.json create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-prod/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-prod/set_appsettings_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-uploadcompletion/appsettings/appsettings.json create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-uploadcompletion/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-uploadcompletion/set_appsettings_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal/appsettings/appsettings.json create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal/set_appsettings_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/appsettings/appsettings.json create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/component/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/component/set_appsettings_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/component/set_secrets_provider_class.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-batchupdatemembernotif/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-batchupdatemembernotif/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-completion/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-completion/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-gathermembernotificationinfo/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-gathermembernotificationinfo/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-indexer/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-indexer/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-processor/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-processor/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-uploadcompletion/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-uploadcompletion/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-batchupdatemembernotif/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-batchupdatemembernotif/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-completion/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-completion/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-gathermembernotificationinfo/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-gathermembernotificationinfo/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-indexer/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-indexer/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-processor/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-processor/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-uploadcompletion/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-uploadcompletion/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/set_configmap_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/appsettings/appsettings.json create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/component/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/component/set_appsettings_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/component/set_secrets_provider_class.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-batchupdatemembernotif/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-batchupdatemembernotif/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-completion/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-completion/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-gathermembernotificationinfo/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-gathermembernotificationinfo/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-indexer/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-indexer/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-processor/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-processor/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-uploadcompletion/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-uploadcompletion/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-batchupdatemembernotif/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-batchupdatemembernotif/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-completion/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-completion/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-gathermembernotificationinfo/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-gathermembernotificationinfo/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-indexer/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-indexer/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-processor/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-processor/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-uploadcompletion/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-uploadcompletion/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/set_configmap_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/appsettings/appsettings.json create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/component/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/component/set_appsettings_deployment.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/component/set_secrets_provider_class.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-batchupdatemembernotif/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-batchupdatemembernotif/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-completion/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-completion/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-gathermembernotificationinfo/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-gathermembernotificationinfo/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-indexer/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-indexer/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-processor/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-processor/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-uploadcompletion/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-uploadcompletion/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-batchupdatemembernotif/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-batchupdatemembernotif/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-completion/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-completion/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-gathermembernotificationinfo/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-gathermembernotificationinfo/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-indexer/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-indexer/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-processor/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-processor/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-uploadcompletion/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-uploadcompletion/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal/kustomization.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal/set_virtual_service.yaml create mode 100644 LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/set_configmap_deployment.yaml diff --git a/LCU.API.Internal.DocumentIngestor/.gitignore b/LCU.API.Internal.DocumentIngestor/.gitignore new file mode 100644 index 0000000..41ee9e4 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/.gitignore @@ -0,0 +1,363 @@ +## 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 +*_h.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 + +# 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/ + +# CodeRush personal settings +.cr/personal + +# 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 +.idea/** diff --git a/LCU.API.Internal.DocumentIngestor/Dockerfile b/LCU.API.Internal.DocumentIngestor/Dockerfile new file mode 100644 index 0000000..f49c45e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/Dockerfile @@ -0,0 +1,41 @@ +# .NET Core SDK +FROM mcr.microsoft.com/dotnet/sdk:8.0 AS aspnetcore-build + +# Copy Projects +COPY LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor.csproj ./source/LCU.API.Internal.DocumentIngestor/ +COPY LCU.API.Internal.DocumentIngestorLib/LCU.API.Internal.DocumentIngestorLib.csproj ./source/LCU.API.Internal.DocumentIngestorLib/ +COPY LCU.Library.Internal.DocumentIngestorModels/LCU.Library.Internal.DocumentIngestorModels.csproj ./source/LCU.Library.Internal.DocumentIngestorModels/ + +# 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.DocumentIngestor/LCU.API.Internal.DocumentIngestor.csproj + +# Copy All Files +COPY . ./source/ + +FROM aspnetcore-build AS test +LABEL test=true +COPY LCU.API.Internal.DocumentIngestorTests/LCU.API.Internal.DocumentIngestorTests.csproj ./source/LCU.API.Internal.DocumentIngestorTests/ +RUN dotnet restore ./source/LCU.API.Internal.DocumentIngestorTests/LCU.API.Internal.DocumentIngestorTests.csproj +RUN dotnet test -c Release --results-directory /testresults --logger "trx;LogFileName=test_results.trx" ./source/LCU.API.Internal.DocumentIngestorTests/LCU.API.Internal.DocumentIngestorTests.csproj + +# .NET Core Publish +FROM aspnetcore-build as publish +RUN dotnet publish ./source/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor.csproj -c Release -o /dist + +# ASP.NET Core +FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine3.20 +RUN apk add --no-cache icu-libs && apk add --no-cache tzdata; +ENV TZ America/Chicago +ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false +ENV ASPNETCORE_ENVIRONMENT=Development + +WORKDIR /app +COPY --from=publish /dist . +ENTRYPOINT ["dotnet", "LCU.API.Internal.DocumentIngestor.dll"] diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor.sln b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor.sln new file mode 100644 index 0000000..85256f6 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor.sln @@ -0,0 +1,71 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.0.32112.339 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCU.API.Internal.DocumentIngestor", "LCU.API.Internal.DocumentIngestor\LCU.API.Internal.DocumentIngestor.csproj", "{9A992EC6-3DC7-40E8-B091-D1F5CB89DCBC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCU.Library.Internal.DocumentIngestorModels", "LCU.Library.Internal.DocumentIngestorModels\LCU.Library.Internal.DocumentIngestorModels.csproj", "{7CF884F8-E4AA-4AD4-8F18-839E917189C4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCU.API.Internal.DocumentIngestorLib", "LCU.API.Internal.DocumentIngestorLib\LCU.API.Internal.DocumentIngestorLib.csproj", "{8FD9C489-045E-4530-9980-F4ACBDFB71A4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCU.API.Internal.DocumentIngestorTests", "LCU.API.Internal.DocumentIngestorTests\LCU.API.Internal.DocumentIngestorTests.csproj", "{9CE57A4B-7C3E-4750-B2D5-8AF4590AADEE}" +EndProject +Project("{00D1A9C2-B5F0-4AF3-8072-F6C62B433612}") = "LCU.API.Internal.DocumentIngestorSql", "LCU.API.Internal.DocumentIngestorSql\LCU.API.Internal.DocumentIngestorSql.sqlproj", "{781F2DE1-9629-49D1-82A4-015B62EE92EF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LCU.API.Internal.DocumentIngestorLibTests", "LCU.API.Internal.DocumentIngestorLibTests\LCU.API.Internal.DocumentIngestorLibTests.csproj", "{D91F57F1-CD10-497E-BB5B-99F421D8188C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + Test|Any CPU = Test|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {9A992EC6-3DC7-40E8-B091-D1F5CB89DCBC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9A992EC6-3DC7-40E8-B091-D1F5CB89DCBC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9A992EC6-3DC7-40E8-B091-D1F5CB89DCBC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9A992EC6-3DC7-40E8-B091-D1F5CB89DCBC}.Release|Any CPU.Build.0 = Release|Any CPU + {9A992EC6-3DC7-40E8-B091-D1F5CB89DCBC}.Test|Any CPU.ActiveCfg = Test|Any CPU + {9A992EC6-3DC7-40E8-B091-D1F5CB89DCBC}.Test|Any CPU.Build.0 = Test|Any CPU + {7CF884F8-E4AA-4AD4-8F18-839E917189C4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7CF884F8-E4AA-4AD4-8F18-839E917189C4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7CF884F8-E4AA-4AD4-8F18-839E917189C4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7CF884F8-E4AA-4AD4-8F18-839E917189C4}.Release|Any CPU.Build.0 = Release|Any CPU + {7CF884F8-E4AA-4AD4-8F18-839E917189C4}.Test|Any CPU.ActiveCfg = Test|Any CPU + {7CF884F8-E4AA-4AD4-8F18-839E917189C4}.Test|Any CPU.Build.0 = Test|Any CPU + {8FD9C489-045E-4530-9980-F4ACBDFB71A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8FD9C489-045E-4530-9980-F4ACBDFB71A4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8FD9C489-045E-4530-9980-F4ACBDFB71A4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8FD9C489-045E-4530-9980-F4ACBDFB71A4}.Release|Any CPU.Build.0 = Release|Any CPU + {8FD9C489-045E-4530-9980-F4ACBDFB71A4}.Test|Any CPU.ActiveCfg = Test|Any CPU + {8FD9C489-045E-4530-9980-F4ACBDFB71A4}.Test|Any CPU.Build.0 = Test|Any CPU + {9CE57A4B-7C3E-4750-B2D5-8AF4590AADEE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9CE57A4B-7C3E-4750-B2D5-8AF4590AADEE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9CE57A4B-7C3E-4750-B2D5-8AF4590AADEE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9CE57A4B-7C3E-4750-B2D5-8AF4590AADEE}.Release|Any CPU.Build.0 = Release|Any CPU + {9CE57A4B-7C3E-4750-B2D5-8AF4590AADEE}.Test|Any CPU.ActiveCfg = Test|Any CPU + {9CE57A4B-7C3E-4750-B2D5-8AF4590AADEE}.Test|Any CPU.Build.0 = Test|Any CPU + {781F2DE1-9629-49D1-82A4-015B62EE92EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {781F2DE1-9629-49D1-82A4-015B62EE92EF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {781F2DE1-9629-49D1-82A4-015B62EE92EF}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {781F2DE1-9629-49D1-82A4-015B62EE92EF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {781F2DE1-9629-49D1-82A4-015B62EE92EF}.Release|Any CPU.Build.0 = Release|Any CPU + {781F2DE1-9629-49D1-82A4-015B62EE92EF}.Release|Any CPU.Deploy.0 = Release|Any CPU + {781F2DE1-9629-49D1-82A4-015B62EE92EF}.Test|Any CPU.ActiveCfg = Release|Any CPU + {781F2DE1-9629-49D1-82A4-015B62EE92EF}.Test|Any CPU.Build.0 = Release|Any CPU + {781F2DE1-9629-49D1-82A4-015B62EE92EF}.Test|Any CPU.Deploy.0 = Release|Any CPU + {D91F57F1-CD10-497E-BB5B-99F421D8188C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D91F57F1-CD10-497E-BB5B-99F421D8188C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D91F57F1-CD10-497E-BB5B-99F421D8188C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D91F57F1-CD10-497E-BB5B-99F421D8188C}.Release|Any CPU.Build.0 = Release|Any CPU + {D91F57F1-CD10-497E-BB5B-99F421D8188C}.Test|Any CPU.ActiveCfg = Test|Any CPU + {D91F57F1-CD10-497E-BB5B-99F421D8188C}.Test|Any CPU.Build.0 = Test|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {65B8A2AE-E03C-4F4D-80C3-8747BAC5B819} + EndGlobalSection +EndGlobal diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/ApiConfiguration.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/ApiConfiguration.cs new file mode 100644 index 0000000..6d811ec --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/ApiConfiguration.cs @@ -0,0 +1,25 @@ +namespace LCU.API.Internal.DocumentIngestor.Configurations; + +public class ApiConfiguration +{ + public string AppName { get; set; } + public string SeqUrl { get; set; } + public string SeqApiKey { get; set; } + public string TimeZone { get; set; } + public string[] CorsAllowedOrigins { get; set; } + public FeatureFlags FeatureFlags { get; set; } + public string ProcessStatusTypeEmailUrl { get; set; } + public int CriticalFailureReprocessLimit { get; set; } + public int NotificationDataFailureReprocessLimit { get; set; } + public int CompletionRetryCount { get; set; } + public int DocumentProcessingReQueueCountLimit { get; set; } = 0; + public string DocumentIngestorApiKey { get; set; } + public int FileUploadCutoffHours { get; set; } + public int MaxMemberNotificationAttempts { get; set; } + public int MaliciousFileSearchPaddingHours { get; set; } + public string NotificationEmailTemplate { get; set; } + public string NotificationEmailRowTemplate { get; set; } + public bool IsHistoric { get; set; } + public int BatchSkipAmount { get; set; } + public Notifications Notifications { get; set; } = new(); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/CoreApiWrapperConfiguration.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/CoreApiWrapperConfiguration.cs new file mode 100644 index 0000000..8087d8e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/CoreApiWrapperConfiguration.cs @@ -0,0 +1,58 @@ +using System.ComponentModel.DataAnnotations.Schema; +namespace LCU.API.Internal.DocumentIngestor.Configurations; + +public class CoreApiWrapperConfiguration +{ + public string Url { get; set; } + public string GetPersonsTaxIdData { get; set; } + public string GetOrganizationsTaxIdData { get; set; } + public string GetOwnersByAccountNumber { get; set; } + public string GetOwnersByOrganizationName { get; set; } + public string GetOwnersByPersonName { get; set; } + public string GetAgreementByUserId { get; set; } + public string GetAgreeUsersByAccounts { get; set; } + public string GetAgreeUsersByPersonNumber { get; set; } + public string GetAgreeUserByOrganizationNumber { get; set; } + public string GetAgreementAccountByAccountId { get; set; } + public string GetAgreementAccountsByUserId { get; set; } + public string GetPersonOrOrganizationNumberByMemberId { get; set; } + + public int RetryCount { get; set; } + + [NotMapped] + public string GetPersonsTaxIdDataUrl => Url + GetPersonsTaxIdData; + + [NotMapped] + public string GetOrganizationsTaxIdDataUrl => Url + GetOrganizationsTaxIdData; + + [NotMapped] + public string GetOwnersByAccountNumberUrl => Url + GetOwnersByAccountNumber; + + [NotMapped] + public string GetOwnersByOrganizationNameUrl => Url + GetOwnersByOrganizationName; + + [NotMapped] + public string GetOwnersByPersonNameUrl => Url + GetOwnersByPersonName; + + [NotMapped] + public string GetAgreementByUserIdUrl => Url + GetAgreementByUserId; + + [NotMapped] + public string GetAgreeUsersByAccountsUrl => Url + GetAgreeUsersByAccounts; + + [NotMapped] + public string GetAgreeUsersByPersonNumberUrl => Url + GetAgreeUsersByPersonNumber; + + [NotMapped] + public string GetAgreeUserByOrganizationNumberUrl => Url + GetAgreeUserByOrganizationNumber; + + [NotMapped] + public string GetAgreementAccountByAccountIdUrl => Url + GetAgreementAccountByAccountId; + + [NotMapped] + public string GetAgreementAccountsByUserIdUrl => Url + GetAgreementAccountsByUserId; + + [NotMapped] + public string GetPersonOrOrganizationNumberByMemberIdUrl => Url + GetPersonOrOrganizationNumberByMemberId; + +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/DigitalBankingConfiguration.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/DigitalBankingConfiguration.cs new file mode 100644 index 0000000..668eca3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/DigitalBankingConfiguration.cs @@ -0,0 +1,19 @@ +using System.ComponentModel.DataAnnotations.Schema; +namespace LCU.API.Internal.DocumentIngestor.Configurations; + +public class DigitalBankingConfiguration +{ + public string DigitalBankingUrl { get; set; } + public string MobileBankingBaseUrl {get; set;} + public string MobileBankingApiKey { get; set; } + public string MobileBankingLinkId { get; set; } + + [NotMapped] + public Uri MobileBankingUri + { + get + { + return new Uri(MobileBankingBaseUrl+"?Link="+MobileBankingLinkId+"&Key="+MobileBankingApiKey); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/DispatcherJobCreationConfiguration.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/DispatcherJobCreationConfiguration.cs new file mode 100644 index 0000000..8199706 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/DispatcherJobCreationConfiguration.cs @@ -0,0 +1,8 @@ +using LCU.Library.Internal.DispatcherModels.Entities; +namespace LCU.API.Internal.DocumentIngestor.Configurations; + +public class DispatcherJobCreationConfiguration +{ + public List DocumentIngestorDispatcherErrorRecipients { get; set; } + public List JobTags { get; set; } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/DocumentCodeDetailCacheConfiguration.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/DocumentCodeDetailCacheConfiguration.cs new file mode 100644 index 0000000..93e8063 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/DocumentCodeDetailCacheConfiguration.cs @@ -0,0 +1,8 @@ +namespace LCU.API.Internal.DocumentIngestor.Configurations +{ + public class DocumentCodeDetailCacheConfiguration + { + public string CacheName { get; set; } + public int ExpirationMinutes { get; set; } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/DocumentTypeRetrieverConfiguration.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/DocumentTypeRetrieverConfiguration.cs new file mode 100644 index 0000000..62ad2f3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/DocumentTypeRetrieverConfiguration.cs @@ -0,0 +1,26 @@ +using System.ComponentModel.DataAnnotations.Schema; +namespace LCU.API.Internal.DocumentIngestor.Configurations; + +public class DocumentTypeRetrieverConfiguration +{ + public string Url { get; set; } + public string GetDocumentCodeDetail { get; set; } + public string GetDocumentCodeDetails { get; set; } + public string GetListOfMaliciousDocuments { get; set; } + public string GetDocumentInformationById { get; set; } + public string Username { get; set; } + public string Password { get; set; } + public int RetryCount { get; set; } + + [NotMapped] + public string GetDocumentCodeDetailUrl => Url + GetDocumentCodeDetail; + + [NotMapped] + public string GetDocumentCodeDetailsUrl => Url + GetDocumentCodeDetails; + + [NotMapped] + public string GetListOfMaliciousDocumentsUrl => Url + GetListOfMaliciousDocuments; + + [NotMapped] + public string GetDocumentInformationByIdUrl => Url + GetDocumentInformationById; +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/DocumentTypeUploaderConfiguration.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/DocumentTypeUploaderConfiguration.cs new file mode 100644 index 0000000..d7db5bd --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/DocumentTypeUploaderConfiguration.cs @@ -0,0 +1,38 @@ +using System.ComponentModel.DataAnnotations.Schema; +namespace LCU.API.Internal.DocumentIngestor.Configurations; + +public class DocumentTypeUploaderConfiguration +{ + public string Url { get; set; } + public string QueuePrimaryOwnerDocumentUpload {get; set;} + public string QueueAccountDocumentUpload { get; set; } + public string QueueGenericDocumentUpload { get; set; } + public int RetryCount { get; set; } + + [NotMapped] + public Uri QueuePrimaryOwnerDocumentUploadUri + { + get + { + return new Uri(Url+QueuePrimaryOwnerDocumentUpload); + } + } + + [NotMapped] + public Uri QueueAccountDocumentUploadUri + { + get + { + return new Uri(Url + QueueAccountDocumentUpload); + } + } + + [NotMapped] + public Uri QueueGenericDocumentUploadUri + { + get + { + return new Uri(Url + QueueGenericDocumentUpload); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/FeatureFlags.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/FeatureFlags.cs new file mode 100644 index 0000000..59f7227 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/FeatureFlags.cs @@ -0,0 +1,19 @@ +namespace LCU.API.Internal.DocumentIngestor.Configurations; + +public class FeatureFlags +{ + public bool RunBatchIngestionConsumer { get; set; } + public bool RunIngestorIndexConsumer { get; set; } + public bool RunIngestorProcessingConsumer { get; set; } + public bool RunIngestorCompletionConsumer { get; set; } + public bool RunIngestionFolderCleanUpConsumer { get; set; } + public bool RunPdfPartitionerConsumer { get; set; } + public bool RunPdfPartitionerCompletionConsumer { get; set; } + public bool RunUploadCompletionConsumer { get; set; } + public bool RunMemberDocumentNotifierConsumer { get; set; } + public bool RunMemberNotificationCompletionConsumer { get; set; } + public bool RestrictNotificationRecipients { get; set; } + public bool RunGatherMemberNotificationInfoConsumer { get; set; } + public bool RunBatchUpdateMemberNotificationDataConsumer { get; set; } + public bool RunProcessStatusTypeSummaryConsumer { get; set; } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/FileOperationsApiConfiguration.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/FileOperationsApiConfiguration.cs new file mode 100644 index 0000000..0c46584 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/FileOperationsApiConfiguration.cs @@ -0,0 +1,64 @@ +using System.ComponentModel.DataAnnotations.Schema; +namespace LCU.API.Internal.DocumentIngestor.Configurations; + +public class FileOperationsApiConfiguration +{ + public string Url { get; set; } + public string GetFileContentEndpoint { get; set; } + public string GetPdfContentEndpoint { get; set; } + public string ValidateFileExists { get; set; } + public string ValidatePdfPageExists { get; set; } + public string BuildDynamicDirectoryList { get; set; } + public string BuildDynamicFileList { get; set; } + public string QueueBatchPdfParser { get; set; } + public string DirectMoveFile { get; set; } + public string DirectWriteFile { get; set; } + public string DirectCreateDirectory { get; set; } + public string DirectUnzipFile { get; set; } + public string DirectZipFile { get; set; } + public string DirectDeleteDirectory { get; set; } + public string DirectDeleteFile { get; set; } + public int RetryCount { get; set; } + + [NotMapped] + public Uri GetFileContentUri => new Uri(Url + GetFileContentEndpoint); + + [NotMapped] + public Uri GetPdfContentUri => new Uri(Url + GetPdfContentEndpoint); + + [NotMapped] + public Uri ValidateFileExistsUri => new Uri(Url + ValidateFileExists); + + [NotMapped] + public Uri ValidatePdfPageExistsUri => new Uri(Url + ValidatePdfPageExists); + + [NotMapped] + public Uri BuildDynamicDirectoryListUri => new Uri(Url + BuildDynamicDirectoryList); + + [NotMapped] + public Uri BuildDynamicFileListUri => new Uri(Url + BuildDynamicFileList); + + [NotMapped] + public Uri QueueBatchPdfParserUri => new Uri(Url + QueueBatchPdfParser); + + [NotMapped] + public Uri DirectMoveFileUri => new Uri(Url + DirectMoveFile); + + [NotMapped] + public Uri DirectWriteFileUri => new Uri(Url + DirectWriteFile); + + [NotMapped] + public Uri DirectCreateDirectoryUri => new Uri(Url + DirectCreateDirectory); + + [NotMapped] + public Uri DirectUnzipFileUri => new Uri(Url + DirectUnzipFile); + + [NotMapped] + public Uri DirectZipFileUri => new Uri(Url + DirectZipFile); + + [NotMapped] + public Uri DirectDeleteDirectoryUri => new Uri(Url + DirectDeleteDirectory); + + [NotMapped] + public Uri DirectDeleteFileUri => new Uri(Url + DirectDeleteFile); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/MemberPreferencesApiConfiguration.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/MemberPreferencesApiConfiguration.cs new file mode 100644 index 0000000..1f213da --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/MemberPreferencesApiConfiguration.cs @@ -0,0 +1,25 @@ +using System.ComponentModel.DataAnnotations.Schema; +namespace LCU.API.Internal.DocumentIngestor.Configurations; + +public class MemberPreferencesApiConfiguration +{ + public string Url { get; set; } + public string GetMemberOptInAgreementInfoByUserId { get; set; } + public string GetMemberOptInSettingsByUserId { get; set; } + public string EmailSuccessfulSend { get; set; } + public string EmailFailedSend { get; set; } + public int RetryCount { get; set; } + + [NotMapped] + public string GetMemberOptInAgreementInfoByUserIdUrl => Url + GetMemberOptInAgreementInfoByUserId; + + [NotMapped] + public string GetMemberOptInSettingsByUserIdUrl => Url + GetMemberOptInSettingsByUserId; + + [NotMapped] + public string EmailSuccessfulSendUrl => Url + EmailSuccessfulSend; + + [NotMapped] + public string EmailFailedSendUrl => Url + EmailFailedSend; + +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/NotificationApiConfiguration.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/NotificationApiConfiguration.cs new file mode 100644 index 0000000..2ce4cee --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/NotificationApiConfiguration.cs @@ -0,0 +1,12 @@ +using System.ComponentModel.DataAnnotations.Schema; +namespace LCU.API.Internal.DocumentIngestor.Configurations; + +public class NotificationApiConfiguration +{ + public string Url { get; set; } + public string Email { get; set; } + public int RetryCount { get; set; } + + [NotMapped] + public string EmailUrl => Url + Email; +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/Notifications.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/Notifications.cs new file mode 100644 index 0000000..8ac7e93 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/Notifications.cs @@ -0,0 +1,6 @@ +namespace LCU.API.Internal.DocumentIngestor.Configurations; + +public class Notifications +{ + public string? AllowedRecipientExpression { get; set; } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/ReceiveEndpointConfigurations.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/ReceiveEndpointConfigurations.cs new file mode 100644 index 0000000..b438753 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/ReceiveEndpointConfigurations.cs @@ -0,0 +1,19 @@ +using LCU.Library.Internal.LcuMassTransitModels; +namespace LCU.API.Internal.DocumentIngestor.Configurations; + +public class ReceiveEndpointConfigurations +{ + public ReceiveEndpointConfiguration BatchIngestionReceiveEndpoint { get; set; } + public ReceiveEndpointConfiguration DocumentIngestorReceiveEndpoint { get; set; } + public ReceiveEndpointConfiguration DocumentIngestorProcessingReceiveEndpoint { get; set; } + public ReceiveEndpointConfiguration DocumentIngestorCompletionReceiveEndpoint { get; set; } + public ReceiveEndpointConfiguration PdfPartitionerEndpoint { get; set; } + public ReceiveEndpointConfiguration PdfPartitionerCompletionEndpoint { get; set; } + public ReceiveEndpointConfiguration UploadCompletionEndpoint { get; set; } + public ReceiveEndpointConfiguration MemberDocumentNotifierEndpoint { get; set; } + public ReceiveEndpointConfiguration MemberNotificationCompletionEndpoint { get; set; } + public ReceiveEndpointConfiguration IngestionFolderCleanUpReceiveEndpoint { get; set; } + public ReceiveEndpointConfiguration GatherMemberNotificationInfoReceiveEndpoint { get; set; } + public ReceiveEndpointConfiguration BatchUpdateMemberNotificationDataEndpoint { get; set; } + public ReceiveEndpointConfiguration ProcessStatusTypeEmailReceiveEndpoint { get; set; } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/SqlConnectionConfiguration.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/SqlConnectionConfiguration.cs new file mode 100644 index 0000000..4d603d3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Configurations/SqlConnectionConfiguration.cs @@ -0,0 +1,8 @@ +namespace LCU.API.Internal.DocumentIngestor.Configurations; + +public class SqlConnectionConfiguration +{ + public string ConnectionString { get; set; } + public int MaxRetryCount { get; set; } + public TimeSpan MaxRetryDelay { get; set; } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/BatchIngestionConsumer.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/BatchIngestionConsumer.cs new file mode 100644 index 0000000..60070a9 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/BatchIngestionConsumer.cs @@ -0,0 +1,44 @@ +using MassTransit; +using Serilog; +using LCU.Library.Internal.Exceptions; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Consumers; + +public class BatchIngestionConsumer : IConsumer +{ + private readonly IServiceScopeFactory _scopeFactory; + + public BatchIngestionConsumer(IServiceScopeFactory scopeFactory) + { + _scopeFactory = scopeFactory; + } + + public async Task Consume(ConsumeContext context) + { + try + { + Log.Debug("Starting HandleBatchIngestion."); + using var scope = _scopeFactory.CreateScope(); + await Task.Run(async () => await scope.ServiceProvider.GetRequiredService().HandleBatchIngestion(context.Message)); + Log.Debug("Starting HandleBatchIngestion."); + } + catch (ServiceException serviceException) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error(serviceException, $"Batch Ingestion Failure. " + + $"The Batch Ingestion Request is placed on LCU.DocumentIngestor.BatchIngestion_error."); + throw; + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, $"Unexpected Batch Ingestion Failure. " + + $"The Batch Ingestion Request is placed on LCU.DocumentIngestor.BatchIngestion_error."); + throw; + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/BatchUpdateMemberNotificationDataConsumer.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/BatchUpdateMemberNotificationDataConsumer.cs new file mode 100644 index 0000000..5f92624 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/BatchUpdateMemberNotificationDataConsumer.cs @@ -0,0 +1,53 @@ +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using MassTransit; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Consumers; + +public class BatchUpdateMemberNotificationDataConsumer : IConsumer> +{ + private readonly IServiceScopeFactory _scopeFactory; + + public BatchUpdateMemberNotificationDataConsumer(IServiceScopeFactory scopeFactory) + { + _scopeFactory = scopeFactory; + } + + public async Task Consume(ConsumeContext> context) + { + try + { + Log.Debug("Starting BatchUpdateMemberNotificationData"); + using var scope = _scopeFactory.CreateScope(); + + var batchUpdateMemberNotificationDataRequests = new List(); + for (int index = 0; index < context.Message.Length; index++) + { + ConsumeContext messageContext = context.Message[index]; + batchUpdateMemberNotificationDataRequests.Add(messageContext.Message); + } + + await Task.Run(async () => await scope.ServiceProvider.GetRequiredService().HandleBatchUpdateMemberNotificationData(batchUpdateMemberNotificationDataRequests)); + Log.Debug("Ending BatchUpdateMemberNotificationData"); + } + catch (ServiceException serviceException) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error(serviceException, $"Document Ingestor Failure. " + + $"The BatchUpdateMemberNotificationDataRequest is placed on LCU.DocumentIngestor.BatchUpdateMemberNotificationData_error."); + throw; + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, $"Unexpected Document Ingestor Failure. " + + $"The BatchUpdateMemberNotificationDataRequest is placed on LCU.DocumentIngestor.BatchUpdateMemberNotificationData_error."); + throw; + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/GatherMemberNotificationInfoConsumer.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/GatherMemberNotificationInfoConsumer.cs new file mode 100644 index 0000000..a61f16d --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/GatherMemberNotificationInfoConsumer.cs @@ -0,0 +1,45 @@ +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using MassTransit; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Consumers; + +public class GatherMemberNotificationInfoConsumer : IConsumer +{ + private readonly IServiceScopeFactory _scopeFactory; + + public GatherMemberNotificationInfoConsumer(IServiceScopeFactory scopeFactory) + { + _scopeFactory = scopeFactory; + } + + public async Task Consume(ConsumeContext context) + { + try + { + Log.Debug("Starting GatherMemberNotificationInfoRequest"); + using var scope = _scopeFactory.CreateScope(); + await Task.Run(async () => await scope.ServiceProvider.GetRequiredService().HandleMemberNotificationInfoGathering(context.Message)); + Log.Debug("Ending GatherMemberNotificationInfoRequest"); + } + catch (ServiceException serviceException) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error(serviceException, $"Document Ingestor Failure. " + + $"The GatherMemberNotificationInfoRequest is placed on LCU.DocumentIngestor.GatherMemberNotificationInfo_error."); + throw; + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, $"Unexpected Document Ingestor Failure. " + + $"The GatherMemberNotificationInfoRequest is placed on LCU.DocumentIngestor.GatherMemberNotificationInfo_error."); + throw; + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/IngestionFolderCleanUpConsumer.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/IngestionFolderCleanUpConsumer.cs new file mode 100644 index 0000000..9a6764d --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/IngestionFolderCleanUpConsumer.cs @@ -0,0 +1,43 @@ +using MassTransit; +using Serilog; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using LCU.API.Internal.DocumentIngestorLib.Exceptions; +namespace LCU.API.Internal.DocumentIngestor.Consumers; + +public class IngestionFolderCleanUpConsumer : IConsumer +{ + private readonly IServiceScopeFactory _scopeFactory; + + public IngestionFolderCleanUpConsumer(IServiceScopeFactory scopeFactory) + { + _scopeFactory = scopeFactory; + } + + public async Task Consume(ConsumeContext context) + { + try + { + using var scope = _scopeFactory.CreateScope(); + await Task.Run(async () => await scope.ServiceProvider.GetRequiredService().HandleIngestionFolderCleanUp(context.Message)); + } + catch (ServiceException serviceException) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error(serviceException, $"IngestionFolderCleanUp Failure. " + + $"The Processing Request is placed on LCU.DocumentIngestor.IngestionFolderCleanUp_error."); + throw; + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, $"Unexpected IngestionFolderCleanUp Failure. " + + $"The Processing Request is placed on LCU.DocumentIngestor.IngestionFolderCleanUp_error."); + throw; + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/IngestorCompletionConsumer.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/IngestorCompletionConsumer.cs new file mode 100644 index 0000000..e25e31c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/IngestorCompletionConsumer.cs @@ -0,0 +1,52 @@ +using MassTransit; +using Serilog; +using LCU.Library.Internal.Exceptions; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using ApiResponse = LCU.Library.Internal.ApiResponse.Models; +namespace LCU.API.Internal.DocumentIngestor.Consumers; + +public class IngestorCompletionConsumer : IConsumer> +{ + private readonly IServiceScopeFactory _scopeFactory; + + public IngestorCompletionConsumer(IServiceScopeFactory scopeFactory) + { + _scopeFactory = scopeFactory; + } + + public async Task Consume(ConsumeContext> context) + { + try + { + Log.Debug("Starting HandleCompletion"); + using var scope = _scopeFactory.CreateScope(); + + var completionRequests = new List(); + for (int index = 0; index < context.Message.Length; index++) + { + ConsumeContext messageContext = context.Message[index]; + completionRequests.Add(messageContext.Message); + } + + await Task.Run(async () => await scope.ServiceProvider.GetRequiredService().HandleCompletion(completionRequests)); + Log.Debug("Ending HandleCompletion"); + } + catch (ServiceException serviceException) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error(serviceException, $"Document Ingestor Failure. " + + $"The List is placed on LCU.DocumentIngestor.Completion_error."); + throw; + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, $"Unexpected Document Ingestor Failure. " + + $"The List is placed on LCU.DocumentIngestor.Completion_error."); + throw; + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/IngestorIndexConsumer.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/IngestorIndexConsumer.cs new file mode 100644 index 0000000..4458469 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/IngestorIndexConsumer.cs @@ -0,0 +1,44 @@ +using MassTransit; +using Serilog; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +namespace LCU.API.Internal.DocumentIngestor.Consumers; + +public class IngestorIndexConsumer : IConsumer +{ + private readonly IServiceScopeFactory _scopeFactory; + + public IngestorIndexConsumer(IServiceScopeFactory scopeFactory) + { + _scopeFactory = scopeFactory; + } + + public async Task Consume(ConsumeContext context) + { + try + { + Log.Debug("Starting HandleIngestion."); + using var scope = _scopeFactory.CreateScope(); + await Task.Run(async () => await scope.ServiceProvider.GetRequiredService().HandleIngestion(context.Message)); + Log.Debug("Starting HandleIngestion."); + } + catch (ServiceException serviceException) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error(serviceException, $"Document Ingestor Failure. " + + $"The Document Ingestor Request is placed on LCU.DocumentIngestor.Indexing_error."); + throw; + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, $"Unexpected Document Ingestor Failure. " + + $"The Document Upload Request is placed on LCU.DocumentIngestor.Indexing_error."); + throw; + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/IngestorProcessingConsumer.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/IngestorProcessingConsumer.cs new file mode 100644 index 0000000..9f2a513 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/IngestorProcessingConsumer.cs @@ -0,0 +1,50 @@ +using MassTransit; +using Serilog; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using LCU.API.Internal.DocumentIngestorLib.Exceptions; +namespace LCU.API.Internal.DocumentIngestor.Consumers; + +public class IngestorProcessingConsumer : IConsumer +{ + private readonly IServiceScopeFactory _scopeFactory; + + public IngestorProcessingConsumer(IServiceScopeFactory scopeFactory) + { + _scopeFactory = scopeFactory; + } + + public async Task Consume(ConsumeContext context) + { + try + { + using var scope = _scopeFactory.CreateScope(); + await Task.Run(async () => await scope.ServiceProvider.GetRequiredService().HandleProcessing(context.Message)); + } + catch (ArchiveException archiveException) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(archiveException, $"Document Ingestor Failure. Failure to Archive!"); + throw; + } + catch (ServiceException serviceException) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error(serviceException, $"Document Ingestor Failure. " + + $"The Processing Request is placed on LCU.DocumentIngestor.Processing_error."); + throw; + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, $"Unexpected Document Ingestor Failure. " + + $"The Processing Request is placed on LCU.DocumentIngestor.Processing_error."); + throw; + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/MemberDocumentNotifierConsumer.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/MemberDocumentNotifierConsumer.cs new file mode 100644 index 0000000..dedf900 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/MemberDocumentNotifierConsumer.cs @@ -0,0 +1,44 @@ +using MassTransit; +using Serilog; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +namespace LCU.API.Internal.DocumentIngestor.Consumers; + +public class MemberDocumentNotifierConsumer : IConsumer +{ + private readonly IServiceScopeFactory _scopeFactory; + + public MemberDocumentNotifierConsumer(IServiceScopeFactory scopeFactory) + { + _scopeFactory = scopeFactory; + } + + public async Task Consume(ConsumeContext context) + { + try + { + Log.Debug("Starting HandleMemberDocumentNotification"); + using var scope = _scopeFactory.CreateScope(); + await Task.Run(async () => await scope.ServiceProvider.GetRequiredService().HandleMemberDocumentNotification(context.Message)); + Log.Debug("Ending HandleMemberDocumentNotification"); + } + catch (ServiceException serviceException) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error(serviceException, $"Member Document Notifier Failure. " + + $"The request is placed on LCU.DocumentIngestor.MemberDocumentNotifier_error."); + throw; + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, $"Unexpected Member Document Notifier Failure. " + + $"The request is placed on LCU.DocumentIngestor.MemberDocumentNotifier_error."); + throw; + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/MemberNotificationCompletionConsumer.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/MemberNotificationCompletionConsumer.cs new file mode 100644 index 0000000..fabf3da --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/MemberNotificationCompletionConsumer.cs @@ -0,0 +1,44 @@ +using MassTransit; +using Serilog; +using LCU.Library.Internal.Exceptions; +using ApiResponse = LCU.Library.Internal.ApiResponse.Models; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +namespace LCU.API.Internal.DocumentIngestor.Consumers; + +public class MemberNotificationCompletionConsumer : IConsumer +{ + private readonly IServiceScopeFactory _scopeFactory; + + public MemberNotificationCompletionConsumer(IServiceScopeFactory scopeFactory) + { + _scopeFactory = scopeFactory; + } + + public async Task Consume(ConsumeContext context) + { + try + { + Log.Debug("Starting HandleMemberNotificationCompletion"); + using var scope = _scopeFactory.CreateScope(); + await Task.Run(async () => await scope.ServiceProvider.GetRequiredService().HandleMemberNotificationCompletion(context.Message)); + Log.Debug("Ending HandleMemberNotificationCompletion"); + } + catch (ServiceException serviceException) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error(serviceException, "Member Notification Completion Failure. " + + "The request is placed on LCU.DocumentIngestor.MemberNotificationCompletion_error."); + throw; + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, "Unexpected Member Notification Completion Failure. " + + "The request is placed on LCU.DocumentIngestor.MemberNotificationCompletion_error."); + throw; + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/PdfPartitionerCompletionConsumer.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/PdfPartitionerCompletionConsumer.cs new file mode 100644 index 0000000..ae5bf16 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/PdfPartitionerCompletionConsumer.cs @@ -0,0 +1,44 @@ +using MassTransit; +using Serilog; +using LCU.Library.Internal.Exceptions; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using ApiResponse = LCU.Library.Internal.ApiResponse.Models.Response; +namespace LCU.API.Internal.DocumentIngestor.Consumers; + +public class PdfPartitionerCompletionConsumer : IConsumer +{ + private readonly IServiceScopeFactory _scopeFactory; + + public PdfPartitionerCompletionConsumer(IServiceScopeFactory scopeFactory) + { + _scopeFactory = scopeFactory; + } + + public async Task Consume(ConsumeContext context) + { + try + { + Log.Debug("Starting HandlePdfPartitionerCompletion."); + using var scope = _scopeFactory.CreateScope(); + await Task.Run(async () => await scope.ServiceProvider.GetRequiredService().HandlePdfPartitionerCompletion(context.Message)); + Log.Debug("Starting HandlePdfPartitionerCompletion."); + } + catch (ServiceException serviceException) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error(serviceException, $"Handle Pdf Partitioner Completion Failure. " + + $"The Pdf Partitioner Response is placed on LCU.DocumentIngestor.PdfPartitioner.Completion_error."); + throw; + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, $"Unexpected Pdf Partitioner Completion Failure. " + + $"The Pdf Partitioner Response is placed on LCU.DocumentIngestor.PdfPartitioner.Completion_error."); + throw; + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/PdfPartitionerConsumer.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/PdfPartitionerConsumer.cs new file mode 100644 index 0000000..2b01039 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/PdfPartitionerConsumer.cs @@ -0,0 +1,44 @@ +using MassTransit; +using Serilog; +using LCU.Library.Internal.Exceptions; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Consumers; + +public class PdfPartitionerConsumer : IConsumer +{ + private readonly IServiceScopeFactory _scopeFactory; + + public PdfPartitionerConsumer(IServiceScopeFactory scopeFactory) + { + _scopeFactory = scopeFactory; + } + + public async Task Consume(ConsumeContext context) + { + try + { + Log.Debug("Starting HandlePdfPartitioner."); + using var scope = _scopeFactory.CreateScope(); + await Task.Run(async () => await scope.ServiceProvider.GetRequiredService().HandlePdfPartition(context.Message)); + Log.Debug("Starting HandleIngestorPdfPartitioner."); + } + catch (ServiceException serviceException) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error(serviceException, $"Handle Pdf Partitioner Failure. " + + $"The Pdf Partitioner Request is placed on LCU.DocumentIngestor.PdfPartitioner_error."); + throw; + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, $"Unexpected Pdf Partitioner Failure. " + + $"The Pdf Partitioner Request is placed on LCU.DocumentIngestor.PdfPartitioner_error."); + throw; + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/ProcessStatusTypeEmailConsumer.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/ProcessStatusTypeEmailConsumer.cs new file mode 100644 index 0000000..6fc0926 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/ProcessStatusTypeEmailConsumer.cs @@ -0,0 +1,35 @@ +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using LCU.Library.Internal.DocumentIngestorModels.Requests; +using MassTransit; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Consumers; + +public class ProcessStatusTypeEmailConsumer : IConsumer +{ + private readonly IServiceScopeFactory _scopeFactory; + + public ProcessStatusTypeEmailConsumer(IServiceScopeFactory scopeFactory) + { + _scopeFactory = scopeFactory; + } + + public async Task Consume(ConsumeContext context) + { + try + { + Log.Information("ProcessStatusType Email Consumer Listening"); + using var scope = _scopeFactory.CreateScope(); + await Task.Run(() => scope.ServiceProvider.GetRequiredService().HandleProcessStatusTypeEmailRequest(context.Message)); + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, $"Unexpected Process Status Email Consumer Failure. " + + $"The List is placed on LCU.DocumentIngestor.ProcessStatusTypeEmail."); + throw; + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/UploadCompletionConsumer.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/UploadCompletionConsumer.cs new file mode 100644 index 0000000..bec0155 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Consumers/UploadCompletionConsumer.cs @@ -0,0 +1,61 @@ +using MassTransit; +using Serilog; +using LCU.Library.Internal.Exceptions; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using ApiResponse = LCU.Library.Internal.ApiResponse.Models; +using LCU.API.Internal.DocumentIngestorLib.Exceptions; +using Response = LCU.Library.Internal.ApiResponse.Models.Response; +namespace LCU.API.Internal.DocumentIngestor.Consumers; + +public class UploadCompletionConsumer : IConsumer> +{ + private readonly IServiceScopeFactory _scopeFactory; + + public UploadCompletionConsumer(IServiceScopeFactory scopeFactory) + { + _scopeFactory = scopeFactory; + } + + public async Task Consume(ConsumeContext> context) + { + try + { + Log.Debug("Starting HandleUploadCompletion"); + using var scope = _scopeFactory.CreateScope(); + + var uploadCompletionRequests = new List(); + for (int index = 0; index < context.Message.Length; index++) + { + ConsumeContext messageContext = context.Message[index]; + uploadCompletionRequests.Add(messageContext.Message); + } + + await Task.Run(async () => await scope.ServiceProvider.GetRequiredService().HandleUploadCompletion(uploadCompletionRequests)); + Log.Debug("Ending HandleUploadCompletion"); + } + catch (ArchiveException archiveException) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(archiveException, $"Upload Completion Failure. Failure to Archive!"); + throw; + } + catch (ServiceException serviceException) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error(serviceException, $"Upload Completion Failure. " + + $"The List is placed on LCU.DocumentIngestor.UploadCompletion_error."); + throw; + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, $"Unexpected Upload Completion Failure. " + + $"The List is placed on LCU.DocumentIngestor.UploadCompletion_error."); + throw; + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/BatchIngestionController.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/BatchIngestionController.cs new file mode 100644 index 0000000..8e78315 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/BatchIngestionController.cs @@ -0,0 +1,40 @@ +using Microsoft.AspNetCore.Mvc; +using Serilog; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +namespace LCU.API.Internal.DocumentIngestor.Controllers; + +[ApiController] +[Route("[controller]")] +public class BatchIngestionController : ControllerBase +{ + private readonly IQueueBatchIngestionService _queueBatchIngestionService; + + public BatchIngestionController(IQueueBatchIngestionService queueBatchIngestionService) + { + _queueBatchIngestionService = queueBatchIngestionService; + } + + [HttpPost("QueueBatchIngestion")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public async Task QueueBatchIngestion([FromBody] BatchIngestionRequest request) + { + try + { + await _queueBatchIngestionService.QueueBatchIngestionRequest(request); + 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.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/DocumentIngestorController.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/DocumentIngestorController.cs new file mode 100644 index 0000000..f5f1180 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/DocumentIngestorController.cs @@ -0,0 +1,41 @@ +using Microsoft.AspNetCore.Mvc; +using Serilog; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +namespace LCU.API.Internal.DocumentIngestor.Controllers; + +[ApiController] +[Route("[controller]")] +public class DocumentIngestorController : ControllerBase +{ + private readonly IQueueDocumentIngestorService _queueDocumentIngestorService; + + public DocumentIngestorController(IQueueDocumentIngestorService queueDocumentIngestorService) + { + _queueDocumentIngestorService = queueDocumentIngestorService; + } + + [HttpPost("QueueDocumentIngestor")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public async Task QueueDocumentIngestor([FromBody] IngestorRequest request) + { + try + { + await _queueDocumentIngestorService.QueueDocumentIngestorRequest(request); + 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.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/DocumentProcessingInfoController.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/DocumentProcessingInfoController.cs new file mode 100644 index 0000000..b72f81a --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/DocumentProcessingInfoController.cs @@ -0,0 +1,292 @@ +using Serilog; +using Microsoft.AspNetCore.Mvc; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; + +namespace LCU.API.Internal.DocumentIngestor.Controllers; + +[ApiController] +[Route("[controller]")] +public class DocumentProcessingInfoController : ControllerBase +{ + private readonly IDocumentProcessingInfoService _documentProcessingInfoService; + + public DocumentProcessingInfoController(IDocumentProcessingInfoService documentProcessingInfoService) + { + _documentProcessingInfoService = documentProcessingInfoService; + } + + [HttpGet()] + [ProducesResponseType(200)] + [ProducesResponseType(204)] + [ProducesResponseType(typeof(DocumentProcessingInfo), 400)] + [ProducesResponseType(500)] + public async Task Get() + { + try + { + var result = await _documentProcessingInfoService.GetAsync(); + if (result == null || !result.Any()) + { + return NoContent(); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpGet("{id:int}")] + [ProducesResponseType(200)] + [ProducesResponseType(204)] + [ProducesResponseType(typeof(DocumentProcessingInfo), 400)] + [ProducesResponseType(500)] + public async Task GetById(int id) + { + try + { + if (id <= 0) + { + return BadRequest($"Id {id} is invalid."); + } + + var result = await _documentProcessingInfoService.GetByIdAsync(id); + if (result == null) + { + return NoContent(); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("ByDocumentId")] + [ProducesResponseType(typeof(IDictionary), 200)] + [ProducesResponseType(500)] + public async Task GetByDocumentIds([FromBody]Guid[] ids) + { + try + { + var result = await _documentProcessingInfoService.GetByDocumentIdsAsync(ids); + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpGet("GetByIngestorRunInfoId/{ingestorRunInfoId:guid}")] + [ProducesResponseType(200)] + [ProducesResponseType(204)] + [ProducesResponseType(typeof(DocumentProcessingInfo), 400)] + [ProducesResponseType(500)] + public async Task GetByIngestorRunInfoId(Guid ingestorRunInfoId) + { + try + { + if (ingestorRunInfoId == Guid.Empty) + { + return BadRequest($"IngestorRunInfoId {ingestorRunInfoId} is invalid."); + } + + var result = await _documentProcessingInfoService.GetByIngestorRunInfoIdAsync(ingestorRunInfoId); + if (result == null || !result.Any()) + { + return NoContent(); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost] + [ProducesResponseType(201)] + [ProducesResponseType(typeof(DocumentProcessingInfo), 400)] + [ProducesResponseType(500)] + public async Task Post([FromBody] DocumentProcessingInfo documentProcessingInfo) + { + try + { + var result = await _documentProcessingInfoService.SaveAsync(documentProcessingInfo); + return CreatedAtAction(nameof(GetById), new { id = result.DocumentProcessingInfoId }, result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPut()] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(404)] + [ProducesResponseType(500)] + public async Task Put([FromBody] DocumentProcessingInfo documentProcessingInfo) + { + try + { + var result = await _documentProcessingInfoService.Update(documentProcessingInfo); + if (result == null) + { + return NotFound($"The DocumentProcessingInfo with " + + $"DocumentProcessingInfoId:{documentProcessingInfo.DocumentProcessingInfoId} " + + $"could not be found."); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpDelete("{id:int}")] + [ProducesResponseType(200)] + [ProducesResponseType(500)] + public async Task Delete(int id) + { + try + { + await _documentProcessingInfoService.Delete(id); + return Ok(); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("GetFilteredDocumentProcessingInfo")] + [ProducesResponseType(typeof(PagedResponse), 200)] + [ProducesResponseType(500)] + public async Task GetFilteredDocumentProcessingInfo([FromBody] Filter filter) + { + try + { + var filterResult = await _documentProcessingInfoService.GetFilteredDocumentProcessingInfo(filter); + var result = new PagedResponse(filterResult, filter); + return Ok(result); + } + catch (ServiceException) + { + return StatusCode(StatusCodes.Status500InternalServerError); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("SetDocumentsToEntityUnknown")] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(404)] + [ProducesResponseType(500)] + public async Task SetDocumentsToEntityUnknown(EntityUnknownRequest request) + { + try + { + var results = await _documentProcessingInfoService.SetDocumentsToEntityUnknown(request); + + if (!results.Any()) + { + return NoContent(); + } + + return Ok(results); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + + [HttpPost("UpdateStatus")] + [ProducesResponseType(typeof(DocumentProcessingInfo), 200)] + [ProducesResponseType(204)] + [ProducesResponseType(400)] + [ProducesResponseType(404)] + [ProducesResponseType(500)] + public async Task UpdateDocumentProcessingInfoStatus(DocumentProcessingInfoStatusRequest request) + { + try + { + var result = await _documentProcessingInfoService.UpdateDocumentProcessingInfoStatus(request); + + if (result is null) + { + return NoContent(); + } + + return Ok(result); + } + 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.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/DocumentReprocessingController.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/DocumentReprocessingController.cs new file mode 100644 index 0000000..8602166 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/DocumentReprocessingController.cs @@ -0,0 +1,111 @@ +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.Library.Internal.ApiSecurity.Attributes; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +using Microsoft.AspNetCore.Mvc; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Controllers; + +[ApiController] +[Route("[controller]")] +public class DocumentReprocessingController : ControllerBase +{ + private readonly IDocumentReprocessingService _reprocessingService; + + public DocumentReprocessingController(IDocumentReprocessingService reprocessingService) + { + _reprocessingService = reprocessingService; + } + + [ApiKey] + [HttpPost("QueueReprocessDocumentByDocumentProcessingInfoId/{documentProcessingInfoId:int}/{userName}")] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(404)] + [ProducesResponseType(500)] + public async Task QueueReprocessDocumentByDocumentProcessingInfoId(int documentProcessingInfoId, string userName) + { + try + { + if (documentProcessingInfoId <= 0 || string.IsNullOrWhiteSpace(userName)) + { + return BadRequest($"documentProcessingInfoId and userName are required."); + } + + await _reprocessingService.QueueReprocessDocumentByDocumentProcessingInfoId(documentProcessingInfoId, userName); + return Accepted(); + } + catch (ArgumentNullException exception) + { + return StatusCode(StatusCodes.Status404NotFound, exception.Message); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [ApiKey] + [HttpPost("QueueOverrideDocumentByDocumentProcessingInfoId")] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(404)] + [ProducesResponseType(500)] + public async Task QueueOverrideDocumentByDocumentProcessingInfoId(OwnerOverrideInfo ownerOverrideRequest) + { + try + { + await _reprocessingService.QueueOverrideDocumentByDocumentProcessingInfoId(ownerOverrideRequest); + return Accepted(); + } + catch (ArgumentNullException exception) + { + return StatusCode(StatusCodes.Status404NotFound, exception.Message); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [ApiKey] + [HttpPost("QueueReprocessAllCriticalFailures/{userName}")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(404)] + [ProducesResponseType(500)] + public async Task QueueReprocessAllCriticalFailures(string userName) + { + try + { + if (string.IsNullOrWhiteSpace(userName)) + { + return BadRequest($"UserName is required."); + } + + await _reprocessingService.QueueReprocessAllCriticalFailures(userName); + 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.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/DocumentTypeArchiveDeleteInfoController.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/DocumentTypeArchiveDeleteInfoController.cs new file mode 100644 index 0000000..c1e9a5d --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/DocumentTypeArchiveDeleteInfoController.cs @@ -0,0 +1,159 @@ +using Serilog; +using Microsoft.AspNetCore.Mvc; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; + +namespace LCU.API.Internal.DocumentIngestor.Controllers; + +[Obsolete] +[ApiController] +[Route("[controller]")] +public class DocumentTypeArchiveDeleteInfoController : ControllerBase +{ + private readonly IDocumentTypeArchiveDeleteInfoService _documentTypeArchiveDeleteInfoService; + + public DocumentTypeArchiveDeleteInfoController(IDocumentTypeArchiveDeleteInfoService documentTypeArchiveDeleteInfoService) + { + _documentTypeArchiveDeleteInfoService = documentTypeArchiveDeleteInfoService; + } + + [HttpGet()] + [ProducesResponseType(200)] + [ProducesResponseType(204)] + [ProducesResponseType(typeof(DocumentTypeArchiveDeleteInfo), 400)] + [ProducesResponseType(500)] + public async Task Get() + { + try + { + var result = await _documentTypeArchiveDeleteInfoService.GetAsync(); + if (result == null || !result.Any()) + { + return NoContent(); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpGet("GetByDocumentTypeName/{documentTypeName}")] + [ProducesResponseType(200)] + [ProducesResponseType(204)] + [ProducesResponseType(typeof(DocumentTypeArchiveDeleteInfo), 400)] + [ProducesResponseType(500)] + public async Task GetByDocumentTypeName(string documentTypeName) + { + try + { + if (string.IsNullOrWhiteSpace(documentTypeName)) + { + return BadRequest($"DocumentTypeName {documentTypeName} is invalid."); + } + + var result = await _documentTypeArchiveDeleteInfoService.GetByDocumentTypeNameAsync(documentTypeName); + if (result == null) + { + return NoContent(); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost] + [ProducesResponseType(201)] + [ProducesResponseType(typeof(DocumentTypeArchiveDeleteInfo), 400)] + [ProducesResponseType(500)] + public async Task Post([FromBody] DocumentTypeArchiveDeleteInfo documentTypeArchiveDeleteInfo) + { + try + { + var result = await _documentTypeArchiveDeleteInfoService.SaveAsync(documentTypeArchiveDeleteInfo); + return CreatedAtAction(nameof(GetByDocumentTypeName), new { documentTypeName = result.DocumentTypeName }, result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPut()] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(404)] + [ProducesResponseType(500)] + public async Task Put([FromBody] DocumentTypeArchiveDeleteInfo documentTypeArchiveDeleteInfo) + { + try + { + var result = await _documentTypeArchiveDeleteInfoService.Update(documentTypeArchiveDeleteInfo); + if (result == null) + { + return NotFound($"The DocumentTypeArchiveDeleteInfo with " + + $"DocumentTypeName: {documentTypeArchiveDeleteInfo.DocumentTypeName} " + + $"could not be found."); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpDelete("{documentTypeName}")] + [ProducesResponseType(200)] + [ProducesResponseType(500)] + public async Task Delete(string documentTypeName) + { + try + { + if (string.IsNullOrWhiteSpace(documentTypeName)) + { + return BadRequest($"DocumentTypeName {documentTypeName} is invalid."); + } + + await _documentTypeArchiveDeleteInfoService.Delete(documentTypeName); + return Ok(); + } + 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.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/IngestionFolderCleanUpController.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/IngestionFolderCleanUpController.cs new file mode 100644 index 0000000..d9a5ebc --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/IngestionFolderCleanUpController.cs @@ -0,0 +1,48 @@ +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.Library.Internal.ApiSecurity.Attributes; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using Microsoft.AspNetCore.Mvc; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Controllers; + +[ApiController] +[Route("[controller]")] +public class IngestionFolderCleanUpController : ControllerBase +{ + private readonly IQueueIngestionFolderCleanUpService _queueIngestionFolderCleanUpService; + public IngestionFolderCleanUpController(IQueueIngestionFolderCleanUpService queueIngestionFolderCleanUpService) + { + _queueIngestionFolderCleanUpService = queueIngestionFolderCleanUpService; + } + + [HttpPost("QueueIngestionFolderCleanUp")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public async Task QueueIngestionFolderCleanUp([FromBody] IngestionFolderCleanUpRequest request) + { + try + { + if (string.IsNullOrWhiteSpace(request.ArchiveRootPath)) + { + return BadRequest($"ArchiveRootPath is required."); + } + + await _queueIngestionFolderCleanUpService.QueueIngestionFolderCleanUpRequest(request); + 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.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/IngestorRunInfoController.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/IngestorRunInfoController.cs new file mode 100644 index 0000000..980fa4c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/IngestorRunInfoController.cs @@ -0,0 +1,118 @@ +using Serilog; +using Microsoft.AspNetCore.Mvc; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +namespace LCU.API.Internal.DocumentIngestor.Controllers; + +[ApiController] +[Route("[controller]")] +public class IngestorRunInfoController : ControllerBase +{ + private readonly IIngestorRunInfoService _ingestorRunInfoService; + + public IngestorRunInfoController(IIngestorRunInfoService ingestorRunInfoService) + { + _ingestorRunInfoService = ingestorRunInfoService; + } + + [HttpGet("{ingestorRunInfoId:guid}")] + [ProducesResponseType(200)] + [ProducesResponseType(204)] + [ProducesResponseType(typeof(IngestorRunInfo), 400)] + [ProducesResponseType(500)] + public async Task GetByIngestorRunInfoId(Guid ingestorRunInfoId) + { + try + { + var result = await _ingestorRunInfoService.GetByIdAsync(ingestorRunInfoId); + if (result == null) + { + return NoContent(); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost] + [ProducesResponseType(200)] + [ProducesResponseType(typeof(IngestorRunInfo), 400)] + [ProducesResponseType(500)] + public async Task Post([FromBody] IngestorRunInfo ingestorRunInfo) + { + try + { + var result = await _ingestorRunInfoService.SaveAsync(ingestorRunInfo); + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPut()] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(404)] + [ProducesResponseType(500)] + public async Task Put([FromBody] IngestorRunInfo ingestorRunInfo) + { + try + { + var result = await _ingestorRunInfoService.Update(ingestorRunInfo); + if (result == null) + { + return NotFound($"The ingestorRunInfo with IngestorRunInfoId:{ingestorRunInfo.IngestorRunInfoId} " + + $"could not be found."); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpDelete("{ingestorRunInfoId:guid}")] + [ProducesResponseType(200)] + [ProducesResponseType(500)] + public async Task Delete(Guid ingestorRunInfoId) + { + try + { + await _ingestorRunInfoService.Delete(ingestorRunInfoId); + return Ok(); + } + 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.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/MemberDocumentNotifierController.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/MemberDocumentNotifierController.cs new file mode 100644 index 0000000..ff9e68d --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/MemberDocumentNotifierController.cs @@ -0,0 +1,40 @@ +using Microsoft.AspNetCore.Mvc; +using Serilog; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +namespace LCU.API.Internal.DocumentIngestor.Controllers; + +[ApiController] +[Route("[controller]")] +public class MemberDocumentNotifierController : ControllerBase +{ + private readonly IQueueMemberDocumentNotifierService _queueMemberDocumentNotifierService; + + public MemberDocumentNotifierController(IQueueMemberDocumentNotifierService queueMemberDocumentNotifierService) + { + _queueMemberDocumentNotifierService = queueMemberDocumentNotifierService; + } + + [HttpPost("QueueMemberDocumentNotifier")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public async Task QueueMemberDocumentNotifier([FromBody] MemberDocumentNotificationRequest memberDocumentNotificationRequest) + { + try + { + await _queueMemberDocumentNotifierService.QueueMemberDocumentNotifierRequest(memberDocumentNotificationRequest); + 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.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/MemberNotificationInfoController.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/MemberNotificationInfoController.cs new file mode 100644 index 0000000..570e5e5 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/MemberNotificationInfoController.cs @@ -0,0 +1,330 @@ +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Security; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.Api.Internal.DocumentIngestorLib.Extensions; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Controllers; + +[ApiController] +[Route("[controller]")] +public class MemberNotificationInfoController : ControllerBase +{ + private readonly IMemberNotificationInfoService _memberNotificationInfoService; + private readonly ApiConfiguration _apiConfiguration; + + public MemberNotificationInfoController(IMemberNotificationInfoService memberNotificationInfoService, + ApiConfiguration apiConfiguration) + { + _memberNotificationInfoService = memberNotificationInfoService; + _apiConfiguration = apiConfiguration; + } + + [HttpGet()] + [ProducesResponseType(200)] + [ProducesResponseType(204)] + [ProducesResponseType(typeof(MemberNotificationInfo), 400)] + [ProducesResponseType(500)] + public async Task Get() + { + try + { + var result = await _memberNotificationInfoService.GetAsync(); + if (result == null || !result.Any()) + { + return NoContent(); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpGet("{id:int}")] + [ProducesResponseType(200)] + [ProducesResponseType(204)] + [ProducesResponseType(typeof(MemberNotificationInfo), 400)] + [ProducesResponseType(500)] + public async Task GetById(int id) + { + try + { + if (id <= 0) + { + return BadRequest($"Id {id} is invalid."); + } + + var result = await _memberNotificationInfoService.GetByIdAsync(id); + if (result == null) + { + return NoContent(); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpGet("GetByDocumentProcessingInfoId/{documentProcessingInfoId:int}")] + [ProducesResponseType(200)] + [ProducesResponseType(204)] + [ProducesResponseType(typeof(IEnumerable), 400)] + [ProducesResponseType(500)] + public async Task GetByDocumentProcessingInfoId(int documentProcessingInfoId) + { + try + { + if (documentProcessingInfoId <= 0) + { + return BadRequest($"DocumentProcessingInfoId {documentProcessingInfoId} is invalid."); + } + + var result = await _memberNotificationInfoService.GetByDocumentProcessingInfoIdAsync(documentProcessingInfoId); + if (result == null || !result.Any()) + { + return NoContent(); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost] + [ProducesResponseType(201)] + [ProducesResponseType(typeof(MemberNotificationInfo), 400)] + [ProducesResponseType(500)] + public async Task Post([FromBody] MemberNotificationInfo memberNotificationInfo) + { + try + { + var result = await _memberNotificationInfoService.SaveAsync(memberNotificationInfo); + return CreatedAtAction(nameof(GetById), new { id = result.DocumentProcessingInfoId }, result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPut()] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(404)] + [ProducesResponseType(500)] + public async Task Put([FromBody] MemberNotificationInfo memberNotificationInfo) + { + try + { + var result = await _memberNotificationInfoService.Update(memberNotificationInfo); + if (result == null) + { + return NotFound($"The MemberNotificationInfo with " + + $"MemberNotificationInfoId:{memberNotificationInfo.MemberNotificationInfoId} " + + $"could not be found."); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPut("UpdateRange")] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(404)] + [ProducesResponseType(500)] + public async Task Put([FromBody] List memberNotificationInfos) + { + try + { + var result = await _memberNotificationInfoService.UpdateRange(memberNotificationInfos); + if (result == null) + { + return NotFound($"MemberNotificationInfos could not be found."); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpDelete("{id:int}")] + [ProducesResponseType(200)] + [ProducesResponseType(500)] + public async Task Delete(int id) + { + try + { + if (id <= 0) + { + return BadRequest($"MemberNotificationInfoId {id} is invalid."); + } + + await _memberNotificationInfoService.Delete(id); + return Ok(); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("GetByNotificationStatus")] + [ProducesResponseType(typeof(IEnumerable), 200)] + [ProducesResponseType(500)] + public async Task GetByNotificationStatus(NotificationStatusTypes status) + { + try + { + var result = await _memberNotificationInfoService.GetByNotificationStatusAsync(status); + return Ok(result); + } + catch (ServiceException) + { + return StatusCode(StatusCodes.Status500InternalServerError); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost("GetSendableMemberNotificationInfos")] + [ProducesResponseType(typeof(IEnumerable), 200)] + [ProducesResponseType(500)] + public async Task GetSendableMemberNotificationInfos(DateTime minimumUploadDate) + { + try + { + var uploadDate = minimumUploadDate.ConvertToTimeZone(_apiConfiguration.TimeZone); + var result = await _memberNotificationInfoService.GetSendableMemberNotificationInfosAsync(uploadDate, + _apiConfiguration.MaxMemberNotificationAttempts); + return Ok(result); + } + catch (ServiceException) + { + return StatusCode(StatusCodes.Status500InternalServerError); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [Authorize(SetDocumentNotificationStatusPolicy.Name)] + [HttpPut("{memberNotificationInfoId:int}/{notificationStatus}")] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(401)] + [ProducesResponseType(500)] + public async Task SetDocumentNotificationStatus(int memberNotificationInfoId, NotificationStatusTypes notificationStatus, [FromBody]string reason) + { + try + { + var userName = HttpContext.User.Claims.Single(c => c.Type == "name").Value; + if (!await _memberNotificationInfoService.SetDocumentNotificationStatus(memberNotificationInfoId, notificationStatus, userName, reason)) + { + return BadRequest(); + } + + return Ok(); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [Authorize(SetDocumentNotificationStatusPolicy.Name)] + [HttpPut("BulkSetDocumentNotificationStatus")] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(401)] + [ProducesResponseType(500)] + public async Task BulkSetDocumentNotificationStatus([FromBody] BulkNotificationStatusRequest request) + { + try + { + var userName = HttpContext.User.Claims.Single(c => c.Type == "name").Value; + if (!await _memberNotificationInfoService.BulkSetDocumentNotificationStatus(request, userName)) + { + return BadRequest(); + } + + return Ok(); + } + 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.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/OsgPreprocessorController.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/OsgPreprocessorController.cs new file mode 100644 index 0000000..5c8e900 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/OsgPreprocessorController.cs @@ -0,0 +1,44 @@ +using Microsoft.AspNetCore.Mvc; +using Serilog; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +namespace LCU.API.Internal.DocumentIngestor.Controllers; + +[Obsolete("06/02/2023 - Used to prepare historical documents for ingestion. No longer in use.")] +[ApiController] +[Route("[controller]")] +public class OsgPreprocessorController : ControllerBase +{ + private readonly IOsgPreprocessorService _osgPreprocessorService; + + public OsgPreprocessorController(IOsgPreprocessorService osgPreprocessorService) + { + _osgPreprocessorService = osgPreprocessorService; + } + + [HttpPost("PreprocessOsgIndexFile")] + [ProducesResponseType(202)] + [ProducesResponseType(204)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public async Task PreprocessOsgIndexFile([FromBody] OsgPreprocessorRequest request) + { + try + { + await _osgPreprocessorService.HandleOsgPreprocessing(request); + 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.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/PdfPartitionerController.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/PdfPartitionerController.cs new file mode 100644 index 0000000..9936fed --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/PdfPartitionerController.cs @@ -0,0 +1,40 @@ +using Microsoft.AspNetCore.Mvc; +using Serilog; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +namespace LCU.API.Internal.DocumentIngestor.Controllers; + +[ApiController] +[Route("[controller]")] +public class PdfPartitionerController : ControllerBase +{ + private readonly IQueuePdfPartitionerService _queuePdfPartitionerService; + + public PdfPartitionerController(IQueuePdfPartitionerService queuePdfPartitionerService) + { + _queuePdfPartitionerService = queuePdfPartitionerService; + } + + [HttpPost("QueueIngestorPdfPartitioner")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public async Task QueueIngestorPdfPartitioner([FromBody] PdfPartitionerRequest request) + { + try + { + await _queuePdfPartitionerService.QueuePdfPartitionerRequest(request); + 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.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/PdfPartitionerLogController.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/PdfPartitionerLogController.cs new file mode 100644 index 0000000..30361d0 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/PdfPartitionerLogController.cs @@ -0,0 +1,150 @@ +using Serilog; +using Microsoft.AspNetCore.Mvc; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +namespace LCU.API.Internal.DocumentIngestor.Controllers; + +[ApiController] +[Route("[controller]")] +public class PdfPartitionerLogController : ControllerBase +{ + private readonly IPdfPartitionerLogService _pdfPartitionerLogServiceService; + + public PdfPartitionerLogController(IPdfPartitionerLogService pdfPartitionerLogServiceService) + { + _pdfPartitionerLogServiceService = pdfPartitionerLogServiceService; + } + + [HttpGet()] + [ProducesResponseType(200)] + [ProducesResponseType(204)] + [ProducesResponseType(typeof(PdfPartitionerLog), 400)] + [ProducesResponseType(500)] + public async Task Get() + { + try + { + var result = await _pdfPartitionerLogServiceService.GetAsync(); + if (result == null || !result.Any()) + { + return NoContent(); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpGet("{id:int}")] + [ProducesResponseType(200)] + [ProducesResponseType(204)] + [ProducesResponseType(typeof(PdfPartitionerLog), 400)] + [ProducesResponseType(500)] + public async Task GetById(int id) + { + try + { + if (id <= 0) + { + return BadRequest($"Id {id} is invalid."); + } + + var result = await _pdfPartitionerLogServiceService.GetByIdAsync(id); + if (result == null) + { + return NoContent(); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpGet("GetByPdfPartitionerRunInfoId/{pdfPartitionerRunInfoId:guid}")] + [ProducesResponseType(200)] + [ProducesResponseType(204)] + [ProducesResponseType(typeof(PdfPartitionerLog), 400)] + [ProducesResponseType(500)] + public async Task GetByPdfPartitionerRunInfoId(Guid pdfPartitionerRunInfoId) + { + try + { + var result = await _pdfPartitionerLogServiceService.GetByPdfPartitionerRunInfoIdAsync(pdfPartitionerRunInfoId); + if (result == null || !result.Any()) + { + return NoContent(); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost] + [ProducesResponseType(201)] + [ProducesResponseType(typeof(PdfPartitionerLog), 400)] + [ProducesResponseType(500)] + public async Task Post([FromBody] PdfPartitionerLog pdfPartitionerLog) + { + try + { + var result = await _pdfPartitionerLogServiceService.SaveAsync(pdfPartitionerLog); + return CreatedAtAction(nameof(GetById), new { id = result.PdfPartitionerLogId }, result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpDelete("{id:int}")] + [ProducesResponseType(200)] + [ProducesResponseType(500)] + public async Task Delete(int id) + { + try + { + await _pdfPartitionerLogServiceService.Delete(id); + return Ok(); + } + 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.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/PdfPartitionerRunInfoController.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/PdfPartitionerRunInfoController.cs new file mode 100644 index 0000000..3d11f01 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/PdfPartitionerRunInfoController.cs @@ -0,0 +1,118 @@ +using Serilog; +using Microsoft.AspNetCore.Mvc; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +namespace LCU.API.Internal.DocumentIngestor.Controllers; + +[ApiController] +[Route("[controller]")] +public class PdfPartitionerRunInfoController : ControllerBase +{ + private readonly IPdfPartitionerRunInfoService _pdfPartitionerRunInfoService; + + public PdfPartitionerRunInfoController(IPdfPartitionerRunInfoService pdfPartitionerRunInfoService) + { + _pdfPartitionerRunInfoService = pdfPartitionerRunInfoService; + } + + [HttpGet("{pdfPartitionerRunInfoId:guid}")] + [ProducesResponseType(200)] + [ProducesResponseType(204)] + [ProducesResponseType(typeof(PdfPartitionerRunInfo), 400)] + [ProducesResponseType(500)] + public async Task GetByPdfPartitionerRunInfoId(Guid pdfPartitionerRunInfoId) + { + try + { + var result = await _pdfPartitionerRunInfoService.GetByIdAsync(pdfPartitionerRunInfoId); + if (result == null) + { + return NoContent(); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost] + [ProducesResponseType(200)] + [ProducesResponseType(typeof(PdfPartitionerRunInfo), 400)] + [ProducesResponseType(500)] + public async Task Post([FromBody] PdfPartitionerRunInfo pdfPartitionerRunInfo) + { + try + { + var result = await _pdfPartitionerRunInfoService.SaveAsync(pdfPartitionerRunInfo); + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPut()] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(404)] + [ProducesResponseType(500)] + public async Task Put([FromBody] PdfPartitionerRunInfo pdfPartitionerRunInfo) + { + try + { + var result = await _pdfPartitionerRunInfoService.Update(pdfPartitionerRunInfo); + if (result == null) + { + return NotFound($"The pdfPartitionerRunInfo with PdfPartitionerRunInfoId:{pdfPartitionerRunInfo.PdfPartitionerRunInfoId} " + + $"could not be found."); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpDelete("{pdfPartitionerRunInfoId:guid}")] + [ProducesResponseType(200)] + [ProducesResponseType(500)] + public async Task Delete(Guid pdfPartitionerRunInfoId) + { + try + { + await _pdfPartitionerRunInfoService.Delete(pdfPartitionerRunInfoId); + return Ok(); + } + 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.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/ProcessingLogController.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/ProcessingLogController.cs new file mode 100644 index 0000000..cde991b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/ProcessingLogController.cs @@ -0,0 +1,185 @@ +using Serilog; +using Microsoft.AspNetCore.Mvc; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +namespace LCU.API.Internal.DocumentIngestor.Controllers; + +[ApiController] +[Route("[controller]")] +public class ProcessingLogController : ControllerBase +{ + private readonly IProcessingLogService _processingLogService; + + public ProcessingLogController(IProcessingLogService processingLogService) + { + _processingLogService = processingLogService; + } + + [HttpGet()] + [ProducesResponseType(200)] + [ProducesResponseType(204)] + [ProducesResponseType(typeof(ProcessingLog), 400)] + [ProducesResponseType(500)] + public async Task Get() + { + try + { + var result = await _processingLogService.GetAsync(); + if (result == null || !result.Any()) + { + return NoContent(); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpGet("{id:int}")] + [ProducesResponseType(200)] + [ProducesResponseType(204)] + [ProducesResponseType(typeof(ProcessingLog), 400)] + [ProducesResponseType(500)] + public async Task GetById(int id) + { + try + { + if (id <= 0) + { + return BadRequest($"Id {id} is invalid."); + } + + var result = await _processingLogService.GetByIdAsync(id); + if (result == null) + { + return NoContent(); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpGet("GetByDocumentProcessingInfoId/{documentProcessingInfoId:int}")] + [ProducesResponseType(200)] + [ProducesResponseType(204)] + [ProducesResponseType(typeof(ProcessingLog), 400)] + [ProducesResponseType(500)] + public async Task GetByDocumentProcessingInfoId(int documentProcessingInfoId) + { + try + { + if (documentProcessingInfoId <= 0) + { + return BadRequest($"DocumentProcessingInfoId {documentProcessingInfoId} is invalid."); + } + + var result = await _processingLogService.GetByDocumentProcessingInfoIdAsync(documentProcessingInfoId); + if (result == null || !result.Any()) + { + return NoContent(); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPost] + [ProducesResponseType(201)] + [ProducesResponseType(typeof(ProcessingLog), 400)] + [ProducesResponseType(500)] + public async Task Post([FromBody] ProcessingLog processingLog) + { + try + { + var result = await _processingLogService.SaveAsync(processingLog); + return CreatedAtAction(nameof(GetById), new { id = result.ProcessingLogId }, result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpPut()] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(404)] + [ProducesResponseType(500)] + public async Task Put([FromBody] ProcessingLog processingLog) + { + try + { + var result = await _processingLogService.Update(processingLog); + if (result == null) + { + return NotFound($"The ProcessingLog with " + + $"ProcessingLogId: {processingLog.ProcessingLogId} " + + $"could not be found."); + } + + return Ok(result); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [HttpDelete("{id:int}")] + [ProducesResponseType(200)] + [ProducesResponseType(500)] + public async Task Delete(int id) + { + try + { + await _processingLogService.Delete(id); + return Ok(); + } + 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.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/QueueProcessStatusTypeEmailController.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/QueueProcessStatusTypeEmailController.cs new file mode 100644 index 0000000..cfa194c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/QueueProcessStatusTypeEmailController.cs @@ -0,0 +1,51 @@ +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.Library.Internal.DocumentIngestorModels.Requests; +using LCU.Library.Internal.Exceptions; +using Microsoft.AspNetCore.Mvc; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Controllers; + +[ApiController] +[Route("[controller]")] +public class QueueProcessStatusTypeEmailController : ControllerBase +{ + private readonly IQueueProcessStatusTypeEmailService _queueProcessTypeEmailService; + + public QueueProcessStatusTypeEmailController(IQueueProcessStatusTypeEmailService queueProcessTypeEmailService) + { + _queueProcessTypeEmailService = queueProcessTypeEmailService; + } + + [HttpPost("QueueProcessStatusTypeEmailRequest", Name = "QueueProcessStatusTypeEmailRequest")] + [ProducesResponseType(200)] + [ProducesResponseType(400)] + [ProducesResponseType(500)] + public async Task QueueProcessStatusTypeEmailByRequest(ProcessStatusTypeEmailRequest request) + { + try + { + if (!request.EmailAddresses.Any()) + { + return BadRequest("ProcessStatusType Email Request had no recipients."); + } + + if (request.HasInvalidStatuses(out var invalid)) + { + return BadRequest($"The following process statuses are not allowed: {string.Join(", ", invalid)}"); + } + + await _queueProcessTypeEmailService.QueueProcessStatusTypeEmailRequest(request); + return Ok($"ProcessStatusType Email Request Queued Successfully"); + } + catch (ServiceException) + { + return StatusCode(StatusCodes.Status500InternalServerError); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/StatusController.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/StatusController.cs new file mode 100644 index 0000000..6e82159 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/StatusController.cs @@ -0,0 +1,37 @@ +using Microsoft.AspNetCore.Mvc; +using Serilog; +using LCU.Library.Internal.Status.Services; +using LCU.Library.Internal.Exceptions; +namespace LCU.API.Internal.DocumentIngestor.Controllers; + +[ApiController] +[Route("[controller]")] +public class StatusController : ControllerBase +{ + private readonly IApiHealthCheckService _apiHealthCheckService; + + public StatusController(IApiHealthCheckService apiHealthCheckService) + { + _apiHealthCheckService = apiHealthCheckService; + } + + [HttpGet] + [ProducesResponseType(200)] + [ProducesResponseType(500)] + public IActionResult Get() + { + try + { + return Ok(_apiHealthCheckService.CheckApiHealthAndBuildEnvironmentView()); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/UploadCompletionReprocessingController.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/UploadCompletionReprocessingController.cs new file mode 100644 index 0000000..0287ea8 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Controllers/UploadCompletionReprocessingController.cs @@ -0,0 +1,82 @@ +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.Library.Internal.ApiSecurity.Attributes; +using LCU.Library.Internal.Exceptions; +using Microsoft.AspNetCore.Mvc; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Controllers; + +[ApiController] +[Route("[controller]")] +public class UploadCompletionReprocessingController : ControllerBase +{ + private readonly IUploadCompletionReprocessingService _reprocessingService; + + public UploadCompletionReprocessingController(IUploadCompletionReprocessingService reprocessingService) + { + _reprocessingService = reprocessingService; + } + + [ApiKey] + [HttpPost("QueueReprocessUploadCompletionByDocumentProcessingInfoId/{documentProcessingInfoId:int}/{userName}")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(401)] + [ProducesResponseType(404)] + [ProducesResponseType(500)] + public async Task QueueReprocessUploadCompletionByDocumentProcessingInfoId(int documentProcessingInfoId, string userName) + { + try + { + if (documentProcessingInfoId <= 0 || string.IsNullOrWhiteSpace(userName)) + { + return BadRequest($"DocumentProcessingInfoId and UserName are required."); + } + + await _reprocessingService.QueueReprocessUploadCompletionByDocumentProcessingInfoId(documentProcessingInfoId, userName); + return Accepted(); + } + catch (ArgumentNullException exception) + { + return StatusCode(StatusCodes.Status404NotFound, exception.Message); + } + catch (ServiceException exception) + { + return StatusCode(StatusCodes.Status500InternalServerError, exception.Message); + } + catch (Exception exception) + { + Log.Error(exception, "Unexpected Exception"); + return StatusCode(StatusCodes.Status500InternalServerError); + } + } + + [ApiKey] + [HttpPost("QueueReprocessAllNotificationDataFailures/{userName}")] + [ProducesResponseType(202)] + [ProducesResponseType(400)] + [ProducesResponseType(401)] + [ProducesResponseType(500)] + public async Task QueueReprocessAllNotificationDataFailures(string userName) + { + try + { + if (string.IsNullOrWhiteSpace(userName)) + { + return BadRequest($"UserName is required."); + } + + await _reprocessingService.QueueReprocessAllNotificationDataFailures(userName); + 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.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/CoreApiWrapperDao.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/CoreApiWrapperDao.cs new file mode 100644 index 0000000..5b7fe72 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/CoreApiWrapperDao.cs @@ -0,0 +1,95 @@ +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Utilities; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Mixed; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Organizations; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Persons; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Tax; +namespace LCU.API.Internal.DocumentIngestor.DataAccess; + +public class CoreApiWrapperDao : ICoreApiWrapperDao +{ + private readonly CoreApiWrapperConfiguration _coreApiWrapperConfiguration; + public CoreApiWrapperDao(CoreApiWrapperConfiguration coreApiWrapperConfiguration) + { + _coreApiWrapperConfiguration = coreApiWrapperConfiguration; + } + + public async Task> GetPersonsTaxIdData(string taxId) + { + var url = _coreApiWrapperConfiguration.GetPersonsTaxIdDataUrl.Replace("{taxId}", taxId); + return await HttpUtilities.GetAsync>(url, _coreApiWrapperConfiguration.RetryCount); + } + + public async Task> GetOrganizationsTaxIdData(string taxId) + { + var url = _coreApiWrapperConfiguration.GetOrganizationsTaxIdDataUrl.Replace("{taxId}", taxId); + return await HttpUtilities.GetAsync>(url, _coreApiWrapperConfiguration.RetryCount); + } + + public async Task> GetOwnersByAccountNumber(string accountNumber, string creationDate) + { + var url = _coreApiWrapperConfiguration.GetOwnersByAccountNumberUrl + $"?accountNumber={accountNumber}&creationDate={creationDate}"; + return await HttpUtilities.GetAsync>(url, _coreApiWrapperConfiguration.RetryCount); + } + + public async Task> GetOwnersByOrganizationName(string organizationName) + { + var url = _coreApiWrapperConfiguration.GetOwnersByOrganizationNameUrl.Replace("{organizationName}", organizationName); + return await HttpUtilities.GetAsync>(url, _coreApiWrapperConfiguration.RetryCount); + } + + public async Task> GetOwnersByPersonName(string personName) + { + var url = _coreApiWrapperConfiguration.GetOwnersByPersonNameUrl.Replace("{personName}", personName); + return await HttpUtilities.GetAsync>(url, _coreApiWrapperConfiguration.RetryCount); + } + + public async Task?> GetAgreeUsersByAccount(string accountNumber) + { + var url = $"{_coreApiWrapperConfiguration.GetAgreeUsersByAccountsUrl}?accountNumbers={accountNumber}"; + return await HttpUtilities.GetAsyncNewton?>(url, null, _coreApiWrapperConfiguration.RetryCount); + } + + public async Task?> GetAgreeUsersByPersonNumber(string personNumber) + { + var url = _coreApiWrapperConfiguration.GetAgreeUsersByPersonNumberUrl.Replace("{personNumber}", personNumber); + return await HttpUtilities.GetAsyncNewton?>(url, null, _coreApiWrapperConfiguration.RetryCount); + } + + public async Task GetAgreeUserByOrganizationNumber(string organizationNumber) + { + var uri = new Uri(_coreApiWrapperConfiguration.GetAgreeUserByOrganizationNumberUrl.Replace("{organizationNumber}", organizationNumber)); + return await HttpUtilities.GetStringResponseAsync(uri, _coreApiWrapperConfiguration.RetryCount); + } + + public async Task GetAgreementByUserId(string userId) + { + var url = _coreApiWrapperConfiguration.GetAgreementByUserIdUrl.Replace("{userId}", userId); + return await HttpUtilities.GetAsync(new Uri(url), null, _coreApiWrapperConfiguration.RetryCount); + } + + public async Task GetAgreementAccountByAccountId(string accountId) + { + return await HttpUtilities.GetAsync( + _coreApiWrapperConfiguration.GetAgreementAccountByAccountIdUrl.Replace("{accountId}", accountId), + _coreApiWrapperConfiguration.RetryCount); + } + + public async Task?> GetAgreementAccountsByUserId(string userId) + { + return await HttpUtilities.GetAsync?>( + _coreApiWrapperConfiguration.GetAgreementAccountsByUserIdUrl.Replace("{userId}", userId), + _coreApiWrapperConfiguration.RetryCount); + } + + public async Task GetPersonOrOrganizationNumberByMemberId(string memberId) + { + return await HttpUtilities.GetAsync( + new Uri(_coreApiWrapperConfiguration.GetPersonOrOrganizationNumberByMemberIdUrl.Replace("{memberId}", memberId)), + null, + _coreApiWrapperConfiguration.RetryCount); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/DocumentTypeRetrieverDao.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/DocumentTypeRetrieverDao.cs new file mode 100644 index 0000000..73579b5 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/DocumentTypeRetrieverDao.cs @@ -0,0 +1,122 @@ +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Utilities; +using LCU.Library.DocumentType.Models.Requests; +using LCU.Library.DocumentType.Models.Responses; +using LCU.Library.DocumentType.Models.Responses.External; +using Microsoft.Extensions.Caching.Memory; +using System.Collections.Specialized; +using System.Web; + +namespace LCU.API.Internal.DocumentIngestor.DataAccess; + +public class DocumentTypeRetrieverDao : IDocumentTypeRetrieverDao +{ + private readonly DocumentTypeRetrieverConfiguration _documentTypeRetrieverConfiguration; + private readonly DocumentCodeDetailCacheConfiguration _documentCodeDetailCacheConfiguration; + private readonly ApiConfiguration _apiConfiguration; + private IMemoryCache _cache; + + private const string ClientKeyName = "Client"; + private const string ClientKeyValue = "DocumentIngestor"; + private const string ApiKeyName = "ApiKey"; + + private const string UsernameKey = "userName"; + private const string PasswordKey = "password"; + + public DocumentTypeRetrieverDao(DocumentTypeRetrieverConfiguration documentTypeRetrieverConfiguration, + DocumentCodeDetailCacheConfiguration documentCodeDetailCacheConfiguration, + ApiConfiguration apiConfiguration, + IMemoryCache cache) + { + _documentTypeRetrieverConfiguration = documentTypeRetrieverConfiguration; + _documentCodeDetailCacheConfiguration = documentCodeDetailCacheConfiguration; + _apiConfiguration = apiConfiguration; + _cache = cache; + } + + public async Task> GetDocumentCodeDetails() + { + return await HttpUtilities.GetAsyncNewton>( + _documentTypeRetrieverConfiguration.GetDocumentCodeDetailsUrl, + GetDocumentCodeApiKeyHeaders(), + _documentTypeRetrieverConfiguration.RetryCount); + } + + public async Task GetDocumentCodeDetail(string documentCode) + { + return await HttpUtilities.GetAsyncNewton( + _documentTypeRetrieverConfiguration.GetDocumentCodeDetailsUrl.Replace("{documentCode}", documentCode), + GetDocumentCodeApiKeyHeaders(), + _documentTypeRetrieverConfiguration.RetryCount); + } + + public async Task> GetDocumentCodeDetailsCache() + { + IEnumerable documentCodeDetails; + if (!_cache.TryGetValue(_documentCodeDetailCacheConfiguration.CacheName, out documentCodeDetails)) + { + documentCodeDetails = await GetDocumentCodeDetails(); + + var cacheEntryOptions = new MemoryCacheEntryOptions() + .SetAbsoluteExpiration(TimeSpan.FromMinutes(_documentCodeDetailCacheConfiguration.ExpirationMinutes)); + + _cache.Set(_documentCodeDetailCacheConfiguration.CacheName, documentCodeDetails, cacheEntryOptions); + } + + return documentCodeDetails; + } + + public async Task?> GetListOfMaliciousDocuments(MaliciousDocumentSearchFilter filter) + { + var uri = new Uri($"{_documentTypeRetrieverConfiguration.GetListOfMaliciousDocumentsUrl}{EncodeFilterUri(filter)}"); + return await HttpUtilities.GetAsync>(uri, + GetDocumentApiKeyHeaders(), + _documentTypeRetrieverConfiguration.RetryCount); + } + + public async Task GetDocumentInformationById(Guid documentId) + { + var uri = new Uri($"{_documentTypeRetrieverConfiguration.GetDocumentInformationByIdUrl.Replace("{documentId}", documentId.ToString())}"); + return await HttpUtilities.GetAsync(uri, + GetDocumentCodeApiKeyHeaders(), + _documentTypeRetrieverConfiguration.RetryCount); + } + + private string EncodeFilterUri(MaliciousDocumentSearchFilter filter) + { + NameValueCollection nameValueCollection = HttpUtility.ParseQueryString(string.Empty); + if (filter.MaliciousDateStart != null) + { + nameValueCollection.Add("MaliciousDateStart", filter.MaliciousDateStart.ToString()); + } + + if (filter.MaliciousDateEnd != null) + { + nameValueCollection.Add("MaliciousDateEnd", filter.MaliciousDateEnd.ToString()); + } + + return $"?{nameValueCollection}"; + } + + private Dictionary GetDocumentCodeApiKeyHeaders() + { + var headers = new Dictionary + { + { ClientKeyName, ClientKeyValue }, + { ApiKeyName, _apiConfiguration.DocumentIngestorApiKey } + }; + + return headers; + } + + private Dictionary GetDocumentApiKeyHeaders() + { + var headers = new Dictionary + { + { UsernameKey, _documentTypeRetrieverConfiguration.Username }, + { PasswordKey, _documentTypeRetrieverConfiguration.Password } + }; + + return headers; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/DocumentTypeUploaderApiDao.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/DocumentTypeUploaderApiDao.cs new file mode 100644 index 0000000..695c899 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/DocumentTypeUploaderApiDao.cs @@ -0,0 +1,38 @@ +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Utilities; +using LCU.Library.DocumentType.Models.Requests.PrimaryOwner; +using LCU.Library.DocumentType.Models.Requests.Account; +using LCU.Library.DocumentType.Models.Requests.Generic; + +namespace LCU.API.Internal.DocumentIngestor.DataAccess; + +public class DocumentTypeUploaderApiDao : IDocumentTypeUploaderApiDao +{ + private readonly DocumentTypeUploaderConfiguration _documentTypeUploaderConfiguration; + + public DocumentTypeUploaderApiDao(DocumentTypeUploaderConfiguration documentTypeUploaderConfiguration) + { + _documentTypeUploaderConfiguration = documentTypeUploaderConfiguration; + } + + public async Task UploadPrimaryOwnerDocument(PrimaryOwnerDocumentRequest primaryOwnerDocumentRequest) + { + await HttpUtilities.PostAsync(_documentTypeUploaderConfiguration.QueuePrimaryOwnerDocumentUploadUri, + primaryOwnerDocumentRequest, + _documentTypeUploaderConfiguration.RetryCount); + } + + public async Task UploadAccountDocument(AccountDocumentRequest accountDocumentRequest) + { + await HttpUtilities.PostAsync(_documentTypeUploaderConfiguration.QueueAccountDocumentUploadUri, + accountDocumentRequest, + _documentTypeUploaderConfiguration.RetryCount); + } + + public async Task UploadGenericDocument(GenericDocumentRequest genericDocumentRequest) + { + await HttpUtilities.PostAsync(_documentTypeUploaderConfiguration.QueueGenericDocumentUploadUri, + genericDocumentRequest, + _documentTypeUploaderConfiguration.RetryCount); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/FileOperationsApiDao.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/FileOperationsApiDao.cs new file mode 100644 index 0000000..5d807da --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/FileOperationsApiDao.cs @@ -0,0 +1,118 @@ +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Utilities; +using LCU.Library.Internal.FileOperationsModels.Models; +namespace LCU.API.Internal.DocumentIngestor.DataAccess; + +public class FileOperationsApiDao : IFileOperationsApiDao +{ + private readonly FileOperationsApiConfiguration _fileOperationsApiConfiguration; + + public FileOperationsApiDao(FileOperationsApiConfiguration fileOperationsApiConfiguration) + { + _fileOperationsApiConfiguration = fileOperationsApiConfiguration; + } + + public async Task DirectMoveFile(MoveFileRequest moveFileRequest) + { + return await HttpUtilities.PostAsync(_fileOperationsApiConfiguration.DirectMoveFileUri, + moveFileRequest, + _fileOperationsApiConfiguration.RetryCount, + 300); + } + + public async Task DirectWriteFile(WriteFileRequest writeFileRequest) + { + return await HttpUtilities.PostAsync(_fileOperationsApiConfiguration.DirectWriteFileUri, + writeFileRequest, + _fileOperationsApiConfiguration.RetryCount); + } + + public async Task DirectCreateDirectory(CreateDirectoryRequest createDirectoryRequest) + { + return await HttpUtilities.PostAsync(_fileOperationsApiConfiguration.DirectCreateDirectoryUri, + createDirectoryRequest, + _fileOperationsApiConfiguration.RetryCount); + } + + public async Task DirectUnzipFile(UnzipFileRequest unzipFileRequest) + { + return await HttpUtilities.PostAsync(_fileOperationsApiConfiguration.DirectUnzipFileUri, + unzipFileRequest, + _fileOperationsApiConfiguration.RetryCount, + 300); + } + + public async Task DirectZipDirectory(ZipDirectoryRequest zipDirectoryRequest) + { + return await HttpUtilities.PostAsync(_fileOperationsApiConfiguration.DirectZipFileUri, + zipDirectoryRequest, + _fileOperationsApiConfiguration.RetryCount, + 300); + } + + public async Task DirectDeleteDirectory(DeleteDirectoryRequest deleteDirectoryRequest) + { + return await HttpUtilities.PostAsync(_fileOperationsApiConfiguration.DirectDeleteDirectoryUri, + deleteDirectoryRequest, + _fileOperationsApiConfiguration.RetryCount, + 300); + } + + public async Task DirectDeleteFile(DeleteFileRequest deleteFileRequest) + { + return await HttpUtilities.PostAsync(_fileOperationsApiConfiguration.DirectDeleteFileUri, + deleteFileRequest, + _fileOperationsApiConfiguration.RetryCount, + 300); + } + + public async Task GetFileContent(string filePath) + { + var finalFilePath = filePath.Replace("\\", "%5C"); + var uri = new Uri($"{_fileOperationsApiConfiguration.GetFileContentUri}/{finalFilePath}"); + return await HttpUtilities.GetStringResponseAsync(uri, _fileOperationsApiConfiguration.RetryCount); + } + + public async Task GetPdfByteContent(string filePath) + { + var finalFilePath = filePath.Replace("\\", "%5C"); + var uri = new Uri($"{_fileOperationsApiConfiguration.GetPdfContentUri}/{finalFilePath}"); + return await HttpUtilities.GetByteArrayAsync(uri, _fileOperationsApiConfiguration.RetryCount); + } + + public async Task ValidateFileExists(string filePath) + { + return await HttpUtilities.PostAsync(_fileOperationsApiConfiguration.ValidateFileExistsUri, + filePath, + _fileOperationsApiConfiguration.RetryCount); + } + + public async Task ValidatePdfPageExists(string filePath, string pageNumber) + { + var finalFilePath = filePath.Replace("\\", "%5C"); + return await HttpUtilities.PostAsync(new Uri($"{_fileOperationsApiConfiguration.ValidatePdfPageExistsUri}/{finalFilePath}/{pageNumber}" ), + "", + _fileOperationsApiConfiguration.RetryCount); + } + + public async Task> BuildDynamicDirectoryList(DynamicDirectoryListRequest request) + { + return await HttpUtilities.PostAsync>(_fileOperationsApiConfiguration.BuildDynamicDirectoryListUri, + request, + _fileOperationsApiConfiguration.RetryCount); + } + + public async Task> BuildDynamicFileList(DynamicFileListRequest request) + { + return await HttpUtilities.PostAsync>(_fileOperationsApiConfiguration.BuildDynamicFileListUri, + request, + _fileOperationsApiConfiguration.RetryCount); + } + + public async Task QueueBatchPdfParser(BatchParsePdfRequest batchParsePdfRequest) + { + await HttpUtilities.PostAsync(_fileOperationsApiConfiguration.QueueBatchPdfParserUri, + batchParsePdfRequest, + _fileOperationsApiConfiguration.RetryCount); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/ICoreApiWrapperDao.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/ICoreApiWrapperDao.cs new file mode 100644 index 0000000..6a9ebee --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/ICoreApiWrapperDao.cs @@ -0,0 +1,26 @@ +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Tax; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Persons; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Organizations; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Mixed; + +namespace LCU.API.Internal.DocumentIngestor.DataAccess; + +public interface ICoreApiWrapperDao +{ + Task> GetPersonsTaxIdData(string taxId); + Task> GetOrganizationsTaxIdData(string taxId); + Task> GetOwnersByAccountNumber(string accountNumber, string creationDate); + Task> GetOwnersByOrganizationName(string organizationName); + Task> GetOwnersByPersonName(string personName); + Task?> GetAgreeUsersByAccount(string accountNumber); + Task?> GetAgreeUsersByPersonNumber(string personNumber); + Task GetAgreeUserByOrganizationNumber(string organizationNumber); + Task GetAgreementByUserId(string userId); + Task GetAgreementAccountByAccountId(string accountId); + Task?> GetAgreementAccountsByUserId(string userId); + Task GetPersonOrOrganizationNumberByMemberId(string memberId); + +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/IDocumentTypeRetrieverDao.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/IDocumentTypeRetrieverDao.cs new file mode 100644 index 0000000..4ae513c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/IDocumentTypeRetrieverDao.cs @@ -0,0 +1,14 @@ +using LCU.Library.DocumentType.Models.Requests; +using LCU.Library.DocumentType.Models.Responses; +using LCU.Library.DocumentType.Models.Responses.External; + +namespace LCU.API.Internal.DocumentIngestor.DataAccess; + +public interface IDocumentTypeRetrieverDao +{ + Task> GetDocumentCodeDetails(); + Task GetDocumentCodeDetail(string documentCode); + Task> GetDocumentCodeDetailsCache(); + Task?> GetListOfMaliciousDocuments(MaliciousDocumentSearchFilter filter); + Task GetDocumentInformationById(Guid documentId); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/IDocumentTypeUploaderApiDao.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/IDocumentTypeUploaderApiDao.cs new file mode 100644 index 0000000..8888a90 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/IDocumentTypeUploaderApiDao.cs @@ -0,0 +1,11 @@ +using LCU.Library.DocumentType.Models.Requests.PrimaryOwner; +using LCU.Library.DocumentType.Models.Requests.Account; +using LCU.Library.DocumentType.Models.Requests.Generic; +namespace LCU.API.Internal.DocumentIngestor.DataAccess; + +public interface IDocumentTypeUploaderApiDao +{ + Task UploadPrimaryOwnerDocument(PrimaryOwnerDocumentRequest primaryOwnerDocumentRequest); + Task UploadAccountDocument(AccountDocumentRequest accountDocumentRequest); + Task UploadGenericDocument(GenericDocumentRequest genericDocumentRequest); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/IFileOperationsApiDao.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/IFileOperationsApiDao.cs new file mode 100644 index 0000000..3182de2 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/IFileOperationsApiDao.cs @@ -0,0 +1,21 @@ +using LCU.Library.Internal.FileOperationsModels.Models; + +namespace LCU.API.Internal.DocumentIngestor.DataAccess; + +public interface IFileOperationsApiDao +{ + Task DirectMoveFile(MoveFileRequest moveFileRequest); + Task DirectWriteFile(WriteFileRequest writeFileRequest); + Task DirectCreateDirectory(CreateDirectoryRequest createDirectoryRequest); + Task DirectUnzipFile(UnzipFileRequest unzipFileRequest); + Task DirectZipDirectory(ZipDirectoryRequest zipDirectoryRequest); + Task DirectDeleteDirectory(DeleteDirectoryRequest deleteDirectoryRequest); + Task DirectDeleteFile(DeleteFileRequest deleteFileRequest); + Task GetFileContent(string filePath); + Task GetPdfByteContent(string filePath); + Task ValidateFileExists(string filePath); + Task ValidatePdfPageExists(string filePath, string pageNumber); + Task> BuildDynamicDirectoryList(DynamicDirectoryListRequest request); + Task> BuildDynamicFileList(DynamicFileListRequest request); + Task QueueBatchPdfParser(BatchParsePdfRequest batchParsePdfRequest); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/IMemberPreferencesApiDao.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/IMemberPreferencesApiDao.cs new file mode 100644 index 0000000..4035f2f --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/IMemberPreferencesApiDao.cs @@ -0,0 +1,10 @@ +using LCU.API.Internal.DocumentIngestor.Models.MemberPreferencesDtos; +namespace LCU.API.Internal.DocumentIngestor.DataAccess; + +public interface IMemberPreferencesApiDao +{ + Task GetMemberOptInAgreementInfoByUserId(string userId); + Task GetMemberOptInSettingsByUserId(string userId); + Task EmailSuccessfulSend(string userId, string emailAddress); + Task EmailFailureSend(string userId, string emailAddress); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/INotificationApiDao.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/INotificationApiDao.cs new file mode 100644 index 0000000..241dbec --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/INotificationApiDao.cs @@ -0,0 +1,9 @@ +using LCU.Library.Internal.NotificationsModels.Models; + +namespace LCU.API.Internal.DocumentIngestor.DataAccess +{ + public interface INotificationApiDao + { + Task SendEmailAsync(EmailRequest emailRequest); + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/MemberPreferencesApiDao.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/MemberPreferencesApiDao.cs new file mode 100644 index 0000000..7be402b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/MemberPreferencesApiDao.cs @@ -0,0 +1,64 @@ +using System.Web; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Models.MemberPreferencesDtos; +using LCU.API.Internal.DocumentIngestor.Utilities; +using LCU.Library.Internal.DocumentIngestorModels.Constants; + +namespace LCU.API.Internal.DocumentIngestor.DataAccess; + +public class MemberPreferencesApiDao : IMemberPreferencesApiDao +{ + private readonly MemberPreferencesApiConfiguration _memberPreferencesApiConfiguration; + + private const string UserName = "UserName"; + private const string UserType = "UserType"; + + public MemberPreferencesApiDao(MemberPreferencesApiConfiguration memberPreferencesApiConfiguration) + { + _memberPreferencesApiConfiguration = memberPreferencesApiConfiguration; + } + + public async Task GetMemberOptInAgreementInfoByUserId(string userId) + { + var url = _memberPreferencesApiConfiguration.GetMemberOptInAgreementInfoByUserIdUrl.Replace("{userId}", userId.ToString()); + return await HttpUtilities.GetAsync(url, _memberPreferencesApiConfiguration.RetryCount); + } + + public async Task GetMemberOptInSettingsByUserId(string userId) + { + var url = _memberPreferencesApiConfiguration.GetMemberOptInSettingsByUserIdUrl.Replace("{userId}", userId.ToString()); + return await HttpUtilities.GetAsync(url, _memberPreferencesApiConfiguration.RetryCount); + } + + public Task EmailSuccessfulSend(string userId, string emailAddress) => SendEmailStatusUpdate(_memberPreferencesApiConfiguration.EmailSuccessfulSendUrl, userId, emailAddress); + + public Task EmailFailureSend(string userId, string emailAddress) => SendEmailStatusUpdate(_memberPreferencesApiConfiguration.EmailFailedSendUrl, userId, emailAddress); + + private async Task SendEmailStatusUpdate(string route, string userId, string? emailAddress) + { + var url = route.Replace("{userId}", userId); + var uri = new UriBuilder(url); + if (emailAddress is not null) + { + var query = HttpUtility.ParseQueryString(uri.Query); + query["email"] = emailAddress; + uri.Query = query.ToString(); + } + + await HttpUtilities.PostAsync(uri.Uri, + "", + GetMemberPreferencesHeaders(), + _memberPreferencesApiConfiguration.RetryCount); + } + + private Dictionary GetMemberPreferencesHeaders() + { + var headers = new Dictionary + { + { UserName, Users.System }, + { UserType, Users.System } + }; + + return headers; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/NotificationApiDao.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/NotificationApiDao.cs new file mode 100644 index 0000000..bbfd88d --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/DataAccess/NotificationApiDao.cs @@ -0,0 +1,22 @@ +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Utilities; +using LCU.Library.Internal.NotificationsModels.Models; + +namespace LCU.API.Internal.DocumentIngestor.DataAccess; + +public class NotificationApiDao : INotificationApiDao +{ + private readonly NotificationApiConfiguration _notificationApiConfiguration; + + public NotificationApiDao(NotificationApiConfiguration notificationApiConfiguration) + { + _notificationApiConfiguration = notificationApiConfiguration; + } + + public async Task SendEmailAsync(EmailRequest emailRequest) + { + await HttpUtilities.PostAsync(new Uri(_notificationApiConfiguration.EmailUrl), + emailRequest, + _notificationApiConfiguration.RetryCount); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Initializers/CloudRoleNameTelemetryInitializer.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Initializers/CloudRoleNameTelemetryInitializer.cs new file mode 100644 index 0000000..3b11fdf --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Initializers/CloudRoleNameTelemetryInitializer.cs @@ -0,0 +1,12 @@ +using Microsoft.ApplicationInsights.Channel; +using Microsoft.ApplicationInsights.Extensibility; + +namespace LCU.API.Internal.DocumentIngestor.Initializers; + +public class CloudRoleNameTelemetryInitializer : ITelemetryInitializer +{ + public void Initialize(ITelemetry telemetry) + { + telemetry.Context.Cloud.RoleName = "DocumentIngestor"; + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor.csproj b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor.csproj new file mode 100644 index 0000000..6da44de --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor.csproj @@ -0,0 +1,62 @@ + + + + net8.0 + enable + enable + latest + Debug;Release;Test + AnyCPU + + + + 1701;1702;8618; 1591 + + + + 1701;1702;8618; 1591 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Always + + + Always + + + + diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Models/MemberPreferencesDtos/MemberOptInAgreementInformation.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Models/MemberPreferencesDtos/MemberOptInAgreementInformation.cs new file mode 100644 index 0000000..f7f3a16 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Models/MemberPreferencesDtos/MemberOptInAgreementInformation.cs @@ -0,0 +1,8 @@ +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements; +namespace LCU.API.Internal.DocumentIngestor.Models.MemberPreferencesDtos; + +public class MemberOptInAgreementInformation +{ + public Agreement Agreement { get; set; } + public IEnumerable Accounts { get; set; } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Models/MemberPreferencesDtos/MemberOptInInformation.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Models/MemberPreferencesDtos/MemberOptInInformation.cs new file mode 100644 index 0000000..87711da --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Models/MemberPreferencesDtos/MemberOptInInformation.cs @@ -0,0 +1,7 @@ +namespace LCU.API.Internal.DocumentIngestor.Models.MemberPreferencesDtos; + +public class MemberOptInInformation +{ + public MemberOptInSettings MemberOptinSettings { get; set; } + public bool HasPendingUpdates { get; set; } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Models/MemberPreferencesDtos/MemberOptInSettings.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Models/MemberPreferencesDtos/MemberOptInSettings.cs new file mode 100644 index 0000000..95d1b49 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Models/MemberPreferencesDtos/MemberOptInSettings.cs @@ -0,0 +1,28 @@ +namespace LCU.API.Internal.DocumentIngestor.Models.MemberPreferencesDtos; + +public class MemberOptInSettings +{ + public const string Paper = "Paper"; + public const string Electronic = "Electronic"; + + public int Id { get; set; } + public string UserId { get; set; } + public string EStatements { get; set; } + public string ENotifications { get; set; } + public string UniversalOptIn { get; set; } + public string LegalVersion { get; set; } + public DateTime? LegalDate { get; set; } + public string UnifiedOptInEmail { get; set; } + public string EStatementsEmail { get; set; } + public string ENotificationsEmail { get; set; } + + public bool IsUnifiedPaperEnrolled() + { + return string.Equals(UniversalOptIn, Paper, StringComparison.InvariantCultureIgnoreCase); + } + + public bool IsUnifiedElectronicEnrolled() + { + return string.Equals(UniversalOptIn, Electronic, StringComparison.InvariantCultureIgnoreCase); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Program.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Program.cs new file mode 100644 index 0000000..1b64358 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Program.cs @@ -0,0 +1,650 @@ +using System.Text.Json.Serialization; +using Microsoft.EntityFrameworkCore; +using Microsoft.OpenApi.Models; +using Newtonsoft.Json; +using Serilog; +using MassTransit; +using LCU.Library.Internal.LcuMassTransit; +using LCU.Library.Internal.LcuMassTransitModels; +using LCU.Library.Internal.Logging; +using LCU.Library.Internal.Logging.Models; +using LCU.Library.Internal.Logging.Middleware; +using LCU.Library.Internal.Configuration; +using LCU.Library.Internal.ApiSecurity; +using LCU.Library.Internal.Status; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Consumers; +using LCU.API.Internal.DocumentIngestor.DataAccess; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; +using LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.PdfParserServices; +using LCU.API.Internal.DocumentIngestor.Services.MemberNotificationInfoDeterminingServices; +using LCU.API.Internal.DocumentIngestorLib.Repositories; +using LCU.API.Internal.DocumentIngestorLib.Persistence; +using LCU.Api.Internal.DispatcherSharedLib; +using LCU.API.Internal.DocumentIngestor.Initializers; +using LCU.API.Internal.DocumentIngestor.Security; +using LCU.Library.Internal.LCUServiceFactory; +using LCU.Library.Internal.LCUServiceFactory.Configurations; +using Microsoft.ApplicationInsights.DependencyCollector; +using Microsoft.ApplicationInsights.Extensibility; +using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Authorization; +using Microsoft.Identity.Web; +using Microsoft.ApplicationInsights.AspNetCore.Extensions; + +string MyAllowSpecificOrigins = "_myAllowSpecificOrigins"; + +var builder = BuildBuilder(args); +BuildServicesAndConfigurations(builder); +BuildAppAndRun(builder); + +WebApplicationBuilder BuildBuilder(string[] args) +{ + var builder = WebApplication.CreateBuilder(args); + builder.Configuration.AddJsonFile("/app/config/environment-appsettings/appsettings.json", optional: true, reloadOnChange: true); + builder.Configuration.AddJsonFile("/app/config/workload-appsettings/appsettings.json", optional: true, reloadOnChange: true); + builder.Configuration.AddJsonFile("/vault/secrets/document-ingestor-azure-ad-client-secret.json", optional: true, reloadOnChange: true); + builder.Configuration.AddJsonFile("/vault/secrets/document-ingestor-application-insights-instrumentation-key.json", optional: true, reloadOnChange: true); + builder.Configuration.AddJsonFile("/vault/secrets/document-ingestor-document-manager.json", optional: true, reloadOnChange: true); + builder.Configuration.AddJsonFile("/vault/secrets/document-ingestor-queue-password.json", optional: true, reloadOnChange: true); + builder.Configuration.AddJsonFile("/vault/secrets/document-ingestor-queue-user-name.json", optional: true, reloadOnChange: true); + builder.Configuration.AddJsonFile("/vault/secrets/document-ingestor-database-connection.json", optional: true, reloadOnChange: true); + builder.Configuration.AddJsonFile("/vault/secrets/document-ingestor-environment-from-vault.json", optional: true, reloadOnChange: true); + builder.Configuration.AddJsonFile("/vault/secrets/document-ingestor-document-ingestor-api-key.json", optional: true, reloadOnChange: true); + builder.Configuration.AddJsonFile("/vault/secrets/document-ingestor-seq-api-key.json", optional: true, reloadOnChange: true); + builder.Configuration.AddJsonFile("/vault/secrets/document-ingestor-mobile-banking-api-key.json", optional: true, reloadOnChange: true); + builder.Host.UseSerilog(); + return builder; +} + +void BuildServicesAndConfigurations(WebApplicationBuilder builder) +{ + var services = builder.Services; + var configuration = builder.Configuration; + + var apiConfiguration = 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); + configuration.Bind(services); + var security = configuration.Bind(services, "Security"); + var dbConfiguration = configuration.Bind(services); + var servicesFactoryConfiguration = configuration.Bind(services); + + services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) + .AddMicrosoftIdentityWebApi(configuration.GetSection("AzureAd")); + services.AddAuthorization(options => + { + options.AddPolicy("user_token", policy => + { + policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme); + policy.RequireAuthenticatedUser(); + }); + options.DefaultPolicy = options.GetPolicy("user_token")!; + + options.AddPolicy(SetDocumentNotificationStatusPolicy.Name, policyBuilder => SetDocumentNotificationStatusPolicy.PolicyFactory(policyBuilder, security)); + }); + services.AddSingleton(); + + var insightsServiceOptions = new ApplicationInsightsServiceOptions() { ConnectionString = configuration["ApplicationInsights:InstrumentationKey"] }; + services.AddApplicationInsightsTelemetry(insightsServiceOptions); + services.AddSingleton(); + services.ConfigureTelemetryModule((module,o)=>{ + module.IncludeDiagnosticSourceActivities.Add("MassTransit"); + }); + + services.AddMemoryCache(); + + services.AddDbContext(options => + { + options.UseSqlServer + ( + dbConfiguration.ConnectionString, + sql => sql.EnableRetryOnFailure(dbConfiguration.MaxRetryCount, dbConfiguration.MaxRetryDelay, null) + ); + }); + + var loggerConfiguration = new LoggingConfiguration(apiConfiguration.AppName, + apiConfiguration.SeqApiKey, + apiConfiguration.SeqUrl); + var lcuLogging = new LcuLogging(loggerConfiguration); + lcuLogging.UseLcuLogging(); + + services.AddCors(options => + { + options.AddPolicy(MyAllowSpecificOrigins, + builder => + { + builder.WithOrigins( + apiConfiguration.CorsAllowedOrigins + ).AllowAnyHeader().AllowAnyMethod(); + }); + }); + + var connectionConfiguration = MassTransitConfigurationSetUp.AddConnectionConfiguration(ref services, configuration); + //debugging + Console.WriteLine(JsonConvert.SerializeObject(connectionConfiguration)); + + var receiveEndpointConfigurations = new ReceiveEndpointConfigurations() + { + BatchIngestionReceiveEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, + "BatchIngestionReceiveEndpoint"), + DocumentIngestorReceiveEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, + "DocumentIngestorReceiveEndpoint"), + DocumentIngestorProcessingReceiveEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, + "DocumentIngestorProcessingReceiveEndpoint"), + DocumentIngestorCompletionReceiveEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, + "DocumentIngestorCompletionReceiveEndpoint"), + PdfPartitionerEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, "PdfPartitionerEndpoint"), + PdfPartitionerCompletionEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, + "PdfPartitionerCompletionEndpoint"), + UploadCompletionEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, + "UploadCompletionEndpoint"), + MemberDocumentNotifierEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, + "MemberDocumentNotifierEndpoint"), + MemberNotificationCompletionEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, + "MemberNotificationCompletionEndpoint"), + IngestionFolderCleanUpReceiveEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, + "IngestionFolderCleanUpReceiveEndpoint"), + GatherMemberNotificationInfoReceiveEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, + "GatherMemberNotificationInfoReceiveEndpoint"), + BatchUpdateMemberNotificationDataEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, + "BatchUpdateMemberNotificationDataEndpoint"), + ProcessStatusTypeEmailReceiveEndpoint = MassTransitConfigurationSetUp.GetReceiveEndpointConfiguration(configuration, "ProcessStatusTypeEmailReceiveEndpoint") + }; + services.AddSingleton(receiveEndpointConfigurations); + //debugging + Console.WriteLine(JsonConvert.SerializeObject(receiveEndpointConfigurations)); + + services.AddLCUStatusServicesWithApiHealthCheck(configuration); + + AddMassTransitServices(ref services, connectionConfiguration, receiveEndpointConfigurations, apiConfiguration); + AddDocumentIngestorServices(services); + AddDocumentIngestorDaos(services); + AddDocumentIngestorLib(ref services); + services.AddHttpClient(); + services.AddDispatcherServices(configuration); + + services.AddLCUServiceFactoryAndValidateServiceRegistration(servicesFactoryConfiguration); + services.AddLCUServiceFactoryAndValidateServiceRegistration(servicesFactoryConfiguration); + services.AddLCUServiceFactoryAndValidateServiceRegistration(servicesFactoryConfiguration); + services.AddLCUServiceFactoryAndValidateServiceRegistration(servicesFactoryConfiguration); + + services.AddControllers().AddJsonOptions(options => options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter())); + services.AddEndpointsApiExplorer(); + services.AddSwaggerGen(c => + { + c.SwaggerDoc("v1", new OpenApiInfo { Title = $"{apiConfiguration.AppName}", Version = "v1" }); + + var authority = $"https://login.microsoftonline.com/{configuration.GetSection("AzureAd")["TenantId"]}"; + c.AddSecurityDefinition + ( + nameof(SecuritySchemeType.OpenIdConnect), + new OpenApiSecurityScheme + { + Type = SecuritySchemeType.OAuth2, + Flows = new OpenApiOAuthFlows + { + AuthorizationCode = new OpenApiOAuthFlow + { + AuthorizationUrl = new Uri($"{authority}/oauth2/v2.0/authorize"), + TokenUrl = new Uri($"{authority}/oauth2/v2.0/token") + } + } + } + ); + c.AddSecurityRequirement + ( + new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = nameof(SecuritySchemeType.OpenIdConnect) + } + }, + Array.Empty() + } + } + ); + + c.AddSecurityDefinition("ApiKey", new OpenApiSecurityScheme + { + In = ParameterLocation.Header, + Name = "ApiKey" + }); + c.AddSecurityDefinition("ApiClient", new OpenApiSecurityScheme + { + In = ParameterLocation.Header, + Name = "Client" + }); + c.AddSecurityRequirement + ( + new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "ApiKey" + } + }, + Array.Empty() + } + } + ); + c.AddSecurityRequirement + ( + new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "ApiClient" + } + }, + Array.Empty() + } + } + ); + }); + + services.AddApiKeySecurity(configuration); +} + +void AddMassTransitServices(ref IServiceCollection services, + ConnectionConfiguration connectionConfiguration, + ReceiveEndpointConfigurations receiveEndpointConfigurations, + ApiConfiguration apiConfiguration) +{ + services.AddMassTransit(x => + { + x.AddConsumer(); + x.AddConsumer(); + x.AddConsumer(); + x.AddConsumer(); + x.AddConsumer(); + x.AddConsumer(); + x.AddConsumer(); + x.AddConsumer(); + x.AddConsumer(); + x.AddConsumer(); + x.AddConsumer(); + x.AddConsumer(); + x.AddConsumer(); + + x.UsingRabbitMq((context, cfg) => + { + cfg.Host(connectionConfiguration.HostUrl, "/", host => + { + host.Username(connectionConfiguration.UserName); + host.Password(connectionConfiguration.Password); + }); + cfg.UseTimeout(t => t.Timeout = TimeSpan.FromSeconds(420)); + + if (apiConfiguration.FeatureFlags.RunBatchIngestionConsumer) + { + cfg.ReceiveEndpoint(receiveEndpointConfigurations.BatchIngestionReceiveEndpoint.ReceiveEndpoint, e => + { + e.ConfigureConsumer(context); + e.SetQuorumQueue(); + e.PrefetchCount = receiveEndpointConfigurations.BatchIngestionReceiveEndpoint.PrefetchLimit; + e.UseTimeout(t => t.Timeout = TimeSpan.FromSeconds(420)); + }); + } + + if (apiConfiguration.FeatureFlags.RunIngestorIndexConsumer) + { + cfg.ReceiveEndpoint(receiveEndpointConfigurations.DocumentIngestorReceiveEndpoint.ReceiveEndpoint, e => + { + e.ConfigureConsumer(context); + e.SetQuorumQueue(); + e.PrefetchCount = receiveEndpointConfigurations.DocumentIngestorReceiveEndpoint.PrefetchLimit; + e.UseTimeout(t => t.Timeout = TimeSpan.FromSeconds(420)); + }); + } + + if (apiConfiguration.FeatureFlags.RunIngestorProcessingConsumer) + { + cfg.ReceiveEndpoint(receiveEndpointConfigurations.DocumentIngestorProcessingReceiveEndpoint.ReceiveEndpoint, e => + { + e.ConfigureConsumer(context); + e.SetQuorumQueue(); + e.PrefetchCount = receiveEndpointConfigurations.DocumentIngestorProcessingReceiveEndpoint.PrefetchLimit; + e.UseTimeout(t => t.Timeout = TimeSpan.FromSeconds(420)); + }); + } + + if (apiConfiguration.FeatureFlags.RunIngestorCompletionConsumer) + { + cfg.ReceiveEndpoint(receiveEndpointConfigurations.DocumentIngestorCompletionReceiveEndpoint.ReceiveEndpoint, e => + { + e.ConfigureConsumer(context); + e.SetQuorumQueue(); + e.PrefetchCount = receiveEndpointConfigurations.DocumentIngestorCompletionReceiveEndpoint.PrefetchLimit; + e.UseTimeout(t => t.Timeout = TimeSpan.FromSeconds(420)); + }); + } + + if (apiConfiguration.FeatureFlags.RunIngestionFolderCleanUpConsumer) + { + cfg.ReceiveEndpoint(receiveEndpointConfigurations.IngestionFolderCleanUpReceiveEndpoint.ReceiveEndpoint, e => + { + e.ConfigureConsumer(context); + e.SetQuorumQueue(); + e.PrefetchCount = receiveEndpointConfigurations.IngestionFolderCleanUpReceiveEndpoint.PrefetchLimit; + e.UseTimeout(t => t.Timeout = TimeSpan.FromSeconds(420)); + }); + } + + if (apiConfiguration.FeatureFlags.RunPdfPartitionerConsumer) + { + cfg.ReceiveEndpoint(receiveEndpointConfigurations.PdfPartitionerEndpoint.ReceiveEndpoint, e => + { + e.ConfigureConsumer(context); + e.SetQuorumQueue(); + e.PrefetchCount = receiveEndpointConfigurations.PdfPartitionerEndpoint.PrefetchLimit; + e.UseTimeout(t => t.Timeout = TimeSpan.FromSeconds(420)); + }); + } + + if (apiConfiguration.FeatureFlags.RunPdfPartitionerCompletionConsumer) + { + cfg.ReceiveEndpoint(receiveEndpointConfigurations.PdfPartitionerCompletionEndpoint.ReceiveEndpoint, e => + { + e.ConfigureConsumer(context); + e.SetQuorumQueue(); + e.PrefetchCount = receiveEndpointConfigurations.PdfPartitionerCompletionEndpoint.PrefetchLimit; + e.UseTimeout(t => t.Timeout = TimeSpan.FromSeconds(420)); + }); + } + + if (apiConfiguration.FeatureFlags.RunUploadCompletionConsumer) + { + cfg.ReceiveEndpoint(receiveEndpointConfigurations.UploadCompletionEndpoint.ReceiveEndpoint, e => + { + e.ConfigureConsumer(context); + e.SetQuorumQueue(); + e.PrefetchCount = receiveEndpointConfigurations.UploadCompletionEndpoint.PrefetchLimit; + e.UseTimeout(t => t.Timeout = TimeSpan.FromSeconds(420)); + }); + } + + if (apiConfiguration.FeatureFlags.RunMemberDocumentNotifierConsumer) + { + cfg.ReceiveEndpoint(receiveEndpointConfigurations.MemberDocumentNotifierEndpoint.ReceiveEndpoint, e => + { + e.ConfigureConsumer(context); + e.SetQuorumQueue(); + e.PrefetchCount = receiveEndpointConfigurations.MemberDocumentNotifierEndpoint.PrefetchLimit; + e.UseTimeout(t => t.Timeout = TimeSpan.FromSeconds(420)); + }); + } + + if (apiConfiguration.FeatureFlags.RunMemberNotificationCompletionConsumer) + { + cfg.ReceiveEndpoint(receiveEndpointConfigurations.MemberNotificationCompletionEndpoint.ReceiveEndpoint, e => + { + e.ConfigureConsumer(context); + e.SetQuorumQueue(); + e.PrefetchCount = receiveEndpointConfigurations.MemberNotificationCompletionEndpoint.PrefetchLimit; + e.UseTimeout(t => t.Timeout = TimeSpan.FromSeconds(420)); + }); + } + + if (apiConfiguration.FeatureFlags.RunGatherMemberNotificationInfoConsumer) + { + cfg.ReceiveEndpoint(receiveEndpointConfigurations.GatherMemberNotificationInfoReceiveEndpoint.ReceiveEndpoint, e => + { + e.ConfigureConsumer(context); + e.SetQuorumQueue(); + e.PrefetchCount = receiveEndpointConfigurations.GatherMemberNotificationInfoReceiveEndpoint.PrefetchLimit; + e.UseTimeout(t => t.Timeout = TimeSpan.FromSeconds(420)); + }); + } + + if (apiConfiguration.FeatureFlags.RunBatchUpdateMemberNotificationDataConsumer) + { + cfg.ReceiveEndpoint(receiveEndpointConfigurations.BatchUpdateMemberNotificationDataEndpoint.ReceiveEndpoint, e => + { + e.ConfigureConsumer(context); + e.SetQuorumQueue(); + e.PrefetchCount = receiveEndpointConfigurations.BatchUpdateMemberNotificationDataEndpoint.PrefetchLimit; + e.UseTimeout(t => t.Timeout = TimeSpan.FromSeconds(420)); + }); + } + if (apiConfiguration.FeatureFlags.RunProcessStatusTypeSummaryConsumer) + { + cfg.ReceiveEndpoint(receiveEndpointConfigurations.ProcessStatusTypeEmailReceiveEndpoint.ReceiveEndpoint, e => + { + e.ConfigureConsumer(context); + e.SetQuorumQueue(); + e.PrefetchCount = receiveEndpointConfigurations.ProcessStatusTypeEmailReceiveEndpoint.PrefetchLimit; + e.UseTimeout(t => t.Timeout = TimeSpan.FromSeconds(420)); + }); + } + }); + }); + services.AddMassTransitHostedService(); +} + +void AddDocumentIngestorServices(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.AddTransient(); + + AddIngestionOperationServices(services); + AddQueueServices(services); + AddIngestorIndexServices(services); + AddIngestorPdfIndexServices(services); + AddIngestorPdfParserServices(services); + AddIngestorProcessingServices(services); + AddMemberNotificationInfoDeterminingServices(services); + AddMicroApiServices(services); + AddValueDeterminingServices(services); +} + +void AddIngestionOperationServices(IServiceCollection services) +{ + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); +} + +void AddQueueServices(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(); +} + +void AddIngestorIndexServices(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(); +} + +void AddIngestorPdfIndexServices(IServiceCollection services) +{ + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); +} + +void AddIngestorPdfParserServices(IServiceCollection services) +{ + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); +} + +void AddIngestorProcessingServices(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(); +} + +void AddMemberNotificationInfoDeterminingServices(IServiceCollection services) +{ + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); +} + +void AddMicroApiServices(IServiceCollection services) +{ + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); +} + +void AddValueDeterminingServices(IServiceCollection services) +{ + services.AddScoped(); + services.AddScoped(); +} + +void AddDocumentIngestorDaos(IServiceCollection services) +{ + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); +} + +void AddDocumentIngestorLib(ref IServiceCollection services) +{ + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); + services.AddScoped(); +} + +void BuildAppAndRun(WebApplicationBuilder builder) +{ + var app = builder.Build(); + + // Configure the HTTP request pipeline. + if (app.Environment.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseSwagger(c=> + { + c.PreSerializeFilters.Add((swaggerDoc, request) => + { + const string prefixHeader = "X-Forwarded-Prefix"; + if (!request.Headers.ContainsKey(prefixHeader)) return; + + var serverUrl = request.Headers[prefixHeader]; + swaggerDoc.Servers = new List() + { + new() { Description = serverUrl, Url = serverUrl } + }; + }); + }); + app.UseSwaggerUI(c => + { + c.RoutePrefix = "swagger"; + c.SwaggerEndpoint("v1/swagger.json", "LCU.API.Internal.DocumentIngestor v1"); + c.OAuthClientId(app.Configuration.GetSection("AzureAd")["ClientId"]); + c.OAuthUsePkce(); + c.OAuthScopes(app.Configuration.GetSection("Swagger")["OAuthScope"]); + }); + app.UseMiddleware(); + app.UseSerilogRequestLogging(options => + { + options.EnrichDiagnosticContext = RequestResponseLoggingMiddleware.RequestDataParser.EnrichFromRequest; + }); + + app.UseRouting(); + app.UseAuthentication(); + app.UseAuthorization(); + app.UseCors(MyAllowSpecificOrigins); + app.UseHttpsRedirection(); + app.MapControllers(); + app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); + + app.Run(); +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Properties/launchSettings.json b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Properties/launchSettings.json new file mode 100644 index 0000000..00b67d4 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Properties/launchSettings.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:30999", + "sslPort": 44346 + } + }, + "profiles": { + "LCU.API.Internal.DocumentIngestor": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7139;http://localhost:5139", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Security/GroupMembershipRequirement.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Security/GroupMembershipRequirement.cs new file mode 100644 index 0000000..4a48d77 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Security/GroupMembershipRequirement.cs @@ -0,0 +1,13 @@ +using Microsoft.AspNetCore.Authorization; + +namespace LCU.API.Internal.DocumentIngestor.Security; + +public class GroupMembershipRequirement : IAuthorizationRequirement +{ + public IReadOnlyCollection Groups { get; } + + public GroupMembershipRequirement(params string[] groups) + { + Groups = groups; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Security/GroupMembershipRequirementHandler.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Security/GroupMembershipRequirementHandler.cs new file mode 100644 index 0000000..07644e4 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Security/GroupMembershipRequirementHandler.cs @@ -0,0 +1,20 @@ +using Microsoft.AspNetCore.Authorization; + +namespace LCU.API.Internal.DocumentIngestor.Security; + +public class GroupMembershipRequirementHandler : AuthorizationHandler +{ + protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, GroupMembershipRequirement requirement) + { + var groups = context.User.Claims.Where(c => c.Type == "groups") + .Concat(context.User.Claims.Where(c => c.Type == "roles")) + .Select(c => c.Value); + + if (groups.Any(requirement.Groups.Contains)) + { + context.Succeed(requirement); + } + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Security/ITRolePolicy.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Security/ITRolePolicy.cs new file mode 100644 index 0000000..2ce96ce --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Security/ITRolePolicy.cs @@ -0,0 +1,11 @@ +using Microsoft.AspNetCore.Authorization; + +namespace LCU.API.Internal.DocumentIngestor.Security; + +public static class ITRolePolicy +{ + public static AuthorizationPolicy PolicyFactory(AuthorizationPolicyBuilder builder, SecurityConfiguration configuration) + => builder.RequireAuthenticatedUser() + .AddRequirements(new GroupMembershipRequirement(configuration.ITRole.Split(","))) + .Build(); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Security/SecurityConfiguration.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Security/SecurityConfiguration.cs new file mode 100644 index 0000000..c4ba2b6 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Security/SecurityConfiguration.cs @@ -0,0 +1,6 @@ +namespace LCU.API.Internal.DocumentIngestor.Security; + +public class SecurityConfiguration +{ + public string ITRole { get; set; } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Security/SetDocumentNotificationStatusPolicy.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Security/SetDocumentNotificationStatusPolicy.cs new file mode 100644 index 0000000..8f3fdf3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Security/SetDocumentNotificationStatusPolicy.cs @@ -0,0 +1,11 @@ +using Microsoft.AspNetCore.Authorization; + +namespace LCU.API.Internal.DocumentIngestor.Security; + +public static class SetDocumentNotificationStatusPolicy +{ + public const string Name = nameof(SetDocumentNotificationStatusPolicy); + + public static AuthorizationPolicy PolicyFactory(AuthorizationPolicyBuilder builder, SecurityConfiguration configuration) + => ITRolePolicy.PolicyFactory(builder, configuration); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/AttributeDeterminingServices/AccountOwnerDeterminingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/AttributeDeterminingServices/AccountOwnerDeterminingService.cs new file mode 100644 index 0000000..99f0443 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/AttributeDeterminingServices/AccountOwnerDeterminingService.cs @@ -0,0 +1,189 @@ +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Utilities; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Extensions; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Mixed; + +namespace LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; + +public class AccountOwnerDeterminingService : BaseOwnerDeterminingService, IAccountOwnerDeterminingService +{ + private readonly ICoreApiWrapperService _coreApiWrapperService; + + public AccountOwnerDeterminingService(ICoreApiWrapperService coreApiWrapperService) + { + _coreApiWrapperService = coreApiWrapperService; + } + + public async Task> DetermineAccountOwnerAttribute(string entityName, + string accountNumber, + DateTime creationDate, + OwnerOverrideInfo ownerOverrideInfo) + { + var accountOwners = await _coreApiWrapperService.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString()); + var accountOwnerAttribute = BuildAccountAttribute(accountNumber, accountOwners, ownerOverrideInfo); + + if (accountOwnerAttribute.PersonNumbers?.Count == 0 && + accountOwnerAttribute.OrganizationNumbers?.Count == 0) + { + var message = + $"A PersonNumber or OrganizationNumber could not be determined for an Account Owner of AccountNumber: {accountNumber} and EntityName: {entityName}. " + + "The DNA call provided no results back."; + return ErrorCaptureResult.CreateErrorPayload(message, accountOwnerAttribute); + } + + if (ownerOverrideInfo != null) + { + return ErrorCaptureResult.CreateSuccessPayload(accountOwnerAttribute); + } + + return CheckPrimaryOwner(entityName, accountOwnerAttribute, accountOwners); + } + + public async Task> DetermineAccountOwnerAttributeByMemberNumberOrUserId(string memberNumberOrUserId, + string accountNumber, + string docType, + DateTime creationDate, + OwnerOverrideInfo ownerOverrideInfo) + { + var accountOwners = await _coreApiWrapperService.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString()); + var accountOwnerAttribute = BuildAccountAttribute(accountNumber, accountOwners, ownerOverrideInfo); + + if (accountOwnerAttribute.PersonNumbers?.Count == 0 && + accountOwnerAttribute.OrganizationNumbers?.Count == 0) + { + var message = + $"A PersonNumber or OrganizationNumber could not be determined for an Account Owner of AccountNumber: {accountNumber} and MemberNumberOrUserId: {memberNumberOrUserId}. " + + "The DNA call provided no results back."; + return ErrorCaptureResult.CreateErrorPayload(message, accountOwnerAttribute); + } + + if (ownerOverrideInfo != null) + { + return ErrorCaptureResult.CreateSuccessPayload(accountOwnerAttribute); + } + + long personNumber = 0; + long orgNumber = 0; + + if ( + EnumExtensions.GetValueFromName(docType) != AccountDocumentTypes.MtgNtOneHundredTen && EnumExtensions.GetValueFromName(docType) != AccountDocumentTypes.OpsNtOneHundredTwentyNine && EnumExtensions.GetValueFromName(docType) != AccountDocumentTypes.DmdNtOneHundredThirtyFour && EnumExtensions.GetValueFromName(docType) != AccountDocumentTypes.NegativeBalanceLetter || + memberNumberOrUserId.ToUpper().StartsWith("M") && + (EnumExtensions.GetValueFromName(docType) == AccountDocumentTypes.MtgNtOneHundredTen || EnumExtensions.GetValueFromName(docType) == AccountDocumentTypes.OpsNtOneHundredTwentyNine || EnumExtensions.GetValueFromName(docType) == AccountDocumentTypes.DmdNtOneHundredThirtyFour || EnumExtensions.GetValueFromName(docType) == AccountDocumentTypes.NegativeBalanceLetter) + ) + { + try + { + PersonOrganization personOrganization = await _coreApiWrapperService.GetPersonOrOrganizationNumberByMemberId(memberNumberOrUserId.ToUpper().TrimStart('M')); + + if(personOrganization.PersonNumber != null) + { + personNumber = long.Parse(personOrganization.PersonNumber); + } + if(personOrganization.OrganizationNumber != null) + { + orgNumber = long.Parse(personOrganization.OrganizationNumber); + } + } + catch (ServiceException ex) + { + return ErrorCaptureResult.CreateErrorPayload(ex.Message, accountOwnerAttribute); + } + } + else + { + try + { + var agreementByMemberNumberOrUserId = await _coreApiWrapperService.GetAgreementByUserId(memberNumberOrUserId); + + personNumber = agreementByMemberNumberOrUserId.PersonNumber; + orgNumber = agreementByMemberNumberOrUserId.ByOrgNbr; + } + catch (Exception ex) + { + return ErrorCaptureResult.CreateErrorPayload(ex.Message, accountOwnerAttribute); + } + } + + try + { + var agreementAccount = await _coreApiWrapperService.GetAgreementAccountByAccountId(accountNumber); + + if (personNumber != agreementAccount.TaxReportForPersonNumber && orgNumber != agreementAccount.TaxReportForOrgNumber) + { + var message = + $"Person numbers ({personNumber}/{agreementAccount.TaxReportForPersonNumber}) and Organization numbers ({orgNumber}/{agreementAccount.TaxReportForOrgNumber}) did not match from GetAgreementAccountByAccountId for Account Number: {accountNumber}"; + return ErrorCaptureResult.CreateErrorPayload(message, accountOwnerAttribute); + } + + return ErrorCaptureResult.CreateSuccessPayload(accountOwnerAttribute); + } + catch (Exception ex) + { + return ErrorCaptureResult.CreateErrorPayload(ex.Message, accountOwnerAttribute); + } + } + + private AccountAttribute BuildAccountAttribute(string accountNumber, IEnumerable accountOwnerships, OwnerOverrideInfo? ownerOverrideInfo) + { + var personNumbers = new List(); + var organizationNumbers = new List(); + + if (ownerOverrideInfo != null) + { + switch (ownerOverrideInfo.EntityType) + { + case EntityTypes.Person: + personNumbers.Add(ownerOverrideInfo.EntityId); + break; + case EntityTypes.Organization: + organizationNumbers.Add(ownerOverrideInfo.EntityId); + break; + } + } + + personNumbers.AddRange(accountOwnerships.Where(person => person.PersonNumber > 0) + .Select(p => p.PersonNumber.ToString())); + + organizationNumbers.AddRange(accountOwnerships.Where(org => org.ByOrgNbr > 0) + .Select(o => o.ByOrgNbr.ToString())); + + return new AccountAttribute + { + AccountNumber = accountNumber, + PersonNumbers = personNumbers.Distinct().ToList(), + OrganizationNumbers = organizationNumbers.Distinct().ToList() + }; + } + + private static ErrorCaptureResult CheckPrimaryOwner(string entityName, AccountAttribute accountAttribute, IEnumerable accountOwnerships) + { + var primaryOwner = accountOwnerships.FirstOrDefault(x => x.IsPrimaryOwner); + + if (primaryOwner == null) + { + var message = $"A PersonNumber or OrganizationNumber could not be determined for an Account Owner of AccountNumber: {accountAttribute.AccountNumber} and EntityName: {entityName}. " + + $"The DNA call provided no primary owner back, but responded with {accountOwnerships.ToDetailString()}"; + return ErrorCaptureResult.CreateErrorPayload(message, accountAttribute); + } + + var doesReturnNameMatch = primaryOwner.PersonNumber > 0 + ? DoesPersonNameMatchExpectedEntityName(primaryOwner, entityName) + : DoesNameMatchExpectedEntityName(primaryOwner.OrganizationName, entityName); + + if (!doesReturnNameMatch) + { + var message = $"A PersonNumber or OrganizationNumber could not be determined for an Account Owner of AccountNumber: {accountAttribute.AccountNumber} and EntityName: {entityName}. " + + $"The DNA call provided a primary owner of: {primaryOwner.ToDetailString()}, which did not match the EntityName"; + return ErrorCaptureResult.CreateErrorPayload(message, accountAttribute); + } + + return ErrorCaptureResult.CreateSuccessPayload(accountAttribute); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/AttributeDeterminingServices/BaseOwnerDeterminingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/AttributeDeterminingServices/BaseOwnerDeterminingService.cs new file mode 100644 index 0000000..41051eb --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/AttributeDeterminingServices/BaseOwnerDeterminingService.cs @@ -0,0 +1,42 @@ +using System.Text.RegularExpressions; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts; + +namespace LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; + +public abstract class BaseOwnerDeterminingService +{ + protected static bool DoesPersonNameMatchExpectedEntityName(AccountOwnership primaryOwner, string entityName) + { + var trimmedFirstName = primaryOwner.FirstName?.Trim(); + var trimmedMiddleName = primaryOwner.MiddleName?.Trim(); + var trimmedMiddleInitial = primaryOwner.MiddleInitial?.Trim(); + var trimmedLastName = primaryOwner.LastName?.Trim(); + var trimmedSuffix = primaryOwner.Suffix?.Trim(); + + var fullNameMiddleInitial = $"{trimmedFirstName} {trimmedMiddleInitial} {trimmedLastName} {trimmedSuffix}"; + var fullNameMiddleName = $"{trimmedFirstName} {trimmedMiddleName} {trimmedLastName} {trimmedSuffix}"; + var fullNameMiddleInitialNoSuffix = $"{trimmedFirstName} {trimmedMiddleInitial} {trimmedLastName}"; + var fullNameMiddleNameNoSuffix = $"{trimmedFirstName} {trimmedMiddleName} {trimmedLastName}"; + var firstNameLastName = $"{trimmedFirstName} {trimmedLastName}"; + + return DoesNameMatchExpectedEntityName(entityName, fullNameMiddleInitial) || + DoesNameMatchExpectedEntityName(entityName, fullNameMiddleName) || + DoesNameMatchExpectedEntityName(entityName, fullNameMiddleInitialNoSuffix) || + DoesNameMatchExpectedEntityName(entityName, fullNameMiddleNameNoSuffix) || + DoesNameMatchExpectedEntityName(entityName, firstNameLastName); + } + + protected static bool DoesNameMatchExpectedEntityName(string name, string expectedName) + { + var trimmedOrganizationName = RemoveSpecialCharactersAndSpacing(name); + return RemoveSpecialCharactersAndSpacing(expectedName).Equals(trimmedOrganizationName, StringComparison.InvariantCultureIgnoreCase); + } + protected static string RemoveSpecialCharactersAndSpacing(string name) + { + var nonSpecialString = string.IsNullOrWhiteSpace(name) + ? "" + : Regex.Replace(name.Trim(), @"[^0-9a-zA-Z\-\&\s*]+", ""); + var nonSpecialStringSpacing = nonSpecialString.Trim().Replace(" ", " "); + return nonSpecialStringSpacing.Length > 39 ? nonSpecialStringSpacing[..40].Trim() : nonSpecialStringSpacing; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/AttributeDeterminingServices/IAccountOwnerDeterminingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/AttributeDeterminingServices/IAccountOwnerDeterminingService.cs new file mode 100644 index 0000000..d163a22 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/AttributeDeterminingServices/IAccountOwnerDeterminingService.cs @@ -0,0 +1,18 @@ +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; + +namespace LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; + +public interface IAccountOwnerDeterminingService +{ + Task> DetermineAccountOwnerAttribute(string entityName, + string accountNumber, + DateTime creationDate, + OwnerOverrideInfo overrideRequest); + Task> DetermineAccountOwnerAttributeByMemberNumberOrUserId(string id, + string accountNumber, + string docType, + DateTime creationDate, + OwnerOverrideInfo ownerOverrideInfo); +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/AttributeDeterminingServices/IPrimaryOwnerDeterminingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/AttributeDeterminingServices/IPrimaryOwnerDeterminingService.cs new file mode 100644 index 0000000..1a0c3d2 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/AttributeDeterminingServices/IPrimaryOwnerDeterminingService.cs @@ -0,0 +1,28 @@ +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; + +namespace LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; + +public interface IPrimaryOwnerDeterminingService +{ + Task> DeterminePrimaryOwnerAttribute(string entityName, + string accountNumber, + string taxId, + OwnerOverrideInfo overrideRequest); + + Task> DeterminePrimaryOwnerAttribute(string entityName, + string accountNumber, + DateTime creationDate, + OwnerOverrideInfo overrideRequest); + + Task> DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(string id, + string accountNumber, + string docType, + DateTime creationDate, + OwnerOverrideInfo overrideRequest); + + Task> DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(string memberNumberOrUserId, + string entityName, + OwnerOverrideInfo overrideRequest); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/AttributeDeterminingServices/PrimaryOwnerDeterminingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/AttributeDeterminingServices/PrimaryOwnerDeterminingService.cs new file mode 100644 index 0000000..6f616a6 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/AttributeDeterminingServices/PrimaryOwnerDeterminingService.cs @@ -0,0 +1,418 @@ +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Utilities; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Extensions; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Mixed; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Tax; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; + +namespace LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; + +public class PrimaryOwnerDeterminingService : BaseOwnerDeterminingService, IPrimaryOwnerDeterminingService +{ + private readonly ICoreApiWrapperService _coreApiWrapperService; + + public PrimaryOwnerDeterminingService(ICoreApiWrapperService coreApiWrapperService) + { + _coreApiWrapperService = coreApiWrapperService; + } + + public async Task> DeterminePrimaryOwnerAttribute(string entityName, + string accountNumber, + DateTime creationDate, + OwnerOverrideInfo overrideRequest) + { + + if (overrideRequest != null) + { + return await OverridePrimaryOwnerAttribute(accountNumber, overrideRequest); + } + + var primaryOwnerAttribute = new PrimaryOwnerAttribute + { + AccountNumber = accountNumber + }; + + var accountOwnerships = await _coreApiWrapperService.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString()); + + if (!accountOwnerships.Any()) + { + var message = $"A PersonNumber or OrganizationNumber could not be determined for a Primary Owner of AccountNumber: {accountNumber} and EntityName: {entityName}. " + + "The DNA call provided no results back."; + return ErrorCaptureResult.CreateErrorPayload(message, primaryOwnerAttribute); + } + + var primaryOwners = accountOwnerships.Where(account => account.IsPrimaryOwner).ToList(); + + if (primaryOwners.Count != 1) + { + var message = $"A PersonNumber or OrganizationNumber could not be determined for an Account Owner of AccountNumber: {accountNumber} and EntityName: {entityName}. " + + $"The DNA call provided no single primary owner back, but responded with {accountOwnerships.ToDetailString()}"; + return ErrorCaptureResult.CreateErrorPayload(message, primaryOwnerAttribute); + } + + var primaryOwner = primaryOwners.First(); + + var doesReturnNameMatch = primaryOwner.PersonNumber > 0 + ? DoesPersonNameMatchExpectedEntityName(primaryOwner, entityName) + : DoesNameMatchExpectedEntityName(primaryOwner.OrganizationName, entityName); + + if (!doesReturnNameMatch) + { + var message = $"A PersonNumber or OrganizationNumber could not be determined for an Account Owner of AccountNumber: {accountNumber} and EntityName: {entityName}. " + + $"The DNA call provided a primary owner of: {primaryOwner.ToDetailString()}, which did not match the EntityName"; + return ErrorCaptureResult.CreateErrorPayload(message, primaryOwnerAttribute); + } + + if (primaryOwner.PersonNumber > 0) + { + primaryOwnerAttribute.PersonNumber = primaryOwner.PersonNumber.ToString(); + } + else + { + primaryOwnerAttribute.OrganizationNumber = primaryOwner.ByOrgNbr.ToString(); + } + + return ErrorCaptureResult.CreateSuccessPayload(primaryOwnerAttribute); + } + + public async Task> DeterminePrimaryOwnerAttribute(string entityName, + string accountNumber, + string taxId, + OwnerOverrideInfo overrideRequest) + { + if (overrideRequest != null) + { + return await OverridePrimaryOwnerAttribute(accountNumber, overrideRequest); + } + + var primaryOwnerAttribute = new PrimaryOwnerAttribute + { + AccountNumber = accountNumber + }; + + var personsTaxIdData = await _coreApiWrapperService.GetPersonsTaxIdData(taxId); + var personTaxIdDataResponses = personsTaxIdData.ToList(); + + if (DetermineIfPrimaryOwnerIsPerson(entityName, personTaxIdDataResponses, primaryOwnerAttribute, out var errorCaptureResult)) + { + return errorCaptureResult; + } + + var organizationTaxIdData = await _coreApiWrapperService.GetOrganizationsTaxIdData(taxId); + var organizationTaxIdDataResponses = organizationTaxIdData.ToList(); + + if (DetermineIfPrimaryOwnerIsOrganization(entityName, organizationTaxIdDataResponses, primaryOwnerAttribute, out var successPayload)) + { + return successPayload; + } + + if (!organizationTaxIdDataResponses.Any() && !personTaxIdDataResponses.Any()) + { + var message = $"A PersonNumber or OrganizationNumber could not be determined for an Account Owner of AccountNumber: {accountNumber}, Tin: {taxId} and EntityName: {entityName}. " + + "The DNA call provided no results back."; + return ErrorCaptureResult.CreateErrorPayload(message, primaryOwnerAttribute); + } + + var errorMessage = $"A PersonNumber or OrganizationNumber could not be determined for an Account Owner of AccountNumber: {accountNumber}, Tin: {taxId} and EntityName: {entityName}. " + + "The DNA call provided no primary owner back, but responded with " + + string.Join + ( + "; ", + personTaxIdDataResponses.ToDetailString(), + organizationTaxIdDataResponses.ToDetailString() + ); + + return ErrorCaptureResult.CreateErrorPayload(errorMessage, primaryOwnerAttribute); + } + + public async Task> DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(string memberNumberOrUserId, + string accountNumber, + string docType, + DateTime creationDate, + OwnerOverrideInfo overrideRequest) + { + if (overrideRequest != null) + { + return await OverridePrimaryOwnerAttribute(accountNumber, overrideRequest); + } + + var primaryOwnerAttribute = new PrimaryOwnerAttribute() + { + AccountNumber = accountNumber + }; + + Agreement? agreementByMemberNumberOrUserId; + long personNumber = 0; + long orgNumber = 0; + + if ( + memberNumberOrUserId.ToUpper().StartsWith("M") || + EnumExtensions.GetValueFromName(docType) == PrimaryOwnerDocumentTypes.MmStmxt + ) + { + try + { + PersonOrganization personOrganization = await _coreApiWrapperService.GetPersonOrOrganizationNumberByMemberId(memberNumberOrUserId.ToUpper().TrimStart('M')); + + if (personOrganization.PersonNumber != null) + { + personNumber = long.Parse(personOrganization.PersonNumber); + } + else if (personOrganization.OrganizationNumber != null) + { + orgNumber = long.Parse(personOrganization.OrganizationNumber); + } + else + { + return ErrorCaptureResult.CreateErrorPayload($"Error finding PersonOrganization by MemberId: {memberNumberOrUserId}", primaryOwnerAttribute); + } + } + catch (ServiceException ex) + { + return ErrorCaptureResult.CreateErrorPayload(ex.Message, primaryOwnerAttribute); + } + } + else + { + try + { + agreementByMemberNumberOrUserId = await _coreApiWrapperService.GetAgreementByUserId(memberNumberOrUserId); + + if (agreementByMemberNumberOrUserId == null) + { + var message = + $"An agreement could not be found from GetAgreementByUserId for User ID: {memberNumberOrUserId}"; + return ErrorCaptureResult.CreateErrorPayload(message, primaryOwnerAttribute); + } + + personNumber = agreementByMemberNumberOrUserId.PersonNumber; + orgNumber = agreementByMemberNumberOrUserId.ByOrgNbr; + } catch (ServiceException ex) + { + return ErrorCaptureResult.CreateErrorPayload(ex.Message, primaryOwnerAttribute); + } + } + + if (EnumExtensions.GetValueFromName(docType) == PrimaryOwnerDocumentTypes.MmStmxt) + { + try + { + var agreementAccount = await _coreApiWrapperService.GetAgreementAccountByAccountId(accountNumber); + + if (agreementAccount == null) + { + var message = + $"An agreement account could not be found from GetAgreementAccountByAccountId for Account Number: {accountNumber}"; + return ErrorCaptureResult.CreateErrorPayload(message, primaryOwnerAttribute); + } + + if (personNumber != agreementAccount.TaxReportForPersonNumber && orgNumber != agreementAccount.TaxReportForOrgNumber) + { + var message = + $"Person numbers ({personNumber}/{agreementAccount.TaxReportForPersonNumber}) and Organization numbers ({orgNumber}/{agreementAccount.TaxReportForOrgNumber}) did not match from GetAgreementAccountByAccountId for Account Number: {accountNumber}"; + return ErrorCaptureResult.CreateErrorPayload(message, primaryOwnerAttribute); + } + + } + catch (ServiceException ex) + { + return ErrorCaptureResult.CreateErrorPayload(ex.Message, primaryOwnerAttribute); + } + } + + if (orgNumber == 0) + { + primaryOwnerAttribute.PersonNumber = personNumber.ToString(); + } + else + { + primaryOwnerAttribute.OrganizationNumber = orgNumber.ToString(); + } + + return ErrorCaptureResult.CreateSuccessPayload(primaryOwnerAttribute); + } + + public async Task> DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(string memberNumberOrUserId, + string entityName, + OwnerOverrideInfo overrideRequest) + { + var primaryOwnerAttribute = new PrimaryOwnerAttribute(); + + if (overrideRequest != null) + { + return await OverridePrimaryOwnerAttribute(null, overrideRequest); + } + + Agreement? agreementByMemberNumberOrUserId; + var returnedName = string.Empty; + long personNumber = 0; + long orgNumber = 0; + + if (memberNumberOrUserId.ToUpper().StartsWith("M") || memberNumberOrUserId.ToUpper().StartsWith("C")) + { + try + { + PersonOrganization personOrganization = await _coreApiWrapperService.GetPersonOrOrganizationNumberByMemberId(memberNumberOrUserId.ToUpper().TrimStart('M').TrimStart('C')); + + if (personOrganization.PersonNumber != null) + { + personNumber = long.Parse(personOrganization.PersonNumber); + returnedName = personOrganization.EntityName; + } + else if (personOrganization.OrganizationNumber != null) + { + orgNumber = long.Parse(personOrganization.OrganizationNumber); + returnedName = personOrganization.EntityName; + } + else + { + return ErrorCaptureResult.CreateErrorPayload($"Error finding PersonOrganization by MemberId: {memberNumberOrUserId}", primaryOwnerAttribute); + } + } + catch (ServiceException ex) + { + return ErrorCaptureResult.CreateErrorPayload(ex.Message, primaryOwnerAttribute); + } + } + else + { + try + { + agreementByMemberNumberOrUserId = await _coreApiWrapperService.GetAgreementByUserId(memberNumberOrUserId); + + if (agreementByMemberNumberOrUserId == null) + { + // Checking to make sure UserId is not improperly mapped memberNumber + PersonOrganization personOrganization = await _coreApiWrapperService.GetPersonOrOrganizationNumberByMemberId(memberNumberOrUserId.ToUpper().TrimStart('M').TrimStart('C')); + + if (personOrganization.PersonNumber != null) + { + personNumber = long.Parse(personOrganization.PersonNumber); + returnedName = personOrganization.EntityName; + } + else if (personOrganization.OrganizationNumber != null) + { + orgNumber = long.Parse(personOrganization.OrganizationNumber); + returnedName = personOrganization.EntityName; + } + else + { + var message = + $"An agreement could not be found from GetAgreementByUserId for User ID: {memberNumberOrUserId}"; + return ErrorCaptureResult.CreateErrorPayload(message, primaryOwnerAttribute); + } + + } + else + { + personNumber = agreementByMemberNumberOrUserId.PersonNumber; + orgNumber = agreementByMemberNumberOrUserId.ByOrgNbr; + + if (orgNumber == 0) + { + returnedName = $"{agreementByMemberNumberOrUserId.FirstName} {agreementByMemberNumberOrUserId.MiddleInitial} {agreementByMemberNumberOrUserId.LastName} {agreementByMemberNumberOrUserId.Suffix}"; + } + else + { + returnedName = agreementByMemberNumberOrUserId.OrganizationName; + } + } + + } catch (ServiceException ex) + { + return ErrorCaptureResult.CreateErrorPayload(ex.Message, primaryOwnerAttribute); + } + } + + if (!DoesNameMatchExpectedEntityName(returnedName, entityName)) + { + var message = + $"The entityName ({entityName}) did not match from GetAgreementAccountByAccountId for returnedName: {returnedName}"; + return ErrorCaptureResult.CreateErrorPayload(message, primaryOwnerAttribute); + } + + if (orgNumber == 0) + { + primaryOwnerAttribute.PersonNumber = personNumber.ToString(); + } + else + { + primaryOwnerAttribute.OrganizationNumber = orgNumber.ToString(); + } + + return ErrorCaptureResult.CreateSuccessPayload(primaryOwnerAttribute); + } + + private async Task> OverridePrimaryOwnerAttribute(string accountNumber, OwnerOverrideInfo request) + { + var primaryOwnerAttribute = new PrimaryOwnerAttribute() + { + AccountNumber = accountNumber, + PersonNumber = request.EntityType == EntityTypes.Person ? request.EntityId : null, + OrganizationNumber = request.EntityType == EntityTypes.Organization ? request.EntityId : null, + }; + + return ErrorCaptureResult.CreateSuccessPayload(primaryOwnerAttribute); + } + + private static bool DetermineIfPrimaryOwnerIsPerson(string entityName, + IReadOnlyCollection personTaxIdDataResponses, + PrimaryOwnerAttribute primaryOwnerAttribute, + out ErrorCaptureResult? errorCaptureResult) + { + errorCaptureResult = null; + + if (!personTaxIdDataResponses.Any()) + { + return false; + } + var personNumber = personTaxIdDataResponses + .Where(person => DoesNameMatchExpectedEntityName(person.NameLastFirstMiddleSuffix, entityName)) + .Select(p => p.PersonNumber).FirstOrDefault(); + + var personNumberString = personNumber <= 0 ? null : personNumber.ToString(); + + if (string.IsNullOrEmpty(personNumberString)) + { + return false; + } + + primaryOwnerAttribute.PersonNumber = personNumberString; + errorCaptureResult = ErrorCaptureResult.CreateSuccessPayload(primaryOwnerAttribute); + return true; + } + + private static bool DetermineIfPrimaryOwnerIsOrganization(string entityName, + IReadOnlyCollection organizationTaxIdDataResponses, + PrimaryOwnerAttribute primaryOwnerAttribute, + out ErrorCaptureResult? successPayload) + { + successPayload = null; + + if (!organizationTaxIdDataResponses.Any()) + { + return false; + } + + var organizationNumber = organizationTaxIdDataResponses + .Where(org => DoesNameMatchExpectedEntityName(org.Name, entityName)) + .Select(p => p.OrganizationNumber).FirstOrDefault(); + + var organizationNumberString = organizationNumber != 0 ? organizationNumber.ToString() : null; + + if (string.IsNullOrEmpty(organizationNumberString)) + { + return false; + } + + primaryOwnerAttribute.OrganizationNumber = organizationNumberString; + successPayload = ErrorCaptureResult.CreateSuccessPayload(primaryOwnerAttribute); + return true; + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessingInfoService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessingInfoService.cs new file mode 100644 index 0000000..98e9c03 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessingInfoService.cs @@ -0,0 +1,638 @@ +using System.Data.SqlClient; +using Serilog; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestorLib.Repositories; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.Library.Internal.DocumentIngestorModels.Constants; + +namespace LCU.API.Internal.DocumentIngestor.Services; + +public class DocumentProcessingInfoService : IDocumentProcessingInfoService +{ + private readonly IUnitOfWork _unitOfWork; + private readonly IDocumentProcessingInfoRepository _documentProcessingInfoRepository; + private readonly IProcessingLogService _processingLogService; + private readonly Dictionary> _statusChangeRejectionList = + new () + { + [ProcessStatusTypes.Processing] = new() + { + ProcessStatusTypes.Reprocessing, + ProcessStatusTypes.UploadCompletionReprocessing + }, + [ProcessStatusTypes.Completed] = new() + { + ProcessStatusTypes.Processing, + ProcessStatusTypes.Completed, + ProcessStatusTypes.ArchiveFailure, + ProcessStatusTypes.CriticalFailure, + ProcessStatusTypes.DataMappingFailure, + ProcessStatusTypes.Reprocessing, + ProcessStatusTypes.NotificationDataFailure, + ProcessStatusTypes.UploadCompletionReprocessing + }, + [ProcessStatusTypes.ArchiveFailure] = new() + { + ProcessStatusTypes.UploadCompletionReprocessing + }, + [ProcessStatusTypes.CriticalFailure] = new() + { + ProcessStatusTypes.UploadCompletionReprocessing + }, + [ProcessStatusTypes.DataMappingFailure] = new() + { + ProcessStatusTypes.Processing, + ProcessStatusTypes.Completed, + ProcessStatusTypes.ArchiveFailure, + ProcessStatusTypes.CriticalFailure, + ProcessStatusTypes.DataMappingFailure, + ProcessStatusTypes.Reprocessing, + ProcessStatusTypes.NotificationDataFailure, + ProcessStatusTypes.UploadCompletionReprocessing + }, + [ProcessStatusTypes.Reprocessing] = new() + { + ProcessStatusTypes.Processing, + ProcessStatusTypes.UploadCompletionReprocessing + }, + [ProcessStatusTypes.NotificationDataFailure] = new() + { + ProcessStatusTypes.Processing, + ProcessStatusTypes.ArchiveFailure, + ProcessStatusTypes.CriticalFailure, + ProcessStatusTypes.DataMappingFailure, + ProcessStatusTypes.Reprocessing, + ProcessStatusTypes.UploadCompletionReprocessing + }, + [ProcessStatusTypes.UploadCompletionReprocessing] = new() + { + ProcessStatusTypes.Processing, + ProcessStatusTypes.ArchiveFailure, + ProcessStatusTypes.CriticalFailure, + ProcessStatusTypes.DataMappingFailure, + ProcessStatusTypes.Reprocessing + } + + }; + + public DocumentProcessingInfoService(IUnitOfWork unitOfWork, + IDocumentProcessingInfoRepository documentProcessingInfoRepository, + IProcessingLogService processingLogService) + { + _unitOfWork = unitOfWork; + _documentProcessingInfoRepository = documentProcessingInfoRepository; + _processingLogService = processingLogService; + } + + public async Task> GetAsync() + { + try + { + var documentProcessingInfos = await _documentProcessingInfoRepository.FindAsync(); + return documentProcessingInfos; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving DocumentProcessingInfos."); + throw new ServiceException($"Failure retrieving DocumentProcessingInfos."); + } + } + + public async Task GetByIdAsync(int id) + { + try + { + var documentProcessingInfo = await _documentProcessingInfoRepository.FindByIdAsync(id); + return documentProcessingInfo; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving DocumentProcessingInfo with DocumentProcessingInfoId {id}."); + throw new ServiceException($"Failure retrieving DocumentProcessingInfo with DocumentProcessingInfoId {id}."); + } + } + + public async Task> GetListByIdAsync(List ids) + { + try + { + var documentProcessingInfo = await _documentProcessingInfoRepository.FindListByIdAsync(ids); + return documentProcessingInfo; + } + catch (Exception exception) + { + var message = $"Failure retrieving list of DocumentProcessingInfos with DocumentProcessingInfoIds: {String.Join(", ", ids.ToArray())}."; + Log.Error(exception, message); + throw new ServiceException(message); + } + } + + public async Task> GetByIngestorRunInfoIdAsync(Guid ingestorRunInfoId) + { + try + { + var documentProcessingInfos = await _documentProcessingInfoRepository.FindByIngestorRunInfoIdAsync(ingestorRunInfoId); + return documentProcessingInfos; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving DocumentProcessingInfos with IngestorRunInfoId {ingestorRunInfoId}."); + throw new ServiceException($"Failure retrieving DocumentProcessingInfos with IngestorRunInfoId {ingestorRunInfoId}."); + } + } + + public async Task> GetByProcessStatusTypeAsync(ProcessStatusTypes statusType, bool? isUnknown = null) + { + try + { + return await _documentProcessingInfoRepository.FindByProcessStatusTypeAsync(statusType, isUnknown); + } + catch (Exception exception) + { + var message = $"Failure retrieving DocumentProcessingInfos with Process Status Type {statusType}. " + + "IsUnknown: " + (isUnknown is null ? "null" : isUnknown.ToString()); + Log.Error(exception, message); + throw new ServiceException(message); + } + } + + public async Task> GetByProcessStatusTypeListAsync(List statusTypes, bool? isUnknown = null) + { + try + { + return await _documentProcessingInfoRepository.FindByProcessStatusTypeListAsync(statusTypes, isUnknown); + } + catch (Exception exception) + { + var message = $"Failure retrieving DocumentProcessingInfos with Process Status Type {(statusTypes is null ? "null" : string.Join(",", statusTypes))}. " + + "IsUnknown: " + (isUnknown is null ? "null" : isUnknown.ToString()); + Log.Error(exception, message); + throw new ServiceException(message); + } + + } + + public async Task> GetCompletedFirstPassByIngestorRunInfoIdAsync(Guid ingestorRunInfoId) + { + try + { + return await _documentProcessingInfoRepository.FindCompletedFirstPassByIngestorRunInfoIdAsync(ingestorRunInfoId); + } + catch (Exception exception) + { + var message = + "Failure retrieving CompletedFirstPassByIngestorRunInfoId DocumentProcessingInfos. " + + $"IngestorRunInfoId: {ingestorRunInfoId}"; + Log.Error(exception, message); + throw new ServiceException(message); + } + } + + public async Task SaveAsync(DocumentProcessingInfo documentProcessingInfo) + { + try + { + var result = await _documentProcessingInfoRepository.AddAsync(documentProcessingInfo); + await _unitOfWork.CompleteAsync(); + return result; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure saving DocumentProcessingInfo."); + throw new ServiceException($"Failure saving DocumentProcessingInfo."); + } + } + + public async Task SaveRangeAsync(DocumentProcessingInfo[] documentProcessingInfos) + { + try + { + await _documentProcessingInfoRepository.AddRangeAsync(documentProcessingInfos); + await _unitOfWork.CompleteAsync(); + } + catch (Exception exception) + { + Log.Error(exception, "Failure saving range DocumentProcessingInfo."); + throw new ServiceException("Failure saving range DocumentProcessingInfo."); + } + } + + public async Task UpdateStatusAndAddLog(int documentProcessingInfoId, + ProcessStatusTypes statusType, + string logMessage, + string userName, + bool? entityIsUnknown = null) + { + return await UpdateStatusAndAddLog(documentProcessingInfoId, statusType, new List(new string[] { logMessage }), userName, entityIsUnknown); + } + + public async Task UpdateStatusAndAddLog(int documentProcessingInfoId, + ProcessStatusTypes statusType, + List logMessages, + string userName, + bool? entityIsUnknown = null) + { + try + { + var documentProcessingInfo = await GetByIdAsync(documentProcessingInfoId); + return await UpdateStatusAndAddLog(documentProcessingInfo, statusType, logMessages, userName, entityIsUnknown); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure Updating Status and Adding Processing Log. DocumentProcessingInfoId: {documentProcessingInfoId}"); + throw new ServiceException($"Failure Updating Status and Adding Processing Log. DocumentProcessingInfoId: {documentProcessingInfoId}"); + } + } + + public async Task UpdateStatusAndAddLog(DocumentProcessingInfo documentProcessingInfo, + ProcessStatusTypes statusType, + string logMessage, + string userName, + bool? entityIsUnknown = null) + { + return await UpdateStatusAndAddLog(documentProcessingInfo, statusType, new List(new string[] { logMessage }), userName, entityIsUnknown); + } + + public async Task UpdateStatusAndAddLog(DocumentProcessingInfo documentProcessingInfo, + ProcessStatusTypes statusType, + List logMessages, + string userName, + bool? entityIsUnknown = null) + { + try + { + ArgumentNullException.ThrowIfNull(documentProcessingInfo); + + documentProcessingInfo.StatusType = statusType; + if (entityIsUnknown is not null) + { + documentProcessingInfo.EntityUnknown = entityIsUnknown ?? documentProcessingInfo.EntityUnknown; + } + var updated = await Update(documentProcessingInfo); + if (updated == null) + { + return null; + } + + foreach (var log in logMessages) + { + if (string.IsNullOrWhiteSpace(log)) continue; + var processingLog = new ProcessingLog(updated.DocumentProcessingInfoId, DateTime.Now, log, userName); + await _processingLogService.SaveAsync(processingLog); + } + + return updated; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure Updating Status and Adding Processing Log. DocumentProcessingInfoId: {documentProcessingInfo.DocumentProcessingInfoId}"); + throw new ServiceException($"Failure Updating Status and Adding Processing Log. DocumentProcessingInfoId: {documentProcessingInfo.DocumentProcessingInfoId}"); + } + } + + public async Task UpdateProcessCountAndStatusAndAddLog(int documentProcessingInfoId, + ProcessStatusTypes statusType, + string logMessage, + string userName, + bool? entityIsUnknown = null) + { + return await UpdateProcessCountAndStatusAndAddLog(documentProcessingInfoId, statusType, new List(new string[] { logMessage }), userName, entityIsUnknown); + } + + public async Task UpdateProcessCountAndStatusAndAddLog(int documentProcessingInfoId, + ProcessStatusTypes statusType, + List logMessages, + string userName, + bool? entityIsUnknown = null) + { + try + { + var documentProcessingInfo = await GetByIdAsync(documentProcessingInfoId); + return await UpdateProcessCountAndStatusAndAddLog(documentProcessingInfo, statusType, logMessages, userName, entityIsUnknown); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure Updating Process Count, Status, and Adding Processing Log. DocumentProcessingInfoId: {documentProcessingInfoId}"); + throw new ServiceException($"Failure Updating Process Count, Status, and Adding Processing Log. DocumentProcessingInfoId: {documentProcessingInfoId}"); + } + } + + public async Task> UpdateProcessCountAndStatusAndAddLog(List requests) + { + var processingLogs = new List(); + var documentProcessingInfos = await GetListByIdAsync(requests.Select(r => r.ProcessingRequest.DocumentProcessingInfoId).ToList()); + + var completionProcessingDatas = PairCompletionRequestAndDocumentProcessingInfo(requests, documentProcessingInfos); + + foreach (var data in completionProcessingDatas) + { + data.DocumentProcessingInfo.ProcessCount++; + data.DocumentProcessingInfo.StatusType = data.CompletionRequest.ProcessResult.ProcessStatusType; + data.DocumentProcessingInfo.EntityUnknown = data.CompletionRequest.ProcessResult.EntityIsUnknown ?? data.DocumentProcessingInfo.EntityUnknown; + if(data.CompletionRequest.ProcessResult.MessageStack != null || data.CompletionRequest.ProcessResult.MessageStack.Count > 0) + { + foreach (var message in data.CompletionRequest.ProcessResult.MessageStack) + { + if (string.IsNullOrWhiteSpace(message)) continue; + processingLogs.Add(new ProcessingLog(data.CompletionRequest.ProcessingRequest.DocumentProcessingInfoId, DateTime.Now, message, Users.System)); + } + } + } + + await UpdateRangeAsync(completionProcessingDatas.Select(d => d.DocumentProcessingInfo).ToList()); + if (processingLogs.Count() >= 1) + { + await _processingLogService.SaveRangeAsync(processingLogs); + } + return completionProcessingDatas; + } + + public async Task UpdateProcessCountAndStatusAndAddLog(DocumentProcessingInfo documentProcessingInfo, + ProcessStatusTypes statusType, + string logMessage, + string userName, + bool? entityIsUnknown = null) + { + return await UpdateProcessCountAndStatusAndAddLog(documentProcessingInfo, statusType, new List(new string[] { logMessage }), userName, entityIsUnknown); + } + + public async Task UpdateProcessCountAndStatusAndAddLog(DocumentProcessingInfo documentProcessingInfo, + ProcessStatusTypes statusType, + List logMessages, + string userName, + bool? entityIsUnknown = null) + { + try + { + ArgumentNullException.ThrowIfNull(documentProcessingInfo); + documentProcessingInfo.ProcessCount++; + return await UpdateStatusAndAddLog(documentProcessingInfo, statusType, logMessages, userName, entityIsUnknown); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure Updating Process Count, Status, and Adding Processing Log. DocumentProcessingInfoId: {documentProcessingInfo.DocumentProcessingInfoId}"); + throw new ServiceException($"Failure Updating Process Count, Status, and Adding Processing Log. DocumentProcessingInfoId: {documentProcessingInfo.DocumentProcessingInfoId}"); + } + } + + public List PairCompletionRequestAndDocumentProcessingInfo(List requests, IEnumerable documentProcessingInfos) + { + var completionProcessingDatas = new List(); + foreach (var request in requests) + { + var documentProcessingInfo = documentProcessingInfos.Where(d => d.DocumentProcessingInfoId == request.ProcessingRequest.DocumentProcessingInfoId).FirstOrDefault(); + if (documentProcessingInfo is null) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error(new Exception(), $"Failure during PairCompletionRequestAndDocumentProcessingInfo. " + + $"The DocumentProcessingInfo was not found for DocumentProcessingInfoId: {request.ProcessingRequest.DocumentProcessingInfoId}"); + continue; + } + completionProcessingDatas.Add(new CompletionProcessingData() { CompletionRequest = request, DocumentProcessingInfo = documentProcessingInfo }); + } + return completionProcessingDatas; + } + + public async Task Update(DocumentProcessingInfo documentProcessingInfo) + { + try + { + var existing = await GetByIdAsync(documentProcessingInfo.DocumentProcessingInfoId); + if (existing == null) + { + return existing; + } + + existing.CreatedDate = documentProcessingInfo.CreatedDate; + existing.DocumentValuePayload = documentProcessingInfo.DocumentValuePayload; + existing.StatusType = documentProcessingInfo.StatusType; + existing.EntityUnknown = documentProcessingInfo.EntityUnknown; + + _documentProcessingInfoRepository.Update(existing); + _unitOfWork.Complete(); + + return existing; + } + catch (SqlException sqlException) + { + Log.Error(sqlException, $"SQL Failure updating DocumentProcessingInfo. " + + $"DocumentProcessingInfoId: {documentProcessingInfo.DocumentProcessingInfoId}"); + throw new ServiceException($"SQL Failure updating DocumentProcessingInfo. " + + $"DocumentProcessingInfoId: {documentProcessingInfo.DocumentProcessingInfoId}"); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure updating DocumentProcessingInfo. " + + $"DocumentProcessingInfoId: {documentProcessingInfo.DocumentProcessingInfoId}"); + throw new ServiceException($"Failure updating DocumentProcessingInfo. " + + $"DocumentProcessingInfoId: {documentProcessingInfo.DocumentProcessingInfoId}"); + } + } + + public async Task> UpdateRangeAsync(IEnumerable documentProcessingInfos) + { + try + { + var infos = documentProcessingInfos.ToList(); + + _documentProcessingInfoRepository.UpdateRange(infos); + await _unitOfWork.CompleteAsync(); + return infos; + } + catch (SqlException sqlException) + { + var message = "SQL Failure updating list of DocumentProcessingInfos."; + Log.Error(sqlException, message); + throw new ServiceException(message); + } + catch (Exception exception) + { + var message = "Failure updating list of DocumentProcessingInfos."; + Log.Error(exception, message); + throw new ServiceException(message); + } + } + + public async Task Delete(int id) + { + try + { + var documentProcessingInfo = await GetByIdAsync(id); + ArgumentNullException.ThrowIfNull(documentProcessingInfo); + _documentProcessingInfoRepository.Remove(documentProcessingInfo); + _unitOfWork.Complete(); + } + catch (SqlException sqlException) + { + Log.Error(sqlException, $"SQL failure removing DocumentProcessingInfo. DocumentProcessingInfoId: {id}"); + throw new ServiceException($"SQL failure removing DocumentProcessingInfo. DocumentProcessingInfoId: {id}"); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure removing DocumentProcessingInfo. DocumentProcessingInfoId: {id}"); + throw new ServiceException($"Failure removing DocumentProcessingInfo. DocumentProcessingInfoId: {id}"); + } + } + + public async Task> GetFilteredDocumentProcessingInfo(Filter filter) + { + try + { + return await _documentProcessingInfoRepository.FilteredListAsync(filter); + } + catch (Exception exception) + { + Log.Error(exception, "Failure retrieving filtered documentProcessingInfo."); + throw new ServiceException("Failure retrieving filtered documentProcessingInfo."); + } + } + + public async Task CountCompletedByIngestorRunInfoIdAsync(Guid ingestorRunInfoId) + { + try + { + return await _documentProcessingInfoRepository.CountCompletedByIngestorRunInfoIdAsync(ingestorRunInfoId); + } + catch (Exception exception) + { + Log.Error(exception, "Failure counting CompletedByIngestorRunInfoId DocumentProcessingInfos for run info {IngestorRunInfoId}", ingestorRunInfoId); + throw new ServiceException($"Failure counting CompletedByIngestorRunInfoId DocumentProcessingInfos for run info {ingestorRunInfoId}"); + } + } + + public async Task CountCompletedFirstPassByIngestorRunInfoIdAsync(Guid ingestorRunInfoId) + { + try + { + return await _documentProcessingInfoRepository.CountCompletedFirstPassByIngestorRunInfoIdAsync(ingestorRunInfoId); + } + catch (Exception exception) + { + Log.Error(exception, "Failure counting CompletedFirstPassByIngestorRunInfoId DocumentProcessingInfos for run info {IngestorRunInfoId}", ingestorRunInfoId); + throw new ServiceException($"Failure counting CompletedFirstPassByIngestorRunInfoId DocumentProcessingInfos for run info {ingestorRunInfoId}"); + } + } + + public async Task?> SetDocumentsToEntityUnknown(EntityUnknownRequest request) + { + try + { + var documentProcessingInfos = await GetListByIdAsync(request.DocumentProcessingInfoIds); + + if (!documentProcessingInfos.Any()) + { + throw new ServiceException("No DocumentProcessingInfo(s) were found"); + } + + foreach (var documentProcessingInfo in documentProcessingInfos) + { + var logMessage = "Record's EntityUnknown set to True. DocumentProcessingInfoId:" + + $" {documentProcessingInfo.DocumentProcessingInfoId} by {request.UserName} on {DateTime.Now}"; + var processingLog = new ProcessingLog(documentProcessingInfo.DocumentProcessingInfoId, DateTime.Now, logMessage, request.UserName); + processingLog = await _processingLogService.SaveAsync(processingLog); + + if (processingLog == null) + { + throw new ServiceException("ProcessingLog could not be saved for DocumentProcessingInfoId: " + + documentProcessingInfo.DocumentProcessingInfoId); + } + + documentProcessingInfo.EntityUnknown = true; + await Update(documentProcessingInfo); + } + + return documentProcessingInfos; + } + catch (ArgumentNullException exception) + { + var message = "Failure during SetDocumentsToUnknown for " + + $"DocumentProcessingInfoIds: ({string.Join(", ", request.DocumentProcessingInfoIds.ToArray())}). " + + $"ExceptionMessage: {exception.Message}"; + Log.Error(exception, message); + throw new ServiceException(message); + } + catch (Exception exception) + { + var message = "Failure during SetDocumentsToUnknown for " + + $"DocumentProcessingInfoIds: ({string.Join(", ", request.DocumentProcessingInfoIds.ToArray())})."; + Log.Error(exception, message); + throw new ServiceException(message); + } + } + + public async Task UpdateDocumentProcessingInfoStatus(DocumentProcessingInfoStatusRequest request) + { + try + { + var documentProcessingInfo = await GetByIdAsync(request.DocumentProcessingInfoId); + + if (documentProcessingInfo == null) + { + throw new ServiceException("DocumentProcessingInfo was not found."); + } + + if (documentProcessingInfo.StatusType == request.ProcessStatus) + { + throw new ServiceException("DocumentProcessingInfo had the same status as the request and cannot be changed. " + + $"Status: {documentProcessingInfo.StatusType}"); + } + + var statusChangeNotAllowed = _statusChangeRejectionList[documentProcessingInfo.StatusType].Contains(request.ProcessStatus); + if (statusChangeNotAllowed) + { + throw new ServiceException($"DocumentProcessingInfo had a status of '{Enum.GetName(documentProcessingInfo.StatusType)}' " + + $"and cannot be changed to the requested status of '{Enum.GetName(request.ProcessStatus)}'."); + } + + + var logMessage = $"Record's ProcessStatus changed from {documentProcessingInfo.StatusType} to {request.ProcessStatus}." + + $" DocumentProcessingInfoId: {documentProcessingInfo.DocumentProcessingInfoId} by {request.Username} on {DateTime.Now}." + + $" Reason: {request.ReasonMessage}"; + + return await UpdateStatusAndAddLog(documentProcessingInfo, request.ProcessStatus, new List { logMessage }, request.Username); + } + catch (ArgumentNullException exception) + { + var message = "Failure during UpdateDocumentProcessingInfoStatus for " + + $"DocumentProcessingInfoId: ({request.DocumentProcessingInfoId}). " + + $"ExceptionMessage: {exception.Message}"; + Log.Error(exception, message); + throw new ServiceException(message); + } + catch (Exception exception) + { + var message = "Failure during UpdateDocumentProcessingInfoStatus for " + + $"DocumentProcessingInfoId: ({request.DocumentProcessingInfoId})."; + Log.Error(exception, message); + throw new ServiceException(message); + } + } + + public async Task> GetByDocumentIdsAsync(Guid[] ids) + { + try + { + var infos = (await _documentProcessingInfoRepository.FindByDocumentIdsAsync(ids)) + .Where(i => i.DocumentId != null) + .ToDictionary(i => i.DocumentId.Value); + + foreach (var missingId in ids.Where(i => !infos.ContainsKey(i))) + { + infos[missingId] = null; + } + + return infos; + } + catch (Exception exception) + { + var message = "Failure retrieving DocumentProcessingInfos by DocumentIds."; + Log.Error(exception, message); + throw new ServiceException(message); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/DocumentProcessingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/DocumentProcessingService.cs new file mode 100644 index 0000000..7d5d355 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/DocumentProcessingService.cs @@ -0,0 +1,11 @@ +using LCU.Library.Internal.LCUServiceFactory.Configurations; +using LCU.Library.Internal.LCUServiceFactory.Services; + +namespace LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; + +public abstract class DocumentProcessingService : LcuAbstractService +{ + protected DocumentProcessingService(ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration.GetServiceFactoryRegistrationByInterface()) + { } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/FosDnaDocumentProcessingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/FosDnaDocumentProcessingService.cs new file mode 100644 index 0000000..374d2d6 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/FosDnaDocumentProcessingService.cs @@ -0,0 +1,257 @@ +using System.Globalization; +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Extensions; +using LCU.Library.DocumentType.Models.Requests.Account; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.DocumentType.Models.Requests.PrimaryOwner; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.DocumentIngestorModels.Validations; +using LCU.Library.Internal.LCUServiceFactory.Configurations; +using Newtonsoft.Json; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices +{ + public class FosDnaDocumentProcessingService : DocumentProcessingService, IDocumentProcessingService + { + private const DataSourceTypes DataSource = DataSourceTypes.DNA; + private const SourceTypes Source = SourceTypes.FOS; + + private readonly IPrimaryOwnerDeterminingService _primaryOwnerDeterminingService; + private readonly IAccountOwnerDeterminingService _accountOwnerDeterminingService; + private readonly IFileOperationsApiService _fileOperationsApiService; + private readonly IDocumentTypeUploaderApiService _documentTypeUploaderApiService; + + public FosDnaDocumentProcessingService(IPrimaryOwnerDeterminingService primaryOwnerDeterminingService, + IAccountOwnerDeterminingService accountDeterminingService, + IFileOperationsApiService fileOperationsApiService, + IDocumentTypeUploaderApiService documentTypeUploaderApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _documentTypeUploaderApiService = documentTypeUploaderApiService; + _fileOperationsApiService = fileOperationsApiService; + _primaryOwnerDeterminingService = primaryOwnerDeterminingService; + _accountOwnerDeterminingService = accountDeterminingService; + } + + public async Task ProcessRequest(ProcessingRequest request) + { + var processResult = new ProcessResult(); + + try + { + Log.Debug("Starting FosDnaDocument ProcessRequest."); + ArgumentNullException.ThrowIfNull(request); + var documentValues = JsonConvert.DeserializeObject(request.DocumentValuePayload); + ArgumentNullException.ThrowIfNull(documentValues); + + processResult = ValidateRecord(processResult, documentValues, request.OwnerOverrideInfo); + if (!processResult.Success) + { + return processResult; + } + + if (!DateTime.TryParseExact(documentValues.CreationDate, "MMddyyyy", CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out var creationDate)) + { + var message = $"A Creation Date of '{documentValues.CreationDate}' could not be properly formatted " + + $"for an Account Owner of AccountNumber: {documentValues?.AccountNumber} and EntityName: {documentValues?.EntityName}"; + processResult = ProcessResult.ProcessDataMappingFailure(processResult, message); + return processResult; + } + + if (EnumExtensions.IsDocumentTypeOf(documentValues.DocType)) + { + processResult = await HandlePrimaryOwner(request, processResult, documentValues, creationDate); + } + else if (EnumExtensions.IsDocumentTypeOf(documentValues.DocType)) + { + processResult = await HandleAccountOwner(request, processResult, documentValues, creationDate); + } + else + { + var message = $"Document Type of {documentValues.DocType} could not be found." + + $"for an Account Owner of AccountNumber: {documentValues?.AccountNumber} and EntityName: {documentValues?.EntityName}"; + Log.Error(message); + processResult = ProcessResult.ProcessCriticalFailure(processResult, message); + return processResult; + } + + Log.Debug("Ending FosDna ProcessRequest."); + } + catch (Exception exception) + { + var message = "An Exception occured while FosDnaDocument ProcessRequest. " + + $"Exception Message: {exception.Message} "; + Log.Error(exception, message); + processResult = ProcessResult.ProcessCriticalFailure(processResult, message); + } + + return processResult; + } + + public ProcessResult ValidateRecord(ProcessResult processResult, + FosDnaDocument documentValues, + OwnerOverrideInfo? ownerOverrideInfo) + { + // Keep at top to set EntityUnknown for PsInfoChangeNotice documents with invalid Account Numbers + // Business would like override to skip AccountNumber validation for PsInfoChangeNotice + if (!SkipAccountNumberValidationForPsInfoChangeNotice(documentValues.DocType, ownerOverrideInfo)) + { + processResult = MetaDataValidation.ValidateAccountNumber(processResult, documentValues.AccountNumber); + processResult = SetToEntityUnknown(processResult, documentValues.DocType, ownerOverrideInfo); + } + processResult = MetaDataValidation.ValidateFileName(processResult, documentValues.DocName); + processResult = MetaDataValidation.ValidateFullName(processResult, documentValues.EntityName); + return processResult; + } + + public async Task HandlePrimaryOwner(ProcessingRequest request, + ProcessResult processResult, + FosDnaDocument documentValues, + DateTime creationDate) + { + var primaryOwnerAttribute = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttribute(documentValues.EntityName, + documentValues.AccountNumber, + creationDate, + request.OwnerOverrideInfo); + + if (!primaryOwnerAttribute.Success) + { + processResult = ProcessResult.ProcessDataMappingFailure(processResult, + primaryOwnerAttribute.Message); + return processResult; + } + + var primaryOwnerRequest = await BuildPrimaryOwnerUploadRequest(request, documentValues, creationDate, primaryOwnerAttribute.Payload); + await _documentTypeUploaderApiService.UploadPrimaryOwnerDocument(primaryOwnerRequest, request, processResult); + + return processResult; + } + + public async Task HandleAccountOwner(ProcessingRequest request, + ProcessResult processResult, + FosDnaDocument documentValues, + DateTime creationDate) + { + var accountOwnerAttribute = await _accountOwnerDeterminingService.DetermineAccountOwnerAttribute(documentValues.EntityName, + documentValues.AccountNumber, + creationDate, + request.OwnerOverrideInfo); + + if (!accountOwnerAttribute.Success) + { + processResult = ProcessResult.ProcessDataMappingFailure(processResult, + accountOwnerAttribute.Message); + return processResult; + } + + var accountOwnerRequest = await BuildAccountUploadRequest(request, documentValues, creationDate, accountOwnerAttribute.Payload); + await _documentTypeUploaderApiService.UploadAccountDocument(accountOwnerRequest, request, processResult); + + return processResult; + } + + public async Task BuildPrimaryOwnerUploadRequest(ProcessingRequest request, + FosDnaDocument documentValues, + DateTime creationDate, + PrimaryOwnerAttribute primaryOwnerAttribute) + { + var contentBytes = await _fileOperationsApiService.GetContentBytes(request.IngestorRequest.RootPath, + request.DocumentFileName); + + var type = documentValues.DocType.GetValueFromName(); + ArgumentNullException.ThrowIfNull(type); + + var primaryOwnerDocumentRequest = new PrimaryOwnerDocumentRequest + { + Content = contentBytes, + PrimaryOwnerAttribute = primaryOwnerAttribute, + PrimaryOwnerDocumentMetadata = new PrimaryOwnerDocumentMetadata + { + Source = Source, + DataSource = DataSource, + Name = documentValues.DocName, + Type = type, + CreatedDate = creationDate, + TraceId = request.IngestorRunInfoId + } + }; + return primaryOwnerDocumentRequest; + } + + public async Task BuildAccountUploadRequest(ProcessingRequest request, + FosDnaDocument documentValues, + DateTime creationDate, + AccountAttribute accountAttribute) + { + var contentBytes = await _fileOperationsApiService.GetContentBytes(request.IngestorRequest.RootPath, + request.DocumentFileName); + + var type = documentValues.DocType.GetValueFromName(); + ArgumentNullException.ThrowIfNull(type); + + var accountOwnerDocumentRequest = new AccountDocumentRequest + { + Content = contentBytes, + AccountAttribute = accountAttribute, + AccountDocumentMetadata = new AccountDocumentMetadata + { + Source = Source, + DataSource = DataSource, + Name = documentValues.DocName, + Type = type, + CreatedDate = creationDate, + TraceId = request.IngestorRunInfoId + } + }; + return accountOwnerDocumentRequest; + } + + private ProcessResult SetToEntityUnknown(ProcessResult processResult, + string documentType, + OwnerOverrideInfo? ownerOverrideInfo) + { + if (string.IsNullOrWhiteSpace(documentType) + || processResult.Success + || processResult.ProcessStatusType != ProcessStatusTypes.DataMappingFailure + || ownerOverrideInfo is not null) + { + return processResult; + } + + if (EnumExtensions.IsDocumentTypeOf(documentType)) + { + switch (documentType.GetValueFromName()) + { + case PrimaryOwnerDocumentTypes.PsInfoChangeNotice: + processResult.EntityIsUnknown = true; + break; + } + } + + return processResult; + } + + private bool SkipAccountNumberValidationForPsInfoChangeNotice(string docType, OwnerOverrideInfo? ownerOverrideInfo) + { + if (!EnumExtensions.IsDocumentTypeOf(docType)) + { + return false; + } + + if (ownerOverrideInfo is null + || docType.GetValueFromName() != PrimaryOwnerDocumentTypes.PsInfoChangeNotice) + { + return false; + } + + return true; + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/FosLoanStatementProcessingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/FosLoanStatementProcessingService.cs new file mode 100644 index 0000000..596eabc --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/FosLoanStatementProcessingService.cs @@ -0,0 +1,128 @@ +using System.Globalization; +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Extensions; +using LCU.Library.DocumentType.Models.Requests.Account; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.DocumentIngestorModels.Validations; +using LCU.Library.Internal.LCUServiceFactory.Configurations; +using Newtonsoft.Json; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices +{ + public class FosLoanStatementProcessingService : DocumentProcessingService, IDocumentProcessingService + { + private const DataSourceTypes DataSource = DataSourceTypes.DNA; + private const SourceTypes Source = SourceTypes.FOS; + private const string DateFormat = "yyyyMMdd"; + private readonly IAccountOwnerDeterminingService _accountOwnerDeterminingService; + private readonly IFileOperationsApiService _fileOperationsApiService; + private readonly IDocumentTypeUploaderApiService _documentTypeUploaderApiService; + + public FosLoanStatementProcessingService(IAccountOwnerDeterminingService accountDeterminingService, + IFileOperationsApiService fileOperationsApiService, + IDocumentTypeUploaderApiService documentTypeUploaderApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _documentTypeUploaderApiService = documentTypeUploaderApiService; + _fileOperationsApiService = fileOperationsApiService; + _accountOwnerDeterminingService = accountDeterminingService; + } + + public async Task ProcessRequest(ProcessingRequest request) + { + var processResult = new ProcessResult(); + + try + { + Log.Debug("Starting FosLoanStatement ProcessRequest."); + ArgumentNullException.ThrowIfNull(request); + var documentValues = JsonConvert.DeserializeObject(request.DocumentValuePayload); + ArgumentNullException.ThrowIfNull(documentValues); + + processResult = ValidateRecord(processResult, documentValues); + if (!processResult.Success) + { + return processResult; + } + + if (!DateTime.TryParseExact(documentValues.CreationDate, DateFormat, CultureInfo.InvariantCulture, + DateTimeStyles.AssumeLocal, out var creationDate)) + { + var message = + $"A Creation Date of {documentValues.CreationDate} could not be properly formatted from format: {DateFormat}"; + return ProcessResult.ProcessDataMappingFailure(processResult, message); + } + + var accountOwnerAttribute = await _accountOwnerDeterminingService.DetermineAccountOwnerAttribute( + documentValues.EntityName, + documentValues.AccountNumber, + creationDate, + request.OwnerOverrideInfo); + + if (!accountOwnerAttribute.Success) + { + return ProcessResult.ProcessDataMappingFailure(processResult, + accountOwnerAttribute.Message); + } + + var accountOwnerRequest = await BuildAccountUploadRequest(request, documentValues, creationDate, accountOwnerAttribute.Payload); + await _documentTypeUploaderApiService.UploadAccountDocument(accountOwnerRequest, request, processResult); + + Log.Debug("Ending FosLoanStatement ProcessRequest."); + } + catch (Exception exception) + { + var message = $"An Exception occured while FosLoanStatement ProcessRequest. " + + $"Exception Message: {exception.Message} "; + Log.Error(exception, message); + processResult = ProcessResult.ProcessCriticalFailure(processResult, message); + } + + return processResult; + } + + public ProcessResult ValidateRecord(ProcessResult processResult, FosLoanStatement documentValues) + { + processResult = MetaDataValidation.ValidateAccountNumber(processResult, documentValues.AccountNumber); + processResult = MetaDataValidation.ValidateFileName(processResult, documentValues.DocName); + processResult = MetaDataValidation.ValidateFullName(processResult, documentValues.EntityName); + processResult = MetaDataValidation.ValidateDocumentType(processResult, documentValues.DocType); + + return processResult; + } + + public async Task BuildAccountUploadRequest(ProcessingRequest request, + FosLoanStatement documentValues, + DateTime creationDate, + AccountAttribute accountAttribute) + { + var contentBytes = await _fileOperationsApiService.GetContentBytes(request.IngestorRequest.RootPath, + request.DocumentFileName); + + var type = documentValues.DocType.GetValueFromName(); + ArgumentNullException.ThrowIfNull(type); + + var accountOwnerDocumentRequest = new AccountDocumentRequest + { + Content = contentBytes, + AccountAttribute = accountAttribute, + AccountDocumentMetadata = new AccountDocumentMetadata + { + Source = Source, + DataSource = DataSource, + Name = request.DocumentFileName, + Type = type, + CreatedDate = creationDate, + TraceId = request.IngestorRunInfoId + } + }; + return accountOwnerDocumentRequest; + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/FosTaxStatementProcessingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/FosTaxStatementProcessingService.cs new file mode 100644 index 0000000..88489ea --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/FosTaxStatementProcessingService.cs @@ -0,0 +1,161 @@ +using Newtonsoft.Json; +using Serilog; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Extensions; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.DocumentType.Models.Requests.PrimaryOwner; +using LCU.Library.DocumentType.Models.Requests.Generic; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.DocumentIngestorModels.Validations; +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; + +public class FosTaxStatementProcessingService : DocumentProcessingService, IDocumentProcessingService +{ + private readonly IPrimaryOwnerDeterminingService _primaryOwnerDeterminingService; + private readonly IFileOperationsApiService _fileOperationsApiService; + private readonly IDocumentTypeUploaderApiService _documentTypeUploaderApiService; + private const DataSourceTypes DataSource = DataSourceTypes.DNA; + private const SourceTypes Source = SourceTypes.FOS; + + public FosTaxStatementProcessingService(IPrimaryOwnerDeterminingService userIdDeterminingService, + IFileOperationsApiService fileOperationsApiService, + IDocumentTypeUploaderApiService documentTypeUploaderApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _documentTypeUploaderApiService = documentTypeUploaderApiService; + _fileOperationsApiService = fileOperationsApiService; + _primaryOwnerDeterminingService = userIdDeterminingService; + } + + public async Task ProcessRequest(ProcessingRequest request) + { + var processResult = new ProcessResult(); + try + { + Log.Debug("Starting FosTaxStatement ProcessRequest."); + ArgumentNullException.ThrowIfNull(request); + var documentValues = JsonConvert.DeserializeObject(request.DocumentValuePayload); + ArgumentNullException.ThrowIfNull(documentValues); + + processResult = ValidateRecord(processResult, documentValues); + if (!processResult.Success) + { + return processResult; + } + + if (EnumExtensions.IsDocumentTypeOf(documentValues.FileName)) + { + var primaryOwnerAttribute = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttribute( + documentValues.FullName, + documentValues.AccountNumber, + documentValues.PrimaryTIN, + request.OwnerOverrideInfo); + + if (!primaryOwnerAttribute.Success) + { + processResult = ProcessResult.ProcessDataMappingFailure(processResult, + primaryOwnerAttribute.Message); + return processResult; + } + + var uploadRequest = await BuildUploadRequest(request, documentValues, primaryOwnerAttribute.Payload); + await _documentTypeUploaderApiService.UploadPrimaryOwnerDocument(uploadRequest, request, processResult); + } + else if (EnumExtensions.IsDocumentTypeOf(documentValues.FileName)) + { + var genericAttribute = new GenericDocumentAttribute + { + EntityName = documentValues.FullName + }; + + var uploadRequest = await BuildGenericUploadRequest(request, documentValues, genericAttribute); + await _documentTypeUploaderApiService.UploadGenericDocument(uploadRequest, request, processResult); + } + else + { + var message = $"Document Type of {documentValues.FileName} could not be found."; + Log.Error(message); + processResult = ProcessResult.ProcessCriticalFailure(processResult, message); + return processResult; + } + } + catch (Exception exception) + { + var message = "An Exception occured while FosTaxStatement ProcessRequest. " + + $"Exception Message: {exception.Message} "; + Log.Error(exception, message); + processResult = ProcessResult.ProcessCriticalFailure(processResult, message); + } + + Log.Debug("Ending FosTaxStatement ProcessRequest."); + return processResult; + } + + public ProcessResult ValidateRecord(ProcessResult processResult, FosTaxStatementDocument documentValues) + { + processResult = MetaDataValidation.ValidateAccountNumber(processResult, documentValues.AccountNumber); + processResult = MetaDataValidation.ValidateFileName(processResult, documentValues.FileName); + processResult = MetaDataValidation.ValidateFullName(processResult, documentValues.FullName); + processResult = MetaDataValidation.ValidatePdf(processResult, documentValues.PDF); + processResult = MetaDataValidation.ValidateTin(processResult, documentValues.PrimaryTIN); + return processResult; + } + + public async Task BuildUploadRequest(ProcessingRequest request, + FosTaxStatementDocument documentValues, + PrimaryOwnerAttribute primaryOwnerAttribute) + { + var contentBytes = await _fileOperationsApiService.GetContentBytes(request.IngestorRequest.RootPath, + request.DocumentFileName); + + var type = documentValues.FileName.GetValueFromName(); + + var primaryOwnerDocumentRequest = new PrimaryOwnerDocumentRequest + { + Content = contentBytes, + PrimaryOwnerAttribute = primaryOwnerAttribute, + PrimaryOwnerDocumentMetadata = new PrimaryOwnerDocumentMetadata + { + Source = Source, + DataSource = DataSource, + Name = documentValues.PDF, + Type = type, + CreatedDate = DateTime.Now.Date, + TraceId = request.IngestorRunInfoId + } + }; + return primaryOwnerDocumentRequest; + } + + public async Task BuildGenericUploadRequest(ProcessingRequest request, + FosTaxStatementDocument documentValues, + GenericDocumentAttribute genericDocumentAttribute) + { + var contentBytes = await _fileOperationsApiService.GetContentBytes(request.IngestorRequest.RootPath, + request.DocumentFileName); + + var type = documentValues.FileName.GetValueFromName(); + + var genericDocumentRequest = new GenericDocumentRequest + { + Content = contentBytes, + GenericDocumentAttribute = genericDocumentAttribute, + GenericDocumentMetadata = new GenericDocumentMetadata + { + Source = Source, + DataSource = DataSource, + Name = documentValues.PDF, + Type = type, + CreatedDate = DateTime.Now.Date, + TraceId = request.IngestorRunInfoId + } + }; + return genericDocumentRequest; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/IDocumentProcessingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/IDocumentProcessingService.cs new file mode 100644 index 0000000..d21dd69 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/IDocumentProcessingService.cs @@ -0,0 +1,9 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.LCUServiceFactory.Services; + +namespace LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; + +public interface IDocumentProcessingService : ILcuService +{ + Task ProcessRequest(ProcessingRequest request); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgDnaNoticeSplitProcessingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgDnaNoticeSplitProcessingService.cs new file mode 100644 index 0000000..cf7b8f3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgDnaNoticeSplitProcessingService.cs @@ -0,0 +1,126 @@ +using Newtonsoft.Json; +using Serilog; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Extensions; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.DocumentIngestorModels.Validations; +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using System.Globalization; +using LCU.Library.DocumentType.Models.Requests.Account; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; + +public class OsgDnaNoticeSplitProcessingService : DocumentProcessingService, IDocumentProcessingService +{ + private readonly IAccountOwnerDeterminingService _accountOwnerDeterminingService; + private readonly IFileOperationsApiService _fileOperationsApiService; + private readonly IDocumentTypeUploaderApiService _documentTypeUploaderApiService; + private const DataSourceTypes DataSource = DataSourceTypes.DNA; + private const SourceTypes Source = SourceTypes.OSG; + private const string DateFormat = "MMddyyyy"; + + public OsgDnaNoticeSplitProcessingService(IFileOperationsApiService fileOperationsApiService, + IDocumentTypeUploaderApiService documentTypeUploaderApiService, + IAccountOwnerDeterminingService accountOwnerDeterminingService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _documentTypeUploaderApiService = documentTypeUploaderApiService; + _fileOperationsApiService = fileOperationsApiService; + _accountOwnerDeterminingService = accountOwnerDeterminingService; + } + + public async Task ProcessRequest(ProcessingRequest request) + { + var processResult = new ProcessResult(); + try + { + Log.Debug("Starting OsgDnaNoticeSplit ProcessRequest."); + ArgumentNullException.ThrowIfNull(request); + var documentValues = JsonConvert.DeserializeObject(request.DocumentValuePayload); + ArgumentNullException.ThrowIfNull(documentValues); + + processResult = ValidateRecord(processResult, documentValues); + if (!processResult.Success) + { + return processResult; + } + + if (!DateTime.TryParseExact(documentValues.CreationDate, DateFormat, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out var creationDate)) + { + var message = $"A Creation Date of '{documentValues.CreationDate}' could not be properly formatted " + + $"for an Account Owner of EntityName: {documentValues?.RecipientName} and EntityId: {documentValues?.AccountNumber}"; + processResult = ProcessResult.ProcessDataMappingFailure(processResult, message); + return processResult; + } + + var accountOwnerAttribute = await _accountOwnerDeterminingService.DetermineAccountOwnerAttributeByMemberNumberOrUserId(documentValues.UserId, + documentValues.AccountNumber, + documentValues.NoticeId, + creationDate, + request.OwnerOverrideInfo); + + if (!accountOwnerAttribute.Success) + { + processResult = ProcessResult.ProcessDataMappingFailure(processResult, + accountOwnerAttribute.Message); + return processResult; + } + + var accountOwnerRequest = await BuildUploadRequest(request, documentValues, creationDate, accountOwnerAttribute.Payload); + await _documentTypeUploaderApiService.UploadAccountDocument(accountOwnerRequest, request, processResult); + + } + catch (Exception exception) + { + var message = "An Exception occured while OsgTaxStatement ProcessRequest. " + + $"Exception Message: {exception.Message} "; + Log.Error(exception, message); + processResult = ProcessResult.ProcessCriticalFailure(processResult, message); + } + + Log.Debug("Ending OsgTaxStatement ProcessRequest."); + return processResult; + } + + public ProcessResult ValidateRecord(ProcessResult processResult, OsgDnaNoticeSplit documentValues) + { + processResult = MetaDataValidation.ValidateAccountNumber(processResult, documentValues.AccountNumber); + processResult = MetaDataValidation.ValidateFileName(processResult, documentValues.NoticeName); + processResult = MetaDataValidation.ValidateFullName(processResult, documentValues.RecipientName); + processResult = MetaDataValidation.ValidatePdf(processResult, documentValues.PdfName); + return processResult; + } + + public async Task BuildUploadRequest(ProcessingRequest request, + OsgDnaNoticeSplit documentValues, + DateTime creationDate, + AccountAttribute accountAttribute) + { + var contentBytes = await _fileOperationsApiService.GetContentBytes(request.IngestorRequest.RootPath, + request.DocumentFileName); + + var type = documentValues.NoticeId.GetValueFromName(); + ArgumentNullException.ThrowIfNull(type); + + var accountOwnerDocumentRequest = new AccountDocumentRequest + { + Content = contentBytes, + AccountAttribute = accountAttribute, + AccountDocumentMetadata = new AccountDocumentMetadata + { + Source = Source, + DataSource = DataSource, + Name = documentValues.NoticeName, + Type = type, + CreatedDate = creationDate, + TraceId = request.IngestorRunInfoId + } + }; + return accountOwnerDocumentRequest; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgDnaNoticesProcessingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgDnaNoticesProcessingService.cs new file mode 100644 index 0000000..f16fe39 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgDnaNoticesProcessingService.cs @@ -0,0 +1,187 @@ +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Extensions; +using LCU.Library.DocumentType.Models.Requests.Account; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.DocumentType.Models.Requests.PrimaryOwner; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.DocumentIngestorModels.Validations; +using Newtonsoft.Json; +using Serilog; +using System.Globalization; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices +{ + public class OsgDnaNoticesProcessingService : DocumentProcessingService, IDocumentProcessingService + { + private const DataSourceTypes DataSource = DataSourceTypes.DNA; + private const SourceTypes Source = SourceTypes.OSG; + private readonly IPrimaryOwnerDeterminingService _primaryOwnerDeterminingService; + private readonly IFileOperationsApiService _fileOperationsApiService; + private readonly IDocumentTypeUploaderApiService _documentTypeUploaderApiService; + private readonly IAccountOwnerDeterminingService _accountOwnerDeterminingService; + private const string DateFormat = "yyyyMMdd"; + + public OsgDnaNoticesProcessingService(IPrimaryOwnerDeterminingService userIdDeterminingService, + IFileOperationsApiService fileOperationsApiService, + IDocumentTypeUploaderApiService documentTypeUploaderApiService, + IAccountOwnerDeterminingService accountDeterminingService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _documentTypeUploaderApiService = documentTypeUploaderApiService; + _fileOperationsApiService = fileOperationsApiService; + _primaryOwnerDeterminingService = userIdDeterminingService; + _accountOwnerDeterminingService = accountDeterminingService; + } + + public async Task ProcessRequest(ProcessingRequest request) + { + var processResult = new ProcessResult(); + try + { + Log.Debug("Starting OsgDnaNoticesDocument ProcessRequest."); + ArgumentNullException.ThrowIfNull(request); + var documentValues = JsonConvert.DeserializeObject(request.DocumentValuePayload); + ArgumentNullException.ThrowIfNull(documentValues); + + processResult = ValidateRecord(processResult, documentValues); + if (!processResult.Success) + { + return processResult; + } + if (!DateTime.TryParseExact(documentValues.CreationDate, DateFormat, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out var creationDate)) + { + var message = $"A Creation Date of '{documentValues.CreationDate}' could not be properly formatted " + + $"for an Account Owner of AccountNumber: {documentValues?.AccountNumber} and EntityId: {documentValues?.MemberNumberOrUserId}"; + processResult = ProcessResult.ProcessDataMappingFailure(processResult, message); + return processResult; + } + + if (EnumExtensions.IsDocumentTypeOf(documentValues.DocType)) + { + var primaryOwnerAttribute = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(documentValues.MemberNumberOrUserId, + documentValues.AccountNumber, + documentValues.DocType, + creationDate, + request.OwnerOverrideInfo); + + if (!primaryOwnerAttribute.Success) + { + processResult = ProcessResult.ProcessDataMappingFailure(processResult, + primaryOwnerAttribute.Message); + return processResult; + } + + var primaryOwnerRequest = await BuildPrimaryOwnerUploadRequest(request, documentValues, creationDate, primaryOwnerAttribute.Payload); + await _documentTypeUploaderApiService.UploadPrimaryOwnerDocument(primaryOwnerRequest, request, processResult); + + } + else if (EnumExtensions.IsDocumentTypeOf(documentValues.DocType)) + { + var accountOwnerAttribute = await _accountOwnerDeterminingService.DetermineAccountOwnerAttributeByMemberNumberOrUserId(documentValues.MemberNumberOrUserId, + documentValues.AccountNumber, + documentValues.DocType, + creationDate, + request.OwnerOverrideInfo); + + if (!accountOwnerAttribute.Success) + { + processResult = ProcessResult.ProcessDataMappingFailure(processResult, + accountOwnerAttribute.Message); + return processResult; + } + + var accountOwnerRequest = await BuildAccountUploadRequest(request, documentValues, creationDate, accountOwnerAttribute.Payload); + await _documentTypeUploaderApiService.UploadAccountDocument(accountOwnerRequest, request, processResult); + } + else + { + var message = $"Document Type of {documentValues.DocType} could not be found." + + $"for an Account Owner of AccountNumber: {documentValues?.AccountNumber} and EntityName: {documentValues?.MemberNumberOrUserId}"; + Log.Error(message); + processResult = ProcessResult.ProcessCriticalFailure(processResult, message); + return processResult; + } + + Log.Debug("Ending OsgDnaNotices ProcessRequest."); + + } + catch (Exception exception) + { + var message = "An Exception occured while OsgDnaNoticesDocument ProcessRequest. " + + $"Exception Message: {exception.Message} "; + Log.Error(exception, message); + processResult = ProcessResult.ProcessCriticalFailure(processResult, message); + } + return processResult; + } + + public async Task BuildAccountUploadRequest(ProcessingRequest request, + OsgDnaNoticesDocument documentValues, + DateTime creationDate, + AccountAttribute accountAttribute) + { + var contentBytes = await _fileOperationsApiService.GetContentBytes(request.IngestorRequest.RootPath, + request.DocumentFileName); + + var type = documentValues.DocType.GetValueFromName(); + ArgumentNullException.ThrowIfNull(type); + + var accountOwnerDocumentRequest = new AccountDocumentRequest + { + Content = contentBytes, + AccountAttribute = accountAttribute, + AccountDocumentMetadata = new AccountDocumentMetadata + { + Source = Source, + DataSource = DataSource, + Name = request.DocumentFileName, + Type = type, + CreatedDate = creationDate, + TraceId = request.IngestorRunInfoId + } + }; + return accountOwnerDocumentRequest; + } + + public async Task BuildPrimaryOwnerUploadRequest(ProcessingRequest request, + OsgDnaNoticesDocument documentValues, + DateTime creationDate, + PrimaryOwnerAttribute primaryOwnerAttribute) + { + var contentBytes = await _fileOperationsApiService.GetContentBytes(request.IngestorRequest.RootPath, + request.DocumentFileName); + + var type = documentValues.DocType.GetValueFromName(); + ArgumentNullException.ThrowIfNull(type); + + var primaryOwnerDocumentRequest = new PrimaryOwnerDocumentRequest + { + Content = contentBytes, + PrimaryOwnerAttribute = primaryOwnerAttribute, + PrimaryOwnerDocumentMetadata = new PrimaryOwnerDocumentMetadata + { + Source = Source, + DataSource = DataSource, + Name = request.DocumentFileName, + Type = type, + CreatedDate = creationDate, + TraceId = request.IngestorRunInfoId + } + }; + return primaryOwnerDocumentRequest; + } + + private static ProcessResult ValidateRecord(ProcessResult processResult, OsgDnaNoticesDocument documentValues) + { + processResult = MetaDataValidation.ValidateAccountNumber(processResult, documentValues.AccountNumber); + processResult = MetaDataValidation.ValidateDate(processResult, documentValues.CreationDate, DateFormat); + + return processResult; + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgHistoricalDocumentProcessingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgHistoricalDocumentProcessingService.cs new file mode 100644 index 0000000..cad3c82 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgHistoricalDocumentProcessingService.cs @@ -0,0 +1,134 @@ +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Extensions; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.DocumentType.Models.Requests.PrimaryOwner; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.DocumentIngestorModels.Validations; +using Newtonsoft.Json; +using Serilog; +using System.Globalization; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices +{ + public class OsgHistoricalDocumentProcessingService : DocumentProcessingService, IDocumentProcessingService + { + private const DataSourceTypes DataSource = DataSourceTypes.DNA; + private const SourceTypes Source = SourceTypes.OSG; + private readonly IPrimaryOwnerDeterminingService _primaryOwnerDeterminingService; + private readonly IFileOperationsApiService _fileOperationsApiService; + private readonly IDocumentTypeUploaderApiService _documentTypeUploaderApiService; + private const string DateFormat = "yyyyMMdd"; + + public OsgHistoricalDocumentProcessingService(IPrimaryOwnerDeterminingService userIdDeterminingService, + IFileOperationsApiService fileOperationsApiService, + IDocumentTypeUploaderApiService documentTypeUploaderApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _documentTypeUploaderApiService = documentTypeUploaderApiService; + _fileOperationsApiService = fileOperationsApiService; + _primaryOwnerDeterminingService = userIdDeterminingService; + } + + public async Task ProcessRequest(ProcessingRequest request) + { + var processResult = new ProcessResult(); + try + { + Log.Debug("Starting OsgHistoricalDocument ProcessRequest."); + ArgumentNullException.ThrowIfNull(request); + var documentValues = JsonConvert.DeserializeObject(request.DocumentValuePayload); + ArgumentNullException.ThrowIfNull(documentValues); + + processResult = ValidateRecord(processResult, documentValues); + if (!processResult.Success) + { + return processResult; + } + if (!DateTime.TryParseExact(documentValues.CreationDate, DateFormat, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out var creationDate)) + { + var message = $"A Creation Date of '{documentValues.CreationDate}' could not be properly formatted " + + $"for an Account Owner of EntityName: {documentValues?.EntityName} and EntityId: {documentValues?.MemberNumberOrUserId}"; + processResult = ProcessResult.ProcessDataMappingFailure(processResult, message); + return processResult; + } + + if (EnumExtensions.IsDocumentTypeOf(documentValues.DocType)) + { + var primaryOwnerAttribute = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(documentValues.MemberNumberOrUserId, + documentValues.EntityName, + request.OwnerOverrideInfo); + + if (!primaryOwnerAttribute.Success) + { + processResult = ProcessResult.ProcessDataMappingFailure(processResult, primaryOwnerAttribute.Message); + return processResult; + } + + var primaryOwnerRequest = await BuildPrimaryOwnerUploadRequest(request, documentValues, creationDate, primaryOwnerAttribute.Payload); + await _documentTypeUploaderApiService.UploadPrimaryOwnerDocument(primaryOwnerRequest, request, processResult); + + } + else + { + var message = $"Document Type of {documentValues.DocType} could not be found." + + $"for an Account Owner of EntityName: {documentValues?.EntityName} and EntityId: {documentValues?.MemberNumberOrUserId}"; + Log.Error(message); + processResult = ProcessResult.ProcessCriticalFailure(processResult, message); + return processResult; + } + + Log.Debug("Ending OsgHistoricalDocument ProcessRequest."); + + } + catch (Exception exception) + { + var message = "An Exception occured while OsgHistoricalDocument ProcessRequest. " + + $"Exception Message: {exception.Message} "; + Log.Error(exception, message); + processResult = ProcessResult.ProcessCriticalFailure(processResult, message); + } + return processResult; + } + + private async Task BuildPrimaryOwnerUploadRequest(ProcessingRequest request, + OsgHistoricalDocument documentValues, + DateTime creationDate, + PrimaryOwnerAttribute primaryOwnerAttribute) + { + var contentBytes = await _fileOperationsApiService.GetContentBytes(request.IngestorRequest.RootPath, + request.DocumentFileName); + + var type = documentValues.DocType.GetValueFromName(); + ArgumentNullException.ThrowIfNull(type); + + var primaryOwnerDocumentRequest = new PrimaryOwnerDocumentRequest + { + Content = contentBytes, + PrimaryOwnerAttribute = primaryOwnerAttribute, + PrimaryOwnerDocumentMetadata = new PrimaryOwnerDocumentMetadata + { + Source = Source, + DataSource = DataSource, + Name = request.DocumentFileName, + Type = type, + CreatedDate = creationDate, + TraceId = request.IngestorRunInfoId + } + }; + return primaryOwnerDocumentRequest; + } + + private static ProcessResult ValidateRecord(ProcessResult processResult, OsgHistoricalDocument documentValues) + { + processResult = MetaDataValidation.ValidateFullName(processResult, documentValues.EntityName); + processResult = MetaDataValidation.ValidateDate(processResult, documentValues.CreationDate, DateFormat); + + return processResult; + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgTaxStatementProcessingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgTaxStatementProcessingService.cs new file mode 100644 index 0000000..af52b3a --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgTaxStatementProcessingService.cs @@ -0,0 +1,173 @@ +using Newtonsoft.Json; +using Serilog; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Extensions; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.DocumentType.Models.Requests.PrimaryOwner; +using LCU.Library.DocumentType.Models.Requests.Generic; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.DocumentIngestorModels.Validations; +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using Microsoft.VisualBasic; +using System.Globalization; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; + +public class OsgTaxStatementProcessingService : DocumentProcessingService, IDocumentProcessingService +{ + private readonly IPrimaryOwnerDeterminingService _primaryOwnerDeterminingService; + private readonly IFileOperationsApiService _fileOperationsApiService; + private readonly IDocumentTypeUploaderApiService _documentTypeUploaderApiService; + private const DataSourceTypes DataSource = DataSourceTypes.DNA; + private const SourceTypes Source = SourceTypes.OSG; + private const string DateFormat = "MMddyyyy"; + + public OsgTaxStatementProcessingService(IPrimaryOwnerDeterminingService userIdDeterminingService, + IFileOperationsApiService fileOperationsApiService, + IDocumentTypeUploaderApiService documentTypeUploaderApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _documentTypeUploaderApiService = documentTypeUploaderApiService; + _fileOperationsApiService = fileOperationsApiService; + _primaryOwnerDeterminingService = userIdDeterminingService; + } + + public async Task ProcessRequest(ProcessingRequest request) + { + var processResult = new ProcessResult(); + try + { + Log.Debug("Starting OsgTaxStatement ProcessRequest."); + ArgumentNullException.ThrowIfNull(request); + var documentValues = JsonConvert.DeserializeObject(request.DocumentValuePayload); + ArgumentNullException.ThrowIfNull(documentValues); + + processResult = ValidateRecord(processResult, documentValues); + if (!processResult.Success) + { + return processResult; + } + + if (!DateTime.TryParseExact(documentValues.CreationDate, DateFormat, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out var creationDate)) + { + var message = $"A Creation Date of '{documentValues.CreationDate}' could not be properly formatted " + + $"for an Account Owner of EntityName: {documentValues?.RecipientName} and EntityId: {documentValues?.AccountNumber}"; + processResult = ProcessResult.ProcessDataMappingFailure(processResult, message); + return processResult; + } + + if (EnumExtensions.IsDocumentTypeOf(documentValues.NoticeName)) + { + var primaryOwnerAttribute = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttribute( + documentValues.RecipientName, + documentValues.AccountNumber, + documentValues.SSN, + request.OwnerOverrideInfo); + + if (!primaryOwnerAttribute.Success) + { + processResult = ProcessResult.ProcessDataMappingFailure(processResult, + primaryOwnerAttribute.Message); + return processResult; + } + + var uploadRequest = await BuildUploadRequest(request, documentValues, primaryOwnerAttribute.Payload, creationDate); + await _documentTypeUploaderApiService.UploadPrimaryOwnerDocument(uploadRequest, request, processResult); + } + else if (EnumExtensions.IsDocumentTypeOf(documentValues.NoticeName)) + { + var genericAttribute = new GenericDocumentAttribute + { + EntityName = documentValues.RecipientName + }; + + var uploadRequest = await BuildGenericUploadRequest(request, documentValues, genericAttribute); + await _documentTypeUploaderApiService.UploadGenericDocument(uploadRequest, request, processResult); + } + else + { + var message = $"Document Type of {documentValues.NoticeName} could not be found."; + Log.Error(message); + processResult = ProcessResult.ProcessCriticalFailure(processResult, message); + return processResult; + } + } + catch (Exception exception) + { + var message = "An Exception occured while OsgTaxStatement ProcessRequest. " + + $"Exception Message: {exception.Message} "; + Log.Error(exception, message); + processResult = ProcessResult.ProcessCriticalFailure(processResult, message); + } + + Log.Debug("Ending OsgTaxStatement ProcessRequest."); + return processResult; + } + + public ProcessResult ValidateRecord(ProcessResult processResult, OsgTaxStatement documentValues) + { + processResult = MetaDataValidation.ValidateAccountNumber(processResult, documentValues.AccountNumber); + processResult = MetaDataValidation.ValidateFileName(processResult, documentValues.NoticeName); + processResult = MetaDataValidation.ValidateFullName(processResult, documentValues.RecipientName); + processResult = MetaDataValidation.ValidatePdf(processResult, documentValues.PdfName); + processResult = MetaDataValidation.ValidateTin(processResult, documentValues.SSN); + return processResult; + } + + public async Task BuildUploadRequest(ProcessingRequest request, + OsgTaxStatement documentValues, + PrimaryOwnerAttribute primaryOwnerAttribute, + DateTime creationDate) + { + var contentBytes = await _fileOperationsApiService.GetContentBytes(request.IngestorRequest.RootPath, + request.DocumentFileName); + + var type = documentValues.NoticeName.GetValueFromName(); + + var primaryOwnerDocumentRequest = new PrimaryOwnerDocumentRequest + { + Content = contentBytes, + PrimaryOwnerAttribute = primaryOwnerAttribute, + PrimaryOwnerDocumentMetadata = new PrimaryOwnerDocumentMetadata + { + Source = Source, + DataSource = DataSource, + Name = documentValues.PdfName, + Type = type, + CreatedDate = creationDate, + TraceId = request.IngestorRunInfoId + } + }; + return primaryOwnerDocumentRequest; + } + + public async Task BuildGenericUploadRequest(ProcessingRequest request, + OsgTaxStatement documentValues, + GenericDocumentAttribute genericDocumentAttribute) + { + var contentBytes = await _fileOperationsApiService.GetContentBytes(request.IngestorRequest.RootPath, + request.DocumentFileName); + + var type = documentValues.NoticeName.GetValueFromName(); + + var genericDocumentRequest = new GenericDocumentRequest + { + Content = contentBytes, + GenericDocumentAttribute = genericDocumentAttribute, + GenericDocumentMetadata = new GenericDocumentMetadata + { + Source = Source, + DataSource = DataSource, + Name = documentValues.PdfName, + Type = type, + CreatedDate = DateTime.Now.Date, + TraceId = request.IngestorRunInfoId + } + }; + return genericDocumentRequest; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgTemenosNoticeProcessingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgTemenosNoticeProcessingService.cs new file mode 100644 index 0000000..757c9b8 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgTemenosNoticeProcessingService.cs @@ -0,0 +1,131 @@ +using System.Globalization; +using Newtonsoft.Json; +using Serilog; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Extensions; +using LCU.Library.DocumentType.Models.Requests.Account; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.DocumentIngestorModels.Validations; +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; + +public class OsgTemenosNoticeProcessingService : DocumentProcessingService, IDocumentProcessingService +{ + private readonly IAccountOwnerDeterminingService _accountOwnerDeterminingService; + private readonly IFileOperationsApiService _fileOperationsApiService; + private readonly IDocumentTypeUploaderApiService _documentTypeUploaderApiService; + private const DataSourceTypes DataSource = DataSourceTypes.DNA; + private const SourceTypes Source = SourceTypes.XDI; + private const string DateFormat = "MMddyyyy"; + + public OsgTemenosNoticeProcessingService(IAccountOwnerDeterminingService accountOwnerDeterminingService, + IFileOperationsApiService fileOperationsApiService, + IDocumentTypeUploaderApiService documentTypeUploaderApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _documentTypeUploaderApiService = documentTypeUploaderApiService; + _fileOperationsApiService = fileOperationsApiService; + _accountOwnerDeterminingService = accountOwnerDeterminingService; + } + + public async Task ProcessRequest(ProcessingRequest request) + { + var processResult = new ProcessResult(); + try + { + Log.Debug("Starting OsgTemenosNotice ProcessRequest."); + ArgumentNullException.ThrowIfNull(request); + + var documentValues = JsonConvert.DeserializeObject(request.DocumentValuePayload); + ArgumentNullException.ThrowIfNull(documentValues); + + processResult = ValidateRecord(processResult, documentValues); + + if (!processResult.Success) + { + return processResult; + } + + if (!DateTime.TryParseExact(documentValues.CreationDate, + DateFormat, + CultureInfo.InvariantCulture, + DateTimeStyles.AssumeLocal, + out var creationDate)) + { + var message = $"A Creation Date of {documentValues.CreationDate} could not " + + $"be properly formatted from format: {DateFormat}"; + return ProcessResult.ProcessDataMappingFailure(processResult, + message); + } + + var accountOwnerAttribute = await _accountOwnerDeterminingService.DetermineAccountOwnerAttribute(documentValues.EntityName, + documentValues.AccountNumber, + creationDate, + request.OwnerOverrideInfo); + if (!accountOwnerAttribute.Success) + { + return ProcessResult.ProcessDataMappingFailure(processResult, + accountOwnerAttribute.Message); + } + + var accountOwnerRequest = await BuildUploadRequest(request, + documentValues, + creationDate, + accountOwnerAttribute.Payload); + await _documentTypeUploaderApiService.UploadAccountDocument(accountOwnerRequest, request, processResult); + + Log.Debug("Ending OsgTemenosNoticesDocument ProcessRequest."); + } + catch (Exception exception) + { + var message = + $"An Exception occured while OsgTemenosNoticesDocument ProcessRequest. Exception Message: {exception.Message}"; + Log.Error(exception, message); + processResult = ProcessResult.ProcessCriticalFailure(processResult, message); + } + + return processResult; + } + + private static ProcessResult ValidateRecord(ProcessResult processResult, OsgTemenosNoticesDocument documentValues) + { + processResult = MetaDataValidation.ValidateAccountNumber(processResult, documentValues.AccountNumber); + processResult = MetaDataValidation.ValidatePdf(processResult, documentValues.PDF); + processResult = MetaDataValidation.ValidateFullName(processResult, documentValues.EntityName); + processResult = MetaDataValidation.ValidateDate(processResult, documentValues.CreationDate, DateFormat); + processResult = MetaDataValidation.ValidateDocumentType(processResult, documentValues.DocumentType); + return processResult; + } + + private async Task BuildUploadRequest(ProcessingRequest request, + OsgTemenosNoticesDocument documentValues, + DateTime creationDate, + AccountAttribute accountAttribute) + { + var contentBytes = await _fileOperationsApiService.GetContentBytes(request.IngestorRequest.RootPath, request.DocumentFileName); + + var type = documentValues.DocumentType.GetValueFromName(); + ArgumentNullException.ThrowIfNull(type); + + return new AccountDocumentRequest + { + Content = contentBytes, + AccountAttribute = accountAttribute, + AccountDocumentMetadata = new AccountDocumentMetadata + { + Source = Source, + DataSource = DataSource, + Name = documentValues.PDF, + Type = type, + CreatedDate = creationDate, + TraceId = request.IngestorRunInfoId + } + }; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgVehicleTaxStatementProcessingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgVehicleTaxStatementProcessingService.cs new file mode 100644 index 0000000..2509244 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgVehicleTaxStatementProcessingService.cs @@ -0,0 +1,126 @@ +using Newtonsoft.Json; +using Serilog; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Extensions; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.DocumentType.Models.Requests.PrimaryOwner; +using LCU.Library.DocumentType.Models.Requests.Generic; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.DocumentIngestorModels.Validations; +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using Microsoft.VisualBasic; +using System.Globalization; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; + +public class OsgVehicleTaxStatementProcessingService : DocumentProcessingService, IDocumentProcessingService +{ + private readonly IPrimaryOwnerDeterminingService _primaryOwnerDeterminingService; + private readonly IFileOperationsApiService _fileOperationsApiService; + private readonly IDocumentTypeUploaderApiService _documentTypeUploaderApiService; + private const DataSourceTypes DataSource = DataSourceTypes.DNA; + private const SourceTypes Source = SourceTypes.OSG; + private const string DateFormat = "MMddyyyy"; + + public OsgVehicleTaxStatementProcessingService(IPrimaryOwnerDeterminingService userIdDeterminingService, + IFileOperationsApiService fileOperationsApiService, + IDocumentTypeUploaderApiService documentTypeUploaderApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _documentTypeUploaderApiService = documentTypeUploaderApiService; + _fileOperationsApiService = fileOperationsApiService; + _primaryOwnerDeterminingService = userIdDeterminingService; + } + + public async Task ProcessRequest(ProcessingRequest request) + { + var processResult = new ProcessResult(); + try + { + Log.Debug("Starting OsgVehicleTaxStatement ProcessRequest."); + ArgumentNullException.ThrowIfNull(request); + var documentValues = JsonConvert.DeserializeObject(request.DocumentValuePayload); + ArgumentNullException.ThrowIfNull(documentValues); + + processResult = ValidateRecord(processResult, documentValues); + if (!processResult.Success) + { + return processResult; + } + + if (!DateTime.TryParseExact(documentValues.CreationDate, DateFormat, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out var creationDate)) + { + var message = $"A Creation Date of '{documentValues.CreationDate}' could not be properly formatted " + + $"for an Account Owner of EntityName: {documentValues?.RecipientName} and EntityId: {documentValues?.AccountNumber}"; + processResult = ProcessResult.ProcessDataMappingFailure(processResult, message); + return processResult; + } + + var primaryOwnerAttribute = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttribute( + documentValues.RecipientName, + documentValues.AccountNumber, + creationDate, + request.OwnerOverrideInfo); + + if (!primaryOwnerAttribute.Success) + { + processResult = ProcessResult.ProcessDataMappingFailure(processResult, + primaryOwnerAttribute.Message); + return processResult; + } + + var uploadRequest = await BuildUploadRequest(request, documentValues, primaryOwnerAttribute.Payload, creationDate); + await _documentTypeUploaderApiService.UploadPrimaryOwnerDocument(uploadRequest, request, processResult); + } + catch (Exception exception) + { + var message = "An Exception occured while OsgVehicleTaxStatement ProcessRequest. " + + $"Exception Message: {exception.Message} "; + Log.Error(exception, message); + processResult = ProcessResult.ProcessCriticalFailure(processResult, message); + } + + Log.Debug("Ending OsgVehicleTaxStatement ProcessRequest."); + return processResult; + } + + public ProcessResult ValidateRecord(ProcessResult processResult, OsgTaxStatement documentValues) + { + processResult = MetaDataValidation.ValidateAccountNumber(processResult, documentValues.AccountNumber); + processResult = MetaDataValidation.ValidateFileName(processResult, documentValues.NoticeName); + processResult = MetaDataValidation.ValidateFullName(processResult, documentValues.RecipientName); + processResult = MetaDataValidation.ValidatePdf(processResult, documentValues.PdfName); + return processResult; + } + + public async Task BuildUploadRequest(ProcessingRequest request, + OsgTaxStatement documentValues, + PrimaryOwnerAttribute primaryOwnerAttribute, + DateTime creationDate) + { + var contentBytes = await _fileOperationsApiService.GetContentBytes(request.IngestorRequest.RootPath, + request.DocumentFileName); + + var type = documentValues.NoticeId.GetValueFromName(); + + var primaryOwnerDocumentRequest = new PrimaryOwnerDocumentRequest + { + Content = contentBytes, + PrimaryOwnerAttribute = primaryOwnerAttribute, + PrimaryOwnerDocumentMetadata = new PrimaryOwnerDocumentMetadata + { + Source = Source, + DataSource = DataSource, + Name = documentValues.PdfName, + Type = type, + CreatedDate = creationDate, + TraceId = request.IngestorRunInfoId + } + }; + return primaryOwnerDocumentRequest; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgWeilandStatementProcessingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgWeilandStatementProcessingService.cs new file mode 100644 index 0000000..137dfc7 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/OsgWeilandStatementProcessingService.cs @@ -0,0 +1,137 @@ +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Extensions; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.DocumentType.Models.Requests.Account; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.DocumentIngestorModels.Validations; +using Newtonsoft.Json; +using Serilog; +using System.Globalization; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices +{ + public class OsgWeilandStatementProcessingService : DocumentProcessingService, IDocumentProcessingService + { + private const DataSourceTypes DataSource = DataSourceTypes.WEILAND; + private const SourceTypes Source = SourceTypes.OSG; + private readonly IAccountOwnerDeterminingService _accountOwnerDeterminingService; + private readonly IFileOperationsApiService _fileOperationsApiService; + private readonly IDocumentTypeUploaderApiService _documentTypeUploaderApiService; + private const string DateFormat = "yyyyMMdd"; + + public OsgWeilandStatementProcessingService(IAccountOwnerDeterminingService accountOwnerDeterminingService, + IFileOperationsApiService fileOperationsApiService, + IDocumentTypeUploaderApiService documentTypeUploaderApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _documentTypeUploaderApiService = documentTypeUploaderApiService; + _fileOperationsApiService = fileOperationsApiService; + _accountOwnerDeterminingService = accountOwnerDeterminingService; + } + + public async Task ProcessRequest(ProcessingRequest request) + { + var processResult = new ProcessResult(); + try + { + Log.Debug("Starting OsgWeilandDocument ProcessRequest."); + ArgumentNullException.ThrowIfNull(request); + var documentValues = JsonConvert.DeserializeObject(request.DocumentValuePayload); + ArgumentNullException.ThrowIfNull(documentValues); + + processResult = ValidateRecord(processResult, documentValues); + if (!processResult.Success) + { + return processResult; + } + if (!DateTime.TryParseExact(documentValues.Date, DateFormat, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out var creationDate)) + { + var message = $"A Creation Date of '{documentValues.Date}' could not be properly formatted " + + $"for an Account Owner of EntityName: {documentValues?.AccountTitle} and EntityId: {documentValues?.AccountNumber}"; + processResult = ProcessResult.ProcessDataMappingFailure(processResult, message); + return processResult; + } + + if (EnumExtensions.IsDocumentTypeOf(documentValues.DocCode)) + { + var accountOwnerAttribute = await _accountOwnerDeterminingService.DetermineAccountOwnerAttribute(documentValues.AccountTitle, + documentValues.AccountNumber, + creationDate, + request.OwnerOverrideInfo); + + if (!accountOwnerAttribute.Success) + { + processResult = ProcessResult.ProcessDataMappingFailure(processResult, accountOwnerAttribute.Message); + return processResult; + } + + var accountOwnerRequest = await BuildUploadRequest(request, + documentValues, + creationDate, + accountOwnerAttribute.Payload); + await _documentTypeUploaderApiService.UploadAccountDocument(accountOwnerRequest, request, processResult); + + } + else + { + var message = $"Document Type of {documentValues.DocCode} could not be found." + + $"for an Account Owner of EntityName: {documentValues?.AccountTitle} and EntityId: {documentValues?.AccountNumber}"; + Log.Error(message); + processResult = ProcessResult.ProcessCriticalFailure(processResult, message); + return processResult; + } + + Log.Debug("Ending OsgWeilandStatement ProcessRequest."); + + } + catch (Exception exception) + { + var message = "An Exception occured while OsgWeilandStatement ProcessRequest. " + + $"Exception Message: {exception.Message} "; + Log.Error(exception, message); + processResult = ProcessResult.ProcessCriticalFailure(processResult, message); + } + return processResult; + } + + private async Task BuildUploadRequest(ProcessingRequest request, + OsgWeilandStatement documentValues, + DateTime creationDate, + AccountAttribute accountAttribute) + { + var contentBytes = await _fileOperationsApiService.GetContentBytes(request.IngestorRequest.RootPath, request.DocumentFileName); + + var type = documentValues.DocCode.GetValueFromName(); + ArgumentNullException.ThrowIfNull(type); + + return new AccountDocumentRequest + { + Content = contentBytes, + AccountAttribute = accountAttribute, + AccountDocumentMetadata = new AccountDocumentMetadata + { + Source = Source, + DataSource = DataSource, + Name = documentValues.PdfName, + Type = type, + CreatedDate = creationDate, + TraceId = request.IngestorRunInfoId + } + }; + } + + private static ProcessResult ValidateRecord(ProcessResult processResult, OsgWeilandStatement documentValues) + { + processResult = MetaDataValidation.ValidateAccountNumber(processResult, documentValues.AccountNumber); + processResult = MetaDataValidation.ValidatePdf(processResult, documentValues.PdfName); + processResult = MetaDataValidation.ValidateDate(processResult, documentValues.Date, DateFormat); + processResult = MetaDataValidation.ValidateDocumentType(processResult, documentValues.DocCode); + return processResult; + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/XdiActionNoticesProcessingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/XdiActionNoticesProcessingService.cs new file mode 100644 index 0000000..472234b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/XdiActionNoticesProcessingService.cs @@ -0,0 +1,105 @@ +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Extensions; +using LCU.Library.DocumentType.Models.Requests.Generic; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.DocumentIngestorModels.Validations; +using LCU.Library.Internal.LCUServiceFactory.Configurations; +using Newtonsoft.Json; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; + +public class XdiActionNoticesProcessingService : DocumentProcessingService, IDocumentProcessingService +{ + private const DataSourceTypes DataSource = DataSourceTypes.ACTION; + private const SourceTypes Source = SourceTypes.XDI; + private const string DateFormat = "mm/dd/yyyy"; + + private readonly IFileOperationsApiService _fileOperationsApiService; + private readonly IDocumentTypeUploaderApiService _documentTypeUploaderApiService; + + public XdiActionNoticesProcessingService(IFileOperationsApiService fileOperationsApiService, + IDocumentTypeUploaderApiService documentTypeUploaderApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _documentTypeUploaderApiService = documentTypeUploaderApiService; + _fileOperationsApiService = fileOperationsApiService; + } + + public async Task ProcessRequest(ProcessingRequest request) + { + var processResult = new ProcessResult(); + try + { + Log.Debug("Starting XdiActionNotice ProcessRequest."); + ArgumentNullException.ThrowIfNull(request); + + var documentValues = JsonConvert.DeserializeObject(request.DocumentValuePayload); + ArgumentNullException.ThrowIfNull(documentValues); + + processResult = ValidateRecord(processResult, documentValues); + + if (!processResult.Success) + { + return processResult; + } + + var genericAttribute = new GenericDocumentAttribute + { + EntityName = documentValues.EntityName + }; + + var uploadRequest = await BuildUploadRequest(request, documentValues, genericAttribute); + await _documentTypeUploaderApiService.UploadGenericDocument(uploadRequest, request, processResult); + + Log.Debug("Ending XdiActionNoticeDocument ProcessRequest."); + } + catch (Exception exception) + { + var message = + $"An Exception occured while XdiActionNoticeDocument ProcessRequest. Exception Message: {exception.Message}"; + Log.Error(exception, message); + processResult = ProcessResult.ProcessCriticalFailure(processResult, message); + } + + return processResult; + } + + private static ProcessResult ValidateRecord(ProcessResult processResult, XdiActionNoticesDocument documentValues) + { + processResult = MetaDataValidation.ValidateFullName(processResult, documentValues.EntityName); + processResult = MetaDataValidation.ValidateDate(processResult, documentValues.CreationDate, DateFormat); + processResult = MetaDataValidation.ValidateDocumentType(processResult, documentValues.DocumentType); + return processResult; + } + + public async Task BuildUploadRequest(ProcessingRequest request, + XdiActionNoticesDocument documentValues, + GenericDocumentAttribute genericDocumentAttribute) + { + var contentBytes = await _fileOperationsApiService.GetContentBytes(request.IngestorRequest.RootPath, + request.DocumentFileName); + + var type = documentValues.DocumentType.GetValueFromName(); + + var genericDocumentRequest = new GenericDocumentRequest + { + Content = contentBytes, + GenericDocumentAttribute = genericDocumentAttribute, + GenericDocumentMetadata = new GenericDocumentMetadata + { + Source = Source, + DataSource = DataSource, + Name = documentValues.DocumentName, + Type = type, + CreatedDate = DateTime.Parse(documentValues.CreationDate), + TraceId = request.IngestorRunInfoId + } + }; + return genericDocumentRequest; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/XdiDnaNoticeDocumentProcessingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/XdiDnaNoticeDocumentProcessingService.cs new file mode 100644 index 0000000..a71a242 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentProcessorServices/XdiDnaNoticeDocumentProcessingService.cs @@ -0,0 +1,131 @@ +using System.Globalization; +using Newtonsoft.Json; +using Serilog; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Extensions; +using LCU.Library.DocumentType.Models.Requests.Account; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.DocumentIngestorModels.Validations; +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; + +public class XdiDnaNoticeDocumentProcessingService : DocumentProcessingService, IDocumentProcessingService +{ + private readonly IAccountOwnerDeterminingService _accountOwnerDeterminingService; + private readonly IFileOperationsApiService _fileOperationsApiService; + private readonly IDocumentTypeUploaderApiService _documentTypeUploaderApiService; + private const DataSourceTypes DataSource = DataSourceTypes.DNA; + private const SourceTypes Source = SourceTypes.XDI; + private const string DateFormat = "MM/dd/yyyy"; + + public XdiDnaNoticeDocumentProcessingService(IAccountOwnerDeterminingService accountOwnerDeterminingService, + IFileOperationsApiService fileOperationsApiService, + IDocumentTypeUploaderApiService documentTypeUploaderApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _documentTypeUploaderApiService = documentTypeUploaderApiService; + _fileOperationsApiService = fileOperationsApiService; + _accountOwnerDeterminingService = accountOwnerDeterminingService; + } + + public async Task ProcessRequest(ProcessingRequest request) + { + var processResult = new ProcessResult(); + try + { + Log.Debug("Starting XdiDnaNoticeDocument ProcessRequest."); + ArgumentNullException.ThrowIfNull(request); + + var documentValues = JsonConvert.DeserializeObject(request.DocumentValuePayload); + ArgumentNullException.ThrowIfNull(documentValues); + + processResult = ValidateRecord(processResult, documentValues); + + if (!processResult.Success) + { + return processResult; + } + + if (!DateTime.TryParseExact(documentValues.CreationDate, + DateFormat, + CultureInfo.InvariantCulture, + DateTimeStyles.AssumeLocal, + out var creationDate)) + { + var message = $"A Creation Date of {documentValues.CreationDate} could not " + + $"be properly formatted from format: {DateFormat}"; + return ProcessResult.ProcessDataMappingFailure(processResult, + message); + } + + var accountOwnerAttribute = await _accountOwnerDeterminingService.DetermineAccountOwnerAttribute(documentValues.EntityName, + documentValues.AccountNumber, + creationDate, + request.OwnerOverrideInfo); + if (!accountOwnerAttribute.Success) + { + return ProcessResult.ProcessDataMappingFailure(processResult, + accountOwnerAttribute.Message); + } + + var accountOwnerRequest = await BuildUploadRequest(request, + documentValues, + creationDate, + accountOwnerAttribute.Payload); + await _documentTypeUploaderApiService.UploadAccountDocument(accountOwnerRequest, request, processResult); + + Log.Debug("Ending XdiDnaNoticeDocument ProcessRequest."); + } + catch (Exception exception) + { + var message = + $"An Exception occured while XdiDnaNoticeDocument ProcessRequest. Exception Message: {exception.Message}"; + Log.Error(exception, message); + processResult = ProcessResult.ProcessCriticalFailure(processResult, message); + } + + return processResult; + } + + private static ProcessResult ValidateRecord(ProcessResult processResult, XdiDnaNoticesDocument documentValues) + { + processResult = MetaDataValidation.ValidateAccountNumber(processResult, documentValues.AccountNumber); + processResult = MetaDataValidation.ValidatePdf(processResult, documentValues.PDF); + processResult = MetaDataValidation.ValidateFullName(processResult, documentValues.EntityName); + processResult = MetaDataValidation.ValidateDate(processResult, documentValues.CreationDate, DateFormat); + processResult = MetaDataValidation.ValidateDocumentType(processResult, documentValues.DocumentType); + return processResult; + } + + private async Task BuildUploadRequest(ProcessingRequest request, + XdiDnaNoticesDocument documentValues, + DateTime creationDate, + AccountAttribute accountAttribute) + { + var contentBytes = await _fileOperationsApiService.GetContentBytes(request.IngestorRequest.RootPath, request.DocumentFileName); + + var type = documentValues.DocumentType.GetValueFromName(); + ArgumentNullException.ThrowIfNull(type); + + return new AccountDocumentRequest + { + Content = contentBytes, + AccountAttribute = accountAttribute, + AccountDocumentMetadata = new AccountDocumentMetadata + { + Source = Source, + DataSource = DataSource, + Name = documentValues.PDF, + Type = type, + CreatedDate = creationDate, + TraceId = request.IngestorRunInfoId + } + }; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentReprocessingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentReprocessingService.cs new file mode 100644 index 0000000..693bd27 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentReprocessingService.cs @@ -0,0 +1,132 @@ +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using Newtonsoft.Json; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Services; + +public class DocumentReprocessingService : IDocumentReprocessingService +{ + private readonly IIngestorRunInfoService _ingestorRunInfoService; + private readonly IDocumentProcessingInfoService _documentProcessingInfoService; + private readonly IOwnerOverrideInfoService _ownerOverrideInfoService; + private readonly IQueueDocumentProcessingService _queueDocumentProcessing; + private readonly ApiConfiguration _apiConfiguration; + + public DocumentReprocessingService(IIngestorRunInfoService ingestorRunInfoService, + IDocumentProcessingInfoService documentProcessingInfoService, + IOwnerOverrideInfoService ownerOverrideInfoService, + IQueueDocumentProcessingService queueDocumentProcessing, + ApiConfiguration apiConfiguration) + { + _ingestorRunInfoService = ingestorRunInfoService; + _documentProcessingInfoService = documentProcessingInfoService; + _ownerOverrideInfoService = ownerOverrideInfoService; + _queueDocumentProcessing = queueDocumentProcessing; + _apiConfiguration = apiConfiguration; + } + + public async Task QueueReprocessDocumentByDocumentProcessingInfoId(int documentProcessingInfoId, string userName) + { + try + { + var ownerOverrideInfos = await _ownerOverrideInfoService.GetByDocumentProcessingInfoIdAsync(documentProcessingInfoId); + var logMessage = $"Reprocess run of DocumentProcessingInfoId: {documentProcessingInfoId} by {userName} on {DateTime.Now}"; + + await QueueProcessingRequest(documentProcessingInfoId, ownerOverrideInfos?.FirstOrDefault(), logMessage, userName); + } + catch (ArgumentNullException exception) + { + Log.Error(exception, $"Failure to reprocess, DocumentProcessingInfo could not be found. " + + $"DocumentProcessingInfoId: {documentProcessingInfoId}"); + throw; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure reprocessing DocumentProcessingInfo. DocumentProcessingInfoId: {documentProcessingInfoId}"); + throw new ServiceException($"Failure reprocessing DocumentProcessingInfo. DocumentProcessingInfoId: {documentProcessingInfoId}"); + } + } + + public async Task QueueOverrideDocumentByDocumentProcessingInfoId(OwnerOverrideInfo ownerOverrideInfo) + { + try + { + ownerOverrideInfo = await _ownerOverrideInfoService.SaveAsync(ownerOverrideInfo); + var logMessage = $"Override triggered by {ownerOverrideInfo.UserName} at {DateTime.Now} with values: {JsonConvert.SerializeObject(ownerOverrideInfo)}"; + + await QueueProcessingRequest(ownerOverrideInfo.DocumentProcessingInfoId, ownerOverrideInfo, logMessage, ownerOverrideInfo.UserName); + } + catch (ArgumentNullException exception) + { + Log.Error(exception, $"Failure to override, DocumentProcessingInfo could not be found. " + + $"DocumentProcessingInfoId: {ownerOverrideInfo.DocumentProcessingInfoId}"); + throw; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure overriding DocumentProcessingInfo. " + + $"DocumentProcessingInfoId: {ownerOverrideInfo.DocumentProcessingInfoId} | " + + $"EntityType: {Enum.GetName(typeof(EntityTypes), ownerOverrideInfo.EntityType)} | " + + $"EntityId: {ownerOverrideInfo.EntityId}"); + throw new ServiceException($"Failure overriding DocumentProcessingInfo. DocumentProcessingInfoId: {ownerOverrideInfo.DocumentProcessingInfoId}"); + } + } + + public async Task QueueReprocessAllCriticalFailures(string userName) + { + try + { + var result = await _documentProcessingInfoService.GetByProcessStatusTypeAsync(ProcessStatusTypes.CriticalFailure); + var documentProcessingInfos = result.Take(_apiConfiguration.CriticalFailureReprocessLimit); + + foreach (var documentProcessingInfo in documentProcessingInfos) + { + await QueueReprocessDocumentByDocumentProcessingInfoId(documentProcessingInfo.DocumentProcessingInfoId, userName); + } + } + catch (ArgumentNullException exception) + { + var message = "Failure during reprocess of DocumentProcessingInfos of ProcessStatusType: CriticalFailure." + + $" ExceptionMessage: {exception.Message}"; + Log.Error(exception, message); + throw new ServiceException(message); + } + catch (Exception exception) + { + Log.Error(exception, "Failure to reprocess all DocumentProcessingInfos with ProcessStatusType: CriticalFailure."); + throw new ServiceException("Failure to reprocess all DocumentProcessingInfos with ProcessStatusType: CriticalFailure."); + } + } + + private async Task QueueProcessingRequest(int documentProcessingInfoId, OwnerOverrideInfo? ownerOverrideInfo, string logMessage, string userName) + { + var documentProcessingInfo = await _documentProcessingInfoService.GetByIdAsync(documentProcessingInfoId); + ArgumentNullException.ThrowIfNull(documentProcessingInfo); + + var ingestorRunInfo = await _ingestorRunInfoService.GetByIdAsync(documentProcessingInfo.IngestorRunInfoId); + ArgumentNullException.ThrowIfNull(ingestorRunInfo); + + var processingRequest = new ProcessingRequest() + { + DocumentProcessingInfoId = documentProcessingInfoId, + IngestorRunInfoId = documentProcessingInfo.IngestorRunInfoId, + DocumentFileName = documentProcessingInfo.DocumentFileName, + DocumentValuePayload = documentProcessingInfo.DocumentValuePayload, + IngestorRequest = new IngestorRequest() + { + IngestorType = ingestorRunInfo.IngestorType, + RootPath = ingestorRunInfo.IndexFilePath, + IndexFileName = ingestorRunInfo.IndexFileName + }, + OwnerOverrideInfo = ownerOverrideInfo + }; + + await _documentProcessingInfoService.UpdateStatusAndAddLog(documentProcessingInfoId, ProcessStatusTypes.Reprocessing, logMessage, userName); + await _queueDocumentProcessing.QueueDocumentProcessingRequest(processingRequest); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentTypeArchiveDeleteInfoService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentTypeArchiveDeleteInfoService.cs new file mode 100644 index 0000000..d213665 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/DocumentTypeArchiveDeleteInfoService.cs @@ -0,0 +1,134 @@ +using System.Data.SqlClient; +using Serilog; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestorLib.Repositories; +namespace LCU.API.Internal.DocumentIngestor.Services; + +public class DocumentTypeArchiveDeleteInfoService : IDocumentTypeArchiveDeleteInfoService +{ + private readonly IDocumentTypeArchiveDeleteInfoRepository _documentTypeArchiveDeleteInfoRepository; + private readonly IUnitOfWork _unitOfWork; + + public DocumentTypeArchiveDeleteInfoService(IUnitOfWork unitOfWork, + IDocumentTypeArchiveDeleteInfoRepository documentTypeArchiveDeleteInfoRepository) + { + _documentTypeArchiveDeleteInfoRepository = documentTypeArchiveDeleteInfoRepository; + _unitOfWork = unitOfWork; + } + + public async Task> GetAsync() + { + try + { + var documentProcessingInfos = await _documentTypeArchiveDeleteInfoRepository.FindAsync(); + return documentProcessingInfos; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving DocumentTypeArchiveDeleteInfos."); + throw new ServiceException($"Failure retrieving DocumentTypeArchiveDeleteInfos."); + } + } + + public async Task GetByDocumentTypeNameAsync(TEnum documentType) where TEnum : Enum + { + try + { + var typesName = Enum.GetName(typeof(TEnum), documentType); + ArgumentNullException.ThrowIfNull(typesName); + var processingLogs = await _documentTypeArchiveDeleteInfoRepository.FindByDocumentTypeNameAsync(typesName); + return processingLogs; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving DocumentTypeArchiveDeleteInfo with DocumentType {documentType}."); + throw new ServiceException($"Failure retrieving DocumentTypeArchiveDeleteInfo with DocumentType {documentType}."); + } + } + + public async Task GetByDocumentTypeNameAsync(string documentTypeName) + { + try + { + var processingLogs = await _documentTypeArchiveDeleteInfoRepository.FindByDocumentTypeNameAsync(documentTypeName); + return processingLogs; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving DocumentTypeArchiveDeleteInfo with DocumentTypeName {documentTypeName}."); + throw new ServiceException($"Failure retrieving DocumentTypeArchiveDeleteInfo with DocumentType {documentTypeName}."); + } + } + + public async Task SaveAsync(DocumentTypeArchiveDeleteInfo documentTypeArchiveDeleteInfo) + { + try + { + var result = await _documentTypeArchiveDeleteInfoRepository.AddAsync(documentTypeArchiveDeleteInfo); + await _unitOfWork.CompleteAsync(); + return result; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure saving DocumentTypeArchiveDeleteInfo."); + throw new ServiceException($"Failure saving DocumentTypeArchiveDeleteInfo. Exception Message: {exception.Message}"); + } + } + + public async Task Update(DocumentTypeArchiveDeleteInfo documentTypeArchiveDeleteInfo) + { + try + { + var existing = await GetByDocumentTypeNameAsync(documentTypeArchiveDeleteInfo.DocumentTypeName); + if(existing == null) + { + return existing; + } + + existing.ArchiveDays = documentTypeArchiveDeleteInfo.ArchiveDays; + existing.ArchiveMonths = documentTypeArchiveDeleteInfo.ArchiveMonths; + existing.DeleteDays = documentTypeArchiveDeleteInfo.DeleteDays; + + _documentTypeArchiveDeleteInfoRepository.Update(existing); + _unitOfWork.Complete(); + + return existing; + } + catch (SqlException sqlException) + { + Log.Error(sqlException, $"SQL Failure updating DocumentTypeArchiveDeleteInfo. " + + $"DocumentTypeName: {documentTypeArchiveDeleteInfo.DocumentTypeName}"); + throw new ServiceException($"SQL Failure updating DocumentTypeArchiveDeleteInfo. " + + $"DocumentTypeName: {documentTypeArchiveDeleteInfo.DocumentTypeName}"); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure updating DocumentTypeArchiveDeleteInfo. " + + $"DocumentTypeName: {documentTypeArchiveDeleteInfo.DocumentTypeName}"); + throw new ServiceException($"Failure updating DocumentTypeArchiveDeleteInfo. " + + $"DocumentTypeName: {documentTypeArchiveDeleteInfo.DocumentTypeName}"); + } + } + + public async Task Delete(string documentTypeName) + { + try + { + var documentTypeArchiveDeleteInfo = await GetByDocumentTypeNameAsync(documentTypeName); + ArgumentNullException.ThrowIfNull(documentTypeArchiveDeleteInfo); + _documentTypeArchiveDeleteInfoRepository.Remove(documentTypeArchiveDeleteInfo); + _unitOfWork.Complete(); + } + catch (SqlException sqlException) + { + Log.Error(sqlException, $"SQL failure removing DocumentTypeArchiveDeleteInfo. DocumentTypeName: {documentTypeName}"); + throw new ServiceException($"SQL failure removing DocumentTypeArchiveDeleteInfo. DocumentTypeName: {documentTypeName}"); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure removing DocumentTypeArchiveDeleteInfo. DocumentTypeName: {documentTypeName}"); + throw new ServiceException($"Failure removing DocumentTypeArchiveDeleteInfo. DocumentTypeName: {documentTypeName}"); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IDocumentProcessingInfoService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IDocumentProcessingInfoService.cs new file mode 100644 index 0000000..97e8b45 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IDocumentProcessingInfoService.cs @@ -0,0 +1,69 @@ +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; + +namespace LCU.API.Internal.DocumentIngestor.Services; + +public interface IDocumentProcessingInfoService +{ + Task> GetAsync(); + Task GetByIdAsync(int id); + Task> GetListByIdAsync(List ids); + Task> GetByIngestorRunInfoIdAsync(Guid ingestorRunInfoId); + Task> GetByProcessStatusTypeAsync(ProcessStatusTypes statusType, bool? isUnknown = null); + Task> GetByProcessStatusTypeListAsync(List statusTypes, bool? isUnknown = null); + Task> GetCompletedFirstPassByIngestorRunInfoIdAsync(Guid ingestorRunInfoId); + Task SaveAsync(DocumentProcessingInfo documentProcessingInfo); + Task SaveRangeAsync(DocumentProcessingInfo[] documentProcessingInfos); + Task UpdateStatusAndAddLog(int documentProcessingInfoId, + ProcessStatusTypes statusType, + string logMessage, + string userName, + bool? entityIsUnknown = null); + Task UpdateStatusAndAddLog(int documentProcessingInfoId, + ProcessStatusTypes statusType, + List logMessages, + string userName, + bool? entityIsUnknown = null); + Task UpdateStatusAndAddLog(DocumentProcessingInfo documentProcessingInfo, + ProcessStatusTypes statusType, + string logMessage, + string userName, + bool? entityIsUnknown = null); + Task UpdateStatusAndAddLog(DocumentProcessingInfo documentProcessingInfo, + ProcessStatusTypes statusType, + List logMessages, + string userName, + bool? entityIsUnknown = null); + Task> UpdateProcessCountAndStatusAndAddLog(List requests); + Task UpdateProcessCountAndStatusAndAddLog(int documentProcessingInfoId, + ProcessStatusTypes statusType, + string logMessage, + string userName, + bool? entityIsUnknown = null); + Task UpdateProcessCountAndStatusAndAddLog(int documentProcessingInfoId, + ProcessStatusTypes statusType, + List logMessages, + string userName, + bool? entityIsUnknown = null); + Task UpdateProcessCountAndStatusAndAddLog(DocumentProcessingInfo documentProcessingInfo, + ProcessStatusTypes statusType, + string logMessage, + string userName, + bool? entityIsUnknown = null); + Task UpdateProcessCountAndStatusAndAddLog(DocumentProcessingInfo documentProcessingInfo, + ProcessStatusTypes statusType, + List logMessages, + string userName, + bool? entityIsUnknown = null); + Task Update(DocumentProcessingInfo documentProcessingInfo); + Task> UpdateRangeAsync(IEnumerable documentProcessingInfos); + Task Delete(int id); + Task> GetFilteredDocumentProcessingInfo(Filter filter); + Task CountCompletedFirstPassByIngestorRunInfoIdAsync(Guid ingestorRunInfoId); + Task CountCompletedByIngestorRunInfoIdAsync(Guid ingestorRunInfoId); + Task?> SetDocumentsToEntityUnknown(EntityUnknownRequest request); + Task UpdateDocumentProcessingInfoStatus(DocumentProcessingInfoStatusRequest request); + Task> GetByDocumentIdsAsync(Guid[] ids); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IDocumentReprocessingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IDocumentReprocessingService.cs new file mode 100644 index 0000000..f248b21 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IDocumentReprocessingService.cs @@ -0,0 +1,10 @@ +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.API.Internal.DocumentIngestor.Services; + +public interface IDocumentReprocessingService +{ + Task QueueReprocessDocumentByDocumentProcessingInfoId(int documentProcessingInfoId, string userName); + Task QueueOverrideDocumentByDocumentProcessingInfoId(OwnerOverrideInfo ownerOverrideRequest); + Task QueueReprocessAllCriticalFailures(string userName); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IDocumentTypeArchiveDeleteInfoService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IDocumentTypeArchiveDeleteInfoService.cs new file mode 100644 index 0000000..eef95d5 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IDocumentTypeArchiveDeleteInfoService.cs @@ -0,0 +1,12 @@ +using LCU.Library.Internal.DocumentIngestorModels.Entities; +namespace LCU.API.Internal.DocumentIngestor.Services; + +public interface IDocumentTypeArchiveDeleteInfoService +{ + Task> GetAsync(); + Task GetByDocumentTypeNameAsync(TEnum documentType) where TEnum : Enum; + Task GetByDocumentTypeNameAsync(string documentType); + Task SaveAsync(DocumentTypeArchiveDeleteInfo documentTypeArchiveDeleteInfo); + Task Update(DocumentTypeArchiveDeleteInfo documentTypeArchiveDeleteInfo); + Task Delete(string documentTypeName); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IIngestorRunInfoService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IIngestorRunInfoService.cs new file mode 100644 index 0000000..7cb0460 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IIngestorRunInfoService.cs @@ -0,0 +1,12 @@ +using LCU.Library.Internal.DocumentIngestorModels.Entities; +namespace LCU.API.Internal.DocumentIngestor.Services; + +public interface IIngestorRunInfoService +{ + Task GetByIdAsync(Guid id); + Task> GetListByIdAsync(List ingestorRunInfoIds); + Task SaveAsync(IngestorRunInfo ingestorRunInfo); + Task Update(IngestorRunInfo ingestorRunInfo); + Task Delete(Guid ingestorRunInfoId); + IEnumerable FindByIngestionEndDateNotArchived(DateTime ingestionEndDate); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IMemberNotificationInfoService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IMemberNotificationInfoService.cs new file mode 100644 index 0000000..7c9be0b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IMemberNotificationInfoService.cs @@ -0,0 +1,22 @@ +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; + +namespace LCU.API.Internal.DocumentIngestor.Services; + +public interface IMemberNotificationInfoService +{ + Task> GetAsync(); + Task GetByIdAsync(int id); + Task> GetListByIdAsync(List ids); + Task> GetByDocumentProcessingInfoIdAsync(int documentProcessingInfoId); + Task> GetByNotificationStatusAsync(NotificationStatusTypes status); + Task> GetSendableMemberNotificationInfosAsync(DateTime minimumUploadDate, int maxAttempts); + Task SaveAsync(MemberNotificationInfo memberNotificationInfo); + Task SaveListAsync(List memberNotificationInfos); + Task Update(MemberNotificationInfo memberNotificationInfo); + Task> UpdateRange(IEnumerable memberNotificationInfos); + Task Delete(int id); + Task SetDocumentNotificationStatus(int memberNotificationInfoId, NotificationStatusTypes notificationStatus, string userName, string reason); + Task BulkSetDocumentNotificationStatus(BulkNotificationStatusRequest request, string userName); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IOsgPreprocessorInfoService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IOsgPreprocessorInfoService.cs new file mode 100644 index 0000000..9e87c3c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IOsgPreprocessorInfoService.cs @@ -0,0 +1,17 @@ +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.API.Internal.DocumentIngestor.Services; + +public interface IOsgPreprocessorInfoService +{ + Task> GetAsync(); + Task GetByIdAsync(int id); + Task> GetListByIdAsync(List ids); + Task> GetByDocumentTypeAsync(string documentType); + Task> GetByMemberNumberAsync(string memberNumber); + Task SaveAsync(OsgPreprocessorInfo osgPreprocessorInfo); + Task SaveListAsync(List osgPreprocessorInfos); + Task Update(OsgPreprocessorInfo osgPreprocessorInfo); + Task> UpdateRange(IEnumerable osgPreprocessorInfos); + Task Delete(int id); +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IOwnerOverrideInfoService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IOwnerOverrideInfoService.cs new file mode 100644 index 0000000..f310dc4 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IOwnerOverrideInfoService.cs @@ -0,0 +1,12 @@ +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.API.Internal.DocumentIngestor.Services; + +public interface IOwnerOverrideInfoService +{ + Task?> GetAsync(); + Task GetByIdAsync(int id); + Task?> GetByDocumentProcessingInfoIdAsync(int documentProcessingInfoId); + Task SaveAsync(OwnerOverrideInfo ownerOverrideInfo); + Task Delete(int id); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IPdfPartitionerLogService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IPdfPartitionerLogService.cs new file mode 100644 index 0000000..7a6303b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IPdfPartitionerLogService.cs @@ -0,0 +1,12 @@ +using LCU.Library.Internal.DocumentIngestorModels.Entities; +namespace LCU.API.Internal.DocumentIngestor.Services; + +public interface IPdfPartitionerLogService +{ + Task> GetAsync(); + Task GetByIdAsync(int id); + Task> GetByPdfPartitionerRunInfoIdAsync(Guid pdfPartitionerRunInfoId); + Task SaveListAsync(Guid pdfPartitionerRunInfoId, List messageLogs); + Task SaveAsync(PdfPartitionerLog pdfPartitionerLog); + Task Delete(int id); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IPdfPartitionerRunInfoService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IPdfPartitionerRunInfoService.cs new file mode 100644 index 0000000..09c34af --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IPdfPartitionerRunInfoService.cs @@ -0,0 +1,11 @@ +using LCU.Library.Internal.DocumentIngestorModels.Entities; +namespace LCU.API.Internal.DocumentIngestor.Services; + +public interface IPdfPartitionerRunInfoService +{ + Task GetByIdAsync(Guid id); + Task SaveAsync(PdfPartitionerRunInfo pdfPartitionerRunInfo); + Task IncreaseCountsAndUpdate(Guid pdfPartitionerRunInfoId, bool successful); + Task Update(PdfPartitionerRunInfo pdfPartitionerRunInfo); + Task Delete(Guid pdfPartitionerRunInfoId); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IProcessingLogService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IProcessingLogService.cs new file mode 100644 index 0000000..9d7e9f1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IProcessingLogService.cs @@ -0,0 +1,13 @@ +using LCU.Library.Internal.DocumentIngestorModels.Entities; +namespace LCU.API.Internal.DocumentIngestor.Services; + +public interface IProcessingLogService +{ + Task> GetAsync(); + Task GetByIdAsync(int id); + Task> GetByDocumentProcessingInfoIdAsync(int documentProcessingInfoId); + Task SaveAsync(ProcessingLog processingLog); + Task SaveRangeAsync(IEnumerable processingLogs); + Task Update(ProcessingLog processingLog); + Task Delete(int id); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IUploadCompletionReprocessingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IUploadCompletionReprocessingService.cs new file mode 100644 index 0000000..da2cea7 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IUploadCompletionReprocessingService.cs @@ -0,0 +1,7 @@ +namespace LCU.API.Internal.DocumentIngestor.Services; + +public interface IUploadCompletionReprocessingService +{ + Task QueueReprocessUploadCompletionByDocumentProcessingInfoId(int documentProcessingInfoId, string userName); + Task QueueReprocessAllNotificationDataFailures(string userName); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/FosDnaDocumentIndexService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/FosDnaDocumentIndexService.cs new file mode 100644 index 0000000..11d687c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/FosDnaDocumentIndexService.cs @@ -0,0 +1,83 @@ +using System.Globalization; +using Newtonsoft.Json; +using Serilog; +using CsvHelper; +using CsvHelper.Configuration; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; + +public class FosDnaDocumentIndexService : IndexParserService, IIndexParserService +{ + + private readonly IFileOperationsApiService _fileOperationsApiService; + + public FosDnaDocumentIndexService(IFileOperationsApiService fileOperationsApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _fileOperationsApiService = fileOperationsApiService; + } + + public async Task HandleIndexRequest(IngestorRequest request) + { + Log.Debug("Starting HandleIndexRequest for FosDnaDocument."); + var result = new IngestorResult(); + try + { + ArgumentNullException.ThrowIfNull(request); + var records = await GetFileContentAndParseRecords(request.FinalIndexFilePath); + result = PrepareRunInfoAndProcessRequests(request, records, result); + } + catch (Exception exception) + { + Log.Error(exception, "An Exception occured while HandleDnaDocumentRequest."); + result = new IngestorResult(true, exception.Message); + } + + Log.Debug("Ending HandleIndexRequest for FosDnaDocument."); + return result; + } + + public async Task> GetFileContentAndParseRecords(string finalIndexFilePath) + { + var indexFileContent = await _fileOperationsApiService.GetFileContent(finalIndexFilePath); + using var stringReader = new StringReader(indexFileContent); + var config = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = ",", HasHeaderRecord = false }; + using var csv = new CsvReader(stringReader, config); + var csvRecords = csv.GetRecords(); + return csvRecords.ToList(); + } + + public IngestorResult PrepareRunInfoAndProcessRequests(IngestorRequest request, + List documentMetaData, + IngestorResult result) + { + result.IngestorRunInfo = new IngestorRunInfo(Guid.NewGuid(), + DateTime.Now, + request.IngestorType, + request.RootPath, + request.IndexFileName, + documentMetaData.Count); + result.ProcessingRequests = new List(); + + foreach (var record in documentMetaData){ + var processingRequest = new ProcessingRequest + { + IngestorRunInfoId = result.IngestorRunInfo.IngestorRunInfoId, + IngestorRequest = request, + DocumentFileName = record.DocName, + DocumentValuePayload = JsonConvert.SerializeObject(record), + DocumentTypeDisplayName = record.DocType + }; + result.ProcessingRequests.Add(processingRequest); + } + + return result; + } + +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/FosLoanStatementIndexService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/FosLoanStatementIndexService.cs new file mode 100644 index 0000000..31557d4 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/FosLoanStatementIndexService.cs @@ -0,0 +1,98 @@ +using System.Text.RegularExpressions; +using System.Globalization; +using Newtonsoft.Json; +using Serilog; +using CsvHelper; +using CsvHelper.Configuration; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; + +public class FosLoanStatementIndexService : IndexParserService, IPdfIndexParserService +{ + + private readonly IFileOperationsApiService _fileOperationsApiService; + + public FosLoanStatementIndexService(IFileOperationsApiService fileOperationsApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _fileOperationsApiService = fileOperationsApiService; + } + + public async Task HandleIndexRequest(IngestorRequest request) + { + Log.Debug("Starting HandleIndexRequest for FosLoanStatement."); + var result = new IngestorResult(); + try + { + ArgumentNullException.ThrowIfNull(request); + var records = await GetFileContentAndParseRecords(request.FinalIndexFilePath); + result = PrepareRunInfoAndProcessRequests(request, records, result); + } + catch (Exception exception) + { + Log.Error(exception, "An Exception occured while HandleLoanStatementRequest."); + result = new IngestorResult(true, exception.Message); + } + + Log.Debug("Ending HandleIndexRequest for FosLoanStatement."); + return result; + } + + public async Task> GetFileContentAndParseRecords(string finalIndexFilePath) + { + var indexFileContent = await _fileOperationsApiService.GetFileContent(finalIndexFilePath); + using var stringReader = new StringReader(indexFileContent); + var config = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = "|", HasHeaderRecord = false }; + using var csv = new CsvReader(stringReader, config); + var csvRecords = csv.GetRecords(); + return csvRecords.ToList(); + } + + public IngestorResult PrepareRunInfoAndProcessRequests(IngestorRequest request, + List documentMetaData, + IngestorResult result) + { + result.IngestorRunInfo = new IngestorRunInfo(Guid.NewGuid(), + DateTime.Now, + request.IngestorType, + request.RootPath, + request.IndexFileName, + documentMetaData.Count()); + result.ProcessingRequests = new List(); + + foreach (var record in documentMetaData) + { + var parsedPdfName = CreateParsedPdfName(record); + var processingRequest = new ProcessingRequest() + { + IngestorRunInfoId = result.IngestorRunInfo.IngestorRunInfoId, + IngestorRequest = request, + DocumentFileName = parsedPdfName, + DocumentValuePayload = JsonConvert.SerializeObject(record), + DocumentTypeDisplayName = record.DocType + }; + result.ProcessingRequests.Add(processingRequest); + } + + return result; + } + + public string CreateParsedPdfName(T record) + { + if (record is not FosLoanStatement fosLoanStatement) + { + throw new Exception("Record is not a FosLoanStatement"); + } + + var documentWithoutExtensions = Path.GetFileNameWithoutExtension(fosLoanStatement.DocName); + var entityName = Regex.Replace(fosLoanStatement.EntityName, "[^A-Za-z0-9 -]", ""); + var parsedPdfName = $"{documentWithoutExtensions}_{entityName}_{fosLoanStatement.DocType}_{fosLoanStatement.StartingPage}.pdf"; + return parsedPdfName; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/FosTaxStatementIndexService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/FosTaxStatementIndexService.cs new file mode 100644 index 0000000..51a9527 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/FosTaxStatementIndexService.cs @@ -0,0 +1,82 @@ +using CsvHelper; +using CsvHelper.Configuration; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using Newtonsoft.Json; +using Serilog; +using System.Globalization; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; + +public class FosTaxStatementIndexService : IndexParserService, IIndexParserService +{ + private readonly IFileOperationsApiService _fileOperationsApiService; + + public FosTaxStatementIndexService(IFileOperationsApiService fileOperationsApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _fileOperationsApiService = fileOperationsApiService; + } + + public async Task HandleIndexRequest(IngestorRequest request) + { + Log.Debug("Starting HandleIndexRequest for FosTaxStatement."); + var result = new IngestorResult(); + try + { + ArgumentNullException.ThrowIfNull(request); + var records = await GetFileContentAndParseRecords(request.FinalIndexFilePath); + result = PrepareRunInfoAndProcessRequests(request, records, result); + } + catch (Exception exception) + { + Log.Error(exception, "An Exception occured while HandleTaxStatementRequest."); + result = new IngestorResult(true, exception.Message); + } + + Log.Debug("Ending HandleIndexRequest for FosTaxStatement."); + return result; + } + + public async Task> GetFileContentAndParseRecords(string finalIndexFilePath) + { + var indexFileContent = await _fileOperationsApiService.GetFileContent(finalIndexFilePath); + using var stringReader = new StringReader(indexFileContent); + var config = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = ",", HasHeaderRecord = false }; + using var csv = new CsvReader(stringReader, config); + var csvRecords = csv.GetRecords(); + return csvRecords.ToList(); + } + + public IngestorResult PrepareRunInfoAndProcessRequests(IngestorRequest request, + List documentMetaData, + IngestorResult result) + { + result.IngestorRunInfo = new IngestorRunInfo(Guid.NewGuid(), + DateTime.Now, + request.IngestorType, + request.RootPath, + request.IndexFileName, + documentMetaData.Count()); + result.ProcessingRequests = new List(); + + foreach (var record in documentMetaData) + { + var processingRequest = new ProcessingRequest() + { + IngestorRunInfoId = result.IngestorRunInfo.IngestorRunInfoId, + IngestorRequest = request, + DocumentFileName = record.PDF, + DocumentValuePayload = JsonConvert.SerializeObject(record), + DocumentTypeDisplayName = record.FileName + }; + result.ProcessingRequests.Add(processingRequest); + } + + return result; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/IIndexParserService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/IIndexParserService.cs new file mode 100644 index 0000000..914cd61 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/IIndexParserService.cs @@ -0,0 +1,10 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.LCUServiceFactory.Services; + +namespace LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; + +public interface IIndexParserService : ILcuService +{ + Task HandleIndexRequest(IngestorRequest request); + Task> GetFileContentAndParseRecords(string finalIndexFilePath); +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/IPdfIndexParserService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/IPdfIndexParserService.cs new file mode 100644 index 0000000..5819eb9 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/IPdfIndexParserService.cs @@ -0,0 +1,9 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.LCUServiceFactory.Services; + +namespace LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; + +public interface IPdfIndexParserService : IIndexParserService +{ + public string CreateParsedPdfName(T record); +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/IndexParserService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/IndexParserService.cs new file mode 100644 index 0000000..45bdb38 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/IndexParserService.cs @@ -0,0 +1,11 @@ +using LCU.Library.Internal.LCUServiceFactory.Configurations; +using LCU.Library.Internal.LCUServiceFactory.Services; + +namespace LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; + +public class IndexParserService : LcuAbstractService +{ + protected IndexParserService(ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration.GetServiceFactoryRegistrationByInterface()) + { } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgDnaNoticeSplitIndexService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgDnaNoticeSplitIndexService.cs new file mode 100644 index 0000000..2106491 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgDnaNoticeSplitIndexService.cs @@ -0,0 +1,82 @@ +using CsvHelper; +using CsvHelper.Configuration; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using Newtonsoft.Json; +using Serilog; +using System.Globalization; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; + +public class OsgDnaNoticeSplitIndexService : IndexParserService, IIndexParserService +{ + private readonly IFileOperationsApiService _fileOperationsApiService; + + public OsgDnaNoticeSplitIndexService(IFileOperationsApiService fileOperationsApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _fileOperationsApiService = fileOperationsApiService; + } + + public async Task HandleIndexRequest(IngestorRequest request) + { + Log.Debug("Starting HandleIndexRequest for OsgDnaNoticeSplitIndexService."); + var result = new IngestorResult(); + try + { + ArgumentNullException.ThrowIfNull(request); + var records = await GetFileContentAndParseRecords(request.FinalIndexFilePath); + result = PrepareRunInfoAndProcessRequests(request, records, result); + } + catch (Exception exception) + { + Log.Error(exception, "An Exception occured while HandleIndexRequest."); + result = new IngestorResult(true, exception.Message); + } + + Log.Debug("Ending HandleIndexRequest for OsgDnaNoticeSplitIndexService."); + return result; + } + + public async Task> GetFileContentAndParseRecords(string finalIndexFilePath) + { + var indexFileContent = await _fileOperationsApiService.GetFileContent(finalIndexFilePath); + using var stringReader = new StringReader(indexFileContent); + var config = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = "|", HasHeaderRecord = false }; + using var csv = new CsvReader(stringReader, config); + var csvRecords = csv.GetRecords(); + return csvRecords.ToList(); + } + + public IngestorResult PrepareRunInfoAndProcessRequests(IngestorRequest request, + List documentMetaData, + IngestorResult result) + { + result.IngestorRunInfo = new IngestorRunInfo(Guid.NewGuid(), + DateTime.Now, + request.IngestorType, + request.RootPath, + request.IndexFileName, + documentMetaData.Count()); + result.ProcessingRequests = new List(); + + foreach (var record in documentMetaData) + { + var processingRequest = new ProcessingRequest() + { + IngestorRunInfoId = result.IngestorRunInfo.IngestorRunInfoId, + IngestorRequest = request, + DocumentFileName = record.PdfName, + DocumentValuePayload = JsonConvert.SerializeObject(record), + DocumentTypeDisplayName = record.NoticeId + }; + result.ProcessingRequests.Add(processingRequest); + } + + return result; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgDnaNoticesIndexService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgDnaNoticesIndexService.cs new file mode 100644 index 0000000..4906a80 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgDnaNoticesIndexService.cs @@ -0,0 +1,94 @@ +using CsvHelper; +using CsvHelper.Configuration; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using Newtonsoft.Json; +using Serilog; +using System.Globalization; +using System.Text.RegularExpressions; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestor.Services.IndexParserServices +{ + public class OsgDnaNoticesIndexService : IndexParserService, IPdfIndexParserService + { + private readonly IFileOperationsApiService _fileOperationsApiService; + public OsgDnaNoticesIndexService(IFileOperationsApiService fileOperationsApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _fileOperationsApiService = fileOperationsApiService; + } + + public async Task> GetFileContentAndParseRecords(string finalIndexFilePath) + { + var indexFileContent = await _fileOperationsApiService.GetFileContent(finalIndexFilePath); + using var stringReader = new StringReader(indexFileContent); + var config = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = "|", HasHeaderRecord = false }; + using var csv = new CsvReader(stringReader, config); + return csv.GetRecords().ToList(); + } + + public async Task HandleIndexRequest(IngestorRequest request) + { + Log.Debug("Starting HandleIndexRequest for OsgDnaNotices."); + var result = new IngestorResult(); + try + { + ArgumentNullException.ThrowIfNull(request); + var records = await GetFileContentAndParseRecords(request.FinalIndexFilePath); + result = PrepareRunInfoAndProcessRequests(request, records, result); + } + catch (Exception exception) + { + Log.Error(exception, "An Exception occured while HandleIndexRequest."); + result = new IngestorResult(true, exception.Message); + } + + Log.Debug("Ending HandleIndexRequest for OsgDnaNotices."); + return result; + } + + public IngestorResult PrepareRunInfoAndProcessRequests(IngestorRequest request, List records, IngestorResult result) + { + result.IngestorRunInfo = new IngestorRunInfo(Guid.NewGuid(), + DateTime.Now, + request.IngestorType, + request.RootPath, + request.IndexFileName, + records.Count()); + result.ProcessingRequests = new List(); + + foreach (var record in records) + { + var parsedPdfName = CreateParsedPdfName(record); + var processingRequest = new ProcessingRequest() + { + IngestorRunInfoId = result.IngestorRunInfo.IngestorRunInfoId, + IngestorRequest = request, + DocumentFileName = parsedPdfName, + DocumentValuePayload = JsonConvert.SerializeObject(record), + DocumentTypeDisplayName = record.DocType + }; + result.ProcessingRequests.Add(processingRequest); + } + + return result; + } + + public string CreateParsedPdfName(T record) + { + if (record is not OsgDnaNoticesDocument osgDnaNoticesDocument) + { + throw new Exception("Record is not a OsgDnaNoticesDocument"); + } + + var entityId = Regex.Replace(osgDnaNoticesDocument.MemberNumberOrUserId, "[^A-Za-z0-9 -]", ""); + var accountNumber = string.IsNullOrWhiteSpace(osgDnaNoticesDocument.AccountNumber) ? "0" : osgDnaNoticesDocument.AccountNumber; + var parsedPdfName = $"{accountNumber}_{entityId}_{osgDnaNoticesDocument.DocType}_{osgDnaNoticesDocument.StartingPage}.pdf"; + return parsedPdfName; + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgHistoricalDocumentIndexService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgHistoricalDocumentIndexService.cs new file mode 100644 index 0000000..78d9b52 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgHistoricalDocumentIndexService.cs @@ -0,0 +1,94 @@ +using CsvHelper; +using CsvHelper.Configuration; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using Newtonsoft.Json; +using Serilog; +using System.Globalization; +using System.Text.RegularExpressions; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestor.Services.IndexParserServices +{ + public class OsgHistoricalDocumentIndexService : IndexParserService, IPdfIndexParserService + { + private readonly IFileOperationsApiService _fileOperationsApiService; + public OsgHistoricalDocumentIndexService(IFileOperationsApiService fileOperationsApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _fileOperationsApiService = fileOperationsApiService; + } + + public async Task> GetFileContentAndParseRecords(string finalIndexFilePath) + { + var indexFileContent = await _fileOperationsApiService.GetFileContent(finalIndexFilePath); + using var stringReader = new StringReader(indexFileContent); + var config = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = "|", HasHeaderRecord = false }; + using var csv = new CsvReader(stringReader, config); + return csv.GetRecords().ToList(); + } + + public async Task HandleIndexRequest(IngestorRequest request) + { + Log.Debug("Starting HandleIndexRequest for OsgHistoricalDocument."); + var result = new IngestorResult(); + try + { + ArgumentNullException.ThrowIfNull(request); + var records = await GetFileContentAndParseRecords(request.FinalIndexFilePath); + result = PrepareRunInfoAndProcessRequests(request, records, result); + } + catch (Exception exception) + { + Log.Error(exception, "An Exception occured while HandleIndexRequest."); + result = new IngestorResult(true, exception.Message); + } + + Log.Debug("Ending HandleIndexRequest for OsgHistoricalDocument."); + return result; + } + + public IngestorResult PrepareRunInfoAndProcessRequests(IngestorRequest request, List records, IngestorResult result) + { + result.IngestorRunInfo = new IngestorRunInfo(Guid.NewGuid(), + DateTime.Now, + request.IngestorType, + request.RootPath, + request.IndexFileName, + records.Count()); + result.ProcessingRequests = new List(); + + foreach (var record in records) + { + var parsedPdfName = CreateParsedPdfName(record); + var processingRequest = new ProcessingRequest() + { + IngestorRunInfoId = result.IngestorRunInfo.IngestorRunInfoId, + IngestorRequest = request, + DocumentFileName = parsedPdfName, + DocumentValuePayload = JsonConvert.SerializeObject(record), + DocumentTypeDisplayName = record.DocType + }; + result.ProcessingRequests.Add(processingRequest); + } + + return result; + } + + public string CreateParsedPdfName(T record) + { + if (record is not OsgHistoricalDocument osgHistoricalDocument) + { + throw new Exception("Record is not a OsgHistoricalDocument"); + } + + var entityId = Regex.Replace(osgHistoricalDocument.MemberNumberOrUserId, "[^A-Za-z0-9 -]", ""); + var entityName = Regex.Replace(osgHistoricalDocument.EntityName, "[^A-Za-z0-9 -]", ""); + var parsedPdfName = $"{entityName}_{entityId}_{osgHistoricalDocument.DocType}_{osgHistoricalDocument.StartingPage}.pdf"; + return parsedPdfName; + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgTaxStatementIndexService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgTaxStatementIndexService.cs new file mode 100644 index 0000000..def8646 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgTaxStatementIndexService.cs @@ -0,0 +1,82 @@ +using CsvHelper; +using CsvHelper.Configuration; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using Newtonsoft.Json; +using Serilog; +using System.Globalization; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; + +public class OsgTaxStatementIndexService : IndexParserService, IIndexParserService +{ + private readonly IFileOperationsApiService _fileOperationsApiService; + + public OsgTaxStatementIndexService(IFileOperationsApiService fileOperationsApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _fileOperationsApiService = fileOperationsApiService; + } + + public async Task HandleIndexRequest(IngestorRequest request) + { + Log.Debug("Starting HandleIndexRequest for OsgTaxStatement."); + var result = new IngestorResult(); + try + { + ArgumentNullException.ThrowIfNull(request); + var records = await GetFileContentAndParseRecords(request.FinalIndexFilePath); + result = PrepareRunInfoAndProcessRequests(request, records, result); + } + catch (Exception exception) + { + Log.Error(exception, "An Exception occured while HandleTaxStatementRequest."); + result = new IngestorResult(true, exception.Message); + } + + Log.Debug("Ending HandleIndexRequest for OsgTaxStatement."); + return result; + } + + public async Task> GetFileContentAndParseRecords(string finalIndexFilePath) + { + var indexFileContent = await _fileOperationsApiService.GetFileContent(finalIndexFilePath); + using var stringReader = new StringReader(indexFileContent); + var config = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = "|", HasHeaderRecord = false }; + using var csv = new CsvReader(stringReader, config); + var csvRecords = csv.GetRecords(); + return csvRecords.ToList(); + } + + public IngestorResult PrepareRunInfoAndProcessRequests(IngestorRequest request, + List documentMetaData, + IngestorResult result) + { + result.IngestorRunInfo = new IngestorRunInfo(Guid.NewGuid(), + DateTime.Now, + request.IngestorType, + request.RootPath, + request.IndexFileName, + documentMetaData.Count()); + result.ProcessingRequests = new List(); + + foreach (var record in documentMetaData) + { + var processingRequest = new ProcessingRequest() + { + IngestorRunInfoId = result.IngestorRunInfo.IngestorRunInfoId, + IngestorRequest = request, + DocumentFileName = record.PdfName, + DocumentValuePayload = JsonConvert.SerializeObject(record), + DocumentTypeDisplayName = record.NoticeName + }; + result.ProcessingRequests.Add(processingRequest); + } + + return result; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgTemenosNoticeIndexService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgTemenosNoticeIndexService.cs new file mode 100644 index 0000000..a400c9b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgTemenosNoticeIndexService.cs @@ -0,0 +1,80 @@ +using System.Globalization; +using Newtonsoft.Json; +using Serilog; +using CsvHelper.Configuration; +using CsvHelper; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; + +public class OsgTemenosNoticeDocumentIndexService : IndexParserService, IIndexParserService +{ + + private readonly IFileOperationsApiService _fileOperationsApiService; + + public OsgTemenosNoticeDocumentIndexService(IFileOperationsApiService fileOperationsApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _fileOperationsApiService = fileOperationsApiService; + } + + public async Task HandleIndexRequest(IngestorRequest request) + { + Log.Debug("Starting HandleIndexRequest for OsgTemenosNoticeRequest."); + var result = new IngestorResult(); + try + { + ArgumentNullException.ThrowIfNull(request); + var records = await GetFileContentAndParseRecords(request.FinalIndexFilePath); + result = PrepareRunInfoAndProcessRequests(request, records, result); + } + catch (Exception exception) + { + Log.Error(exception, "An Exception occured while handling OsgTemenosNoticeRequest."); + result = new IngestorResult(true, exception.Message); + } + + Log.Debug("Ending HandleIndexRequest for OsgTemenosNoticeRequest."); + return result; + } + + public async Task> GetFileContentAndParseRecords(string finalIndexFilePath) + { + var indexFileContent = await _fileOperationsApiService.GetFileContent(finalIndexFilePath); + using var stringReader = new StringReader(indexFileContent); + var config = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = "|", HasHeaderRecord = false }; + using var csv = new CsvReader(stringReader, config); + return csv.GetRecords().ToList(); + } + + private static IngestorResult PrepareRunInfoAndProcessRequests(IngestorRequest request, + IReadOnlyCollection documentMetaData, + IngestorResult result) + { + result.IngestorRunInfo = new IngestorRunInfo(Guid.NewGuid(), + DateTime.Now, + request.IngestorType, + request.RootPath, + request.IndexFileName, + documentMetaData.Count); + + result.ProcessingRequests = new List(); + + foreach (var processingRequest in documentMetaData.Select(record => new ProcessingRequest + { + IngestorRunInfoId = result.IngestorRunInfo.IngestorRunInfoId, + IngestorRequest = request, + DocumentFileName = record.PDF, + DocumentValuePayload = JsonConvert.SerializeObject(record), + DocumentTypeDisplayName = record.DocumentType + })){ + result.ProcessingRequests.Add(processingRequest); + } + return result; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgVehicleTaxStatementIndexService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgVehicleTaxStatementIndexService.cs new file mode 100644 index 0000000..3b95ac3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgVehicleTaxStatementIndexService.cs @@ -0,0 +1,82 @@ +using CsvHelper; +using CsvHelper.Configuration; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using Newtonsoft.Json; +using Serilog; +using System.Globalization; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; + +public class OsgVehicleTaxStatementIndexService : IndexParserService, IIndexParserService +{ + private readonly IFileOperationsApiService _fileOperationsApiService; + + public OsgVehicleTaxStatementIndexService(IFileOperationsApiService fileOperationsApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _fileOperationsApiService = fileOperationsApiService; + } + + public async Task HandleIndexRequest(IngestorRequest request) + { + Log.Debug("Starting HandleIndexRequest for OsgTaxStatement."); + var result = new IngestorResult(); + try + { + ArgumentNullException.ThrowIfNull(request); + var records = await GetFileContentAndParseRecords(request.FinalIndexFilePath); + result = PrepareRunInfoAndProcessRequests(request, records, result); + } + catch (Exception exception) + { + Log.Error(exception, "An Exception occured while HandleTaxStatementRequest."); + result = new IngestorResult(true, exception.Message); + } + + Log.Debug("Ending HandleIndexRequest for OsgTaxStatement."); + return result; + } + + public async Task> GetFileContentAndParseRecords(string finalIndexFilePath) + { + var indexFileContent = await _fileOperationsApiService.GetFileContent(finalIndexFilePath); + using var stringReader = new StringReader(indexFileContent); + var config = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = "|", HasHeaderRecord = false }; + using var csv = new CsvReader(stringReader, config); + var csvRecords = csv.GetRecords(); + return csvRecords.ToList(); + } + + public IngestorResult PrepareRunInfoAndProcessRequests(IngestorRequest request, + List documentMetaData, + IngestorResult result) + { + result.IngestorRunInfo = new IngestorRunInfo(Guid.NewGuid(), + DateTime.Now, + request.IngestorType, + request.RootPath, + request.IndexFileName, + documentMetaData.Count()); + result.ProcessingRequests = new List(); + + foreach (var record in documentMetaData) + { + var processingRequest = new ProcessingRequest() + { + IngestorRunInfoId = result.IngestorRunInfo.IngestorRunInfoId, + IngestorRequest = request, + DocumentFileName = record.PdfName, + DocumentValuePayload = JsonConvert.SerializeObject(record), + DocumentTypeDisplayName = record.NoticeId + }; + result.ProcessingRequests.Add(processingRequest); + } + + return result; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgWeilandStatementIndexService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgWeilandStatementIndexService.cs new file mode 100644 index 0000000..cac013a --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/OsgWeilandStatementIndexService.cs @@ -0,0 +1,79 @@ +using CsvHelper; +using CsvHelper.Configuration; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using Newtonsoft.Json; +using Serilog; +using System.Globalization; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestor.Services.IndexParserServices +{ + public class OsgWeilandStatementIndexService : IndexParserService, IIndexParserService + { + private readonly IFileOperationsApiService _fileOperationsApiService; + public OsgWeilandStatementIndexService(IFileOperationsApiService fileOperationsApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _fileOperationsApiService = fileOperationsApiService; + } + + public async Task> GetFileContentAndParseRecords(string finalIndexFilePath) + { + var indexFileContent = await _fileOperationsApiService.GetFileContent(finalIndexFilePath); + using var stringReader = new StringReader(indexFileContent); + var config = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = ",", HasHeaderRecord = true }; + using var csv = new CsvReader(stringReader, config); + return csv.GetRecords().ToList(); + } + + public async Task HandleIndexRequest(IngestorRequest request) + { + Log.Debug("Starting HandleIndexRequest for OsgWeilandDocument."); + var result = new IngestorResult(); + try + { + ArgumentNullException.ThrowIfNull(request); + var records = await GetFileContentAndParseRecords(request.FinalIndexFilePath); + result = PrepareRunInfoAndProcessRequests(request, records, result); + } + catch (Exception exception) + { + Log.Error(exception, "An Exception occured while HandleIndexRequest."); + result = new IngestorResult(true, exception.Message); + } + + Log.Debug("Ending HandleIndexRequest for OsgWeilandDocument."); + return result; + } + + public IngestorResult PrepareRunInfoAndProcessRequests(IngestorRequest request, List records, IngestorResult result) + { + result.IngestorRunInfo = new IngestorRunInfo(Guid.NewGuid(), + DateTime.Now, + request.IngestorType, + request.RootPath, + request.IndexFileName, + records.Count()); + result.ProcessingRequests = new List(); + + foreach (var record in records) + { + var processingRequest = new ProcessingRequest() + { + IngestorRunInfoId = result.IngestorRunInfo.IngestorRunInfoId, + IngestorRequest = request, + DocumentFileName = record.PdfName, + DocumentValuePayload = JsonConvert.SerializeObject(record), + DocumentTypeDisplayName = record.DocCode + }; + result.ProcessingRequests.Add(processingRequest); + } + + return result; + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/XdiActionNoticeDocumentIndexService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/XdiActionNoticeDocumentIndexService.cs new file mode 100644 index 0000000..51ab3fb --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/XdiActionNoticeDocumentIndexService.cs @@ -0,0 +1,81 @@ +using System.Globalization; +using Newtonsoft.Json; +using Serilog; +using CsvHelper.Configuration; +using CsvHelper; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; + +public class XdiActionNoticeDocumentIndexService : IndexParserService, IIndexParserService +{ + + private readonly IFileOperationsApiService _fileOperationsApiService; + + public XdiActionNoticeDocumentIndexService(IFileOperationsApiService fileOperationsApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _fileOperationsApiService = fileOperationsApiService; + } + + public async Task HandleIndexRequest(IngestorRequest request) + { + Log.Debug("Starting HandleIndexRequest for XdiActionNoticeDocumentRequest."); + var result = new IngestorResult(); + try + { + ArgumentNullException.ThrowIfNull(request); + var records = await GetFileContentAndParseRecords(request.FinalIndexFilePath); + result = PrepareRunInfoAndProcessRequests(request, records, result); + } + catch (Exception exception) + { + Log.Error(exception, "An Exception occured while handling XdiActionNoticeDocumentRequest."); + result = new IngestorResult(true, exception.Message); + } + + Log.Debug("Ending HandleIndexRequest for XdiActionNoticeDocumentRequest."); + return result; + } + + public async Task> GetFileContentAndParseRecords(string finalIndexFilePath) + { + var indexFileContent = await _fileOperationsApiService.GetFileContent(finalIndexFilePath); + using var stringReader = new StringReader(indexFileContent); + var config = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = "|", HasHeaderRecord = false }; + using var csv = new CsvReader(stringReader, config); + return csv.GetRecords().ToList(); + } + + private static IngestorResult PrepareRunInfoAndProcessRequests(IngestorRequest request, + IReadOnlyCollection documentMetaData, + IngestorResult result) + { + result.IngestorRunInfo = new IngestorRunInfo(Guid.NewGuid(), + DateTime.Now, + request.IngestorType, + request.RootPath, + request.IndexFileName, + documentMetaData.Count); + + result.ProcessingRequests = new List(); + + foreach (var processingRequest in documentMetaData.Select(record => new ProcessingRequest + { + IngestorRunInfoId = result.IngestorRunInfo.IngestorRunInfoId, + IngestorRequest = request, + DocumentFileName = record.DocumentName, + DocumentValuePayload = JsonConvert.SerializeObject(record), + DocumentTypeDisplayName = record.DocumentType + })) + { + result.ProcessingRequests.Add(processingRequest); + } + return result; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/XdiDnaNoticeDocumentIndexService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/XdiDnaNoticeDocumentIndexService.cs new file mode 100644 index 0000000..c29fe29 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IndexParserServices/XdiDnaNoticeDocumentIndexService.cs @@ -0,0 +1,80 @@ +using System.Globalization; +using Newtonsoft.Json; +using Serilog; +using CsvHelper.Configuration; +using CsvHelper; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; + +public class XdiDnaNoticeDocumentIndexService : IndexParserService, IIndexParserService +{ + + private readonly IFileOperationsApiService _fileOperationsApiService; + + public XdiDnaNoticeDocumentIndexService(IFileOperationsApiService fileOperationsApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _fileOperationsApiService = fileOperationsApiService; + } + + public async Task HandleIndexRequest(IngestorRequest request) + { + Log.Debug("Starting HandleIndexRequest for XdiDnaNoticeDocumentRequest."); + var result = new IngestorResult(); + try + { + ArgumentNullException.ThrowIfNull(request); + var records = await GetFileContentAndParseRecords(request.FinalIndexFilePath); + result = PrepareRunInfoAndProcessRequests(request, records, result); + } + catch (Exception exception) + { + Log.Error(exception, "An Exception occured while handling XdiDnaNoticeDocumentRequest."); + result = new IngestorResult(true, exception.Message); + } + + Log.Debug("Ending HandleIndexRequest for XdiDnaNoticeDocumentRequest."); + return result; + } + + public async Task> GetFileContentAndParseRecords(string finalIndexFilePath) + { + var indexFileContent = await _fileOperationsApiService.GetFileContent(finalIndexFilePath); + using var stringReader = new StringReader(indexFileContent); + var config = new CsvConfiguration(CultureInfo.InvariantCulture) { Delimiter = "|", HasHeaderRecord = false }; + using var csv = new CsvReader(stringReader, config); + return csv.GetRecords().ToList(); + } + + private static IngestorResult PrepareRunInfoAndProcessRequests(IngestorRequest request, + IReadOnlyCollection documentMetaData, + IngestorResult result) + { + result.IngestorRunInfo = new IngestorRunInfo(Guid.NewGuid(), + DateTime.Now, + request.IngestorType, + request.RootPath, + request.IndexFileName, + documentMetaData.Count); + + result.ProcessingRequests = new List(); + + foreach (var processingRequest in documentMetaData.Select(record => new ProcessingRequest + { + IngestorRunInfoId = result.IngestorRunInfo.IngestorRunInfoId, + IngestorRequest = request, + DocumentFileName = record.PDF, + DocumentValuePayload = JsonConvert.SerializeObject(record), + DocumentTypeDisplayName = record.DocumentType + })){ + result.ProcessingRequests.Add(processingRequest); + } + return result; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/BatchIngestionService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/BatchIngestionService.cs new file mode 100644 index 0000000..0da1133 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/BatchIngestionService.cs @@ -0,0 +1,199 @@ +using Serilog; +using TimeZoneConverter; +using LCU.Library.Internal.ApiResponse.Services; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Api.Internal.DispatcherSharedLib.BuilderServices; +using LCU.Library.Internal.DispatcherModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.Library.Internal.DispatcherModels.Enums; +using LCU.Library.Internal.FileOperationsModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public class BatchIngestionService : IBatchIngestionService +{ + public delegate void AddWorkItem(IngestorRequest request, WorkItemDetails workItemDetails); + public delegate AddWorkItem AddIngestorRequestWorkItemStrategy(IRequestBuilderService builder); + + private readonly ApiConfiguration _apiConfiguration; + private readonly DispatcherJobCreationConfiguration _dispatcherJobCreationConfiguration; + private readonly IFileOperationsApiService _fileOperationsApiService; + private readonly IRequestBuilderService _dispatcherRequestBuilder; + + private const string JobRequestingApplication = "Document Ingestor Api"; + private const string JobName = "Document Ingestor - {IngestorType}"; + private const string JobDescription = "This is an Single-Use job that has been created by Document Ingestor Api. After successfully processed it will no longer be needed."; + private const string ArchivedDirectory = "Archived"; + private const string CreateArchivedWorkItemName = "Create Archived Directory"; + private const string CreateArchivedWorkItemDescription = "Full Path: {Path}"; + private const string CreateIngestorRequestWorkItemName = "Ingestor Request"; + private const string CreateIngestorRequestWorkItemDescription = "IngestorType: {IngestorType}"; + + public BatchIngestionService + ( + ApiConfiguration apiConfiguration, + DispatcherJobCreationConfiguration dispatcherJobCreationConfiguration, + IFileOperationsApiService fileOperationsApiService, + IRequestBuilderService dispatcherRequestBuilder + ) + { + _apiConfiguration = apiConfiguration; + _dispatcherJobCreationConfiguration = dispatcherJobCreationConfiguration; + _fileOperationsApiService = fileOperationsApiService; + _dispatcherRequestBuilder = dispatcherRequestBuilder; + } + + public async Task HandleBatchIngestion(BatchIngestionRequest request) + { + try + { + ArgumentNullException.ThrowIfNull(request); + var dynamicDirectoryListRequest = new DynamicDirectoryListRequest + { + Path = request.FinalRootBasePath, + DynamicDirectoryName = request.ParentDynamicDirectory, + DynamicFileSettings = request.ParentDynamicDirectorySettings + }; + var dynamicDirectories = await _fileOperationsApiService.BuildDynamicDirectoryList(dynamicDirectoryListRequest); + + var batchIngestionResult = new BatchIngestionResult(); + foreach (var directory in dynamicDirectories) + { + batchIngestionResult = await CreateAndSendDispatcherRequest(request, directory, batchIngestionResult); + } + + if (batchIngestionResult.IsFailure) + { + var message = $"There were {batchIngestionResult.FailureCount} Ingestor Requests that failed to be created."; + batchIngestionResult.Messages.Add(message); + } + + await QueueReturnResponse.QueueResponse(request, batchIngestionResult.IsSuccessfull, batchIngestionResult.Messages); + } + catch (ArgumentNullException) + { + throw; + } + catch (Exception exception) + { + const string errorMessage = "Failure during document ingestion."; + var errorMessageWithException = $"{errorMessage} Exception Message: {exception.Message}"; + Log.Error(exception, errorMessage); + await QueueReturnResponse.QueueResponse(request, false, new List { errorMessageWithException }); + throw new ServiceException(errorMessageWithException); + } + } + + public async Task CreateAndSendDispatcherRequest(BatchIngestionRequest request, + string directory, + BatchIngestionResult batchIngestionResult) + { + try + { + SetupJobDetails(request); + var ingestionRootPath = DetermineIngestionRootPath(request, directory); + SetupCreateArchivedDirectoryWorkItem(ingestionRootPath); + await SetupCreateIngestorRequestWorkItem(request, ingestionRootPath); + + var successful = _dispatcherRequestBuilder.SendDispatcherRequest(); + if (!successful) + { + throw new Exception("Failure to send dispatcher request."); + } + } + catch (Exception exception) + { + batchIngestionResult.AddToFailureCount(exception.Message); + } + + return batchIngestionResult; + } + + public void SetupJobDetails(BatchIngestionRequest request) + { + var timeZone = TZConvert.GetTimeZoneInfo(_apiConfiguration.TimeZone); + var dateNow = TimeZoneInfo.ConvertTime(DateTime.Now, timeZone); + var jobDetails = new JobDetails + { + RequestingApplication = JobRequestingApplication, + Name = JobName.Replace("{IngestorType}", request.IngestorType.ToString()), + Description = JobDescription, + CreatedBy = JobRequestingApplication, + CreatedAt = dateNow, + NextRunTime = dateNow, + ErrorRecipients = _dispatcherJobCreationConfiguration.DocumentIngestorDispatcherErrorRecipients, + JobTags = _dispatcherJobCreationConfiguration.JobTags, + JobStatus = JobStatus.ReadyToSchedule + }; + _dispatcherRequestBuilder.CreateJob(jobDetails); + } + + public string DetermineIngestionRootPath(BatchIngestionRequest request, string directory) + { + var subDirectoryPath = request.SubDirectoryPath.EndsWith("\\") || string.IsNullOrWhiteSpace(request.SubDirectoryPath) ? + request.SubDirectoryPath : + $"{request.SubDirectoryPath}\\"; + var formattedDirectory = directory.EndsWith("\\") ? directory : $"{directory}\\"; + var ingestionRootPath = request.FinalRootBasePath + formattedDirectory + subDirectoryPath; + return ingestionRootPath; + } + + private void SetupCreateArchivedDirectoryWorkItem(string ingestionRootPath) + { + var createDirectoryRequest = new CreateDirectoryRequest + { + DirectoryName = ArchivedDirectory, + DirectoryPath = ingestionRootPath + }; + var createDirectoryWorkItemDetails = new WorkItemDetails + { + Name = CreateArchivedWorkItemName, + Description = CreateArchivedWorkItemDescription.Replace("{Path}", ingestionRootPath + ArchivedDirectory), + Order = 1 + }; + _dispatcherRequestBuilder.AddWorkItem(createDirectoryRequest, createDirectoryWorkItemDetails, ActionType.CreateDirectory); + } + + private async Task SetupCreateIngestorRequestWorkItem(BatchIngestionRequest request, string ingestionRootPath) + { + var indexFile = await DetermineIndexFile(request, ingestionRootPath); + var ingestorRequest = new IngestorRequest + { + IngestorType = request.IngestorType, + RootPath = ingestionRootPath, + IndexFileName = indexFile + }; + var ingestorWorkItemDetails = new WorkItemDetails + { + Name = CreateIngestorRequestWorkItemName, + Description = CreateIngestorRequestWorkItemDescription.Replace("{IngestorType}", ingestorRequest.IngestorType.ToString()), + Order = 2 + }; + + ActionType ingestionType; + + if ((!_apiConfiguration.IsHistoric)) + { + ingestionType = ActionType.DocumentIngestor; + } + else + { + ingestionType = ActionType.HistoricalDocumentIngestor; + } + + _dispatcherRequestBuilder.AddWorkItem(ingestorRequest, ingestorWorkItemDetails, ingestionType); + } + + public async Task DetermineIndexFile(BatchIngestionRequest request, string directory) + { + var dynamicFileListRequest = new DynamicFileListRequest + { + Path = directory, + Filename = request.DynamicIndexFileName, + DynamicFileSettings = request.DynamicFileSettings + }; + + return await _fileOperationsApiService.BuildDynamicFile(dynamicFileListRequest); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/BatchUpdateMemberNotificationDataService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/BatchUpdateMemberNotificationDataService.cs new file mode 100644 index 0000000..cd92be1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/BatchUpdateMemberNotificationDataService.cs @@ -0,0 +1,126 @@ +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.QueueResult; +using LCU.Library.Internal.Exceptions; +using MassTransit; +using Serilog; +using System.Data.SqlClient; + +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public class BatchUpdateMemberNotificationDataService : IBatchUpdateMemberNotificationDataService +{ + public readonly IMemberNotificationInfoService _memberNotificationInfoService; + public readonly IQueueCompletionService _queueCompletionService; + public readonly ApiConfiguration _apiConfiguration; + public BatchUpdateMemberNotificationDataService(IMemberNotificationInfoService memberNotificationInfoService, + IQueueCompletionService queueCompletionService, + ApiConfiguration apiConfiguration) + { + _memberNotificationInfoService = memberNotificationInfoService; + _queueCompletionService = queueCompletionService; + _apiConfiguration = apiConfiguration; + } + + public async Task HandleBatchUpdateMemberNotificationData(List requests) + { + try + { + ArgumentNullException.ThrowIfNull(requests); + + var completedBatchUpdateMemberNotificationDataRequests = await SaveBatchMemberNotificationInfos(requests); + + foreach(var request in requests) + { + if (request.GatherMemberNotificationInfoRequest.CompletionRequest.ProcessResult.ProcessStatusType == ProcessStatusTypes.Processing) + { + ProcessResult.ProcessCompleted(request.GatherMemberNotificationInfoRequest.CompletionRequest.ProcessResult, null); + } + } + + await QueueCompletionRequests(completedBatchUpdateMemberNotificationDataRequests); + } + catch (ServiceException serviceException) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error(serviceException, $"Batch Update Member Notification Failure. " + + $"The List is placed on LCU.DocumentIngestor.BatchUpdateMemberNotification_error."); + throw; + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, $"Unexpected Batch Update Member Notification Failure. " + + $"The List is placed on LCU.DocumentIngestor.BatchUpdateMemberNotification_error."); + throw; + } + } + + public async Task> SaveBatchMemberNotificationInfos(List requests) + { + try + { + await _memberNotificationInfoService.SaveListAsync(requests.SelectMany(r => r.MemberNotificationInfos).ToList()); + } + catch (SqlException ex) + { + Log.Error("Error during SaveBatchMemberNotificationInfos. ProcessResults are being set to CriticalFailure"); + foreach (var request in requests) + { + request.GatherMemberNotificationInfoRequest.CompletionRequest.ProcessResult = + ProcessResult.ProcessNotificationDataFailure(request.GatherMemberNotificationInfoRequest.CompletionRequest.ProcessResult, + "Failure during Batch save of MemberNotificationInfo"); + } + } + return requests; + } + + public async Task QueueCompletionRequests(List requests) + { + var tasks = requests.Select(r => QueueCompletionRequest(r.GatherMemberNotificationInfoRequest.CompletionRequest)); + + var results = await Task.WhenAll(tasks); + + var message = string.Join(Environment.NewLine, + results + .Where(r => !r.Success) + .Select(r => $"Failed to Queue Completion after BatchUpdateMemberNotification. " + + $"DocumentProcessingInfoId: {r.CompletionRequest.ProcessingRequest.DocumentProcessingInfoId}, " + + $"DocumentFileName: {r.CompletionRequest.ProcessingRequest.DocumentFileName}.")); + + if (!string.IsNullOrEmpty(message)) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error(new Exception(), message); + } + } + + public async Task QueueCompletionRequest(CompletionRequest request) + { + try + { + await _queueCompletionService.QueueCompletionRequest(request.ProcessingRequest, request.ProcessResult); + return new QueueCompletionResult + { + Success = true, + CompletionRequest = request + }; + } + catch (Exception ex) + { + var errorMessage = $"Exception during QueueCompletionRequest. ErrorMessage: {ex.Message}"; + Log.Warning(errorMessage); + return new QueueCompletionResult + { + Success = false, + CompletionRequest = request + }; + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/CompletionService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/CompletionService.cs new file mode 100644 index 0000000..d76d4eb --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/CompletionService.cs @@ -0,0 +1,159 @@ +using Dapper; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using MassTransit; +using Newtonsoft.Json; +using Serilog; +using Response = LCU.Library.Internal.ApiResponse.Models.Response; + +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public class CompletionService : ICompletionService +{ + private readonly IIngestorRunInfoService _ingestorRunInfoService; + private readonly IDocumentProcessingInfoService _documentProcessingInfoService; + private readonly IResponseQueue _responseQueue; + + public CompletionService + ( + IIngestorRunInfoService ingestorRunInfoService, + IDocumentProcessingInfoService documentProcessingInfoService, + IResponseQueue responseQueue + ) + { + _ingestorRunInfoService = ingestorRunInfoService; + _documentProcessingInfoService = documentProcessingInfoService; + _responseQueue = responseQueue; + } + + public async Task HandleCompletion(List responses) + { + try + { + ArgumentNullException.ThrowIfNull(responses); + var requests = DeserializeResponses(responses); + ArgumentNullException.ThrowIfNull(requests); + + await HandleMessagesAndUpdateDocumentProcessInfo(requests); + } + catch (ArgumentNullException) + { + throw; + } + catch (Exception exception) + { + throw new ServiceException($"Exception was thrown in HandleCompletion. " + + $"Exception Message: {exception.Message}"); + } + } + + public List DeserializeResponses(List responses) + { + var requests = new List(); + + foreach (var response in responses) + { + var request = JsonConvert.DeserializeObject(response.ResponsePayload); + if (response.ResponseStack != null) + { + request.ProcessResult.MessageStack.AddRange(response.ResponseStack); + } + requests.Add(request); + } + + return requests; + } + + private async Task HandleMessagesAndUpdateDocumentProcessInfo(List requests) + { + var completionProcessingDatas = await CreateAndFilterCompletionProcessingDatas(requests); + + var ingestorRunInfoGroups = completionProcessingDatas.GroupBy( + d => d.DocumentProcessingInfo.IngestorRunInfoId, + d => d, + (key, d) => new { IngestorRunInfoId = key, CompletionProcessingData = d.ToList() }); + var ingestorRunInfos = await GetAndFilterIngestorRunInfos(ingestorRunInfoGroups.Select(i => i.IngestorRunInfoId).ToList()); + + foreach (var ingestorRunInfoGroup in ingestorRunInfoGroups) + { + await ProcessRunInfos(ingestorRunInfoGroup.CompletionProcessingData, + ingestorRunInfos.Where(i => i.IngestorRunInfoId == ingestorRunInfoGroup.IngestorRunInfoId).FirstOrDefault()); + } + } + + public async Task> CreateAndFilterCompletionProcessingDatas(List requests) + { + var completionProcessingDatas = await _documentProcessingInfoService.UpdateProcessCountAndStatusAndAddLog(requests); + completionProcessingDatas.RemoveAll(d => d.DocumentProcessingInfo.ProcessCount > 1); + completionProcessingDatas.GroupBy(d => d.DocumentProcessingInfo.DocumentProcessingInfoId).Select(d => d.First()).ToList(); + return completionProcessingDatas; + } + + public async Task> GetAndFilterIngestorRunInfos(List ingestorRunInfoIds) + { + var ingestorRunInfos = await _ingestorRunInfoService.GetListByIdAsync(ingestorRunInfoIds); + ingestorRunInfos.AsList().RemoveAll(i => i.EndTimeStamp != null); + return ingestorRunInfos; + } + + public async Task ProcessRunInfos(List completionProcessingDatas, IngestorRunInfo runInfo) + { + if (runInfo == null) + { + return; + } + runInfo.IngestionRunCount += completionProcessingDatas.Count(); + if (runInfo.IngestionRunCount != runInfo.IndexTotal) + { + await _ingestorRunInfoService.Update(runInfo); + return; + } + runInfo.EndTimeStamp = DateTime.Now; + var documentProcessingInfosFromRunInfo = await _documentProcessingInfoService.GetCompletedFirstPassByIngestorRunInfoIdAsync(runInfo.IngestorRunInfoId); + await _ingestorRunInfoService.Update(runInfo); + await DetermineCountsAndQueueResponse(documentProcessingInfosFromRunInfo, completionProcessingDatas.FirstOrDefault().CompletionRequest, runInfo); + } + + private async Task DetermineCountsAndQueueResponse(IEnumerable documentProcessingInfos, CompletionRequest request, IngestorRunInfo ingestorRunInfo) + { + var successCount = documentProcessingInfos.Count(documentProcessingInfo => + documentProcessingInfo.StatusType == ProcessStatusTypes.Completed + ); + + var dataMappingFailureCount = documentProcessingInfos.Count(documentProcessingInfo => + documentProcessingInfo.StatusType == ProcessStatusTypes.DataMappingFailure + ); + + var criticalFailureCount = documentProcessingInfos.Count(documentProcessingInfo => + documentProcessingInfo.StatusType == ProcessStatusTypes.CriticalFailure + ); + + var archiveFailureCount = documentProcessingInfos.Count(documentProcessingInfo => + documentProcessingInfo.StatusType == ProcessStatusTypes.ArchiveFailure + ); + + var message = $"IngestorRunInfoId: {ingestorRunInfo.IngestorRunInfoId}, " + + $"Amount Ingested: {ingestorRunInfo.IndexTotal}, " + + $"Success Count: {successCount}, " + + $"Data Mapping Failure Count: {dataMappingFailureCount}, " + + $"Critical Failure Count: {criticalFailureCount}, " + + $"Archive Failure Count: {archiveFailureCount}"; + + if (criticalFailureCount + archiveFailureCount > 0) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error(new Exception(), $"CriticalFailure or ArchiveFailure found during completion. Dispatcher Job is being marked as successful. " + + $"Please Investigate failures.{Environment.NewLine}" + message); + } + + var messageStack = new List { message }; + Log.Information(message); + + await _responseQueue.Enqueue(request.ProcessingRequest.IngestorRequest, true, messageStack); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/DocumentProcessorService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/DocumentProcessorService.cs new file mode 100644 index 0000000..9ac4e9a --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/DocumentProcessorService.cs @@ -0,0 +1,148 @@ +using Serilog; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.API.Internal.DocumentIngestorLib.Exceptions; +using LCU.Library.Internal.LCUServiceFactory.Services; +using Newtonsoft.Json; + +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public class DocumentProcessorService : IDocumentProcessorService +{ + private ApiConfiguration _apiConfiguration; + private readonly IQueueDocumentProcessingService _queueDocumentProcessingService; + private readonly IQueueCompletionService _queueCompletionService; + private readonly IFileOperationsApiService _fileOperationsApiService; + private readonly ILcuServiceFactory _serviceFactory; + + public DocumentProcessorService(ApiConfiguration apiConfiguration, + IQueueDocumentProcessingService queueDocumentProcessingService, + IQueueCompletionService queueCompletionService, + IFileOperationsApiService fileOperationsApiService, + ILcuServiceFactory serviceFactory) + { + _apiConfiguration = apiConfiguration; + _queueDocumentProcessingService = queueDocumentProcessingService; + _queueCompletionService = queueCompletionService; + _fileOperationsApiService = fileOperationsApiService; + _serviceFactory = serviceFactory; + } + + public async Task HandleProcessing(ProcessingRequest request) + { + try + { + ArgumentNullException.ThrowIfNull(request); + var documentNeedsProcessing = await ValidateDocumentNeedsProcessing(request); + + if (!documentNeedsProcessing) + { + var skippedMessage = "Skipping: Document has already been processed and is archived."; + var processResult = ProcessResult.ProcessCompleted(new ProcessResult(), skippedMessage); + await _queueCompletionService.QueueCompletionRequest(request, processResult); + return; + } + + var result = await PerformDocumentProcess(request); + if (!result.Success) + { + await HandlePostProcessingFailure(request, result); + return; + } + + await ArchiveDocument(request); + } + catch (ArgumentNullException) + { + throw; + } + catch (ArchiveException) + { + throw; + } + catch (Exception exception) + { + var errorMessage = "Failure during document processing. " + + $"DocumentProcessingInfoId: {request.DocumentProcessingInfoId }, " + + $"IngestorRunInfoId:{request.IngestorRunInfoId}, " + + $"DocumentFileName: {request.DocumentFileName}, " + + $"Exception Message: {exception.Message}"; + var result = ProcessResult.ProcessCriticalFailure(new ProcessResult(), errorMessage); + await HandlePostProcessingFailure(request, result); + } + } + + private async Task ValidateDocumentNeedsProcessing(ProcessingRequest request) + { + var filePath = request.IngestorRequest.RootPath + request.DocumentFileName; + var archiveFilePath = $"{request.IngestorRequest.ArchivePath}" + + $"{request.DocumentFileName}"; + var documentNeedsProcessing = await _fileOperationsApiService.ValidateFileExistsAndNotArchived(filePath, archiveFilePath); + return documentNeedsProcessing; + } + + private async Task PerformDocumentProcess(ProcessingRequest request) + { + try + { + var service = _serviceFactory.GetService(request.IngestorRequest.IngestorType); + + if (service is null) + { + throw new NotImplementedException(); + } + + return await service.ProcessRequest(request); + } + catch (Exception exception) + { + return new ProcessResult(true, exception.Message); + } + } + + public async Task HandlePostProcessingFailure(ProcessingRequest request, ProcessResult result) + { + if (result.ProcessStatusType == ProcessStatusTypes.CriticalFailure && + request.RetryCount < _apiConfiguration.DocumentProcessingReQueueCountLimit) + { + request.RetryCount++; + Log.Warning("Processing Request ran into a Critical Failure Type and is being Re-Queued." + + $"ProcessingRequest: {JsonConvert.SerializeObject(request)}"); + await _queueDocumentProcessingService.QueueDocumentProcessingRequest(request); + return; + } + + if(request.RetryCount > 0) + { + result.MessageStack.Add($"Document attempted to retry processing {request.RetryCount} time(s)."); + } + + await _queueCompletionService.QueueCompletionRequest(request, result); + } + + private async Task ArchiveDocument(ProcessingRequest request) + { + try + { + var response = await _fileOperationsApiService.DirectMoveFile(request.IngestorRequest.RootPath, + request.DocumentFileName, + request.IngestorRequest.ArchivePath); + if (!response.IsSuccessful) + { + throw new Exception(string.Join("; ", response.MessageStack.ToArray())); + } + } + catch (Exception exception) + { + throw new ArchiveException("Failure to archive document. | " + + $"FileName: {request.DocumentFileName} | " + + $"RootPath: {request.IngestorRequest.RootPath} | " + + $"ArchivePath: {request.IngestorRequest.ArchivePath} | " + + $"Exception Message: {exception.Message}"); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/GatherMemberNotificationInfoService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/GatherMemberNotificationInfoService.cs new file mode 100644 index 0000000..fae3777 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/GatherMemberNotificationInfoService.cs @@ -0,0 +1,57 @@ +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.Services.MemberNotificationInfoDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public class GatherMemberNotificationInfoService : IGatherMemberNotificationInfoService +{ + private readonly IMemberNotificationInfoDeterminingService _memberNotificationInfoDeterminingService; + private readonly IQueueCompletionService _queueCompletionService; + private readonly IQueueBatchUpdateMemberNotificationDataService _queueBatchUpdateMemberNotificationDataService; + + public GatherMemberNotificationInfoService(IMemberNotificationInfoDeterminingService memberNotificationInfoDeterminingService, + IQueueCompletionService queueCompletionService, + IQueueBatchUpdateMemberNotificationDataService queueBatchUpdateMemberNotificationDataService) + { + _memberNotificationInfoDeterminingService = memberNotificationInfoDeterminingService; + _queueCompletionService = queueCompletionService; + _queueBatchUpdateMemberNotificationDataService = queueBatchUpdateMemberNotificationDataService; + } + + public async Task HandleMemberNotificationInfoGathering(GatherMemberNotificationInfoRequest request) + { + try + { + var memberNotificationInfos = await _memberNotificationInfoDeterminingService.HandleMemberNotificationInfos(request.CompletionRequest.MemberNotificationInfoRequest); + + if(!memberNotificationInfos.Any()) + { + if (request.CompletionRequest.ProcessResult.ProcessStatusType == ProcessStatusTypes.Processing) + { + ProcessResult.ProcessCompleted(request.CompletionRequest.ProcessResult, null); + } + + await _queueCompletionService.QueueCompletionRequest(request.CompletionRequest.ProcessingRequest, + request.CompletionRequest.ProcessResult); + return; + } + + await _queueBatchUpdateMemberNotificationDataService.QueueBatchUpdateMemberNotificationDataRequest( + new BatchUpdateMemberNotificationDataRequest( + memberNotificationInfos, + request)); + } + catch (Exception exception) + { + var message = $"Failure to gather and create member notification info."; + request.CompletionRequest.ProcessResult = ProcessResult.ProcessNotificationDataFailure(request.CompletionRequest.ProcessResult, $"{message}, Exception Message: {exception.Message}"); + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error(exception, message); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IBatchIngestionService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IBatchIngestionService.cs new file mode 100644 index 0000000..b15c3f8 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IBatchIngestionService.cs @@ -0,0 +1,9 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; + +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public interface IBatchIngestionService +{ + Task HandleBatchIngestion(BatchIngestionRequest request); + Task DetermineIndexFile(BatchIngestionRequest request, string directory); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IBatchUpdateMemberNotificationDataService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IBatchUpdateMemberNotificationDataService.cs new file mode 100644 index 0000000..2166e64 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IBatchUpdateMemberNotificationDataService.cs @@ -0,0 +1,8 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; + +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public interface IBatchUpdateMemberNotificationDataService +{ + Task HandleBatchUpdateMemberNotificationData(List requests); +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/ICompletionService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/ICompletionService.cs new file mode 100644 index 0000000..456d14c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/ICompletionService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.ApiResponse.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public interface ICompletionService +{ + Task HandleCompletion(List responses); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IDocumentProcessorService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IDocumentProcessorService.cs new file mode 100644 index 0000000..aa3c6eb --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IDocumentProcessorService.cs @@ -0,0 +1,8 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; + +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public interface IDocumentProcessorService +{ + Task HandleProcessing(ProcessingRequest request); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IGatherMemberNotificationInfoService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IGatherMemberNotificationInfoService.cs new file mode 100644 index 0000000..e4b507f --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IGatherMemberNotificationInfoService.cs @@ -0,0 +1,8 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; + +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public interface IGatherMemberNotificationInfoService +{ + Task HandleMemberNotificationInfoGathering(GatherMemberNotificationInfoRequest request); +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IIndexService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IIndexService.cs new file mode 100644 index 0000000..9a38fb5 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IIndexService.cs @@ -0,0 +1,8 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; + +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public interface IIndexService +{ + Task HandleIngestion(IngestorRequest request); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IIngestionFolderCleanUpService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IIngestionFolderCleanUpService.cs new file mode 100644 index 0000000..d022d2a --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IIngestionFolderCleanUpService.cs @@ -0,0 +1,8 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; + +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public interface IIngestionFolderCleanUpService +{ + Task HandleIngestionFolderCleanUp(IngestionFolderCleanUpRequest request); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IMemberDocumentNotifierService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IMemberDocumentNotifierService.cs new file mode 100644 index 0000000..38307ef --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IMemberDocumentNotifierService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public interface IMemberDocumentNotifierService +{ + Task HandleMemberDocumentNotification(MemberDocumentNotificationRequest request); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IMemberNotificationCompletionService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IMemberNotificationCompletionService.cs new file mode 100644 index 0000000..accfb1b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IMemberNotificationCompletionService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.ApiResponse.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public interface IMemberNotificationCompletionService +{ + Task HandleMemberNotificationCompletion(Response returnResponse); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IOsgPreprocessorService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IOsgPreprocessorService.cs new file mode 100644 index 0000000..073d3ad --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IOsgPreprocessorService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public interface IOsgPreprocessorService +{ + Task HandleOsgPreprocessing(OsgPreprocessorRequest request); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IPdfPartitionerCompletionService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IPdfPartitionerCompletionService.cs new file mode 100644 index 0000000..0d05f47 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IPdfPartitionerCompletionService.cs @@ -0,0 +1,8 @@ +using LCU.Library.Internal.ApiResponse.Models; + +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public interface IPdfPartitionerCompletionService +{ + Task HandlePdfPartitionerCompletion(Response response); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IPdfPartitionerService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IPdfPartitionerService.cs new file mode 100644 index 0000000..f9467bd --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IPdfPartitionerService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public interface IPdfPartitionerService +{ + Task HandlePdfPartition(PdfPartitionerRequest request); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IProcessStatusTypeEmailService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IProcessStatusTypeEmailService.cs new file mode 100644 index 0000000..87d6d1d --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IProcessStatusTypeEmailService.cs @@ -0,0 +1,11 @@ +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Requests; + +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices +{ + public interface IProcessStatusTypeEmailService + { + Task HandleProcessStatusTypeEmailRequest(ProcessStatusTypeEmailRequest request); + Task SendProcessStatusEmailAsync(IEnumerable listDocumentProcessingInfo, ProcessStatusTypeEmailRequest request); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IUploadCompletionService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IUploadCompletionService.cs new file mode 100644 index 0000000..b958d3e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IUploadCompletionService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.ApiResponse.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public interface IUploadCompletionService +{ + Task HandleUploadCompletion(List requests); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IndexService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IndexService.cs new file mode 100644 index 0000000..f873bf0 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IndexService.cs @@ -0,0 +1,177 @@ +using LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.Library.Internal.ApiResponse.Services; +using LCU.Library.Internal.DocumentIngestorModels.Constants; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.LCUServiceFactory.Services; +using Serilog; +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public class IndexService : IIndexService +{ + private readonly IQueueDocumentProcessingService _queueDocumentProcessing; + private readonly IIngestorRunInfoService _ingestorRunInfoService; + private readonly IDocumentProcessingInfoService _documentProcessingInfoService; + private readonly IDocumentTypeRetrieverService _documentTypeRetrieverService; + private readonly ILcuServiceFactory _serviceFactory; + + public IndexService(IQueueDocumentProcessingService queueDocumentProcessing, + IIngestorRunInfoService ingestorRunInfoService, + IDocumentProcessingInfoService documentProcessingInfoService, + IDocumentTypeRetrieverService documentTypeRetrieverService, + ILcuServiceFactory serviceFactory) + { + _queueDocumentProcessing = queueDocumentProcessing; + _ingestorRunInfoService = ingestorRunInfoService; + _documentProcessingInfoService = documentProcessingInfoService; + _documentTypeRetrieverService = documentTypeRetrieverService; + _serviceFactory = serviceFactory; + } + + public async Task HandleIngestion(IngestorRequest request) + { + try + { + ArgumentNullException.ThrowIfNull(request); + var result = await PerformIngestor(request); + if (result.FatalFailure) + { + var errorMessage = string.Join("; ", result.MessageStack.ToArray()); + throw new Exception($"Fatal Failure occured. Error Message: {errorMessage}"); + } + + await SendProcessRequest(result); + } + catch (ArgumentNullException) + { + throw; + } + catch (Exception exception) + { + const string errorMessage = "Failure during document ingestion."; + var errorMessageWithException = $"{errorMessage} Exception Message: {exception.Message}"; + Log.Error(exception, errorMessage); + await QueueReturnResponse.QueueResponse(request, false, new List { errorMessageWithException }); + throw new ServiceException(errorMessageWithException); + } + } + + public async Task PerformIngestor(IngestorRequest request) + { + try + { + var service = _serviceFactory.GetService(request.IngestorType); + + if (service is null) + { + throw new NotImplementedException(); + } + + return await service.HandleIndexRequest(request); + } + catch (Exception exception) + { + return new IngestorResult(true, exception.Message); + } + } + + /// + /// This method is used to: + /// - Save IngestorRunInfo + /// - Create/Save DocumentProcessingInfo + /// - Queue for processing + /// + /// NOTE: If there are any failures to save to database this process should be stopped by exception and will be + /// caught, logged, maidbot will be used, and the IngestorRequest will be placed on the LCU.DocumentIngestor.Indexing_error. + /// + /// NOTE: If failure to queue an exception will be logged, DocumentProcessInfo's status will be set to CriticalFailure, and a ProcessLog will be created. + /// + /// + /// + public async Task SendProcessRequest(IngestorResult result) + { + result.IngestorRunInfo = await _ingestorRunInfoService.SaveAsync(result.IngestorRunInfo); + ArgumentNullException.ThrowIfNull(result.IngestorRunInfo); + + var documentCodeDetailInfos = await GetDistinctDocumentCodeDetailInfos(result.ProcessingRequests); + + List documentProcessingInfos = new(); + + foreach (var processRequest in result.ProcessingRequests) + { + var documentProcessingInfo = new DocumentProcessingInfo(result.IngestorRunInfo.IngestorRunInfoId, + DateTime.Now, + processRequest.DocumentValuePayload, + ProcessStatusTypes.Processing, + processRequest.DocumentFileName, + documentCodeDetailInfos[processRequest.DocumentTypeDisplayName].DocumentType, + documentCodeDetailInfos[processRequest.DocumentTypeDisplayName].DocumentBusinessName); + + documentProcessingInfos.Add(documentProcessingInfo); + } + + await _documentProcessingInfoService.SaveRangeAsync(documentProcessingInfos.ToArray()); + + var savedDocumentProcessingInfos = (await _documentProcessingInfoService.GetByIngestorRunInfoIdAsync(result.IngestorRunInfo.IngestorRunInfoId)).ToArray(); + + var tasks = new List(); + + tasks.AddRange( + savedDocumentProcessingInfos.Select( + (documentProcessingInfo) => + { + var processRequest = result.ProcessingRequests.First(processingRequest => processingRequest.DocumentFileName == documentProcessingInfo.DocumentFileName); + processRequest.DocumentProcessingInfoId = documentProcessingInfo.DocumentProcessingInfoId; + + return SendDocumentProcessingRequest(processRequest, documentProcessingInfo); + } + ) + ); + + await Task.WhenAll(tasks); + } + + private async Task> GetDistinctDocumentCodeDetailInfos(IEnumerable processingRequests) + { + var distinctProcessingRequests = processingRequests.Select(pr => pr.DocumentTypeDisplayName).Distinct(); + var documentCodeDetailInfos = new Dictionary(); + + foreach (var documentTypeDisplayName in distinctProcessingRequests) + { + // TODO: Get by range? + var documentCodeDetail = + await _documentTypeRetrieverService.GetDocumentCodeDetailByDisplayName(documentTypeDisplayName); + documentCodeDetailInfos.Add(documentTypeDisplayName, documentCodeDetail); + } + + return documentCodeDetailInfos; + } + + public async Task SendDocumentProcessingRequest(ProcessingRequest processRequest, DocumentProcessingInfo documentProcessInfo) + { + try + { + await _queueDocumentProcessing.QueueDocumentProcessingRequest(processRequest); + } + catch (Exception exception) + { + var errorMessage = "Failure to Queue DocumentProcessingRequest. " + + $"DocumentProcessInfoId: {documentProcessInfo.DocumentProcessingInfoId}, " + + $"Exception Message: {exception.Message}"; + Log.Error(errorMessage); + + var documentProcessingInfo = await _documentProcessingInfoService.UpdateStatusAndAddLog(documentProcessInfo, + ProcessStatusTypes.CriticalFailure, + errorMessage, + Users.System); + if (documentProcessingInfo == null) + { + throw new Exception("Unable to update DocumentProcessingInfo, null returned."); + } + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IngestionFolderCleanUpService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IngestionFolderCleanUpService.cs new file mode 100644 index 0000000..0e20ae7 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/IngestionFolderCleanUpService.cs @@ -0,0 +1,329 @@ +using System.Text.RegularExpressions; +using Serilog; +using LCU.Library.Internal.ApiResponse.Services; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.API.Internal.DocumentIngestor.Utilities; +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.Library.Internal.FileOperationsModels.Models.NameSettings; + +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public class IngestionFolderCleanUpService : IIngestionFolderCleanUpService +{ + private readonly IFileOperationsApiService _fileOperationsApiService; + private readonly IIngestorRunInfoService _ingestorRunInfoService; + private readonly IDocumentProcessingInfoService _documentProcessingInfoService; + + private readonly Regex _zipRootPathRegex = new(@"(?^.*\\\d{8}\\)", RegexOptions.Compiled | RegexOptions.IgnoreCase); + private readonly Regex _zipFileName = new(@"^.*\\\d{8}\\(?[a-zA-Z0-9 _.\(\)-]+)\\", RegexOptions.Compiled | RegexOptions.IgnoreCase); + + public IngestionFolderCleanUpService + ( + IFileOperationsApiService fileOperationsApiService, + IIngestorRunInfoService ingestorRunInfoService, + IDocumentProcessingInfoService documentProcessingInfoService + ) + { + _fileOperationsApiService = fileOperationsApiService; + _ingestorRunInfoService = ingestorRunInfoService; + _documentProcessingInfoService = documentProcessingInfoService; + } + + public async Task HandleIngestionFolderCleanUp(IngestionFolderCleanUpRequest request) + { + try + { + var ingestionFolderCleanUpResult = new IngestionFolderCleanUpResult(); + var archiveDirectoryWasCreated = false; + + var ingestorRunInfos = _ingestorRunInfoService.FindByIngestionEndDateNotArchived(request.CleanUpIngestionFoldersUntilDate).ToList(); + + if (!ingestorRunInfos.Any()) + { + var failureMessage = + $"No ingestions were found to clean up with the IngestionEndedDate: {request.IngestionEndedDate}"; + ingestionFolderCleanUpResult.Messages.Add(failureMessage); + Log.Information($"Failure while handling IngestionFolderCleanUp. {failureMessage}"); + } + + foreach (var ingestorRunInfo in ingestorRunInfos) + { + var zipFileName = GetZipFileName(ingestorRunInfo.IndexFilePath); + if (string.IsNullOrWhiteSpace(zipFileName.Replace(".zip", string.Empty))) + { + var failureMessage = $"A ZipFileName with the required pattern could not be found for IngestorRunInfoId: {ingestorRunInfo.IngestorRunInfoId}. " + + $"IndexFilePath: {ingestorRunInfo.IndexFilePath} | " + + $"Example: '\\{DateTime.Now:yyyyMMdd}\\(ZipFileName).zip'."; + Log.Error("Failure while handling IngestionFolderCleanUp. " + failureMessage); + ingestionFolderCleanUpResult.AddToFailureCount(failureMessage); + continue; + } + + var zipRootFolder = GetZipRootFolder(ingestorRunInfo.IndexFilePath); + if (string.IsNullOrWhiteSpace(zipRootFolder)) + { + var failureMessage = $"A ZipRootFolder with the required pattern could not be found for IngestorRunInfoId: {ingestorRunInfo.IngestorRunInfoId}. " + + $"IndexFilePath: {ingestorRunInfo.IndexFilePath} | " + + $"Example: '\\(ZipRootFolder)\\{DateTime.Now:yyyyMMdd}\\'."; + Log.Error("Failure while handling IngestionFolderCleanUp. " + failureMessage); + ingestionFolderCleanUpResult.AddToFailureCount(failureMessage); + continue; + } + + var unzippedFolderName = GetUnzippedFolderName(ingestorRunInfo.IndexFilePath); + if (string.IsNullOrWhiteSpace(unzippedFolderName)) + { + var failureMessage = $"A UnzippedFolderName with the required pattern could not be found for IngestorRunInfoId: {ingestorRunInfo.IngestorRunInfoId}. " + + $"IndexFilePath: {ingestorRunInfo.IndexFilePath} | " + + $"Example: '\\{DateTime.Now:yyyyMMdd}\\(UnzippedFolderName)\\'.";; + Log.Error("Failure while handling IngestionFolderCleanUp. " + failureMessage); + ingestionFolderCleanUpResult.AddToFailureCount(failureMessage); + continue; + } + + var countOfCompletedDocumentProcessingInfos = await _documentProcessingInfoService.CountCompletedByIngestorRunInfoIdAsync(ingestorRunInfo.IngestorRunInfoId); + var skipIncompleteIngestion = ingestorRunInfo.IndexTotal != countOfCompletedDocumentProcessingInfos; + if (skipIncompleteIngestion) + { + continue; + } + + var archivedFileCountMatchResult = await ArchiveFileCountMatchesIndexTotal(ingestorRunInfo, ingestionFolderCleanUpResult); + ingestionFolderCleanUpResult = archivedFileCountMatchResult.result; + if (!archivedFileCountMatchResult.success) + { + continue; + } + + var zipFileExistsResult = await ZipFileExists(ingestorRunInfo.IngestorRunInfoId, zipRootFolder, zipFileName, ingestionFolderCleanUpResult); + ingestionFolderCleanUpResult = zipFileExistsResult.result; + if (!zipFileExistsResult.success) + { + continue; + } + + archiveDirectoryWasCreated = await CreateArchiveDirectory(request, archiveDirectoryWasCreated); + ingestionFolderCleanUpResult = await MoveZipFile(ingestorRunInfo.IngestorRunInfoId, + zipRootFolder, + zipFileName, + request.ArchiveRootPathAndFolder, + ingestionFolderCleanUpResult); + ingestionFolderCleanUpResult = await DeleteUnzippedFolder(ingestorRunInfo, zipRootFolder, unzippedFolderName, ingestionFolderCleanUpResult); + ingestionFolderCleanUpResult = await UpdateArchiveTimeStamp(ingestorRunInfo, ingestionFolderCleanUpResult); + } + + await QueueReturnResponse.QueueResponse(request, ingestionFolderCleanUpResult.IsSuccessful, ingestionFolderCleanUpResult.Messages); + } + catch (ServiceException serviceException) + { + await QueueReturnResponse.QueueResponse(request, false, new List { serviceException.Message }); + Log.Error(serviceException, "Failure while handling IngestionFolderCleanUp."); + throw new ServiceException(serviceException.Message); + } + catch (Exception exception) + { + const string errorMessage = "Failure while handling IngestionFolderCleanUp."; + var errorMessageWithException = $"{errorMessage} Exception Message: {exception.Message}"; + Log.Error(exception, errorMessage); + await QueueReturnResponse.QueueResponse(request, false, new List { errorMessageWithException }); + throw new ServiceException(errorMessageWithException); + } + } + + private async Task CreateArchiveDirectory(IngestionFolderCleanUpRequest request, bool archiveDirectoryWasCreated) + { + if (archiveDirectoryWasCreated) + { + return archiveDirectoryWasCreated; + } + + try + { + var createDirectory = + await _fileOperationsApiService.DirectCreateDirectory(request.ArchiveRootPath, + request.ArchiveFolderName); + + if (!createDirectory.IsSuccessful) + { + throw new ServiceException( + $"Error when attempting to create archive directory: {request.ArchiveRootPathAndFolder}"); + } + } + catch (ServiceException serviceException) + { + if (!serviceException.Message.Contains("Directory exists at path")) + { + throw; + } + } + + return true; + } + + private async Task MoveZipFile(Guid ingestorRunInfoId, + string zipRootFolder, + string zipFileName, + string archivePath, + IngestionFolderCleanUpResult ingestionFolderCleanUpResult) + { + try + { + await _fileOperationsApiService.DirectMoveFile(zipRootFolder, zipFileName, archivePath); + } + catch (ServiceException serviceException) + { + var failureMessage = + $"Failed to move zip file ({zipRootFolder + "\\" + zipFileName}) to ({archivePath}) for IngestorRunInfoId: {ingestorRunInfoId}. " + + $"Exception: {serviceException.Message}"; + Log.Error(failureMessage); + ingestionFolderCleanUpResult.AddToFailureCount(failureMessage); + } + + return ingestionFolderCleanUpResult; + } + + private async Task<(bool success, IngestionFolderCleanUpResult result)> ArchiveFileCountMatchesIndexTotal(IngestorRunInfo ingestorRunInfo, + IngestionFolderCleanUpResult ingestionFolderCleanUpResult) + { + try + { + var archivedFilesRequest = new DynamicFileListRequest() + { + Path = ingestorRunInfo.IndexFilePath + "\\Archived", + Filename = "{ArchiveFiles}", + DynamicFileSettings = new DynamicNameSetting() + { + RegexSettings = new List() + { + new() + { + Tag = "{ArchiveFiles}", + Regex = ".*" + } + } + } + }; + + var archivedFilesCount = (await _fileOperationsApiService.BuildDynamicFileList(archivedFilesRequest)).Count(); + if (archivedFilesCount != ingestorRunInfo.IndexTotal) + { + throw new Exception($"Count of files in Archived directory ({archivedFilesCount}) does not" + + $"match IndexTotal ({ingestorRunInfo.IndexTotal}) for IngestorRunInfoId: {ingestorRunInfo.IngestorRunInfoId}"); + } + + return (true, ingestionFolderCleanUpResult); + } + catch (Exception exception) + { + Log.Error("Failure while handling IngestionFolderCleanUp. " + exception.Message); + ingestionFolderCleanUpResult.AddToFailureCount(exception.Message); + return (false, ingestionFolderCleanUpResult); + } + } + + private async Task DeleteUnzippedFolder(IngestorRunInfo ingestorRunInfo, + string zipRootFolder, + string unzippedFolderName, + IngestionFolderCleanUpResult ingestionFolderCleanUpResult) + { + + try + { + var deleteDirectory = + await _fileOperationsApiService.DirectDeleteDirectory(unzippedFolderName, + zipRootFolder, + 5); + + if (!deleteDirectory.IsSuccessful) + { + var failureMessage = + $"Failed to delete directory {ingestorRunInfo.IndexFilePath} for IngestorRunInfoId {ingestorRunInfo.IngestorRunInfoId}"; + Log.Error(failureMessage); + ingestionFolderCleanUpResult.AddToFailureCount(failureMessage); + } + } + catch (ServiceException serviceException) + { + var failureMessage = + $"Failed to delete directory {ingestorRunInfo.IndexFilePath} for IngestorRunInfoId {ingestorRunInfo.IngestorRunInfoId}. " + + $"Exception: {serviceException.Message}"; + Log.Error(failureMessage); + ingestionFolderCleanUpResult.AddToFailureCount(failureMessage); + } + + return ingestionFolderCleanUpResult; + } + + private async Task UpdateArchiveTimeStamp(IngestorRunInfo ingestorRunInfo, + IngestionFolderCleanUpResult ingestionFolderCleanUpResult) + { + ingestorRunInfo.ArchiveTimeStamp = DateTime.Now; + try + { + await _ingestorRunInfoService.Update(ingestorRunInfo); + } + catch (Exception ex) + { + ingestionFolderCleanUpResult.AddToFailureCount( + $"Failure to update ArchiveTimeStamp for IngestorRunInfoId: {ingestorRunInfo.IngestorRunInfoId}"); + Log.Error(ex.Message); + } + + return ingestionFolderCleanUpResult; + } + + private string GetZipRootFolder(string indexFilePath) => + _zipRootPathRegex.Match(indexFilePath).Groups["ziprootpath"].Value; + + private string GetZipFileName(string indexFilePath) => + _zipFileName.Match(indexFilePath).Groups["zipfilename"].Value + ".zip"; + + private string GetUnzippedFolderName(string indexFilePath) => + _zipFileName.Match(indexFilePath).Groups["zipfilename"].Value; + + private async Task<(bool success, IngestionFolderCleanUpResult result)> ZipFileExists(Guid ingestorRunInfoId, + string zipRootFolder, + string zipFileName, + IngestionFolderCleanUpResult ingestionFolderCleanUpResult) + { + try + { + var escapedZipFileName = SpecialCharacters.EscapeSpecialCharacters(zipFileName); + var zipFileRequest = new DynamicFileListRequest() + { + Path = zipRootFolder, + Filename = "{ZipFileRegex}", + DynamicFileSettings = new DynamicNameSetting() + { + RegexSettings = new List() + { + new() + { + Tag = "{ZipFileRegex}", + // (?i) = ignore case + Regex = $"(?i){escapedZipFileName}" + } + } + } + }; + + var zipFiles = await _fileOperationsApiService.BuildDynamicFileList(zipFileRequest); + + if (zipFiles.Count() != 1) + { + throw new Exception($"Failed to find zip file '{escapedZipFileName}' in '{zipRootFolder}' for IngestorRunInfoId: {ingestorRunInfoId}"); + } + + return (true, ingestionFolderCleanUpResult); + } + catch (Exception exception) + { + Log.Error("Failure while handling IngestionFolderCleanUp. " + exception.Message); + ingestionFolderCleanUpResult.AddToFailureCount(exception.Message); + return (false, ingestionFolderCleanUpResult); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/MemberDocumentNotifierService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/MemberDocumentNotifierService.cs new file mode 100644 index 0000000..81665f0 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/MemberDocumentNotifierService.cs @@ -0,0 +1,379 @@ +using System.Text; +using System.Text.RegularExpressions; +using Newtonsoft.Json; +using Serilog; +using LCU.Api.Internal.DocumentIngestorLib.Extensions; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Services.MemberNotificationInfoDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.Library.DocumentType.Models.Requests; +using LCU.Library.Internal.NotificationsModels.Models; +using LCU.Library.Internal.ApiResponse.Models; +using LCU.Library.Internal.ApiResponse.Services; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.LcuMassTransitModels; + +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public class MemberDocumentNotifierService : IMemberDocumentNotifierService +{ + private readonly IMemberNotificationInfoService _memberNotificationInfoService; + private readonly IDocumentTypeRetrieverService _documentTypeRetrieverService; + private readonly IDocumentProcessingInfoService _documentProcessingInfoService; + private readonly INotificationApiService _notificationApiService; + private readonly IMemberNotificationInfoDeterminingService _memberNotificationInfoDeterminingService; + private readonly IQueueMemberNotificationCompletionService _queueMemberNotificationCompletionService; + private readonly ApiConfiguration _apiConfiguration; + private readonly ConnectionConfiguration _connectionConfiguration; + private readonly ReceiveEndpointConfiguration _memberNotificationCompletionReceiveEndpointConfiguration; + private readonly DigitalBankingConfiguration _digitalBankingConfiguration; + + private const string EntityNameTag = "{EntityName}"; + private const string NumberOfDocumentsTag = "{NumberOfDocuments}"; + private const string DocOrDocsTag = "{DocOrDocs}"; + private const string TableRowsTag = "{TableRows}"; + private const string DocumentNameTag = "{DocumentName}"; + private const string DigitalBankingTag = "{DigitalBanking}"; + private const string MobileBankingTag = "{MobileBanking}"; + + public MemberDocumentNotifierService(IMemberNotificationInfoService memberNotificationInfoService, + IDocumentTypeRetrieverService documentTypeRetrieverService, + IDocumentProcessingInfoService documentProcessingInfoService, + INotificationApiService notificationApiService, + IMemberNotificationInfoDeterminingService memberNotificationInfoDeterminingService, + IQueueMemberNotificationCompletionService queueMemberNotificationCompletionService, + ApiConfiguration apiConfiguration, + ConnectionConfiguration connectionConfiguration, + ReceiveEndpointConfigurations receiveEndpointConfigurations, + DigitalBankingConfiguration digitalBankingConfiguration) + { + _memberNotificationInfoService = memberNotificationInfoService; + _documentTypeRetrieverService = documentTypeRetrieverService; + _documentProcessingInfoService = documentProcessingInfoService; + _notificationApiService = notificationApiService; + _memberNotificationInfoDeterminingService = memberNotificationInfoDeterminingService; + _queueMemberNotificationCompletionService = queueMemberNotificationCompletionService; + _apiConfiguration = apiConfiguration; + _connectionConfiguration = connectionConfiguration; + _memberNotificationCompletionReceiveEndpointConfiguration = receiveEndpointConfigurations.MemberNotificationCompletionEndpoint; + _digitalBankingConfiguration = digitalBankingConfiguration; + } + + public async Task HandleMemberDocumentNotification(MemberDocumentNotificationRequest request) + { + try + { + ArgumentNullException.ThrowIfNull(request); + var result = await PrepareAndSendNotifications(request); + await QueueReturnResponse.QueueResponse(request, result.IsSuccessful, result.Messages); + } + catch (ArgumentNullException) + { + throw; + } + catch (Exception exception) + { + throw new ServiceException(exception.Message); + } + } + + public async Task PrepareAndSendNotifications(MemberDocumentNotificationRequest request) + { + var result = new MemberDocumentNotificationResult(); + try + { + var memberNotificationInfos = await GetMemberNotificationInfos(request); + + if (!memberNotificationInfos.Any()) + { + result.Messages.Add("No MemberNotificationInfos found."); + return result; + } + + var memberNotificationInfoCount = memberNotificationInfos.Count(); + var skipAmount = _apiConfiguration.BatchSkipAmount == null || _apiConfiguration.BatchSkipAmount == 0 + ? memberNotificationInfoCount + : _apiConfiguration.BatchSkipAmount; + + var documentProcessingInfos = memberNotificationInfos.Chunk(skipAmount).Select(async memberNotificationInfoChunk => { + var documentProcessingInfoIds = memberNotificationInfoChunk + .Select(memberNotificationInfo => memberNotificationInfo.DocumentProcessingInfoId).ToList(); + var documentProcessingInfoGroup = await _documentProcessingInfoService.GetListByIdAsync(documentProcessingInfoIds); + return documentProcessingInfoGroup; + }).SelectMany(memberNotificationInfoChunkResult => memberNotificationInfoChunkResult.Result).ToList(); + + var filteredResults = await RemoveMaliciousDocuments(memberNotificationInfos, documentProcessingInfos); + + memberNotificationInfos = filteredResults.MemberNotificationInfos; + documentProcessingInfos = filteredResults.DocumentProcessingInfos.ToList(); + + memberNotificationInfos = await UpdateForSending(memberNotificationInfos); + + var emailGroups = memberNotificationInfos.Where(x => x.DeliveryMethod != DeliveryMethod.Paper) + .GroupBy(x => ( x.AgreeUserId, x.EmailAddress )); + + if (!emailGroups.Any()) + { + result.Messages.Add("Result returned no emails to send."); + return result; + } + + foreach (var emailGroup in emailGroups) + { + if (string.IsNullOrWhiteSpace(emailGroup.Key.EmailAddress)) + { + var completionRequest = new MemberNotificationCompletionRequest() + { + MemberNotificationInfoIds = emailGroup.Select(x => x.MemberNotificationInfoId).ToList() + }; + + var message = $"Email address was null for AgreeUserId: {emailGroup.Key.AgreeUserId}"; + await _queueMemberNotificationCompletionService.QueueMemberNotificationCompletionRequest(completionRequest, false, new() { message }); + continue; + } + + var memberNotificationDocIds = emailGroup.Select(x => x.DocumentProcessingInfoId).Distinct(); + var userDocumentProcessingInfos = documentProcessingInfos.Where(x => memberNotificationDocIds.Contains(x.DocumentProcessingInfoId)); + + result = await PopulateAndSendNotification(emailGroup, + result, + userDocumentProcessingInfos); + } + } + catch (Exception exception) + { + var message = "Failed to PrepareAndSendNotifications."; + Log.Error(exception, message); + result.AddToFailureCount($"{message} Exception Message: {exception.Message}"); + } + + return result; + } + + private async Task PopulateAndSendNotification + ( + IGrouping<(string AgreeUserId, string EmailAddress), + MemberNotificationInfo> memberNotificationInfos, + MemberDocumentNotificationResult result, + IEnumerable documentProcessingInfos + ) + { + const string errorMessage = "Failed to PopulateAndSendNotification."; + async Task Unsendable(MemberDocumentNotificationResult result, string message) + { + result.AddToFailureCount($"{errorMessage} Error Message: {message}"); + + var updateList = memberNotificationInfos.ToList(); + updateList.ForEach(x => x.NotificationStatusType = NotificationStatusTypes.CriticalFailure); + await UpdateMemberNotificationInfoByBatch(updateList); + + return result; + } + + try + { + var emailRequest = await CreateEmailRequest(memberNotificationInfos, documentProcessingInfos); + + if (emailRequest == null) + { + throw new Exception("emailRequest returned null."); + } + + if (_apiConfiguration.FeatureFlags.RestrictNotificationRecipients) + { + var pattern = new Regex(_apiConfiguration.Notifications.AllowedRecipientExpression, RegexOptions.IgnoreCase); + var unapprovedEmails = emailRequest.Recipient + .Where(s => !pattern.IsMatch(s)) + .ToArray(); + + if (unapprovedEmails.Any()) + { + var requestEmailAddresses = string.Join(", ", emailRequest.Recipient.ToArray()); + + var message = + $"{nameof(FeatureFlags.RestrictNotificationRecipients)} flag did not allow the email to send " + + $"because an address is outside the approved pattern of ({_apiConfiguration.Notifications.AllowedRecipientExpression}). " + + $"Emails: {requestEmailAddresses}"; + return await Unsendable(result, message); + } + } + + await _notificationApiService.SendEmailAsync(emailRequest); + } + catch (Exception exception) + { + Log.Error(exception, errorMessage); + + return await Unsendable(result, exception.Message); + } + + return result; + } + + private async Task> GetMemberNotificationInfos(MemberDocumentNotificationRequest request) + { + if (request.RunCriticalFailureNotifications) + { + return await _memberNotificationInfoService.GetByNotificationStatusAsync(NotificationStatusTypes.CriticalFailure); + } + var dateTimeNow = DateTime.Now.AddHours(_apiConfiguration.FileUploadCutoffHours) + .ConvertToTimeZone(_apiConfiguration.TimeZone); + return await _memberNotificationInfoService.GetSendableMemberNotificationInfosAsync(dateTimeNow, + _apiConfiguration.MaxMemberNotificationAttempts); + } + + private async Task> UpdateForSending(IEnumerable memberNotificationInfos) + { + foreach (var memberNotificationInfo in memberNotificationInfos) + { + if (memberNotificationInfo.NotificationStatusType == NotificationStatusTypes.Failure) + { + var contact = await _memberNotificationInfoDeterminingService.DetermineDeliveryMethod(memberNotificationInfo); + memberNotificationInfo.EmailAddress = contact.EmailAddress; + memberNotificationInfo.DeliveryMethod = contact.DeliveryMethod; + } + + if (memberNotificationInfo.DeliveryMethod == DeliveryMethod.Paper) + { + memberNotificationInfo.NotificationStatusType = NotificationStatusTypes.Complete; + continue; + } + + var dateTimeNow = DateTime.Now.ConvertToTimeZone(_apiConfiguration.TimeZone); + memberNotificationInfo.SentTimeStamp = dateTimeNow; + memberNotificationInfo.NotificationStatusType = NotificationStatusTypes.WaitingResponse; + } + + await UpdateMemberNotificationInfoByBatch(memberNotificationInfos); + + return memberNotificationInfos.Where(x => x.NotificationStatusType == NotificationStatusTypes.WaitingResponse); + } + + private async Task<(IEnumerable MemberNotificationInfos, + IEnumerable DocumentProcessingInfos)> RemoveMaliciousDocuments(IEnumerable memberNotificationInfos, + IEnumerable documentProcessingInfos) + { + var dateTimes = memberNotificationInfos.Select(x => x.UploadDate.ConvertToTimeZone(_apiConfiguration.TimeZone)).OrderBy(x => x); + var minDateTime = dateTimes.First().AddHours(_apiConfiguration.MaliciousFileSearchPaddingHours * -1); + var maxDateTime = dateTimes.Last().AddHours(_apiConfiguration.MaliciousFileSearchPaddingHours); + + var maliciousSearchFilter = new MaliciousDocumentSearchFilter() + { + MaliciousDateStart = minDateTime, + MaliciousDateEnd = maxDateTime + }; + + var maliciousDocuments = await _documentTypeRetrieverService.GetListOfMaliciousDocuments(maliciousSearchFilter); + + if (maliciousDocuments == null) + { + return (memberNotificationInfos, documentProcessingInfos); + } + + documentProcessingInfos = documentProcessingInfos.Where(documentProcessingInfo => { + return maliciousDocuments.Any(maliciousDocument => + maliciousDocument.DocumentId != documentProcessingInfo.DocumentId); + }); + + memberNotificationInfos = memberNotificationInfos.Where(memberNotificationInfo => { + return documentProcessingInfos.Any(documentProcessingInfo => + documentProcessingInfo.DocumentProcessingInfoId == memberNotificationInfo.DocumentProcessingInfoId); + }); + + return (memberNotificationInfos, documentProcessingInfos); + } + + private async Task CreateEmailRequest(IGrouping<(string AgreeUserId, string EmailAddress), MemberNotificationInfo> memberNotificationInfos, + IEnumerable documentProcessingInfos) + { + var memberNotificationInfoIds = memberNotificationInfos.Select(x => x.MemberNotificationInfoId).ToList(); + + var entityName = memberNotificationInfos.FirstOrDefault()?.EntityName; + var documents = await CreateDocumentRows(documentProcessingInfos); + var documentCount = documentProcessingInfos.Count(); + + if (!documentProcessingInfos.Any() || + string.IsNullOrWhiteSpace(entityName) || + string.IsNullOrWhiteSpace(documents)) + { + return null; + } + + var notifierEmailTemplateReader = new StreamReader(_apiConfiguration.NotificationEmailTemplate); + string emailBody = notifierEmailTemplateReader.ReadToEnd(); + emailBody = emailBody.Replace(EntityNameTag, entityName); + emailBody = emailBody.Replace(NumberOfDocumentsTag, documentCount.ToString()); + emailBody = emailBody.Replace(DocOrDocsTag, documentCount == 1 ? "eDocument" : "eDocuments"); + emailBody = emailBody.Replace(TableRowsTag, documents.ToString()); + emailBody = emailBody.Replace(DigitalBankingTag, _digitalBankingConfiguration.DigitalBankingUrl); + emailBody = emailBody.Replace(MobileBankingTag, _digitalBankingConfiguration.MobileBankingUri.ToString()); + + var completionRequest = new MemberNotificationCompletionRequest() + { + MemberNotificationInfoIds = memberNotificationInfoIds.ToList() + }; + + // TODO: Update EmailRequest to Notification Library when available + return new EmailRequest() + { + Recipient = new List { memberNotificationInfos.Key.EmailAddress }, + Subject = $"{entityName}, view your new eDocuments from Landmark.", + Body = emailBody, + ResponseItems = new List + { + new ResponseItem() + { + ResponsePayload = JsonConvert.SerializeObject(completionRequest), + ReturnQueueConnectionConfig = new QueueConnectionConfig() + { + Url = _connectionConfiguration.HostUrl, + Username = _connectionConfiguration.UserName, + Password = _connectionConfiguration.Password + }, + ReturnQueueConsumerConfig = new QueueConsumerConfig() + { + ExchangeName = _memberNotificationCompletionReceiveEndpointConfiguration.ReceiveEndpoint + } + } + } + }; + } + + private async Task CreateDocumentRows(IEnumerable documents) + { + var documentRowReader = new StreamReader(_apiConfiguration.NotificationEmailRowTemplate); + string documentRow = documentRowReader.ReadToEnd(); + + var documentRows = new StringBuilder(); + foreach (var document in documents.OrderBy(x => x.DocumentBusinessName)) + { + var docCodeDetail = await _documentTypeRetrieverService.GetDocumentCodeDetailByBusinessName(document.DocumentBusinessName); + documentRows.Append(documentRow.Replace(DocumentNameTag, docCodeDetail.DocumentMemberFacingName)); + } + + return documentRows.ToString(); + } + + private async Task> UpdateMemberNotificationInfoByBatch( + IEnumerable memberNotificationInfos) + { + var memberNotificationInfoCount = memberNotificationInfos.Count(); + var skipAmount = _apiConfiguration.BatchSkipAmount == null || _apiConfiguration.BatchSkipAmount == 0 + ? memberNotificationInfoCount + : _apiConfiguration.BatchSkipAmount; + + var memberNotificationInfosChunks = memberNotificationInfos.Chunk(skipAmount); + var memberNotificationInfoResult = new List(); + foreach (IEnumerable memberNotificationInfoChunk in memberNotificationInfosChunks) + { + var result = await _memberNotificationInfoService.UpdateRange(memberNotificationInfoChunk); + memberNotificationInfoResult.AddRange(result); + } + + return memberNotificationInfoResult; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/MemberNotificationCompletionService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/MemberNotificationCompletionService.cs new file mode 100644 index 0000000..24b7fdc --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/MemberNotificationCompletionService.cs @@ -0,0 +1,162 @@ +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.Api.Internal.DocumentIngestorLib.Extensions; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.ApiResponse.Models; +using LCU.Library.Internal.DocumentIngestorModels.Constants; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using Newtonsoft.Json; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public class MemberNotificationCompletionService : IMemberNotificationCompletionService +{ + private readonly IMemberNotificationInfoService _memberNotificationInfoService; + private readonly IMemberPreferencesApiService _memberPreferencesApiService; + private readonly IProcessingLogService _processingLogService; + private readonly ApiConfiguration _apiConfiguration; + + public MemberNotificationCompletionService(IMemberNotificationInfoService memberNotificationInfoService, + IMemberPreferencesApiService memberPreferencesApiService, + IProcessingLogService processingLogService, + ApiConfiguration apiConfiguration) + { + _memberNotificationInfoService = memberNotificationInfoService; + _memberPreferencesApiService = memberPreferencesApiService; + _processingLogService = processingLogService; + _apiConfiguration = apiConfiguration; + } + + public async Task HandleMemberNotificationCompletion(Response returnResponse) + { + try + { + ArgumentNullException.ThrowIfNull(returnResponse); + var request = JsonConvert.DeserializeObject(returnResponse.ResponsePayload); + ArgumentNullException.ThrowIfNull(request); + + await CompleteAndUpdateStatuses(request.MemberNotificationInfoIds, + returnResponse.Successful, + returnResponse.ResponseStack); + } + catch (ArgumentNullException) + { + throw; + } + catch (Exception exception) + { + throw new ServiceException("Exception was thrown in HandleMemberNotificationCompletion. " + + $"Response: {JsonConvert.SerializeObject(returnResponse)}" + + $"Exception Message: {exception.Message}"); + } + } + + public async Task CompleteAndUpdateStatuses(List ids, bool success, List logs) + { + try + { + var memberNotificationInfos = await _memberNotificationInfoService.GetListByIdAsync(ids); + + var emailGroups = memberNotificationInfos.GroupBy(x => (x.AgreeUserId, x.EmailAddress)); + foreach (var emailGroup in emailGroups) + { + var isUndeliverable = false; + foreach (var memberNotificationInfo in emailGroup) + { + var updatedMemberNotification = await UpdateStatusAndLog(memberNotificationInfo, success, logs); + + if (updatedMemberNotification.NotificationStatusType == NotificationStatusTypes.Undeliverable) + { + isUndeliverable = true; + } + } + + if (success || isUndeliverable) + { + await UpdatePreferencesEmailStatus(emailGroup.Key.AgreeUserId, + emailGroup.Key.EmailAddress, + success); + } + } + } + catch (Exception exception) + { + var message = "Failure on CompleteAndUpdateStatuses for MemberNotificationInfos."; + Log.Error(exception, message); + throw new ServiceException(message); + } + } + + private async Task UpdateStatusAndLog(MemberNotificationInfo memberNotificationInfo, bool success, List logs) + { + try + { + var dateTimeNow = DateTime.Now.ConvertToTimeZone(_apiConfiguration.TimeZone); + memberNotificationInfo.ResponseTimeStamp = dateTimeNow; + + memberNotificationInfo = DetermineStatus(memberNotificationInfo, success); + await _memberNotificationInfoService.Update(memberNotificationInfo); + + foreach (var log in logs) + { + var processingLog = new ProcessingLog(memberNotificationInfo.DocumentProcessingInfoId, DateTime.Now, log, Users.System); + await _processingLogService.SaveAsync(processingLog); + } + + return memberNotificationInfo; + } + catch (Exception exception) + { + var message = "Failure on UpdateStatusAndLog for MemberNotificationInfo. " + + $"MemberNotificationId: {memberNotificationInfo.MemberNotificationInfoId}"; + Log.Error(exception, message); + throw new ServiceException(message); + } + } + + private MemberNotificationInfo DetermineStatus(MemberNotificationInfo memberNotificationInfo, bool success) + { + if (success) + { + memberNotificationInfo.NotificationStatusType = NotificationStatusTypes.Complete; + return memberNotificationInfo; + } + + if (memberNotificationInfo.Attempts >= _apiConfiguration.MaxMemberNotificationAttempts) + { + memberNotificationInfo.NotificationStatusType = NotificationStatusTypes.Undeliverable; + return memberNotificationInfo; + } + + memberNotificationInfo.NotificationStatusType = NotificationStatusTypes.Failure; + memberNotificationInfo.Attempts++; + + return memberNotificationInfo; + } + + private async Task UpdatePreferencesEmailStatus(string agreeUserId, string emailAddress, bool success) + { + try + { + await _memberPreferencesApiService.EmailStatusSend(agreeUserId, + emailAddress, + success); + } + catch (Exception exception) + { + var message = "Failure to UpdatePreferencesEmailStatus. Message: " + exception.Message; + + if (exception.Message.Contains("NotFound")) + { + Log.Warning(exception, message); + } + else + { + throw new Exception(message); + } + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/OsgPreprocessorService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/OsgPreprocessorService.cs new file mode 100644 index 0000000..54189f5 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/OsgPreprocessorService.cs @@ -0,0 +1,445 @@ +using System.Text.RegularExpressions; +using System.Globalization; +using System.Xml; +using System.Xml.Serialization; +using Serilog; +using Newtonsoft.Json; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.XmlParser; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Api.Internal.DocumentIngestorLib.Extensions; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.Library.Internal.FileOperationsModels.Models.NameSettings; +using LCU.Library.Internal.FileOperationsModels.Models; + +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +[Obsolete("06/02/2023 - Used to prepare historical documents for ingestion. No longer in use.")] +public class OsgPreprocessorService : IOsgPreprocessorService +{ + private readonly IFileOperationsApiService _fileOperationsApiService; + private readonly IOsgPreprocessorInfoService _osgPreprocessorInfoService; + private readonly ApiConfiguration _apiConfiguration; + private const string AllPdfsRegexTag = "{Regex0}"; + private const string _statement = "Statement"; + private const string _mmSTMXT = "MM_STMXT"; + private const string _document = "DOCUMENT"; + private DateTime _minDocDate = new DateTime(2020,09,01); + private DateTime _maxDocDate = new DateTime(2022,08,31); + private const string AllRegex = ".*"; + private const string SourceIndexExtension = ".XML"; + private const string OutputIndexExtension = ".csv"; + private const string PdfExtension = ".PDF"; + private const string ZipExtension = ".ZIP"; + private const string OsgPreprocessorRunInfoLogFileName = "OsgPreprocessorRunInfo"; + private const string OsgPreprocessorRunInfoLogFileExt = "txt"; + private const string _pdfPartitionDateFormat = "MMddyyyy"; + private const string _osgIndexDateFormat = "yyyy/MM/dd"; + private int _maxZipsPerDateFolder = 2; + + public OsgPreprocessorService(IFileOperationsApiService fileOperationsApiService, + IOsgPreprocessorInfoService osgPreprocessorInfoService, + ApiConfiguration apiConfiguration) + { + _fileOperationsApiService = fileOperationsApiService; + _osgPreprocessorInfoService = osgPreprocessorInfoService; + _apiConfiguration = apiConfiguration; + } + + public async Task HandleOsgPreprocessing(OsgPreprocessorRequest request) + { + try + { + ArgumentNullException.ThrowIfNull(request); + var allZipsInDirectory = await DetermineAllFilesInDirectory(request.SourceBasePath, ZipExtension); + + var fileCounter = 1; + var directoryDate = request.ArchiveStartDate; + var batchRunInfoId = Guid.NewGuid(); + foreach (var zipFile in allZipsInDirectory) + { + var zipFileStartTime = DateTime.Now.ConvertToTimeZone(_apiConfiguration.TimeZone); + await PrepareZipFile(zipFile, request); + + var osgPreprocessorRunInfo = await HandleOsgFolder(zipFile, batchRunInfoId, zipFileStartTime, request); + if (osgPreprocessorRunInfo.HasStatements) + { + osgPreprocessorRunInfo.DirectoryDate = directoryDate.ToString(_pdfPartitionDateFormat); + await WriteOsgPreprocessorRunInfoLog(zipFile, osgPreprocessorRunInfo); + + if (!osgPreprocessorRunInfo.Incomplete) + { + if (fileCounter == 1) + { + var createDateDirectoryRequest = await _fileOperationsApiService.DirectCreateDirectory(request.OutputBasePath, osgPreprocessorRunInfo.DirectoryDate); + if (!createDateDirectoryRequest.IsSuccessful) + { + var message = $"OsgPreprocessing failed. Failed to create directory ({request.OutputBasePath}{osgPreprocessorRunInfo.DirectoryDate})."; + Log.Error(message); + throw new Exception(message); + } + + fileCounter++; + } + else if (fileCounter > 1 && fileCounter < _maxZipsPerDateFolder) + { + fileCounter++; + } + else + { + directoryDate = directoryDate.AddDays(1); + fileCounter = 1; + } + } + + await ZipAndMoveResults(zipFile, osgPreprocessorRunInfo.FinalWorkingDirectory, osgPreprocessorRunInfo); + } + + var deleteDirectoriesResult = await _fileOperationsApiService.DirectDeleteDirectory(osgPreprocessorRunInfo.UnZippedFolder, request.WorkingBasePath, 1); + if (!deleteDirectoriesResult.IsSuccessful) + { + throw new Exception($"Failure to DeleteDirectories for OSG Preprocessed. Message: {string.Join(",", deleteDirectoriesResult.MessageStack)}"); + } + + if (osgPreprocessorRunInfo.Incomplete) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error($"There was an issue during preprocessing. The preprocessing run info has been " + + $"logged to the following zip file ({Path.GetFileNameWithoutExtension(zipFile)}_Final{ZipExtension}) " + + $"at location ({osgPreprocessorRunInfo.FinalWorkingDirectory})"); + } + } + } + catch (ArgumentNullException) + { + throw; + } + catch (Exception exception) + { + const string errorMessage = "Failure during OsgPreprocessing. The OsgPreprocessor has been stopped."; + var errorMessageWithException = $"{errorMessage} Exception Message: {exception.Message}"; + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error(exception, errorMessage); + throw new ServiceException(errorMessageWithException); + } + } + + private async Task HandleOsgFolder(string zipFile, Guid batchRunInfoId, DateTime zipFileStartTime, OsgPreprocessorRequest request) + { + var osgPreprocessorRunInfo = new OsgPreprocessorRunInfo(request); + + try + { + osgPreprocessorRunInfo.UnZippedFolder = Path.GetFileNameWithoutExtension(zipFile); + var indexFiles = await DetermineAllFilesInDirectory(osgPreprocessorRunInfo.FinalWorkingDirectory, SourceIndexExtension); + if (indexFiles?.Count() != 1) + { + throw new Exception($"Could not determine IndexFile for zip file: {request.WorkingBasePath}{zipFile}."); + } + + var indexFile = indexFiles.FirstOrDefault(); + if (indexFile == null) + { + throw new Exception($"IndexFile was null for zip file: {request.WorkingBasePath}{zipFile}."); + } + + osgPreprocessorRunInfo.IndexFile = indexFile; + var indexFilePath = Path.GetFullPath(osgPreprocessorRunInfo.IndexFilePath).Replace(char.Parse("\\"), Path.DirectorySeparatorChar); + var records = ParseRecords(indexFilePath); + if (records == null || !records.Any()) + { + osgPreprocessorRunInfo.HasStatements = false; + Log.Information($"OsgPreprocess Index file returned no statements. ZipFile: {request.WorkingBasePath}{zipFile}"); + return osgPreprocessorRunInfo; + } + + var indexFileGroups = records.GroupBy(x => x.ArchiveOutput.PdfIndex); + if (!indexFileGroups.Any()) + { + throw new Exception("IndexFileGroups by PdfIndex returned no results."); + } + + var pdfsInFolder = await DetermineAllFilesInDirectory(osgPreprocessorRunInfo.FinalWorkingDirectory, PdfExtension); + foreach (var indexFileGroup in indexFileGroups) + { + var parsingResult = await WriteParsedRecordGroup(indexFile, indexFileGroup.Key, indexFileGroup.ToList(), osgPreprocessorRunInfo.FinalWorkingDirectory, pdfsInFolder); + osgPreprocessorRunInfo.OsgPreprocessorResults.Add(parsingResult); + } + + if (request.SaveXmlOutput) + { + var recordsToSave = TransformXmlDocsToInfos(batchRunInfoId, zipFile, zipFileStartTime, records).ToList(); + await _osgPreprocessorInfoService.SaveListAsync(recordsToSave); + } + + var anyIncomplete = osgPreprocessorRunInfo.OsgPreprocessorResults.Any(result => !result.Success); + osgPreprocessorRunInfo.Incomplete = anyIncomplete; + + if (!anyIncomplete) + { + var deleteResponse = await _fileOperationsApiService.DirectDeleteFile(osgPreprocessorRunInfo.FinalWorkingDirectory, osgPreprocessorRunInfo.IndexFile); + if (!deleteResponse.IsSuccessful) + { + throw new Exception($"Failed to delete the source index file: {osgPreprocessorRunInfo.FinalWorkingDirectory}{osgPreprocessorRunInfo.IndexFile}."); + } + } + } + catch (Exception exception) + { + const string errorMessage = "Failure during OsgPreprocessing."; + + Log.Error(exception, errorMessage); + var errorMessageWithException = $"{errorMessage} Exception Message: {exception.Message}"; + osgPreprocessorRunInfo.Incomplete = true; + osgPreprocessorRunInfo.Messages.Add(errorMessageWithException); + } + + return osgPreprocessorRunInfo; + } + + private IEnumerable ParseRecords(string filePath) + { + using var xmlReader = XmlReader.Create(filePath, new XmlReaderSettings() { ConformanceLevel = ConformanceLevel.Fragment, IgnoreWhitespace = true }); + var documents = SerializeHistoricalDocs(xmlReader); + var filtered = documents.Where(x => x.DocumentType == _statement && + (DateTime.ParseExact(x.CreationDate, _osgIndexDateFormat, CultureInfo.InvariantCulture) >= _minDocDate && + DateTime.ParseExact(x.CreationDate, _osgIndexDateFormat, CultureInfo.InvariantCulture) <= _maxDocDate)); + + return filtered.ToList(); + } + + private IEnumerable SerializeHistoricalDocs(XmlReader source) + { + var xmlSerializer = new XmlSerializer(typeof(XmlOsgHistoricalDocument)); + while (!source.EOF) + { + if (source.NodeType == XmlNodeType.Element && + source.Name == _document) + { + var sourceString = source.ReadOuterXml(); + StringReader rdr = new StringReader(sourceString); + + var xmlOsgHistoricalDocument = (XmlOsgHistoricalDocument)xmlSerializer.Deserialize(rdr); + xmlOsgHistoricalDocument.XmlOutput = sourceString; + + yield return xmlOsgHistoricalDocument; + } + else + { + source.Read(); + } + } + } + + private async Task WriteParsedRecordGroup(string indexFile, + int key, + List xmlOsgHistoricalDocuments, + string folderPath, + List pdfsInFolder) + { + var result = new OsgPreprocessorResult(); + try + { + var newFileName = $"{Path.GetFileNameWithoutExtension(indexFile)}.{key}"; + var targetDirectory = Path.Combine(folderPath, $"{newFileName}\\"); + var outputFile = result.OutputFile = Path.Combine(targetDirectory, $"{newFileName}{OutputIndexExtension}"); + + var doesParsedFileExist = await _fileOperationsApiService.ValidateFileExists(outputFile); + if (doesParsedFileExist) + { + var message = $"OsgPreprocessing failed. A parsed index file already exists. File: {outputFile}"; + Log.Error(message); + result.AddFailureAndMessage(message); + return result; + } + + var pdfRegex = new Regex(@".*\." + $"{key}.PDF", RegexOptions.IgnoreCase); + var pdfFile = pdfsInFolder.Where(x => pdfRegex.IsMatch(x)).FirstOrDefault(); + + if (string.IsNullOrWhiteSpace(pdfFile)) + { + var message = $"OsgPreprocessing failed. A matching PDF could not be found."; + Log.Error(message); + result.AddFailureAndMessage(message); + return result; + } + + var createResponse = await _fileOperationsApiService.DirectCreateDirectory(folderPath, newFileName); + if (!createResponse.IsSuccessful) + { + var message = $"OsgPreprocessing failed. Failed to create a directory. Messages: {string.Join(", ", createResponse.MessageStack)}"; + Log.Error(message); + result.AddFailureAndMessage(message); + return result; + } + + var moveResponse = await _fileOperationsApiService.DirectMoveFile(folderPath, pdfFile, targetDirectory); + if (!moveResponse.IsSuccessful) + { + var message = $"OsgPreprocessing failed. Failed to move pdf file ({folderPath}{pdfFile}). Messages: {string.Join(", ", moveResponse.MessageStack)}"; + Log.Error(message); + result.AddFailureAndMessage(message); + return result; + } + + var outputRows = xmlOsgHistoricalDocuments.Select(x => + $"\"\"|\"{_mmSTMXT}\"|\"{x.OriginalAddress.EntityName}\"|\"{x.MemberNumberOrUserId}\"|\"{x.CreationDate.Replace("/", "")}\"|" + + $"\"{x.ArchiveOutput.StartingPage}\"|\"{x.ArchiveOutput.NumberOfPages}\""); + + var writeResponse = await _fileOperationsApiService.DirectWriteFile(newFileName, OutputIndexExtension, string.Join("\n", outputRows), targetDirectory); + + if (!writeResponse.IsSuccessful) + { + var message = $"OsgPreprocessing failed. Failed to write index file. Messages: {string.Join(", ", writeResponse.MessageStack)}"; + Log.Error(message); + result.AddFailureAndMessage(message); + return result; + } + + result.Success = true; + return result; + } + catch (Exception ex) + { + var message = $"Failure to WriteParsedRecordGroup. Exception: {ex.Message}"; + Log.Error(message); + result.AddFailureAndMessage(message); + return result; + } + } + + private async Task PrepareZipFile(string zipFile, OsgPreprocessorRequest request) + { + var moveZipFileRequest = await _fileOperationsApiService.DirectMoveFile(request.SourceBasePath, + zipFile, + request.WorkingBasePath); + if (!moveZipFileRequest.IsSuccessful) + { + var message = $"OsgPreprocessing failed. Failed to move zip file ({request.SourceBasePath}{zipFile})."; + Log.Error(message); + throw new Exception(message); + } + + var unzipFileRequest = await _fileOperationsApiService.DirectUnzipFile(request.WorkingBasePath, + zipFile, + request.WorkingBasePath, + true); + if (!unzipFileRequest.IsSuccessful) + { + var message = $"OsgPreprocessing failed. Failed to unzip zip file ({request.WorkingBasePath}{zipFile})."; + Log.Error(message); + throw new Exception(message); + } + + var deleteFileRequest = await _fileOperationsApiService.DirectDeleteFile(request.WorkingBasePath, zipFile); + if (!deleteFileRequest.IsSuccessful) + { + var message = $"OsgPreprocessing failed. Failed to delete zip file ({request.WorkingBasePath}{zipFile})."; + Log.Error(message); + throw new Exception(message); + } + } + + private async Task ZipAndMoveResults(string zipFile, string finalWorkingDirectory, OsgPreprocessorRunInfo osgPreprocessorRunInfo) + { + var zipOutputName = $"{Path.GetFileNameWithoutExtension(zipFile)}_FINAL"; + var zipFileName = $"{zipOutputName}{ZipExtension}"; + var zipFileRequest = await _fileOperationsApiService.DirectZipDirectory(finalWorkingDirectory, + osgPreprocessorRunInfo.OsgPreprocessorRequest.WorkingBasePath, + zipFileName); + if (!zipFileRequest.IsSuccessful) + { + var message = $"OsgPreprocessing failed. Failed to zip files for source zip file: {zipFile}."; + Log.Error(message); + throw new Exception(message); + } + + var moveZipRequest = await _fileOperationsApiService.DirectMoveFile(osgPreprocessorRunInfo.OsgPreprocessorRequest.WorkingBasePath, + zipFileName, + osgPreprocessorRunInfo.FinalOutputDirectory); + if (!moveZipRequest.IsSuccessful) + { + var message = $"OsgPreprocessing failed. Failed to move output zip file ({osgPreprocessorRunInfo.OsgPreprocessorRequest.WorkingBasePath}{zipFileName})."; + Log.Error(message); + throw new Exception(message); + } + + if (!osgPreprocessorRunInfo.Incomplete) + { + var unzipFileRequest = await _fileOperationsApiService.DirectUnzipFile(osgPreprocessorRunInfo.FinalOutputDirectory, zipFileName, osgPreprocessorRunInfo.FinalOutputDirectory, false); + if(!unzipFileRequest.IsSuccessful) + { + var message = $"OsgPreprocessing failed. Failed to unzip file ({osgPreprocessorRunInfo.FinalOutputDirectory})."; + Log.Error(message); + throw new Exception(message); + } + } + } + + private async Task> DetermineAllFilesInDirectory(string directory, string extension) + { + var dynamicSettingsForAllPdfs = new DynamicNameSetting() + { + RegexSettings = new List + { + new RegexSetting + { + Tag = AllPdfsRegexTag, + Regex = AllRegex + } + } + }; + + var dynamicFileListRequest = new DynamicFileListRequest + { + Path = directory, + Filename = $"{AllPdfsRegexTag}{extension}", + DynamicFileSettings = dynamicSettingsForAllPdfs + }; + + var listOfPdfs = await _fileOperationsApiService.BuildDynamicFileList(dynamicFileListRequest); + return listOfPdfs.ToList(); + } + + private async Task WriteOsgPreprocessorRunInfoLog(string zipFile, OsgPreprocessorRunInfo osgPreprocessorRunInfo) + { + var serializedOsgPreprocessorRunInfo = JsonConvert.SerializeObject(osgPreprocessorRunInfo, Newtonsoft.Json.Formatting.Indented); + var writeResponse = await _fileOperationsApiService.DirectWriteFile($"{OsgPreprocessorRunInfoLogFileName}_{zipFile}", + OsgPreprocessorRunInfoLogFileExt, + serializedOsgPreprocessorRunInfo, + osgPreprocessorRunInfo.FinalWorkingDirectory); + + if (!writeResponse.IsSuccessful) + { + throw new Exception("Failure to save Osg Preprocessor Run Info Log."); + } + } + + private IEnumerable TransformXmlDocsToInfos(Guid batchRunInfoId, + string zipFileName, + DateTime zipFileStartTime, + IEnumerable records) + { + return records.Select(record => + new OsgPreprocessorInfo() + { + BatchRunInfoId = batchRunInfoId, + ZipFileName = zipFileName, + ZipFileStartTime = zipFileStartTime, + ZipFileEndTime = DateTime.Now.ConvertToTimeZone(_apiConfiguration.TimeZone), + MemberNumber = record.MemberNumberOrUserId, + EntityName = record.OriginalAddress.EntityName, + DocumentType = record.DocumentType, + CreatedDate = DateTime.ParseExact(record.CreationDate, _osgIndexDateFormat, CultureInfo.InvariantCulture), + StartingPage = record.ArchiveOutput.StartingPage, + NumberOfPages = record.ArchiveOutput.NumberOfPages, + XmlOutput = record.XmlOutput + } + ); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/PdfPartitionerCompletionService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/PdfPartitionerCompletionService.cs new file mode 100644 index 0000000..ccb754c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/PdfPartitionerCompletionService.cs @@ -0,0 +1,61 @@ +using Newtonsoft.Json; +using LCU.Library.Internal.ApiResponse.Services; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.ApiResponse.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public class PdfPartitionerCompletionService : IPdfPartitionerCompletionService +{ + private readonly IPdfPartitionerRunInfoService _pdfPartitionerRunInfoService; + private readonly IPdfPartitionerLogService _pdfPartitionerLogService; + + public PdfPartitionerCompletionService(IPdfPartitionerRunInfoService pdfPartitionerRunInfoService, + IPdfPartitionerLogService pdfPartitionerLogService) + { + _pdfPartitionerRunInfoService = pdfPartitionerRunInfoService; + _pdfPartitionerLogService = pdfPartitionerLogService; + } + + public async Task HandlePdfPartitionerCompletion(Response response) + { + try + { + ArgumentNullException.ThrowIfNull(response); + var pdfPartitionerResult = JsonConvert.DeserializeObject(response.ResponsePayload); + ArgumentNullException.ThrowIfNull(pdfPartitionerResult); + + var wasSuccessful = !pdfPartitionerResult.FailedToQueueToParse; + var pdfPartitionLogs = new List(); + if (wasSuccessful) + { + wasSuccessful = response.Successful; + if(response.ResponseStack != null) + { + pdfPartitionLogs.AddRange(response.ResponseStack); + } + } + + pdfPartitionLogs.AddRange(pdfPartitionerResult.MessageStack); + var pdfPartitionerRunInfo = await _pdfPartitionerRunInfoService.IncreaseCountsAndUpdate(pdfPartitionerResult.PdfPartitionerRunInfoId, wasSuccessful); + await _pdfPartitionerLogService.SaveListAsync(pdfPartitionerRunInfo.PdfPartitionerRunInfoId, pdfPartitionLogs); + + if (pdfPartitionerRunInfo.PdfPartitionerCompleted) + { + var pdfPartitionerLogs = await _pdfPartitionerLogService.GetByPdfPartitionerRunInfoIdAsync(pdfPartitionerRunInfo.PdfPartitionerRunInfoId); + var messageStack = pdfPartitionerLogs.Select(pdfPartitionerLog => pdfPartitionerLog.LogMessage).ToList(); + await QueueReturnResponse.QueueResponse(pdfPartitionerResult.PdfPartitionerRequest, pdfPartitionerRunInfo.WasSuccessful, messageStack); + } + } + catch (ArgumentNullException) + { + throw; + } + catch (Exception exception) + { + throw new ServiceException($"Exception was thrown in HandlePdfPartitionerCompletion. " + + $"Response: {JsonConvert.SerializeObject(response)}" + + $"Exception Message: {exception.Message}"); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/PdfPartitionerService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/PdfPartitionerService.cs new file mode 100644 index 0000000..844f4c1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/PdfPartitionerService.cs @@ -0,0 +1,242 @@ +using System.Text.RegularExpressions; +using Serilog; +using Newtonsoft.Json; +using LCU.Library.Internal.ApiResponse.Services; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.PdfParserServices; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.ApiResponse.Models; +using LCU.Library.Internal.LcuMassTransitModels; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.Library.Internal.FileOperationsModels.Models.NameSettings; +using LCU.Library.Internal.FileOperationsModels.Shared; +using LCU.Library.Internal.LCUServiceFactory.Services; + +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public class PdfPartitionerService : IPdfPartitionerService +{ + private readonly ConnectionConfiguration _connectionConfiguration; + private readonly ReceiveEndpointConfiguration _pdfPartitionerCompletionEndpoint; + private readonly IPdfPartitionerRunInfoService _pdfPartitionerRunInfoService; + private readonly IFileOperationsApiService _fileOperationsApiService; + private readonly IQueuePdfPartitionerCompletionService _queuePdfPartitionerCompletionService; + private readonly ILcuServiceFactory _pdfParserServiceFactory; + private const string AllPdfsRegexTag = "{Regex0}"; + private const string AllPdfsRegex = ".*"; + + public PdfPartitionerService(ConnectionConfiguration connectionConfiguration, + ReceiveEndpointConfigurations receiveEndpointConfigurations, + IPdfPartitionerRunInfoService pdfPartitionerRunInfoService, + IFileOperationsApiService fileOperationsApiService, + IQueuePdfPartitionerCompletionService queuePdfPartitionerCompletionService, + ILcuServiceFactory pdfParserServiceFactory) + { + _connectionConfiguration = connectionConfiguration; + _pdfPartitionerCompletionEndpoint = receiveEndpointConfigurations.PdfPartitionerCompletionEndpoint; + _pdfPartitionerRunInfoService = pdfPartitionerRunInfoService; + _fileOperationsApiService = fileOperationsApiService; + _queuePdfPartitionerCompletionService = queuePdfPartitionerCompletionService; + _pdfParserServiceFactory = pdfParserServiceFactory; + } + + public async Task HandlePdfPartition(PdfPartitionerRequest request) + { + try + { + ArgumentNullException.ThrowIfNull(request); + var dynamicDirectoryListRequest = new DynamicDirectoryListRequest + { + Path = request.FinalRootBasePath, + DynamicDirectoryName = request.ParentDynamicDirectory, + DynamicFileSettings = request.ParentDynamicDirectorySettings + }; + var dynamicDirectories = await _fileOperationsApiService.BuildDynamicDirectoryList(dynamicDirectoryListRequest); + + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo(DateTime.Now, + request.PdfParserType, + request.FinalRootBasePath, + dynamicDirectories.ToList().Count); + pdfPartitionerRunInfo = await _pdfPartitionerRunInfoService.SaveAsync(pdfPartitionerRunInfo); + + foreach (var directory in dynamicDirectories) + { + await PartitionPdf(request, directory, pdfPartitionerRunInfo); + } + } + catch (ArgumentNullException) + { + throw; + } + catch (Exception exception) + { + const string errorMessage = "Failure during HandlePdfPartition."; + var errorMessageWithException = $"{errorMessage} Exception Message: {exception.Message}"; + Log.Error(exception, errorMessage); + await QueueReturnResponse.QueueResponse(request, false, new List { errorMessageWithException }); + throw new ServiceException(errorMessageWithException); + } + } + + public async Task PartitionPdf(PdfPartitionerRequest request, string directory, PdfPartitionerRunInfo pdfPartitionerRunInfo) + { + var result = new PdfPartitionerResult(pdfPartitionerRunInfo.PdfPartitionerRunInfoId, request); + try + { + var ingestionRootPath = DetermineIngestionRootPath(request, directory); + var indexFile = await DetermineIndexFile(request, ingestionRootPath); + var allPdfs = await DetermineAllPdfsInDirectory(ingestionRootPath); + var mainPdf = DeterminMainPdfInDirectory(request, allPdfs); + var batchPdfParserRequest = await PdfParserSwitch(request, ingestionRootPath, indexFile, mainPdf); + + var canSkipParsing = CanSkipPdfParse(request, allPdfs, batchPdfParserRequest); + if (canSkipParsing) + { + result.MessageStack.Add($"Skipping Pdf Partition for Pdf {mainPdf} at the path {ingestionRootPath}"); + await _queuePdfPartitionerCompletionService.QueuePdfPartitionerCompletionRequest(result); + return; + } + + batchPdfParserRequest.RootPath = ingestionRootPath; + batchPdfParserRequest.PdfName = mainPdf; + batchPdfParserRequest = SetUpPdfPartitionerApiResponse(result, batchPdfParserRequest); + await _fileOperationsApiService.QueueBatchPdfParser(batchPdfParserRequest); + } + catch (Exception exception) + { + Log.Error(exception.Message); + result.AddFailureAndMessage(exception.Message); + await _queuePdfPartitionerCompletionService.QueuePdfPartitionerCompletionRequest(result); + } + } + + public string DetermineIngestionRootPath(PdfPartitionerRequest request, string directory) + { + var subDirectoryPath = request.SubDirectoryPath.EndsWith("\\") || string.IsNullOrWhiteSpace(request.SubDirectoryPath) ? + request.SubDirectoryPath : + $"{request.SubDirectoryPath}\\"; + var formattedDirectory = directory.EndsWith("\\") ? directory : $"{directory}\\"; + var ingestionRootPath = request.FinalRootBasePath + formattedDirectory + subDirectoryPath; + return ingestionRootPath; + } + + public async Task DetermineIndexFile(PdfPartitionerRequest request, string path) + { + var dynamicFileListRequest = new DynamicFileListRequest + { + Path = path, + Filename = request.DynamicIndexFileName, + DynamicFileSettings = request.DynamicFileSettings + }; + + return await _fileOperationsApiService.BuildDynamicFile(dynamicFileListRequest); + } + + public async Task> DetermineAllPdfsInDirectory(string directory) + { + var dynamicSettingsForAllPdfs = new DynamicNameSetting() + { + RegexSettings = new List + { + new RegexSetting + { + Tag = AllPdfsRegexTag, + Regex = AllPdfsRegex + } + } + }; + + var dynamicFileListRequest = new DynamicFileListRequest + { + Path = directory, + Filename = $"{AllPdfsRegexTag}.(?i:pdf)", + DynamicFileSettings = dynamicSettingsForAllPdfs + }; + + var listOfPdfs = await _fileOperationsApiService.BuildDynamicFileList(dynamicFileListRequest); + return listOfPdfs.ToList(); + } + + public string DeterminMainPdfInDirectory(PdfPartitionerRequest request, List allPdfsInDirectory) + { + var regex = new Regex(request.DynamicPdfName); + if (request?.DynamicPdfSettings?.RegexSettings != null) + { + regex = RegexNameHandler.BuildRegexName(request.DynamicPdfName, request.DynamicPdfSettings); + } + + var mainPdf = allPdfsInDirectory.Where(pdf => regex.IsMatch(pdf)).ToList(); + if (mainPdf.Count > 1) + { + var message = $"There were more than one pdf that met the dynamic pdf settings. " + + $"DynamicPdfName:{request.DynamicPdfName}," + + $"DynamicPdfSettings:{JsonConvert.SerializeObject(request.DynamicPdfSettings)}"; + throw new Exception(message); + } + + var pdf = mainPdf.FirstOrDefault(); + if (pdf == null) + { + var message = $"There were no pdfs that met the dynamic pdf settings. " + + $"DynamicPdfName:{request.DynamicPdfName}," + + $"DynamicPdfSettings:{JsonConvert.SerializeObject(request.DynamicPdfSettings)}"; + throw new Exception(message); + } + + return pdf; + } + + public async Task PdfParserSwitch(PdfPartitionerRequest request, string rootPath, string indexFile, string pdfName) + { + + var service = _pdfParserServiceFactory.GetService(request.PdfParserType); + + if (service is null) + { + throw new NotImplementedException(); + } + + return await service.DetermineBatchParsePdfRequest(rootPath, indexFile, pdfName); + } + + public bool CanSkipPdfParse(PdfPartitionerRequest request, List allPdfs, BatchParsePdfRequest batchParsePdfRequest) + { + if (!request.SkipParseIfCountsMatch) + { + return false; + } + + var countsMatch = allPdfs.Count == batchParsePdfRequest.BatchPdfs.Count + 1; + return countsMatch && request.SkipParseIfCountsMatch; + } + + public BatchParsePdfRequest SetUpPdfPartitionerApiResponse(PdfPartitionerResult pdfPartitionerResult, + BatchParsePdfRequest batchParsePdfRequest) + { + var serializedResponse = JsonConvert.SerializeObject(pdfPartitionerResult); + var newReturnItem = new ResponseItem + { + ResponsePayload = serializedResponse, + ReturnQueueConnectionConfig = new QueueConnectionConfig + { + Url = _connectionConfiguration.HostUrl, + Username = _connectionConfiguration.UserName, + Password = _connectionConfiguration.Password + }, + ReturnQueueConsumerConfig = new QueueConsumerConfig + { + ExchangeName = _pdfPartitionerCompletionEndpoint.ReceiveEndpoint + } + }; + + batchParsePdfRequest.ResponseItems = new List + { + newReturnItem + }; + return batchParsePdfRequest; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/ProcessStatusTypeEmailService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/ProcessStatusTypeEmailService.cs new file mode 100644 index 0000000..6fd203a --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/ProcessStatusTypeEmailService.cs @@ -0,0 +1,103 @@ +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.ApiResponse.Services; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Requests; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.NotificationsModels.Models; +using Microsoft.OpenApi.Extensions; +using Serilog; +using System.Text; + +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +public class ProcessStatusTypeEmailService : IProcessStatusTypeEmailService +{ + private readonly INotificationApiService _notificationApiService; + private readonly IDocumentProcessingInfoService _documentProcessingInfoService; + private readonly ApiConfiguration _apiConfiguration; + + public ProcessStatusTypeEmailService(INotificationApiService notificationApiService, IDocumentProcessingInfoService documentProcessingInfoService, + ApiConfiguration apiConfiguration) + { + _notificationApiService = notificationApiService; + _documentProcessingInfoService = documentProcessingInfoService; + _apiConfiguration = apiConfiguration; + } + + public async Task HandleProcessStatusTypeEmailRequest(ProcessStatusTypeEmailRequest request) + { + try + { + var processStatusTypeInfoResults = await _documentProcessingInfoService.GetByProcessStatusTypeListAsync(request.ProcessStatusTypes, false); + + if (processStatusTypeInfoResults.Any()) + { + await SendProcessStatusEmailAsync(processStatusTypeInfoResults, request); + } + + var message = $"Handle Process Status Type Email Request of {string.Join(", ", request.ProcessStatusTypes)} statuses completed successfully."; + await QueueReturnResponse.QueueResponse(request, true, new List { message }); + } + catch (ServiceException exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)).Error(exception, "Service Exception"); + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)).Error(exception, "Unexpected Exception"); + } + } + + public async Task SendProcessStatusEmailAsync(IEnumerable listDocumentProcessingInfo, ProcessStatusTypeEmailRequest request) + { + if (request != null) + { + var subject = CheckDataMappingFailures(request.ProcessStatusTypes) ? "Data mapping errors" : + string.Join(", ", request.ProcessStatusTypes.Select(x => x.GetDisplayName())) + " statuses"; + + var bodyMessage = GetEmailBodyMessage(request.ProcessStatusTypes, listDocumentProcessingInfo.ToList()); + + var emailRequest = new EmailRequest + { + Subject = $"Document Manager: {subject} found", + Recipient = request.EmailAddresses, + Body = GetLowerEnvironmentHtml() + "This is an auto generated message.
" + "
" + bodyMessage.ToString() + + request.ProcessStatusTypeEmailUrl + }; + + await _notificationApiService.SendEmailAsync(emailRequest); + } + } + + private bool CheckDataMappingFailures(List statusTypes) + { + return statusTypes.Count == 1 && statusTypes.Contains(ProcessStatusTypes.DataMappingFailure); + } + + private string GetEmailBodyMessage(List statusTypes, List processingResults) + { + var bodyMessage = new StringBuilder(); + foreach (var statusType in statusTypes) + { + var processCount = processingResults.Where(x => x.StatusType.Equals(statusType)).Count(); + var typeDescription = CheckDataMappingFailures(statusTypes) ? " mapping errors" : $"{statusType} status."; + bodyMessage.Append($"There are {processCount} documents found that have {typeDescription}
" + "
"); + } + return bodyMessage.ToString(); + } + + private string GetLowerEnvironmentHtml() + { + var message = string.Empty; + var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT"); + if (!string.IsNullOrEmpty(env) && !env.Equals("Production", StringComparison.Ordinal)) + { + message = $"This is from the {env.ToUpper()} Environment

"; + } + return message; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/UploadCompletionService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/UploadCompletionService.cs new file mode 100644 index 0000000..248ef30 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestionOperationServices/UploadCompletionService.cs @@ -0,0 +1,259 @@ +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.Services.MemberNotificationInfoDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.API.Internal.DocumentIngestorLib.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.QueueResult; +using LCU.Library.Internal.Exceptions; +using MassTransit; +using Newtonsoft.Json; +using Serilog; +using Response = LCU.Library.Internal.ApiResponse.Models.Response; +namespace LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +public class UploadCompletionService : IUploadCompletionService +{ + private readonly IQueueCompletionService _queueCompletionService; + private readonly IFileOperationsApiService _fileOperationsApiService; + private readonly IDocumentProcessingInfoService _documentProcessingInfoService; + private readonly IMemberNotificationInfoDeterminingService _memberNotificationInfoDeterminingService; + private readonly IQueueGatherMemberNotificationInfoService _queueGatherMemberNotificationInfoService; + private const string _documentIdKey = "DocumentId"; + + public UploadCompletionService(IQueueCompletionService queueCompletionService, + IFileOperationsApiService fileOperationsApiService, + IDocumentProcessingInfoService documentProcessingInfoService, + IMemberNotificationInfoDeterminingService memberNotificationInfoDeterminingService, + IQueueGatherMemberNotificationInfoService queueGatherMemberNotificationInfoService) + { + _queueCompletionService = queueCompletionService; + _fileOperationsApiService = fileOperationsApiService; + _documentProcessingInfoService = documentProcessingInfoService; + _memberNotificationInfoDeterminingService = memberNotificationInfoDeterminingService; + _queueGatherMemberNotificationInfoService = queueGatherMemberNotificationInfoService; + } + + public async Task HandleUploadCompletion(List responses) + { + try + { + ArgumentNullException.ThrowIfNull(responses); + + var batchUploadCompletion = DeserializeAndSortResponses(responses); + + if (batchUploadCompletion.SuccessfulUploadCompletions.Count() > 0) + { + batchUploadCompletion = await HandleSuccessfulCompletionRequests(batchUploadCompletion); + } + + if (batchUploadCompletion.UnsuccessfulUploadCompletions.Count() > 0) + { + batchUploadCompletion = await HandleUnsuccessfulCompletionRequests(batchUploadCompletion); + } + } + catch (ArgumentNullException) + { + throw; + } + catch (ArchiveException) + { + throw; + } + catch (Exception exception) + { + throw new ServiceException("Exception was thrown in HandleCompletion. " + + $"Exception Message: {exception.Message}"); + } + } + + public BatchUploadCompletionRequest DeserializeAndSortResponses(List responses) + { + var batchUploadCompletion = new BatchUploadCompletionRequest() + { + SuccessfulUploadCompletions = new List(), + UnsuccessfulUploadCompletions = new List() + }; + + foreach (var response in responses) + { + var request = JsonConvert.DeserializeObject(response.ResponsePayload); + + if (response.Successful) + { + batchUploadCompletion.SuccessfulUploadCompletions.Add(new UploadCompletionRequest(request, response)); + } + else + { + batchUploadCompletion.UnsuccessfulUploadCompletions.Add(new UploadCompletionRequest(request, response)); + } + } + + return batchUploadCompletion; + } + + public async Task HandleSuccessfulCompletionRequests(BatchUploadCompletionRequest batchUploadCompletionRequest) + { + batchUploadCompletionRequest.DocumentProcessingInfos = await _documentProcessingInfoService.GetListByIdAsync(batchUploadCompletionRequest.SuccessfulUploadCompletions + .Select(r => r.CompletionRequest.ProcessingRequest.DocumentProcessingInfoId) + .ToList()); + + batchUploadCompletionRequest = AddDocumentIdToDocumentProcessingInfo(batchUploadCompletionRequest); + + batchUploadCompletionRequest.DocumentProcessingInfos = await _documentProcessingInfoService.UpdateRangeAsync(batchUploadCompletionRequest.DocumentProcessingInfos); + + return await CreateAndQueueGatherMemberNotificationInfoRequest(batchUploadCompletionRequest); + } + + public BatchUploadCompletionRequest AddDocumentIdToDocumentProcessingInfo(BatchUploadCompletionRequest batchUploadCompletionRequest) + { + foreach (var info in batchUploadCompletionRequest.DocumentProcessingInfos) + { + var request = batchUploadCompletionRequest.SuccessfulUploadCompletions.Where(r => + r.CompletionRequest.ProcessingRequest.DocumentProcessingInfoId == info.DocumentProcessingInfoId).FirstOrDefault(); + + ArgumentNullException.ThrowIfNull(request); + + var idResponse = ""; + if (!request.Response.ReturnCollection.TryGetValue(_documentIdKey, out idResponse)) + { + batchUploadCompletionRequest.UnsuccessfulUploadCompletions.Add(request); + batchUploadCompletionRequest.SuccessfulUploadCompletions.Remove(request); + continue; + } + + Guid documentId; + if (!Guid.TryParse(idResponse, out documentId)) + { + batchUploadCompletionRequest.UnsuccessfulUploadCompletions.Add(request); + batchUploadCompletionRequest.SuccessfulUploadCompletions.Remove(request); + continue; + } + + info.DocumentId = documentId; + } + + return batchUploadCompletionRequest; + } + + public async Task CreateAndQueueGatherMemberNotificationInfoRequest(BatchUploadCompletionRequest request) + { + var tasks = request.SuccessfulUploadCompletions.Select(r => QueueGatherMemberNotificationInfoRequest( + new GatherMemberNotificationInfoRequest() + { + CompletionRequest = r.CompletionRequest + }, r)); + + var results = await Task.WhenAll(tasks); + + foreach (var result in results) + { + if (!result.Success) + { + request.UnsuccessfulUploadCompletions.Add(result.OriginalRequest); + } + } + + return request; + } + + public async Task QueueGatherMemberNotificationInfoRequest(GatherMemberNotificationInfoRequest GatherMemberNotificationInfoRequest, + UploadCompletionRequest uploadCompletionRequest) + { + try + { + await _queueGatherMemberNotificationInfoService.QueueGatherMemberNotificationInfoRequest(GatherMemberNotificationInfoRequest); + return new QueueGatherMemberNotificationInfoResult + { + Success = true, + OriginalRequest = uploadCompletionRequest + }; + } + catch (Exception ex) + { + var errorMessage = $"Exception during CreateAndQueueGatherMemberNotificationInfoRequest. ErrorMessage: {ex.Message}"; + Log.Warning(errorMessage); + return new QueueGatherMemberNotificationInfoResult + { + Success = false, + OriginalRequest = uploadCompletionRequest + }; + } + } + + public async Task HandleUnsuccessfulCompletionRequests(BatchUploadCompletionRequest batchUploadCompletionRequest) + { + foreach (var request in batchUploadCompletionRequest.UnsuccessfulUploadCompletions) + { + await UnArchiveDocument(request.CompletionRequest.ProcessingRequest); + request.CompletionRequest.ProcessResult = ProcessResult.ProcessCriticalFailure(request.CompletionRequest.ProcessResult, + request.Response.ResponseStack); + } + + await CreateAndQueueCompletionRequest(batchUploadCompletionRequest.UnsuccessfulUploadCompletions); + + return batchUploadCompletionRequest; + } + + private async Task UnArchiveDocument(ProcessingRequest request) + { + try + { + var response = await _fileOperationsApiService.DirectMoveFile(request.IngestorRequest.ArchivePath, + request.DocumentFileName, + request.IngestorRequest.RootPath); + if (!response.IsSuccessful) + { + throw new Exception(string.Join("; ", response.MessageStack.ToArray())); + } + } + catch (Exception exception) + { + throw new ArchiveException($"Failure to unarchive document. Exception Message: {exception.Message}"); + } + } + + private async Task CreateAndQueueCompletionRequest(List requests) + { + var tasks = requests.Select(r => QueueCompletionRequest(r.CompletionRequest)); + + var results = await Task.WhenAll(tasks); + + var message = string.Join(Environment.NewLine, + results + .Where(r => !r.Success) + .Select(r => $"Failed to Queue Completion after UploadCompletion Failure. " + + $"DocumentProcessingInfoId: {r.CompletionRequest.ProcessingRequest.DocumentProcessingInfoId}, " + + $"DocumentFileName: {r.CompletionRequest.ProcessingRequest.DocumentFileName}.")); + + if (!string.IsNullOrEmpty(message)) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error(new Exception(), message); + } + } + + private async Task QueueCompletionRequest(CompletionRequest request) + { + try + { + await _queueCompletionService.QueueCompletionRequest(request.ProcessingRequest, request.ProcessResult); + return new QueueCompletionResult + { + Success = true, + CompletionRequest = request + }; + } + catch (Exception ex) + { + var errorMessage = $"Exception during CreateAndQueueCompletionRequest. ErrorMessage: {ex.Message}"; + Log.Warning(errorMessage); + return new QueueCompletionResult + { + Success = false, + CompletionRequest = request + }; + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestorRunInfoService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestorRunInfoService.cs new file mode 100644 index 0000000..8348efc --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/IngestorRunInfoService.cs @@ -0,0 +1,132 @@ +using System.Data.SqlClient; +using Serilog; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestorLib.Repositories; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +namespace LCU.API.Internal.DocumentIngestor.Services; + +public class IngestorRunInfoService : IIngestorRunInfoService +{ + private readonly IIngestorRunInfoRepository _ingestorRunInfoRepository; + private readonly IUnitOfWork _unitOfWork; + + public IngestorRunInfoService(IUnitOfWork unitOfWork, + IIngestorRunInfoRepository ingestorRunInfoRepository) + { + _ingestorRunInfoRepository = ingestorRunInfoRepository; + _unitOfWork = unitOfWork; + } + + public async Task GetByIdAsync(Guid ingestorRunInfoId) + { + try + { + var ingestorRunInfo = await _ingestorRunInfoRepository.FindByIdAsync(ingestorRunInfoId); + return ingestorRunInfo; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving IngestorRunInfo with IngestorRunInfoId {ingestorRunInfoId}."); + throw new ServiceException($"Failure retrieving IngestorRunInfo with IngestorRunInfoId {ingestorRunInfoId}."); + } + } + + public async Task> GetListByIdAsync(List ingestorRunInfoIds) + { + try + { + var ingestorRunInfos = await _ingestorRunInfoRepository.FindListByIdAsync(ingestorRunInfoIds); + return ingestorRunInfos; + } + catch (Exception exception) + { + + Log.Error(exception, $"Failure retrieving List of IngestorRunInfo with IngestorRunInfoIds: {string.Join(", ", ingestorRunInfoIds)}."); + throw new ServiceException($"Failure retrieving List of IngestorRunInfo with IngestorRunInfoIds: {string.Join(", ", ingestorRunInfoIds)}."); + } + } + + public IEnumerable FindByIngestionEndDateNotArchived(DateTime ingestionEndDate) + { + try + { + var ingestorRunInfo = _ingestorRunInfoRepository.FindByIngestionEndDateNotArchived(ingestionEndDate); + return ingestorRunInfo; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving IngestorRunInfo with IngestionEndDate {ingestionEndDate}."); + throw new ServiceException($"Failure retrieving IngestorRunInfo with IngestionEndDate {ingestionEndDate}."); + } + } + + public async Task SaveAsync(IngestorRunInfo ingestorRunInfo) + { + try + { + var result = await _ingestorRunInfoRepository.AddAsync(ingestorRunInfo); + await _unitOfWork.CompleteAsync(); + return result; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure saving IngestorRunInfo."); + throw new ServiceException($"Failure saving IngestorRunInfo."); + } + } + + public async Task Update(IngestorRunInfo ingestorRunInfo) + { + try + { + var existing = await GetByIdAsync(ingestorRunInfo.IngestorRunInfoId); + ArgumentNullException.ThrowIfNull(existing); + + existing.StartTimeStamp = ingestorRunInfo.StartTimeStamp; + existing.EndTimeStamp = ingestorRunInfo.EndTimeStamp; + existing.IngestorType = ingestorRunInfo.IngestorType; + existing.IndexFilePath = ingestorRunInfo.IndexFilePath; + existing.IndexFileName = ingestorRunInfo.IndexFileName; + existing.IndexTotal = ingestorRunInfo.IndexTotal; + existing.ArchiveTimeStamp = ingestorRunInfo.ArchiveTimeStamp; + existing.IngestionRunCount = ingestorRunInfo.IngestionRunCount; + + _ingestorRunInfoRepository.Update(existing); + _unitOfWork.Complete(); + + return existing; + } + catch (SqlException sqlException) + { + Log.Error(sqlException, $"SQL Failure updating IngestorRunInfo. IngestorRunInfo: {ingestorRunInfo.IngestorRunInfoId}"); + throw new ServiceException($"SQL Failure updating IngestorRunInfo. IngestorRunInfo: {ingestorRunInfo.IngestorRunInfoId}"); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure updating IngestorRunInfo. IngestorRunInfo: {ingestorRunInfo.IngestorRunInfoId}"); + throw new ServiceException($"Failure updating IngestorRunInfo. IngestorRunInfo: {ingestorRunInfo.IngestorRunInfoId}"); + } + } + + public async Task Delete(Guid ingestorRunInfoId) + { + try + { + var ingestorRunInfo = await _ingestorRunInfoRepository.FindByIdAsync(ingestorRunInfoId); + ArgumentNullException.ThrowIfNull(ingestorRunInfo); + _ingestorRunInfoRepository.Remove(ingestorRunInfo); + _unitOfWork.Complete(); + } + catch (SqlException sqlException) + { + Log.Error(sqlException, $"SQL failure removing IngestorRunInfo. IngestorRunInfoId: {ingestorRunInfoId}"); + throw new ServiceException($"SQL failure removing IngestorRunInfo. IngestorRunInfoId: {ingestorRunInfoId}"); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure removing IngestorRunInfo. IngestorRunInfoId: {ingestorRunInfoId}"); + throw new ServiceException($"Failure removing IngestorRunInfo. IngestorRunInfoId: {ingestorRunInfoId}"); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/AccountNotificationInfoDeterminingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/AccountNotificationInfoDeterminingService.cs new file mode 100644 index 0000000..4f2a73e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/AccountNotificationInfoDeterminingService.cs @@ -0,0 +1,78 @@ +using LCU.Api.Internal.DocumentIngestorLib.Extensions; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.Exceptions; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Services.MemberNotificationInfoDeterminingServices; + +public class AccountNotificationInfoDeterminingService : IAccountNotificationInfoDeterminingService +{ + private readonly ICoreApiWrapperService _coreApiWrapperService; + private readonly ApiConfiguration _apiConfiguration; + + public AccountNotificationInfoDeterminingService(ICoreApiWrapperService coreApiWrapperService, + ApiConfiguration apiConfiguration) + { + _coreApiWrapperService = coreApiWrapperService; + _apiConfiguration = apiConfiguration; + } + + public async Task> DetermineAccountOwnerNotificationInfos(string accountNumber) + { + try + { + var dateTimeNow = DateTime.Now.ConvertToTimeZone(_apiConfiguration.TimeZone); + var agreeUserAccounts = await _coreApiWrapperService.GetAgreeUsersByAccount(accountNumber); + if (agreeUserAccounts?.Count() > 1) + { + throw new Exception("More then one AgreeUserAccounts returned. Expected only one back."); + } + + var agreeUserAccount = agreeUserAccounts?.FirstOrDefault(); + if (IsMemberNumberOrNull(agreeUserAccount?.UserId)) + { + return new List() + { + new () + { + UploadDate = dateTimeNow, + NotificationStatusType = NotificationStatusTypes.Complete, + Attempts = 1 + } + }; + } + + var user = await _coreApiWrapperService.GetAgreementByUserId(agreeUserAccount?.UserId); + return new List() + { + new () + { + AgreeUserId = agreeUserAccount.UserId, + EntityName = user.OrganizationName == null ? user.FirstName : user.OrganizationName, + UploadDate = dateTimeNow, + NotificationStatusType = NotificationStatusTypes.Pending, + Attempts = 1 + } + }; + } + catch (Exception ex) + { + var message = $"Failure to Determine Account Owner Notification Info by accountNumber: {accountNumber}. Exception Message: {ex.Message}"; + Log.Error(message); + throw new ServiceException(message); + } + } + + private bool IsMemberNumberOrNull(string userId) + { + if (userId == null) + { + return true; + } + + return string.Equals(userId.Substring(0, 1), "M", StringComparison.OrdinalIgnoreCase); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/IAccountNotificationInfoDeterminingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/IAccountNotificationInfoDeterminingService.cs new file mode 100644 index 0000000..2b74277 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/IAccountNotificationInfoDeterminingService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.DocumentIngestorModels.Entities; +namespace LCU.API.Internal.DocumentIngestor.Services.MemberNotificationInfoDeterminingServices; + +public interface IAccountNotificationInfoDeterminingService +{ + Task> DetermineAccountOwnerNotificationInfos(string accountNumber); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/IMemberNotificationInfoDeterminingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/IMemberNotificationInfoDeterminingService.cs new file mode 100644 index 0000000..8d8d6b5 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/IMemberNotificationInfoDeterminingService.cs @@ -0,0 +1,10 @@ +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.MemberNotificationInfoDeterminingServices; + +public interface IMemberNotificationInfoDeterminingService +{ + Task> HandleMemberNotificationInfos(MemberNotificationInfoRequest memberNotificationInfoRequest); + Task<(string EmailAddress, DeliveryMethod DeliveryMethod)> DetermineDeliveryMethod(MemberNotificationInfo memberNotificationInfo); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/IPrimaryNotificationInfoDeterminingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/IPrimaryNotificationInfoDeterminingService.cs new file mode 100644 index 0000000..568b808 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/IPrimaryNotificationInfoDeterminingService.cs @@ -0,0 +1,9 @@ +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +namespace LCU.API.Internal.DocumentIngestor.Services.MemberNotificationInfoDeterminingServices; + +public interface IPrimaryNotificationInfoDeterminingService +{ + Task> DeterminePrimaryOwnerNotificationInfos(string entityNumber, + EntityTypes entityType); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/MemberNotificationInfoDeterminingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/MemberNotificationInfoDeterminingService.cs new file mode 100644 index 0000000..a58f056 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/MemberNotificationInfoDeterminingService.cs @@ -0,0 +1,109 @@ +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.DocumentType.Extensions; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Services.MemberNotificationInfoDeterminingServices; + +public class MemberNotificationInfoDeterminingService : IMemberNotificationInfoDeterminingService +{ + private readonly IAccountNotificationInfoDeterminingService _accountNotificationInfoDeterminingService; + private readonly IPrimaryNotificationInfoDeterminingService _primaryNotificationInfoDeterminingService; + private readonly IMemberNotificationInfoService _memberNotificationInfoService; + private readonly IMemberPreferencesApiService _memberPreferencesApiService; + private readonly IDocumentProcessingInfoService _documentProcessingInfoService; + + public MemberNotificationInfoDeterminingService(IAccountNotificationInfoDeterminingService accountNotificationInfoDeterminingService, + IPrimaryNotificationInfoDeterminingService primaryNotificationInfoDeterminingService, + IMemberNotificationInfoService memberNotificationInfoService, + IMemberPreferencesApiService memberPreferencesApiService, + IDocumentProcessingInfoService documentProcessingInfoService) + { + _accountNotificationInfoDeterminingService = accountNotificationInfoDeterminingService; + _primaryNotificationInfoDeterminingService = primaryNotificationInfoDeterminingService; + _memberNotificationInfoService = memberNotificationInfoService; + _memberPreferencesApiService = memberPreferencesApiService; + _documentProcessingInfoService = documentProcessingInfoService; + } + + public async Task> HandleMemberNotificationInfos(MemberNotificationInfoRequest memberNotificationInfoRequest) + { + if (memberNotificationInfoRequest.DocumentOwnerType == DocumentOwnerTypes.Generic) + { + return new List(); + } + + return await DetermineMemberNotificationInfos(memberNotificationInfoRequest); + } + + public async Task> DetermineMemberNotificationInfos(MemberNotificationInfoRequest memberNotificationInfoRequest) + { + var memberNotificationInfos = memberNotificationInfoRequest.DocumentOwnerType switch + { + DocumentOwnerTypes.PrimaryOwner => await _primaryNotificationInfoDeterminingService.DeterminePrimaryOwnerNotificationInfos(memberNotificationInfoRequest.DocumentEntityNumber, + memberNotificationInfoRequest.EntityType), + DocumentOwnerTypes.AccountOwner => await _accountNotificationInfoDeterminingService.DetermineAccountOwnerNotificationInfos(memberNotificationInfoRequest.DocumentEntityNumber), + _ => throw new NotImplementedException() + }; + + foreach (var memberNotificationInfo in memberNotificationInfos) + { + memberNotificationInfo.DocumentProcessingInfoId = memberNotificationInfoRequest.DocumentProcessingInfoId; + + var contact = await DetermineDeliveryMethod(memberNotificationInfo); + memberNotificationInfo.EmailAddress = contact.EmailAddress; + memberNotificationInfo.DeliveryMethod = contact.DeliveryMethod; + + if (memberNotificationInfo.DeliveryMethod == DeliveryMethod.Paper) + { + memberNotificationInfo.NotificationStatusType = NotificationStatusTypes.Complete; + } + } + + return memberNotificationInfos; + } + + public async Task<(string EmailAddress, DeliveryMethod DeliveryMethod)> DetermineDeliveryMethod(MemberNotificationInfo memberNotificationInfo) + { + try + { + (string, DeliveryMethod) DeliveryMethodFactory(string? email, string? deliveryMethod) + { + var preference = deliveryMethod?.GetValueFromName() ?? DeliveryMethod.Paper; + + return preference == DeliveryMethod.Electronic && !string.IsNullOrEmpty(email) + ? (email, DeliveryMethod.Electronic) + : (string.Empty, DeliveryMethod.Paper); + } + + if (string.IsNullOrWhiteSpace(memberNotificationInfo.AgreeUserId)) + { + return DeliveryMethodFactory(null, null); + } + + var memberOptInSettings = (await _memberPreferencesApiService.GetMemberOptInSettingsByUserId(memberNotificationInfo.AgreeUserId)).MemberOptinSettings; + if (memberOptInSettings is null) + { + return DeliveryMethodFactory(null, null); + } + if (memberOptInSettings.UniversalOptIn is not null) + { + return DeliveryMethodFactory(memberOptInSettings.UnifiedOptInEmail, memberOptInSettings.UniversalOptIn); + } + + var documentProcessingInfo = await _documentProcessingInfoService.GetByIdAsync(memberNotificationInfo.DocumentProcessingInfoId); + return documentProcessingInfo.DocumentType is "Statement" + ? DeliveryMethodFactory(memberOptInSettings.EStatementsEmail, memberOptInSettings.EStatements) + : DeliveryMethodFactory(memberOptInSettings.ENotificationsEmail, memberOptInSettings.ENotifications); + } + catch (Exception exception) + { + var message = $"Failure DeterminingDeliveryMethod for MemberNotificationInfo with Id:{memberNotificationInfo.MemberNotificationInfoId}."; + Log.Error(exception, message); + throw new ServiceException(message); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/PrimaryNotificationInfoDeterminingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/PrimaryNotificationInfoDeterminingService.cs new file mode 100644 index 0000000..1abcc70 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoDeterminingServices/PrimaryNotificationInfoDeterminingService.cs @@ -0,0 +1,109 @@ +using LCU.Api.Internal.DocumentIngestorLib.Extensions; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.Exceptions; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Services.MemberNotificationInfoDeterminingServices; + +public class PrimaryNotificationInfoDeterminingService : IPrimaryNotificationInfoDeterminingService +{ + + private readonly ICoreApiWrapperService _coreApiWrapperService; + private readonly ApiConfiguration _apiConfiguration; + + public PrimaryNotificationInfoDeterminingService(ICoreApiWrapperService coreApiWrapperService, + ApiConfiguration apiConfiguration) + { + _coreApiWrapperService = coreApiWrapperService; + _apiConfiguration = apiConfiguration; + } + + public async Task> DeterminePrimaryOwnerNotificationInfos(string entityNumber, + EntityTypes entityType) + { + try + { + var dateTimeNow = DateTime.Now.ConvertToTimeZone(_apiConfiguration.TimeZone); + var userIds = await GetUserIdsByEntityType(entityNumber, entityType); + + var memberNotificationInfos = new List(); + if (userIds is null || !userIds.Any()) + { + return new List + { + new() + { + UploadDate = dateTimeNow, + NotificationStatusType = NotificationStatusTypes.Complete, + Attempts = 1 + } + }; + } + + foreach (var userId in userIds) + { + var user = await _coreApiWrapperService.GetAgreementByUserId(userId); + if (user is null) + { + memberNotificationInfos.Add( new MemberNotificationInfo + { + UploadDate = dateTimeNow, + NotificationStatusType = NotificationStatusTypes.Complete, + Attempts = 1 + }); + + continue; + } + + memberNotificationInfos.Add( new MemberNotificationInfo() + { + AgreeUserId = userId, + EntityName = user.OrganizationName ?? user.FirstName, + UploadDate = dateTimeNow, + NotificationStatusType = NotificationStatusTypes.Pending, + Attempts = 1 + }); + } + + return memberNotificationInfos.ToList(); + } + catch (Exception ex) + { + var message = $"Failure to Determine Primary Owner Notification Info by entityNumber: {entityNumber}. Exception Message: {ex.Message}"; + Log.Error(message); + throw new ServiceException(message); + } + } + + private async Task> GetUserIdsByEntityType(string entityNumber, EntityTypes entityType) + { + var userIds = new List(); + if (entityType == EntityTypes.Person) + { + var result = await _coreApiWrapperService.GetAgreeUsersByPersonNumber(entityNumber); + + var ids = result?.Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); + if (ids is null || !ids.Any()) + { + return new List(); + } + + return ids; + } + else if (entityType == EntityTypes.Organization) + { + var result = await _coreApiWrapperService.GetAgreeUserByOrganizationNumber(entityNumber); + + if (string.IsNullOrWhiteSpace(result)) + { + return new List(); + } + + userIds = new List() { result }; + } + return userIds; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoService.cs new file mode 100644 index 0000000..053ee43 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MemberNotificationInfoService.cs @@ -0,0 +1,284 @@ +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestorLib.Repositories; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using Serilog; +using System.Data.SqlClient; + +namespace LCU.API.Internal.DocumentIngestor.Services; + +public class MemberNotificationInfoService : IMemberNotificationInfoService +{ + private readonly IUnitOfWork _unitOfWork; + private readonly ApiConfiguration _apiConfiguration; + private readonly IMemberNotificationInfoRepository _memberNotificationInfoRepository; + private readonly IProcessingLogService _processingLogService; + + public MemberNotificationInfoService + ( + IUnitOfWork unitOfWork, + ApiConfiguration apiConfiguration, + IMemberNotificationInfoRepository memberNotificationInfoRepository, + IProcessingLogService processingLogService + ) + { + _unitOfWork = unitOfWork; + _apiConfiguration = apiConfiguration; + _memberNotificationInfoRepository = memberNotificationInfoRepository; + _processingLogService = processingLogService; + } + + public async Task> GetAsync() + { + try + { + var memberNotificationInfos = await _memberNotificationInfoRepository.FindAsync(); + return memberNotificationInfos; + } + catch (Exception exception) + { + Log.Error(exception, "Failure retrieving MemberNotificationInfos."); + throw new ServiceException("Failure retrieving MemberNotificationInfos."); + } + } + + public async Task GetByIdAsync(int id) + { + try + { + var memberNotificationInfo = await _memberNotificationInfoRepository.FindByIdAsync(id); + return memberNotificationInfo; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving MemberNotificationInfo with MemberNotificationInfoId {id}."); + throw new ServiceException($"Failure retrieving MemberNotificationInfo with MemberNotificationInfoId {id}."); + } + } + + public async Task> GetListByIdAsync(List ids) + { + try + { + var memberNotificationInfo = await _memberNotificationInfoRepository.FindListByIdAsync(ids); + return memberNotificationInfo; + } + catch (Exception exception) + { + var message = $"Failure retrieving list of MemberNotificationInfos with MemberNotificationInfoIds: {String.Join(", ", ids.ToArray())}."; + Log.Error(exception, message); + throw new ServiceException(message); + } + } + + public async Task> GetByDocumentProcessingInfoIdAsync(int documentProcessingInfoId) + { + try + { + var memberNotificationInfos = await _memberNotificationInfoRepository.FindByDocumentProcessingInfoIdAsync(documentProcessingInfoId); + return memberNotificationInfos; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving MemberNotificationInfos with DocumentProcessingInfoId {documentProcessingInfoId}."); + throw new ServiceException($"Failure retrieving MemberNotificationInfos with DocumentProcessingInfoId {documentProcessingInfoId}."); + } + } + + public async Task> GetByNotificationStatusAsync(NotificationStatusTypes status) + { + try + { + var memberNotificationInfos = await _memberNotificationInfoRepository.FindByNotificationStatusAsync(status); + return memberNotificationInfos; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving MemberNotificationInfos by Status. Status: {status}"); + throw new ServiceException("Failure retrieving MemberNotificationInfos."); + } + } + + public async Task> GetSendableMemberNotificationInfosAsync(DateTime minimumUploadDate, int maxAttempts) + { + try + { + var memberNotificationInfos = await _memberNotificationInfoRepository.FindSendableMemberNotificationsAsync(minimumUploadDate, maxAttempts); + return memberNotificationInfos; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving Sendable MemberNotificationInfos. MinimumUploadDate: {minimumUploadDate} | MaxAttempts: {maxAttempts}"); + throw new ServiceException($"Failure retrieving MemberNotificationInfos."); + } + } + + public async Task SaveAsync(MemberNotificationInfo memberNotificationInfo) + { + try + { + var result = await _memberNotificationInfoRepository.AddAsync(memberNotificationInfo); + await _unitOfWork.CompleteAsync(); + return result; + } + catch (Exception exception) + { + Log.Error(exception, "Failure saving MemberNotificationInfo."); + throw new ServiceException("Failure saving MemberNotificationInfo."); + } + } + + public async Task SaveListAsync(List memberNotificationInfos) + { + try + { + await _memberNotificationInfoRepository.AddListAsync(memberNotificationInfos); + await _unitOfWork.CompleteAsync(); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure saving list of MemberNotificationInfo."); + throw new ServiceException($"Failure saving list MemberNotificationInfo."); + } + } + + public async Task Update(MemberNotificationInfo memberNotificationInfo) + { + try + { + _memberNotificationInfoRepository.Update(memberNotificationInfo); + await _unitOfWork.CompleteAsync(); + + return memberNotificationInfo; + } + catch (SqlException sqlException) + { + Log.Error(sqlException, "SQL Failure updating MemberNotificationInfo. " + + $"MemberNotificationInfoId: {memberNotificationInfo.MemberNotificationInfoId}"); + throw new ServiceException("SQL Failure updating MemberNotificationInfo. " + + $"MemberNotificationInfoId: {memberNotificationInfo.MemberNotificationInfoId}"); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure updating MemberNotificationInfo. " + + $"MemberNotificationInfoId: {memberNotificationInfo.MemberNotificationInfoId}"); + throw new ServiceException($"Failure updating MemberNotificationInfo. " + + $"MemberNotificationInfoId: {memberNotificationInfo.MemberNotificationInfoId}"); + } + } + + public async Task> UpdateRange(IEnumerable memberNotificationInfos) + { + try + { + _memberNotificationInfoRepository.UpdateRange(memberNotificationInfos); + await _unitOfWork.CompleteAsync(); + + return memberNotificationInfos; + } + catch (SqlException sqlException) + { + Log.Error(sqlException, "SQL Failure updating list of MemberNotificationInfos."); + throw new ServiceException("SQL Failure updating list of MemberNotificationInfos."); + } + catch (Exception exception) + { + Log.Error(exception, "Failure updating list of MemberNotificationInfos."); + throw new ServiceException("Failure updating list of MemberNotificationInfos."); + } + } + + public async Task Delete(int id) + { + try + { + var memberNotificationInfo = await GetByIdAsync(id); + ArgumentNullException.ThrowIfNull(memberNotificationInfo); + _memberNotificationInfoRepository.Remove(memberNotificationInfo); + _unitOfWork.Complete(); + } + catch (SqlException sqlException) + { + Log.Error(sqlException, $"SQL failure removing MemberNotificationInfo. MemberNotificationInfoId: {id}"); + throw new ServiceException($"SQL failure removing MemberNotificationInfo. MemberNotificationInfoId: {id}"); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure removing MemberNotificationInfo. MemberNotificationInfoId: {id}"); + throw new ServiceException($"Failure removing MemberNotificationInfo. MemberNotificationInfoId: {id}"); + } + } + + public async Task SetDocumentNotificationStatus(int memberNotificationInfoId, NotificationStatusTypes notificationStatus, string userName, string reason) + { + try + { + var memberNotificationInfo = await GetByIdAsync(memberNotificationInfoId); + if (memberNotificationInfo is null) return false; + + var originalStatus = memberNotificationInfo.NotificationStatusType; + + memberNotificationInfo.NotificationStatusType = notificationStatus; + await Update(memberNotificationInfo); + + var processingLog = new ProcessingLog(memberNotificationInfo.DocumentProcessingInfoId, DateTime.UtcNow, + $"Updated notification status for MemberNotificationInfoId: {memberNotificationInfoId} from {originalStatus} to {notificationStatus} because {reason}", userName); + await _processingLogService.SaveAsync(processingLog); + + return true; + } + catch (Exception exception) + { + var message = $"Failure setting notification status for MemberNotificationInfoId: {memberNotificationInfoId} to {notificationStatus.ToString()}."; + Log.Error(exception, message); + throw new ServiceException(message); + } + } + + public async Task BulkSetDocumentNotificationStatus(BulkNotificationStatusRequest request, string userName) + { + try + { + var memberNotificationInfos = + await _memberNotificationInfoRepository.GetMemberNotificationInfosByFilter(request.Filter); + + var memberNotificationInfosChunks = memberNotificationInfos.Chunk(_apiConfiguration.BatchSkipAmount); + foreach (var memberNotificationInfoChunk in memberNotificationInfosChunks) + { + var listClone = memberNotificationInfoChunk.Select(x => + new MemberNotificationInfo() + { + MemberNotificationInfoId = x.MemberNotificationInfoId, + DocumentProcessingInfoId = x.DocumentProcessingInfoId, + NotificationStatusType = x.NotificationStatusType + }).ToList(); + + var processingLogs = listClone.Select(x => new ProcessingLog(x.DocumentProcessingInfoId, DateTime.UtcNow, + $"Bulk notification status update for MemberNotificationId: {x.MemberNotificationInfoId} " + + $"from {x.NotificationStatusType} to {request.NotificationStatus} because {request.ReasonMessage}", + userName)); + + foreach (var memberNotificationInfo in memberNotificationInfoChunk) + { + if (memberNotificationInfo == null) continue; + memberNotificationInfo.NotificationStatusType = request.NotificationStatus; + } + + _memberNotificationInfoRepository.UpdateRange(memberNotificationInfoChunk); + await _unitOfWork.CompleteAsync(); + + await _processingLogService.SaveRangeAsync(processingLogs); + } + + return true; + } + catch (Exception exception) + { + var message = $"Failure on bulk update of notification status to {request.NotificationStatus.ToString()}."; + Log.Error(exception, message); + throw new ServiceException(message); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/CoreApiWrapperService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/CoreApiWrapperService.cs new file mode 100644 index 0000000..0139e90 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/CoreApiWrapperService.cs @@ -0,0 +1,182 @@ +using Serilog; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Tax; +using LCU.API.Internal.DocumentIngestor.DataAccess; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Persons; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Organizations; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Mixed; + +namespace LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; + +public class CoreApiWrapperService : ICoreApiWrapperService +{ + private readonly ICoreApiWrapperDao _coreApiWrapperDao; + + public CoreApiWrapperService(ICoreApiWrapperDao coreApiWrapperDao) + { + _coreApiWrapperDao = coreApiWrapperDao; + } + + public async Task> GetPersonsTaxIdData(string taxId) + { + try + { + return await _coreApiWrapperDao.GetPersonsTaxIdData(taxId); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure Get Persons TaxId Data From CoreApiWrapper. TaxId: {taxId}"); + throw new ServiceException($"Failure Get Persons TaxId Data From CoreApiWrapper. TaxId: {taxId}, Exception Message: {exception.Message}"); + } + } + + public async Task> GetOrganizationsTaxIdData(string taxId) + { + try + { + return await _coreApiWrapperDao.GetOrganizationsTaxIdData(taxId); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure Get Organizations TaxId Data From CoreApiWrapper. TaxId: {taxId}"); + throw new ServiceException($"Failure Get Organizations TaxId Data From CoreApiWrapper. TaxId: {taxId}, Exception Message: {exception.Message}"); + } + } + + public async Task> GetOwnersByAccountNumber(string accountNumber, string creationDate) + { + try + { + return await _coreApiWrapperDao.GetOwnersByAccountNumber(accountNumber, creationDate); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure Get Owners By Account Number From CoreApiWrapper. AccountNumber: {accountNumber} | CreationDate: {creationDate}"); + throw new ServiceException($"Failure Get Owners By Account Number From CoreApiWrapper. AccountNumber: {accountNumber} | CreationDate: {creationDate}, Exception Message: {exception.Message}"); + } + } + + public async Task> GetOwnersByOrganizationName(string organizationName) + { + try + { + return await _coreApiWrapperDao.GetOwnersByOrganizationName(organizationName); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure Get Owners By Organization Name From CoreApiWrapper. OrganizationName: {organizationName}"); + throw new ServiceException($"Failure Get Owners By Organization Name From CoreApiWrapper. OrganizationName: {organizationName}, Exception Message: {exception.Message}"); + } + } + + public async Task> GetOwnersByPersonName(string personName) + { + try + { + return await _coreApiWrapperDao.GetOwnersByPersonName(personName); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure Get Owners By Person Name From CoreApiWrapper. PersonName: {personName}"); + throw new ServiceException($"Failure Get Owners By Person Name From CoreApiWrapper. PersonName: {personName}, Exception Message: {exception.Message}"); + } + } + + public async Task?> GetAgreeUsersByAccount(string accountNumber) + { + try + { + return await _coreApiWrapperDao.GetAgreeUsersByAccount(accountNumber); + } + catch (Exception exception) + { + var message = $"Failure Get Agree Users By AccountNumber From CoreApiWrapper. AccountNumber: {accountNumber}"; + Log.Error(exception, message); + throw new ServiceException($"{message}, Exception Message: {exception.Message}"); + } + } + + public async Task?> GetAgreeUsersByPersonNumber(string personNumber) + { + try + { + return await _coreApiWrapperDao.GetAgreeUsersByPersonNumber(personNumber); + } + catch (Exception exception) + { + var message = $"Failure Get Agree Users By Person Number From CoreApiWrapper. PersonNumber: {personNumber}"; + Log.Error(exception, message); + throw new ServiceException($"{message}, Exception Message: {exception.Message}"); + } + } + + public async Task GetAgreeUserByOrganizationNumber(string organizationNumber) + { + try + { + return await _coreApiWrapperDao.GetAgreeUserByOrganizationNumber(organizationNumber); + } + catch (Exception exception) + { + var message = $"Failure Get Agree User By Organization Number From CoreApiWrapper. OrganizationNumber: {organizationNumber}"; + Log.Error(exception, message); + throw new ServiceException($"{message}, Exception Message: {exception.Message}"); + } + } + + public async Task GetAgreementByUserId(string userId) + { + try + { + return await _coreApiWrapperDao.GetAgreementByUserId(userId); + } + catch (Exception exception) + { + var message = $"Failure Get Agree User By UserId From CoreApiWrapper. UserId: {userId}"; + Log.Error(exception, message); + throw new ServiceException($"{message}, Exception Message: {exception.Message}"); + } + } + + public async Task GetAgreementAccountByAccountId(string accountId) + { + try + { + return await _coreApiWrapperDao.GetAgreementAccountByAccountId(accountId); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure Get Agreement Account By Account Id From CoreApiWrapper. AccountId: {accountId}"); + throw new ServiceException($"Failure Get Agreement Account By Account Id From CoreApiWrapper. AccountId: {accountId}, Exception Message: {exception.Message}"); + } + } + + public async Task?> GetAgreementAccountsByUserId(string userId) + { + try + { + return await _coreApiWrapperDao.GetAgreementAccountsByUserId(userId); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure Get Agreement Account By User Id From CoreApiWrapper. UserId: {userId}"); + throw new ServiceException($"Failure Get Agreement Account By User Id From CoreApiWrapper. UserId: {userId}, Exception Message: {exception.Message}"); + } + } + + public async Task GetPersonOrOrganizationNumberByMemberId(string memberId) + { + try + { + return await _coreApiWrapperDao.GetPersonOrOrganizationNumberByMemberId(memberId); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure Get PersonOrganization By Member Id From CoreApiWrapper. MemberId: {memberId}"); + throw new ServiceException($"Failure Get PersonOrganization By Member Id From CoreApiWrapper. MemberId: {memberId}, Exception Message: {exception.Message}"); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/DocumentTypeRetrieverService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/DocumentTypeRetrieverService.cs new file mode 100644 index 0000000..9c6cd05 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/DocumentTypeRetrieverService.cs @@ -0,0 +1,156 @@ +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.DataAccess; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Extensions; +using LCU.Library.DocumentType.Models.Requests; +using LCU.Library.DocumentType.Models.Responses; +using LCU.Library.DocumentType.Models.Responses.External; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; + +public class DocumentTypeRetrieverService : IDocumentTypeRetrieverService +{ + private readonly IDocumentTypeRetrieverDao _documentTypeRetrieverDao; + private const string _unknown = "Unknown"; + + public DocumentTypeRetrieverService(IDocumentTypeRetrieverDao documentTypeRetrieverDao) + { + _documentTypeRetrieverDao = documentTypeRetrieverDao; + } + + public async Task GetDocumentCodeDetail(string documentCode) + { + try + { + return await _documentTypeRetrieverDao.GetDocumentCodeDetail(documentCode); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure To Get DocumentCodeDetail By DocumentCode From DocumentTypeRetriever. DocumentCode: {documentCode}"); + throw new ServiceException($"Failure To Get DocumentCodeDetail By DocumentCode From DocumentTypeRetriever. DocumentCode: {documentCode} | " + + $"Exception Message: {exception.Message}"); + } + } + + public async Task> GetDocumentCodeDetails() + { + try + { + return await _documentTypeRetrieverDao.GetDocumentCodeDetails(); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure To Get DocumentCodeDetails From DocumentTypeRetriever."); + throw new ServiceException($"Failure To Get DocumentCodeDetails From DocumentTypeRetriever. Exception Message: {exception.Message}"); + } + } + + public async Task GetDocumentCodeDetailByDisplayName(string documentTypeDisplayName) + { + try + { + var documentCodeDetails = await _documentTypeRetrieverDao.GetDocumentCodeDetailsCache(); + var documentCodeDetail = documentCodeDetails? + .Where(x => x.DocumentCode == documentTypeDisplayName.TranslateDocumentCode()) + .FirstOrDefault(); + + if (documentCodeDetail == null) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error($"Failure Get Document Code Detail. DocumentTypeDisplayName: {documentTypeDisplayName}"); + + return new DocumentCodeDetailInfo() + { + DocumentType = _unknown, + DocumentBusinessName = _unknown, + DocumentMemberFacingName = _unknown + }; + } + + return new DocumentCodeDetailInfo() + { + DocumentType = Enum.GetName(typeof(DocumentTypes), documentCodeDetail.DocumentType), + DocumentBusinessName = documentCodeDetail.DocumentBusinessName, + DocumentMemberFacingName = documentCodeDetail.DocumentMemberFacingName + }; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure To Get DocumentCodeDetails By DocumentCode From DocumentTypeRetriever. " + + $"DocumentTypeDisplayName: {documentTypeDisplayName}"); + throw new ServiceException($"Failure To Get DocumentCodeDetails By DocumentCode From DocumentTypeRetriever. " + + $"DocumentTypeDisplayName: {documentTypeDisplayName} | Exception Message: {exception.Message}"); + } + } + + public async Task GetDocumentCodeDetailByBusinessName(string documentBusinessName) + { + try + { + var documentCodeDetails = await _documentTypeRetrieverDao.GetDocumentCodeDetailsCache(); + var documentCodeDetail = documentCodeDetails? + .Where(x => x.DocumentBusinessName == documentBusinessName) + .FirstOrDefault(); + + if (documentCodeDetail == null) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error($"Failure Get Document Code Detail. DocumentBusinessName: {documentBusinessName}"); + + return new DocumentCodeDetailInfo() + { + DocumentType = _unknown, + DocumentBusinessName = _unknown, + DocumentMemberFacingName = _unknown + }; + } + + return new DocumentCodeDetailInfo() + { + DocumentType = Enum.GetName(typeof(DocumentTypes), documentCodeDetail.DocumentType), + DocumentBusinessName = documentCodeDetail.DocumentBusinessName, + DocumentMemberFacingName = documentCodeDetail.DocumentMemberFacingName + }; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure To Get DocumentCodeDetails By DocumentBusinessName From DocumentTypeRetriever. " + + $"DocumentBusinessName: {documentBusinessName}"); + throw new ServiceException($"Failure To Get DocumentCodeDetails By DocumentBusinessName From DocumentTypeRetriever. " + + $"DocumentBusinessName: {documentBusinessName} | Exception Message: {exception.Message}"); + } + } + + public async Task> GetListOfMaliciousDocuments(MaliciousDocumentSearchFilter filter) + { + try + { + return await _documentTypeRetrieverDao.GetListOfMaliciousDocuments(filter); + } + catch (Exception exception) + { + Log.Error(exception, "Failure To Get List of MaliciousDocuments From DocumentTypeRetriever."); + throw new ServiceException($"Failure To Get List of MaliciousDocuments From DocumentTypeRetriever. Exception Message: {exception.Message}"); + } + } + + public async Task GetDocumentInformationById(Guid documentId) + { + try + { + return await _documentTypeRetrieverDao.GetDocumentInformationById(documentId); + } + catch (Exception exception) + { + var message = + $"Failure to get DocumentInformation with DocumentId ({documentId}) from DocumentTypeRetriever."; + Log.Error(exception, message); + throw new ServiceException($"{message} Exception Message: {exception.Message}"); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/DocumentTypeUploaderApiService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/DocumentTypeUploaderApiService.cs new file mode 100644 index 0000000..adfd232 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/DocumentTypeUploaderApiService.cs @@ -0,0 +1,171 @@ +using Serilog; +using Newtonsoft.Json; +using LCU.Library.Internal.Exceptions; +using LCU.Library.DocumentType.Models.Requests.PrimaryOwner; +using LCU.Library.DocumentType.Models.Requests.Account; +using LCU.Library.DocumentType.Models.Requests.Generic; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.DataAccess; +using LCU.Library.Internal.LcuMassTransitModels; +using LCU.Library.Internal.ApiResponse.Models; + +namespace LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; + +public class DocumentTypeUploaderApiService : IDocumentTypeUploaderApiService +{ + private readonly IDocumentTypeUploaderApiDao _documentTypeUploaderApiDao; + private readonly ConnectionConfiguration _connectionConfiguration; + private readonly ReceiveEndpointConfiguration _uploadCompletionReceiveEndpointConfiguration; + + public DocumentTypeUploaderApiService(IDocumentTypeUploaderApiDao documentTypeUploaderApiDao, + ConnectionConfiguration connectionConfiguration, + ReceiveEndpointConfigurations receiveEndpointConfigurations) + { + _documentTypeUploaderApiDao = documentTypeUploaderApiDao; + _connectionConfiguration = connectionConfiguration; + _uploadCompletionReceiveEndpointConfiguration = receiveEndpointConfigurations.UploadCompletionEndpoint; + } + + public async Task UploadPrimaryOwnerDocument(PrimaryOwnerDocumentRequest primaryOwnerDocumentRequest, + ProcessingRequest request, + ProcessResult result) + { + try + { + var isPersonEntityType = !string.IsNullOrEmpty(primaryOwnerDocumentRequest.PrimaryOwnerAttribute.PersonNumber); + var documentEntityNumber = isPersonEntityType ? + primaryOwnerDocumentRequest.PrimaryOwnerAttribute.PersonNumber : + primaryOwnerDocumentRequest.PrimaryOwnerAttribute.OrganizationNumber; + var entityType = isPersonEntityType ? EntityTypes.Person : EntityTypes.Organization; + + var completionRequest = new CompletionRequest + { + ProcessingRequest = request, + ProcessResult = result, + MemberNotificationInfoRequest = new MemberNotificationInfoRequest + { + DocumentProcessingInfoId = request.DocumentProcessingInfoId, + DocumentOwnerType = DocumentOwnerTypes.PrimaryOwner, + DocumentEntityNumber = documentEntityNumber, + EntityType = entityType + } + }; + + primaryOwnerDocumentRequest.ResponseItems = new List + { + new ResponseItem() + { + ResponsePayload = JsonConvert.SerializeObject(completionRequest), + ReturnQueueConnectionConfig = new QueueConnectionConfig() + { + Url = _connectionConfiguration.HostUrl, + Username = _connectionConfiguration.UserName, + Password = _connectionConfiguration.Password + }, + ReturnQueueConsumerConfig = new QueueConsumerConfig() + { + ExchangeName = _uploadCompletionReceiveEndpointConfiguration.ReceiveEndpoint + } + } + }; + + await _documentTypeUploaderApiDao.UploadPrimaryOwnerDocument(primaryOwnerDocumentRequest); + } + catch (Exception exception) + { + Log.Error(exception, "Failure Primary Owner Document Upload."); + throw new ServiceException($"Failure during Primary Owner Document Upload. Exception Message: {exception.Message}"); + } + } + + public async Task UploadAccountDocument(AccountDocumentRequest accountDocumentRequest, + ProcessingRequest request, + ProcessResult result) + { + try + { + var completionRequest = new CompletionRequest + { + ProcessingRequest = request, + ProcessResult = result, + MemberNotificationInfoRequest = new MemberNotificationInfoRequest + { + DocumentProcessingInfoId = request.DocumentProcessingInfoId, + DocumentOwnerType = DocumentOwnerTypes.AccountOwner, + DocumentEntityNumber = accountDocumentRequest.AccountAttribute.AccountNumber, + EntityType = EntityTypes.Unknown + } + }; + + accountDocumentRequest.ResponseItems = new List + { + new ResponseItem() + { + ResponsePayload = JsonConvert.SerializeObject(completionRequest), + ReturnQueueConnectionConfig = new QueueConnectionConfig() + { + Url = _connectionConfiguration.HostUrl, + Username = _connectionConfiguration.UserName, + Password = _connectionConfiguration.Password + }, + ReturnQueueConsumerConfig = new QueueConsumerConfig() + { + ExchangeName = _uploadCompletionReceiveEndpointConfiguration.ReceiveEndpoint + } + } + }; + await _documentTypeUploaderApiDao.UploadAccountDocument(accountDocumentRequest); + } + catch (Exception exception) + { + Log.Error(exception, "Failure Account Document Upload."); + throw new ServiceException($"Failure during Account Document Upload. Exception Message: {exception.Message}"); + } + } + + public async Task UploadGenericDocument(GenericDocumentRequest genericDocumentRequest, + ProcessingRequest request, + ProcessResult result) + { + try + { + var completionRequest = new CompletionRequest + { + ProcessingRequest = request, + ProcessResult = result, + MemberNotificationInfoRequest = new MemberNotificationInfoRequest + { + DocumentProcessingInfoId = request.DocumentProcessingInfoId, + DocumentOwnerType = DocumentOwnerTypes.Generic + } + }; + + genericDocumentRequest.ResponseItems = new List + { + new ResponseItem() + { + ResponsePayload = JsonConvert.SerializeObject(completionRequest), + ReturnQueueConnectionConfig = new QueueConnectionConfig() + { + Url = _connectionConfiguration.HostUrl, + Username = _connectionConfiguration.UserName, + Password = _connectionConfiguration.Password + }, + ReturnQueueConsumerConfig = new QueueConsumerConfig() + { + ExchangeName = _uploadCompletionReceiveEndpointConfiguration.ReceiveEndpoint + } + } + }; + + await _documentTypeUploaderApiDao.UploadGenericDocument(genericDocumentRequest); + } + catch (Exception exception) + { + Log.Error(exception, "Failure Generic Document Upload."); + throw new ServiceException($"Failure during Generic Document Upload. Exception Message: {exception.Message}"); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/FileOperationsApiService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/FileOperationsApiService.cs new file mode 100644 index 0000000..1fd29eb --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/FileOperationsApiService.cs @@ -0,0 +1,321 @@ +using Serilog; +using Newtonsoft.Json; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.DataAccess; +using LCU.Library.Internal.FileOperationsModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; + +public class FileOperationsApiService : IFileOperationsApiService +{ + private readonly IFileOperationsApiDao _fileOperationsApiDao; + + public FileOperationsApiService(IFileOperationsApiDao fileOperationsApiDao) + { + _fileOperationsApiDao = fileOperationsApiDao; + } + + public async Task DirectMoveFile(string sourcePath, string sourceFile, string destinationPath) + { + try + { + var moveFileRequest = new MoveFileRequest + { + SourcePath = sourcePath, + SourceFile = sourceFile, + DestinationPath = destinationPath + }; + return await _fileOperationsApiDao.DirectMoveFile(moveFileRequest); + } + catch (Exception exception) + { + var error = $"Failure during MoveFile. Exception Message: {exception.Message}"; + Log.Error(error); + throw new ServiceException(error); + } + } + + public async Task DirectWriteFile(string fileName, string extension, string fileData, string destinationPath) + { + try + { + var writeFileRequest = new WriteFileRequest + { + FileName = fileName, + Extension = extension, + FileData = fileData, + DestinationPath = destinationPath + }; + return await _fileOperationsApiDao.DirectWriteFile(writeFileRequest); + } + catch (Exception exception) + { + var error = $"Failure during WriteFile. Exception Message: {exception.Message}"; + Log.Error(error); + throw new ServiceException(error); + } + } + + public async Task DirectCreateDirectory(string directoryPath, string directoryName) + { + try + { + var createDirectoryRequest = new CreateDirectoryRequest + { + DirectoryPath = directoryPath, + DirectoryName = directoryName + }; + return await _fileOperationsApiDao.DirectCreateDirectory(createDirectoryRequest); + } + catch (Exception exception) + { + var error = $"Failure during CreateDirectory. Exception Message: {exception.Message}"; + Log.Error(error); + throw new ServiceException(error); + } + } + + + public async Task DirectUnzipFile(string sourceDirectory, + string zipFileName, + string destinationPath, + bool useZipFileNameAsFinalDestination) + { + try + { + var unzipFileRequest = new UnzipFileRequest + { + SourceDirectory = sourceDirectory, + ZipFileName = zipFileName, + DestinationPath = destinationPath, + UseZipFileNameAsFinalDestination = useZipFileNameAsFinalDestination + }; + return await _fileOperationsApiDao.DirectUnzipFile(unzipFileRequest); + } + catch (Exception exception) + { + var error = $"Failure during UnzipFile. Exception Message: {exception.Message}"; + Log.Error(error); + throw new ServiceException(error); + } + } + + public async Task DirectZipDirectory(string sourceDirectory, string zipPath, string zipFileName) + { + try + { + var zipDirectoryRequest = new ZipDirectoryRequest + { + SourceDirectory = sourceDirectory, + ZipPath = zipPath, + ZipFileName = zipFileName + }; + return await _fileOperationsApiDao.DirectZipDirectory(zipDirectoryRequest); + } + catch (Exception exception) + { + var error = $"Failure during ZipDirectory. Exception Message: {exception.Message}"; + Log.Error(error); + throw new ServiceException(error); + } + } + + public async Task DirectDeleteDirectory(string directoryName, string directoryRootPath, int maxAmountOfDirectories) + { + try + { + var deleteDirectoryRequest = new DeleteDirectoryRequest + { + DirectoryName = directoryName, + DirectoryRootPath = directoryRootPath, + MaxAmountOfDirectories = maxAmountOfDirectories, + Recursive = true + }; + return await _fileOperationsApiDao.DirectDeleteDirectory(deleteDirectoryRequest); + } + catch (Exception exception) + { + var error = $"Failure during DeleteDirectory. Exception Message: {exception.Message}"; + Log.Error(error); + throw new ServiceException(error); + } + } + + public async Task DirectDeleteFile(string sourcePath, string sourceFile) + { + try + { + var deleteFileRequest = new DeleteFileRequest + { + SourcePath = sourcePath, + SourceFile = sourceFile + }; + return await _fileOperationsApiDao.DirectDeleteFile(deleteFileRequest); + } + catch (Exception exception) + { + var error = $"Failure during DeleteFile. Exception Message: {exception.Message}"; + Log.Error(error); + throw new ServiceException(error); + } + } + + public async Task GetFileContent(string filePath) + { + try + { + return await _fileOperationsApiDao.GetFileContent(filePath); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure to Get File Content. FilePath: {filePath}"); + throw new ServiceException($"Failure to Get File Content. FilePath: {filePath}. " + + $"Exception Message: {exception.Message}"); + } + } + + public async Task GetPdfByteContent(string filePath) + { + try + { + return await _fileOperationsApiDao.GetPdfByteContent(filePath); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure to Get PDF Content. FilePath: {filePath}"); + throw new ServiceException($"Failure to Get PDF Content. FilePath: {filePath}. " + + $"Exception Message: {exception.Message}"); + } + } + + public async Task GetContentBytes(string documentPath, string documentFileName) + { + var filePath = documentPath + documentFileName; + return await GetPdfByteContent(filePath); + } + + public async Task ValidateFileExists(string filePath) + { + try + { + return await _fileOperationsApiDao.ValidateFileExists(filePath); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure to Validate File Exists. FilePath:{filePath}."); + throw new ServiceException($"Failure to Validate File Exists. FilePath:{filePath}. " + + $"Exception Message: {exception.Message}"); + } + } + + public async Task ValidateFileExistsAndNotArchived(string filePath, string archiveFilePath) + { + var fileExists = await ValidateFileExists(filePath); + if (fileExists) + { + return true; + } + + var archiveFileExists = await ValidateFileExists(archiveFilePath); + if (archiveFileExists) + { + return false; + } + + throw new Exception("File does not exist."); + } + + public async Task ValidatePdfPageExists(string filePath, string pageNumber) + { + + try + { + return await _fileOperationsApiDao.ValidatePdfPageExists(filePath, pageNumber); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure to Validate PDF Page Exists. FilePath:{filePath} | PageNumber:{pageNumber}."); + throw new ServiceException($"Failure to Validate PDF Page Exists. FilePath:{filePath} | PageNumber: {pageNumber}. " + + $"Exception Message: {exception.Message}"); + } + } + + public async Task> BuildDynamicDirectoryList(DynamicDirectoryListRequest request) + { + try + { + return await _fileOperationsApiDao.BuildDynamicDirectoryList(request); + } + catch (Exception exception) + { + var message = $"Failure to Build Dynamic Directory List. " + + $"Path:{request.Path}" + + $"DynamicDirectoryName: {request.DynamicDirectoryName}."; + Log.Error(exception, message); + throw new ServiceException($"{message} Exception Message: {exception.Message}"); + } + } + + public async Task BuildDynamicFile(DynamicFileListRequest request) + { + try + { + var dynamicFiles = await BuildDynamicFileList(request); + if (dynamicFiles.Count() > 1) + { + var message = $"There were more than one file that met the dynamic file settings. " + + $"DynamicFileListRequest:{JsonConvert.SerializeObject(request)}"; + throw new Exception(message); + } + + var file = dynamicFiles.FirstOrDefault(); + if (file == null) + { + var message = $"There were no files that met the dynamic file settings. " + + $"DynamicFileListRequest:{JsonConvert.SerializeObject(request)}"; + throw new Exception(message); + } + + return file; + } + catch (Exception exception) + { + var message = $"Failure to Build Dynamic File. " + + $"Path:{request.Path}" + + $"Filename: {request.Filename}."; + Log.Error(exception, message); + throw new ServiceException($"{message} Exception Message: {exception.Message}"); + } + } + + public async Task> BuildDynamicFileList(DynamicFileListRequest request) + { + try + { + return await _fileOperationsApiDao.BuildDynamicFileList(request); + } + catch (Exception exception) + { + var message = $"Failure to Build Dynamic File List. " + + $"Path:{request.Path}" + + $"Filename: {request.Filename}."; + Log.Error(exception, message); + throw new ServiceException($"{message} Exception Message: {exception.Message}"); + } + } + + public async Task QueueBatchPdfParser(BatchParsePdfRequest batchParsePdfRequest) + { + try + { + await _fileOperationsApiDao.QueueBatchPdfParser(batchParsePdfRequest); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure to Queue BatchParsePdfRequest. " + + $"FilePath:{batchParsePdfRequest.RootPath}/{batchParsePdfRequest.PdfName} "); + throw new ServiceException($"Failure to Queue BatchParsePdfRequest. " + + $"FilePath:{batchParsePdfRequest.RootPath}/{batchParsePdfRequest.PdfName} " + + $"Exception Message: {exception.Message}"); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/ICoreApiWrapperService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/ICoreApiWrapperService.cs new file mode 100644 index 0000000..3485ccc --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/ICoreApiWrapperService.cs @@ -0,0 +1,25 @@ +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Mixed; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Organizations; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Persons; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Tax; +namespace LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; + +public interface ICoreApiWrapperService +{ + Task> GetPersonsTaxIdData(string taxId); + Task> GetOrganizationsTaxIdData(string taxId); + Task> GetOwnersByAccountNumber(string accountNumber, string creationDate); + Task> GetOwnersByOrganizationName(string organizationName); + Task> GetOwnersByPersonName(string personName); + Task GetAgreementAccountByAccountId(string accountId); + Task?> GetAgreementAccountsByUserId(string userId); + Task?> GetAgreeUsersByAccount(string accountNumber); + Task?> GetAgreeUsersByPersonNumber(string personNumber); + Task GetAgreeUserByOrganizationNumber(string organizationNumber); + Task GetAgreementByUserId(string userId); + Task GetPersonOrOrganizationNumberByMemberId(string memberId); + +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/IDocumentTypeRetrieverService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/IDocumentTypeRetrieverService.cs new file mode 100644 index 0000000..c2cacff --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/IDocumentTypeRetrieverService.cs @@ -0,0 +1,16 @@ +using LCU.Library.DocumentType.Models.Requests; +using LCU.Library.DocumentType.Models.Responses; +using LCU.Library.DocumentType.Models.Responses.External; +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; + +public interface IDocumentTypeRetrieverService +{ + Task GetDocumentCodeDetail(string documentCode); + Task> GetDocumentCodeDetails(); + Task GetDocumentCodeDetailByDisplayName(string documentTypeDisplayName); + Task> GetListOfMaliciousDocuments(MaliciousDocumentSearchFilter filter); + Task GetDocumentInformationById(Guid documentId); + Task GetDocumentCodeDetailByBusinessName(string documentBusinessName); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/IDocumentTypeUploaderApiService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/IDocumentTypeUploaderApiService.cs new file mode 100644 index 0000000..845f709 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/IDocumentTypeUploaderApiService.cs @@ -0,0 +1,19 @@ +using LCU.Library.DocumentType.Models.Requests.PrimaryOwner; +using LCU.Library.DocumentType.Models.Requests.Account; +using LCU.Library.DocumentType.Models.Requests.Generic; +using LCU.Library.Internal.DocumentIngestorModels.Models; + +namespace LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; + +public interface IDocumentTypeUploaderApiService +{ + Task UploadPrimaryOwnerDocument(PrimaryOwnerDocumentRequest primaryOwnerDocumentRequest, + ProcessingRequest request, + ProcessResult result); + Task UploadAccountDocument(AccountDocumentRequest accountDocumentRequest, + ProcessingRequest request, + ProcessResult result); + Task UploadGenericDocument(GenericDocumentRequest genericDocumentRequest, + ProcessingRequest request, + ProcessResult result); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/IFileOperationsApiService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/IFileOperationsApiService.cs new file mode 100644 index 0000000..0e5d85d --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/IFileOperationsApiService.cs @@ -0,0 +1,28 @@ + +using LCU.Library.Internal.FileOperationsModels.Models; + +namespace LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; + +public interface IFileOperationsApiService +{ + Task DirectMoveFile(string sourcePath, string sourceFile, string destinationPath); + Task DirectWriteFile(string fileName, string extension, string fileData, string destinationPath); + Task DirectCreateDirectory(string directoryPath, string directoryName); + Task DirectUnzipFile(string sourceDirectory, + string zipFileName, + string destinationPath, + bool useZipFileNameAsFinalDestination); + Task DirectZipDirectory(string sourceDirectory, string zipPath, string zipFileName); + Task DirectDeleteDirectory(string directoryName, string directoryRootPath, int maxAmountOfDirectories); + Task DirectDeleteFile(string sourcePath, string sourceFile); + Task GetFileContent(string filePath); + Task GetPdfByteContent(string filePath); + Task GetContentBytes(string documentPath, string documentFileName); + Task ValidateFileExists(string filePath); + Task ValidateFileExistsAndNotArchived(string filePath, string archiveFilePath); + Task ValidatePdfPageExists(string filePath, string pageNumber); + Task> BuildDynamicDirectoryList(DynamicDirectoryListRequest request); + Task BuildDynamicFile(DynamicFileListRequest request); + Task> BuildDynamicFileList(DynamicFileListRequest request); + Task QueueBatchPdfParser(BatchParsePdfRequest batchParsePdfRequest); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/IMemberPreferencesApiService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/IMemberPreferencesApiService.cs new file mode 100644 index 0000000..8003ed5 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/IMemberPreferencesApiService.cs @@ -0,0 +1,9 @@ +using LCU.API.Internal.DocumentIngestor.Models.MemberPreferencesDtos; +namespace LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; + +public interface IMemberPreferencesApiService +{ + Task GetMemberOptInAgreementInfoByUserId(string userId); + Task GetMemberOptInSettingsByUserId(string userId); + Task EmailStatusSend(string userId, string emailAddress, bool success); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/INotificationApiService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/INotificationApiService.cs new file mode 100644 index 0000000..33511bc --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/INotificationApiService.cs @@ -0,0 +1,10 @@ +using LCU.API.Internal.DocumentIngestor.Models; +using LCU.Library.Internal.NotificationsModels.Models; + +namespace LCU.API.Internal.DocumentIngestor.Services.MicroApiServices +{ + public interface INotificationApiService + { + Task SendEmailAsync(EmailRequest emailRequest); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/MemberPreferencesApiService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/MemberPreferencesApiService.cs new file mode 100644 index 0000000..78e0e6b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/MemberPreferencesApiService.cs @@ -0,0 +1,65 @@ +using Serilog; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.DataAccess; +using LCU.API.Internal.DocumentIngestor.Models.MemberPreferencesDtos; +namespace LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; + +public class MemberPreferencesApiService : IMemberPreferencesApiService +{ + private readonly IMemberPreferencesApiDao _memberPreferencesApiDao; + + public MemberPreferencesApiService(IMemberPreferencesApiDao memberPreferencesApiDao) + { + _memberPreferencesApiDao = memberPreferencesApiDao; + } + + public async Task GetMemberOptInAgreementInfoByUserId(string userId) + { + try + { + return await _memberPreferencesApiDao.GetMemberOptInAgreementInfoByUserId(userId); + } + catch (Exception exception) + { + var message = $"Failure Get Member Opt In Agreement Information From Member Preferences Api. UserId: {userId}"; + Log.Error(exception, message); + throw new ServiceException($"{message}, Exception Message: {exception.Message}"); + } + } + + public async Task GetMemberOptInSettingsByUserId(string userId) + { + try + { + return await _memberPreferencesApiDao.GetMemberOptInSettingsByUserId(userId); + } + catch (Exception exception) + { + var message = $"Failure Get Member Opt In Settings From Member Preferences Api. UserId: {userId}"; + Log.Error(exception, message); + throw new ServiceException($"{message}, Exception Message: {exception.Message}"); + } + } + + public async Task EmailStatusSend(string userId, string emailAddress, bool success) + { + + try + { + if (success) + { + await _memberPreferencesApiDao.EmailSuccessfulSend(userId, emailAddress); + } + else + { + await _memberPreferencesApiDao.EmailFailureSend(userId, emailAddress); + } + } + catch (Exception exception) + { + var message = $"Failure to notify Member Preferences Api with UserId({userId}) and EmailAddress({emailAddress}) with status: {success})."; + Log.Error(exception, message); + throw new ServiceException($"{message}, Exception Message: {exception.Message}"); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/NotificationApiService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/NotificationApiService.cs new file mode 100644 index 0000000..494b4bf --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/MicroApiServices/NotificationApiService.cs @@ -0,0 +1,29 @@ +using LCU.API.Internal.DocumentIngestor.DataAccess; +using LCU.Library.Internal.NotificationsModels.Models; +using LCU.Library.Internal.Exceptions; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; + +public class NotificationApiService : INotificationApiService +{ + private readonly INotificationApiDao _notificationServiceApiDao; + + public NotificationApiService(INotificationApiDao notificationApiServiceDao) + { + _notificationServiceApiDao = notificationApiServiceDao; + } + + public async Task SendEmailAsync(EmailRequest emailRequest) + { + try + { + await _notificationServiceApiDao.SendEmailAsync(emailRequest); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure to send email. Subject: {emailRequest.Subject}; Recipients: {string.Join(", ", emailRequest.Recipient)}"); + throw new ServiceException($"Failure to send email. Subject: {emailRequest.Subject}; Recipients: {string.Join(", ", emailRequest.Recipient)}; Exception Message: {exception.Message}"); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/OsgPreprocessorInfoService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/OsgPreprocessorInfoService.cs new file mode 100644 index 0000000..6b4bc04 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/OsgPreprocessorInfoService.cs @@ -0,0 +1,230 @@ +using LCU.API.Internal.DocumentIngestorLib.Repositories; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +using Serilog; +using System.Data.SqlClient; + +namespace LCU.API.Internal.DocumentIngestor.Services; + +[Obsolete("06/02/2023 - Used to prepare historical documents for ingestion. No longer in use.")] +public class OsgPreprocessorInfoService : IOsgPreprocessorInfoService +{ + private readonly IUnitOfWork _unitOfWork; + private readonly IOsgPreprocessorInfoRepository _osgPreprocessorInfoRepository; + + public OsgPreprocessorInfoService(IUnitOfWork unitOfWork, + IOsgPreprocessorInfoRepository osgPreprocessingInfoRepository) + { + _unitOfWork = unitOfWork; + _osgPreprocessorInfoRepository = osgPreprocessingInfoRepository; + } + + public async Task> GetAsync() + { + try + { + var osgPreprocessorInfos = await _osgPreprocessorInfoRepository.FindAsync(); + return osgPreprocessorInfos; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving OsgPreprocessorInfos."); + throw new ServiceException($"Failure retrieving OsgPreprocessorInfos."); + } + } + + public async Task GetByIdAsync(int id) + { + try + { + var osgPreprocessorInfo = await _osgPreprocessorInfoRepository.FindByIdAsync(id); + return osgPreprocessorInfo; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving OsgPreprocessorInfo with OsgPreprocessorInfoId {id}."); + throw new ServiceException($"Failure retrieving OsgPreprocessorInfo with OsgPreprocessorInfoId {id}."); + } + } + + public async Task> GetListByIdAsync(List ids) + { + try + { + var osgPreprocessorInfo = await _osgPreprocessorInfoRepository.FindListByIdAsync(ids); + return osgPreprocessorInfo; + } + catch (Exception exception) + { + var message = $"Failure retrieving list of OsgPreprocessorInfos with OsgPreprocessorInfoIds: {String.Join(", ", ids.ToArray())}."; + Log.Error(exception, message); + throw new ServiceException(message); + } + } + + public async Task> GetByDocumentTypeAsync(string documentType) + { + try + { + var osgPreprocessorInfos = await _osgPreprocessorInfoRepository.FindByDocumentType(documentType); + return osgPreprocessorInfos; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving OsgPreprocessorInfos with DocumentType: {documentType}."); + throw new ServiceException($"Failure retrieving OsgPreprocessorInfos with DocumentType: {documentType}."); + } + } + + public async Task> GetByMemberNumberAsync(string memberNumber) + { + try + { + var osgPreprocessorInfos = await _osgPreprocessorInfoRepository.FindByMemberNumber(memberNumber); + return osgPreprocessorInfos; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving OsgPreprocessorInfos with MemberNumber: {memberNumber}."); + throw new ServiceException($"Failure retrieving OsgPreprocessorInfos with MemberNumber: {memberNumber}."); + } + } + + public async Task SaveAsync(OsgPreprocessorInfo osgPreprocessorInfo) + { + try + { + var result = await _osgPreprocessorInfoRepository.AddAsync(osgPreprocessorInfo); + await _unitOfWork.CompleteAsync(); + return result; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure saving OsgPreprocessorInfo."); + throw new ServiceException($"Failure saving OsgPreprocessorInfo."); + } + } + + public async Task SaveListAsync(List osgPreprocessorInfos) + { + try + { + await _osgPreprocessorInfoRepository.AddListAsync(osgPreprocessorInfos); + await _unitOfWork.CompleteAsync(); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure saving list of OsgPreprocessorInfo."); + throw new ServiceException($"Failure saving list OsgPreprocessorInfo."); + } + } + + public async Task Update(OsgPreprocessorInfo osgPreprocessorInfo) + { + try + { + var existing = await GetByIdAsync(osgPreprocessorInfo.OsgPreprocessorInfoId); + if (existing == null) + { + return existing; + } + + existing.BatchRunInfoId = osgPreprocessorInfo.BatchRunInfoId; + existing.ZipFileName = osgPreprocessorInfo.ZipFileName; + existing.ZipFileStartTime = osgPreprocessorInfo.ZipFileStartTime; + existing.ZipFileEndTime = osgPreprocessorInfo.ZipFileEndTime; + existing.DocumentType = osgPreprocessorInfo.DocumentType; + existing.EntityName = osgPreprocessorInfo.EntityName; + existing.MemberNumber = osgPreprocessorInfo.MemberNumber; + existing.CreatedDate = osgPreprocessorInfo.CreatedDate; + existing.StartingPage = osgPreprocessorInfo.StartingPage; + existing.NumberOfPages = osgPreprocessorInfo.NumberOfPages; + existing.XmlOutput = osgPreprocessorInfo.XmlOutput; + + _osgPreprocessorInfoRepository.Update(existing); + _unitOfWork.Complete(); + + return existing; + } + catch (SqlException sqlException) + { + Log.Error(sqlException, $"SQL Failure updating OsgPreprocessorInfo. " + + $"OsgPreprocessorInfoId: {osgPreprocessorInfo.OsgPreprocessorInfoId}"); + throw new ServiceException($"SQL Failure updating DocumentProcessingInfo. " + + $"OsgPreprocessorInfoId: {osgPreprocessorInfo.OsgPreprocessorInfoId}"); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure updating OsgPreprocessorInfo. " + + $"OsgPreprocessorInfoId: {osgPreprocessorInfo.OsgPreprocessorInfoId}"); + throw new ServiceException($"Failure updating OsgPreprocessorInfo. " + + $"OsgPreprocessorInfoId: {osgPreprocessorInfo.OsgPreprocessorInfoId}"); + } + } + + public async Task> UpdateRange(IEnumerable osgPreprocessorInfos) + { + try + { + var updateList = new List(); + foreach (var osgPreprocessorInfo in osgPreprocessorInfos) + { + var existing = await GetByIdAsync(osgPreprocessorInfo.OsgPreprocessorInfoId); + if (existing == null) + { + continue; + } + + existing.BatchRunInfoId = osgPreprocessorInfo.BatchRunInfoId; + existing.ZipFileName = osgPreprocessorInfo.ZipFileName; + existing.ZipFileStartTime = osgPreprocessorInfo.ZipFileStartTime; + existing.ZipFileEndTime = osgPreprocessorInfo.ZipFileEndTime; + existing.DocumentType = osgPreprocessorInfo.DocumentType; + existing.EntityName = osgPreprocessorInfo.EntityName; + existing.MemberNumber = osgPreprocessorInfo.MemberNumber; + existing.CreatedDate = osgPreprocessorInfo.CreatedDate; + existing.StartingPage = osgPreprocessorInfo.StartingPage; + existing.NumberOfPages = osgPreprocessorInfo.NumberOfPages; + existing.XmlOutput = osgPreprocessorInfo.XmlOutput; + + updateList.Add(existing); + } + + _osgPreprocessorInfoRepository.UpdateRange(updateList); + _unitOfWork.Complete(); + + return updateList; + } + catch (SqlException sqlException) + { + Log.Error(sqlException, $"SQL Failure updating list of OsgPreprocessorInfos."); + throw new ServiceException($"SQL Failure updating list of OsgPreprocessorInfos."); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure updating list of OsgPreprocessorInfos."); + throw new ServiceException($"Failure updating list of OsgPreprocessorInfos."); + } + } + + public async Task Delete(int id) + { + try + { + var osgPreprocessorInfo = await GetByIdAsync(id); + ArgumentNullException.ThrowIfNull(osgPreprocessorInfo); + _osgPreprocessorInfoRepository.Remove(osgPreprocessorInfo); + _unitOfWork.Complete(); + } + catch (SqlException sqlException) + { + Log.Error(sqlException, $"SQL failure removing OsgPreprocessorInfo. OsgPreprocessorInfoId: {id}"); + throw new ServiceException($"SQL failure removing OsgPreprocessorInfo. OsgPreprocessorInfoId: {id}"); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure removing OsgPreprocessorInfo. OsgPreprocessorInfoId: {id}"); + throw new ServiceException($"Failure removing OsgPreprocessorInfo. OsgPreprocessorInfoId: {id}"); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/OwnerOverrideInfoService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/OwnerOverrideInfoService.cs new file mode 100644 index 0000000..d99912c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/OwnerOverrideInfoService.cs @@ -0,0 +1,97 @@ +using LCU.API.Internal.DocumentIngestorLib.Repositories; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +using Serilog; +using System.Data.SqlClient; +namespace LCU.API.Internal.DocumentIngestor.Services; + +public class OwnerOverrideInfoService : IOwnerOverrideInfoService +{ + private readonly IUnitOfWork _unitOfWork; + private readonly IOwnerOverrideInfoRepository _ownerOverrideInfoRepository; + + public OwnerOverrideInfoService(IUnitOfWork unitOfWork, + IOwnerOverrideInfoRepository ownerOverrideInfoRepository) + { + _unitOfWork = unitOfWork; + _ownerOverrideInfoRepository = ownerOverrideInfoRepository; + } + + public async Task?> GetAsync() + { + try + { + var ownerOverrideInfos = await _ownerOverrideInfoRepository.FindAsync(); + return ownerOverrideInfos; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving OwnerOverrideInfos."); + throw new ServiceException($"Failure retrieving OwnerOverrideInfos. Exception Message: {exception.Message}"); + } + } + + public async Task GetByIdAsync(int id) + { + try + { + var ownerOverrideInfo = await _ownerOverrideInfoRepository.FindByIdAsync(id); + return ownerOverrideInfo; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving OwnerOverrideInfo with OwnerOverrideInfoId {id}."); + throw new ServiceException($"Failure retrieving OwnerOverrideInfo with OwnerOverrideInfoId {id}. Exception Message: {exception.Message}"); + } + } + + public async Task?> GetByDocumentProcessingInfoIdAsync(int documentProcessingInfoId) + { + try + { + var ownerOverrideInfos = await _ownerOverrideInfoRepository.FindByDocumentProcessingInfoIdAsync(documentProcessingInfoId); + return ownerOverrideInfos; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving OwnerOverrideInfos with DocumentProcessingInfoId {documentProcessingInfoId}."); + throw new ServiceException($"Failure retrieving OwnerOverrideInfos with DocumentProcessingInfoId {documentProcessingInfoId}. Exception Message: {exception.Message}"); + } + } + + public async Task SaveAsync(OwnerOverrideInfo ownerOverrideInfo) + { + try + { + var result = await _ownerOverrideInfoRepository.AddAsync(ownerOverrideInfo); + await _unitOfWork.CompleteAsync(); + return result; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure saving OwnerOverrideInfo."); + throw new ServiceException($"Failure saving OwnerOverrideInfo."); + } + } + + public async Task Delete(int id) + { + try + { + var ownerOverrideInfo = await GetByIdAsync(id); + ArgumentNullException.ThrowIfNull(ownerOverrideInfo); + _ownerOverrideInfoRepository.Remove(ownerOverrideInfo); + _unitOfWork.Complete(); + } + catch (SqlException sqlException) + { + Log.Error(sqlException, $"SQL failure removing OwnerOverrideInfo. OwnerOverrideInfoId: {id}"); + throw new ServiceException($"SQL failure removing OwnerOverrideInfo. OwnerOverrideInfoId: {id}"); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure removing OwnerOverrideInfo. OwnerOverrideInfoId: {id}"); + throw new ServiceException($"Failure removing OwnerOverrideInfo. OwnerOverrideInfoId: {id}"); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfParserServices/FosLoanStatementPdfService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfParserServices/FosLoanStatementPdfService.cs new file mode 100644 index 0000000..3fc1a9c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfParserServices/FosLoanStatementPdfService.cs @@ -0,0 +1,135 @@ +using Serilog; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.Library.Internal.LCUServiceFactory.Configurations; +using LCU.Library.Internal.LCUServiceFactory.Services; + +namespace LCU.API.Internal.DocumentIngestor.Services.PdfParserServices; + +public class FosLoanStatementPdfService : PdfParserService, IPdfParserService +{ + private readonly ILcuServiceFactory _indexParserServiceFactory; + private readonly IFileOperationsApiService _fileOperationsApiService; + + public FosLoanStatementPdfService(IFileOperationsApiService fileOperationsApiService, + ILcuServiceFactory indexParserServiceFactory, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _indexParserServiceFactory = indexParserServiceFactory; + _fileOperationsApiService = fileOperationsApiService; + } + + public async Task DetermineBatchParsePdfRequest(string rootPath, string indexFile, string pdfName) + { + try + { + var indexFilePath = rootPath + indexFile; + var records = await GetFileContentAndParseRecords(indexFilePath); + var batchParsePdfRequest = await GetParsedPdfFiles(records, rootPath, pdfName); + return batchParsePdfRequest; + } + catch (Exception exception) + { + var message = $"An Exception occured while DetermineBatchParsePdfRequest. " + + $"IndexFile:{indexFile}, RootPath:{rootPath}, MainPdfName:{pdfName}"; + Log.Error(exception, message); + throw new ServiceException($"{message}, ExceptionMessage:{exception.Message}"); + } + } + + private async Task> GetFileContentAndParseRecords(string indexFilePath) + { + var indexParserService = _indexParserServiceFactory.GetService(IngestorTypes.FosLoanStatement); + + if (indexParserService is null) + { + throw new NotImplementedException(); + } + + return await indexParserService.GetFileContentAndParseRecords(indexFilePath); + } + + public async Task GetParsedPdfFiles(List records, string rootPath, string pdfName) + { + await ValidatePdfsCanBeParsed(records, pdfName, rootPath); + var batchParsePdfRequest = CreateBatchParsePdfRequest(records); + return batchParsePdfRequest; + } + + private async Task ValidatePdfsCanBeParsed(List records, + string pdfName, + string rootPath) + { + var maxPage = records.Select(record => + { + if (!int.TryParse(record.StartingPage, out int startingPage) || !int.TryParse(record.NumberOfPages, out int numberOfPages)) + { + var message = $"'StartingPage' or 'NumberOfPages' for {pdfName} could not be parsed to int." + + $" StartingPage: {record.StartingPage} | NumberOfPages: {record.NumberOfPages}"; + Log.Error(message); + throw new ServiceException(message); + } + + return startingPage + (numberOfPages - 1); + } + ).OrderByDescending(x => x).FirstOrDefault(); + + var pdfFullPath = string.Concat(rootPath, pdfName); + var pdfPageExists = await _fileOperationsApiService.ValidatePdfPageExists(pdfFullPath, maxPage.ToString()); + + if (!pdfPageExists.IsSuccessful) + { + var message = $"Page does not exist for {pdfName} at EndingPage: ({maxPage}). MessageStack: {String.Join("; ", pdfPageExists.MessageStack.ToArray())}"; + Log.Error(message); + throw new ServiceException(message); + } + } + + private BatchParsePdfRequest CreateBatchParsePdfRequest(List records) + { + var batchParsePdfRequest = new BatchParsePdfRequest + { + BatchPdfs = new List() + }; + foreach (var record in records) + { + if (!int.TryParse(record.StartingPage, out int startingPage) || !int.TryParse(record.NumberOfPages, out int numberOfPages)) + { + var message = $"'StartingPage' or 'NumberOfPages' for {record.DocName} could not be parsed to int." + + $" StartingPage: {record.StartingPage} | NumberOfPages: {record.NumberOfPages}"; + Log.Error(message); + throw new ServiceException(message); + } + + var endingPage = startingPage + (numberOfPages - 1); + var parsedPdfName = GetParsedPdfName(record); + var batchPdf = new BatchPdf() + { + PageStart = startingPage, + PageStop = endingPage, + ParsedPdfname = Path.GetFileNameWithoutExtension(parsedPdfName) + }; + + batchParsePdfRequest.BatchPdfs.Add(batchPdf); + } + + return batchParsePdfRequest; + } + + private string GetParsedPdfName(FosLoanStatement fosLoanStatement) + { + var indexParserService = _indexParserServiceFactory.GetService(IngestorTypes.FosLoanStatement); + + if (indexParserService is null) + { + throw new NotImplementedException(); + } + + return indexParserService.CreateParsedPdfName(fosLoanStatement); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfParserServices/IPdfParserService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfParserServices/IPdfParserService.cs new file mode 100644 index 0000000..657aedc --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfParserServices/IPdfParserService.cs @@ -0,0 +1,11 @@ +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.Library.Internal.LCUServiceFactory.Services; + +namespace LCU.API.Internal.DocumentIngestor.Services.PdfParserServices; + +public interface IPdfParserService : ILcuService +{ + Task DetermineBatchParsePdfRequest(string rootPath, + string indexFile, + string pdfName); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfParserServices/OsgDnaNoticesPdfService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfParserServices/OsgDnaNoticesPdfService.cs new file mode 100644 index 0000000..94fb75b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfParserServices/OsgDnaNoticesPdfService.cs @@ -0,0 +1,136 @@ +using Serilog; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.LCUServiceFactory.Configurations; +using LCU.Library.Internal.LCUServiceFactory.Services; + +namespace LCU.API.Internal.DocumentIngestor.Services.PdfParserServices; + +public class OsgDnaNoticesPdfService : PdfParserService, IPdfParserService +{ + private readonly ILcuServiceFactory _indexParserServiceFactory; + private readonly IFileOperationsApiService _fileOperationsApiService; + + public OsgDnaNoticesPdfService(ILcuServiceFactory indexParserServiceFactory, + IFileOperationsApiService fileOperationsApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _indexParserServiceFactory = indexParserServiceFactory; + _fileOperationsApiService = fileOperationsApiService; + } + + public async Task DetermineBatchParsePdfRequest(string rootPath, string indexFile, string pdfName) + { + try + { + var indexFilePath = rootPath + indexFile; + var records = await GetFileContentAndParseRecords(indexFilePath); + var batchParsePdfRequest = await GetParsedPdfFiles(records.ToList(), rootPath, pdfName); + return batchParsePdfRequest; + } + catch (Exception exception) + { + var message = $"An Exception occured while DetermineBatchParsePdfRequest. " + + $"IndexFile:{indexFile}, RootPath:{rootPath}, MainPdfName:{pdfName}"; + Log.Error(exception, message); + throw new ServiceException($"{message}, ExceptionMessage:{exception.Message}"); + } + } + + private async Task> GetFileContentAndParseRecords(string indexFilePath) + { + var indexParserService = _indexParserServiceFactory.GetService(IngestorTypes.OsgDnaNoticesDocument); + + if (indexParserService is null) + { + throw new NotImplementedException(); + } + + return await indexParserService.GetFileContentAndParseRecords(indexFilePath); + } + + public async Task GetParsedPdfFiles(List records, string rootPath, string pdfName) + { + await ValidatePdfsCanBeParsed(records, pdfName, rootPath); + var batchParsePdfRequest = CreateBatchParsePdfRequest(records); + return batchParsePdfRequest; + } + + private async Task ValidatePdfsCanBeParsed(List records, + string pdfName, + string rootPath) + { + var maxPage = records.Select(record => + { + GetStartingPageAndNumberOfPages(record, out int startingPage, out int numberOfPages); + return startingPage + (numberOfPages - 1); + } + ).OrderByDescending(x => x).FirstOrDefault(); + + var pdfFullPath = string.Concat(rootPath, pdfName); + var pdfPageExists = await _fileOperationsApiService.ValidatePdfPageExists(pdfFullPath, maxPage.ToString()); + + if (!pdfPageExists.IsSuccessful) + { + var message = $"Page does not exist for {pdfName} at EndingPage: ({maxPage}). MessageStack: {String.Join("; ", pdfPageExists.MessageStack.ToArray())}"; + Log.Error(message); + throw new ServiceException(message); + } + + return true; + } + + private BatchParsePdfRequest CreateBatchParsePdfRequest(List records) + { + var batchParsePdfRequest = new BatchParsePdfRequest + { + BatchPdfs = new List() + }; + foreach (var record in records) + { + + GetStartingPageAndNumberOfPages(record, out int startingPage, out int numberOfPages); + + var endingPage = startingPage + (numberOfPages - 1); + var parsedPdfName = GetParsedPdfName(record); + var batchPdf = new BatchPdf() + { + PageStart = startingPage, + PageStop = endingPage, + ParsedPdfname = Path.GetFileNameWithoutExtension(parsedPdfName) + }; + + batchParsePdfRequest.BatchPdfs.Add(batchPdf); + } + + return batchParsePdfRequest; + } + + private static void GetStartingPageAndNumberOfPages(OsgDnaNoticesDocument record, out int startingPage, out int numberOfPages) + { + if (!int.TryParse(record.StartingPage, out startingPage) || !int.TryParse(record.NumberOfPages, out numberOfPages)) + { + var message = $"'StartingPage' or 'NumberOfPages' for account {record.AccountNumber} could not be parsed to int. " + + $"StartingPage: {record.StartingPage} | NumberOfPages: {record.NumberOfPages}"; + Log.Error(message); + throw new ServiceException(message); + } + } + + private string GetParsedPdfName(OsgDnaNoticesDocument osgDnaNoticesDocument) + { + var indexParserService = _indexParserServiceFactory.GetService(IngestorTypes.OsgDnaNoticesDocument); + + if (indexParserService is null) + { + throw new NotImplementedException(); + } + + return indexParserService.CreateParsedPdfName(osgDnaNoticesDocument); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfParserServices/OsgHistoricalDocumentPdfService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfParserServices/OsgHistoricalDocumentPdfService.cs new file mode 100644 index 0000000..2805cfe --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfParserServices/OsgHistoricalDocumentPdfService.cs @@ -0,0 +1,136 @@ +using Serilog; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.LCUServiceFactory.Configurations; +using LCU.Library.Internal.LCUServiceFactory.Services; + +namespace LCU.API.Internal.DocumentIngestor.Services.PdfParserServices; + +public class OsgHistoricalDocumentPdfService : PdfParserService, IPdfParserService +{ + private readonly ILcuServiceFactory _indexParserServiceFactory; + private readonly IFileOperationsApiService _fileOperationsApiService; + + public OsgHistoricalDocumentPdfService(ILcuServiceFactory indexParserServiceFactory, + IFileOperationsApiService fileOperationsApiService, + ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration) + { + _indexParserServiceFactory = indexParserServiceFactory; + _fileOperationsApiService = fileOperationsApiService; + } + + public async Task DetermineBatchParsePdfRequest(string rootPath, string indexFile, string pdfName) + { + try + { + var indexFilePath = rootPath + indexFile; + var records = await GetFileContentAndParseRecords(indexFilePath); + var batchParsePdfRequest = await GetParsedPdfFiles(records.ToList(), rootPath, pdfName); + return batchParsePdfRequest; + } + catch (Exception exception) + { + var message = $"An Exception occured while DetermineBatchParsePdfRequest. " + + $"IndexFile:{indexFile}, RootPath:{rootPath}, MainPdfName:{pdfName}"; + Log.Error(exception, message); + throw new ServiceException($"{message}, ExceptionMessage:{exception.Message}"); + } + } + + private async Task> GetFileContentAndParseRecords(string indexFilePath) + { + var indexParserService = _indexParserServiceFactory.GetService(IngestorTypes.OsgHistoricalDocument); + + if (indexParserService is null) + { + throw new NotImplementedException(); + } + + return await indexParserService.GetFileContentAndParseRecords(indexFilePath); + } + + private async Task GetParsedPdfFiles(List records, string rootPath, string pdfName) + { + await ValidatePdfsCanBeParsed(records, pdfName, rootPath); + var batchParsePdfRequest = CreateBatchParsePdfRequest(records); + return batchParsePdfRequest; + } + + private async Task ValidatePdfsCanBeParsed(List records, + string pdfName, + string rootPath) + { + var maxPage = records.Select(record => + { + GetStartingPageAndNumberOfPages(record, out int startingPage, out int numberOfPages); + return startingPage + (numberOfPages - 1); + } + ).Max(); + + var pdfFullPath = string.Concat(rootPath, pdfName); + var pdfPageExists = await _fileOperationsApiService.ValidatePdfPageExists(pdfFullPath, maxPage.ToString()); + + if (!pdfPageExists.IsSuccessful) + { + var message = $"Page does not exist for {pdfName} at EndingPage: ({maxPage}). MessageStack: {String.Join("; ", pdfPageExists.MessageStack.ToArray())}"; + Log.Error(message); + throw new ServiceException(message); + } + + return true; + } + + private BatchParsePdfRequest CreateBatchParsePdfRequest(List records) + { + var batchParsePdfRequest = new BatchParsePdfRequest + { + BatchPdfs = new List() + }; + foreach (var record in records) + { + + GetStartingPageAndNumberOfPages(record, out int startingPage, out int numberOfPages); + + var endingPage = startingPage + (numberOfPages - 1); + var parsedPdfName = GetParsedPdfName(record); + var batchPdf = new BatchPdf() + { + PageStart = startingPage, + PageStop = endingPage, + ParsedPdfname = Path.GetFileNameWithoutExtension(parsedPdfName) + }; + + batchParsePdfRequest.BatchPdfs.Add(batchPdf); + } + + return batchParsePdfRequest; + } + + private static void GetStartingPageAndNumberOfPages(OsgHistoricalDocument record, out int startingPage, out int numberOfPages) + { + if (!int.TryParse(record.StartingPage, out startingPage) || !int.TryParse(record.NumberOfPages, out numberOfPages)) + { + var message = $"'StartingPage' or 'NumberOfPages' for entityId {record.MemberNumberOrUserId} could not be parsed to int. " + + $"StartingPage: {record.StartingPage} | NumberOfPages: {record.NumberOfPages}"; + Log.Error(message); + throw new ServiceException(message); + } + } + + private string GetParsedPdfName(OsgHistoricalDocument osgHistoricalDocument) + { + var indexParserService = _indexParserServiceFactory.GetService(IngestorTypes.OsgHistoricalDocument); + + if (indexParserService is null) + { + throw new NotImplementedException(); + } + + return indexParserService.CreateParsedPdfName(osgHistoricalDocument); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfParserServices/PdfParserService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfParserServices/PdfParserService.cs new file mode 100644 index 0000000..2e364f3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfParserServices/PdfParserService.cs @@ -0,0 +1,11 @@ +using LCU.Library.Internal.LCUServiceFactory.Configurations; +using LCU.Library.Internal.LCUServiceFactory.Services; + +namespace LCU.API.Internal.DocumentIngestor.Services.PdfParserServices; + +public class PdfParserService : LcuAbstractService +{ + protected PdfParserService(ServicesFactoryConfiguration servicesFactoryConfiguration) + : base(servicesFactoryConfiguration.GetServiceFactoryRegistrationByInterface()) + { } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfPartitionerLogService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfPartitionerLogService.cs new file mode 100644 index 0000000..126f2aa --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfPartitionerLogService.cs @@ -0,0 +1,118 @@ +using System.Data.SqlClient; +using Serilog; +using LCU.API.Internal.DocumentIngestorLib.Repositories; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +namespace LCU.API.Internal.DocumentIngestor.Services; + +public class PdfPartitionerLogService : IPdfPartitionerLogService +{ + private readonly IPdfPartitionerLogRepository _pdfPartitionerLogRepository; + private readonly IUnitOfWork _unitOfWork; + + public PdfPartitionerLogService(IUnitOfWork unitOfWork, + IPdfPartitionerLogRepository pdfPartitionerLogRepository) + { + _pdfPartitionerLogRepository = pdfPartitionerLogRepository; + _unitOfWork = unitOfWork; + } + + public async Task> GetAsync() + { + try + { + var pdfPartitionerLogs = await _pdfPartitionerLogRepository.FindAsync(); + return pdfPartitionerLogs; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving PdfPartitionerLogs."); + throw new ServiceException($"Failure retrieving PdfPartitionerLogs."); + } + } + + public async Task GetByIdAsync(int id) + { + try + { + var pdfPartitionerLog = await _pdfPartitionerLogRepository.FindByIdAsync(id); + return pdfPartitionerLog; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving PdfPartitionerLog with PdfPartitionerLogId {id}."); + throw new ServiceException($"Failure retrieving PdfPartitionerLog with PdfPartitionerLogId {id}."); + } + } + + public async Task> GetByPdfPartitionerRunInfoIdAsync(Guid pdfPartitionerRunInfoId) + { + try + { + var pdfPartitionerLogs = await _pdfPartitionerLogRepository.FindByPdfPartitionerRunInfoIdAsync(pdfPartitionerRunInfoId); + return pdfPartitionerLogs; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving PdfPartitionerLogs with PdfPartitionerRunInfoId {pdfPartitionerRunInfoId}."); + throw new ServiceException($"Failure retrieving PdfPartitionerLogs with PdfPartitionerRunInfoId {pdfPartitionerRunInfoId}."); + } + } + + public async Task SaveListAsync(Guid pdfPartitionerRunInfoId, List messageLogs) + { + try + { + var pdfPartitionerLogs = new List(); + foreach(var messageLog in messageLogs) + { + var newPdfPartitionerLog = new PdfPartitionerLog(pdfPartitionerRunInfoId, DateTime.Now, messageLog); + pdfPartitionerLogs.Add(await _pdfPartitionerLogRepository.AddAsync(newPdfPartitionerLog)); + } + + await _pdfPartitionerLogRepository.AddRangeAsync(pdfPartitionerLogs); + await _unitOfWork.CompleteAsync(); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure saving PdfPartitionerLog."); + throw new ServiceException($"Failure saving PdfPartitionerLog."); + } + } + + public async Task SaveAsync(PdfPartitionerLog pdfPartitionerLog) + { + try + { + var result = await _pdfPartitionerLogRepository.AddAsync(pdfPartitionerLog); + await _unitOfWork.CompleteAsync(); + return result; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure saving PdfPartitionerLog."); + throw new ServiceException($"Failure saving PdfPartitionerLog."); + } + } + + public async Task Delete(int id) + { + try + { + var pdfPartitionerLog = await GetByIdAsync(id); + ArgumentNullException.ThrowIfNull(pdfPartitionerLog); + _pdfPartitionerLogRepository.Remove(pdfPartitionerLog); + _unitOfWork.Complete(); + } + catch (SqlException sqlException) + { + Log.Error(sqlException, $"SQL failure removing PdfPartitionerLog. PdfPartitionerLogId: {id}"); + throw new ServiceException($"SQL failure removing PdfPartitionerLog. PdfPartitionerLogId: {id}"); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure removing PdfPartitionerLog. PdfPartitionerLogId: {id}"); + throw new ServiceException($"Failure removing PdfPartitionerLog. PdfPartitionerLogId: {id}"); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfPartitionerRunInfoService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfPartitionerRunInfoService.cs new file mode 100644 index 0000000..b1acce9 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/PdfPartitionerRunInfoService.cs @@ -0,0 +1,140 @@ +using System.Data.SqlClient; +using Serilog; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestorLib.Repositories; +namespace LCU.API.Internal.DocumentIngestor.Services; + +public class PdfPartitionerRunInfoService : IPdfPartitionerRunInfoService +{ + private readonly IPdfPartitionerRunInfoRepository _pdfPartitionerRunInfoRepository; + private readonly IUnitOfWork _unitOfWork; + + public PdfPartitionerRunInfoService(IUnitOfWork unitOfWork, + IPdfPartitionerRunInfoRepository pdfPartitionerRunInfoRepository) + { + _pdfPartitionerRunInfoRepository = pdfPartitionerRunInfoRepository; + _unitOfWork = unitOfWork; + } + + public async Task GetByIdAsync(Guid pdfPartitionerRunInfoId) + { + try + { + var pdfPartitionerRunInfo = await _pdfPartitionerRunInfoRepository.FindByIdAsync(pdfPartitionerRunInfoId); + return pdfPartitionerRunInfo; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving PdfPartitionerRunInfo with PdfPartitionerRunInfoId {pdfPartitionerRunInfoId}."); + throw new ServiceException($"Failure retrieving PdfPartitionerRunInf with PdfPartitionerRunInfoId {pdfPartitionerRunInfoId}."); + } + } + + public async Task SaveAsync(PdfPartitionerRunInfo pdfPartitionerRunInfo) + { + try + { + var result = await _pdfPartitionerRunInfoRepository.AddAsync(pdfPartitionerRunInfo); + await _unitOfWork.CompleteAsync(); + return result; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure saving PdfPartitionerRunInfo."); + throw new ServiceException($"Failure saving PdfPartitionerRunInfo."); + } + } + + public async Task IncreaseCountsAndUpdate(Guid pdfPartitionerRunInfoId, bool successful) + { + try + { + var existing = await GetByIdAsync(pdfPartitionerRunInfoId); + ArgumentNullException.ThrowIfNull(existing); + + if (successful) + { + existing.SuccessCount++; + } + else + { + existing.FailureCount++; + } + + if (existing.PdfPartitionerCompleted) + { + existing.EndTimeStamp = DateTime.Now; + } + + _pdfPartitionerRunInfoRepository.Update(existing); + _unitOfWork.Complete(); + + return existing; + } + catch (SqlException sqlException) + { + Log.Error(sqlException, $"SQL Failure IncreaseCountsAndUpdate PdfPartitionerRunInfo. PdfPartitionerRunInfoId: {pdfPartitionerRunInfoId}"); + throw new ServiceException($"SQL Failure IncreaseCountsAndUpdate PdfPartitionerRunInfo. PdfPartitionerRunInfoId: {pdfPartitionerRunInfoId}"); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure updating IncreaseCountsAndUpdate. PdfPartitionerRunInfoId: {pdfPartitionerRunInfoId}"); + throw new ServiceException($"Failure updating IncreaseCountsAndUpdate. PdfPartitionerRunInfoId: {pdfPartitionerRunInfoId}"); + } + + } + + public async Task Update(PdfPartitionerRunInfo pdfPartitionerRunInfo) + { + try + { + var existing = await GetByIdAsync(pdfPartitionerRunInfo.PdfPartitionerRunInfoId); + ArgumentNullException.ThrowIfNull(existing); + + existing.StartTimeStamp = pdfPartitionerRunInfo.StartTimeStamp; + existing.EndTimeStamp = pdfPartitionerRunInfo.EndTimeStamp; + existing.PdfParserType = pdfPartitionerRunInfo.PdfParserType; + existing.Path = pdfPartitionerRunInfo.Path; + existing.IndexTotal = pdfPartitionerRunInfo.IndexTotal; + existing.FailureCount = pdfPartitionerRunInfo.FailureCount; + existing.SuccessCount = pdfPartitionerRunInfo.SuccessCount; + + _pdfPartitionerRunInfoRepository.Update(existing); + _unitOfWork.Complete(); + + return existing; + } + catch (SqlException sqlException) + { + Log.Error(sqlException, $"SQL Failure updating PdfPartitionerRunInfo. PdfPartitionerRunInfoId: {pdfPartitionerRunInfo.PdfPartitionerRunInfoId}"); + throw new ServiceException($"SQL Failure updating PdfPartitionerRunInfo. PdfPartitionerRunInfoId: {pdfPartitionerRunInfo.PdfPartitionerRunInfoId}"); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure updating PdfPartitionerRunInfo. PdfPartitionerRunInfoId: {pdfPartitionerRunInfo.PdfPartitionerRunInfoId}"); + throw new ServiceException($"Failure updating PdfPartitionerRunInfo. PdfPartitionerRunInfoId: {pdfPartitionerRunInfo.PdfPartitionerRunInfoId}"); + } + } + + public async Task Delete(Guid pdfPartitionerRunInfoId) + { + try + { + var pdfPartitionerRunInfo = await _pdfPartitionerRunInfoRepository.FindByIdAsync(pdfPartitionerRunInfoId); + ArgumentNullException.ThrowIfNull(pdfPartitionerRunInfo); + _pdfPartitionerRunInfoRepository.Remove(pdfPartitionerRunInfo); + _unitOfWork.Complete(); + } + catch (SqlException sqlException) + { + Log.Error(sqlException, $"SQL failure removing PdfPartitionerRunInfo. PdfPartitionerRunInfoId: {pdfPartitionerRunInfoId}"); + throw new ServiceException($"SQL failure removing PdfPartitionerRunInfo. PdfPartitionerRunInfoId: {pdfPartitionerRunInfoId}"); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure removing PdfPartitionerRunInfo. PdfPartitionerRunInfoId: {pdfPartitionerRunInfoId}"); + throw new ServiceException($"Failure removing PdfPartitionerRunInfo. PdfPartitionerRunInfoId: {pdfPartitionerRunInfoId}"); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/ProcessingLogService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/ProcessingLogService.cs new file mode 100644 index 0000000..00023af --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/ProcessingLogService.cs @@ -0,0 +1,147 @@ +using LCU.API.Internal.DocumentIngestorLib.Repositories; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +using Serilog; +using System.Data.SqlClient; + +namespace LCU.API.Internal.DocumentIngestor.Services; + +public class ProcessingLogService : IProcessingLogService +{ + private readonly IProcessingLogRepository _processingLogRepository; + private readonly IUnitOfWork _unitOfWork; + + public ProcessingLogService(IUnitOfWork unitOfWork, + IProcessingLogRepository processingLogRepository) + { + _processingLogRepository = processingLogRepository; + _unitOfWork = unitOfWork; + } + + public async Task> GetAsync() + { + try + { + var documentProcessingInfos = await _processingLogRepository.FindAsync(); + return documentProcessingInfos; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving ProcessingLogs."); + throw new ServiceException($"Failure retrieving ProcessingLogs."); + } + } + + public async Task GetByIdAsync(int id) + { + try + { + var processingLog = await _processingLogRepository.FindByIdAsync(id); + return processingLog; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving ProcessingLog with ProcessingLogId {id}."); + throw new ServiceException($"Failure retrieving ProcessingLog with ProcessingLogId {id}."); + } + } + + public async Task> GetByDocumentProcessingInfoIdAsync(int documentProcessingInfoId) + { + try + { + var processingLogs = await _processingLogRepository.FindByDocumentProcessingInfoIdAsync(documentProcessingInfoId); + return processingLogs; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure retrieving ProcessingLogs with DocumentProcessingInfoId {documentProcessingInfoId}."); + throw new ServiceException($"Failure retrieving ProcessingLogs with DocumentProcessingInfoId {documentProcessingInfoId}."); + } + } + + public async Task SaveAsync(ProcessingLog processingLog) + { + try + { + var result = await _processingLogRepository.AddAsync(processingLog); + await _unitOfWork.CompleteAsync(); + return result; + } + catch (Exception exception) + { + Log.Error(exception, "Failure saving ProcessingLog."); + throw new ServiceException("Failure saving ProcessingLog."); + } + } + + public async Task SaveRangeAsync(IEnumerable processingLogs) + { + try + { + await _processingLogRepository.AddRangeAsync(processingLogs); + await _unitOfWork.CompleteAsync(); + } + catch (Exception exception) + { + Log.Error(exception, "Failure saving ProcessingLogs."); + throw new ServiceException("Failure saving ProcessingLogs."); + } + } + + public async Task Update(ProcessingLog processingLog) + { + try + { + var existing = await GetByIdAsync(processingLog.ProcessingLogId); + if (existing == null) + { + return existing; + } + + existing.LogTimeStamp = processingLog.LogTimeStamp; + existing.LogMessage = processingLog.LogMessage; + existing.UserName = processingLog.UserName; + + _processingLogRepository.Update(existing); + _unitOfWork.Complete(); + + return existing; + } + catch (SqlException sqlException) + { + Log.Error(sqlException, $"SQL Failure updating ProcessingLog. " + + $"ProcessingLogId: {processingLog.ProcessingLogId}"); + throw new ServiceException($"SQL Failure updating ProcessingLog. " + + $"ProcessingLogId: {processingLog.ProcessingLogId}"); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure updating ProcessingLog. " + + $"ProcessingLogId: {processingLog.ProcessingLogId}"); + throw new ServiceException($"Failure updating ProcessingLog. " + + $"ProcessingLogId: {processingLog.ProcessingLogId}"); + } + } + + public async Task Delete(int id) + { + try + { + var processingLog = await GetByIdAsync(id); + ArgumentNullException.ThrowIfNull(processingLog); + _processingLogRepository.Remove(processingLog); + _unitOfWork.Complete(); + } + catch (SqlException sqlException) + { + Log.Error(sqlException, $"SQL failure removing ProcessingLog. ProcessingLogId: {id}"); + throw new ServiceException($"SQL failure removing ProcessingLog. ProcessingLogId: {id}"); + } + catch (Exception exception) + { + Log.Error(exception, $"Failure removing ProcessingLog. ProcessingLogId: {id}"); + throw new ServiceException($"Failure removing ProcessingLog. ProcessingLogId: {id}"); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueBatchIngestionService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueBatchIngestionService.cs new file mode 100644 index 0000000..d8690cd --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueBatchIngestionService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public interface IQueueBatchIngestionService +{ + Task QueueBatchIngestionRequest(BatchIngestionRequest request); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueBatchUpdateMemberNotificationDataService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueBatchUpdateMemberNotificationDataService.cs new file mode 100644 index 0000000..50d7283 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueBatchUpdateMemberNotificationDataService.cs @@ -0,0 +1,8 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; + +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public interface IQueueBatchUpdateMemberNotificationDataService +{ + Task QueueBatchUpdateMemberNotificationDataRequest(BatchUpdateMemberNotificationDataRequest request); +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueCompletionService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueCompletionService.cs new file mode 100644 index 0000000..9786585 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueCompletionService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public interface IQueueCompletionService +{ + Task QueueCompletionRequest(ProcessingRequest request, ProcessResult result); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueDocumentIngestorService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueDocumentIngestorService.cs new file mode 100644 index 0000000..913b979 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueDocumentIngestorService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public interface IQueueDocumentIngestorService +{ + Task QueueDocumentIngestorRequest(IngestorRequest request); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueDocumentProcessingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueDocumentProcessingService.cs new file mode 100644 index 0000000..76cd96f --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueDocumentProcessingService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public interface IQueueDocumentProcessingService +{ + Task QueueDocumentProcessingRequest(ProcessingRequest request); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueGatherMemberNotificationInfoService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueGatherMemberNotificationInfoService.cs new file mode 100644 index 0000000..14715a4 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueGatherMemberNotificationInfoService.cs @@ -0,0 +1,8 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; + +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public interface IQueueGatherMemberNotificationInfoService +{ + Task QueueGatherMemberNotificationInfoRequest(GatherMemberNotificationInfoRequest request); +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueIngestionFolderCleanUpService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueIngestionFolderCleanUpService.cs new file mode 100644 index 0000000..30eb052 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueIngestionFolderCleanUpService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public interface IQueueIngestionFolderCleanUpService +{ + Task QueueIngestionFolderCleanUpRequest(IngestionFolderCleanUpRequest request); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueMemberDocumentNotifierService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueMemberDocumentNotifierService.cs new file mode 100644 index 0000000..1f11e2b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueMemberDocumentNotifierService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public interface IQueueMemberDocumentNotifierService +{ + Task QueueMemberDocumentNotifierRequest(MemberDocumentNotificationRequest memberDocumentNotificationRequest); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueMemberNotificationCompletionService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueMemberNotificationCompletionService.cs new file mode 100644 index 0000000..0309e53 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueMemberNotificationCompletionService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public interface IQueueMemberNotificationCompletionService +{ + Task QueueMemberNotificationCompletionRequest(MemberNotificationCompletionRequest request, bool success, List messages); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueuePdfPartitionerCompletionService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueuePdfPartitionerCompletionService.cs new file mode 100644 index 0000000..43b5e46 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueuePdfPartitionerCompletionService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public interface IQueuePdfPartitionerCompletionService +{ + Task QueuePdfPartitionerCompletionRequest(PdfPartitionerResult result); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueuePdfPartitionerService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueuePdfPartitionerService.cs new file mode 100644 index 0000000..4e62058 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueuePdfPartitionerService.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public interface IQueuePdfPartitionerService +{ + Task QueuePdfPartitionerRequest(PdfPartitionerRequest request); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueProcessStatusTypeEmailService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueProcessStatusTypeEmailService.cs new file mode 100644 index 0000000..e687dc5 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IQueueProcessStatusTypeEmailService.cs @@ -0,0 +1,8 @@ +using LCU.Library.Internal.DocumentIngestorModels.Requests; + +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public interface IQueueProcessStatusTypeEmailService +{ + Task QueueProcessStatusTypeEmailRequest(ProcessStatusTypeEmailRequest request); +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IResponseQueue.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IResponseQueue.cs new file mode 100644 index 0000000..efadccc --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/IResponseQueue.cs @@ -0,0 +1,8 @@ +using LCU.Library.Internal.DocumentIngestorModels.Models; + +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public interface IResponseQueue +{ + Task Enqueue(IngestorRequest ingestorRequest, bool success, List messages); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueBatchIngestionService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueBatchIngestionService.cs new file mode 100644 index 0000000..0dde4f1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueBatchIngestionService.cs @@ -0,0 +1,35 @@ +using MassTransit; +using Serilog; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public class QueueBatchIngestionService : IQueueBatchIngestionService +{ + private readonly ISendEndpoint _sendEndpoint; + + public QueueBatchIngestionService(IBusControl busControl, + ReceiveEndpointConfigurations receiveEndpointConfigurations) + { + _sendEndpoint = busControl.GetSendEndpoint(receiveEndpointConfigurations.BatchIngestionReceiveEndpoint.ReceiveEndpointUri).Result; + } + + public async Task QueueBatchIngestionRequest(BatchIngestionRequest request) + { + try + { + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await _sendEndpoint.Send(request, cancellationTokenSource.Token); + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, "Failed to Queue Batch Ingestion Request."); + throw new ServiceException("Failed to Queue Batch Ingestion Request."); + } + } +} + diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueBatchUpdateMemberNotificationDataService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueBatchUpdateMemberNotificationDataService.cs new file mode 100644 index 0000000..3658830 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueBatchUpdateMemberNotificationDataService.cs @@ -0,0 +1,34 @@ +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using MassTransit; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public class QueueBatchUpdateMemberNotificationDataService : IQueueBatchUpdateMemberNotificationDataService +{ + private readonly ISendEndpoint _sendEndpoint; + + public QueueBatchUpdateMemberNotificationDataService(IBusControl busControl, + ReceiveEndpointConfigurations receiveEndpointConfigurations) + { + _sendEndpoint = busControl.GetSendEndpoint(receiveEndpointConfigurations.BatchUpdateMemberNotificationDataEndpoint.ReceiveEndpointUri).Result; + } + public async Task QueueBatchUpdateMemberNotificationDataRequest(BatchUpdateMemberNotificationDataRequest request) + { + try + { + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await _sendEndpoint.Send(request, cancellationTokenSource.Token); + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, "Failed to Queue Batch Update Member Notification Data Request."); + throw new ServiceException("Failed to Queue Batch Update Member Notification Data Request."); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueCompletionService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueCompletionService.cs new file mode 100644 index 0000000..5ae5a6c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueCompletionService.cs @@ -0,0 +1,56 @@ +using MassTransit; +using Serilog; +using Newtonsoft.Json; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Configurations; +using ApiResponse = LCU.Library.Internal.ApiResponse.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.RetryUtilities; + +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public class QueueCompletionService : IQueueCompletionService +{ + private readonly ISendEndpoint _sendEndpoint; + private readonly ApiConfiguration _apiConfiguration; + + public QueueCompletionService(IBusControl busControl, + ReceiveEndpointConfigurations receiveEndpointConfigurations, + ApiConfiguration apiConfiguration) + { + _sendEndpoint = busControl.GetSendEndpoint( + receiveEndpointConfigurations.DocumentIngestorCompletionReceiveEndpoint.ReceiveEndpointUri).Result; + _apiConfiguration = apiConfiguration; + } + + public async Task QueueCompletionRequest(ProcessingRequest request, ProcessResult result) + { + try + { + var completionRequest = new CompletionRequest() + { + ProcessingRequest = request, + ProcessResult = result + }; + + var responseRequest = new ApiResponse.Response() + { + Successful = result.Success, + ResponsePayload = JsonConvert.SerializeObject(completionRequest) + }; + + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + + var retryPolicy = RetryUtilities.GetRetryPolicy(_apiConfiguration.CompletionRetryCount); + await retryPolicy.ExecuteAsync(async () => + { + await _sendEndpoint.Send(responseRequest, cancellationTokenSource.Token); + }); + } + catch (Exception exception) + { + Log.Error(exception, "Failed to Queue Completion Request."); + throw new ServiceException("Failed to Queue Completion Request."); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueDocumentIngestorService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueDocumentIngestorService.cs new file mode 100644 index 0000000..8387a5b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueDocumentIngestorService.cs @@ -0,0 +1,35 @@ +using MassTransit; +using Serilog; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public class QueueDocumentIngestorService : IQueueDocumentIngestorService +{ + private readonly ISendEndpoint _sendEndpoint; + + public QueueDocumentIngestorService(IBusControl busControl, + ReceiveEndpointConfigurations receiveEndpointConfigurations) + { + _sendEndpoint = busControl.GetSendEndpoint(receiveEndpointConfigurations.DocumentIngestorReceiveEndpoint.ReceiveEndpointUri).Result; + } + + public async Task QueueDocumentIngestorRequest(IngestorRequest request) + { + try + { + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await _sendEndpoint.Send(request, cancellationTokenSource.Token); + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, "Failed to Queue Document Ingestor Request."); + throw new ServiceException("Failed to Queue Document Ingestor Request."); + } + } +} + diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueDocumentProcessingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueDocumentProcessingService.cs new file mode 100644 index 0000000..1097366 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueDocumentProcessingService.cs @@ -0,0 +1,35 @@ +using MassTransit; +using Serilog; +using LCU.Library.Internal.Exceptions; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public class QueueDocumentProcessingService : IQueueDocumentProcessingService +{ + private readonly ISendEndpoint _sendEndpoint; + + public QueueDocumentProcessingService(IBusControl busControl, + ReceiveEndpointConfigurations receiveEndpointConfigurations) + { + _sendEndpoint = busControl.GetSendEndpoint(receiveEndpointConfigurations.DocumentIngestorProcessingReceiveEndpoint.ReceiveEndpointUri).Result; + } + + public async Task QueueDocumentProcessingRequest(ProcessingRequest request) + { + try + { + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await _sendEndpoint.Send(request, cancellationTokenSource.Token); + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, "Failed to Queue Document Processing Request."); + throw new ServiceException("Failed to Queue Document Processing Request."); + } + } + +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueGatherMemberNotificationInfoService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueGatherMemberNotificationInfoService.cs new file mode 100644 index 0000000..1d58113 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueGatherMemberNotificationInfoService.cs @@ -0,0 +1,35 @@ +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using MassTransit; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public class QueueGatherMemberNotificationInfoService : IQueueGatherMemberNotificationInfoService +{ + private readonly ISendEndpoint _sendEndpoint; + + public QueueGatherMemberNotificationInfoService(IBusControl busControl, + ReceiveEndpointConfigurations receiveEndpointConfigurations) + { + _sendEndpoint = busControl.GetSendEndpoint(receiveEndpointConfigurations.GatherMemberNotificationInfoReceiveEndpoint.ReceiveEndpointUri).Result; + } + + public async Task QueueGatherMemberNotificationInfoRequest(GatherMemberNotificationInfoRequest request) + { + try + { + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await _sendEndpoint.Send(request, cancellationTokenSource.Token); + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, "Failed to Queue Gather Member Notification Info Request."); + throw new ServiceException("Failed to Queue Gather Member Notification Info Request."); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueIngestionFolderCleanUpService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueIngestionFolderCleanUpService.cs new file mode 100644 index 0000000..c4149c5 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueIngestionFolderCleanUpService.cs @@ -0,0 +1,34 @@ +using MassTransit; +using Serilog; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public class QueueIngestionFolderCleanUpService : IQueueIngestionFolderCleanUpService +{ + private readonly ISendEndpoint _sendEndpoint; + + public QueueIngestionFolderCleanUpService(IBusControl busControl, + ReceiveEndpointConfigurations receiveEndpointConfigurations) + { + _sendEndpoint = busControl.GetSendEndpoint(receiveEndpointConfigurations.IngestionFolderCleanUpReceiveEndpoint.ReceiveEndpointUri).Result; + } + + public async Task QueueIngestionFolderCleanUpRequest(IngestionFolderCleanUpRequest request) + { + try + { + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await _sendEndpoint.Send(request, cancellationTokenSource.Token); + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, "Failed to Queue IngestionFolderCleanUp Request."); + throw new ServiceException("Failed to Queue IngestionFolderCleanUp Request."); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueMemberDocumentNotifierService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueMemberDocumentNotifierService.cs new file mode 100644 index 0000000..a7258ad --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueMemberDocumentNotifierService.cs @@ -0,0 +1,35 @@ +using MassTransit; +using Serilog; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.Api.Internal.MaidBotLib.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public class QueueMemberDocumentNotifierService : IQueueMemberDocumentNotifierService +{ + private readonly ISendEndpoint _sendEndpoint; + + public QueueMemberDocumentNotifierService(IBusControl busControl, + ReceiveEndpointConfigurations receiveEndpointConfigurations) + { + _sendEndpoint = busControl.GetSendEndpoint(receiveEndpointConfigurations.MemberDocumentNotifierEndpoint.ReceiveEndpointUri).Result; + } + + public async Task QueueMemberDocumentNotifierRequest(MemberDocumentNotificationRequest memberDocumentNotificationRequest) + { + try + { + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await _sendEndpoint.Send(memberDocumentNotificationRequest, cancellationTokenSource.Token); + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, "Failed to Queue Member Document Notifier Request."); + throw new ServiceException("Failed to Queue Member Document Notifier Request."); + } + } +} + diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueMemberNotificationCompletionService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueMemberNotificationCompletionService.cs new file mode 100644 index 0000000..bca43cc --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueMemberNotificationCompletionService.cs @@ -0,0 +1,44 @@ +using MassTransit; +using Serilog; +using Newtonsoft.Json; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using ApiResponse = LCU.Library.Internal.ApiResponse.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public class QueueMemberNotificationCompletionService : IQueueMemberNotificationCompletionService +{ + private readonly ISendEndpoint _sendEndpoint; + + public QueueMemberNotificationCompletionService(IBusControl busControl, + ReceiveEndpointConfigurations receiveEndpointConfigurations) + { + _sendEndpoint = busControl.GetSendEndpoint(receiveEndpointConfigurations.MemberNotificationCompletionEndpoint.ReceiveEndpointUri).Result; + } + + public async Task QueueMemberNotificationCompletionRequest(MemberNotificationCompletionRequest request, bool success, List messages) + { + try + { + var responseRequest = new ApiResponse.Response() + { + Successful = success, + ResponsePayload = JsonConvert.SerializeObject(request), + ResponseStack = messages + }; + + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await _sendEndpoint.Send(responseRequest, cancellationTokenSource.Token); + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, "Failed to Queue Member Notification Completion Request."); + throw new ServiceException("Failed to Queue Member Notification Completion Request."); + } + } +} + diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueuePdfPartitionerCompletionService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueuePdfPartitionerCompletionService.cs new file mode 100644 index 0000000..1a30594 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueuePdfPartitionerCompletionService.cs @@ -0,0 +1,43 @@ +using MassTransit; +using Serilog; +using Newtonsoft.Json; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using ApiResponse = LCU.Library.Internal.ApiResponse.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public class QueuePdfPartitionerCompletionService : IQueuePdfPartitionerCompletionService +{ + private readonly ISendEndpoint _sendEndpoint; + + public QueuePdfPartitionerCompletionService(IBusControl busControl, + ReceiveEndpointConfigurations receiveEndpointConfigurations) + { + _sendEndpoint = busControl.GetSendEndpoint(receiveEndpointConfigurations.PdfPartitionerCompletionEndpoint.ReceiveEndpointUri).Result; + } + + public async Task QueuePdfPartitionerCompletionRequest(PdfPartitionerResult result) + { + try + { + var responseRequest = new ApiResponse.Response() + { + Successful = !result.FailedToQueueToParse, + ResponsePayload = JsonConvert.SerializeObject(result) + }; + + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await _sendEndpoint.Send(responseRequest, cancellationTokenSource.Token); + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, "Failed to Queue Pdf Partitioner Result."); + throw new ServiceException("Failed to Queue Pdf Partitioner Result."); + } + } +} + diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueuePdfPartitionerService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueuePdfPartitionerService.cs new file mode 100644 index 0000000..b82b311 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueuePdfPartitionerService.cs @@ -0,0 +1,35 @@ +using MassTransit; +using Serilog; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public class QueuePdfPartitionerService : IQueuePdfPartitionerService +{ + private readonly ISendEndpoint _sendEndpoint; + + public QueuePdfPartitionerService(IBusControl busControl, + ReceiveEndpointConfigurations receiveEndpointConfigurations) + { + _sendEndpoint = busControl.GetSendEndpoint(receiveEndpointConfigurations.PdfPartitionerEndpoint.ReceiveEndpointUri).Result; + } + + public async Task QueuePdfPartitionerRequest(PdfPartitionerRequest request) + { + try + { + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await _sendEndpoint.Send(request, cancellationTokenSource.Token); + } + catch (Exception exception) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Fatal(exception, "Failed to Queue Pdf Partitioner Request."); + throw new ServiceException("Failed to Queue Pdf Partitioner Request."); + } + } +} + diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueProcessStatusTypeEmailService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueProcessStatusTypeEmailService.cs new file mode 100644 index 0000000..4ec7d67 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/QueueProcessStatusTypeEmailService.cs @@ -0,0 +1,35 @@ +using LCU.Api.Internal.MaidBotLib.Models; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.Library.Internal.DocumentIngestorModels.Requests; +using LCU.Library.Internal.Exceptions; +using MassTransit; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public class QueueProcessStatusTypeEmailService : IQueueProcessStatusTypeEmailService +{ + private readonly ISendEndpoint _sendEndpoint; + + public QueueProcessStatusTypeEmailService(IBusControl busControl, + ReceiveEndpointConfigurations receiveEndpointConfigurations) + { + _sendEndpoint = busControl.GetSendEndpoint(receiveEndpointConfigurations.ProcessStatusTypeEmailReceiveEndpoint.ReceiveEndpointUri).Result; + } + + public async Task QueueProcessStatusTypeEmailRequest(ProcessStatusTypeEmailRequest request) + { + try + { + var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + await _sendEndpoint.Send(request, cancellationTokenSource.Token); + } + catch (Exception ex) + { + Log.ForContext(Enum.GetName(typeof(PropertyEnum), PropertyEnum.Group), + Enum.GetName(typeof(GroupEnum), GroupEnum.ITDevelopment)) + .Error(ex, "Failed to Queue ProcessStatusType Email Request."); + throw new ServiceException("Failed to Queue ProcessStatusType Email Request."); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/ResponseQueue.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/ResponseQueue.cs new file mode 100644 index 0000000..7d621b8 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/QueueServices/ResponseQueue.cs @@ -0,0 +1,10 @@ +using LCU.Library.Internal.ApiResponse.Services; +using LCU.Library.Internal.DocumentIngestorModels.Models; + +namespace LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +public class ResponseQueue : IResponseQueue +{ + public Task Enqueue(IngestorRequest ingestorRequest, bool success, List messages) + => QueueReturnResponse.QueueResponse(ingestorRequest, success, messages); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/UploadCompletionReprocessingService.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/UploadCompletionReprocessingService.cs new file mode 100644 index 0000000..f71d4a0 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Services/UploadCompletionReprocessingService.cs @@ -0,0 +1,166 @@ +using Newtonsoft.Json; +using Serilog; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestorLib.Extensions; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Extensions; +using LCU.Library.Internal.ApiResponse.Models; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; + +namespace LCU.API.Internal.DocumentIngestor.Services; + +public class UploadCompletionReprocessingService : IUploadCompletionReprocessingService +{ + private readonly IIngestorRunInfoService _ingestorRunInfoService; + private readonly IDocumentProcessingInfoService _documentProcessingInfoService; + private readonly IDocumentTypeRetrieverService _documentTypeRetrieverService; + private readonly IUploadCompletionService _uploadCompletionService; + private readonly ApiConfiguration _apiConfiguration; + + private const string DocumentIdKey = "DocumentId"; + + public UploadCompletionReprocessingService(IIngestorRunInfoService ingestorRunInfoService, + IDocumentProcessingInfoService documentProcessingInfoService, + IDocumentTypeRetrieverService documentTypeRetrieverService, + IUploadCompletionService uploadCompletionService, + ApiConfiguration apiConfiguration) + { + _ingestorRunInfoService = ingestorRunInfoService; + _documentProcessingInfoService = documentProcessingInfoService; + _documentTypeRetrieverService = documentTypeRetrieverService; + _uploadCompletionService = uploadCompletionService; + _apiConfiguration = apiConfiguration; + } + + public async Task QueueReprocessUploadCompletionByDocumentProcessingInfoId(int documentProcessingInfoId, string userName) + { + try + { + var logMessage = $"Notification reprocess run of DocumentProcessingInfoId: {documentProcessingInfoId} by {userName} on {DateTime.Now}"; + await QueueUploadCompletionRequest(documentProcessingInfoId, logMessage, userName); + } + catch (ArgumentNullException exception) + { + Log.Error(exception, "Failure to reprocess UploadCompletion, DocumentProcessingInfo could not be found. " + + $"DocumentProcessingInfoId: {documentProcessingInfoId}"); + throw; + } + catch (Exception exception) + { + Log.Error(exception, $"Failure reprocessing UploadCompletion for DocumentProcessingInfo. DocumentProcessingInfoId: {documentProcessingInfoId}"); + throw new ServiceException($"Failure reprocessing notification for DocumentProcessingInfo. DocumentProcessingInfoId: {documentProcessingInfoId}"); + } + } + + public async Task QueueReprocessAllNotificationDataFailures(string userName) + { + try + { + var result = await _documentProcessingInfoService.GetByProcessStatusTypeAsync(ProcessStatusTypes.NotificationDataFailure); + var documentProcessingInfos = result.Take(_apiConfiguration.NotificationDataFailureReprocessLimit); + + foreach (var documentProcessingInfo in documentProcessingInfos) + { + await QueueReprocessUploadCompletionByDocumentProcessingInfoId(documentProcessingInfo.DocumentProcessingInfoId, userName); + } + } + catch (ArgumentNullException exception) + { + var message = "Failure during reprocess of DocumentProcessingInfos of " + + $"ProcessStatusType: NotificationDataFailure. ExceptionMessage: {exception.Message}"; + Log.Error(exception, message); + throw new ServiceException(message); + } + catch (Exception exception) + { + var message = + "Failure to reprocess all DocumentProcessingInfos with ProcessStatusType: NotificationDataFailure."; + Log.Error(exception, message); + throw new ServiceException(message); + } + } + + private async Task QueueUploadCompletionRequest(int documentProcessingInfoId, string logMessage, string userName) + { + var response = await CreateResponse(documentProcessingInfoId); + await _documentProcessingInfoService.UpdateStatusAndAddLog(documentProcessingInfoId, ProcessStatusTypes.UploadCompletionReprocessing, logMessage, userName); + await _uploadCompletionService.HandleUploadCompletion(new List() { response }); + } + + private async Task CreateResponse(int documentProcessingInfoId) + { + var documentProcessingInfo = await _documentProcessingInfoService.GetByIdAsync(documentProcessingInfoId); + var ingestorRunInfo = await _ingestorRunInfoService.GetByIdAsync(documentProcessingInfo.IngestorRunInfoId); + + var documentId = documentProcessingInfo.DocumentId ?? + throw new ServiceException("DocumentId for DocumentProcessingInfo with " + + $"Id ({documentProcessingInfoId}) was null."); + var document = await _documentTypeRetrieverService.GetDocumentInformationById(documentId); + + var documentType = + EnumExtensions.IsDocumentTypeOf(document.Type) + ? DocumentOwnerTypes.PrimaryOwner + : EnumExtensions.IsDocumentTypeOf(document.Type) + ? DocumentOwnerTypes.AccountOwner + : EnumExtensions.IsDocumentTypeOf(document.Type) + ? DocumentOwnerTypes.Generic + : throw new NotImplementedException(); + + var entityType = + document.PersonNumbers.FilterNullsAndZerosOrDefault() != null + ? EntityTypes.Person + : document.OrganizationNumbers.FilterNullsAndZerosOrDefault() != null + ? EntityTypes.Organization + : EntityTypes.Unknown; + + var entityNumber = documentType switch + { + DocumentOwnerTypes.PrimaryOwner => + entityType == EntityTypes.Person + ? document.PersonNumbers?.FirstOrDefault() + : entityType == EntityTypes.Organization + ? document.OrganizationNumbers?.FirstOrDefault() + : null, + DocumentOwnerTypes.AccountOwner => document.AccountNumber.ToString(), + DocumentOwnerTypes.Generic => null, + _ => throw new NotImplementedException() + }; + + var request = new CompletionRequest() + { + ProcessingRequest = new ProcessingRequest() + { + DocumentProcessingInfoId = documentProcessingInfoId, + IngestorRunInfoId = documentProcessingInfo.IngestorRunInfoId, + DocumentFileName = documentProcessingInfo.DocumentFileName, + DocumentTypeDisplayName = documentProcessingInfo.DocumentBusinessName, + DocumentValuePayload = documentProcessingInfo.DocumentValuePayload, + IngestorRequest = new IngestorRequest() + { + IngestorType = ingestorRunInfo.IngestorType, + RootPath = ingestorRunInfo.IndexFilePath, + IndexFileName = ingestorRunInfo.IndexFileName + }, + }, + ProcessResult = ProcessResult.ProcessCompleted(new ProcessResult(), null), + MemberNotificationInfoRequest = new MemberNotificationInfoRequest() + { + DocumentProcessingInfoId = documentProcessingInfoId, + DocumentEntityNumber = entityNumber, + DocumentOwnerType = documentType, + EntityType = entityType + } + }; + + return new Response() + { + ResponsePayload = JsonConvert.SerializeObject(request), + Successful = true, + ReturnCollection = new Dictionary { { DocumentIdKey, documentId.ToString() } } + }; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Templates/NotificationEmailRowTemplate.html b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Templates/NotificationEmailRowTemplate.html new file mode 100644 index 0000000..dc2d1c2 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Templates/NotificationEmailRowTemplate.html @@ -0,0 +1,3 @@ + + {DocumentName} + \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Templates/NotificationEmailTemplate.html b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Templates/NotificationEmailTemplate.html new file mode 100644 index 0000000..069d586 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Templates/NotificationEmailTemplate.html @@ -0,0 +1,107 @@ + + + + + + + +

+ Hi {EntityName}, +

+ + + + + + + +
+ You have {NumberOfDocuments} new {DocOrDocs} ready to view. Please log into Digital Banking or the Mobile App to + ensure you don’t miss any important information. +


+ + + + + + + + + {TableRows} + +
Available {DocOrDocs}:


+ + + + + + + +
+ Thank you for being a Landmark member! +

+ Landmark Credit Union +


+ + + + + + + +
+ You are receiving this email because you have agreed to receive statement, forms, and notices from Landmark Credit Union + electronically. You have the right to withdraw your consent to receive these electronic communications at any time. To do so, + log into Online Banking and choose “Statements & Notices” and then “Manage Delivery Preferences.” After that you can choose to + “Update My Preferences.” There are no fees for choosing to withdraw your consent or for receiving these documents in paper form. +

+ For further assistance, please call (262) 796-4500. +
+ + \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Utilities/HttpUtilities.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Utilities/HttpUtilities.cs new file mode 100644 index 0000000..6b97c36 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Utilities/HttpUtilities.cs @@ -0,0 +1,307 @@ +using LCU.Library.Internal.Exceptions; +using Serilog; +using System.Text; +using System.Text.Json; +using JsonSerializer = System.Text.Json.JsonSerializer; +using Newtonsoft.Json; +using LCU.Library.Internal.RetryUtilities; + +namespace LCU.API.Internal.DocumentIngestor.Utilities; + +public class HttpUtilities +{ + public static HttpClient CreateClient(Uri uri) + { + var handler = new HttpClientHandler + { + SslProtocols = System.Security.Authentication.SslProtocols.Tls12 | + System.Security.Authentication.SslProtocols.Tls11 | + System.Security.Authentication.SslProtocols.Tls, + ServerCertificateCustomValidationCallback = (sender, cert, chain, sslPolicyErrors) => true + }; + + var httpClient = new HttpClient(handler) + { + Timeout = TimeSpan.FromSeconds(60), + BaseAddress = uri + }; + + return httpClient; + } + + public static async Task PostAsync(Uri uri, TRequest request, int retryCount = 0) + { + try + { + var client = CreateClient(uri); + var jsonBody = JsonSerializer.Serialize(request); + var content = new StringContent(jsonBody, Encoding.UTF8, "application/json"); + var retryPolicy = RetryUtilities.GetRetryPolicy(retryCount); + await retryPolicy.ExecuteAsync(async () => + { + var response = await client.PostAsync(uri, content); + + if (!response.IsSuccessStatusCode) + { + throw new ServiceException($"StatusCode:{response.StatusCode}, " + + $"Content: {response.Content.ReadAsStringAsync().Result}"); + } + return response; + }); + } + catch (Exception exception) + { + Log.Error(exception, "Failure during PostAsync."); + throw new ServiceException($"Failure during PostAsync. Exception Message: {exception.Message}"); + } + } + + public static async Task PostAsync(Uri uri, + TRequest request, + Dictionary? headers, + int retryCount = 0) + { + try + { + var client = CreateClient(uri); + client = AddApiSecurityHeaders(client, headers); + var jsonBody = JsonSerializer.Serialize(request); + var content = new StringContent(jsonBody, Encoding.UTF8, "application/json"); + var retryPolicy = RetryUtilities.GetRetryPolicy(retryCount); + await retryPolicy.ExecuteAsync(async () => + { + var response = await client.PostAsync(uri, content); + + if (!response.IsSuccessStatusCode) + { + throw new ServiceException($"StatusCode:{response.StatusCode}, " + + $"Content: {response.Content.ReadAsStringAsync().Result}"); + } + return response; + }); + } + catch (Exception exception) + { + Log.Error(exception, "Failure during PostAsync."); + throw new ServiceException($"Failure during PostAsync. Exception Message: {exception.Message}"); + } + } + + public static async Task PostAsync(Uri uri, TRequest request, int retryCount = 0, int timeoutSeconds = 60) + { + try + { + var client = CreateClient(uri); + client.Timeout = TimeSpan.FromSeconds(timeoutSeconds); + var jsonBody = JsonSerializer.Serialize(request); + var content = new StringContent(jsonBody, Encoding.UTF8, "application/json"); + var retryPolicy = RetryUtilities.GetRetryPolicy(retryCount); + var result = await retryPolicy.ExecuteAsync(async () => + { + var response = await client.PostAsync(uri, content); + + if (!response.IsSuccessStatusCode) + { + throw new ServiceException($"StatusCode:{response.StatusCode}, " + + $"Content: {response.Content.ReadAsStringAsync().Result}"); + } + + var stringResponse = await response.Content.ReadAsStringAsync(); + + return JsonSerializer.Deserialize(stringResponse, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + }); + return result; + } + catch (Exception exception) + { + Log.Error(exception, "Failure during PostAsync."); + throw new ServiceException($"Failure during PostAsync. Exception Message: {exception.Message}"); + } + } + + public static async Task PostStringResponseAsync(Uri uri, TRequest request, int retryCount = 0) + { + try + { + var client = CreateClient(uri); + var jsonBody = JsonSerializer.Serialize(request); + var content = new StringContent(jsonBody, Encoding.UTF8, "application/json"); + var retryPolicy = RetryUtilities.GetRetryPolicy(retryCount); + var result = await retryPolicy.ExecuteAsync(async () => + { + var response = await client.PostAsync(uri, content); + if (!response.IsSuccessStatusCode) + { + throw new ServiceException($"StatusCode:{response.StatusCode}, " + + $"Content: {response.Content.ReadAsStringAsync().Result}"); + } + + return await response.Content.ReadAsStringAsync(); + }); + return result; + } + catch (Exception exception) + { + Log.Error(exception, "Failure during PostAsync."); + throw new ServiceException($"Failure during PostAsync. Exception Message: {exception.Message}"); + } + } + + + public static async Task GetByteArrayAsync(Uri uri, int retryCount = 0) + { + try + { + var client = CreateClient(uri); + var retryPolicy = RetryUtilities.GetRetryPolicy(retryCount); + var result = await retryPolicy.ExecuteAsync(async () => + { + var response = await client.GetAsync(uri); + if (!response.IsSuccessStatusCode) + { + throw new ServiceException($"StatusCode:{response.StatusCode}, " + + $"Content: {response.Content.ReadAsStringAsync().Result}"); + } + + return await response.Content.ReadAsByteArrayAsync(); + }); + return result; + } + catch (Exception exception) + { + Log.Error(exception, "Failure during GetByteArrayAsync."); + throw new ServiceException($"Failure during GetByteArrayAsync. Exception Message: {exception.Message}"); + } + } + + public static async Task GetStringResponseAsync(Uri uri, int retryCount = 0) + { + try + { + var client = CreateClient(uri); + var retryPolicy = RetryUtilities.GetRetryPolicy(retryCount); + var result = await retryPolicy.ExecuteAsync(async () => + { + var response = await client.GetAsync(uri); + if (!response.IsSuccessStatusCode) + { + throw new ServiceException($"StatusCode:{response.StatusCode}, " + + $"Content: {response.Content.ReadAsStringAsync().Result}"); + } + + return await response.Content.ReadAsStringAsync(); + }); + return result; + } + catch (Exception exception) + { + Log.Error(exception, "Failure during GetStringResponseAsync."); + throw new ServiceException($"Failure during GetStringResponseAsync. Exception Message: {exception.Message}"); + } + } + + public static async Task GetAsync(string url, int retryCount = 0) + { + try + { + var uri = new Uri(url); + var client = CreateClient(uri); + + var retryPolicy = RetryUtilities.GetRetryPolicy(retryCount); + var result = await retryPolicy.ExecuteAsync(async () => + { + var response = await client.GetAsync(uri); + if (!response.IsSuccessStatusCode) + { + throw new ServiceException($"StatusCode:{response.StatusCode}, " + + $"Content: {response.Content.ReadAsStringAsync().Result}"); + } + var stringResponse = await response.Content.ReadAsStringAsync(); + return JsonSerializer.Deserialize(stringResponse, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + }); + + return result; + } + catch (Exception exception) + { + Log.Error(exception, "Failure during GetAsync."); + throw new ServiceException($"Failure during GetAsync. Exception Message: {exception.Message}"); + } + } + + + public static async Task GetAsync(Uri uri, + Dictionary headers, + int retryCount = 0) + { + try + { + var client = CreateClient(uri); + client = AddApiSecurityHeaders(client, headers); + var retryPolicy = RetryUtilities.GetRetryPolicy(retryCount); + var result = await retryPolicy.ExecuteAsync(async () => + { + var response = await client.GetAsync(uri); + + if (!response.IsSuccessStatusCode) + { + throw new ServiceException($"StatusCode:{response.StatusCode}, " + + $"Content: {response.Content.ReadAsStringAsync().Result}"); + } + + var stringResponse = await response.Content.ReadAsStringAsync(); + return JsonConvert.DeserializeObject(stringResponse); + }); + return result; + } + catch (Exception exception) + { + Log.Error(exception, "Failure during GetAsync."); + throw new ServiceException($"Failure during GetAsync. Exception Message: {exception.Message}"); + } + } + + public static async Task GetAsyncNewton(string url, + Dictionary? headers = null, + int retryCount = 0) + { + try + { + var uri = new Uri(url); + var client = CreateClient(uri); + client = AddApiSecurityHeaders(client, headers); + var retryPolicy = RetryUtilities.GetRetryPolicy(retryCount); + var result = await retryPolicy.ExecuteAsync(async () => + { + var response = await client.GetAsync(uri); + if (!response.IsSuccessStatusCode) + { + throw new ServiceException($"StatusCode:{response.StatusCode}, " + + $"Content: {response.Content.ReadAsStringAsync().Result}"); + } + + var stringResponse = await response.Content.ReadAsStringAsync(); + return JsonConvert.DeserializeObject(stringResponse); + }); + + return result; + } + catch (Exception exception) + { + Log.Error(exception, "Failure during GetAsync."); + throw new ServiceException($"Failure during GetAsync. Exception Message: {exception.Message}"); + } + } + + public static HttpClient AddApiSecurityHeaders(HttpClient client, Dictionary headers) + { + if (headers == null) return client; + + foreach (var (key, value) in headers) + { + client.DefaultRequestHeaders.Add(key, value); + } + + return client; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Utilities/SpecialCharacters.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Utilities/SpecialCharacters.cs new file mode 100644 index 0000000..3731f39 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Utilities/SpecialCharacters.cs @@ -0,0 +1,33 @@ +using LCU.Library.Internal.Exceptions; +using Serilog; + +namespace LCU.API.Internal.DocumentIngestor.Utilities +{ + public class SpecialCharacters + { + private static Dictionary specialCharactersDictionary = new Dictionary() + { + { @"(",@"\(" }, + { @")",@"\)" } + }; + + public static string EscapeSpecialCharacters(string text) + { + try + { + foreach (string character in specialCharactersDictionary.Keys) + { + text = text.Replace(character, $@"{specialCharactersDictionary[character]}"); + } + + return text; + } + catch(Exception exception) + { + Log.Error(exception, $"Failure during EscapeSpecialCharacters on text {text}"); + throw new ServiceException($"Failure during EscapeSpecialCharacters on text {text}. Exception Message: {exception.Message}"); + } + } + + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Utilities/ToDetailStringExtension.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Utilities/ToDetailStringExtension.cs new file mode 100644 index 0000000..c863cec --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/Utilities/ToDetailStringExtension.cs @@ -0,0 +1,32 @@ +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Tax; + +namespace LCU.API.Internal.DocumentIngestor.Utilities; + +public static class ToDetailStringExtension +{ + public static string ToDetailString(this IEnumerable owners) => + string.Join("; ", owners.Select(o => o.ToDetailString())); + + public static string ToDetailString(this AccountOwnership owner) => owner.PersonNumber != 0 + ? FormatPersonDetailString(owner.FirstName, owner.MiddleName, owner.LastName, owner.PersonNumber) + : FormatOrganizationDetailString(owner.OrganizationName, owner.ByOrgNbr); + + public static string ToDetailString(this IEnumerable owners) => + string.Join("; ", owners.Select(o => o.ToDetailString())); + + public static string ToDetailString(this PersonTaxIdDataResponse owner) => + FormatPersonDetailString(owner.FirstName, owner.MiddleName, owner.LastName, owner.PersonNumber); + + public static string ToDetailString(this IEnumerable owners) => + string.Join("; ", owners.Select(o => o.ToDetailString())); + + public static string ToDetailString(this OrganizationTaxIdDataResponse owner) => + FormatOrganizationDetailString(owner.Name, owner.OrganizationNumber); + + private static string FormatPersonDetailString(string firstName, string middleName, string lastName, long id) => + $"Person Detail: First Name {firstName}, Middle {middleName}, Last {lastName} and ID {id}"; + + private static string FormatOrganizationDetailString(string name, long id) => + $"Organization Detail: Organization Name {name} and ID {id}"; +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/appsettings.json b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/appsettings.json new file mode 100644 index 0000000..ec84a46 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestor/appsettings.json @@ -0,0 +1,392 @@ +{ + "Primary": { + "AppName": "Document Ingestor Api", + "SeqUrl": "http://localhost:5080", + "SeqKey": "9MQu0vLDwQ1LCFzGixZM", + "TimeZone": "America/Chicago", + "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" + ], + "CriticalFailureReprocessLimit": 1000, + "NotificationDataFailureReprocessLimit": 1000, + "CompletionRetryCount": 5, + "DocumentProcessingReQueueCountLimit": 1, + "FileUploadCutoffHours": -2, + "MaxMemberNotificationAttempts": 3, + "MaliciousFileSearchPaddingHours": 1, + "NotificationEmailTemplate": "./Templates/NotificationEmailTemplate.html", + "NotificationEmailRowTemplate": "./Templates/NotificationEmailRowTemplate.html", + "FeatureFlags": { + "RunBatchIngestionConsumer": true, + "RunIngestorIndexConsumer": true, + "RunIngestorProcessingConsumer": true, + "RunIngestorCompletionConsumer": true, + "RunIngestionFolderCleanUpConsumer": true, + "RunPdfPartitionerConsumer": true, + "RunPdfPartitionerCompletionConsumer": true, + "RunUploadCompletionConsumer": true, + "RunMemberDocumentNotifierConsumer": true, + "RunMemberNotificationCompletionConsumer": true, + "RunGatherMemberNotificationInfoConsumer": true, + "RunBatchUpdateMemberNotificationDataConsumer": true, + "RestrictNotificationRecipients": true, + "RunProcessStatusTypeSummaryConsumer": true + }, + "DocumentIngestorApiKey": "bbdbbb74-1b4d-4140-889e-08f2d7a1d711", + "IsHistoric": false, + "BatchSkipAmount": 10000, + "Notifications": { + "AllowedRecipientExpression": "leslie\\.ann\\.perkins@gmail\\.com|LeslieSauck@landmarkcu\\.com|JoshuaAnnear@landmarkcu\\.com|BenVandervort@landmarkcu\\.com|WendySchenk@landmarkcu\\.com|PriyaDuba@landmarkcu\\.com|FredDebelack@landmarkcu\\.com|leslie.sauck@gmail\\.com|lesliesauck@nvisia\\.com|mitchpotrykus@nvisia\\.com|TaylorSullivan@landmarkcu\\.com|tsullivan@nvisia\\.com|MitchPotrykus@landmarkcu\\.com|mpotrykus@nvisia\\.com|John-PaulEnsign@landmarkcu\\.com|jpensign@nvisia\\.com|ChristopherDykstra@landmarkcu\\.com|cdykstra@nvisia\\.com|BarbVandenburg@landmarkcu\\.com|barbv@nvisia\\.com" + } + }, + "ApiHealthCheckConfiguration": { + "VaultStatusConfiguration": { + "RunVaultStatusCheck": true, + "EnvironmentFromVault": "", + "EnvironmentFromConfigmap": "local" + } + }, + "AzureAd": { + "Instance": "https://login.microsoftonline.com/", + "Domain": "landmarkcu.onmicrosoft.com", + "TenantId": "63cd1554-2783-4a86-ae50-b9e6c21c9499", + "CallbackPath": "/signin-oidc", + "ClientId": "27a3a812-7338-4c55-81ac-33c415e8b401", + "ClientSecret": "qS48Q~qY0ltLSpNuD4p3K3zimrem8QHHx1-aZabl" + }, + "ApplicationInsights": { + "InstrumentationKey": "Azure-Key-Vault" + }, + "Security": { + "ITRole": "Doc_Mgr_IT_Admin,QA_Testing" + }, + "Swagger": { + "OAuthScope": "api://27a3a812-7338-4c55-81ac-33c415e8b401/user.groups" + }, + "SqlConnectionConfiguration": { + "ConnectionString": "data source=localhost;initial catalog=DocumentIngestor;Integrated Security=SSPI;MultipleActiveResultSets=True;App=EntityFramework;Encrypt=False;", + "MaxRetryCount": 3, + "MaxRetryDelay": "00:00:30" + }, + "ConnectionConfiguration": { + "HostUrl": "localhost", + "UserName": "guest", + "Password": "guest" + }, + "BatchIngestionReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.BatchIngestion", + "ReceiveEndpointType": "exchange", + "PrefetchLimit": 1 + }, + "DocumentIngestorReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Indexing", + "ReceiveEndpointType": "exchange", + "PrefetchLimit": 1 + }, + "DocumentIngestorProcessingReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Processing", + "ReceiveEndpointType": "exchange", + "PrefetchLimit": 1 + }, + "DocumentIngestorCompletionReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Completion", + "ReceiveEndpointType": "exchange", + "PrefetchLimit": 100 + }, + "IngestionFolderCleanUpReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.IngestionFolderCleanUp", + "ReceiveEndpointType": "exchange", + "PrefetchLimit": 1 + }, + "PdfPartitionerEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.PdfPartitioner", + "ReceiveEndpointType": "exchange", + "PrefetchLimit": 1 + }, + "PdfPartitionerCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.PdfPartitioner.Completion", + "ReceiveEndpointType": "exchange", + "PrefetchLimit": 1 + }, + "UploadCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.UploadCompletion", + "ReceiveEndpointType": "exchange", + "PrefetchLimit": 100 + }, + "MemberDocumentNotifierEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.MemberDocumentNotifier", + "ReceiveEndpointType": "exchange", + "PrefetchLimit": 1 + }, + "MemberNotificationCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.MemberNotificationCompletion", + "ReceiveEndpointType": "exchange", + "PrefetchLimit": 1 + }, + "GatherMemberNotificationInfoReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.GatherMemberNotificationInfo", + "ReceiveEndpointType": "exchange", + "PrefetchLimit": 1 + }, + "ProcessStatusTypeEmailReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.ProcessStatusTypeEmail", + "ReceiveEndpointType": "exchange", + "PrefetchLimit": 1 + }, + "BatchUpdateMemberNotificationDataEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.BatchUpdateMemberNotificationData", + "ReceiveEndpointType": "exchange", + "PrefetchLimit": 100 + }, + "DocumentTypeUploaderConfiguration": { + "Url": "https://localhost:7039", + "QueuePrimaryOwnerDocumentUpload": "/DocumentUpload/QueuePrimaryOwnerDocumentUpload", + "QueueAccountDocumentUpload": "/DocumentUpload/QueueAccountDocumentUpload", + "QueueGenericDocumentUpload": "/DocumentUpload/QueueGenericDocumentUpload", + "RetryCount": 5 + }, + "FileOperationsApiConfiguration": { + "Url": "https://localhost:57086", + "MoveFileEndpoint": "/api/FileOperations/MoveFile", + "GetFileContentEndpoint": "/api/FileOperations", + "GetPdfContentEndpoint": "/api/Pdf/GetPdfContent", + "ValidateFileExists": "/FileValidation/ValidateFileExists", + "ValidatePdfPageExists": "/FileValidation/ValidatePdfPageExists", + "BuildDynamicDirectoryList": "/DynamicDirectory/BuildDirectoryList", + "BuildDynamicFileList": "/DynamicFile/BuildDynamicFileList", + "QueueBatchPdfParser": "/api/Pdf/QueueBatchPdfParser", + "DirectMoveFile": "/api/DirectFileOperations/MoveFile", + "DirectWriteFile": "/api/DirectFileOperations/WriteFile", + "DirectCreateDirectory": "/api/DirectFileOperations/CreateDirectory", + "DirectUnzipFile": "/api/DirectFileOperations/UnzipFile", + "DirectZipFile": "/api/DirectFileOperations/ZipDirectory", + "DirectDeleteDirectory": "/api/DirectFileOperations/DeleteDirectory", + "DirectDeleteFile": "/api/DirectFileOperations/DeleteFile", + "RetryCount": 3 + }, + "CoreApiWrapperConfiguration": { + "Url": "https://qa-core-api-wrapper-api.apps.azure.lcu-internal.com", + "GetPersonsTaxIdData": "/api/core/Tax/GetPersonsTaxIdData/{taxId}", + "GetOrganizationsTaxIdData": "/api/core/Tax/GetOrganizationsTaxIdData/{taxId}", + "GetOwnersByAccountNumber": "/api/core/Account/GetOwnersByAccountNumber", + "GetOwnersByOrganizationName": "/api/core/Account/GetPrimaryOwnersByOrganizationName/{organizationName}", + "GetOwnersByPersonName": "/api/core/Account/GetPrimaryOwnersByPersonName/{personName}", + "GetAgreeUsersByAccounts": "/api/core/Agree/AgreeUsersByAccounts", + "GetAgreeUsersByPersonNumber": "/api/core/Agree/AgreeUserByPersonNumber/{personNumber}", + "GetAgreeUserByOrganizationNumber": "/api/core/Agree/AgreeUserByOrganizationNumber/{organizationNumber}", + "GetAgreementByUserId": "/api/core/Agree/AgreementByUserId/{userId}", + "GetAgreementAccountByAccountId": "/api/core/Agree/AgreementAccountByAccountId/{accountId}", + "GetAgreementAccountsByUserId": "/api/core/Agree/AgreementAccountsByUserId/{userId}", + "GetPersonOrOrganizationNumberByMemberId": "/api/core/members/GetPersonOrOrganizationNumberByMemberId/{memberId}", + "RetryCount": 5 + }, + "NotificationApiConfiguration": { + "Url": "https://qa-notifications-api.apps.azure.lcu-internal.com", + "Email": "/api/Email", + "RetryCount": 5 + }, + "MemberPreferencesApiConfiguration": { + "Url": "https://qa-member-preferences-api.apps.azure.lcu-internal.com", + "GetMemberOptInAgreementInfoByUserId": "/api/MemberOptInSettings/AgreementInformation/{userId}", + "GetMemberOptInSettingsByUserId": "/api/MemberOptInSettings/{userId}", + "EmailSuccessfulSend": "/api/{userId}/SuccessfulSend", + "EmailFailedSend": "/api/{userId}/FailedSend", + "RetryCount": 5 + }, + "DocumentTypeRetrieverConfiguration": { + "Url": "https://qa-document-type-retriever-api.apps.azure.lcu-internal.com", + "GetDocumentCodeDetails": "/DocumentCodeDetails/Get", + "GetDocumentCodeDetail": "/DocumentCodeDetails/Get/{documentCode}", + "GetListOfMaliciousDocuments": "/Document/GetListOfMaliciousDocuments", + "GetDocumentInformationById": "/Document/GetDocumentInformationById/{documentId}", + "Username": "ven.alkami@landmarkcu.onmicrosoft.com", + "Password": "8ae8796a-b7e6-4c47-881f-e98eacf5e15f", + "RetryCount": 5 + }, + "DocumentCodeDetailCacheConfiguration": { + "CacheName": "DocumentCodeDetails", + "ExpirationMinutes": "480" + }, + "ApiSecurityConfiguration": { + "ApiKeyAuthenticationFailureBehavior": "Error", + "ExternalApiKeySet": { + "DocumentManager": "Xi01QBea7cnEspi78N2c6uVFf2wssr4N" + }, + "InternalApiKeySet": {} + }, + "DispatcherRequestBuilderConfiguration": { + "Url": "https://localhost:44380/api/Ingestion" + }, + "DispatcherJobCreationConfiguration": { + "DocumentIngestorDispatcherErrorRecipients": [ + "ITDevelopment@landmarkcu.onmicrosoft.com" + ], + "JobTags": [ + { + "jobTagId": 0, + "jobId": 0, + "tagId": 12 + }, + { + "jobTagId": 0, + "jobId": 0, + "tagId": 14 + } + ] + }, + "DigitalBankingConfiguration": { + "DigitalBankingUrl": "https://digitalbanking.landmarkcu.com/eDocs", + "MobileBankingBaseUrl": "https://qa-redirect-api.qa.applications.landmarkcu.com/index.html", + "MobileBankingApiKey": "v7ImfIl+lHlvtma8c3BMT6FbVsTisDwpeqIMesM1eN8KvTEPXByT2bOOwCy/Gbly", + "MobileBankingLinkId": "a4e648ff-247a-42a8-b153-4b65d4933d1c" + }, + "ServicesFactoryConfiguration": { + "ServiceFactoryRegistrations": [ + { + "ServiceInterfaceName": "IIndexParserService", + "ServiceRegistrations": [ + { + "ServiceName": "FosTaxStatementIndexService", + "ServiceId": "0" + }, + { + "ServiceName": "FosDnaDocumentIndexService", + "ServiceId": "1" + }, + { + "ServiceName": "XdiDnaNoticeDocumentIndexService", + "ServiceId": "2" + }, + { + "ServiceName": "FosLoanStatementIndexService", + "ServiceId": "3" + }, + { + "ServiceName": "OsgDnaNoticesIndexService", + "ServiceId": "4" + }, + { + "ServiceName": "XdiActionNoticeDocumentIndexService", + "ServiceId": "5" + }, + { + "ServiceName": "OsgHistoricalDocumentIndexService", + "ServiceId": "6" + }, + { + "ServiceName": "OsgWeilandStatementIndexService", + "ServiceId": "7" + }, + { + "ServiceName": "OsgTaxStatementIndexService", + "ServiceId": "8" + }, + { + "ServiceName": "OsgDnaNoticeSplitIndexService", + "ServiceId": "9" + }, + { + "ServiceName": "OsgTemenosNoticeDocumentIndexService", + "ServiceId": "10" + }, + { + "ServiceName": "OsgVehicleTaxStatementIndexService", + "ServiceId": "11" + } + ] + }, + { + "ServiceInterfaceName": "IPdfIndexParserService", + "ServiceRegistrations": [ + { + "ServiceName": "FosLoanStatementIndexService", + "ServiceId": "3" + }, + { + "ServiceName": "OsgDnaNoticesIndexService", + "ServiceId": "4" + }, + { + "ServiceName": "OsgHistoricalDocumentIndexService", + "ServiceId": "6" + } + ] + }, + { + "ServiceInterfaceName": "IPdfParserService", + "ServiceRegistrations": [ + { + "ServiceName": "FosLoanStatementPdfService", + "ServiceId": "0" + }, + { + "ServiceName": "OsgDnaNoticesPdfService", + "ServiceId": "1" + }, + { + "ServiceName": "OsgHistoricalDocumentPdfService", + "ServiceId": "2" + } + ] + }, + { + "ServiceInterfaceName": "IDocumentProcessingService", + "ServiceRegistrations": [ + { + "ServiceName": "FosTaxStatementProcessingService", + "ServiceId": "0" + }, + { + "ServiceName": "FosDnaDocumentProcessingService", + "ServiceId": "1" + }, + { + "ServiceName": "XdiDnaNoticeDocumentProcessingService", + "ServiceId": "2" + }, + { + "ServiceName": "FosLoanStatementProcessingService", + "ServiceId": "3" + }, + { + "ServiceName": "OsgDnaNoticesProcessingService", + "ServiceId": "4" + }, + { + "ServiceName": "XdiActionNoticesProcessingService", + "ServiceId": "5" + }, + { + "ServiceName": "OsgHistoricalDocumentProcessingService", + "ServiceId": "6" + }, + { + "ServiceName": "OsgWeilandStatementProcessingService", + "ServiceId": "7" + }, + { + "ServiceName": "OsgTaxStatementProcessingService", + "ServiceId": "8" + }, + { + "ServiceName": "OsgDnaNoticeSplitProcessingService", + "ServiceId": "9" + }, + { + "ServiceName": "OsgTemenosNoticeProcessingService", + "ServiceId": "10" + }, + { + "ServiceName": "OsgVehicleTaxStatementProcessingService", + "ServiceId": "11" + } + ] + } + ] + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Exceptions/ArchiveException.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Exceptions/ArchiveException.cs new file mode 100644 index 0000000..eabe44f --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Exceptions/ArchiveException.cs @@ -0,0 +1,15 @@ +using System; + +namespace LCU.API.Internal.DocumentIngestorLib.Exceptions +{ + public class ArchiveException : Exception + { + public ArchiveException(string message) : base(message) + { + } + + public ArchiveException(string message, Exception exception) : base(message, exception) + { + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/FilterNullsAndZerosOrDefaultExtension.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/FilterNullsAndZerosOrDefaultExtension.cs new file mode 100644 index 0000000..d1b45dd --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/FilterNullsAndZerosOrDefaultExtension.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using System.Linq; + +namespace LCU.API.Internal.DocumentIngestorLib.Extensions; + +public static class FilterNullsAndZerosOrDefaultExtension +{ + public static string[] FilterNullsAndZerosOrDefault(this IEnumerable list) + { + var filteredList = list?.Where(x => + !string.IsNullOrWhiteSpace(x) && int.Parse(x) != 0 + ).ToList(); + if (filteredList == null || !filteredList.Any()) + { + return null; + } + return filteredList.ToArray(); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoCreatedDateQueryable.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoCreatedDateQueryable.cs new file mode 100644 index 0000000..2e8d7c0 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoCreatedDateQueryable.cs @@ -0,0 +1,32 @@ +using System.Linq; +using Microsoft.EntityFrameworkCore; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; +using System; + +namespace LCU.Api.Internal.DocumentIngestorLib.Extensions.Queryables +{ + public static class DocumentProcessingInfoCreatedDateQueryable + { + public static IQueryable FilterByCreatedDate(this IQueryable queryable, Filter filter) + { + if (filter?.CreatedDateStart == null && filter?.CreatedDateEnd == null) + { + return queryable; + } + + if (filter?.CreatedDateStart == null) + { + filter.CreatedDateStart = DateTime.MinValue; + } + + if (filter?.CreatedDateEnd == null || filter?.CreatedDateEnd == DateTime.MinValue) + { + filter.CreatedDateEnd = DateTime.MaxValue; + } + + return queryable.Where(DocumentProcessingInfo => DocumentProcessingInfo.CreatedDate >= filter.CreatedDateStart && + DocumentProcessingInfo.CreatedDate <= filter.CreatedDateEnd); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoDocBusinessNameQueryable.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoDocBusinessNameQueryable.cs new file mode 100644 index 0000000..457a86a --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoDocBusinessNameQueryable.cs @@ -0,0 +1,20 @@ +using System.Linq; +using Microsoft.EntityFrameworkCore; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; + +namespace LCU.Api.Internal.DocumentIngestorLib.Extensions.Queryables +{ + public static class DocumentProcessingInfoDocBusinessNameQueryable + { + public static IQueryable FilterDocBusinessName(this IQueryable queryable, Filter filter) + { + if (filter?.DocBusinessName == null) + { + return queryable; + } + + return queryable.Where(documentProcessingInfo => documentProcessingInfo.DocumentBusinessName.Contains(filter.DocBusinessName)); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoDocTypeQueryable.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoDocTypeQueryable.cs new file mode 100644 index 0000000..b222ffa --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoDocTypeQueryable.cs @@ -0,0 +1,23 @@ +using System.Linq; +using Microsoft.EntityFrameworkCore; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; +using System.Text.RegularExpressions; + +namespace LCU.Api.Internal.DocumentIngestorLib.Extensions.Queryables +{ + public static class DocumentProcessingInfoDocTypeQueryable + { + public static IQueryable FilterDocType(this IQueryable queryable, Filter filter) + { + if (filter?.DocType == null) + { + return queryable; + } + + var filterDocType = Regex.Replace(filter.DocType, @"\s", ""); + + return queryable.Where(documentProcessingInfo => documentProcessingInfo.DocumentType.Contains(filterDocType)); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoIndexJsonEqualsFilter.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoIndexJsonEqualsFilter.cs new file mode 100644 index 0000000..c52fd7c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoIndexJsonEqualsFilter.cs @@ -0,0 +1,23 @@ +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; +using LCU.API.Internal.DocumentIngestorLib.Persistence; +using System.Linq; + +namespace LCU.Api.Internal.DocumentIngestorLib.Extensions.Queryables; + +public static class DocumentProcessingInfoIndexJsonEqualsFilter +{ + public static IQueryable FilterByIndexFileJsonKeyValueEquals( + this IQueryable queryable, Filter filter) + { + if (filter?.CustomIndexFileFiltersEquals is null) return queryable; + + var result = queryable; + foreach (var indexFilter in filter.CustomIndexFileFiltersEquals) + { + result = result.Where(d => AppDbContext.JSON_VALUE(d.DocumentValuePayload, "$." + indexFilter.Key) == indexFilter.Value); + } + + return result; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoIndexJsonLikeOrFilter.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoIndexJsonLikeOrFilter.cs new file mode 100644 index 0000000..67ef3e5 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoIndexJsonLikeOrFilter.cs @@ -0,0 +1,37 @@ +using System; +using System.Linq; +using System.Linq.Expressions; +using LCU.API.Internal.DocumentIngestorLib.Persistence; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; +using Microsoft.EntityFrameworkCore; + +namespace LCU.Api.Internal.DocumentIngestorLib.Extensions.Queryables; + +public static class DocumentProcessingInfoIndexJsonLikeOrFilter +{ + public static IQueryable FilterByIndexFileJsonKeyValueLikeOr( + this IQueryable queryable, Filter filter) + { + if (filter?.CustomIndexFileFiltersLikeOr is null) return queryable; + + var result = queryable; + + Expression> predicate = f => false; + foreach (var indexFilter in filter.CustomIndexFileFiltersLikeOr) + { + Expression> expression = d => + EF.Functions.Like(AppDbContext.JSON_VALUE(d.DocumentValuePayload, "$." + indexFilter.Key), + $"%{indexFilter.Value.Replace(" ", "%")}%"); + var invokedExpr = Expression.Invoke(expression, predicate.Parameters); + + predicate = Expression.Lambda>(Expression.OrElse(predicate.Body, invokedExpr), + predicate.Parameters); + } + + result = result.Where(predicate); + + return result; + } + +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoIngestorRunInfoIdQueryable.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoIngestorRunInfoIdQueryable.cs new file mode 100644 index 0000000..d1818df --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoIngestorRunInfoIdQueryable.cs @@ -0,0 +1,20 @@ +using System; +using System.Linq; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; + +namespace LCU.Api.Internal.DocumentIngestorLib.Extensions.Queryables +{ + public static class DocumentProcessingInfoIngestorRunInfoIdQueryable + { + public static IQueryable FilterIngestorRunInfoId(this IQueryable queryable, Filter filter) + { + if (filter.IngestorRunInfoId == null) + { + return queryable; + } + + return queryable.Where(documentProcessingInfo => documentProcessingInfo.IngestorRunInfoId == filter.IngestorRunInfoId); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoNotificationStatusQueryable.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoNotificationStatusQueryable.cs new file mode 100644 index 0000000..a653fd7 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoNotificationStatusQueryable.cs @@ -0,0 +1,18 @@ +using System.Linq; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; + +namespace LCU.Api.Internal.DocumentIngestorLib.Extensions.Queryables; + +public static class DocumentProcessingInfoNotificationStatusQueryable +{ + public static IQueryable FilterByNotificationStatusType + ( + this IQueryable queryable, + Filter filter + ) => filter?.NotificationStatusFilters is { Count: > 0 } statusFilter + ? queryable + .Where(q => q.MemberNotificationInfos != null) + .Where(q => q.MemberNotificationInfos.Any(m => statusFilter.Contains(m.NotificationStatusType))) + : queryable; +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoStatusTypeQueryable.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoStatusTypeQueryable.cs new file mode 100644 index 0000000..1fb6225 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/DocumentProcessingInfoStatusTypeQueryable.cs @@ -0,0 +1,28 @@ +using System.Linq; +using Microsoft.EntityFrameworkCore; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; + +namespace LCU.Api.Internal.DocumentIngestorLib.Extensions.Queryables +{ + public static class DocumentProcessingInfoStatusTypeQueryable + { + public static IQueryable FilterByStatusType(this IQueryable queryable, Filter filter) + { + if (filter?.StatusFilters == null || !filter.StatusFilters.Any()) + { + return queryable; + } + + var enabledStatusFilters = filter.StatusFilters.Where(statusFilter => statusFilter.IsEnabled).ToList(); + + var unknownStatusTypes = enabledStatusFilters.Where(status => status.IsUnknown).Select(status => status.StatusType); + var knownStatusTypes = enabledStatusFilters.Where(status => !status.IsUnknown).Select(status => status.StatusType); + + return queryable.Where(documentProcessingInfo => + (documentProcessingInfo.EntityUnknown && unknownStatusTypes.Contains(documentProcessingInfo.StatusType)) || + (!documentProcessingInfo.EntityUnknown && knownStatusTypes.Contains(documentProcessingInfo.StatusType)) + ); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/IncludeAllQueryable.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/IncludeAllQueryable.cs new file mode 100644 index 0000000..c9a3110 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/IncludeAllQueryable.cs @@ -0,0 +1,16 @@ +using System.Linq; +using Microsoft.EntityFrameworkCore; +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.Api.Internal.DocumentIngestorLib.Extensions.Queryables +{ + public static class IncludeAllQueryable + { + public static IQueryable IncludeAll(this IQueryable queryable) + { + return queryable.Include(documentProcessingInfo => documentProcessingInfo.IngestorRunInfo) + .Include(documentProcessingInfo => documentProcessingInfo.ProcessingLogs) + .Include(documentProcessingInfo => documentProcessingInfo.MemberNotificationInfos); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/IncludeFiltersQueryable.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/IncludeFiltersQueryable.cs new file mode 100644 index 0000000..c804c00 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/IncludeFiltersQueryable.cs @@ -0,0 +1,21 @@ +using System.Linq; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; + +namespace LCU.Api.Internal.DocumentIngestorLib.Extensions.Queryables +{ + public static class IncludeFiltersQueryable + { + public static IQueryable IncludeFilters(this IQueryable queryable, Filter filter) + { + return queryable.FilterDocType(filter) + .FilterDocBusinessName(filter) + .FilterByStatusType(filter) + .FilterByCreatedDate(filter) + .FilterByIndexFileJsonKeyValueEquals(filter) + .FilterByIndexFileJsonKeyValueLikeOr(filter) + .FilterIngestorRunInfoId(filter) + .FilterByNotificationStatusType(filter); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/SortableFieldsQueryable.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/SortableFieldsQueryable.cs new file mode 100644 index 0000000..99ae2b9 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/Queryables/SortableFieldsQueryable.cs @@ -0,0 +1,29 @@ +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; +using System.Linq; +using System.Linq.Dynamic.Core; +using System.Text; + +namespace LCU.Api.Internal.DocumentIngestorLib.Extensions.Queryables +{ + public static class SortableFieldsQueryable + { + public static IQueryable OrderBySortableFields(this IQueryable queryable, Filter filter) + { + if (filter?.SortableFields == null || !filter.SortableFields.Any()) + { + return queryable; + } + + var orderBy = new StringBuilder(); + foreach (var field in filter.SortableFields.OrderBy(sortableField => sortableField.Position)) + { + var addedComma = orderBy.ToString() == "" ? "" : " ,"; + var desc = field.IsDescending ? " desc" : ""; + orderBy.Append($"{addedComma}{field.Field}{desc}"); + } + + return queryable.OrderBy(orderBy.ToString()); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/TimeZoneDateTime.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/TimeZoneDateTime.cs new file mode 100644 index 0000000..bbaa41d --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Extensions/TimeZoneDateTime.cs @@ -0,0 +1,14 @@ +using System; +using TimeZoneConverter; + +namespace LCU.Api.Internal.DocumentIngestorLib.Extensions +{ + public static class TimeZoneDateTime + { + public static DateTime ConvertToTimeZone(this DateTime dateTime, string timeZone) + { + var assumedTimezone = TZConvert.GetTimeZoneInfo(timeZone); + return TimeZoneInfo.ConvertTime(dateTime, assumedTimezone); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/LCU.API.Internal.DocumentIngestorLib.csproj b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/LCU.API.Internal.DocumentIngestorLib.csproj new file mode 100644 index 0000000..360fb98 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/LCU.API.Internal.DocumentIngestorLib.csproj @@ -0,0 +1,22 @@ + + + + net8.0 + Latest + Debug;Release;Test + AnyCPU + + + + + + + + + + + + + + + diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Persistence/AppDbContext.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Persistence/AppDbContext.cs new file mode 100644 index 0000000..492554a --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Persistence/AppDbContext.cs @@ -0,0 +1,45 @@ +using System; +using Microsoft.EntityFrameworkCore; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using Microsoft.EntityFrameworkCore.Query; + +namespace LCU.API.Internal.DocumentIngestorLib.Persistence; + +public class AppDbContext : DbContext +{ + public DbSet IngestorRunInfos { get; set; } + public DbSet DocumentProcessingInfos { get; set; } + public DbSet ProcessingLogs { get; set; } + public DbSet DocumentTypeArchiveDeleteInfos { get; set; } + public DbSet OwnerOverrideInfos { get; set; } + public DbSet PdfPartitionerRunInfos { get; set; } + public DbSet PdfPartitionerLogs { get; set; } + public DbSet MemberNotificationInfos { get; set; } + public DbSet OsgPreprocessorInfos { get; set; } + + [DbFunction(nameof(JSON_VALUE), IsBuiltIn = true)] + public static string JSON_VALUE(string column, [NotParameterized] string path) => throw new InvalidOperationException(); + + public AppDbContext(DbContextOptions options) : base(options) { } + + protected override void OnModelCreating(ModelBuilder builder) + { + base.OnModelCreating(builder); + + builder.Entity().ToTable("IngestorRunInfo"); + builder.Entity().ToTable("DocumentProcessingInfo") + .HasMany(x => x.MemberNotificationInfos) + .WithOne() + .HasForeignKey(x => x.DocumentProcessingInfoId) + .IsRequired(false) + .OnDelete(DeleteBehavior.Cascade); + builder.Entity().ToTable("ProcessingLog"); + builder.Entity().ToTable("DocumentTypeArchiveDeleteInfo"); + builder.Entity().HasKey(d => d.DocumentTypeName); + builder.Entity().ToTable("OwnerOverrideInfo"); + builder.Entity().ToTable("PdfPartitionerRunInfo"); + builder.Entity().ToTable("PdfPartitionerLog"); + builder.Entity().ToTable("MemberNotificationInfo"); + builder.Entity().ToTable("OsgPreprocessorInfo"); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/BaseRepository.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/BaseRepository.cs new file mode 100644 index 0000000..08abe70 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/BaseRepository.cs @@ -0,0 +1,17 @@ +using LCU.API.Internal.DocumentIngestorLib.Persistence; +using Microsoft.EntityFrameworkCore; +using System; + +namespace LCU.API.Internal.DocumentIngestorLib.Repositories +{ + public abstract class BaseRepository + { + protected readonly AppDbContext _context; + + public BaseRepository(AppDbContext context) + { + _context = context; + _context.Database.SetCommandTimeout(TimeSpan.FromSeconds(45)); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/DocumentProcessingInfoRepository.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/DocumentProcessingInfoRepository.cs new file mode 100644 index 0000000..70a3329 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/DocumentProcessingInfoRepository.cs @@ -0,0 +1,134 @@ +using System; +using System.Threading.Tasks; +using System.Collections.Generic; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using LCU.API.Internal.DocumentIngestorLib.Persistence; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; +using LCU.Api.Internal.DocumentIngestorLib.Extensions.Queryables; + +namespace LCU.API.Internal.DocumentIngestorLib.Repositories +{ + public class DocumentProcessingInfoRepository : BaseRepository, IDocumentProcessingInfoRepository + { + public DocumentProcessingInfoRepository(AppDbContext context) : base(context) { } + + public async Task> FindAsync() + { + return await _context.DocumentProcessingInfos.ToListAsync(); + } + + public async Task FindByIdAsync(int id) + { + return await _context.DocumentProcessingInfos + .FirstOrDefaultAsync(documentProcessingInfo => documentProcessingInfo.DocumentProcessingInfoId == id); + } + + public async Task> FindListByIdAsync(List ids) + { + return await _context.DocumentProcessingInfos + .Where(documentProcessingInfo => ids.Contains(documentProcessingInfo.DocumentProcessingInfoId)) + .ToListAsync(); + } + + public async Task> FindByIngestorRunInfoIdAsync(Guid ingestorRunInfoId) + { + return await _context.DocumentProcessingInfos + .Where(documentProcessingInfo => documentProcessingInfo.IngestorRunInfoId == ingestorRunInfoId) + .ToListAsync(); + } + + public async Task> FindByProcessStatusTypeAsync(ProcessStatusTypes statusType, bool? isUnknown) + { + return await _context.DocumentProcessingInfos + .Where(documentProcessingInfo => documentProcessingInfo.StatusType.Equals(statusType) + && (isUnknown == null || documentProcessingInfo.EntityUnknown.Equals(isUnknown))) + .ToListAsync(); + } + + + public async Task> FindByProcessStatusTypeListAsync(List statusTypes, bool? isUnknown) + { + return await _context.DocumentProcessingInfos + .Where(documentProcessingInfo => statusTypes.Contains(documentProcessingInfo.StatusType) && + (isUnknown == null || documentProcessingInfo.EntityUnknown == isUnknown)) + .ToListAsync(); + } + + public async Task> FindCompletedFirstPassByIngestorRunInfoIdAsync(Guid ingestorRunInfoId) + { + return await _context.DocumentProcessingInfos.Where(documentProcessingInfo => + documentProcessingInfo.IngestorRunInfoId.Equals(ingestorRunInfoId) && + documentProcessingInfo.ProcessCount >= 1 + ).ToListAsync(); + } + + public async Task AddAsync(DocumentProcessingInfo documentProcessingInfo) + { + var result = await _context.DocumentProcessingInfos.AddAsync(documentProcessingInfo); + return result.Entity; + } + + public async Task AddRangeAsync(DocumentProcessingInfo[] documentProcessingInfos) + { + await _context.DocumentProcessingInfos.AddRangeAsync(documentProcessingInfos); + } + + public void Update(DocumentProcessingInfo documentProcessingInfo) + { + _context.DocumentProcessingInfos.Update(documentProcessingInfo); + } + + public void UpdateRange(List documentProcessingInfos) + { + _context.DocumentProcessingInfos.UpdateRange(documentProcessingInfos); + } + + public void Remove(DocumentProcessingInfo documentProcessingInfo) + { + _context.DocumentProcessingInfos.Remove(documentProcessingInfo); + } + + public async Task> FilteredListAsync(Filter filter) + { + var results = new PagedResult(); + var skip = (filter.Page - 1) * filter.Limit; + + results.Total = await _context.DocumentProcessingInfos + .IncludeAll() + .IncludeFilters(filter) + .CountAsync(); + + results.Items = await _context.DocumentProcessingInfos + .IncludeAll() + .IncludeFilters(filter) + .OrderBySortableFields(filter) + .Skip(skip) + .Take(filter.Limit) + .ToArrayAsync(); + + return results; + } + + public async Task CountCompletedFirstPassByIngestorRunInfoIdAsync(Guid ingestorRunInfoId) + { + return await _context.DocumentProcessingInfos.CountAsync(documentProcessingInfo => + documentProcessingInfo.IngestorRunInfoId.Equals(ingestorRunInfoId) && + documentProcessingInfo.ProcessCount >= 1 + ); + } + + public async Task CountCompletedByIngestorRunInfoIdAsync(Guid ingestorRunInfoId) + { + return await _context.DocumentProcessingInfos.CountAsync(documentProcessingInfo => + documentProcessingInfo.IngestorRunInfoId.Equals(ingestorRunInfoId) && + documentProcessingInfo.StatusType == ProcessStatusTypes.Completed + ); + } + + public async Task> FindByDocumentIdsAsync(Guid[] ids) + => await _context.DocumentProcessingInfos.Where(i => i.DocumentId != null && ids.Contains(i.DocumentId.Value)).ToArrayAsync(); + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/DocumentTypeArchiveDeleteInfoRepository.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/DocumentTypeArchiveDeleteInfoRepository.cs new file mode 100644 index 0000000..0d10d4e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/DocumentTypeArchiveDeleteInfoRepository.cs @@ -0,0 +1,40 @@ +using System.Threading.Tasks; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using LCU.API.Internal.DocumentIngestorLib.Persistence; +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.API.Internal.DocumentIngestorLib.Repositories +{ + public class DocumentTypeArchiveDeleteInfoRepository : BaseRepository, IDocumentTypeArchiveDeleteInfoRepository + { + public DocumentTypeArchiveDeleteInfoRepository(AppDbContext context) : base(context) { } + + public async Task> FindAsync() + { + return await _context.DocumentTypeArchiveDeleteInfos.ToListAsync(); + } + + public async Task FindByDocumentTypeNameAsync(string documentTypesName) + { + return await _context.DocumentTypeArchiveDeleteInfos + .FirstOrDefaultAsync(documentTypeArchiveDeleteInfo => documentTypeArchiveDeleteInfo.DocumentTypeName == documentTypesName); + } + + public async Task AddAsync(DocumentTypeArchiveDeleteInfo documentTypeArchiveDeleteInfo) + { + var result = await _context.DocumentTypeArchiveDeleteInfos.AddAsync(documentTypeArchiveDeleteInfo); + return result.Entity; + } + + public void Update(DocumentTypeArchiveDeleteInfo documentTypeArchiveDeleteInfo) + { + _context.DocumentTypeArchiveDeleteInfos.Update(documentTypeArchiveDeleteInfo); + } + + public void Remove(DocumentTypeArchiveDeleteInfo documentTypeArchiveDeleteInfo) + { + _context.DocumentTypeArchiveDeleteInfos.Remove(documentTypeArchiveDeleteInfo); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IDocumentProcessingInfoRepository.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IDocumentProcessingInfoRepository.cs new file mode 100644 index 0000000..942c17c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IDocumentProcessingInfoRepository.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; + +namespace LCU.API.Internal.DocumentIngestorLib.Repositories +{ + public interface IDocumentProcessingInfoRepository + { + Task> FindAsync(); + Task FindByIdAsync(int id); + Task> FindListByIdAsync(List ids); + Task> FindByIngestorRunInfoIdAsync(Guid ingestorRunInfoId); + Task> FindByProcessStatusTypeAsync(ProcessStatusTypes statusType, bool? isUnknown); + Task> FindByProcessStatusTypeListAsync(List statusTypes, bool? isUnknown); + Task> FindCompletedFirstPassByIngestorRunInfoIdAsync(Guid ingestorRunInfoId); + Task AddAsync(DocumentProcessingInfo documentProcessingInfo); + Task AddRangeAsync(DocumentProcessingInfo[] documentProcessingInfos); + void Update(DocumentProcessingInfo documentProcessingInfo); + void UpdateRange(List documentProcessingInfos); + void Remove(DocumentProcessingInfo documentProcessingInfo); + Task> FilteredListAsync(Filter filter); + Task CountCompletedFirstPassByIngestorRunInfoIdAsync(Guid ingestorRunInfoId); + Task CountCompletedByIngestorRunInfoIdAsync(Guid ingestorRunInfoId); + Task> FindByDocumentIdsAsync(Guid[] ids); + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IDocumentTypeArchiveDeleteInfoRepository.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IDocumentTypeArchiveDeleteInfoRepository.cs new file mode 100644 index 0000000..e88a89f --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IDocumentTypeArchiveDeleteInfoRepository.cs @@ -0,0 +1,15 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.API.Internal.DocumentIngestorLib.Repositories +{ + public interface IDocumentTypeArchiveDeleteInfoRepository + { + Task> FindAsync(); + Task FindByDocumentTypeNameAsync(string documentType); + Task AddAsync(DocumentTypeArchiveDeleteInfo documentTypeArchiveDeleteInfo); + void Update(DocumentTypeArchiveDeleteInfo documentTypeArchiveDeleteInfo); + void Remove(DocumentTypeArchiveDeleteInfo documentTypeArchiveDeleteInfo); + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IIngestorRunInfoRepository.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IIngestorRunInfoRepository.cs new file mode 100644 index 0000000..fe4651c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IIngestorRunInfoRepository.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.API.Internal.DocumentIngestorLib.Repositories +{ + public interface IIngestorRunInfoRepository + { + Task FindByIdAsync(Guid id); + Task> FindListByIdAsync(List ids); + Task AddAsync(IngestorRunInfo ingestorRunInfo); + void Update(IngestorRunInfo ingestorRunInfo); + void Remove(IngestorRunInfo ingestorRunInfo); + IEnumerable FindByIngestionEndDateNotArchived(DateTime ingestionEndDate); + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IMemberNotificationInfoRepository.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IMemberNotificationInfoRepository.cs new file mode 100644 index 0000000..c058111 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IMemberNotificationInfoRepository.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; + +namespace LCU.API.Internal.DocumentIngestorLib.Repositories; + +public interface IMemberNotificationInfoRepository +{ + Task> FindAsync(); + Task FindByIdAsync(int id); + Task> FindListByIdAsync(List ids); + Task> FindByDocumentProcessingInfoIdAsync(int documentProcessingInfoId); + Task> FindByNotificationStatusAsync(NotificationStatusTypes status); + Task> FindSendableMemberNotificationsAsync(DateTime minimumUploadDate, int maxAttempts); + Task AddAsync(MemberNotificationInfo memberNotificationInfo); + Task AddListAsync(List memberNotificationInfos); + void Update(MemberNotificationInfo memberNotificationInfo); + void UpdateRange(IEnumerable memberNotificationInfos); + void Remove(MemberNotificationInfo memberNotificationInfo); + Task> GetMemberNotificationInfosByFilter(Filter filter); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IOsgPreprocessorInfoRepository.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IOsgPreprocessorInfoRepository.cs new file mode 100644 index 0000000..22bd0d3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IOsgPreprocessorInfoRepository.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.API.Internal.DocumentIngestorLib.Repositories; + +public interface IOsgPreprocessorInfoRepository +{ + Task> FindAsync(); + Task FindByIdAsync(int id); + Task> FindListByIdAsync(List ids); + Task> FindByDocumentType(string documentType); + Task> FindByMemberNumber(string memberNumber); + Task AddAsync(OsgPreprocessorInfo osgPreprocessorInfo); + Task AddListAsync(List osgPreprocessorInfos); + void Update(OsgPreprocessorInfo osgPreprocessorInfo); + void UpdateRange(IEnumerable osgPreprocessorInfos); + void Remove(OsgPreprocessorInfo osgPreprocessorInfo); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IOwnerOverrideInfoRepository.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IOwnerOverrideInfoRepository.cs new file mode 100644 index 0000000..50d64f1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IOwnerOverrideInfoRepository.cs @@ -0,0 +1,16 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.API.Internal.DocumentIngestorLib.Repositories +{ + public interface IOwnerOverrideInfoRepository + { + Task> FindAsync(); + Task FindByIdAsync(int id); + Task> FindByDocumentProcessingInfoIdAsync(int documentProcessingInfoId); + Task AddAsync(OwnerOverrideInfo ownerOverrideInfo); + void Update(OwnerOverrideInfo ownerOverrideInfo); + void Remove(OwnerOverrideInfo ownerOverrideInfo); + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IPdfPartitionerLogRepository.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IPdfPartitionerLogRepository.cs new file mode 100644 index 0000000..0e30578 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IPdfPartitionerLogRepository.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.API.Internal.DocumentIngestorLib.Repositories +{ + public interface IPdfPartitionerLogRepository + { + Task> FindAsync(); + Task FindByIdAsync(int id); + Task> FindByPdfPartitionerRunInfoIdAsync(Guid pdfPartitionerRunInfoId); + Task AddRangeAsync(IEnumerable pdfPartitionerLogs); + Task AddAsync(PdfPartitionerLog pdfPartitionerLog); + void Remove(PdfPartitionerLog pdfPartitionerLog); + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IPdfPartitionerRunInfoRepository.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IPdfPartitionerRunInfoRepository.cs new file mode 100644 index 0000000..a7a8e60 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IPdfPartitionerRunInfoRepository.cs @@ -0,0 +1,14 @@ +using System; +using System.Threading.Tasks; +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.API.Internal.DocumentIngestorLib.Repositories +{ + public interface IPdfPartitionerRunInfoRepository + { + Task FindByIdAsync(Guid id); + Task AddAsync(PdfPartitionerRunInfo pdfPartitionerRunInfo); + void Update(PdfPartitionerRunInfo pdfPartitionerRunInfo); + void Remove(PdfPartitionerRunInfo pdfPartitionerRunInfo); + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IProcessingLogRepository.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IProcessingLogRepository.cs new file mode 100644 index 0000000..d1491eb --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IProcessingLogRepository.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.API.Internal.DocumentIngestorLib.Repositories +{ + public interface IProcessingLogRepository + { + Task> FindAsync(); + Task FindByIdAsync(int id); + Task> FindByDocumentProcessingInfoIdAsync(int documentProcessingInfoId); + Task AddAsync(ProcessingLog processingLog); + Task AddRangeAsync(IEnumerable processingLogs); + void Update(ProcessingLog processingLog); + void Remove(ProcessingLog processingLog); + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IUnitOfWork.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IUnitOfWork.cs new file mode 100644 index 0000000..fed319c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IUnitOfWork.cs @@ -0,0 +1,10 @@ +using System.Threading.Tasks; + +namespace LCU.API.Internal.DocumentIngestorLib.Repositories +{ + public interface IUnitOfWork + { + Task CompleteAsync(); + void Complete(); + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IngestorRunInfoRepository.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IngestorRunInfoRepository.cs new file mode 100644 index 0000000..7b3bd78 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/IngestorRunInfoRepository.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using LCU.API.Internal.DocumentIngestorLib.Persistence; +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.API.Internal.DocumentIngestorLib.Repositories +{ + public class IngestorRunInfoRepository : BaseRepository, IIngestorRunInfoRepository + { + public IngestorRunInfoRepository(AppDbContext context) : base(context) { } + + public async Task FindByIdAsync(Guid id) + { + return await _context.IngestorRunInfos.FirstOrDefaultAsync(ingestorRunInfo => ingestorRunInfo.IngestorRunInfoId == id); + } + + public async Task> FindListByIdAsync(List ids) + { + return await _context.IngestorRunInfos.Where(ingestorRunInfo => ids.Contains(ingestorRunInfo.IngestorRunInfoId)).ToListAsync(); + } + + public IEnumerable FindByIngestionEndDateNotArchived(DateTime ingestionEndDate) + { + return _context.IngestorRunInfos.Where(ingestionRunInfo => + ingestionRunInfo.EndTimeStamp < ingestionEndDate && ingestionRunInfo.ArchiveTimeStamp == null); + } + + public async Task AddAsync(IngestorRunInfo ingestorRunInfo) + { + var result = await _context.IngestorRunInfos.AddAsync(ingestorRunInfo); + return result.Entity; + } + + public void Update(IngestorRunInfo ingestorRunInfo) + { + _context.IngestorRunInfos.Update(ingestorRunInfo); + } + + public void Remove(IngestorRunInfo ingestorRunInfo) + { + _context.IngestorRunInfos.Remove(ingestorRunInfo); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/MemberNotificationInfoRepository.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/MemberNotificationInfoRepository.cs new file mode 100644 index 0000000..bebbb75 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/MemberNotificationInfoRepository.cs @@ -0,0 +1,109 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using LCU.Api.Internal.DocumentIngestorLib.Extensions.Queryables; +using LCU.API.Internal.DocumentIngestorLib.Persistence; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; + +namespace LCU.API.Internal.DocumentIngestorLib.Repositories; + +public class MemberNotificationInfoRepository : BaseRepository, IMemberNotificationInfoRepository +{ + public MemberNotificationInfoRepository(AppDbContext context) : base(context) { } + + public async Task> FindAsync() + { + return await _context.MemberNotificationInfos.ToListAsync(); + } + + public async Task FindByIdAsync(int id) + { + return await _context.MemberNotificationInfos + .FirstOrDefaultAsync(memberNotificationInfo => memberNotificationInfo.MemberNotificationInfoId == id); + } + + public async Task> FindListByIdAsync(List ids) + { + return await _context.MemberNotificationInfos + .Where(memberNotificationInfo => ids.Contains(memberNotificationInfo.MemberNotificationInfoId)) + .ToListAsync(); + } + + public async Task> FindByDocumentProcessingInfoIdAsync(int documentProcessingInfoId) + { + return await _context.MemberNotificationInfos + .Where(memberNotificationInfo => documentProcessingInfoId == memberNotificationInfo.DocumentProcessingInfoId) + .ToListAsync(); + } + + public async Task> FindByNotificationStatusAsync(NotificationStatusTypes status) + { + return await _context.MemberNotificationInfos + .Where(memberNotificationInfo => status == memberNotificationInfo.NotificationStatusType) + .ToListAsync(); + } + + public async Task> FindSendableMemberNotificationsAsync(DateTime minimumUploadDate, int maxAttempts) + { + return await _context.MemberNotificationInfos + .Where(memberNotificationInfo => + memberNotificationInfo.UploadDate <= minimumUploadDate && + memberNotificationInfo.Attempts <= maxAttempts && + memberNotificationInfo.DeliveryMethod != DeliveryMethod.Paper && + memberNotificationInfo.NotificationStatusType == NotificationStatusTypes.Pending || + memberNotificationInfo.NotificationStatusType == NotificationStatusTypes.Failure) + .AsNoTracking() + .ToListAsync(); + } + + public async Task AddAsync(MemberNotificationInfo memberNotificationInfo) + { + var result = await _context.MemberNotificationInfos.AddAsync(memberNotificationInfo); + return result.Entity; + } + + public async Task AddListAsync(List memberNotificationInfos) + { + await _context.MemberNotificationInfos.AddRangeAsync(memberNotificationInfos); + } + + public void Update(MemberNotificationInfo memberNotificationInfo) + { + _context.MemberNotificationInfos.Update(memberNotificationInfo); + } + + public void UpdateRange(IEnumerable memberNotificationInfos) + { + _context.MemberNotificationInfos.UpdateRange(memberNotificationInfos); + } + + public void Remove(MemberNotificationInfo memberNotificationInfo) + { + _context.MemberNotificationInfos.Remove(memberNotificationInfo); + } + + public async Task> GetMemberNotificationInfosByFilter(Filter filter) + { + var query = _context.DocumentProcessingInfos + .IncludeFilters(filter) + .Include(documentProcessingInfo => documentProcessingInfo.MemberNotificationInfos) + .Where(x => x.MemberNotificationInfos.Any()) + .SelectMany(x => x.MemberNotificationInfos); + + if (filter.NotificationStatusFilters != null) + { + if (filter.NotificationStatusFilters.Any()) + { + query = query.Where(memberNotificationInfo => + filter.NotificationStatusFilters.Contains(memberNotificationInfo.NotificationStatusType)); + } + } + + return await query.AsNoTracking() + .ToListAsync(); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/OsgPreprocessorInfoRepository.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/OsgPreprocessorInfoRepository.cs new file mode 100644 index 0000000..b105d2e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/OsgPreprocessorInfoRepository.cs @@ -0,0 +1,73 @@ +using System; +using System.Threading.Tasks; +using System.Collections.Generic; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using LCU.API.Internal.DocumentIngestorLib.Persistence; +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.API.Internal.DocumentIngestorLib.Repositories; + +[Obsolete("06/02/2023 - Used to prepare historical documents for ingestion. No longer in use.")] +public class OsgPreprocessorInfoRepository : BaseRepository, IOsgPreprocessorInfoRepository +{ + public OsgPreprocessorInfoRepository(AppDbContext context) : base(context) { } + + public async Task> FindAsync() + { + return await _context.OsgPreprocessorInfos.ToListAsync(); + } + + public async Task FindByIdAsync(int id) + { + return await _context.OsgPreprocessorInfos + .FirstOrDefaultAsync(osgPreprocessorInfo => osgPreprocessorInfo.OsgPreprocessorInfoId == id); + } + + public async Task> FindListByIdAsync(List ids) + { + return await _context.OsgPreprocessorInfos + .Where(osgPreprocessorInfo => ids.Contains(osgPreprocessorInfo.OsgPreprocessorInfoId)) + .ToListAsync(); + } + + public async Task> FindByDocumentType(string documentType) + { + return await _context.OsgPreprocessorInfos + .Where(osgPreprocessorInfo => documentType == osgPreprocessorInfo.DocumentType) + .ToListAsync(); + } + + public async Task> FindByMemberNumber(string memberNumber) + { + return await _context.OsgPreprocessorInfos + .Where(osgPreprocessorInfo => memberNumber == osgPreprocessorInfo.MemberNumber) + .ToListAsync(); + } + + public async Task AddAsync(OsgPreprocessorInfo osgPreprocessorInfo) + { + var result = await _context.OsgPreprocessorInfos.AddAsync(osgPreprocessorInfo); + return result.Entity; + } + + public async Task AddListAsync(List osgPreprocessorInfos) + { + await _context.OsgPreprocessorInfos.AddRangeAsync(osgPreprocessorInfos); + } + + public void Update(OsgPreprocessorInfo osgPreprocessorInfo) + { + _context.OsgPreprocessorInfos.Update(osgPreprocessorInfo); + } + + public void UpdateRange(IEnumerable osgPreprocessorInfos) + { + _context.OsgPreprocessorInfos.UpdateRange(osgPreprocessorInfos); + } + + public void Remove(OsgPreprocessorInfo osgPreprocessorInfo) + { + _context.OsgPreprocessorInfos.Remove(osgPreprocessorInfo); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/OwnerOverrideInfoRepository.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/OwnerOverrideInfoRepository.cs new file mode 100644 index 0000000..7174c61 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/OwnerOverrideInfoRepository.cs @@ -0,0 +1,48 @@ +using System.Threading.Tasks; +using System.Collections.Generic; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using LCU.API.Internal.DocumentIngestorLib.Persistence; +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.API.Internal.DocumentIngestorLib.Repositories +{ + public class OwnerOverrideInfoRepository : BaseRepository, IOwnerOverrideInfoRepository + { + public OwnerOverrideInfoRepository(AppDbContext context) : base(context) { } + + public async Task> FindAsync() + { + return await _context.OwnerOverrideInfos.ToListAsync(); + } + + public async Task FindByIdAsync(int id) + { + return await _context.OwnerOverrideInfos + .FirstOrDefaultAsync(ownerOverrideInfo => ownerOverrideInfo.OwnerOverrideInfoId == id); + } + + public async Task> FindByDocumentProcessingInfoIdAsync(int documentProcessingInfoId) + { + return await _context.OwnerOverrideInfos + .Where(ownerOverrideInfo => ownerOverrideInfo.DocumentProcessingInfoId.ToString().Equals(documentProcessingInfoId.ToString())) + .ToListAsync(); + } + + public async Task AddAsync(OwnerOverrideInfo ownerOverrideInfo) + { + var result = await _context.OwnerOverrideInfos.AddAsync(ownerOverrideInfo); + return result.Entity; + } + + public void Update(OwnerOverrideInfo ownerOverrideInfo) + { + _context.OwnerOverrideInfos.Update(ownerOverrideInfo); + } + + public void Remove(OwnerOverrideInfo ownerOverrideInfo) + { + _context.OwnerOverrideInfos.Remove(ownerOverrideInfo); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/PdfPartitionerLogRepository.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/PdfPartitionerLogRepository.cs new file mode 100644 index 0000000..a921dcf --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/PdfPartitionerLogRepository.cs @@ -0,0 +1,49 @@ +using System; +using System.Threading.Tasks; +using System.Collections.Generic; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using LCU.API.Internal.DocumentIngestorLib.Persistence; +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.API.Internal.DocumentIngestorLib.Repositories +{ + public class PdfPartitionerLogRepository : BaseRepository, IPdfPartitionerLogRepository + { + public PdfPartitionerLogRepository(AppDbContext context) : base(context) { } + + public async Task> FindAsync() + { + return await _context.PdfPartitionerLogs.ToListAsync(); + } + + public async Task FindByIdAsync(int id) + { + return await _context.PdfPartitionerLogs + .FirstOrDefaultAsync(pdfPartitionerLog => pdfPartitionerLog.PdfPartitionerLogId == id); + } + + public async Task> FindByPdfPartitionerRunInfoIdAsync(Guid pdfPartitionerRunInfoId) + { + return await _context.PdfPartitionerLogs + .Where(pdfPartitionerLog => pdfPartitionerLog.PdfPartitionerRunInfoId == pdfPartitionerRunInfoId) + .ToListAsync(); + } + + public async Task AddRangeAsync(IEnumerable pdfPartitionerLogs) + { + await _context.PdfPartitionerLogs.AddRangeAsync(pdfPartitionerLogs); + } + + public async Task AddAsync(PdfPartitionerLog pdfPartitionerLog) + { + var result = await _context.PdfPartitionerLogs.AddAsync(pdfPartitionerLog); + return result.Entity; + } + + public void Remove(PdfPartitionerLog pdfPartitionerLog) + { + _context.PdfPartitionerLogs.Remove(pdfPartitionerLog); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/PdfPartitionerRunInfoRepository.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/PdfPartitionerRunInfoRepository.cs new file mode 100644 index 0000000..c569b31 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/PdfPartitionerRunInfoRepository.cs @@ -0,0 +1,34 @@ +using System; +using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore; +using LCU.API.Internal.DocumentIngestorLib.Persistence; +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.API.Internal.DocumentIngestorLib.Repositories +{ + public class PdfPartitionerRunInfoRepository : BaseRepository, IPdfPartitionerRunInfoRepository + { + public PdfPartitionerRunInfoRepository(AppDbContext context) : base(context) { } + + public async Task FindByIdAsync(Guid id) + { + return await _context.PdfPartitionerRunInfos.FirstOrDefaultAsync(pdfPartitionerRunInfo => pdfPartitionerRunInfo.PdfPartitionerRunInfoId == id); + } + + public async Task AddAsync(PdfPartitionerRunInfo pdfPartitionerRunInfo) + { + var result = await _context.PdfPartitionerRunInfos.AddAsync(pdfPartitionerRunInfo); + return result.Entity; + } + + public void Update(PdfPartitionerRunInfo pdfPartitionerRunInfo) + { + _context.PdfPartitionerRunInfos.Update(pdfPartitionerRunInfo); + } + + public void Remove(PdfPartitionerRunInfo pdfPartitionerRunInfo) + { + _context.PdfPartitionerRunInfos.Remove(pdfPartitionerRunInfo); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/ProcessingLogRepository.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/ProcessingLogRepository.cs new file mode 100644 index 0000000..f7fcd1f --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/ProcessingLogRepository.cs @@ -0,0 +1,53 @@ +using System.Threading.Tasks; +using System.Collections.Generic; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using LCU.API.Internal.DocumentIngestorLib.Persistence; +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.API.Internal.DocumentIngestorLib.Repositories +{ + public class ProcessingLogRepository : BaseRepository, IProcessingLogRepository + { + public ProcessingLogRepository(AppDbContext context) : base(context) { } + + public async Task> FindAsync() + { + return await _context.ProcessingLogs.ToListAsync(); + } + + public async Task FindByIdAsync(int id) + { + return await _context.ProcessingLogs + .FirstOrDefaultAsync(processingLog => processingLog.ProcessingLogId == id); + } + + public async Task> FindByDocumentProcessingInfoIdAsync(int documentProcessingInfoId) + { + return await _context.ProcessingLogs + .Where(processingLog => processingLog.DocumentProcessingInfoId == documentProcessingInfoId) + .ToListAsync(); + } + + public async Task AddAsync(ProcessingLog processingLog) + { + var result = await _context.ProcessingLogs.AddAsync(processingLog); + return result.Entity; + } + + public async Task AddRangeAsync(IEnumerable processingLogs) + { + await _context.ProcessingLogs.AddRangeAsync(processingLogs); + } + + public void Update(ProcessingLog processingLog) + { + _context.ProcessingLogs.Update(processingLog); + } + + public void Remove(ProcessingLog processingLog) + { + _context.ProcessingLogs.Remove(processingLog); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/UnitOfWork.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/UnitOfWork.cs new file mode 100644 index 0000000..819c103 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLib/Repositories/UnitOfWork.cs @@ -0,0 +1,25 @@ +using System.Threading.Tasks; +using LCU.API.Internal.DocumentIngestorLib.Persistence; + +namespace LCU.API.Internal.DocumentIngestorLib.Repositories +{ + public class UnitOfWork : IUnitOfWork + { + private readonly AppDbContext _context; + + public UnitOfWork(AppDbContext context) + { + _context = context; + } + + public async Task CompleteAsync() + { + await _context.SaveChangesAsync(); + } + + public void Complete() + { + _context.SaveChanges(); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Extensions/FilterNullsAndZerosOrDefaultExtensionTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Extensions/FilterNullsAndZerosOrDefaultExtensionTest.cs new file mode 100644 index 0000000..54ea4fd --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Extensions/FilterNullsAndZerosOrDefaultExtensionTest.cs @@ -0,0 +1,25 @@ +using LCU.API.Internal.DocumentIngestorLib.Extensions; + +namespace LCU.API.Internal.DocumentIngestorLibTests.Extensions; + +public class FilterNullsAndZerosOrDefaultTest +{ + [Test] + public void FilterNullsAndZerosOrDefault() + { + var notNullList = new[] { "123", "345" }; + var partialList = new[] { string.Empty, "123" }; + var emptyList = Array.Empty(); + var listEmptyStrings = new[] { string.Empty, string.Empty }; + var listZero = new[] { string.Empty, "0" }; + List? nullValue = null; + + Assert.That(new[] { "123", "345" }, Is.EqualTo(notNullList.FilterNullsAndZerosOrDefault())); + Assert.That(new[] { "123" }, Is.EqualTo(partialList.FilterNullsAndZerosOrDefault())); + + Assert.IsNull(emptyList.FilterNullsAndZerosOrDefault()); + Assert.IsNull(listEmptyStrings.FilterNullsAndZerosOrDefault()); + Assert.IsNull(nullValue.FilterNullsAndZerosOrDefault()); + Assert.IsNull(listZero.FilterNullsAndZerosOrDefault()); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Extensions/Queryables/DocumentProcessingInfoNotificationStatusQueryableTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Extensions/Queryables/DocumentProcessingInfoNotificationStatusQueryableTest.cs new file mode 100644 index 0000000..b25759a --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Extensions/Queryables/DocumentProcessingInfoNotificationStatusQueryableTest.cs @@ -0,0 +1,131 @@ +using FluentAssertions; +using LCU.Api.Internal.DocumentIngestorLib.Extensions.Queryables; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; + +namespace LCU.API.Internal.DocumentIngestorLibTests.Extensions.Queryables; + +public class DocumentProcessingInfoNotificationStatusQueryableTest +{ + [Test] + public void FilterByNotificationStatusType_NotificationStatusFiltersIsNull_ReturnsUnmodifiedQueryable() + { + var processingInfo = InfoFactory(); + var filter = new Filter + { + NotificationStatusFilters = null + }; + var originalProcessingInfo = processingInfo.ToArray(); + + var filtered = processingInfo.FilterByNotificationStatusType(filter); + + filtered.Should().BeEquivalentTo(originalProcessingInfo); + } + + [Test] + public void FilterByNotificationStatusType_NotificationStatusFiltersIsEmpty_ReturnsUnmodifiedQueryable() + { + var processingInfo = InfoFactory(); + var filter = new Filter + { + NotificationStatusFilters = new List() + }; + var originalProcessingInfo = processingInfo.ToArray(); + + var filtered = processingInfo.FilterByNotificationStatusType(filter); + + filtered.Should().BeEquivalentTo(originalProcessingInfo); + } + + [Test] + public void FilterByNotificationStatusType_ProcessingInfoMemberNotificationInfoIsNull_IsFilteredOut() + { + var processingInfo = InfoFactory(); + var filter = new Filter + { + NotificationStatusFilters = processingInfo + .Where(i => i.MemberNotificationInfos != null) + .SelectMany(i => i.MemberNotificationInfos.ToList()) + .Select(i => i.NotificationStatusType) + .Distinct() + .ToList() + }; + + var filtered = processingInfo.FilterByNotificationStatusType(filter); + + filtered.Should().NotContain(i => i.MemberNotificationInfos == null); + } + + [Test] + public void FilterByNotificationStatusType_ProcessingInfoMemberNotificationInfoStatusNotInFilter_IsFilteredOut() + { + var processingInfo = InfoFactory(); + var notIncludedStatuses = Enum.GetValues()[..(Enum.GetValues().Length / 2)]; + var filter = new Filter + { + NotificationStatusFilters = processingInfo + .Where(i => i.MemberNotificationInfos != null) + .SelectMany(i => i.MemberNotificationInfos.ToList()) + .Select(i => i.NotificationStatusType) + .Distinct() + .Except(notIncludedStatuses) + .ToList() + }; + + var filtered = processingInfo.FilterByNotificationStatusType(filter); + + filtered.Should().NotContain(i => notIncludedStatuses.Contains(i.MemberNotificationInfos.FirstOrDefault().NotificationStatusType)); + } + + + [Test] + public void FilterByNotificationStatusType_ProcessingInfoMemberNotificationInfoStatusInFilter_IsRetained() + { + var processingInfo = InfoFactory(); + var includedStatuses = Enum.GetValues()[..(Enum.GetValues().Length / 2)]; + var filter = new Filter + { + NotificationStatusFilters = includedStatuses.Distinct().ToList() + }; + + var filtered = processingInfo.FilterByNotificationStatusType(filter); + + filtered.Should().OnlyContain(i => includedStatuses.Contains(i.MemberNotificationInfos.FirstOrDefault().NotificationStatusType)); + } + + private static IQueryable InfoFactory() + => Enum.GetValues() + .Distinct() + .SelectMany(status => new[] + { + new DocumentProcessingInfo + { + MemberNotificationInfos = new List + { + new() + { + NotificationStatusType = status + } + } + }, + new DocumentProcessingInfo//double each status + { + MemberNotificationInfos = new List + { + new() + { + NotificationStatusType = status + } + } + } + }) + .Concat(new[] + { + new DocumentProcessingInfo + { + MemberNotificationInfos = null + } + }) + .AsQueryable(); +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/LCU.API.Internal.DocumentIngestorLibTests.csproj b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/LCU.API.Internal.DocumentIngestorLibTests.csproj new file mode 100644 index 0000000..0ff0bd3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/LCU.API.Internal.DocumentIngestorLibTests.csproj @@ -0,0 +1,35 @@ + + + + net8.0 + enable + enable + + false + + Debug;Release;Test + + AnyCPU + + + + + + + + + + + + + + + + + + + + + + + diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Repositories/DocumentProcessingInfoRepositoryTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Repositories/DocumentProcessingInfoRepositoryTest.cs new file mode 100644 index 0000000..d6a9ae2 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Repositories/DocumentProcessingInfoRepositoryTest.cs @@ -0,0 +1,821 @@ +using FluentAssertions; +using LCU.API.Internal.DocumentIngestorLib.Persistence; +using LCU.API.Internal.DocumentIngestorLib.Repositories; +using LCU.API.Internal.DocumentIngestorLibTests; +using LCU.Library.Internal.DocumentIngestorModels.Constants; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; +using Microsoft.EntityFrameworkCore; +using Newtonsoft.Json.Linq; +using System; + +namespace LCU.API.Internal.DocumentIngestorLibTests.Repositories; + +public class DocumentProcessingInfoRepositoryTest : IDisposable +{ + private IDocumentProcessingInfoRepository _repository; + + private readonly SqliteAppDbContextFactory _contextFactory = new(); + private AppDbContext _context; + + [SetUp] + public void Setup() + { + _context = _contextFactory.CreateContext(); + _repository = new DocumentProcessingInfoRepository(_context); + } + + [Test] + public async Task FindAsync_AllCases_ReturnsAllDocumentProcessingInfoRecords() + { + var records = new[] + { + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory() + }; + await _context.DocumentProcessingInfos.AddRangeAsync(records); + await _context.SaveChangesAsync(); + + var infos = await _repository.FindAsync(); + + infos.Should().BeEquivalentTo(records); + } + + [Test] + public async Task FindByIdAsync_RecordExists_ReturnsRecord() + { + var matchedRecord = DocumentProcessingInfoFactory(); + var records = new[] + { + DocumentProcessingInfoFactory(), + matchedRecord, + DocumentProcessingInfoFactory() + }; + await _context.DocumentProcessingInfos.AddRangeAsync(records); + await _context.SaveChangesAsync(); + + var info = await _repository.FindByIdAsync(matchedRecord.DocumentProcessingInfoId); + + info.Should().BeEquivalentTo(matchedRecord); + } + + [Test] + public async Task FindByIdAsync_RecordDoesNotExist_ReturnsNull() + { + var records = new[] + { + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory() + }; + await _context.DocumentProcessingInfos.AddRangeAsync(records); + await _context.SaveChangesAsync(); + + var info = await _repository.FindByIdAsync(_idSeries.Next()); + + Assert.That(info, Is.Null); + } + + [Test] + public async Task FindListByIdAsync_RecordsMatchedById_ReturnsMatched() + { + var records = new[] + { + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory() + }; + await _context.DocumentProcessingInfos.AddRangeAsync(records); + await _context.SaveChangesAsync(); + var matchedRecords = records.Where((_, i) => i % 2 == 0).ToArray(); + var ids = matchedRecords + .Select(r => r.DocumentProcessingInfoId) + .Concat(new[] { _idSeries.Next() }) + .ToList(); + + var infos = await _repository.FindListByIdAsync(ids); + + infos.Should().BeEquivalentTo(matchedRecords); + } + + [Test] + public async Task FindByIngestorRunInfoIdAsync_RecordsMatchedByRunInfo_ReturnsMatched() + { + var runInfo = IngestorRunInfoFactory(); + var matchedRecords = new[] + { + DocumentProcessingInfoFactory(runInfo), + DocumentProcessingInfoFactory(runInfo), + DocumentProcessingInfoFactory(runInfo), + }; + await _context.DocumentProcessingInfos.AddRangeAsync + ( + DocumentProcessingInfoFactory(IngestorRunInfoFactory()), + DocumentProcessingInfoFactory(IngestorRunInfoFactory()) + ); + await _context.DocumentProcessingInfos.AddRangeAsync(matchedRecords); + await _context.DocumentProcessingInfos.AddRangeAsync + ( + DocumentProcessingInfoFactory(IngestorRunInfoFactory()), + DocumentProcessingInfoFactory(IngestorRunInfoFactory()) + ); + await _context.SaveChangesAsync(); + + var infos = await _repository.FindByIngestorRunInfoIdAsync(runInfo.IngestorRunInfoId); + + infos.Should().BeEquivalentTo(matchedRecords); + } + + [Test] + public async Task FindByProcessStatusTypeAsync_RecordsMatchingType_ReturnsMatched() + { + var records = new[] + { + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory() + }; + + var type = records[1].StatusType; + await _context.DocumentProcessingInfos.AddRangeAsync(records); + await _context.SaveChangesAsync(); + + var infoByType = await _repository.FindByProcessStatusTypeAsync(type, null); + + infoByType.Where(documentProcessingInfo => documentProcessingInfo.StatusType.Equals(type)); + } + + [Test] + public async Task FindByProcessStatusTypeListAsync_RecordsMatchingType_ReturnsMatched() + { + var records = new[] + { + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory() + }; + + var types = records.Select(u => u.StatusType).ToList(); + + await _context.DocumentProcessingInfos.AddRangeAsync(records); + await _context.SaveChangesAsync(); + + var infoByType = await _repository.FindByProcessStatusTypeListAsync(types, null); + + infoByType.Where(documentProcessingInfo => documentProcessingInfo.StatusType.Equals(types)); + } + + [Test] + public async Task FindByProcessStatusTypeAsync_RecordsMatchingType_IsUnknown_ReturnsMatched() + { + var records = new[] + { + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory() + }; + records[0].EntityUnknown = true; + records[2].EntityUnknown = true; + var type = records[1].StatusType; + await _context.DocumentProcessingInfos.AddRangeAsync(records); + await _context.SaveChangesAsync(); + + var infoByType = await _repository.FindByProcessStatusTypeAsync(type, true); + + infoByType.Should().BeEquivalentTo(records.Where(r => r.StatusType == type && r.EntityUnknown)); + } + + [Test] + public async Task FindByProcessStatusTypeListAsync_RecordsMatchingType_IsUnknown_ReturnsMatched() + { + var records = new[] + { + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory() + }; + + records[0].EntityUnknown = true; + records[2].EntityUnknown = true; + + var types = new List { records[1].StatusType }; + await _context.DocumentProcessingInfos.AddRangeAsync(records); + await _context.SaveChangesAsync(); + + var infoByType = await _repository.FindByProcessStatusTypeListAsync(types, true); + + infoByType.Should().BeEquivalentTo(records.Where(r => r.StatusType.Equals(types) && r.EntityUnknown)); + } + + [Test] + public async Task FindCompletedFirstPassByIngestorRunInfoIdAsync_MatchedByRunInfoAndProcessedAtLeastOnce_ReturnsMatched() + { + var runInfo = IngestorRunInfoFactory(); + var matchedRecords = new[] + { + DocumentProcessingInfoFactory(runInfo), + DocumentProcessingInfoFactory(runInfo), + DocumentProcessingInfoFactory(runInfo), + DocumentProcessingInfoFactory(runInfo), + DocumentProcessingInfoFactory(runInfo), + }; + var matchedProcessedRecords = matchedRecords + .Where((_, i) => i % 2 == 0) + .ToArray(); + foreach (var record in matchedProcessedRecords) + { + record.ProcessCount = Math.Max(1, DateTime.Now.Millisecond); + } + await _context.DocumentProcessingInfos.AddRangeAsync + ( + DocumentProcessingInfoFactory(IngestorRunInfoFactory()), + DocumentProcessingInfoFactory(IngestorRunInfoFactory()) + ); + await _context.DocumentProcessingInfos.AddRangeAsync(matchedRecords); + await _context.DocumentProcessingInfos.AddRangeAsync + ( + DocumentProcessingInfoFactory(IngestorRunInfoFactory()), + DocumentProcessingInfoFactory(IngestorRunInfoFactory()) + ); + await _context.SaveChangesAsync(); + + var runCompleted = await _repository.FindCompletedFirstPassByIngestorRunInfoIdAsync(runInfo.IngestorRunInfoId); + + runCompleted.Should().BeEquivalentTo(matchedProcessedRecords); + } + + [Test] + public async Task AddAsync_AllCases_TracksAndDoesntSave() + { + var info = DocumentProcessingInfoFactory(); + + var added = await _repository.AddAsync(info); + + var tracked = _context.ChangeTracker.Entries() + .Select(e => e.Entity); + var id = info.DocumentProcessingInfoId; + var committed = _context.Database.SqlQuery + ( + @$" +SELECT count(1) +FROM DocumentProcessingInfo i +WHERE i.DocumentProcessingInfoId = {id} +" + ).ToArray() + .Single(); + added.Should().BeEquivalentTo(info); + tracked.Should().Contain(info); + committed.Should().Be(0); + } + + [Test] + public async Task Update_InfoAlreadyExists_TracksAndDoesntSave() + { + var info = DocumentProcessingInfoFactory(); + await _context.DocumentProcessingInfos.AddAsync(info); + await _context.SaveChangesAsync(); + info.ProcessCount++; + + _repository.Update(info); + + var tracked = _context.ChangeTracker.Entries() + .Where(e => e.State == EntityState.Modified) + .Select(e => e.Entity); + var id = info.DocumentProcessingInfoId; + var count = info.ProcessCount; + var updated = _context.Database.SqlQuery + ( + @$" +SELECT count(1) +FROM DocumentProcessingInfo i +WHERE i.DocumentProcessingInfoId = {id} + AND i.ProcessCount = {count} +" + ).ToArray() + .Single(); + tracked.Should().Contain(info); + updated.Should().Be(0); + } + + [Test] + public async Task Remove_InfoAlreadyExists_TracksRemovalAndDoesntSave() + { + var info = DocumentProcessingInfoFactory(); + await _context.DocumentProcessingInfos.AddAsync(info); + await _context.SaveChangesAsync(); + + _repository.Remove(info); + + var tracked = _context.ChangeTracker.Entries() + .Where(e => e.State == EntityState.Deleted) + .Select(e => e.Entity); + var id = info.DocumentProcessingInfoId; + var stored = _context.Database.SqlQuery + ( + @$" +SELECT count(1) +FROM DocumentProcessingInfo i +WHERE i.DocumentProcessingInfoId = {id} +" + ).ToArray() + .Single(); + tracked.Should().Contain(info); + stored.Should().Be(1); + } + + [Test] + public async Task FilteredListAsync_ByDocType_CountsAndFiltersByDocType() + { + var records = new[] + { + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory() + }; + var matchedRecords = records.Where((_, i) => i % 2 == 0).ToArray(); + var docType = matchedRecords.First().DocumentType; + foreach (var record in matchedRecords) + { + record.DocumentType = docType; + } + await _context.DocumentProcessingInfos.AddRangeAsync(records); + await _context.SaveChangesAsync(); + var filter = new Filter + { + DocType = docType, + Page = 2, + Limit = 2 + }; + + var filteredDocuments = await _repository.FilteredListAsync(filter); + + filteredDocuments.Items.Should().BeEquivalentTo(matchedRecords.Skip((filter.Page - 1) * filter.Limit).Take(filter.Limit)); + filteredDocuments.Total.Should().Be(matchedRecords.Length); + } + + [Test] + public async Task FilteredListAsync_ByBusinessName_CountsAndFiltersByBusinessName() + { + var records = new[] + { + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory() + }; + var matchedRecords = records.Where((_, i) => i % 2 == 0).ToArray(); + var businessName = matchedRecords.First().DocumentBusinessName; + foreach (var record in matchedRecords) + { + record.DocumentBusinessName = businessName; + } + await _context.DocumentProcessingInfos.AddRangeAsync(records); + await _context.SaveChangesAsync(); + var filter = new Filter + { + DocBusinessName = businessName, + Page = 2, + Limit = 2 + }; + + var filteredDocuments = await _repository.FilteredListAsync(filter); + + filteredDocuments.Items.Should().BeEquivalentTo(matchedRecords.Skip((filter.Page - 1) * filter.Limit).Take(filter.Limit)); + filteredDocuments.Total.Should().Be(matchedRecords.Length); + } + + [Test] + public async Task FilteredListAsync_ByStatusType_CountsAndFiltersByStatusType() + { + var records = new[] + { + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory() + }; + var matchedRecords = records.Where((_, i) => i % 2 == 0).ToArray(); + var statusType = (ProcessStatusTypes)int.MinValue; + foreach (var record in matchedRecords) + { + record.StatusType = statusType; + } + await _context.DocumentProcessingInfos.AddRangeAsync(records); + await _context.SaveChangesAsync(); + var filter = new Filter + { + StatusFilters = records + .Select(i => i.StatusType) + .Distinct() + .Select(s => new StatusFilter { IsEnabled = s == statusType, StatusType = s }) + .ToList(), + Page = 2, + Limit = 2 + }; + + var filteredDocuments = await _repository.FilteredListAsync(filter); + + filteredDocuments.Items.Should().BeEquivalentTo(matchedRecords.Skip((filter.Page - 1) * filter.Limit).Take(filter.Limit)); + filteredDocuments.Total.Should().Be(matchedRecords.Length); + } + + [Test] + public async Task FilteredListAsync_ByCreatedDate_CountsAndFiltersByCreatedDate() + { + var records = new[] + { + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory() + }; + var matchedRecords = records.Where((_, i) => i % 2 == 0).ToArray(); + var createdDate = matchedRecords.First().CreatedDate; + foreach (var record in matchedRecords) + { + record.CreatedDate = createdDate; + } + foreach (var record in records.Where(r => !matchedRecords.Contains(r))) + { + record.CreatedDate = createdDate.AddDays(1); + } + await _context.DocumentProcessingInfos.AddRangeAsync(records); + await _context.SaveChangesAsync(); + var filter = new Filter + { + CreatedDateStart = createdDate.AddMinutes(-1), + CreatedDateEnd = createdDate.AddMinutes(1), + Page = 2, + Limit = 2 + }; + + var filteredDocuments = await _repository.FilteredListAsync(filter); + + filteredDocuments.Items.Should().HaveCount(filter.Limit); + filteredDocuments.Items.Should().BeSubsetOf(matchedRecords); + filteredDocuments.Total.Should().Be(matchedRecords.Length); + } + + + [Test] + public async Task FilteredListAsync_ByIngestorRunInfoId_CountsAndFiltersByCreatedDate() + { + var runInfo = IngestorRunInfoFactory(); + var records = new[] + { + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory() + }; + var matchedRecords = records.Where((_, i) => i % 2 == 0).ToArray(); + foreach (var record in matchedRecords) + { + record.IngestorRunInfo = runInfo; + } + await _context.DocumentProcessingInfos.AddRangeAsync(records); + await _context.SaveChangesAsync(); + var filter = new Filter + { + IngestorRunInfoId = runInfo.IngestorRunInfoId, + Page = 2, + Limit = 2 + }; + + var filteredDocuments = await _repository.FilteredListAsync(filter); + + filteredDocuments.Items.Should().HaveCount(filter.Limit); + filteredDocuments.Items.Should().BeSubsetOf(matchedRecords); + filteredDocuments.Total.Should().Be(matchedRecords.Length); + } + + [Test] + [Ignore("a real SQL server connection in EF is required for the json filter to work\nthe filter is tested on its own in an integration test")] + public async Task FilteredListAsync_ByIndexFileJsonKeyValue_CountsAndFiltersByDocumentValuePayloadContainingJson() + { + var records = new[] + { + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory() + }; + var matchedRecords = records.Where((_, i) => i % 2 == 0).ToArray(); + var property = JObject.Parse(matchedRecords.First().DocumentValuePayload) + .Properties() + .First(); + foreach (var record in matchedRecords) + { + var payload = JObject.Parse(record.DocumentValuePayload); + payload[property.Name] = property.Value; + + record.DocumentValuePayload = payload.ToString().Replace(" ", string.Empty); + } + await _context.DocumentProcessingInfos.AddRangeAsync(records); + await _context.SaveChangesAsync(); + var filter = new Filter + { + CustomIndexFileFiltersEquals = new Dictionary + { + [property.Name] = property.Value.ToString() + }, + Page = 2, + Limit = 2 + }; + + var filteredDocuments = await _repository.FilteredListAsync(filter); + + filteredDocuments.Items.Should().BeEquivalentTo(matchedRecords.Skip((filter.Page - 1) * filter.Limit).Take(filter.Limit)); + filteredDocuments.Total.Should().Be(matchedRecords.Length); + } + + [Test] + public async Task FilteredListAsync_ByNotificationStatus_CountsAndFiltersByMemberNotificationInfoStatusType() + { + var notificationStatus = NotificationStatusTypesFactory(); + var records = new[] + { + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory(), + DocumentProcessingInfoFactory() + }; + var matchedRecords = records.Where((_, i) => i % 2 == 0).ToArray(); + foreach (var record in matchedRecords) + { + if (!record.MemberNotificationInfos.Any()) continue; + foreach (var notification in record.MemberNotificationInfos) + { + notification.NotificationStatusType = notificationStatus; + } + } + foreach (var record in records.Except(matchedRecords)) + { + if (!record.MemberNotificationInfos.Any()) continue; + foreach (var notification in record.MemberNotificationInfos) + { + notification.NotificationStatusType = NotificationStatusTypesFactory(not: notificationStatus); + } + + } + await _context.DocumentProcessingInfos.AddRangeAsync(records); + await _context.SaveChangesAsync(); + var filter = new Filter + { + NotificationStatusFilters = new List { notificationStatus }, + Page = 2, + Limit = 2 + }; + + var filteredDocuments = await _repository.FilteredListAsync(filter); + + filteredDocuments.Items.Should().BeEquivalentTo(matchedRecords.Skip((filter.Page - 1) * filter.Limit).Take(filter.Limit)); + filteredDocuments.Total.Should().Be(matchedRecords.Length); + } + + [Test] + public async Task CountCompletedFirstPassByIngestorRunInfoIdAsync_AllCases_ReturnsCountOfDocumentProcessingInfoWithIngestorRunInfoIdAndProcessCountMoreThanOne() + { + var ingestorRunInfo = IngestorRunInfoFactory(); + var runInfos = new List { ingestorRunInfo }; + var documents = Enumerable.Repeat + ( + () => DocumentProcessingInfoFactory(ingestorRunInfo), + 100 + ).Select(f => f()) + .ToArray(); + var expectedCount = 0; + foreach (var (document, index) in documents.Select((d, i) => (d, i))) + { + document.ProcessCount = index % 2 == 0 ? 0 : 1; + + if (index % 3 == 0) + { + document.IngestorRunInfoId = ingestorRunInfo.IngestorRunInfoId; + document.IngestorRunInfo = ingestorRunInfo; + } + else + { + var run = IngestorRunInfoFactory(); + runInfos.Add(run); + + document.IngestorRunInfoId = run.IngestorRunInfoId; + document.IngestorRunInfo = run; + } + + expectedCount += index % 2 == 0 && index % 3 == 0 ? 1 : 0; + } + await _context.IngestorRunInfos.AddRangeAsync(runInfos); + await _context.DocumentProcessingInfos.AddRangeAsync(documents); + await _context.SaveChangesAsync(); + + var count = await _repository.CountCompletedFirstPassByIngestorRunInfoIdAsync(ingestorRunInfo.IngestorRunInfoId); + + Assert.That(count, Is.EqualTo(expectedCount)); + } + + [Test] + public async Task FindByDocumentIdsAsync_NullDocumentId_NotReturned() + { + var info = DocumentProcessingInfoFactory(); + info.DocumentId = null; + var ids = Enumerable.Repeat(Guid.NewGuid, 5) + .Select(f => f()) + .ToArray(); + await _context.DocumentProcessingInfos.AddRangeAsync(info); + await _context.SaveChangesAsync(); + + var infos = await _repository.FindByDocumentIdsAsync(ids); + + CollectionAssert.DoesNotContain(infos, info); + } + + [Test] + public async Task FindByDocumentIdsAsync_DocumentIdNotInIds_NotReturned() + { + var info = DocumentProcessingInfoFactory(); + info.DocumentId = Guid.NewGuid(); + var ids = Enumerable.Repeat(Guid.NewGuid, 5) + .Select(f => f()) + .ToArray(); + await _context.DocumentProcessingInfos.AddRangeAsync(info); + await _context.SaveChangesAsync(); + + var infos = await _repository.FindByDocumentIdsAsync(ids); + + CollectionAssert.DoesNotContain(infos, info); + } + + [Test] + public async Task FindByDocumentIdsAsync_DocumentIdsInIds_ReturnsAllMatched() + { + var expectedInfos = Enumerable.Repeat(DocumentProcessingInfoFactory, 5) + .Select(f => + { + var info = f(null); + info.DocumentId = Guid.NewGuid(); + + return info; + }) + .ToArray(); + var ids = Enumerable.Repeat(Guid.NewGuid, expectedInfos.Length) + .Select(f => f()) + .Concat(expectedInfos.Select(i => i.DocumentId.Value)) + .Concat + ( + Enumerable.Repeat(Guid.NewGuid, expectedInfos.Length) + .Select(f => f()) + ) + .ToArray(); + await _context.DocumentProcessingInfos.AddRangeAsync(expectedInfos); + await _context.SaveChangesAsync(); + + var infos = await _repository.FindByDocumentIdsAsync(ids); + + infos.Should().Contain(expectedInfos); + } + + public void Dispose() + { + _contextFactory.Dispose(); + } + + private readonly Random _idSeries = new(DateTime.Now.Millisecond); + + private readonly IngestorRunInfo _runInfo = IngestorRunInfoFactory(); + + private static IngestorRunInfo IngestorRunInfoFactory() + { + return new() + { + EndTimeStamp = DateTime.Now, + IngestorType = IngestorTypes.FosDnaDocument, + IngestorRunInfoId = Guid.NewGuid(), + IndexTotal = DateTime.Now.Millisecond, + IndexFileName = Guid.NewGuid().ToString(), + IndexFilePath = Guid.NewGuid().ToString(), + StartTimeStamp = DateTime.Now + }; + } + + private ProcessStatusTypes ProcessStatusTypesFactory() + => EnumValueFactory(); + + private NotificationStatusTypes NotificationStatusTypesFactory(NotificationStatusTypes? not = null) + => EnumValueFactory(not); + + private T EnumValueFactory(T? not = null) where T : struct, Enum + { + var availableValues = Enum.GetValues().Where(t => not == null || !t.Equals(not.Value)).ToArray(); + + return availableValues[_idSeries.Next() % availableValues.Length]; + } + + private DocumentProcessingInfo DocumentProcessingInfoFactory(IngestorRunInfo? runInfo = null) + => new() + { + CreatedDate = DateTime.Now, + DocumentFileName = Guid.NewGuid().ToString(), + DocumentId = Guid.NewGuid(), + DocumentType = Guid.NewGuid().ToString(), + DocumentBusinessName = Guid.NewGuid().ToString(), + DocumentValuePayload = @$" +{{ + ""{Guid.NewGuid()}"":""{Guid.NewGuid().ToString()}"", + ""{Guid.NewGuid()}"":""{Guid.NewGuid().ToString()}"", + ""{Guid.NewGuid()}"":""{Guid.NewGuid().ToString()}"" +}} +", + DocumentProcessingInfoId = _idSeries.Next(), + IngestorRunInfoId = (runInfo ?? _runInfo).IngestorRunInfoId, + IngestorRunInfo = runInfo ?? _runInfo, + ProcessCount = 0, + StatusType = ProcessStatusTypesFactory(), + MemberNotificationInfos = NotificationInfoFactory() + }; + + private List NotificationInfoFactory() + => new() { + new MemberNotificationInfo + { + NotificationStatusType = NotificationStatusTypesFactory() + }, + new MemberNotificationInfo + { + NotificationStatusType = NotificationStatusTypesFactory() + }, + new MemberNotificationInfo + { + NotificationStatusType = NotificationStatusTypesFactory() + } + }; +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Repositories/MemberNotificationInfoRepositoryTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Repositories/MemberNotificationInfoRepositoryTest.cs new file mode 100644 index 0000000..e42d467 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Repositories/MemberNotificationInfoRepositoryTest.cs @@ -0,0 +1,133 @@ +using FluentAssertions; +using LCU.API.Internal.DocumentIngestorLib.Persistence; +using LCU.API.Internal.DocumentIngestorLib.Repositories; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; + +namespace LCU.API.Internal.DocumentIngestorLibTests.Repositories; + +public class MemberNotificationInfoRepositoryTest : IDisposable +{ + private IMemberNotificationInfoRepository _repository; + + private readonly SqliteAppDbContextFactory _contextFactory = new(); + private AppDbContext _context; + + [SetUp] + public void Setup() + { + _context = _contextFactory.CreateContext(); + _repository = new MemberNotificationInfoRepository(_context); + } + + [Test] + public async Task FindNotificationByDocumentProcessingInfoIdAsync_NoneMatchedByDocumentProcessingInfoId_ReturnsNull() + { + _context.MemberNotificationInfos.RemoveRange(_context.MemberNotificationInfos); + await _context.SaveChangesAsync(); + + var notifications = await _repository.FindByDocumentProcessingInfoIdAsync(DateTime.Now.Millisecond); + + Assert.That(notifications, Is.Empty); + } + + [Test] + public async Task FindNotificationByDocumentProcessingInfoIdAsync_OneMatchedByDocumentProcessingInfoId_ReturnsRecord() + { + var documentProcessingInfo = (await _context.DocumentProcessingInfos.AddAsync(DocumentProcessingInfoFactory())).Entity; + var notificationRecord = (await _context.MemberNotificationInfos.AddAsync(MemberNotificationInfoFactory(documentProcessingInfo.DocumentProcessingInfoId))).Entity; + await _context.SaveChangesAsync(); + + var notification = await _repository.FindByDocumentProcessingInfoIdAsync(notificationRecord.DocumentProcessingInfoId); + + notification.FirstOrDefault().Should().BeEquivalentTo(notificationRecord); + } + + [Test] + public async Task FindNotificationByDocumentProcessingInfoIdAsync_MultipleMatchedByDocumentProcessingInfoId_ReturnsFirst() + { + var documentProcessingInfo = (await _context.DocumentProcessingInfos.AddAsync(DocumentProcessingInfoFactory())).Entity; + var notificationRecord = MemberNotificationInfoFactory(documentProcessingInfo.DocumentProcessingInfoId); + + await _context.MemberNotificationInfos.AddRangeAsync(notificationRecord, + MemberNotificationInfoFactory(notificationRecord.DocumentProcessingInfoId), + MemberNotificationInfoFactory(notificationRecord.DocumentProcessingInfoId)); + await _context.SaveChangesAsync(); + + var notification = await _repository.FindByDocumentProcessingInfoIdAsync(documentProcessingInfo.DocumentProcessingInfoId); + notification.FirstOrDefault()?.DocumentProcessingInfoId.Equals(documentProcessingInfo.DocumentProcessingInfoId); + } + + [Test] + public async Task GetMemberNotificationInfosByFilter_ReturnsRecords() + { + var documentProcessingInfos = new List + { + DocumentProcessingInfoFactory(DateTime.Now.Millisecond), + DocumentProcessingInfoFactory(DateTime.Now.Millisecond + 1), + DocumentProcessingInfoFactory(DateTime.Now.Millisecond + 2) + }; + await _context.DocumentProcessingInfos.AddRangeAsync(documentProcessingInfos); + await _context.MemberNotificationInfos.AddRangeAsync(new List() + { + new() { + DocumentProcessingInfoId = documentProcessingInfos[0].DocumentProcessingInfoId, + NotificationStatusType = NotificationStatusTypes.CriticalFailure + }, + new() { + DocumentProcessingInfoId = documentProcessingInfos[1].DocumentProcessingInfoId, + NotificationStatusType = NotificationStatusTypes.CriticalFailure + }, + new() { + DocumentProcessingInfoId = documentProcessingInfos[2].DocumentProcessingInfoId, + NotificationStatusType = NotificationStatusTypes.Complete + } + } + ); + await _context.SaveChangesAsync(); + + var filter = new Filter + { + NotificationStatusFilters = new List + { + NotificationStatusTypes.CriticalFailure + } + }; + + var notificationInfos = await _repository.GetMemberNotificationInfosByFilter(filter); + + Assert.That(notificationInfos.Count(), Is.EqualTo(2)); + Assert.That(notificationInfos.FirstOrDefault()?.NotificationStatusType, Is.EqualTo(filter.NotificationStatusFilters.FirstOrDefault())); + } + + public void Dispose() + { + _contextFactory.Dispose(); + } + + private static MemberNotificationInfo MemberNotificationInfoFactory(int? documentProcessingInfoId = null) + => new() + { + DocumentProcessingInfoId = documentProcessingInfoId ?? DateTime.Now.Millisecond + }; + + private static DocumentProcessingInfo DocumentProcessingInfoFactory(int? documentProcessingInfoId = null) + => new() + { + DocumentProcessingInfoId = documentProcessingInfoId ?? DateTime.Now.Millisecond, + CreatedDate = DateTime.Now, + DocumentValuePayload = "test", + StatusType = ProcessStatusTypes.Completed, + ProcessCount = 1, + DocumentType = "TaxDocument", + DocumentBusinessName = "1099-MISC", + EntityUnknown = false, + IngestorRunInfo = new IngestorRunInfo() + { + IngestorRunInfoId = Guid.NewGuid(), + IndexTotal = 1, + IndexFileName = "test" + } + }; +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Repositories/ProcessingLogRepositoryTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Repositories/ProcessingLogRepositoryTest.cs new file mode 100644 index 0000000..027c2ec --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Repositories/ProcessingLogRepositoryTest.cs @@ -0,0 +1,120 @@ +using LCU.API.Internal.DocumentIngestorLib.Persistence; +using LCU.API.Internal.DocumentIngestorLib.Repositories; +using LCU.API.Internal.DocumentIngestorLibTests; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; + +namespace LCU.API.Internal.DocumentIngestorLibTests.Repositories; + +public class ProcessingLogRepositoryTest +{ + private IProcessingLogRepository _repository; + + private readonly SqliteAppDbContextFactory _contextFactory = new(); + private AppDbContext _context; + + [SetUp] + public void Setup() + { + _context = _contextFactory.CreateContext(); + _repository = new ProcessingLogRepository(_context); + } + + [Test] + public async Task FindAsync_ReturnsRecord() + { + var id = DateTime.Now.Millisecond; + await _context.DocumentProcessingInfos.AddAsync(DocumentProcessingInfoFactory(id)); + var processingLogs = new List + {ProcessingLogFactory(id + 1), ProcessingLogFactory(id + 2), ProcessingLogFactory(id + 3)}; + processingLogs.ForEach(x => x.DocumentProcessingInfoId = id); + await _context.ProcessingLogs.AddRangeAsync(processingLogs); + await _context.SaveChangesAsync(); + + var logs = await _repository.FindAsync(); + Assert.That(logs.Count(), Is.EqualTo(3)); + } + + [Test] + public async Task FindByIdAsync_ReturnsRecord() + { + var id = DateTime.Now.Millisecond; + await _context.DocumentProcessingInfos.AddAsync(DocumentProcessingInfoFactory(id + 1)); + var log = ProcessingLogFactory(id); + log.DocumentProcessingInfoId = id + 1; + await _context.ProcessingLogs.AddAsync(log); + await _context.SaveChangesAsync(); + + var logs = await _repository.FindByIdAsync(id); + Assert.That(logs.ProcessingLogId, Is.EqualTo(id)); + } + + [Test] + public async Task FindByIdAsync_ReturnsNull() + { + var id = DateTime.Now.Millisecond; + await _context.DocumentProcessingInfos.AddAsync(DocumentProcessingInfoFactory(id + 1)); + var log = ProcessingLogFactory(id); + log.DocumentProcessingInfoId = id + 1; + await _context.ProcessingLogs.AddAsync(log); + await _context.SaveChangesAsync(); + + var logs = await _repository.FindByIdAsync(id + 5); + Assert.That(logs, Is.Null); + } + + [Test] + public async Task FindByDocumentProcessingInfoIdAsync_ReturnsRecord() + { + var id = DateTime.Now.Millisecond; + await _context.DocumentProcessingInfos.AddAsync(DocumentProcessingInfoFactory(id)); + var log = ProcessingLogFactory(); + log.DocumentProcessingInfoId = id; + await _context.ProcessingLogs.AddAsync(log); + await _context.SaveChangesAsync(); + + var logs = await _repository.FindByDocumentProcessingInfoIdAsync(id); + Assert.That(logs.FirstOrDefault()?.DocumentProcessingInfoId, Is.EqualTo(id)); + } + + [Test] + public async Task FindByDocumentProcessingInfoIdAsync_ReturnsNull() + { + var id = DateTime.Now.Millisecond; + await _context.DocumentProcessingInfos.AddAsync(DocumentProcessingInfoFactory(id)); + var log = ProcessingLogFactory(); + log.DocumentProcessingInfoId = id; + await _context.ProcessingLogs.AddAsync(log); + await _context.SaveChangesAsync(); + + var logs = await _repository.FindByDocumentProcessingInfoIdAsync(id + 5); + Assert.That(logs, Is.Empty); + } + + private static ProcessingLog ProcessingLogFactory(int? processingLogId = null) + => new() + { + ProcessingLogId = processingLogId ?? DateTime.Now.Millisecond, + DocumentProcessingInfoId = DateTime.Now.Millisecond, + LogMessage = Guid.NewGuid().ToString(), + }; + + private static DocumentProcessingInfo DocumentProcessingInfoFactory(int? documentProcessingInfoId = null) + => new() + { + DocumentProcessingInfoId = documentProcessingInfoId ?? DateTime.Now.Millisecond, + CreatedDate = DateTime.Now, + DocumentValuePayload = "test", + StatusType = ProcessStatusTypes.Completed, + ProcessCount = 1, + DocumentType = "TaxDocument", + DocumentBusinessName = "1099-MISC", + EntityUnknown = false, + IngestorRunInfo = new IngestorRunInfo() + { + IngestorRunInfoId = Guid.NewGuid(), + IndexTotal = 1, + IndexFileName = "test" + } + }; +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/SqlServerDbContextFactory.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/SqlServerDbContextFactory.cs new file mode 100644 index 0000000..50891f3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/SqlServerDbContextFactory.cs @@ -0,0 +1,138 @@ +using System.Collections; +using System.Collections.Concurrent; +using System.Data; +using Docker.DotNet; +using Docker.DotNet.Models; +using LCU.API.Internal.DocumentIngestorLib.Persistence; +using Microsoft.Data.SqlClient; +using Microsoft.EntityFrameworkCore; + +namespace LCU.API.Internal.DocumentIngestorLibTests; + +public class SqlServerDbContextFactory : IAsyncDisposable +{ + private const int port = 1434; + private const string password = "yourStrong(!)Password"; + + private readonly IList _contexts = new List(); + + private static readonly SemaphoreSlim ContainerUse = new(1); + private static CreateContainerResponse? Container; + private static readonly IDictionary _activeContexts = new ConcurrentDictionary(); + + public async Task CreateContext() + { + await ContainerUse.WaitAsync(); + Container ??= await DatabaseContainerFactory(); + ContainerUse.Release(); + + var connectionString = + $"Data Source=localhost,{port};User Id=sa;Password={password};Database={Guid.NewGuid()};MultipleActiveResultSets=True;App=EntityFramework;Trust Server Certificate=true"; + + var options = new DbContextOptionsBuilder() + .UseSqlServer(connectionString) + .EnableSensitiveDataLogging() + .Options; + + var context = new AppDbContext(options); + await DatabaseConnectionReady(connectionString); + await context.Database.EnsureCreatedAsync(); + + _contexts.Add(context); + _activeContexts[context] = true; + return context; + } + + private static async Task DatabaseContainerFactory() + { + const string ImageName = "mcr.microsoft.com/mssql/server:2019-CU18-ubuntu-20.04"; + const int containerPort = 1433; + + using var docker = new DockerClientConfiguration().CreateClient(); + + await docker.Images.CreateImageAsync + ( + new ImagesCreateParameters + { + FromImage = ImageName + }, + null, + new Progress() + ); + var container = await docker.Containers.CreateContainerAsync + ( + new CreateContainerParameters + { + Image = ImageName, + Name = "LCU.API.Internal.DocumentIngestor.IntegrationTestDatabase", + Env = new List + { + "ACCEPT_EULA=Y", + $"MSSQL_SA_PASSWORD={password}" + }, + ExposedPorts = new Dictionary + { + {$"{containerPort}", default} + }, + HostConfig = new HostConfig + { + PortBindings = new Dictionary> + { + { $"{containerPort}", new List { new() { HostPort = $"{port}" } } } + } + } + } + ); + await docker.Containers.StartContainerAsync(container.ID, new ContainerStartParameters()); + + return container; + } + + private static async Task DatabaseConnectionReady(string connectionString) + { + await using var connection = new SqlConnection(connectionString); + + var ready = false; + var triesRemaining = 20; + while (!ready && triesRemaining > 0) + { + triesRemaining--; + + try + { + await connection.OpenAsync(); + } + catch + { + await Task.Delay(TimeSpan.FromMilliseconds(200)); + } + + ready = connection.State == ConnectionState.Open; + } + } + + public async ValueTask DisposeAsync() + { + foreach (var context in _contexts) + { + await context.DisposeAsync(); + _activeContexts[context] = false; + } + + await ContainerUse.WaitAsync(); + if (_activeContexts.Values.All(a => a == false)) + { + await DisposeContainer(Container); + Container = null; + } + ContainerUse.Release(); + } + + private static async Task DisposeContainer(CreateContainerResponse container) + { + using var docker = new DockerClientConfiguration().CreateClient(); + + await docker.Containers.StopContainerAsync(container.ID, new ContainerStopParameters()); + await docker.Containers.RemoveContainerAsync(container.ID, new ContainerRemoveParameters()); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/SqliteAppDbContextFactory.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/SqliteAppDbContextFactory.cs new file mode 100644 index 0000000..cb543b7 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/SqliteAppDbContextFactory.cs @@ -0,0 +1,35 @@ +using LCU.API.Internal.DocumentIngestorLib.Persistence; +using Microsoft.Data.Sqlite; +using Microsoft.EntityFrameworkCore; + +namespace LCU.API.Internal.DocumentIngestorLibTests; + +public class SqliteAppDbContextFactory : IDisposable +{ + private readonly IList _connections = new List(); + private readonly IList _contexts = new List(); + + public AppDbContext CreateContext() + { + var connection = new SqliteConnection("Filename=:memory:"); + _connections.Add(connection); + connection.Open(); + + var options = new DbContextOptionsBuilder() + .UseSqlite(connection) + .EnableSensitiveDataLogging() + .Options; + + var context = new AppDbContext(options); + context.Database.EnsureCreated(); + + _contexts.Add(context); + return context; + } + + public void Dispose() + { + foreach (var connection in _connections) connection.Dispose(); + foreach (var context in _contexts) context.Dispose(); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Usings.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Usings.cs new file mode 100644 index 0000000..cefced4 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorLibTests/Usings.cs @@ -0,0 +1 @@ +global using NUnit.Framework; \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/DocumentProcessingInfo.sql b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/DocumentProcessingInfo.sql new file mode 100644 index 0000000..40e933c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/DocumentProcessingInfo.sql @@ -0,0 +1,25 @@ +CREATE TABLE [dbo].[DocumentProcessingInfo] +( + [DocumentProcessingInfoId] INT NOT NULL PRIMARY KEY IDENTITY, + [DocumentId] UNIQUEIDENTIFIER NULL, + [IngestorRunInfoId] UNIQUEIDENTIFIER NOT NULL, + [CreatedDate] DATETIME NOT NULL, + [DocumentValuePayload] VARCHAR(MAX) NOT NULL, + [StatusType] INT NOT NULL, + [DocumentFileName] VARCHAR(500) NOT NULL, + [ProcessCount] INT NOT NULL DEFAULT 0, + [DocumentType] VARCHAR(100) NOT NULL, + [DocumentBusinessName] VARCHAR(500) NOT NULL, + [EntityUnknown] BIT NOT NULL DEFAULT 0, + CONSTRAINT [FK_DocumentProcessingInfo_IngestorRunInfo] FOREIGN KEY ([IngestorRunInfoId]) REFERENCES [IngestorRunInfo]([IngestorRunInfoId]) +) +GO + +CREATE NONCLUSTERED INDEX [IX_DocumentProcessingInfo_IngestorRunInfoId_StatusType_CreatedDate] ON [dbo].[DocumentProcessingInfo] +( + [IngestorRunInfoId] ASC, + [StatusType] ASC, + [CreatedDate] ASC +) +INCLUDE([DocumentProcessingInfoId],[DocumentId],[DocumentValuePayload],[DocumentFileName],[ProcessCount],[DocumentType],[DocumentBusinessName],[EntityUnknown]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, FILLFACTOR = 80) ON [PRIMARY] +GO diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/DocumentTypeArchiveDeleteInfo.sql b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/DocumentTypeArchiveDeleteInfo.sql new file mode 100644 index 0000000..68999c3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/DocumentTypeArchiveDeleteInfo.sql @@ -0,0 +1,8 @@ +CREATE TABLE [dbo].[DocumentTypeArchiveDeleteInfo] +( + [DocumentTypeName] VARCHAR(200) NOT NULL, + [ArchiveDays] INT NOT NULL Default 0, + [ArchiveMonths] INT NOT NULL Default 0, + [DeleteDays] INT NULL, + CONSTRAINT [PK_DocumentTypeArchiveDeleteInfo] PRIMARY KEY ([DocumentTypeName]) +) diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/IngestorRunInfo.sql b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/IngestorRunInfo.sql new file mode 100644 index 0000000..f1dd21b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/IngestorRunInfo.sql @@ -0,0 +1,12 @@ +CREATE TABLE [dbo].[IngestorRunInfo] +( + [IngestorRunInfoId] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY, + [StartTimeStamp] DATETIME NOT NULL, + [EndTimeStamp] DATETIME NULL, + [IngestorType] INT NOT NULL, + [IndexFilePath] VARCHAR(1000) NULL, + [IndexFileName] VARCHAR(500) NULL, + [IndexTotal] INT NULL, + [ArchiveTimeStamp] DATETIME NULL, + [IngestionRunCount] INT NOT NULL Default 0 +) diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/LCU.API.Internal.DocumentIngestorSql.refactorlog b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/LCU.API.Internal.DocumentIngestorSql.refactorlog new file mode 100644 index 0000000..ec3d25b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/LCU.API.Internal.DocumentIngestorSql.refactorlog @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/LCU.API.Internal.DocumentIngestorSql.sqlproj b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/LCU.API.Internal.DocumentIngestorSql.sqlproj new file mode 100644 index 0000000..ae7797a --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/LCU.API.Internal.DocumentIngestorSql.sqlproj @@ -0,0 +1,74 @@ + + + + Debug + AnyCPU + LCU.API.Internal.DocumentIngestorSql + 2.0 + 4.1 + {781f2de1-9629-49d1-82a4-015b62ee92ef} + Microsoft.Data.Tools.Schema.Sql.Sql130DatabaseSchemaProvider + Database + + + LCU.API.Internal.DocumentIngestorSql + LCU.API.Internal.DocumentIngestorSql + 1033, CI + BySchemaAndSchemaType + True + v4.7.2 + CS + Properties + False + True + True + + + bin\Release\ + $(MSBuildProjectName).sql + False + pdbonly + true + false + true + prompt + 4 + + + bin\Debug\ + $(MSBuildProjectName).sql + false + true + full + false + true + true + prompt + 4 + + + 11.0 + + True + 11.0 + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/MemberNotificationInfo.sql b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/MemberNotificationInfo.sql new file mode 100644 index 0000000..1e7cb09 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/MemberNotificationInfo.sql @@ -0,0 +1,15 @@ +CREATE TABLE [dbo].[MemberNotificationInfo] +( + [MemberNotificationInfoId] INT NOT NULL PRIMARY KEY IDENTITY, + [DocumentProcessingInfoId] INT NOT NULL, + [UploadDate] DATETIME NOT NULL, + [DeliveryMethod] INT NULL, + [SentTimeStamp] DATETIME NULL, + [AgreeUserId] VARCHAR(50) NULL, + [EntityName] VARCHAR(100) NULL, + [EmailAddress] VARCHAR(100) NULL, + [NotificationStatusType] INT NOT NULL, + [Attempts] INT NOT NULL DEFAULT 0, + [ResponseTimeStamp] DATETIME NULL, + CONSTRAINT [FK_MemberNotificationInfo_DocumentProcessingInfo] FOREIGN KEY ([DocumentProcessingInfoId]) REFERENCES [DocumentProcessingInfo]([DocumentProcessingInfoId]) +) diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/OsgPreprocessorInfo.sql b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/OsgPreprocessorInfo.sql new file mode 100644 index 0000000..d2ec646 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/OsgPreprocessorInfo.sql @@ -0,0 +1,15 @@ +CREATE TABLE [dbo].[OsgPreprocessorInfo] +( + [OsgPreprocessorInfoId] INT NOT NULL PRIMARY KEY IDENTITY, + [BatchRunInfoId] UNIQUEIDENTIFIER NOT NULL, + [ZipFileName] VARCHAR(100) NOT NULL, + [ZipFileStartTime] DATETIME NOT NULL, + [ZipFileEndTime] DATETIME NOT NULL, + [DocumentType] VARCHAR(50) NOT NULL, + [EntityName] VARCHAR(100) NULL, + [MemberNumber] VARCHAR(50) NOT NULL, + [CreatedDate] DATETIME NOT NULL, + [StartingPage] INT NOT NULL, + [NumberOfPages] INT NOT NULL, + [XmlOutput] XML NOT NULL +) diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/OwnerOverrideInfo.sql b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/OwnerOverrideInfo.sql new file mode 100644 index 0000000..b899d4e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/OwnerOverrideInfo.sql @@ -0,0 +1,9 @@ +CREATE TABLE [dbo].[OwnerOverrideInfo] +( + [OwnerOverrideInfoId] INT NOT NULL PRIMARY KEY IDENTITY, + [UserName] VARCHAR(100) NOT NULL, + [EntityId] VARCHAR(500) NULL, + [EntityType] INT NOT NULL, + [DocumentProcessingInfoId] INT NOT NULL, + CONSTRAINT [FK_OwnerOverrideInfo_DocumentProcessingInfo] FOREIGN KEY ([DocumentProcessingInfoId]) REFERENCES [DocumentProcessingInfo]([DocumentProcessingInfoId]) +) diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/PdfPartitionerLog.sql b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/PdfPartitionerLog.sql new file mode 100644 index 0000000..08eb03a --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/PdfPartitionerLog.sql @@ -0,0 +1,8 @@ +CREATE TABLE [dbo].[PdfPartitionerLog] +( + [PdfPartitionerLogId] INT NOT NULL PRIMARY KEY IDENTITY, + [PdfPartitionerRunInfoId] UNIQUEIDENTIFIER NOT NULL, + [LogTimeStamp] DATETIME NOT NULL, + [LogMessage] VARCHAR(MAX) NOT NULL, + CONSTRAINT [FK_PdfPartitionerLog_PdfPartitionerRunInfo] FOREIGN KEY ([PdfPartitionerRunInfoId]) REFERENCES [PdfPartitionerRunInfo]([PdfPartitionerRunInfoId]) +) diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/PdfPartitionerRunInfo.sql b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/PdfPartitionerRunInfo.sql new file mode 100644 index 0000000..2fea842 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/PdfPartitionerRunInfo.sql @@ -0,0 +1,11 @@ +CREATE TABLE [dbo].[PdfPartitionerRunInfo] +( + [PdfPartitionerRunInfoId] UNIQUEIDENTIFIER NOT NULL PRIMARY KEY, + [StartTimeStamp] DATETIME NOT NULL, + [EndTimeStamp] DATETIME NULL, + [PdfParserType] INT NOT NULL, + [Path] VARCHAR(1000) NOT NULL, + [IndexTotal] INT NOT NULL, + [FailureCount] INT NOT NULL Default 0, + [SuccessCount] INT NOT NULL Default 0 +) diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/ProcessingLog.sql b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/ProcessingLog.sql new file mode 100644 index 0000000..c8f98f1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorSql/ProcessingLog.sql @@ -0,0 +1,9 @@ +CREATE TABLE [dbo].[ProcessingLog] +( + [ProcessingLogId] INT NOT NULL PRIMARY KEY IDENTITY, + [DocumentProcessingInfoId] INT NOT NULL, + [LogTimeStamp] DATETIME NOT NULL, + [LogMessage] VARCHAR(MAX) NOT NULL, + [UserName] VARCHAR(100) NOT NULL, + CONSTRAINT [FK_ProcessingLog_DocumentProcessingInfo] FOREIGN KEY ([DocumentProcessingInfoId]) REFERENCES [DocumentProcessingInfo]([DocumentProcessingInfoId]) +) diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/BatchIngestionControllerTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/BatchIngestionControllerTest.cs new file mode 100644 index 0000000..af6218a --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/BatchIngestionControllerTest.cs @@ -0,0 +1,86 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Moq; +using NUnit.Framework; +using LCU.API.Internal.DocumentIngestor.Controllers; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +namespace LCU.API.Internal.DocumentIngestorTests.Controllers; + +public class BatchIngestionControllerTest +{ + private BatchIngestionController _batchIngestionControllerTest; + private Mock _mockQueueBatchIngestionService; + + [SetUp] + public void Setup() + { + _mockQueueBatchIngestionService = new Mock(); + _batchIngestionControllerTest = new BatchIngestionController(_mockQueueBatchIngestionService.Object); + } + + [Test] + public async Task QueueBatchIngestion_Accepted() + { + var request = new BatchIngestionRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + IngestorType = IngestorTypes.FosTaxStatement + }; + _mockQueueBatchIngestionService.Setup(service => service.QueueBatchIngestionRequest(request)).Verifiable(); + + var result = await _batchIngestionControllerTest.QueueBatchIngestion(request); + Assert.NotNull(result); + + var okResult = result as AcceptedResult; + Assert.NotNull(okResult); + Assert.AreEqual(202, okResult!.StatusCode); + _mockQueueBatchIngestionService.Verify(); + } + + [Test] + public async Task QueueBatchIngestion_Failure_UnexpectedException() + { + var request = new BatchIngestionRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + IngestorType = IngestorTypes.FosTaxStatement + }; + _mockQueueBatchIngestionService.Setup(service => service.QueueBatchIngestionRequest(request)) + .Throws(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _batchIngestionControllerTest.QueueBatchIngestion(request); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockQueueBatchIngestionService.Verify(); + } + + [Test] + public async Task QueueBatchIngestion_Failure_ServiceException() + { + var request = new BatchIngestionRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + IngestorType = IngestorTypes.FosTaxStatement + }; + _mockQueueBatchIngestionService.Setup(service => service.QueueBatchIngestionRequest(request)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _batchIngestionControllerTest.QueueBatchIngestion(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockQueueBatchIngestionService.Verify(); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/DocumentIngestorControllerTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/DocumentIngestorControllerTest.cs new file mode 100644 index 0000000..0c876ee --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/DocumentIngestorControllerTest.cs @@ -0,0 +1,75 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Controllers; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.Library.Internal.DocumentIngestorModels.Models; +namespace LCU.API.Internal.DocumentIngestorTests.Controllers; + +public class DocumentIngestorControllerTest +{ + private DocumentIngestorController _documentIngestorController; + private Mock _mockQueueDocumentIngestorService; + + [SetUp] + public void Setup() + { + _mockQueueDocumentIngestorService = new Mock(); + _documentIngestorController = new DocumentIngestorController(_mockQueueDocumentIngestorService.Object); + } + + [Test] + public async Task QueueDocumentIngestor_OK() + { + var request = new IngestorRequest(); + + _mockQueueDocumentIngestorService.Setup(service => service.QueueDocumentIngestorRequest(request)).Verifiable(); + + var result = await _documentIngestorController.QueueDocumentIngestor(request); + Assert.NotNull(result); + + var okResult = result as AcceptedResult; + Assert.NotNull(okResult); + Assert.AreEqual(202, okResult!.StatusCode); + _mockQueueDocumentIngestorService.Verify(); + } + + [Test] + public async Task QueueDocumentIngestor_ServiceException_InternalServerError() + { + var request = new IngestorRequest(); + + _mockQueueDocumentIngestorService.Setup(service => + service.QueueDocumentIngestorRequest(request)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentIngestorController.QueueDocumentIngestor(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockQueueDocumentIngestorService.Verify(); + } + + [Test] + public async Task QueueDocumentIngestor_UnexpectedException_InternalServerError() + { + var request = new IngestorRequest(); + + _mockQueueDocumentIngestorService.Setup(service => + service.QueueDocumentIngestorRequest(request)) + .Throws(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _documentIngestorController.QueueDocumentIngestor(request); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockQueueDocumentIngestorService.Verify(); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/DocumentProcessingInfoControllerTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/DocumentProcessingInfoControllerTest.cs new file mode 100644 index 0000000..6954195 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/DocumentProcessingInfoControllerTest.cs @@ -0,0 +1,573 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Controllers; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using System.Collections.Generic; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using System.Linq; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using Microsoft.AspNetCore.Http; + +namespace LCU.API.Internal.DocumentIngestorTests.Controllers; + +public class DocumentProcessingInfoControllerTest +{ + private DocumentProcessingInfoController _documentProcessingInfoController; + private Mock _mockDocumentProcessingInfoService; + + [SetUp] + public void Setup() + { + _mockDocumentProcessingInfoService = new Mock(); + _documentProcessingInfoController = new DocumentProcessingInfoController(_mockDocumentProcessingInfoService.Object); + } + + [Test] + public async Task Get_OK() + { + var documentProcessingInfos = new List() + { + new DocumentProcessingInfo() + { + DocumentProcessingInfoId = 1 + } + }; + _mockDocumentProcessingInfoService.Setup(service => service.GetAsync()) + .ReturnsAsync(documentProcessingInfos).Verifiable(); + + var result = await _documentProcessingInfoController.Get(); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task Get_ServiceException_InternalServerError() + { + var documentProcessingInfos = new List(); + _mockDocumentProcessingInfoService.Setup(service => service.GetAsync()) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentProcessingInfoController.Get(); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task Get_UnexpectedException_InternalServerError() + { + var documentProcessingInfos = new List(); + _mockDocumentProcessingInfoService.Setup(service => service.GetAsync()) + .ThrowsAsync(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _documentProcessingInfoController.Get(); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task GetById_OK() + { + var id = 1; + var documentProcessingInfo = new DocumentProcessingInfo(); + _mockDocumentProcessingInfoService.Setup(service => service.GetByIdAsync(id)) + .ReturnsAsync(documentProcessingInfo).Verifiable(); + + var result = await _documentProcessingInfoController.GetById(id); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task GetById_ServiceException_InternalServerError() + { + var id = 1; + _mockDocumentProcessingInfoService.Setup(service => service.GetByIdAsync(id)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentProcessingInfoController.GetById(id); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task GetById_UnexpectedException_InternalServerError() + { + var id = 1; + _mockDocumentProcessingInfoService.Setup(service => service.GetByIdAsync(id)) + .ThrowsAsync(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _documentProcessingInfoController.GetById(id); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task GetByIngestorRunInfoId_OK() + { + var ingestorRunInfoId = Guid.NewGuid(); + var documentProcessingInfos = new List() + { + new DocumentProcessingInfo() + { + DocumentProcessingInfoId = 1 + } + }; + _mockDocumentProcessingInfoService.Setup(service => service.GetByIngestorRunInfoIdAsync(ingestorRunInfoId)) + .ReturnsAsync(documentProcessingInfos).Verifiable(); + + var result = await _documentProcessingInfoController.GetByIngestorRunInfoId(ingestorRunInfoId); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task GetByIngestorRunInfoId_ServiceException_InternalServerError() + { + var ingestorRunInfoId = Guid.NewGuid(); + _mockDocumentProcessingInfoService.Setup(service => service.GetByIngestorRunInfoIdAsync(ingestorRunInfoId)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentProcessingInfoController.GetByIngestorRunInfoId(ingestorRunInfoId); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task GetByIngestorRunInfoId_UnexpectedException_InternalServerError() + { + var ingestorRunInfoId = Guid.NewGuid(); + _mockDocumentProcessingInfoService.Setup(service => service.GetByIngestorRunInfoIdAsync(ingestorRunInfoId)) + .ThrowsAsync(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _documentProcessingInfoController.GetByIngestorRunInfoId(ingestorRunInfoId); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task Post_CreatedAtAction() + { + var ingestorRunInfoId = Guid.NewGuid(); + var request = new DocumentProcessingInfo() + { + IngestorRunInfoId = ingestorRunInfoId, + DocumentValuePayload = "Test" + }; + + var requestReturn = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = 1, + DocumentValuePayload = "Test", + IngestorRunInfoId = Guid.NewGuid() + }; + _mockDocumentProcessingInfoService.Setup(service => service.SaveAsync(request)).ReturnsAsync(requestReturn).Verifiable(); + + var result = await _documentProcessingInfoController.Post(request); + Assert.NotNull(result); + + var okResult = result as CreatedAtActionResult; + Assert.NotNull(okResult); + Assert.AreEqual(201, okResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task Post_ServiceException_InternalServerError() + { + var request = new DocumentProcessingInfo(); + _mockDocumentProcessingInfoService.Setup(service => + service.SaveAsync(request)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentProcessingInfoController.Post(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task Post_UnexpectedException_InternalServerError() + { + var request = new DocumentProcessingInfo(); + _mockDocumentProcessingInfoService.Setup(service => + service.SaveAsync(request)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentProcessingInfoController.Post(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task Put_OK() + { + var request = new DocumentProcessingInfo(); + _mockDocumentProcessingInfoService.Setup(service => service.Update(request)).ReturnsAsync(request).Verifiable(); + + var result = await _documentProcessingInfoController.Put(request); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task Put_ServiceException_InternalServerError() + { + var request = new DocumentProcessingInfo(); + _mockDocumentProcessingInfoService.Setup(service => + service.Update(request)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentProcessingInfoController.Put(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task Put_UnexpectedException_InternalServerError() + { + var request = new DocumentProcessingInfo(); + _mockDocumentProcessingInfoService.Setup(service => + service.Update(request)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentProcessingInfoController.Put(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task Delete_OK() + { + var id = 1; + _mockDocumentProcessingInfoService.Setup(service => service.Delete(id)).Verifiable(); + + var result = await _documentProcessingInfoController.Delete(id); + Assert.NotNull(result); + + var okResult = result as OkResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task Delete_ServiceException_InternalServerError() + { + var id = 1; + _mockDocumentProcessingInfoService.Setup(service => + service.Delete(id)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentProcessingInfoController.Delete(id); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task Delete_UnexpectedException_InternalServerError() + { + var id = 1; + _mockDocumentProcessingInfoService.Setup(service => + service.Delete(id)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentProcessingInfoController.Delete(id); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task PagedFilter_Ok() + { + + // Arrange + var filter = new Filter() + { + Limit = 2, + Page = 1 + }; + + _mockDocumentProcessingInfoService.Setup(service => service.GetFilteredDocumentProcessingInfo(filter)) + .ReturnsAsync(new PagedResult() + { + Total = 4, + Items = new List() + { + new DocumentProcessingInfo() {DocumentProcessingInfoId = 1}, + new DocumentProcessingInfo() {DocumentProcessingInfoId = 2}, + new DocumentProcessingInfo() {DocumentProcessingInfoId = 3}, + new DocumentProcessingInfo() {DocumentProcessingInfoId = 4} + } + }); + + // Act + var result = await _documentProcessingInfoController.GetFilteredDocumentProcessingInfo(filter); + + // Assert + Assert.NotNull(result); + + var okObject = result as OkObjectResult; + Assert.NotNull(okObject); + + var pagedResponse = okObject.Value as PagedResponse; + Assert.NotNull(pagedResponse); + + Assert.AreEqual(4, pagedResponse.TotalItems); + + Assert.AreEqual(1, pagedResponse.Items.ElementAt(0).DocumentProcessingInfoId); + Assert.AreEqual(2, pagedResponse.Items.ElementAt(1).DocumentProcessingInfoId); + + Assert.AreEqual(0, pagedResponse.PreviousPage); + Assert.AreEqual(2, pagedResponse.NextPage); + Assert.AreEqual(2, pagedResponse.TotalPages); + } + + [Test] + public async Task SetDocumentsToEntityUnknown_OK() + { + var request = new EntityUnknownRequest() + { + UserName = "System", + DocumentProcessingInfoIds = new List() { 1, 2, 3 } + }; + var documentProcessingInfos = new List() + { + new() + { + DocumentProcessingInfoId = 1, + }, + new() + { + DocumentProcessingInfoId = 2, + }, + new() + { + DocumentProcessingInfoId = 3, + } + }; + _mockDocumentProcessingInfoService.Setup(service => service.SetDocumentsToEntityUnknown(request)).ReturnsAsync(documentProcessingInfos).Verifiable(); + + var result = await _documentProcessingInfoController.SetDocumentsToEntityUnknown(request); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task SetDocumentsToEntityUnknown_ServiceException_InternalServerError() + { + var request = new EntityUnknownRequest() + { + UserName = "System", + DocumentProcessingInfoIds = new List() { 1, 2, 3 } + }; + _mockDocumentProcessingInfoService.Setup(service => + service.SetDocumentsToEntityUnknown(request)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentProcessingInfoController.SetDocumentsToEntityUnknown(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task UpdateStatus_OK() + { + var documentProcessingInfoId = DateTime.Now.Millisecond; + var request = new DocumentProcessingInfoStatusRequest() + { + DocumentProcessingInfoId = documentProcessingInfoId, + ProcessStatus = ProcessStatusTypes.Reprocessing, + ReasonMessage = Guid.NewGuid().ToString(), + Username = Guid.NewGuid().ToString() + }; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = DateTime.Now.Millisecond, + StatusType = ProcessStatusTypes.CriticalFailure + }; + _mockDocumentProcessingInfoService.Setup(service => service.UpdateDocumentProcessingInfoStatus(request)).ReturnsAsync(documentProcessingInfo).Verifiable(); + + var result = await _documentProcessingInfoController.UpdateDocumentProcessingInfoStatus(request); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task UpdateStatus_ServiceException_InternalServerError() + { + var documentProcessingInfoId = DateTime.Now.Millisecond; + var request = new DocumentProcessingInfoStatusRequest() + { + DocumentProcessingInfoId = documentProcessingInfoId, + ProcessStatus = ProcessStatusTypes.Reprocessing, + ReasonMessage = Guid.NewGuid().ToString(), + Username = Guid.NewGuid().ToString() + }; + _mockDocumentProcessingInfoService.Setup(service => + service.UpdateDocumentProcessingInfoStatus(request)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentProcessingInfoController.UpdateDocumentProcessingInfoStatus(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task UpdateStatus_NoContent() + { + var documentProcessingInfoId = DateTime.Now.Millisecond; + var request = new DocumentProcessingInfoStatusRequest() + { + DocumentProcessingInfoId = documentProcessingInfoId, + ProcessStatus = ProcessStatusTypes.Reprocessing, + ReasonMessage = Guid.NewGuid().ToString() + }; + DocumentProcessingInfo? documentProcessingInfo = null; + _mockDocumentProcessingInfoService.Setup(service => + service.UpdateDocumentProcessingInfoStatus(request)) + .ReturnsAsync(documentProcessingInfo); + + var result = await _documentProcessingInfoController.UpdateDocumentProcessingInfoStatus(request); + Assert.NotNull(result); + + var statusResult = result as NoContentResult; + Assert.IsNotNull(statusResult); + Assert.AreEqual(204, statusResult!.StatusCode); + _mockDocumentProcessingInfoService.Verify(); + } + + [Test] + public async Task GetByDocumentIds_InfoServiceReturnsResults_Returns200OkResults() + { + var ids = Enumerable.Repeat(Guid.NewGuid, 5) + .Select(f => f()) + .ToArray(); + var infos = new Dictionary(); + _mockDocumentProcessingInfoService + .Setup(dpis => dpis.GetByDocumentIdsAsync(ids)) + .ReturnsAsync(infos); + + var result = await _documentProcessingInfoController.GetByDocumentIds(ids); + + Assert.IsInstanceOf(result); + Assert.AreEqual(StatusCodes.Status200OK, ((OkObjectResult)result).StatusCode); + Assert.AreEqual(infos, ((OkObjectResult)result).Value); + } + + [Test] + public async Task GetByDocumentIds_InfoServiceThrowsException_Returns500InternalServerError() + { + var ids = Enumerable.Repeat(Guid.NewGuid, 5) + .Select(f => f()) + .ToArray(); + _mockDocumentProcessingInfoService + .Setup(dpis => dpis.GetByDocumentIdsAsync(ids)) + .ThrowsAsync(new Exception()); + + var result = await _documentProcessingInfoController.GetByDocumentIds(ids); + + Assert.IsInstanceOf(result); + Assert.AreEqual(StatusCodes.Status500InternalServerError, ((StatusCodeResult)result).StatusCode); + } + + [Test] + public async Task GetByDocumentIds_InfoServiceThrowsServiceException_Returns500InternalServerError() + { + var ids = Enumerable.Repeat(Guid.NewGuid, 5) + .Select(f => f()) + .ToArray(); + _mockDocumentProcessingInfoService + .Setup(dpis => dpis.GetByDocumentIdsAsync(ids)) + .ThrowsAsync(new ServiceException(string.Empty)); + + var result = await _documentProcessingInfoController.GetByDocumentIds(ids); + + Assert.IsInstanceOf(result); + Assert.AreEqual(StatusCodes.Status500InternalServerError, ((ObjectResult)result).StatusCode); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/DocumentReprocessingControllerTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/DocumentReprocessingControllerTest.cs new file mode 100644 index 0000000..7da31b3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/DocumentReprocessingControllerTest.cs @@ -0,0 +1,226 @@ +using LCU.API.Internal.DocumentIngestor.Controllers; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +using Microsoft.AspNetCore.Mvc; +using Moq; +using NUnit.Framework; +using System; +using System.Threading.Tasks; +using LCU.API.Internal.DocumentIngestor.Services; + +namespace LCU.API.Internal.DocumentIngestorTests.Controllers; + +public class DocumentReprocessingControllerTest +{ + private DocumentReprocessingController _documentReprocessingController; + private Mock _mockReprocessingService; + + [SetUp] + public void Setup() + { + _mockReprocessingService = new Mock(); + _documentReprocessingController = new DocumentReprocessingController(_mockReprocessingService.Object); + } + + [Test] + public async Task ReprocessDocumentByDocumentProcessingInfoId_OK() + { + var id = 1; + var userName = "Test Tester"; + _mockReprocessingService.Setup(service => service.QueueReprocessDocumentByDocumentProcessingInfoId(id, userName)).Verifiable(); + + var result = await _documentReprocessingController.QueueReprocessDocumentByDocumentProcessingInfoId(id, userName); + Assert.NotNull(result); + + var okResult = result as AcceptedResult; + Assert.NotNull(okResult); + Assert.AreEqual(202, okResult!.StatusCode); + _mockReprocessingService.Verify(); + } + + [Test] + public async Task QueueDocumentIngestor_Failure_UnexpectedException() + { + var id = 1; + var userName = "Test Tester"; + _mockReprocessingService.Setup(service => + service.QueueReprocessDocumentByDocumentProcessingInfoId(id, userName)) + .Throws(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _documentReprocessingController.QueueReprocessDocumentByDocumentProcessingInfoId(id, userName); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockReprocessingService.Verify(); + } + + [Test] + public async Task ReprocessDocumentByDocumentProcessingInfoId_Failure_ServiceException() + { + var id = 1; + var userName = "Test Tester"; + _mockReprocessingService.Setup(service => + service.QueueReprocessDocumentByDocumentProcessingInfoId(id, userName)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentReprocessingController.QueueReprocessDocumentByDocumentProcessingInfoId(id, userName); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockReprocessingService.Verify(); + } + + [Test] + public async Task ReprocessDocumentByDocumentProcessingInfoId_Failure_NullException() + { + var id = 1; + var userName = "Test Tester"; + _mockReprocessingService.Setup(service => + service.QueueReprocessDocumentByDocumentProcessingInfoId(id, userName)) + .Throws(new ArgumentNullException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentReprocessingController.QueueReprocessDocumentByDocumentProcessingInfoId(id, userName); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(404, statusResult!.StatusCode); + _mockReprocessingService.Verify(); + } + + [Test] + public async Task QueueOwnerOverrideDocumentByDocumentProcessingInfoId_OK() + { + var documentProcessingInfoId = 1; + var ownerOverrideInfo = new OwnerOverrideInfo() + { + DocumentProcessingInfoId = documentProcessingInfoId + }; + _mockReprocessingService.Setup(service => service.QueueOverrideDocumentByDocumentProcessingInfoId(ownerOverrideInfo)).Verifiable(); + + var result = await _documentReprocessingController.QueueOverrideDocumentByDocumentProcessingInfoId(ownerOverrideInfo); + Assert.NotNull(result); + + var okResult = result as AcceptedResult; + Assert.NotNull(okResult); + Assert.AreEqual(202, okResult!.StatusCode); + _mockReprocessingService.Verify(); + } + + [Test] + public async Task QueueOwnerOverrideDocumentByDocumentProcessingInfoId_Failure_UnexpectedException() + { + var documentProcessingInfoId = 1; + var ownerOverrideInfo = new OwnerOverrideInfo() + { + DocumentProcessingInfoId = documentProcessingInfoId + }; + _mockReprocessingService.Setup(service => + service.QueueOverrideDocumentByDocumentProcessingInfoId(ownerOverrideInfo)) + .Throws(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _documentReprocessingController.QueueOverrideDocumentByDocumentProcessingInfoId(ownerOverrideInfo); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockReprocessingService.Verify(); + } + + [Test] + public async Task QueueOwnerOverrideDocumentByDocumentProcessingInfoId_Failure_ServiceException() + { + var documentProcessingInfoId = 1; + var ownerOverrideInfo = new OwnerOverrideInfo() + { + DocumentProcessingInfoId = documentProcessingInfoId + }; + _mockReprocessingService.Setup(service => + service.QueueOverrideDocumentByDocumentProcessingInfoId(ownerOverrideInfo)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentReprocessingController.QueueOverrideDocumentByDocumentProcessingInfoId(ownerOverrideInfo); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockReprocessingService.Verify(); + } + + [Test] + public async Task QueueOwnerOverrideDocumentByDocumentProcessingInfoId_Failure_NullException() + { + var documentProcessingInfoId = 1; + var ownerOverrideInfo = new OwnerOverrideInfo() + { + DocumentProcessingInfoId = documentProcessingInfoId + }; + _mockReprocessingService.Setup(service => + service.QueueOverrideDocumentByDocumentProcessingInfoId(ownerOverrideInfo)) + .Throws(new ArgumentNullException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentReprocessingController.QueueOverrideDocumentByDocumentProcessingInfoId(ownerOverrideInfo); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(404, statusResult!.StatusCode); + _mockReprocessingService.Verify(); + } + + [Test] + public async Task QueueReprocessAllCriticalFailures_OK() + { + var userName = "ttester"; + _mockReprocessingService.Setup(service => service.QueueReprocessAllCriticalFailures(userName)).Verifiable(); + + var result = await _documentReprocessingController.QueueReprocessAllCriticalFailures(userName); + Assert.NotNull(result); + + var okResult = result as AcceptedResult; + Assert.NotNull(okResult); + Assert.AreEqual(202, okResult!.StatusCode); + _mockReprocessingService.Verify(); + } + + [Test] + public async Task QueueReprocessAllCriticalFailures_Failure_UnexpectedException() + { + var userName = "ttester"; + _mockReprocessingService.Setup(service => + service.QueueReprocessAllCriticalFailures(userName)) + .Throws(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _documentReprocessingController.QueueReprocessAllCriticalFailures(userName); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockReprocessingService.Verify(); + } + + [Test] + public async Task QueueReprocessAllCriticalFailures_Failure_ServiceException() + { + var userName = "ttester"; + _mockReprocessingService.Setup(service => + service.QueueReprocessAllCriticalFailures(userName)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentReprocessingController.QueueReprocessAllCriticalFailures(userName); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockReprocessingService.Verify(); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/DocumentTypeArchiveDeleteInfoControllerTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/DocumentTypeArchiveDeleteInfoControllerTest.cs new file mode 100644 index 0000000..b477e8b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/DocumentTypeArchiveDeleteInfoControllerTest.cs @@ -0,0 +1,323 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Controllers; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using System.Collections.Generic; + +namespace LCU.API.Internal.DocumentIngestorTests.Controllers; + +public class DocumentTypeArchiveDeleteInfoControllerTest +{ + private DocumentTypeArchiveDeleteInfoController _documentTypeArchiveDeleteInfoController; + private Mock _mockDocumentTypeArchiveDeleteInfoService; + + [SetUp] + public void Setup() + { + _mockDocumentTypeArchiveDeleteInfoService = new Mock(); + _documentTypeArchiveDeleteInfoController = new DocumentTypeArchiveDeleteInfoController(_mockDocumentTypeArchiveDeleteInfoService.Object); + } + + [Test] + public async Task Get_OK() + { + var documentTypeName = "OneThousandNinetyNineInt"; + var archiveDays = 200; + var deleteDays = 3000; + var documentTypeArchiveDeleteInfos = new List() + { + new DocumentTypeArchiveDeleteInfo() + { + DocumentTypeName = documentTypeName, + ArchiveDays = archiveDays, + DeleteDays = deleteDays + } + }; + _mockDocumentTypeArchiveDeleteInfoService.Setup(service => service.GetAsync()) + .ReturnsAsync(documentTypeArchiveDeleteInfos).Verifiable(); + + var result = await _documentTypeArchiveDeleteInfoController.Get(); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockDocumentTypeArchiveDeleteInfoService.Verify(); + } + + [Test] + public async Task Get_ServiceException_InternalServerError() + { + _mockDocumentTypeArchiveDeleteInfoService.Setup(service => service.GetAsync()) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentTypeArchiveDeleteInfoController.Get(); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentTypeArchiveDeleteInfoService.Verify(); + } + + [Test] + public async Task Get_UnexpectedException_InternalServerError() + { + _mockDocumentTypeArchiveDeleteInfoService.Setup(service => service.GetAsync()) + .ThrowsAsync(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _documentTypeArchiveDeleteInfoController.Get(); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentTypeArchiveDeleteInfoService.Verify(); + } + + [Test] + public async Task GetByDocumentTypeName_OK() + { + var documentTypeName = "OneThousandNinetyNineInt"; + var archiveDays = 200; + var deleteDays = 3000; + var documentTypeArchiveDeleteInfo = new DocumentTypeArchiveDeleteInfo() + { + DocumentTypeName = documentTypeName, + ArchiveDays = archiveDays, + DeleteDays = deleteDays + }; + _mockDocumentTypeArchiveDeleteInfoService.Setup(service => service.GetByDocumentTypeNameAsync(documentTypeName)) + .ReturnsAsync(documentTypeArchiveDeleteInfo).Verifiable(); + + var result = await _documentTypeArchiveDeleteInfoController.GetByDocumentTypeName(documentTypeName); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockDocumentTypeArchiveDeleteInfoService.Verify(); + } + + [Test] + public async Task GetByDocumentTypeName_ServiceException_InternalServerError() + { + var documentTypeName = "OneThousandNinetyNineInt"; + _mockDocumentTypeArchiveDeleteInfoService.Setup(service => service.GetByDocumentTypeNameAsync(documentTypeName)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentTypeArchiveDeleteInfoController.GetByDocumentTypeName(documentTypeName); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentTypeArchiveDeleteInfoService.Verify(); + } + + [Test] + public async Task GetByDocumentTypeName_UnexpectedException_InternalServerError() + { + var documentTypeName = "OneThousandNinetyNineInt"; + _mockDocumentTypeArchiveDeleteInfoService.Setup(service => service.GetByDocumentTypeNameAsync(documentTypeName)) + .ThrowsAsync(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _documentTypeArchiveDeleteInfoController.GetByDocumentTypeName(documentTypeName); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentTypeArchiveDeleteInfoService.Verify(); + } + + [Test] + public async Task Post_CreatedAtAction() + { + var request = new DocumentTypeArchiveDeleteInfo() + { + DocumentTypeName = "Test", + ArchiveDays = 1, + DeleteDays = null + }; + + var requestReturn = new DocumentTypeArchiveDeleteInfo() + { + DocumentTypeName = "Test", + ArchiveDays = 1, + DeleteDays = null + }; + + _mockDocumentTypeArchiveDeleteInfoService.Setup(service => service.SaveAsync(request)).ReturnsAsync(requestReturn).Verifiable(); + + var result = await _documentTypeArchiveDeleteInfoController.Post(request); + Assert.NotNull(result); + + var createdAtActionResult = result as CreatedAtActionResult; + Assert.NotNull(createdAtActionResult); + Assert.AreEqual(201, createdAtActionResult!.StatusCode); + _mockDocumentTypeArchiveDeleteInfoService.Verify(); + } + + [Test] + public async Task Post_ServiceException_InternalServerError() + { + var request = new DocumentTypeArchiveDeleteInfo(); + _mockDocumentTypeArchiveDeleteInfoService.Setup(service => + service.SaveAsync(request)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentTypeArchiveDeleteInfoController.Post(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentTypeArchiveDeleteInfoService.Verify(); + } + + [Test] + public async Task Post_UnexpectedException_InternalServerError() + { + var documentTypeName = "OneThousandNinetyNineInt"; + var archiveDays = 200; + var deleteDays = 3000; + var documentTypeArchiveDeleteInfo = new DocumentTypeArchiveDeleteInfo() + { + DocumentTypeName = documentTypeName, + ArchiveDays = archiveDays, + DeleteDays = deleteDays + }; + _mockDocumentTypeArchiveDeleteInfoService.Setup(service => + service.SaveAsync(documentTypeArchiveDeleteInfo)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentTypeArchiveDeleteInfoController.Post(documentTypeArchiveDeleteInfo); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentTypeArchiveDeleteInfoService.Verify(); + } + + [Test] + public async Task Put_OK() + { + var documentTypeName = "OneThousandNinetyNineInt"; + var archiveDays = 200; + var deleteDays = 3000; + var documentTypeArchiveDeleteInfo = new DocumentTypeArchiveDeleteInfo() + { + DocumentTypeName = documentTypeName, + ArchiveDays = archiveDays, + DeleteDays = deleteDays + }; + _mockDocumentTypeArchiveDeleteInfoService.Setup(service => + service.Update(documentTypeArchiveDeleteInfo)).ReturnsAsync(documentTypeArchiveDeleteInfo).Verifiable(); + + var result = await _documentTypeArchiveDeleteInfoController.Put(documentTypeArchiveDeleteInfo); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockDocumentTypeArchiveDeleteInfoService.Verify(); + } + + [Test] + public async Task Put_ServiceException_InternalServerError() + { + var documentTypeName = "OneThousandNinetyNineInt"; + var archiveDays = 200; + var deleteDays = 3000; + var documentTypeArchiveDeleteInfo = new DocumentTypeArchiveDeleteInfo() + { + DocumentTypeName = documentTypeName, + ArchiveDays = archiveDays, + DeleteDays = deleteDays + }; + _mockDocumentTypeArchiveDeleteInfoService.Setup(service => + service.Update(documentTypeArchiveDeleteInfo)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentTypeArchiveDeleteInfoController.Put(documentTypeArchiveDeleteInfo); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentTypeArchiveDeleteInfoService.Verify(); + } + + [Test] + public async Task Put_UnexpectedException_InternalServerError() + { + var request = new DocumentTypeArchiveDeleteInfo(); + _mockDocumentTypeArchiveDeleteInfoService.Setup(service => + service.Update(request)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentTypeArchiveDeleteInfoController.Put(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentTypeArchiveDeleteInfoService.Verify(); + } + + [Test] + public async Task Delete_OK() + { + var documentTypeName = "OneThousandNinetyNineInt"; + _mockDocumentTypeArchiveDeleteInfoService.Setup(service => service.Delete(documentTypeName)).Verifiable(); + + var result = await _documentTypeArchiveDeleteInfoController.Delete(documentTypeName); + Assert.NotNull(result); + + var okResult = result as OkResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockDocumentTypeArchiveDeleteInfoService.Verify(); + } + + [Test] + public async Task Delete_ServiceException_InternalServerError() + { + var documentTypeName = "OneThousandNinetyNineInt"; + _mockDocumentTypeArchiveDeleteInfoService.Setup(service => + service.Delete(documentTypeName)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentTypeArchiveDeleteInfoController.Delete(documentTypeName); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentTypeArchiveDeleteInfoService.Verify(); + } + + [Test] + public async Task Delete_UnexpectedException_InternalServerError() + { + var documentTypeName = "OneThousandNinetyNineInt"; + _mockDocumentTypeArchiveDeleteInfoService.Setup(service => + service.Delete(documentTypeName)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentTypeArchiveDeleteInfoController.Delete(documentTypeName); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockDocumentTypeArchiveDeleteInfoService.Verify(); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/IngestorRunInfoControllerTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/IngestorRunInfoControllerTest.cs new file mode 100644 index 0000000..5991fb3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/IngestorRunInfoControllerTest.cs @@ -0,0 +1,221 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Controllers; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +namespace LCU.API.Internal.DocumentIngestorTests.Controllers; + +public class IngestorRunInfoControllerTest +{ + private IngestorRunInfoController _ingestorRunInfoController; + private Mock _mockIngestorRunInfoService; + + [SetUp] + public void Setup() + { + _mockIngestorRunInfoService = new Mock(); + _ingestorRunInfoController = new IngestorRunInfoController(_mockIngestorRunInfoService.Object); + } + + [Test] + public async Task GetByIngestorRunInfoId_OK() + { + var ingestorRunInfoId = new Guid(); + var ingestorRunInfo = new IngestorRunInfo(); + _mockIngestorRunInfoService.Setup(service => service.GetByIdAsync(ingestorRunInfoId)) + .ReturnsAsync(ingestorRunInfo).Verifiable(); + + var result = await _ingestorRunInfoController.GetByIngestorRunInfoId(ingestorRunInfoId); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockIngestorRunInfoService.Verify(); + } + + [Test] + public async Task GetByIngestorRunInfoId_ServiceException_InternalServerError() + { + var ingestorRunInfoId = new Guid(); + _mockIngestorRunInfoService.Setup(service => + service.GetByIdAsync(ingestorRunInfoId)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _ingestorRunInfoController.GetByIngestorRunInfoId(ingestorRunInfoId); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockIngestorRunInfoService.Verify(); + } + + [Test] + public async Task GetByIngestorRunInfoId_UnexpectedException_InternalServerError() + { + var ingestorRunInfoId = new Guid(); + _mockIngestorRunInfoService.Setup(service => + service.GetByIdAsync(ingestorRunInfoId)) + .ThrowsAsync(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _ingestorRunInfoController.GetByIngestorRunInfoId(ingestorRunInfoId); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockIngestorRunInfoService.Verify(); + } + + [Test] + public async Task Post_OK() + { + var request = new IngestorRunInfo(); + _mockIngestorRunInfoService.Setup(service => service.SaveAsync(request)).Verifiable(); + + var result = await _ingestorRunInfoController.Post(request); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockIngestorRunInfoService.Verify(); + } + + [Test] + public async Task Post_ServiceException_InternalServerError() + { + var request = new IngestorRunInfo(); + _mockIngestorRunInfoService.Setup(service => + service.SaveAsync(request)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _ingestorRunInfoController.Post(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockIngestorRunInfoService.Verify(); + } + + [Test] + public async Task Post_UnexpectedException_InternalServerError() + { + var request = new IngestorRunInfo(); + _mockIngestorRunInfoService.Setup(service => + service.SaveAsync(request)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _ingestorRunInfoController.Post(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockIngestorRunInfoService.Verify(); + } + + [Test] + public async Task Put_OK() + { + var request = new IngestorRunInfo(); + _mockIngestorRunInfoService.Setup(service => service.Update(request)).ReturnsAsync(request).Verifiable(); + + var result = await _ingestorRunInfoController.Put(request); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockIngestorRunInfoService.Verify(); + } + + [Test] + public async Task Put_ServiceException_InternalServerError() + { + var request = new IngestorRunInfo(); + _mockIngestorRunInfoService.Setup(service => + service.Update(request)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _ingestorRunInfoController.Put(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockIngestorRunInfoService.Verify(); + } + + [Test] + public async Task Put_UnexpectedException_InternalServerError() + { + var request = new IngestorRunInfo(); + _mockIngestorRunInfoService.Setup(service => + service.Update(request)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _ingestorRunInfoController.Put(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockIngestorRunInfoService.Verify(); + } + + [Test] + public async Task Delete_OK() + { + var ingestorRunInfoId = new Guid(); + _mockIngestorRunInfoService.Setup(service => service.Delete(ingestorRunInfoId)).Verifiable(); + + var result = await _ingestorRunInfoController.Delete(ingestorRunInfoId); + Assert.NotNull(result); + + var okResult = result as OkResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockIngestorRunInfoService.Verify(); + } + + [Test] + public async Task Delete_ServiceException_InternalServerError() + { + var ingestorRunInfoId = new Guid(); + _mockIngestorRunInfoService.Setup(service => + service.Delete(ingestorRunInfoId)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _ingestorRunInfoController.Delete(ingestorRunInfoId); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockIngestorRunInfoService.Verify(); + } + + [Test] + public async Task Delete_UnexpectedException_InternalServerError() + { + var ingestorRunInfoId = new Guid(); + _mockIngestorRunInfoService.Setup(service => + service.Delete(ingestorRunInfoId)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _ingestorRunInfoController.Delete(ingestorRunInfoId); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockIngestorRunInfoService.Verify(); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/MemberDocumentNotifierControllerTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/MemberDocumentNotifierControllerTest.cs new file mode 100644 index 0000000..3b92017 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/MemberDocumentNotifierControllerTest.cs @@ -0,0 +1,79 @@ +using LCU.API.Internal.DocumentIngestor.Controllers; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using Microsoft.AspNetCore.Mvc; +using Moq; +using NUnit.Framework; +using System; +using System.Threading.Tasks; +namespace LCU.API.Internal.DocumentIngestorTests.Controllers; + +public class MemberDocumentNotifierControllerTest +{ + private MemberDocumentNotifierController _memberDocumentNotifierController; + private Mock _mockQueueMemberDocumentNotifierService; + + [SetUp] + public void Setup() + { + _mockQueueMemberDocumentNotifierService = new Mock(); + _memberDocumentNotifierController = new MemberDocumentNotifierController(_mockQueueMemberDocumentNotifierService.Object); + } + + [Test] + public async Task QueueMemberDocumentNotifierRequest_Accepted() + { + var request = new MemberDocumentNotificationRequest + { + RunCriticalFailureNotifications = true + }; + _mockQueueMemberDocumentNotifierService.Setup(service => service.QueueMemberDocumentNotifierRequest(request)).Verifiable(); + + var result = await _memberDocumentNotifierController.QueueMemberDocumentNotifier(request); + Assert.NotNull(result); + + var okResult = result as AcceptedResult; + Assert.NotNull(okResult); + Assert.AreEqual(202, okResult!.StatusCode); + _mockQueueMemberDocumentNotifierService.Verify(); + } + + [Test] + public async Task QueueMemberDocumentNotifierRequest_Failure_UnexpectedException() + { + var request = new MemberDocumentNotificationRequest + { + RunCriticalFailureNotifications = true + }; + _mockQueueMemberDocumentNotifierService.Setup(service => service.QueueMemberDocumentNotifierRequest(request)) + .Throws(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _memberDocumentNotifierController.QueueMemberDocumentNotifier(request); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockQueueMemberDocumentNotifierService.Verify(); + } + + [Test] + public async Task QueueMemberDocumentNotifierRequest_Failure_ServiceException() + { + var request = new MemberDocumentNotificationRequest + { + RunCriticalFailureNotifications = true + }; + _mockQueueMemberDocumentNotifierService.Setup(service => service.QueueMemberDocumentNotifierRequest(request)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _memberDocumentNotifierController.QueueMemberDocumentNotifier(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockQueueMemberDocumentNotifierService.Verify(); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/MemberNotificationInfoControllerTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/MemberNotificationInfoControllerTest.cs new file mode 100644 index 0000000..d8b2b0f --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/MemberNotificationInfoControllerTest.cs @@ -0,0 +1,633 @@ +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Controllers; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using Microsoft.AspNetCore.Mvc; +using Moq; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Security.Claims; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; + +namespace LCU.API.Internal.DocumentIngestorTests.Controllers; + +public class MemberNotificationInfoControllerTest +{ + private MemberNotificationInfoController _memberNotificationInfoController; + + private Mock _mockMemberNotificationInfoService; + private ApiConfiguration _apiConfiguration; + + [SetUp] + public void Setup() + { + _apiConfiguration = new ApiConfiguration() { MaxMemberNotificationAttempts = 3, TimeZone = "America/Chicago" }; + _mockMemberNotificationInfoService = new Mock(); + + _memberNotificationInfoController = new MemberNotificationInfoController + ( + _mockMemberNotificationInfoService.Object, + _apiConfiguration + ) + { + ControllerContext = + { + HttpContext = new DefaultHttpContext() + } + }; + } + + [Test] + public async Task Get_OK() + { + var memberNotificationInfos = new List() + { + new MemberNotificationInfo() + { + MemberNotificationInfoId = 1 + } + }; + _mockMemberNotificationInfoService.Setup(service => service.GetAsync()) + .ReturnsAsync(memberNotificationInfos).Verifiable(); + + var result = await _memberNotificationInfoController.Get(); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task Get_ServiceException_InternalServerError() + { + var memberNotificationInfos = new List(); + _mockMemberNotificationInfoService.Setup(service => service.GetAsync()) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _memberNotificationInfoController.Get(); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task Get_UnexpectedException_InternalServerError() + { + var memberNotificationInfos = new List(); + _mockMemberNotificationInfoService.Setup(service => service.GetAsync()) + .ThrowsAsync(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _memberNotificationInfoController.Get(); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task GetById_OK() + { + var id = 1; + var memberNotificationInfo = new MemberNotificationInfo(); + _mockMemberNotificationInfoService.Setup(service => service.GetByIdAsync(id)) + .ReturnsAsync(memberNotificationInfo).Verifiable(); + + var result = await _memberNotificationInfoController.GetById(id); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task GetById_ServiceException_InternalServerError() + { + var id = 1; + _mockMemberNotificationInfoService.Setup(service => service.GetByIdAsync(id)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _memberNotificationInfoController.GetById(id); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task GetById_UnexpectedException_InternalServerError() + { + var id = 1; + _mockMemberNotificationInfoService.Setup(service => service.GetByIdAsync(id)) + .ThrowsAsync(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _memberNotificationInfoController.GetById(id); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task GetByDocumentProcessingInfoId_OK() + { + var documentProcessingInfoId = 1; + var memberNotificationInfos = new List() + { + new MemberNotificationInfo() + { + DocumentProcessingInfoId = documentProcessingInfoId + } + }; + _mockMemberNotificationInfoService.Setup(service => service.GetByDocumentProcessingInfoIdAsync(documentProcessingInfoId)) + .ReturnsAsync(memberNotificationInfos).Verifiable(); + + var result = await _memberNotificationInfoController.GetByDocumentProcessingInfoId(documentProcessingInfoId); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task GetByDocumentProcessingInfoId_ServiceException_InternalServerError() + { + var documentProcessingInfoId = 1; + _mockMemberNotificationInfoService.Setup(service => service.GetByDocumentProcessingInfoIdAsync(documentProcessingInfoId)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _memberNotificationInfoController.GetByDocumentProcessingInfoId(documentProcessingInfoId); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task GetByDocumentProcessingInfoId_UnexpectedException_InternalServerError() + { + var documentProcessingInfoId = 1; + _mockMemberNotificationInfoService.Setup(service => service.GetByDocumentProcessingInfoIdAsync(documentProcessingInfoId)) + .ThrowsAsync(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _memberNotificationInfoController.GetByDocumentProcessingInfoId(documentProcessingInfoId); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task Post_CreatedAtAction() + { + var documentProcessingInfoId = 1; + var request = new MemberNotificationInfo() + { + DocumentProcessingInfoId = documentProcessingInfoId, + NotificationStatusType = NotificationStatusTypes.Pending + }; + + var requestReturn = new MemberNotificationInfo() + { + DocumentProcessingInfoId = documentProcessingInfoId, + NotificationStatusType = NotificationStatusTypes.Complete + }; + _mockMemberNotificationInfoService.Setup(service => service.SaveAsync(request)).ReturnsAsync(requestReturn).Verifiable(); + + var result = await _memberNotificationInfoController.Post(request); + Assert.NotNull(result); + + var okResult = result as CreatedAtActionResult; + Assert.NotNull(okResult); + Assert.AreEqual(201, okResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task Post_ServiceException_InternalServerError() + { + var request = new MemberNotificationInfo(); + _mockMemberNotificationInfoService.Setup(service => + service.SaveAsync(request)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _memberNotificationInfoController.Post(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task Post_UnexpectedException_InternalServerError() + { + var request = new MemberNotificationInfo(); + _mockMemberNotificationInfoService.Setup(service => + service.SaveAsync(request)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _memberNotificationInfoController.Post(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task Put_OK() + { + var request = new MemberNotificationInfo(); + _mockMemberNotificationInfoService.Setup(service => service.Update(request)).ReturnsAsync(request).Verifiable(); + + var result = await _memberNotificationInfoController.Put(request); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task Put_ServiceException_InternalServerError() + { + var request = new MemberNotificationInfo(); + _mockMemberNotificationInfoService.Setup(service => + service.Update(request)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _memberNotificationInfoController.Put(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task Put_UnexpectedException_InternalServerError() + { + var request = new MemberNotificationInfo(); + _mockMemberNotificationInfoService.Setup(service => + service.Update(request)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _memberNotificationInfoController.Put(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task PutRange_OK() + { + var request = new List(); + _mockMemberNotificationInfoService.Setup(service => service.UpdateRange(request)).ReturnsAsync(request).Verifiable(); + + var result = await _memberNotificationInfoController.Put(request); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task PutRange_ServiceException_InternalServerError() + { + var request = new List(); + _mockMemberNotificationInfoService.Setup(service => + service.UpdateRange(request)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _memberNotificationInfoController.Put(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task PutRange_UnexpectedException_InternalServerError() + { + var request = new List(); + _mockMemberNotificationInfoService.Setup(service => + service.UpdateRange(request)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _memberNotificationInfoController.Put(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task Delete_OK() + { + var id = 1; + _mockMemberNotificationInfoService.Setup(service => service.Delete(id)).Verifiable(); + + var result = await _memberNotificationInfoController.Delete(id); + Assert.NotNull(result); + + var okResult = result as OkResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task Delete_ServiceException_InternalServerError() + { + var id = 1; + _mockMemberNotificationInfoService.Setup(service => + service.Delete(id)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _memberNotificationInfoController.Delete(id); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task Delete_UnexpectedException_InternalServerError() + { + var id = 1; + _mockMemberNotificationInfoService.Setup(service => + service.Delete(id)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _memberNotificationInfoController.Delete(id); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task GetByNotificationStatusAsync_Ok() + { + + var status = NotificationStatusTypes.Pending; + + _mockMemberNotificationInfoService.Setup(service => service.GetByNotificationStatusAsync(status)) + .ReturnsAsync(new List() + { + new MemberNotificationInfo() {NotificationStatusType = NotificationStatusTypes.Pending}, + new MemberNotificationInfo() {NotificationStatusType = NotificationStatusTypes.Pending}, + new MemberNotificationInfo() {NotificationStatusType = NotificationStatusTypes.Pending} + }).Verifiable(); + + var result = await _memberNotificationInfoController.GetByNotificationStatus(status); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockMemberNotificationInfoService.Verify(); + } + + [Test] + public async Task GetSendableMemberNotificationInfos_Ok() + { + var uploadDate = new DateTime(2022, 10, 2); + var memberNotificationInfos = new List() + { + new MemberNotificationInfo() + { + MemberNotificationInfoId = 1, + DocumentProcessingInfoId = 2, + UploadDate = new DateTime(2022, 8, 1), + NotificationStatusType = NotificationStatusTypes.Pending, + DeliveryMethod = DeliveryMethod.Electronic, + Attempts = 1, + EmailAddress = "test@test.com" + } + }; + + _mockMemberNotificationInfoService.Setup(service => service.GetSendableMemberNotificationInfosAsync(uploadDate, + _apiConfiguration.MaxMemberNotificationAttempts)) + .ReturnsAsync(memberNotificationInfos).Verifiable(); + + var result = await _memberNotificationInfoController.GetSendableMemberNotificationInfos(uploadDate); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + } + + [Test] + public async Task SetDocumentNotificationStatus_SetDocumentNotificationStatusSuccessfully_Returns200() + { + var documentProcessingInfoId = DateTime.Now.Millisecond; + var notificationStatus = NotificationStatusTypes.CriticalFailure; + var userName = Guid.NewGuid().ToString(); + var reason = Guid.NewGuid().ToString(); + _mockMemberNotificationInfoService + .Setup(s => s.SetDocumentNotificationStatus(documentProcessingInfoId, notificationStatus, userName, reason)) + .ReturnsAsync(true); + _memberNotificationInfoController.HttpContext.User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim("name", userName) })); + + var response = await _memberNotificationInfoController.SetDocumentNotificationStatus(documentProcessingInfoId, notificationStatus, reason); + + Assert.IsInstanceOf(response); + Assert.AreEqual(StatusCodes.Status200OK, ((OkResult)response).StatusCode); + } + + [Test] + public async Task SetDocumentNotificationStatus_SetDocumentNotificationStatusFailed_Returns400() + { + var documentProcessingInfoId = DateTime.Now.Millisecond; + var notificationStatus = NotificationStatusTypes.Complete; + var userName = Guid.NewGuid().ToString(); + var reason = Guid.NewGuid().ToString(); + _mockMemberNotificationInfoService + .Setup(s => s.SetDocumentNotificationStatus(documentProcessingInfoId, notificationStatus, userName, reason)) + .ReturnsAsync(false); + _memberNotificationInfoController.HttpContext.User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim("name", userName) })); + + var response = await _memberNotificationInfoController.SetDocumentNotificationStatus(documentProcessingInfoId, notificationStatus, reason); + + Assert.IsInstanceOf(response); + Assert.AreEqual(StatusCodes.Status400BadRequest, ((BadRequestResult)response).StatusCode); + } + + [Test] + public async Task SetDocumentNotificationStatus_SetDocumentNotificationStatusThrowsServiceException_Returns500() + { + var documentProcessingInfoId = DateTime.Now.Millisecond; + var notificationStatus = NotificationStatusTypes.Failure; + var message = Guid.NewGuid().ToString(); + var userName = Guid.NewGuid().ToString(); + var reason = Guid.NewGuid().ToString(); + _mockMemberNotificationInfoService + .Setup(s => s.SetDocumentNotificationStatus(documentProcessingInfoId, notificationStatus, userName, reason)) + .ThrowsAsync(new ServiceException(message)); + _memberNotificationInfoController.HttpContext.User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim("name", userName) })); + + var response = await _memberNotificationInfoController.SetDocumentNotificationStatus(documentProcessingInfoId, notificationStatus, reason); + + Assert.IsInstanceOf(response); + Assert.AreEqual(StatusCodes.Status500InternalServerError, ((ObjectResult)response).StatusCode); + Assert.AreEqual(message, ((ObjectResult)response).Value); + } + + [Test] + public async Task SetDocumentNotificationStatus_SetDocumentNotificationStatusThrowsException_Returns500() + { + var documentProcessingInfoId = DateTime.Now.Millisecond; + var notificationStatus = NotificationStatusTypes.Pending; + var userName = Guid.NewGuid().ToString(); + var reason = Guid.NewGuid().ToString(); + _mockMemberNotificationInfoService + .Setup(s => s.SetDocumentNotificationStatus(documentProcessingInfoId, notificationStatus, userName, reason)) + .ThrowsAsync(new Exception()); + + var response = await _memberNotificationInfoController.SetDocumentNotificationStatus(documentProcessingInfoId, notificationStatus, reason); + + Assert.IsInstanceOf(response); + Assert.AreEqual(StatusCodes.Status500InternalServerError, ((StatusCodeResult)response).StatusCode); + } + + [Test] + public async Task BulkSetDocumentNotificationStatus_Success() + { + var request = new BulkNotificationStatusRequest() + { + Filter = new() + { + IngestorRunInfoId = Guid.NewGuid() + }, + NotificationStatus = NotificationStatusTypes.Complete, + ReasonMessage = Guid.NewGuid().ToString() + }; + var userName = Guid.NewGuid().ToString(); + + _mockMemberNotificationInfoService + .Setup(s => s.BulkSetDocumentNotificationStatus(request, userName)) + .ReturnsAsync(true); + _memberNotificationInfoController.HttpContext.User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim("name", userName) })); + + var response = await _memberNotificationInfoController.BulkSetDocumentNotificationStatus(request); + + Assert.IsInstanceOf(response); + Assert.AreEqual(StatusCodes.Status200OK, ((OkResult)response).StatusCode); + } + + [Test] + public async Task BulkSetDocumentNotificationStatus_BadRequest_Returns400() + { + var request = new BulkNotificationStatusRequest() + { + Filter = new() + { + IngestorRunInfoId = Guid.NewGuid() + }, + NotificationStatus = NotificationStatusTypes.Complete, + ReasonMessage = Guid.NewGuid().ToString() + }; + var userName = Guid.NewGuid().ToString(); + _mockMemberNotificationInfoService + .Setup(s => s.BulkSetDocumentNotificationStatus(request, userName)) + .ReturnsAsync(false); + _memberNotificationInfoController.HttpContext.User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim("name", userName) })); + + var response = await _memberNotificationInfoController.BulkSetDocumentNotificationStatus(request); + + Assert.IsInstanceOf(response); + Assert.AreEqual(StatusCodes.Status400BadRequest, ((BadRequestResult)response).StatusCode); + } + + [Test] + public async Task BulkSetDocumentNotificationStatus_ServiceException_Returns500() + { + var request = new BulkNotificationStatusRequest() + { + Filter = new() + { + IngestorRunInfoId = Guid.NewGuid() + }, + NotificationStatus = NotificationStatusTypes.Complete, + ReasonMessage = Guid.NewGuid().ToString() + }; + var userName = Guid.NewGuid().ToString(); + var message = Guid.NewGuid().ToString(); + _mockMemberNotificationInfoService + .Setup(s => s.BulkSetDocumentNotificationStatus(request, userName)) + .ThrowsAsync(new ServiceException(message)); + _memberNotificationInfoController.HttpContext.User = new ClaimsPrincipal(new ClaimsIdentity(new[] { new Claim("name", userName) })); + + var response = await _memberNotificationInfoController.BulkSetDocumentNotificationStatus(request); + + Assert.IsInstanceOf(response); + Assert.AreEqual(StatusCodes.Status500InternalServerError, ((ObjectResult)response).StatusCode); + Assert.AreEqual(message, ((ObjectResult)response).Value); + } + + [Test] + public async Task BulkSetDocumentNotificationStatus_Exception_Returns500() + { + var request = new BulkNotificationStatusRequest() + { + Filter = new() + { + IngestorRunInfoId = Guid.NewGuid() + }, + NotificationStatus = NotificationStatusTypes.Complete, + ReasonMessage = Guid.NewGuid().ToString() + }; + var userName = Guid.NewGuid().ToString(); + _mockMemberNotificationInfoService + .Setup(s => s.BulkSetDocumentNotificationStatus(request, userName)) + .ThrowsAsync(new Exception()); + + var response = await _memberNotificationInfoController.BulkSetDocumentNotificationStatus(request); + + Assert.IsInstanceOf(response); + Assert.AreEqual(StatusCodes.Status500InternalServerError, ((StatusCodeResult)response).StatusCode); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/OsgPreprocessorControllerTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/OsgPreprocessorControllerTest.cs new file mode 100644 index 0000000..2ca1d6f --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/OsgPreprocessorControllerTest.cs @@ -0,0 +1,91 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.API.Internal.DocumentIngestor.Controllers; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using System.Collections.Generic; + +namespace LCU.API.Internal.DocumentIngestorTests.Controllers; + +public class OsgPreprocessorControllerTest +{ + private OsgPreprocessorController _osgPreprocessorController; + private Mock _mockOsgPreprocessorService; + + [SetUp] + public void Setup() + { + _mockOsgPreprocessorService = new Mock(); + _osgPreprocessorController = new OsgPreprocessorController(_mockOsgPreprocessorService.Object); + } + + [Test] + public async Task PreprocessOsgIndexFile_Accepted() + { + var request = new OsgPreprocessorRequest + { + SourceBasePath = "\\\\Tester\\Source", + WorkingBasePath = "\\\\Tester\\Working", + OutputBasePath = "\\\\Tester\\Output", + IncompleteOutputBasePath = "\\\\Tester\\Incomplete" + }; + + _mockOsgPreprocessorService.Setup(service => service.HandleOsgPreprocessing(request)).Verifiable(); + + var result = await _osgPreprocessorController.PreprocessOsgIndexFile(request); + Assert.NotNull(result); + + var okResult = result as AcceptedResult; + Assert.NotNull(okResult); + Assert.AreEqual(202, okResult!.StatusCode); + _mockOsgPreprocessorService.Verify(); + } + + [Test] + public async Task PreprocessOsgIndexFile_Failure_UnexpectedException() + { + var request = new OsgPreprocessorRequest + { + SourceBasePath = "\\\\Tester\\Source", + WorkingBasePath = "\\\\Tester\\Working", + OutputBasePath = "\\\\Tester\\Output", + IncompleteOutputBasePath = "\\\\Tester\\Incomplete" + }; + _mockOsgPreprocessorService.Setup(service => service.HandleOsgPreprocessing(request)) + .Throws(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _osgPreprocessorController.PreprocessOsgIndexFile(request); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockOsgPreprocessorService.Verify(); + } + + [Test] + public async Task PreprocessOsgIndexFile_Failure_ServiceException() + { + var request = new OsgPreprocessorRequest + { + SourceBasePath = "\\\\Tester\\Source", + WorkingBasePath = "\\\\Tester\\Working", + OutputBasePath = "\\\\Tester\\Output", + IncompleteOutputBasePath = "\\\\Tester\\Incomplete" + }; + _mockOsgPreprocessorService.Setup(service => service.HandleOsgPreprocessing(request)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _osgPreprocessorController.PreprocessOsgIndexFile(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockOsgPreprocessorService.Verify(); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/PdfPartitionerControllerTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/PdfPartitionerControllerTest.cs new file mode 100644 index 0000000..8206a54 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/PdfPartitionerControllerTest.cs @@ -0,0 +1,96 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Moq; +using NUnit.Framework; +using LCU.API.Internal.DocumentIngestor.Controllers; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.FileOperationsModels.Models.NameSettings; +namespace LCU.API.Internal.DocumentIngestorTests.Controllers; + +public class PdfPartitionerControllerTest +{ + private PdfPartitionerController _pdfPartitionerController; + private Mock _mockQueuePdfPartitionerService; + + [SetUp] + public void Setup() + { + _mockQueuePdfPartitionerService = new Mock(); + _pdfPartitionerController = new PdfPartitionerController(_mockQueuePdfPartitionerService.Object); + } + + [Test] + public async Task QueueIngestorPdfPartitioner_Accepted() + { + var request = new PdfPartitionerRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + PdfParserType = PdfParserTypes.FosLoanStatement, + DynamicIndexFileName = "TestDynamicIndexFileName.txt", + DynamicPdfName = "TestDynamicPdfname", + DynamicPdfSettings = new DynamicNameSetting() + }; + _mockQueuePdfPartitionerService.Setup(service => service.QueuePdfPartitionerRequest(request)).Verifiable(); + + var result = await _pdfPartitionerController.QueueIngestorPdfPartitioner(request); + Assert.NotNull(result); + + var okResult = result as AcceptedResult; + Assert.NotNull(okResult); + Assert.AreEqual(202, okResult!.StatusCode); + _mockQueuePdfPartitionerService.Verify(); + } + + [Test] + public async Task QueueIngestorPdfPartitioner_Failure_UnexpectedException() + { + var request = new PdfPartitionerRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + PdfParserType = PdfParserTypes.FosLoanStatement, + DynamicIndexFileName = "TestDynamicIndexFileName.txt", + DynamicPdfName = "TestDynamicPdfname", + DynamicPdfSettings = new DynamicNameSetting() + }; + _mockQueuePdfPartitionerService.Setup(service => service.QueuePdfPartitionerRequest(request)) + .Throws(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _pdfPartitionerController.QueueIngestorPdfPartitioner(request); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockQueuePdfPartitionerService.Verify(); + } + + [Test] + public async Task QueueIngestorPdfPartitioner_Failure_ServiceException() + { + var request = new PdfPartitionerRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + PdfParserType = PdfParserTypes.FosLoanStatement, + DynamicIndexFileName = "TestDynamicIndexFileName.txt", + DynamicPdfName = "TestDynamicPdfname", + DynamicPdfSettings = new DynamicNameSetting() + }; + _mockQueuePdfPartitionerService.Setup(service => service.QueuePdfPartitionerRequest(request)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _pdfPartitionerController.QueueIngestorPdfPartitioner(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockQueuePdfPartitionerService.Verify(); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/PdfPartitionerLogControllerTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/PdfPartitionerLogControllerTest.cs new file mode 100644 index 0000000..69ca69f --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/PdfPartitionerLogControllerTest.cs @@ -0,0 +1,306 @@ +using System; +using System.Threading.Tasks; +using System.Collections.Generic; +using Microsoft.AspNetCore.Mvc; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Controllers; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +namespace LCU.API.Internal.DocumentIngestorTests.Controllers; + +public class PdfPartitionerLogControllerTest +{ + private PdfPartitionerLogController _processingLogController; + private Mock _mockPdfPartitionerLogService; + + [SetUp] + public void Setup() + { + _mockPdfPartitionerLogService = new Mock(); + _processingLogController = new PdfPartitionerLogController(_mockPdfPartitionerLogService.Object); + } + + [Test] + public async Task Get_OK() + { + var pdfPartitionerLogId = 1; + var pdfPartitionerRunInfoId = Guid.NewGuid(); + var PdfPartitionerLogs = new List + { + new PdfPartitionerLog + { + PdfPartitionerLogId = pdfPartitionerLogId, + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId + } + }; + _mockPdfPartitionerLogService.Setup(service => service.GetAsync()) + .ReturnsAsync(PdfPartitionerLogs).Verifiable(); + + var result = await _processingLogController.Get(); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockPdfPartitionerLogService.Verify(); + } + + [Test] + public async Task Get_ServiceException_InternalServerError() + { + _mockPdfPartitionerLogService.Setup(service => service.GetAsync()) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.Get(); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockPdfPartitionerLogService.Verify(); + } + + [Test] + public async Task Get_UnexpectedException_InternalServerError() + { + _mockPdfPartitionerLogService.Setup(service => service.GetAsync()) + .ThrowsAsync(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.Get(); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockPdfPartitionerLogService.Verify(); + } + + [Test] + public async Task GetById_OK() + { + var id = 1; + var pdfPartitionerLog = new PdfPartitionerLog + { + PdfPartitionerLogId = id, + PdfPartitionerRunInfoId = Guid.NewGuid() + }; + _mockPdfPartitionerLogService.Setup(service => service.GetByIdAsync(id)) + .ReturnsAsync(pdfPartitionerLog).Verifiable(); + + var result = await _processingLogController.GetById(id); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockPdfPartitionerLogService.Verify(); + } + + [Test] + public async Task GetById_ServiceException_InternalServerError() + { + var id = 1; + _mockPdfPartitionerLogService.Setup(service => service.GetByIdAsync(id)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.GetById(id); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockPdfPartitionerLogService.Verify(); + } + + [Test] + public async Task GetById_UnexpectedException_InternalServerError() + { + var id = 1; + _mockPdfPartitionerLogService.Setup(service => service.GetByIdAsync(id)) + .ThrowsAsync(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.GetById(id); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockPdfPartitionerLogService.Verify(); + } + + [Test] + public async Task GetByPdfPartitionerRunInfoIdAsync_OK() + { + var pdfPartitionerLogId = 1; + var pdfPartitionerRunInfoId = Guid.NewGuid(); + var pdfPartitionerLogs = new List + { + new PdfPartitionerLog + { + PdfPartitionerLogId = pdfPartitionerLogId, + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId + } + }; + _mockPdfPartitionerLogService.Setup(service => service.GetByPdfPartitionerRunInfoIdAsync(pdfPartitionerRunInfoId)) + .ReturnsAsync(pdfPartitionerLogs).Verifiable(); + + var result = await _processingLogController.GetByPdfPartitionerRunInfoId(pdfPartitionerRunInfoId); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockPdfPartitionerLogService.Verify(); + } + + [Test] + public async Task GetByPdfPartitionerRunInfoId_ServiceException_InternalServerError() + { + var pdfPartitionerRunInfoId = Guid.NewGuid(); + _mockPdfPartitionerLogService.Setup(service => service.GetByPdfPartitionerRunInfoIdAsync(pdfPartitionerRunInfoId)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.GetByPdfPartitionerRunInfoId(pdfPartitionerRunInfoId); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockPdfPartitionerLogService.Verify(); + } + + [Test] + public async Task GetByPdfPartitionerRunInfoId_UnexpectedException_InternalServerError() + { + var pdfPartitionerRunInfoId = Guid.NewGuid(); + _mockPdfPartitionerLogService.Setup(service => service.GetByPdfPartitionerRunInfoIdAsync(pdfPartitionerRunInfoId)) + .ThrowsAsync(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.GetByPdfPartitionerRunInfoId(pdfPartitionerRunInfoId); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockPdfPartitionerLogService.Verify(); + } + + [Test] + public async Task Post_CreatedAtAction() + { + var pdfPartitionerLogId = 1; + var pdfPartitionerRunInfoId = Guid.NewGuid(); + var request = new PdfPartitionerLog + { + PdfPartitionerLogId = 0, + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId + }; + + var requestReturn = new PdfPartitionerLog + { + PdfPartitionerLogId = pdfPartitionerLogId, + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId + }; + + _mockPdfPartitionerLogService.Setup(service => service.SaveAsync(request)).ReturnsAsync(requestReturn).Verifiable(); + + var result = await _processingLogController.Post(request); + Assert.NotNull(result); + + var createdAtActionResult = result as CreatedAtActionResult; + Assert.NotNull(createdAtActionResult); + Assert.AreEqual(201, createdAtActionResult!.StatusCode); + _mockPdfPartitionerLogService.Verify(); + } + + [Test] + public async Task Post_ServiceException_InternalServerError() + { + var request = new PdfPartitionerLog(); + _mockPdfPartitionerLogService.Setup(service => + service.SaveAsync(request)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.Post(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockPdfPartitionerLogService.Verify(); + } + + [Test] + public async Task Post_UnexpectedException_InternalServerError() + { + var pdfPartitionerLogId = 1; + var pdfPartitionerRunInfoId = Guid.NewGuid(); + var pdfPartitionerLog = new PdfPartitionerLog + { + PdfPartitionerLogId = pdfPartitionerLogId, + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId + }; + _mockPdfPartitionerLogService.Setup(service => + service.SaveAsync(pdfPartitionerLog)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.Post(pdfPartitionerLog); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockPdfPartitionerLogService.Verify(); + } + + [Test] + public async Task Delete_OK() + { + var id = 1; + _mockPdfPartitionerLogService.Setup(service => service.Delete(id)).Verifiable(); + + var result = await _processingLogController.Delete(id); + Assert.NotNull(result); + + var okResult = result as OkResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockPdfPartitionerLogService.Verify(); + } + + [Test] + public async Task Delete_ServiceException_InternalServerError() + { + var id = 1; + _mockPdfPartitionerLogService.Setup(service => + service.Delete(id)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.Delete(id); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockPdfPartitionerLogService.Verify(); + } + + [Test] + public async Task Delete_UnexpectedException_InternalServerError() + { + var id = 1; + _mockPdfPartitionerLogService.Setup(service => + service.Delete(id)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.Delete(id); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockPdfPartitionerLogService.Verify(); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/PdfPartitionerRunInfoControllerTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/PdfPartitionerRunInfoControllerTest.cs new file mode 100644 index 0000000..e9f03d4 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/PdfPartitionerRunInfoControllerTest.cs @@ -0,0 +1,221 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Controllers; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +namespace LCU.API.Internal.DocumentIngestorTests.Controllers; + +public class PdfPartitionerRunInfoControllerTest +{ + private PdfPartitionerRunInfoController _pdfPartitionerRunInfoController; + private Mock _mockPdfPartitionerRunInfoService; + + [SetUp] + public void Setup() + { + _mockPdfPartitionerRunInfoService = new Mock(); + _pdfPartitionerRunInfoController = new PdfPartitionerRunInfoController(_mockPdfPartitionerRunInfoService.Object); + } + + [Test] + public async Task GetByPdfPartitionerRunInfoId_OK() + { + var pdfPartitionerRunInfoId = new Guid(); + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo(); + _mockPdfPartitionerRunInfoService.Setup(service => service.GetByIdAsync(pdfPartitionerRunInfoId)) + .ReturnsAsync(pdfPartitionerRunInfo).Verifiable(); + + var result = await _pdfPartitionerRunInfoController.GetByPdfPartitionerRunInfoId(pdfPartitionerRunInfoId); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockPdfPartitionerRunInfoService.Verify(); + } + + [Test] + public async Task GetByPdfPartitionerRunInfoId_ServiceException_InternalServerError() + { + var pdfPartitionerRunInfoId = new Guid(); + _mockPdfPartitionerRunInfoService.Setup(service => + service.GetByIdAsync(pdfPartitionerRunInfoId)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _pdfPartitionerRunInfoController.GetByPdfPartitionerRunInfoId(pdfPartitionerRunInfoId); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockPdfPartitionerRunInfoService.Verify(); + } + + [Test] + public async Task GetByPdfPartitionerRunInfoId_UnexpectedException_InternalServerError() + { + var pdfPartitionerRunInfoId = new Guid(); + _mockPdfPartitionerRunInfoService.Setup(service => + service.GetByIdAsync(pdfPartitionerRunInfoId)) + .ThrowsAsync(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _pdfPartitionerRunInfoController.GetByPdfPartitionerRunInfoId(pdfPartitionerRunInfoId); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockPdfPartitionerRunInfoService.Verify(); + } + + [Test] + public async Task Post_OK() + { + var request = new PdfPartitionerRunInfo(); + _mockPdfPartitionerRunInfoService.Setup(service => service.SaveAsync(request)).Verifiable(); + + var result = await _pdfPartitionerRunInfoController.Post(request); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockPdfPartitionerRunInfoService.Verify(); + } + + [Test] + public async Task Post_ServiceException_InternalServerError() + { + var request = new PdfPartitionerRunInfo(); + _mockPdfPartitionerRunInfoService.Setup(service => + service.SaveAsync(request)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _pdfPartitionerRunInfoController.Post(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockPdfPartitionerRunInfoService.Verify(); + } + + [Test] + public async Task Post_UnexpectedException_InternalServerError() + { + var request = new PdfPartitionerRunInfo(); + _mockPdfPartitionerRunInfoService.Setup(service => + service.SaveAsync(request)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _pdfPartitionerRunInfoController.Post(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockPdfPartitionerRunInfoService.Verify(); + } + + [Test] + public async Task Put_OK() + { + var request = new PdfPartitionerRunInfo(); + _mockPdfPartitionerRunInfoService.Setup(service => service.Update(request)).ReturnsAsync(request).Verifiable(); + + var result = await _pdfPartitionerRunInfoController.Put(request); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockPdfPartitionerRunInfoService.Verify(); + } + + [Test] + public async Task Put_ServiceException_InternalServerError() + { + var request = new PdfPartitionerRunInfo(); + _mockPdfPartitionerRunInfoService.Setup(service => + service.Update(request)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _pdfPartitionerRunInfoController.Put(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockPdfPartitionerRunInfoService.Verify(); + } + + [Test] + public async Task Put_UnexpectedException_InternalServerError() + { + var request = new PdfPartitionerRunInfo(); + _mockPdfPartitionerRunInfoService.Setup(service => + service.Update(request)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _pdfPartitionerRunInfoController.Put(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockPdfPartitionerRunInfoService.Verify(); + } + + [Test] + public async Task Delete_OK() + { + var pdfPartitionerRunInfoId = new Guid(); + _mockPdfPartitionerRunInfoService.Setup(service => service.Delete(pdfPartitionerRunInfoId)).Verifiable(); + + var result = await _pdfPartitionerRunInfoController.Delete(pdfPartitionerRunInfoId); + Assert.NotNull(result); + + var okResult = result as OkResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockPdfPartitionerRunInfoService.Verify(); + } + + [Test] + public async Task Delete_ServiceException_InternalServerError() + { + var pdfPartitionerRunInfoId = new Guid(); + _mockPdfPartitionerRunInfoService.Setup(service => + service.Delete(pdfPartitionerRunInfoId)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _pdfPartitionerRunInfoController.Delete(pdfPartitionerRunInfoId); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockPdfPartitionerRunInfoService.Verify(); + } + + [Test] + public async Task Delete_UnexpectedException_InternalServerError() + { + var pdfPartitionerRunInfoId = new Guid(); + _mockPdfPartitionerRunInfoService.Setup(service => + service.Delete(pdfPartitionerRunInfoId)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _pdfPartitionerRunInfoController.Delete(pdfPartitionerRunInfoId); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockPdfPartitionerRunInfoService.Verify(); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/ProcessingLogControllerTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/ProcessingLogControllerTest.cs new file mode 100644 index 0000000..68c3265 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/ProcessingLogControllerTest.cs @@ -0,0 +1,361 @@ +using System; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Mvc; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Controllers; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using System.Collections.Generic; + +namespace LCU.API.Internal.DocumentIngestorTests.Controllers; + +public class ProcessingLogControllerTest +{ + private ProcessingLogController _processingLogController; + private Mock _mockProcessingLogService; + + [SetUp] + public void Setup() + { + _mockProcessingLogService = new Mock(); + _processingLogController = new ProcessingLogController(_mockProcessingLogService.Object); + } + + [Test] + public async Task Get_OK() + { + var processingLogs = new List() + { + new ProcessingLog() + { + ProcessingLogId = 1, + DocumentProcessingInfoId = 1 + } + }; + _mockProcessingLogService.Setup(service => service.GetAsync()) + .ReturnsAsync(processingLogs).Verifiable(); + + var result = await _processingLogController.Get(); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockProcessingLogService.Verify(); + } + + [Test] + public async Task Get_ServiceException_InternalServerError() + { + _mockProcessingLogService.Setup(service => service.GetAsync()) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.Get(); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockProcessingLogService.Verify(); + } + + [Test] + public async Task Get_UnexpectedException_InternalServerError() + { + _mockProcessingLogService.Setup(service => service.GetAsync()) + .ThrowsAsync(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.Get(); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockProcessingLogService.Verify(); + } + + [Test] + public async Task GetById_OK() + { + var id = 1; + var processingLog = new ProcessingLog() + { + ProcessingLogId = 1, + DocumentProcessingInfoId = 1 + }; + _mockProcessingLogService.Setup(service => service.GetByIdAsync(id)) + .ReturnsAsync(processingLog).Verifiable(); + + var result = await _processingLogController.GetById(id); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockProcessingLogService.Verify(); + } + + [Test] + public async Task GetById_ServiceException_InternalServerError() + { + var id = 1; + _mockProcessingLogService.Setup(service => service.GetByIdAsync(id)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.GetById(id); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockProcessingLogService.Verify(); + } + + [Test] + public async Task GetById_UnexpectedException_InternalServerError() + { + var id = 1; + _mockProcessingLogService.Setup(service => service.GetByIdAsync(id)) + .ThrowsAsync(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.GetById(id); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockProcessingLogService.Verify(); + } + + [Test] + public async Task GetByDocumentProcessingInfoId_OK() + { + var documentProcessingInfoId = 1; + var processingLogs = new List() + { + new ProcessingLog() + { + ProcessingLogId = 1, + DocumentProcessingInfoId = 1 + } + }; + _mockProcessingLogService.Setup(service => service.GetByDocumentProcessingInfoIdAsync(documentProcessingInfoId)) + .ReturnsAsync(processingLogs).Verifiable(); + + var result = await _processingLogController.GetByDocumentProcessingInfoId(documentProcessingInfoId); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockProcessingLogService.Verify(); + } + + [Test] + public async Task GetByDocumentProcessingInfoId_ServiceException_InternalServerError() + { + var documentProcessingInfoId = 1; + _mockProcessingLogService.Setup(service => service.GetByDocumentProcessingInfoIdAsync(documentProcessingInfoId)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.GetByDocumentProcessingInfoId(documentProcessingInfoId); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockProcessingLogService.Verify(); + } + + [Test] + public async Task GetByDocumentProcessingInfoId_UnexpectedException_InternalServerError() + { + var documentProcessingInfoId = 1; + _mockProcessingLogService.Setup(service => service.GetByDocumentProcessingInfoIdAsync(documentProcessingInfoId)) + .ThrowsAsync(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.GetByDocumentProcessingInfoId(documentProcessingInfoId); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockProcessingLogService.Verify(); + } + + [Test] + public async Task Post_CreatedAtAction() + { + var request = new ProcessingLog() + { + DocumentProcessingInfoId = 1, + LogTimeStamp = Convert.ToDateTime("1/1/2022"), + LogMessage = "Test" + }; + + var requestReturn = new ProcessingLog() + { + DocumentProcessingInfoId = 1, + ProcessingLogId = 1, + LogTimeStamp = Convert.ToDateTime("1/1/2022"), + LogMessage = "Test", + UserName = "User" + }; + + _mockProcessingLogService.Setup(service => service.SaveAsync(request)).ReturnsAsync(requestReturn).Verifiable(); + + var result = await _processingLogController.Post(request); + Assert.NotNull(result); + + var createdAtActionResult = result as CreatedAtActionResult; + Assert.NotNull(createdAtActionResult); + Assert.AreEqual(201, createdAtActionResult!.StatusCode); + _mockProcessingLogService.Verify(); + } + + [Test] + public async Task Post_ServiceException_InternalServerError() + { + var request = new ProcessingLog(); + _mockProcessingLogService.Setup(service => + service.SaveAsync(request)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.Post(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockProcessingLogService.Verify(); + } + + [Test] + public async Task Post_UnexpectedException_InternalServerError() + { + var processingLog = new ProcessingLog() + { + ProcessingLogId = 1, + DocumentProcessingInfoId = 1 + }; + _mockProcessingLogService.Setup(service => + service.SaveAsync(processingLog)) + .ThrowsAsync(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.Post(processingLog); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockProcessingLogService.Verify(); + } + + [Test] + public async Task Put_OK() + { + var processingLog = new ProcessingLog() + { + ProcessingLogId = 1, + DocumentProcessingInfoId = 1 + }; + _mockProcessingLogService.Setup(service => service.Update(processingLog)).ReturnsAsync(processingLog).Verifiable(); + + var result = await _processingLogController.Put(processingLog); + Assert.NotNull(result); + + var okResult = result as OkObjectResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockProcessingLogService.Verify(); + } + + [Test] + public async Task Put_ServiceException_InternalServerError() + { + var processingLog = new ProcessingLog() + { + ProcessingLogId = 1, + DocumentProcessingInfoId = 1 + }; + _mockProcessingLogService.Setup(service => + service.Update(processingLog)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.Put(processingLog); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockProcessingLogService.Verify(); + } + + [Test] + public async Task Put_UnexpectedException_InternalServerError() + { + var request = new ProcessingLog(); + _mockProcessingLogService.Setup(service => + service.Update(request)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.Put(request); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockProcessingLogService.Verify(); + } + + [Test] + public async Task Delete_OK() + { + var id = 1; + _mockProcessingLogService.Setup(service => service.Delete(id)).Verifiable(); + + var result = await _processingLogController.Delete(id); + Assert.NotNull(result); + + var okResult = result as OkResult; + Assert.NotNull(okResult); + Assert.AreEqual(200, okResult!.StatusCode); + _mockProcessingLogService.Verify(); + } + + [Test] + public async Task Delete_ServiceException_InternalServerError() + { + var id = 1; + _mockProcessingLogService.Setup(service => + service.Delete(id)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.Delete(id); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockProcessingLogService.Verify(); + } + + [Test] + public async Task Delete_UnexpectedException_InternalServerError() + { + var id = 1; + _mockProcessingLogService.Setup(service => + service.Delete(id)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _processingLogController.Delete(id); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockProcessingLogService.Verify(); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/UploadCompletionReprocessingControllerTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/UploadCompletionReprocessingControllerTest.cs new file mode 100644 index 0000000..c64aa70 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Controllers/UploadCompletionReprocessingControllerTest.cs @@ -0,0 +1,169 @@ +using LCU.API.Internal.DocumentIngestor.Controllers; +using LCU.Library.Internal.Exceptions; +using Microsoft.AspNetCore.Mvc; +using Moq; +using NUnit.Framework; +using System; +using System.Threading.Tasks; +using LCU.API.Internal.DocumentIngestor.Services; + +namespace LCU.API.Internal.DocumentIngestorTests.Controllers; + +public class UploadCompletionReprocessingControllerTest +{ + private UploadCompletionReprocessingController _documentReprocessingController; + private Mock _mockUploadCompletionReprocessingService; + + [SetUp] + public void Setup() + { + _mockUploadCompletionReprocessingService = new Mock(); + _documentReprocessingController = new UploadCompletionReprocessingController(_mockUploadCompletionReprocessingService.Object); + } + + [Test] + public async Task QueueReprocessUploadCompletionByDocumentProcessingInfoId_OK() + { + var id = 1; + var userName = "Test Tester"; + _mockUploadCompletionReprocessingService.Setup(service => service.QueueReprocessUploadCompletionByDocumentProcessingInfoId(id, userName)).Verifiable(); + + var result = await _documentReprocessingController.QueueReprocessUploadCompletionByDocumentProcessingInfoId(id, userName); + Assert.NotNull(result); + + var okResult = result as AcceptedResult; + Assert.NotNull(okResult); + Assert.AreEqual(202, okResult!.StatusCode); + _mockUploadCompletionReprocessingService.Verify(); + } + + [Test] + public async Task QueueReprocessUploadCompletionByDocumentProcessingInfoId_Failure_UnexpectedException() + { + var id = 1; + var userName = "Test Tester"; + _mockUploadCompletionReprocessingService.Setup(service => + service.QueueReprocessUploadCompletionByDocumentProcessingInfoId(id, userName)) + .Throws(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _documentReprocessingController.QueueReprocessUploadCompletionByDocumentProcessingInfoId(id, userName); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockUploadCompletionReprocessingService.Verify(); + } + + [Test] + public async Task QueueReprocessUploadCompletionByDocumentProcessingInfoId_Failure_ServiceException() + { + var id = 1; + var userName = "Test Tester"; + _mockUploadCompletionReprocessingService.Setup(service => + service.QueueReprocessUploadCompletionByDocumentProcessingInfoId(id, userName)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentReprocessingController.QueueReprocessUploadCompletionByDocumentProcessingInfoId(id, userName); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockUploadCompletionReprocessingService.Verify(); + } + + [Test] + public async Task QueueReprocessUploadCompletionByDocumentProcessingInfoId_Failure_NullException() + { + var id = 1; + var userName = "Test Tester"; + _mockUploadCompletionReprocessingService.Setup(service => + service.QueueReprocessUploadCompletionByDocumentProcessingInfoId(id, userName)) + .Throws(new ArgumentNullException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentReprocessingController.QueueReprocessUploadCompletionByDocumentProcessingInfoId(id, userName); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(404, statusResult!.StatusCode); + _mockUploadCompletionReprocessingService.Verify(); + } + + [Test] + public async Task QueueReprocessUploadCompletionByDocumentProcessingInfoId_Failure_BadRequest() + { + var id = DateTime.Now.Millisecond; + var userName = string.Empty; + var result = await _documentReprocessingController.QueueReprocessUploadCompletionByDocumentProcessingInfoId(id, userName); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(400, statusResult!.StatusCode); + _mockUploadCompletionReprocessingService.Verify(); + } + + [Test] + public async Task QueueReprocessAllNotificationDataFailures_OK() + { + var userName = "ttester"; + _mockUploadCompletionReprocessingService.Setup(service => service.QueueReprocessAllNotificationDataFailures(userName)).Verifiable(); + + var result = await _documentReprocessingController.QueueReprocessAllNotificationDataFailures(userName); + Assert.NotNull(result); + + var okResult = result as AcceptedResult; + Assert.NotNull(okResult); + Assert.AreEqual(202, okResult!.StatusCode); + _mockUploadCompletionReprocessingService.Verify(); + } + + [Test] + public async Task QueueReprocessAllNotificationDataFailures_Failure_UnexpectedException() + { + var userName = "ttester"; + _mockUploadCompletionReprocessingService.Setup(service => + service.QueueReprocessAllNotificationDataFailures(userName)) + .Throws(new Exception("Thrown From Unit Test")).Verifiable(); + + var result = await _documentReprocessingController.QueueReprocessAllNotificationDataFailures(userName); + Assert.NotNull(result); + + var statusResult = result as StatusCodeResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockUploadCompletionReprocessingService.Verify(); + } + + [Test] + public async Task QueueReprocessAllNotificationDataFailures_Failure_ServiceException() + { + var userName = "ttester"; + _mockUploadCompletionReprocessingService.Setup(service => + service.QueueReprocessAllNotificationDataFailures(userName)) + .Throws(new ServiceException("Thrown From Unit Test")).Verifiable(); + + var result = await _documentReprocessingController.QueueReprocessAllNotificationDataFailures(userName); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(500, statusResult!.StatusCode); + _mockUploadCompletionReprocessingService.Verify(); + } + + [Test] + public async Task QueueReprocessAllNotificationDataFailures_Failure_BadRequest() + { + var userName = string.Empty; + var result = await _documentReprocessingController.QueueReprocessAllNotificationDataFailures(userName); + Assert.NotNull(result); + + var statusResult = result as ObjectResult; + Assert.NotNull(statusResult); + Assert.AreEqual(400, statusResult!.StatusCode); + _mockUploadCompletionReprocessingService.Verify(); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/LCU.API.Internal.DocumentIngestorTests.csproj b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/LCU.API.Internal.DocumentIngestorTests.csproj new file mode 100644 index 0000000..777e87a --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/LCU.API.Internal.DocumentIngestorTests.csproj @@ -0,0 +1,52 @@ + + + + net8.0 + enable + + false + + Debug;Release;Test + + AnyCPU + + + + 1701;1702;CS8618;CS8600;CS8604;CS8620 + + + + 1701;1702;CS8618;CS8600;CS8604;CS8620 + + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + + + + + + + Always + + + Always + + + + diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Models/ProcessResultTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Models/ProcessResultTest.cs new file mode 100644 index 0000000..c1fc750 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Models/ProcessResultTest.cs @@ -0,0 +1,57 @@ +using NUnit.Framework; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using System.Collections.Generic; + +namespace LCU.API.Internal.DocumentIngestorTests.Models; + +public class ProcessResultTest +{ + [Test] + public void ProcessCriticalFailure() + { + var processResult = new ProcessResult(); + var message = "test"; + var result = ProcessResult.ProcessCriticalFailure(processResult, message); + Assert.IsNotNull(result); + Assert.IsFalse(result.Success); + Assert.AreEqual(result.ProcessStatusType, ProcessStatusTypes.CriticalFailure); + Assert.AreEqual(result.MessageStack.Count, 1); + } + + [Test] + public void ProcessCriticalFailure_List() + { + var processResult = new ProcessResult(); + var message = new List { "test", "test1" }; + var result = ProcessResult.ProcessCriticalFailure(processResult, message); + Assert.IsNotNull(result); + Assert.IsFalse(result.Success); + Assert.AreEqual(result.ProcessStatusType, ProcessStatusTypes.CriticalFailure); + Assert.AreEqual(result.MessageStack.Count, 2); + } + + [Test] + public void ProcessDataMappingFailure() + { + var processResult = new ProcessResult(); + var message = "test"; + var result = ProcessResult.ProcessDataMappingFailure(processResult, message); + Assert.IsNotNull(result); + Assert.IsFalse(result.Success); + Assert.AreEqual(result.ProcessStatusType, ProcessStatusTypes.DataMappingFailure); + Assert.AreEqual(result.MessageStack.Count, 1); + } + + [Test] + public void ProcessNotificationDataFailure() + { + var processResult = new ProcessResult(); + var message = "test"; + var result = ProcessResult.ProcessNotificationDataFailure(processResult, message); + Assert.IsNotNull(result); + Assert.IsFalse(result.Success); + Assert.AreEqual(result.ProcessStatusType, ProcessStatusTypes.NotificationDataFailure); + Assert.AreEqual(result.MessageStack.Count, 1); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Models/Validations/MetaDataValidationTests.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Models/Validations/MetaDataValidationTests.cs new file mode 100644 index 0000000..8a74044 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Models/Validations/MetaDataValidationTests.cs @@ -0,0 +1,131 @@ +using System.Linq; +using NUnit.Framework; +using LCU.Library.Internal.DocumentIngestorModels.Constants; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Validations; + +namespace LCU.API.Internal.DocumentIngestorTests.Models.Validations; + +public class MetaDataValidationTests +{ + [Test] + public void ValidateAccountNumber_Valid() + { + var processResult = new ProcessResult(); + var accountNumber = "1"; + var result = MetaDataValidation.ValidateAccountNumber(processResult, accountNumber); + Assert.IsNotNull(result); + Assert.IsTrue(result.Success); + Assert.IsEmpty(result.MessageStack); + } + + [Test] + public void ValidateAccountNumber_InValid() + { + var processResult = new ProcessResult(); + var accountNumber = "0"; + var result = MetaDataValidation.ValidateAccountNumber(processResult, accountNumber); + Assert.IsNotNull(result); + Assert.IsFalse(result.Success); + Assert.AreEqual(ValidationMessages.AccountInvalidMessage, result.MessageStack.First()); + } + + [Test] + public void ValidateFileName_Valid() + { + var processResult = new ProcessResult(); + var fileName = "Tester File Name"; + var result = MetaDataValidation.ValidateFileName(processResult, fileName); + Assert.IsNotNull(result); + Assert.IsTrue(result.Success); + Assert.IsEmpty(result.MessageStack); + } + + [Test] + public void ValidateFileName_InValid() + { + var processResult = new ProcessResult(); + var fileName = ""; + var result = MetaDataValidation.ValidateFileName(processResult, fileName); + Assert.IsNotNull(result); + Assert.IsFalse(result.Success); + Assert.AreEqual(ValidationMessages.FileNameInvalidMessage, result.MessageStack.First()); + } + + [Test] + public void ValidateFullName_Valid() + { + var processResult = new ProcessResult(); + var fullName = "Tester Full Name"; + var result = MetaDataValidation.ValidateFullName(processResult, fullName); + Assert.IsNotNull(result); + Assert.IsTrue(result.Success); + Assert.IsEmpty(result.MessageStack); + } + + [Test] + public void ValidateFullName_InValid() + { + var processResult = new ProcessResult(); + var fullName = ""; + var result = MetaDataValidation.ValidateFullName(processResult, fullName); + Assert.IsNotNull(result); + Assert.IsFalse(result.Success); + Assert.AreEqual(ValidationMessages.FullNameInvalidMessage, result.MessageStack.First()); + } + + [Test] + public void ValidatePdf_Valid() + { + var processResult = new ProcessResult(); + var pdf = "Tester PDF"; + var result = MetaDataValidation.ValidatePdf(processResult, pdf); + Assert.IsNotNull(result); + Assert.IsTrue(result.Success); + Assert.IsEmpty(result.MessageStack); + } + + [Test] + public void ValidatePdf_InValid() + { + var processResult = new ProcessResult(); + var pdf = ""; + var result = MetaDataValidation.ValidatePdf(processResult, pdf); + Assert.IsNotNull(result); + Assert.IsFalse(result.Success); + Assert.AreEqual(ValidationMessages.PdfInvalidMessage, result.MessageStack.First()); + } + + [Test] + public void ValidateTin_Valid() + { + var processResult = new ProcessResult(); + var tin = "111111111"; + var result = MetaDataValidation.ValidateTin(processResult, tin); + Assert.IsNotNull(result); + Assert.IsTrue(result.Success); + Assert.IsEmpty(result.MessageStack); + } + + [Test] + public void ValidateTin_InValid() + { + var processResult = new ProcessResult(); + var tin = ""; + var result = MetaDataValidation.ValidateTin(processResult, tin); + Assert.IsNotNull(result); + Assert.IsFalse(result.Success); + Assert.AreEqual(ValidationMessages.TinInvalidMessage, result.MessageStack.First()); + } + + [Test] + public void ValidateTin_TinZero_InValid() + { + var processResult = new ProcessResult(); + var tin = "0"; + var result = MetaDataValidation.ValidateTin(processResult, tin); + Assert.IsNotNull(result); + Assert.IsFalse(result.Success); + Assert.AreEqual(ValidationMessages.TinInvalidMessage, result.MessageStack.First()); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Security/GroupMembershipRequirementHandlerTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Security/GroupMembershipRequirementHandlerTest.cs new file mode 100644 index 0000000..e04889c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Security/GroupMembershipRequirementHandlerTest.cs @@ -0,0 +1,103 @@ +using System; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using LCU.API.Internal.DocumentIngestor.Security; +using Microsoft.AspNetCore.Authorization; +using NUnit.Framework; + +namespace LCU.API.Internal.DocumentIngestorTests.Security; + +public class GroupMembershipRequirementHandlerTest +{ + private readonly IAuthorizationHandler _handler = new GroupMembershipRequirementHandler(); + + private readonly GroupMembershipRequirement _requirement = new + ( + Guid.NewGuid().ToString(), + Guid.NewGuid().ToString(), + Guid.NewGuid().ToString() + ); + + [Test] + public async Task HandleRequirementAsync_NoRolesOrGroups_RequirementNotSucceeded() + { + var principal = new ClaimsPrincipal(); + var context = new AuthorizationHandlerContext(new[] { _requirement }, principal, null); + + await _handler.HandleAsync(context); + + Assert.IsFalse(context.HasSucceeded); + } + + [Test] + public async Task HandleRequirementAsync_RolesAndGroupsDoesNotIncludeAnyRequirementGroups_RequirementNotSucceeded() + { + var roles = new[] + { + new Claim("roles", Guid.NewGuid().ToString()), + new Claim("roles", Guid.NewGuid().ToString()), + new Claim("roles", Guid.NewGuid().ToString()), + }; + var groups = new[] + { + new Claim("groups", Guid.NewGuid().ToString()), + new Claim("groups", Guid.NewGuid().ToString()), + new Claim("groups", Guid.NewGuid().ToString()), + }; + var principal = new ClaimsPrincipal(new ClaimsIdentity(roles.Concat(groups))); + var context = new AuthorizationHandlerContext(new[] { _requirement }, principal, null); + + await _handler.HandleAsync(context); + + Assert.IsFalse(context.HasSucceeded); + } + + [Test] + public async Task HandleRequirementAsync_OneRoleIncludedInRequirementGroups_RequirementSucceeded() + { + var includedRole = _requirement.Groups.Skip(DateTime.Now.Millisecond % _requirement.Groups.Count).First(); + var roles = new[] + { + new Claim("roles", Guid.NewGuid().ToString()), + new Claim("roles", includedRole), + new Claim("roles", Guid.NewGuid().ToString()), + }; + var groups = new[] + { + new Claim("groups", Guid.NewGuid().ToString()), + new Claim("groups", Guid.NewGuid().ToString()), + new Claim("groups", Guid.NewGuid().ToString()), + }; + var principal = new ClaimsPrincipal(new ClaimsIdentity(roles.Concat(groups))); + var context = new AuthorizationHandlerContext(new[] { _requirement }, principal, null); + + await _handler.HandleAsync(context); + + Assert.IsTrue(context.HasSucceeded); + } + + [Test] + public async Task HandleRequirementAsync_OneGroupIncludedInRequirementGroups_RequirementSucceeded() + { + var includedRole = _requirement.Groups.Skip(DateTime.Now.Millisecond % _requirement.Groups.Count).First(); + var roles = new[] + { + new Claim("roles", Guid.NewGuid().ToString()), + new Claim("roles", includedRole), + new Claim("roles", Guid.NewGuid().ToString()) + }; + var groups = new[] + { + new Claim("groups", Guid.NewGuid().ToString()), + new Claim("groups", includedRole), + new Claim("groups", Guid.NewGuid().ToString()) + }; + var principal = new ClaimsPrincipal(new ClaimsIdentity(roles.Concat(groups))); + var context = new AuthorizationHandlerContext(new[] { _requirement }, principal, null); + + await _handler.HandleAsync(context); + + Assert.IsTrue(context.HasSucceeded); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/AttributeDeterminingServices/AccountOwnerDeterminingServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/AttributeDeterminingServices/AccountOwnerDeterminingServiceTest.cs new file mode 100644 index 0000000..b23f8c3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/AttributeDeterminingServices/AccountOwnerDeterminingServiceTest.cs @@ -0,0 +1,613 @@ +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Mixed; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using Moq; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.AttributeDeterminingServices; + +public class AccountOwnerDeterminingServiceTest +{ + private AccountOwnerDeterminingService _accountOwnerDeterminingService; + private Mock _mockCoreApiWrapperService; + + [SetUp] + public void Setup() + { + _mockCoreApiWrapperService = new Mock(); + _accountOwnerDeterminingService = new AccountOwnerDeterminingService(_mockCoreApiWrapperService.Object); + } + + [Test] + public async Task DetermineAccountOwnerAttributeForDnaDocument_PersonNumberFound_Success() + { + var fullName = "Bill B Billson"; + var accountNumber = "9999"; + var creationDate = new DateTime(2022, 01, 01); + var accountOwnership = new List + { + new() + { + PersonNumber = 1, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + IsPrimaryOwner = true + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString())).ReturnsAsync(accountOwnership); + + var result = await _accountOwnerDeterminingService.DetermineAccountOwnerAttribute(fullName, accountNumber, creationDate, null); + var resultPayload = result.Payload; + + Assert.AreEqual("1", resultPayload.PersonNumbers?[0]); + Assert.IsEmpty(resultPayload.OrganizationNumbers); + Assert.AreEqual("9999", resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByPersonName(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByOrganizationName(It.IsAny()), Times.Never); + } + + [Test] + public async Task DetermineAccountOwnerAttributeForDnaDocument_PersonNumberNotFound_OrganizationFound_Success() + { + var orgName = "The Big Company"; + var accountNumber = "9999"; + var creationDate = new DateTime(2022, 01, 01); + + var accountOwnership = new List + { + new() + { + ByOrgNbr = 2, + OrganizationName = orgName, + IsPrimaryOwner = true + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString())).ReturnsAsync(accountOwnership); + + var result = await _accountOwnerDeterminingService.DetermineAccountOwnerAttribute(orgName, accountNumber, creationDate, null); + var resultPayload = result.Payload; + Assert.AreEqual("2", resultPayload.OrganizationNumbers?[0]); + Assert.IsEmpty(resultPayload.PersonNumbers); + Assert.AreEqual("9999", resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task DetermineAccountOwnerAttributeForDnaDocument_PersonNumberNotFound_OrganizationNotFound_Failure() + { + var fullName = "Bill B Billson"; + var accountNumber = "9999"; + var creationDate = new DateTime(2022, 01, 01); + var accountOwnership = new List(); + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString())).ReturnsAsync(accountOwnership); + + var result = await _accountOwnerDeterminingService.DetermineAccountOwnerAttribute(fullName, accountNumber, creationDate, null); + var resultPayload = result.Payload; + Assert.IsEmpty(resultPayload.OrganizationNumbers); + Assert.IsEmpty(resultPayload.PersonNumbers); + Assert.AreEqual("9999", resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task DetermineAccountOwnerAttributeForDnaDocument_NoPrimaryOwner_Failure() + { + var fullName = "Bill B Billson"; + var accountNumber = ""; + var creationDate = new DateTime(2022, 01, 01); + var accountOwnership = new List + { + new() + { + PersonNumber = 2, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + IsPrimaryOwner = false + }, + new() + { + PersonNumber = 5, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + IsPrimaryOwner = false + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByPersonName(fullName)).ReturnsAsync(accountOwnership); + + var result = await _accountOwnerDeterminingService.DetermineAccountOwnerAttribute(fullName, accountNumber, creationDate, null); + var resultPayload = result.Payload; + Assert.IsFalse(result.Success); + Assert.IsEmpty(resultPayload.OrganizationNumbers); + Assert.IsEmpty(resultPayload.PersonNumbers); + Assert.AreEqual(accountNumber, resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByPersonName(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByOrganizationName(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task DetermineAccountOwnerAttributeForDnaDocument_TooManyOwners_Failure() + { + var fullName = "Bill B Billson"; + var accountNumber = ""; + var creationDate = new DateTime(2022, 01, 01); + var accountOwnership = new List + { + new() + { + PersonNumber = 2, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + IsPrimaryOwner = true + }, + new() + { + PersonNumber = 5, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + IsPrimaryOwner = true + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByPersonName(fullName)).ReturnsAsync(accountOwnership); + + var result = await _accountOwnerDeterminingService.DetermineAccountOwnerAttribute(fullName, accountNumber, creationDate, null); + var resultPayload = result.Payload; + Assert.IsFalse(result.Success); + Assert.IsEmpty(resultPayload.OrganizationNumbers); + Assert.IsEmpty(resultPayload.PersonNumbers); + Assert.AreEqual(accountNumber, resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByPersonName(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByOrganizationName(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task DeterminePrimaryOwnerAttributeForDnaDocument_EntityNameDoesNotMatch_Failure() + { + var fullName = "Bill B Billson"; + var accountNumber = "9999"; + var creationDate = new DateTime(2022, 01, 01); + + var accountOwnership = new List + { + new() + { + ByOrgNbr = 2, + FirstName = "Pete", + MiddleInitial = "P", + LastName = "Peterson", + IsPrimaryOwner = true + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString())).ReturnsAsync(accountOwnership); + + var result = await _accountOwnerDeterminingService.DetermineAccountOwnerAttribute(fullName, accountNumber, creationDate, null); + var resultPayload = result.Payload; + Assert.IsFalse(result.Success); + Assert.AreEqual("2", resultPayload.OrganizationNumbers?[0]); + Assert.IsEmpty(resultPayload.PersonNumbers); + Assert.AreEqual("9999", resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task DetermineAccountOwnerAttributeForDnaDocument_OwnerOverridePerson_Success() + { + var fullName = "Bill B Billson"; + var accountNumber = "9999"; + var documentProcessingInfoId = 123; + var creationDate = new DateTime(2022, 01, 01); + var accountOwnership = new List + { + new() + { + PersonNumber = 1, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + IsPrimaryOwner = true + } + }; + var ownerOverrideRequest = new OwnerOverrideInfo() + { + DocumentProcessingInfoId = documentProcessingInfoId, + EntityId = "888888", + EntityType = EntityTypes.Person, + UserName = "Test Tester" + }; + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString())).ReturnsAsync(accountOwnership); + + var result = await _accountOwnerDeterminingService.DetermineAccountOwnerAttribute(fullName, accountNumber, creationDate, ownerOverrideRequest); + var resultPayload = result.Payload; + + Assert.AreEqual("888888", resultPayload.PersonNumbers?[0]); + Assert.IsEmpty(resultPayload.OrganizationNumbers); + Assert.AreEqual("9999", resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByPersonName(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByOrganizationName(It.IsAny()), Times.Never); + } + + [Test] + public async Task DetermineAccountOwnerAttributeForDnaDocument_OwnerOverrideOrganization_Success() + { + var fullName = "Bill B Billson"; + var accountNumber = "9999"; + var documentProcessingInfoId = 123; + var creationDate = new DateTime(2022, 01, 01); + var accountOwnership = new List + { + new() + { + ByOrgNbr = 1, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + IsPrimaryOwner = true + } + }; + var ownerOverrideRequest = new OwnerOverrideInfo() + { + DocumentProcessingInfoId = documentProcessingInfoId, + EntityId = "888888", + EntityType = EntityTypes.Organization, + UserName = "Test Tester" + }; + + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString())).ReturnsAsync(accountOwnership); + + var result = await _accountOwnerDeterminingService.DetermineAccountOwnerAttribute(fullName, accountNumber, creationDate, ownerOverrideRequest); + var resultPayload = result.Payload; + + Assert.AreEqual("888888", resultPayload.OrganizationNumbers?[0]); + Assert.IsEmpty(resultPayload.PersonNumbers); + Assert.AreEqual("9999", resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByPersonName(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByOrganizationName(It.IsAny()), Times.Never); + } + + [Test] + public async Task DetermineAccountOwnerAttributeForDnaDocument_OwnerOverrideUnknown_Success() + { + var fullName = "Bill B Billson"; + var accountNumber = "9999"; + var documentProcessingInfoId = 123; + var creationDate = new DateTime(2022, 01, 01); + var accountOwnership = new List + { + new() + { + PersonNumber = 1, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + IsPrimaryOwner = true + } + }; + var ownerOverrideRequest = new OwnerOverrideInfo() + { + DocumentProcessingInfoId = documentProcessingInfoId, + EntityId = "888888", + EntityType = EntityTypes.Unknown, + UserName = "Test Tester" + }; + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString())).ReturnsAsync(accountOwnership); + + var result = await _accountOwnerDeterminingService.DetermineAccountOwnerAttribute(fullName, accountNumber, creationDate, ownerOverrideRequest); + var resultPayload = result.Payload; + + Assert.AreEqual("1", resultPayload.PersonNumbers?[0]); + Assert.IsEmpty(resultPayload.OrganizationNumbers); + Assert.AreEqual("9999", resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByPersonName(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByOrganizationName(It.IsAny()), Times.Never); + } + + [Test] + public async Task DetermineAccountOwnerAttributeByMemberNumberOrUserId_StartsWithM_PersonNumberFound_Success() + { + var memberNumberOrUserId = "M1234"; + var accountNumber = "9999"; + var docType = "MTG_NT_110_01"; + var creationDate = new DateTime(2022, 01, 01); + var accountOwnership = new List + { + new() + { + PersonNumber = 1234, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + IsPrimaryOwner = true + } + }; + + var personOrganization = new PersonOrganization() + { + PersonNumber = "1234", + OrganizationNumber = null + }; + + + var agreementAccount = new AgreementAccount() + { + AccountNumber = 9999, + AccountDescription = "PREMIUM CHECKING", + MajorAccountTypeCode = "CK", + TaxReportForPersonNumber = 1234, + TaxReportForOrgNumber = null, + OvrDeliveryMethCD = "PRNT", + AccountOwner = new AgreementAccountOwner + { + AccountNumber = 9999, + AgreementNumber = 0, + UserId = null, + PersonNumber = 0 + } + }; + + _mockCoreApiWrapperService.Setup(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny())).ReturnsAsync(personOrganization).Verifiable(); + _mockCoreApiWrapperService.Setup(x => x.GetAgreementAccountByAccountId(It.IsAny())).ReturnsAsync(agreementAccount); + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString())).ReturnsAsync(accountOwnership); + + var result = await _accountOwnerDeterminingService.DetermineAccountOwnerAttributeByMemberNumberOrUserId(memberNumberOrUserId, accountNumber, docType, creationDate, null); + var resultPayload = result.Payload; + + Assert.IsTrue(result.Success); + Assert.AreEqual("1234", resultPayload.PersonNumbers?[0]); + Assert.IsEmpty(resultPayload.OrganizationNumbers); + Assert.AreEqual("9999", resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementAccountByAccountId(It.IsAny()), Times.Once); + } + + [Test] + public async Task DetermineAccountOwnerAttributeByMemberNumberOrUserId_StartsWithoutM_PersonNumberFound_Success() + { + var memberNumberOrUserId = "1234"; + var accountNumber = "9999"; + var docType = "OPS_NT_119_01"; + var creationDate = new DateTime(2022, 01, 01); + var accountOwnership = new List + { + new() + { + PersonNumber = 1234, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + IsPrimaryOwner = true + } + }; + + var personOrganization = new PersonOrganization() + { + PersonNumber = "1234", + OrganizationNumber = null + }; + + + var agreementAccount = new AgreementAccount() + { + AccountNumber = 9999, + AccountDescription = "PREMIUM CHECKING", + MajorAccountTypeCode = "CK", + TaxReportForPersonNumber = 1234, + TaxReportForOrgNumber = null, + OvrDeliveryMethCD = "PRNT", + AccountOwner = new AgreementAccountOwner + { + AccountNumber = 9999, + AgreementNumber = 0, + UserId = null, + PersonNumber = 0 + } + }; + + _mockCoreApiWrapperService.Setup(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny())).ReturnsAsync(personOrganization).Verifiable(); + _mockCoreApiWrapperService.Setup(x => x.GetAgreementAccountByAccountId(It.IsAny())).ReturnsAsync(agreementAccount); + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString())).ReturnsAsync(accountOwnership); + + var result = await _accountOwnerDeterminingService.DetermineAccountOwnerAttributeByMemberNumberOrUserId(memberNumberOrUserId, accountNumber, docType, creationDate, null); + var resultPayload = result.Payload; + + Assert.IsTrue(result.Success); + Assert.AreEqual("1234", resultPayload.PersonNumbers?[0]); + Assert.IsEmpty(resultPayload.OrganizationNumbers); + Assert.AreEqual("9999", resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementAccountByAccountId(It.IsAny()), Times.Once); + } + + [Test] + public async Task DetermineAccountOwnerAttributeByMemberNumberOrUserId_PersonNumberNotFound_OrganizationNotFound_Failure() + { + var memberNumberOrUserId = "M1234"; + var accountNumber = "9999"; + var docType = "OPS_NT_119_01"; + var creationDate = new DateTime(2022, 01, 01); + var accountOwnership = new List + { + new() + { + PersonNumber = 1, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + IsPrimaryOwner = true + } + }; + + var personOrganization = new PersonOrganization() + { + PersonNumber = null, + OrganizationNumber = null + }; + + _mockCoreApiWrapperService.Setup(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny())).ReturnsAsync(personOrganization).Verifiable(); + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString())).ReturnsAsync(accountOwnership); + + var result = await _accountOwnerDeterminingService.DetermineAccountOwnerAttributeByMemberNumberOrUserId(memberNumberOrUserId, accountNumber, docType, creationDate, null); + var resultPayload = result.Payload; + + Assert.IsFalse(result.Success); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + } + + [Test] + public async Task DetermineAccountOwnerAttributeByMemberNumberOrUserId_AgreementNotFound_Failure() + { + var memberNumberOrUserId = "1234"; + var accountNumber = "9999"; + var docType = "MTG_NT_110_01"; + var creationDate = new DateTime(2022, 01, 01); + var accountOwnership = new List + { + new() + { + PersonNumber = 1, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + IsPrimaryOwner = true + } + }; + + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString())).ReturnsAsync(accountOwnership); + + var result = await _accountOwnerDeterminingService.DetermineAccountOwnerAttributeByMemberNumberOrUserId(memberNumberOrUserId, accountNumber, docType, creationDate, null); + + Assert.IsFalse(result.Success); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementAccountByAccountId(It.IsAny()), Times.Never); + } + + [Test] + public async Task DetermineAccountOwnerAttributeByMemberNumberOrUserId_PersonNumberDoesNotMatch_Failure() + { + var memberNumberOrUserId = "M1234"; + var accountNumber = "9999"; + var docType = "OPS_NT_119_01"; + var creationDate = new DateTime(2022, 01, 01); + var accountOwnership = new List + { + new() + { + PersonNumber = 1, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + IsPrimaryOwner = true + } + }; + + var personOrganization = new PersonOrganization() + { + PersonNumber = "2", + OrganizationNumber = null + }; + + var agreementAccount = new AgreementAccount() + { + AccountNumber = 9999, + AccountDescription = "PREMIUM CHECKING", + MajorAccountTypeCode = "CK", + TaxReportForPersonNumber = 1234, + TaxReportForOrgNumber = null, + OvrDeliveryMethCD = "PRNT", + AccountOwner = new AgreementAccountOwner + { + AccountNumber = 9999, + AgreementNumber = 0, + UserId = null, + PersonNumber = 0 + } + }; + + _mockCoreApiWrapperService.Setup(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny())).ReturnsAsync(personOrganization).Verifiable(); + _mockCoreApiWrapperService.Setup(x => x.GetAgreementAccountByAccountId(It.IsAny())).ReturnsAsync(agreementAccount); + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString())).ReturnsAsync(accountOwnership); + + var result = await _accountOwnerDeterminingService.DetermineAccountOwnerAttributeByMemberNumberOrUserId(memberNumberOrUserId, accountNumber, docType, creationDate, null); + + Assert.IsFalse(result.Success); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementAccountByAccountId(It.IsAny()), Times.Once); + } + + [Test] + public async Task DetermineAccountOwnerAttributeByMemberNumberOrUserId_OrganizationNumberDoesNotMatch_Failure() + { + + var memberNumberOrUserId = "M1234"; + var accountNumber = "9999"; + var docType = "OPS_NT_119_01"; + var creationDate = new DateTime(2022, 01, 01); + var accountOwnership = new List + { + new() + { + PersonNumber = 1, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + IsPrimaryOwner = true, + ByOrgNbr = 123 + } + }; + + var personOrganization = new PersonOrganization() + { + PersonNumber = null, + OrganizationNumber = "456" + }; + + + var agreementAccount = new AgreementAccount() + { + AccountNumber = 9999, + AccountDescription = "PREMIUM CHECKING", + MajorAccountTypeCode = "CK", + TaxReportForPersonNumber = null, + TaxReportForOrgNumber = 123, + OvrDeliveryMethCD = "PRNT", + AccountOwner = new AgreementAccountOwner + { + AccountNumber = 9999, + AgreementNumber = 0, + UserId = null, + PersonNumber = 0 + } + }; + + _mockCoreApiWrapperService.Setup(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny())).ReturnsAsync(personOrganization).Verifiable(); + _mockCoreApiWrapperService.Setup(x => x.GetAgreementAccountByAccountId(It.IsAny())).ReturnsAsync(agreementAccount); + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString())).ReturnsAsync(accountOwnership); + + var result = await _accountOwnerDeterminingService.DetermineAccountOwnerAttributeByMemberNumberOrUserId(memberNumberOrUserId, accountNumber, docType, creationDate, null); + + Assert.IsFalse(result.Success); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementAccountByAccountId(It.IsAny()), Times.Once); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/AttributeDeterminingServices/PrimaryOwnerDeterminingServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/AttributeDeterminingServices/PrimaryOwnerDeterminingServiceTest.cs new file mode 100644 index 0000000..28c7917 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/AttributeDeterminingServices/PrimaryOwnerDeterminingServiceTest.cs @@ -0,0 +1,1006 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Mixed; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Tax; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.Exceptions; +using Moq; +using NUnit.Framework; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.AttributeDeterminingServices; + +public class PrimaryOwnerDeterminingServiceTest +{ + private PrimaryOwnerDeterminingService _primaryOwnerDeterminingService; + private Mock _mockCoreApiWrapperService; + + [SetUp] + public void Setup() + { + _mockCoreApiWrapperService = new Mock(); + _primaryOwnerDeterminingService = new PrimaryOwnerDeterminingService(_mockCoreApiWrapperService.Object); + } + + [Test] + public async Task DeterminePrimaryOwnerAttribute_PersonNumberFound_Success() + { + var taxId = "123245"; + var fullName = "Tester Unit"; + var accountNumber = "9999"; + var personsTaxIdData = new List + { + new() + { + PersonNumber = 1, + NameLastFirstMiddleSuffix = fullName, + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetPersonsTaxIdData(taxId)).ReturnsAsync(personsTaxIdData); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttribute(fullName, accountNumber, taxId, null); + var resultPayload = result.Payload; + Assert.True(result.Success); + Assert.AreEqual("1", resultPayload.PersonNumber); + Assert.IsNull(resultPayload.OrganizationNumber); + Assert.AreEqual(accountNumber, resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetPersonsTaxIdData(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetOrganizationsTaxIdData(It.IsAny()), Times.Never); + } + + [Test] + public async Task DeterminePrimaryOwnerAttribute_PersonNumberNotFound_OrganizationFound_Success() + { + var taxId = "123245"; + var fullName = "Tester UnitOrg"; + var accountNumber = "9999"; + var personsTaxIdData = new List(); + _mockCoreApiWrapperService.Setup(x => x.GetPersonsTaxIdData(taxId)).ReturnsAsync(personsTaxIdData); + + var organizationTaxIdData = new List + { + new() + { + OrganizationNumber = 2, + Name = fullName + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetOrganizationsTaxIdData(taxId)).ReturnsAsync(organizationTaxIdData); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttribute(fullName, accountNumber, taxId, null); + var resultPayload = result.Payload; + Assert.True(result.Success); + Assert.AreEqual("2", resultPayload.OrganizationNumber); + Assert.IsNull(resultPayload.PersonNumber); + Assert.AreEqual(accountNumber, resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetPersonsTaxIdData(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetOrganizationsTaxIdData(It.IsAny()), Times.Once); + } + + [Test] + public async Task DeterminePrimaryOwnerAttribute_PersonNumberNotFound_OrganizationNotFound_Failure() + { + var taxId = "123245"; + var fullName = "Tester UnitOrg"; + var accountNumber = "9999"; + var personsTaxIdData = new List(); + _mockCoreApiWrapperService.Setup(x => x.GetPersonsTaxIdData(taxId)).ReturnsAsync(personsTaxIdData); + + var organizationTaxIdData = new List(); + _mockCoreApiWrapperService.Setup(x => x.GetOrganizationsTaxIdData(taxId)).ReturnsAsync(organizationTaxIdData); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttribute(fullName, accountNumber, taxId, null); + var resultPayload = result.Payload; + Assert.IsFalse(result.Success); + Assert.IsNull(resultPayload.OrganizationNumber); + Assert.IsNull(resultPayload.PersonNumber); + Assert.AreEqual(accountNumber, resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetPersonsTaxIdData(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetOrganizationsTaxIdData(It.IsAny()), Times.Once); + } + + [Test] + public async Task DeterminePrimaryOwnerAttribute_PersonNumberNotFound_FullNameNoMatch_Failure() + { + var taxId = "123245"; + var fullName = "Tester Unit"; + var accountNumber = "9999"; + var personsTaxIdData = new List + { + new() + { + PersonNumber = 1, + NameLastFirstMiddleSuffix = "Tester Unit Nope", + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetPersonsTaxIdData(taxId)).ReturnsAsync(personsTaxIdData); + + var organizationTaxIdData = new List(); + _mockCoreApiWrapperService.Setup(x => x.GetOrganizationsTaxIdData(taxId)).ReturnsAsync(organizationTaxIdData); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttribute(fullName, accountNumber, taxId, null); + var resultPayload = result.Payload; + Assert.IsFalse(result.Success); + Assert.IsNull(resultPayload.OrganizationNumber); + Assert.IsNull(resultPayload.PersonNumber); + _mockCoreApiWrapperService.Verify(x => x.GetPersonsTaxIdData(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetOrganizationsTaxIdData(It.IsAny()), Times.Once); + } + + [Test] + public async Task DeterminePrimaryOwnerAttribute_PersonNumberNotFound_FullNameNoMatch_MessageContainsPersonTaxData() + { + const string taxId = nameof(taxId); + var personNumbers = new Random(DateTime.Now.Millisecond); + var personsTaxIdData = Enumerable.Repeat + ( + () => new PersonTaxIdDataResponse + { + PersonNumber = personNumbers.Next(), + NameLastFirstMiddleSuffix = Guid.NewGuid().ToString(), + FirstName = Guid.NewGuid().ToString(), + MiddleName = Guid.NewGuid().ToString(), + LastName = Guid.NewGuid().ToString() + }, + 5 + ) + .Select(f => f()) + .ToArray(); + _mockCoreApiWrapperService.Setup(x => x.GetPersonsTaxIdData(taxId)).ReturnsAsync(personsTaxIdData); + _mockCoreApiWrapperService.Setup(x => x.GetOrganizationsTaxIdData(taxId)).ReturnsAsync(Enumerable.Empty()); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttribute(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), taxId, null!); + + var message = result.Message; + Assert.IsNotNull(message); + var personMessages = message!.Split("Person Detail:"); + foreach (var person in personsTaxIdData) + { + var personsMessages = personMessages + .Where(o => o.Contains(person.PersonNumber.ToString())) + .ToArray(); + Assert.AreEqual(1, personsMessages.Length); + var personMessage = personsMessages.Single(); + StringAssert.Contains(person.FirstName, personMessage); + StringAssert.Contains(person.MiddleName, personMessage); + StringAssert.Contains(person.LastName, personMessage); + if (Array.IndexOf(personMessages, personMessage) != personMessages.Length - 1) + { + StringAssert.EndsWith(" ", personMessage); + } + } + } + + [Test] + public async Task DeterminePrimaryOwnerAttribute_OrganizationNotFound_FullNameNoMatch_Failure() + { + var taxId = "123245"; + var fullName = "Tester UnitOrg"; + var accountNumber = "9999"; + var personsTaxIdData = new List(); + _mockCoreApiWrapperService.Setup(x => x.GetPersonsTaxIdData(taxId)).ReturnsAsync(personsTaxIdData); + + var organizationTaxIdData = new List + { + new() + { + OrganizationNumber = 2, + Name = "Tester UnitOrg Nope" + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetOrganizationsTaxIdData(taxId)).ReturnsAsync(organizationTaxIdData); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttribute(fullName, accountNumber, taxId, null); + var resultPayload = result.Payload; + Assert.IsFalse(result.Success); + Assert.IsNull(resultPayload.OrganizationNumber); + Assert.IsNull(resultPayload.PersonNumber); + Assert.AreEqual(accountNumber, resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetPersonsTaxIdData(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetOrganizationsTaxIdData(It.IsAny()), Times.Once); + } + + [Test] + public async Task DeterminePrimaryOwnerAttribute_OrganizationNotFound_FullNameNoMatch_MessageContainsOrganziationTaxData() + { + const string taxId = nameof(taxId); + var organizationNumbers = new Random(DateTime.Now.Millisecond); + var organizationTaxIdData = Enumerable.Repeat + ( + () => new OrganizationTaxIdDataResponse + { + OrganizationNumber = organizationNumbers.Next(), + Name = Guid.NewGuid().ToString() + }, + 5 + ) + .Select(f => f()) + .ToArray(); + _mockCoreApiWrapperService.Setup(x => x.GetPersonsTaxIdData(taxId)).ReturnsAsync(Enumerable.Empty()); + _mockCoreApiWrapperService.Setup(x => x.GetOrganizationsTaxIdData(taxId)).ReturnsAsync(organizationTaxIdData); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttribute(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), taxId, null!); + + var message = result.Message; + Assert.IsNotNull(message); + var organizationMessages = message!.Split("Organization Detail:"); + foreach (var organization in organizationTaxIdData) + { + var organizationsMessages = organizationMessages + .Where(o => o.Contains(organization.Name)) + .ToArray(); + Assert.AreEqual(1, organizationsMessages.Length); + var organizationMessage = organizationsMessages.Single(); + StringAssert.Contains(organization.OrganizationNumber.ToString(), organizationMessage); + if (Array.IndexOf(organizationMessages, organizationMessage) != organizationMessages.Length - 1) + { + StringAssert.EndsWith(" ", organizationMessage); + } + } + } + + [Test] + public async Task DeterminePrimaryOwnerAttribute_PersonFound_Success() + { + var fullName = "Bill B Billson"; + var accountNumber = "9999"; + var creationDate = new DateTime(2022, 01, 01); + var accountOwnership = new List + { + new() + { + PersonNumber = 1, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + IsPrimaryOwner = true + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString())).ReturnsAsync(accountOwnership); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttribute(fullName, accountNumber, creationDate, null); + var resultPayload = result.Payload; + Assert.True(result.Success); + Assert.AreEqual("1", resultPayload.PersonNumber); + Assert.IsNull(resultPayload.OrganizationNumber); + Assert.AreEqual(accountNumber, resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByPersonName(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByOrganizationName(It.IsAny()), Times.Never); + } + + [Test] + public async Task DeterminePrimaryOwnerAttribute_PersonNumberNotFound_OrganizationNumberFound_Success() + { + var orgName = "The Big Company"; + var accountNumber = "9999"; + var creationDate = new DateTime(2022, 01, 01); + + var accountOwnership = new List + { + new() + { + ByOrgNbr = 2, + OrganizationName = orgName, + IsPrimaryOwner = true + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString())).ReturnsAsync(accountOwnership); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttribute(orgName, accountNumber, creationDate, null); + var resultPayload = result.Payload; + Assert.True(result.Success); + Assert.AreEqual("2", resultPayload.OrganizationNumber); + Assert.IsNull(resultPayload.PersonNumber); + Assert.AreEqual(accountNumber, resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + } + + + [Test] + public async Task DeterminePrimaryOwnerAttribute_EntityNameDoesNotMatch_Failure() + { + var fullName = "Bill B Billson"; + var accountNumber = "9999"; + var creationDate = new DateTime(2022, 01, 01); + + var accountOwnership = new List + { + new() + { + ByOrgNbr = 2, + FirstName = "Pete", + MiddleInitial = "P", + LastName = "Peterson", + IsPrimaryOwner = true + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString())).ReturnsAsync(accountOwnership); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttribute(fullName, accountNumber, creationDate, null); + var resultPayload = result.Payload; + Assert.IsFalse(result.Success); + Assert.IsNull(resultPayload.OrganizationNumber); + Assert.IsNull(resultPayload.PersonNumber); + Assert.AreEqual(accountNumber, resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task DeterminePrimaryOwnerAttribute_PersonNumberNotFound_OrganizationNumberNotFound_Failure() + { + var fullName = "Bill B Billson"; + var accountNumber = "9999"; + var creationDate = new DateTime(2022, 01, 01); + var accountOwnership = new List(); + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString())).ReturnsAsync(accountOwnership); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttribute(fullName, accountNumber, creationDate, null); + var resultPayload = result.Payload; + Assert.IsFalse(result.Success); + Assert.IsNull(resultPayload.OrganizationNumber); + Assert.IsNull(resultPayload.PersonNumber); + Assert.AreEqual(accountNumber, resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task DeterminePrimaryOwnerAttribute_TooManyOwners_Failure() + { + var fullName = "Bill B Billson"; + var accountNumber = Guid.NewGuid().ToString(); + var creationDate = new DateTime(2022, 01, 01); + var accountOwnership = new List + { + new() + { + PersonNumber = 2, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + IsPrimaryOwner = true + }, + new() + { + PersonNumber = 5, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + IsPrimaryOwner = true + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString())).ReturnsAsync(accountOwnership); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttribute(fullName, accountNumber, creationDate, null); + var resultPayload = result.Payload; + Assert.IsFalse(result.Success); + Assert.IsNull(result.EntityIsUnknown); + Assert.IsNull(resultPayload.OrganizationNumber); + Assert.IsNull(resultPayload.PersonNumber); + Assert.IsNotNull(resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByPersonName(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByOrganizationName(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task DeterminePrimaryOwnerAttribute_NoPrimaryOwner_Failure() + { + var fullName = "Bill B Billson"; + var creationDate = new DateTime(2022, 01, 01); + var accountNumber = "5"; + var accountOwnership = new List + { + new() + { + PersonNumber = 2, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + IsPrimaryOwner = false + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByPersonName(fullName)).ReturnsAsync(accountOwnership); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttribute(fullName, accountNumber, creationDate, null); + var resultPayload = result.Payload; + Assert.IsFalse(result.Success); + Assert.IsNull(resultPayload.OrganizationNumber); + Assert.IsNull(resultPayload.PersonNumber); + Assert.AreEqual(accountNumber, resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByPersonName(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByOrganizationName(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task DeterminePrimaryOwnerAttribute_OwnerOverridePerson_Success() + { + var taxId = "123245"; + var fullName = "Tester Unit"; + var accountNumber = "9999"; + var documentProcessingInfoId = 123; + var personsTaxIdData = new List + { + new() + { + PersonNumber = 1, + NameLastFirstMiddleSuffix = fullName, + } + }; + var ownerOverride = new OwnerOverrideInfo() + { + DocumentProcessingInfoId = documentProcessingInfoId, + UserName = "Test Tester", + EntityId = "888888", + EntityType = EntityTypes.Person + }; + _mockCoreApiWrapperService.Setup(x => x.GetPersonsTaxIdData(taxId)).ReturnsAsync(personsTaxIdData); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttribute(fullName, accountNumber, taxId, ownerOverride); + var resultPayload = result.Payload; + Assert.True(result.Success); + Assert.AreEqual("888888", resultPayload.PersonNumber); + Assert.IsNull(resultPayload.OrganizationNumber); + Assert.AreEqual(accountNumber, resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetPersonsTaxIdData(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetOrganizationsTaxIdData(It.IsAny()), Times.Never); + } + + [Test] + public async Task DeterminePrimaryOwnerAttribute_OwnerOverrideOrganization_Success() + { + var taxId = "123245"; + var fullName = "Tester Unit"; + var documentProcessingInfoId = 123; + var accountNumber = "9999"; + var personsTaxIdData = new List + { + new() + { + OrganizationNumber = 1, + Name = fullName, + } + }; + var ownerOverride = new OwnerOverrideInfo() + { + DocumentProcessingInfoId = documentProcessingInfoId, + UserName = "Test Tester", + EntityId = "888888", + EntityType = EntityTypes.Organization + }; + _mockCoreApiWrapperService.Setup(x => x.GetOrganizationsTaxIdData(taxId)).ReturnsAsync(personsTaxIdData); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttribute(fullName, accountNumber, taxId, ownerOverride); + var resultPayload = result.Payload; + Assert.True(result.Success); + Assert.AreEqual("888888", resultPayload.OrganizationNumber); + Assert.IsNull(resultPayload.PersonNumber); + Assert.AreEqual(accountNumber, resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetPersonsTaxIdData(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetOrganizationsTaxIdData(It.IsAny()), Times.Never); + } + + [Test] + public async Task DeterminePrimaryOwnerAttribute_OwnerOverrideUnknown_Success() + { + var taxId = "123245"; + var fullName = "Tester Unit"; + var accountNumber = "9999"; + var documentProcessingInfoId = 123; + var personsTaxIdData = new List + { + new() + { + PersonNumber = 1, + NameLastFirstMiddleSuffix = fullName, + } + }; + var ownerOverride = new OwnerOverrideInfo() + { + DocumentProcessingInfoId = documentProcessingInfoId, + UserName = "Test Tester", + EntityId = "888888", + EntityType = EntityTypes.Unknown + }; + _mockCoreApiWrapperService.Setup(x => x.GetPersonsTaxIdData(taxId)).ReturnsAsync(personsTaxIdData); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttribute(fullName, accountNumber, taxId, ownerOverride); + var resultPayload = result.Payload; + Assert.True(result.Success); + Assert.IsNull(resultPayload.PersonNumber); + Assert.IsNull(resultPayload.OrganizationNumber); + Assert.AreEqual(accountNumber, resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetPersonsTaxIdData(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetOrganizationsTaxIdData(It.IsAny()), Times.Never); + } + + [Test] + public async Task DeterminePrimaryOwnerAttributeByMemberNumberOrUserId_PersonNumberFound_Success() + { + var memberNumberOrUserId = "M1234"; + var accountNumber = "9999"; + var docType = "LVI_LT_106_01"; + var creationDate = new DateTime(2022, 01, 01); + + var personOrganization = new PersonOrganization() + { + PersonNumber = "1", + OrganizationNumber = null + }; + + _mockCoreApiWrapperService.Setup(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny())).ReturnsAsync(personOrganization).Verifiable(); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(memberNumberOrUserId, accountNumber, docType, creationDate, null); + var resultPayload = result.Payload; + + Assert.True(result.Success); + Assert.AreEqual("1", resultPayload.PersonNumber); + Assert.AreEqual(null, resultPayload.OrganizationNumber); + Assert.AreEqual("9999", resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + } + + [Test] + public async Task DeterminePrimaryOwnerAttributeByMemberNumberOrUserId_OrganizationFound_Success() + { + var memberNumberOrUserId = "M1234"; + var accountNumber = "9999"; + var docType = "LVI_LT_106_01"; + var creationDate = new DateTime(2022, 01, 01); + + var personOrganization = new PersonOrganization() + { + PersonNumber = null, + OrganizationNumber = "123" + }; + + _mockCoreApiWrapperService.Setup(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny())).ReturnsAsync(personOrganization).Verifiable(); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(memberNumberOrUserId, accountNumber, docType, creationDate, null); + var resultPayload = result.Payload; + + Assert.True(result.Success); + Assert.AreEqual(null, resultPayload.PersonNumber); + Assert.AreEqual("123", resultPayload.OrganizationNumber); + Assert.AreEqual("9999", resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + } + + [Test] + public async Task DeterminePrimaryOwnerAttributeByMemberNumberOrUserId_AgreementFound_Success() + { + var memberNumberOrUserId = "1234"; + var accountNumber = "9999"; + var docType = "LVI_LT_106_01"; + var creationDate = new DateTime(2022, 01, 01); + + var agreement = new Agreement() + { + AgreementNumber = 123, + ByOrgNbr = 0, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + PersonNumber = 1234 + }; + + _mockCoreApiWrapperService.Setup(x => x.GetAgreementByUserId(It.IsAny())).ReturnsAsync(agreement); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(memberNumberOrUserId, accountNumber, docType, creationDate, null); + var resultPayload = result.Payload; + + Assert.True(result.Success); + Assert.AreEqual("1234", resultPayload.PersonNumber); + Assert.AreEqual(null, resultPayload.OrganizationNumber); + Assert.AreEqual("9999", resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementAccountByAccountId(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Once); + } + + [Test] + public async Task DeterminePrimaryOwnerAttributeByMemberNumberOrUserId_AgreementMmStmxtFound_Success() + { + var memberNumberOrUserId = "1234"; + var accountNumber = "9999"; + var docType = "MM_STMXT"; + var creationDate = new DateTime(2022, 01, 01); + + var agreement = new Agreement() + { + AgreementNumber = 123, + ByOrgNbr = 0, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + PersonNumber = 1234 + }; + + var agreementAccount = new AgreementAccount() + { + AccountNumber = 9999, + AccountDescription = "PREMIUM CHECKING", + MajorAccountTypeCode = "CK", + TaxReportForPersonNumber = 1234, + TaxReportForOrgNumber = null, + OvrDeliveryMethCD = "PRNT", + AccountOwner = new AgreementAccountOwner + { + AccountNumber = 9999, + AgreementNumber = 0, + UserId = null, + PersonNumber = 0 + } + }; + + var personOrganization = new PersonOrganization() + { + PersonNumber = "1234", + OrganizationNumber = null + }; + + _mockCoreApiWrapperService.Setup(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny())).ReturnsAsync(personOrganization).Verifiable(); + _mockCoreApiWrapperService.Setup(x => x.GetAgreementAccountByAccountId(It.IsAny())).ReturnsAsync(agreementAccount); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(memberNumberOrUserId, accountNumber, docType, creationDate, null); + var resultPayload = result.Payload; + + Assert.True(result.Success); + Assert.AreEqual("1234", resultPayload.PersonNumber); + Assert.AreEqual(null, resultPayload.OrganizationNumber); + Assert.AreEqual("9999", resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementAccountByAccountId(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + } + + [Test] + public async Task DeterminePrimaryOwnerAttributeByMemberNumberOrUserId_PersonNotFound_OrganizationNotFound_Failure() + { + var memberNumberOrUserId = "M1234"; + var accountNumber = "9999"; + var docType = "LVI_LT_106_01"; + var creationDate = new DateTime(2022, 01, 01); + var accountOwnership = new List + { + new() + { + PersonNumber = 1, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + IsPrimaryOwner = true + } + }; + + var personOrganization = new PersonOrganization() + { + PersonNumber = null, + OrganizationNumber = null + }; + + _mockCoreApiWrapperService.Setup(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny())).ReturnsAsync(personOrganization).Verifiable(); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(memberNumberOrUserId, accountNumber, docType, creationDate, null); + var resultPayload = result.Payload; + + Assert.IsFalse(result.Success); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + } + + [Test] + public async Task DeterminePrimaryOwnerAttributeByMemberNumberOrUserId_AgreementNotFound_Failure() + { + var memberNumberOrUserId = "1234"; + var accountNumber = "9999"; + var docType = "LVI_LT_106_01"; + var creationDate = new DateTime(2022, 01, 01); + var accountOwnership = new List + { + new() + { + PersonNumber = 1, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + IsPrimaryOwner = true + } + }; + + _mockCoreApiWrapperService.Setup(x => x.GetOwnersByAccountNumber(accountNumber, creationDate.ToShortDateString())).ReturnsAsync(accountOwnership); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(memberNumberOrUserId, accountNumber, docType, creationDate, null); + var resultPayload = result.Payload; + + Assert.IsFalse(result.Success); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Once); + } + + [Test] + public async Task DeterminePrimaryOwnerAttributeByMemberNumberOrUserId_PersonNumberDoesNotMatch_MM_STMXT_Failure() + { + + var memberNumberOrUserId = "M1234"; + var accountNumber = "9999"; + var docType = "MM_STMXT"; + var creationDate = new DateTime(2022, 01, 01); + var accountOwnership = new List + { + new() + { + PersonNumber = 1, + FirstName = "Bill", + MiddleInitial = "B", + LastName = "Billson", + IsPrimaryOwner = true + } + }; + + var personOrganization = new PersonOrganization() + { + PersonNumber = "2", + OrganizationNumber = null + }; + + var agreementAccount = new AgreementAccount() + { + AccountNumber = 9999, + AccountDescription = "PREMIUM CHECKING", + MajorAccountTypeCode = "CK", + TaxReportForPersonNumber = 5678, + TaxReportForOrgNumber = null, + OvrDeliveryMethCD = "PRNT", + AccountOwner = new AgreementAccountOwner + { + AccountNumber = 9999, + AgreementNumber = 0, + UserId = null, + PersonNumber = 0 + } + }; + + _mockCoreApiWrapperService.Setup(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny())).ReturnsAsync(personOrganization).Verifiable(); + _mockCoreApiWrapperService.Setup(x => x.GetAgreementAccountByAccountId(It.IsAny())).ReturnsAsync(agreementAccount); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(memberNumberOrUserId, + accountNumber, + docType, + creationDate, + null); + + Assert.IsFalse(result.Success); + _mockCoreApiWrapperService.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + } + + [Test] + public async Task DeterminePrimaryOwnerAttributeByMemberNumberOrUserId_Success_Agreement() + { + var memberNumberOrUserId = Guid.NewGuid().ToString(); + var agreement = new Agreement() + { + UserId = memberNumberOrUserId, + AgreementNumber = 123, + ByOrgNbr = 0, + FirstName = Guid.NewGuid().ToString(), + MiddleInitial = Guid.NewGuid().ToString(), + LastName = Guid.NewGuid().ToString(), + Suffix = Guid.NewGuid().ToString(), + PersonNumber = 1234 + }; + + var entityName = $"{agreement.FirstName} {agreement.MiddleInitial} {agreement.LastName} {agreement.Suffix}"; + + _mockCoreApiWrapperService.Setup(x => x.GetAgreementByUserId(It.IsAny())).ReturnsAsync(agreement).Verifiable(); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(memberNumberOrUserId, + entityName, + null); + var resultPayload = result.Payload; + + Assert.True(result.Success); + Assert.AreEqual(agreement.PersonNumber.ToString(), resultPayload.PersonNumber); + Assert.IsNull(resultPayload.OrganizationNumber); + Assert.IsNull(resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Once); + } + + + [Test] + public async Task DeterminePrimaryOwnerAttributeByMemberNumberOrUserId_Success_Agreement_NoAgreement() + { + var memberNumberOrUserId = Guid.NewGuid().ToString(); + var entityName = $"{Guid.NewGuid().ToString()} {Guid.NewGuid().ToString()} {Guid.NewGuid().ToString()} {Guid.NewGuid().ToString()}"; + Agreement nullAgreement = null; + var personOrganization = new PersonOrganization() + { + PersonNumber = DateTime.Now.Millisecond.ToString(), + OrganizationNumber = null, + EntityName = entityName + }; + + _mockCoreApiWrapperService.Setup(x => x.GetAgreementByUserId(It.IsAny())).ReturnsAsync(nullAgreement).Verifiable(); + _mockCoreApiWrapperService.Setup(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny())).ReturnsAsync(personOrganization).Verifiable(); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(memberNumberOrUserId, + entityName, + null); + var resultPayload = result.Payload; + + Assert.True(result.Success); + Assert.AreEqual(personOrganization.PersonNumber, resultPayload.PersonNumber); + Assert.IsNull(resultPayload.OrganizationNumber); + Assert.IsNull(resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny()), Times.Once); + } + + [Test] + public async Task DeterminePrimaryOwnerAttributeByMemberNumberOrUserId_Success_PersonOrganization_PersonNumber() + { + var memberNumberOrUserId = $"M{Guid.NewGuid().ToString()}"; + var entityName = $"{Guid.NewGuid().ToString()} {Guid.NewGuid().ToString()} {Guid.NewGuid().ToString()} {Guid.NewGuid().ToString()}"; + + var personOrganization = new PersonOrganization() + { + PersonNumber = DateTime.Now.Millisecond.ToString(), + OrganizationNumber = null, + EntityName = entityName + }; + + _mockCoreApiWrapperService.Setup(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny())).ReturnsAsync(personOrganization).Verifiable(); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(memberNumberOrUserId, + entityName, + null); + var resultPayload = result.Payload; + + Assert.True(result.Success); + Assert.AreEqual(personOrganization.PersonNumber, resultPayload.PersonNumber); + Assert.IsNull(resultPayload.OrganizationNumber); + Assert.IsNull(resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + } + + [Test] + public async Task DeterminePrimaryOwnerAttributeByMemberNumberOrUserId_Success_PersonOrganization_OrganizationNumber() + { + var memberNumberOrUserId = $"M{Guid.NewGuid().ToString()}"; + var entityName = $"{Guid.NewGuid().ToString()} {Guid.NewGuid().ToString()} {Guid.NewGuid().ToString()} {Guid.NewGuid().ToString()}"; + + var personOrganization = new PersonOrganization + { + PersonNumber = null, + OrganizationNumber = DateTime.Now.Millisecond.ToString(), + EntityName = entityName + }; + + _mockCoreApiWrapperService.Setup(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny())).ReturnsAsync(personOrganization).Verifiable(); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(memberNumberOrUserId, + entityName, + null); + var resultPayload = result.Payload; + + Assert.True(result.Success); + Assert.AreEqual(personOrganization.OrganizationNumber, resultPayload.OrganizationNumber); + Assert.IsNull(resultPayload.PersonNumber); + Assert.IsNull(resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + } + + [Test] + public async Task DeterminePrimaryOwnerAttributeByMemberNumberOrUserId_Failure_PersonOrganization_IsNull() + { + var memberNumberOrUserId = $"M{Guid.NewGuid().ToString()}"; + var entityName = $"{Guid.NewGuid().ToString()} {Guid.NewGuid().ToString()} {Guid.NewGuid().ToString()} {Guid.NewGuid().ToString()}"; + + var personOrganization = new PersonOrganization + { + PersonNumber = null, + OrganizationNumber = null, + EntityName = entityName + }; + + _mockCoreApiWrapperService.Setup(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny())).ReturnsAsync(personOrganization).Verifiable(); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(memberNumberOrUserId, + entityName, + null); + var resultPayload = result.Payload; + + Assert.False(result.Success); + Assert.IsNull(resultPayload.OrganizationNumber); + Assert.IsNull(resultPayload.PersonNumber); + Assert.IsNull(resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + } + + [Test] + public async Task DeterminePrimaryOwnerAttributeByMemberNumberOrUserId_Failure_PersonOrganization_EntityNameDoesNotMatch() + { + var memberNumberOrUserId = $"M{Guid.NewGuid().ToString()}"; + var entityName = $"{Guid.NewGuid().ToString()} {Guid.NewGuid().ToString()} {Guid.NewGuid().ToString()} {Guid.NewGuid().ToString()}"; + + var personOrganization = new PersonOrganization + { + PersonNumber = null, + OrganizationNumber = DateTime.Now.Millisecond.ToString(), + EntityName = Guid.NewGuid().ToString() + }; + + _mockCoreApiWrapperService.Setup(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny())).ReturnsAsync(personOrganization).Verifiable(); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(memberNumberOrUserId, + entityName, + null); + + Assert.False(result.Success); + _mockCoreApiWrapperService.Verify(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + } + + [Test] + public async Task DeterminePrimaryOwnerAttributeByMemberNumberOrUserId_Failure_PersonOrganization_Exception() + { + var memberNumberOrUserId = $"M{Guid.NewGuid().ToString()}"; + var entityName = $"{Guid.NewGuid().ToString()} {Guid.NewGuid().ToString()} {Guid.NewGuid().ToString()} {Guid.NewGuid().ToString()}"; + + _mockCoreApiWrapperService.Setup(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny())) + .ThrowsAsync(new ServiceException("Test")).Verifiable(); + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(memberNumberOrUserId, + entityName, + null); + + Assert.IsFalse(result.Success); + _mockCoreApiWrapperService.Verify(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + } + + [Test] + public async Task DeterminePrimaryOwnerAttributeByMemberNumberOrUserId_Success_PersonOrganization_OwnerOverride() + { + var memberNumberOrUserId = $"M{Guid.NewGuid().ToString()}"; + var entityName = $"{Guid.NewGuid().ToString()} {Guid.NewGuid().ToString()} {Guid.NewGuid().ToString()} {Guid.NewGuid().ToString()}"; + + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = DateTime.Now.Millisecond + }; + + var ownerOverrideInfo = new OwnerOverrideInfo() + { + DocumentProcessingInfoId = documentProcessingInfo.DocumentProcessingInfoId, + EntityType = EntityTypes.Organization, + EntityId = Guid.NewGuid().ToString(), + UserName = Guid.NewGuid().ToString() + }; + + var result = await _primaryOwnerDeterminingService.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(memberNumberOrUserId, + entityName, + ownerOverrideInfo); + var resultPayload = result.Payload; + + Assert.True(result.Success); + Assert.AreEqual(ownerOverrideInfo.EntityId, resultPayload.OrganizationNumber); + Assert.IsNull(resultPayload.PersonNumber); + Assert.IsNull(resultPayload.AccountNumber); + _mockCoreApiWrapperService.Verify(x => x.GetPersonOrOrganizationNumberByMemberId(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessingInfoServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessingInfoServiceTest.cs new file mode 100644 index 0000000..e362126 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessingInfoServiceTest.cs @@ -0,0 +1,957 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestorLib.Repositories; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; + +namespace LCU.API.Internal.DocumentIngestorTests.Services; + +public class DocumentProcessingInfoServiceTest +{ + private DocumentProcessingInfoService _documentProcessingInfoService; + private Mock _unitOfWork; + private Mock _mockDocumentProcessingInfoRepository; + private Mock _mockProcessingLogService; + + [SetUp] + public void Setup() + { + _unitOfWork = new Mock(); + _mockDocumentProcessingInfoRepository = new Mock(); + _mockProcessingLogService = new Mock(); + _documentProcessingInfoService = new DocumentProcessingInfoService(_unitOfWork.Object, _mockDocumentProcessingInfoRepository.Object, _mockProcessingLogService.Object); + } + + [Test] + public async Task GetAsync_DocumentProcessingInfos_Returned() + { + var ingestorRunInfoId = Guid.NewGuid(); + var id = 1; + var documentProcessingInfos = new List() + { + new DocumentProcessingInfo() + { + DocumentProcessingInfoId = id, + IngestorRunInfoId = ingestorRunInfoId + } + }; + _mockDocumentProcessingInfoRepository.Setup(x => x.FindAsync()).ReturnsAsync(documentProcessingInfos); + var result = await _documentProcessingInfoService.GetAsync(); + Assert.IsNotNull(result); + Assert.AreEqual(1, result.Count()); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindAsync(), Times.Once); + } + + [Test] + public void GetAsync_Exception() + { + _mockDocumentProcessingInfoRepository.Setup(x => x.FindAsync()).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _documentProcessingInfoService.GetAsync()); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindAsync(), Times.Once); + } + + [Test] + public async Task GetByIdAsync_DocumentProcessingInfo_Returned() + { + var ingestorRunInfoId = Guid.NewGuid(); + var id = 1; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = id, + IngestorRunInfoId = ingestorRunInfoId + }; + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIdAsync(id)).ReturnsAsync(documentProcessingInfo); + var result = await _documentProcessingInfoService.GetByIdAsync(id); + Assert.IsNotNull(result); + Assert.AreEqual(ingestorRunInfoId, result.IngestorRunInfoId); + Assert.AreEqual(id, result.DocumentProcessingInfoId); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public void GetByIdAsync_Exception() + { + var id = 1; + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIdAsync(id)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _documentProcessingInfoService.GetByIdAsync(id)); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task GetByIngestorRunInfoIdAsync_DocumentProcessingInfos_Returned() + { + var ingestorRunInfoId = Guid.NewGuid(); + var id = 1; + var documentProcessingInfos = new List() + { + new DocumentProcessingInfo() + { + DocumentProcessingInfoId = id, + IngestorRunInfoId = ingestorRunInfoId + } + }; + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIngestorRunInfoIdAsync(ingestorRunInfoId)).ReturnsAsync(documentProcessingInfos); + var result = await _documentProcessingInfoService.GetByIngestorRunInfoIdAsync(ingestorRunInfoId); + Assert.IsNotNull(result); + Assert.AreEqual(1, result.Count()); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIngestorRunInfoIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public void GetByIngestorRunInfoIdAsync_Exception() + { + var ingestorRunInfoId = Guid.NewGuid(); + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIngestorRunInfoIdAsync(ingestorRunInfoId)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _documentProcessingInfoService.GetByIngestorRunInfoIdAsync(ingestorRunInfoId)); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIngestorRunInfoIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task SaveAsync_DocumentProcessingInfo_Returned() + { + var ingestorRunInfoId = Guid.NewGuid(); + var id = 1; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = id, + IngestorRunInfoId = ingestorRunInfoId + }; + _mockDocumentProcessingInfoRepository.Setup(x => x.AddAsync(documentProcessingInfo)).ReturnsAsync(documentProcessingInfo); + var result = await _documentProcessingInfoService.SaveAsync(documentProcessingInfo); + Assert.IsNotNull(result); + Assert.AreEqual(ingestorRunInfoId, result.IngestorRunInfoId); + Assert.AreEqual(id, result.DocumentProcessingInfoId); + _mockDocumentProcessingInfoRepository.Verify(x => x.AddAsync(It.IsAny()), Times.Once); + } + + [Test] + public void SaveAsync_Exception() + { + var ingestorRunInfoId = Guid.NewGuid(); + var id = 1; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = id, + IngestorRunInfoId = ingestorRunInfoId + }; + _mockDocumentProcessingInfoRepository.Setup(x => x.AddAsync(documentProcessingInfo)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _documentProcessingInfoService.SaveAsync(documentProcessingInfo)); + _mockDocumentProcessingInfoRepository.Verify(x => x.AddAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task Update_DocumentProcessingInfo_Returned() + { + var ingestorRunInfoId = Guid.NewGuid(); + var id = 1; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = id, + IngestorRunInfoId = ingestorRunInfoId + }; + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIdAsync(id)).ReturnsAsync(documentProcessingInfo); + _mockDocumentProcessingInfoRepository.Setup(x => x.Update(documentProcessingInfo)); + + var result = await _documentProcessingInfoService.Update(documentProcessingInfo); + Assert.IsNotNull(result); + Assert.AreEqual(ingestorRunInfoId, result.IngestorRunInfoId); + Assert.AreEqual(id, result.DocumentProcessingInfoId); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockDocumentProcessingInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Once); + } + + [Test] + public void Update_FindByIdAsync_ThrowsException() + { + var ingestorRunInfoId = Guid.NewGuid(); + var id = 1; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = id, + IngestorRunInfoId = ingestorRunInfoId + }; + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIdAsync(id)).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _documentProcessingInfoService.Update(documentProcessingInfo)); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockDocumentProcessingInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Never); + } + + [Test] + public void Update_Update_ThrowsException() + { + var ingestorRunInfoId = Guid.NewGuid(); + var id = 1; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = id, + IngestorRunInfoId = ingestorRunInfoId + }; + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIdAsync(id)).ReturnsAsync(documentProcessingInfo); + _mockDocumentProcessingInfoRepository.Setup(x => x.Update(documentProcessingInfo)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _documentProcessingInfoService.Update(documentProcessingInfo)); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockDocumentProcessingInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Once); + } + + [Test] + public async Task UpdateStatusAndAddLog_ById_SingleLog_Returned() + { + var ingestorRunInfoId = Guid.NewGuid(); + var id = 1; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = id, + IngestorRunInfoId = ingestorRunInfoId + }; + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIdAsync(id)).ReturnsAsync(documentProcessingInfo); + _mockDocumentProcessingInfoRepository.Setup(x => x.Update(documentProcessingInfo)); + + var processingLog = new ProcessingLog() + { + DocumentProcessingInfoId = id, + LogTimeStamp = Convert.ToDateTime("1/1/2022"), + LogMessage = "Account fail", + UserName = "User" + + }; + _mockProcessingLogService.Setup(x => x.SaveAsync(It.IsAny())).ReturnsAsync(processingLog); + + var result = await _documentProcessingInfoService.UpdateStatusAndAddLog(id, ProcessStatusTypes.DataMappingFailure, "Account fail", "User"); + Assert.IsNotNull(result); + Assert.AreEqual(ingestorRunInfoId, result.IngestorRunInfoId); + Assert.AreEqual(id, result.DocumentProcessingInfoId); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(id), Times.Exactly(2)); + _mockDocumentProcessingInfoRepository.Verify(x => x.Update(documentProcessingInfo), Times.Once); + _mockProcessingLogService.Verify(x => x.SaveAsync(It.IsAny()), Times.Once); + } + + [Test] + public void UpdateStatusAndAddLog_ById_SingleLog_FindByIdAsync_ThrowsException() + { + var ingestorRunInfoId = Guid.NewGuid(); + var id = 1; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = id, + IngestorRunInfoId = ingestorRunInfoId + }; + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIdAsync(id)).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _documentProcessingInfoService.UpdateStatusAndAddLog(id, ProcessStatusTypes.DataMappingFailure, "Account fail", "User")); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(id), Times.Once); + _mockDocumentProcessingInfoRepository.Verify(x => x.Update(documentProcessingInfo), Times.Never); + _mockProcessingLogService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + } + + [Test] + public void UpdateStatusAndAddLog_ById_SingleLog_Update_ThrowsException() + { + var ingestorRunInfoId = Guid.NewGuid(); + var id = 1; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = id, + IngestorRunInfoId = ingestorRunInfoId + }; + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIdAsync(id)).ReturnsAsync(documentProcessingInfo); + _mockDocumentProcessingInfoRepository.Setup(x => x.Update(documentProcessingInfo)).Throws(new Exception("Error")); ; + + var processingLog = new ProcessingLog() + { + DocumentProcessingInfoId = id, + LogTimeStamp = Convert.ToDateTime("1/1/2022"), + LogMessage = "Account fail" + + }; + _mockProcessingLogService.Setup(x => x.SaveAsync(It.IsAny())).ReturnsAsync(processingLog); + + Assert.ThrowsAsync(async () => await _documentProcessingInfoService.UpdateStatusAndAddLog(id, ProcessStatusTypes.DataMappingFailure, "Account fail", "User")); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(id), Times.Exactly(2)); + _mockDocumentProcessingInfoRepository.Verify(x => x.Update(documentProcessingInfo), Times.Once); + _mockProcessingLogService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + } + + [Test] + public async Task UpdateStatusAndAddLog_ById_TwoLog_Returned() + { + var ingestorRunInfoId = Guid.NewGuid(); + var id = 1; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = id, + IngestorRunInfoId = ingestorRunInfoId + }; + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIdAsync(id)).ReturnsAsync(documentProcessingInfo); + _mockDocumentProcessingInfoRepository.Setup(x => x.Update(documentProcessingInfo)); + + var processingLog = new ProcessingLog() + { + DocumentProcessingInfoId = id, + LogTimeStamp = Convert.ToDateTime("1/1/2022"), + LogMessage = "Account fail", + UserName = "User" + }; + _mockProcessingLogService.Setup(x => x.SaveAsync(It.IsAny())).ReturnsAsync(processingLog); + + var logMessages = new List() + { + "Account fail", + "Name fail" + }; + + var result = await _documentProcessingInfoService.UpdateStatusAndAddLog(id, ProcessStatusTypes.DataMappingFailure, logMessages, "User"); + Assert.IsNotNull(result); + Assert.AreEqual(ingestorRunInfoId, result.IngestorRunInfoId); + Assert.AreEqual(id, result.DocumentProcessingInfoId); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(id), Times.Exactly(2)); + _mockDocumentProcessingInfoRepository.Verify(x => x.Update(documentProcessingInfo), Times.Once); + _mockProcessingLogService.Verify(x => x.SaveAsync(It.IsAny()), Times.Exactly(2)); + } + + [Test] + public void UpdateStatusAndAddLog_ById_TwoLog_FindByIdAsync_ThrowsException() + { + var ingestorRunInfoId = Guid.NewGuid(); + var id = 1; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = id, + IngestorRunInfoId = ingestorRunInfoId + }; + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIdAsync(id)).ThrowsAsync(new Exception("Error")); + + var logMessages = new List() + { + "Account fail", + "Name fail" + }; + Assert.ThrowsAsync(async () => await _documentProcessingInfoService.UpdateStatusAndAddLog(id, + ProcessStatusTypes.DataMappingFailure, + logMessages, + "User")); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(id), Times.Once); + _mockDocumentProcessingInfoRepository.Verify(x => x.Update(documentProcessingInfo), Times.Never); + _mockProcessingLogService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + } + + [Test] + public void UpdateStatusAndAddLog_ById_TwoLog_Update_ThrowsException() + { + var ingestorRunInfoId = Guid.NewGuid(); + var id = 1; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = id, + IngestorRunInfoId = ingestorRunInfoId + }; + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIdAsync(id)).ReturnsAsync(documentProcessingInfo); + _mockDocumentProcessingInfoRepository.Setup(x => x.Update(documentProcessingInfo)).Throws(new Exception("Error")); ; + + var processingLog = new ProcessingLog() + { + DocumentProcessingInfoId = id, + LogTimeStamp = Convert.ToDateTime("1/1/2022"), + LogMessage = "Account fail" + + }; + _mockProcessingLogService.Setup(x => x.SaveAsync(It.IsAny())).ReturnsAsync(processingLog); + + var logMessages = new List() + { + "Account fail", + "Name fail" + }; + Assert.ThrowsAsync(async () => await _documentProcessingInfoService.UpdateStatusAndAddLog(id, + ProcessStatusTypes.DataMappingFailure, + logMessages, + "User")); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(id), Times.Exactly(2)); + _mockDocumentProcessingInfoRepository.Verify(x => x.Update(documentProcessingInfo), Times.Once); + _mockProcessingLogService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + } + + [Test] + public async Task UpdateStatusAndAddLog_Returned() + { + var ingestorRunInfoId = Guid.NewGuid(); + var id = 1; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = id, + IngestorRunInfoId = ingestorRunInfoId + }; + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIdAsync(id)).ReturnsAsync(documentProcessingInfo); + _mockDocumentProcessingInfoRepository.Setup(x => x.Update(documentProcessingInfo)); + + var processingLog = new ProcessingLog() + { + DocumentProcessingInfoId = id, + LogTimeStamp = Convert.ToDateTime("1/1/2022"), + LogMessage = "Account fail", + UserName = "User" + }; + _mockProcessingLogService.Setup(x => x.SaveAsync(It.IsAny())).ReturnsAsync(processingLog); + + var result = await _documentProcessingInfoService.UpdateStatusAndAddLog(documentProcessingInfo, + ProcessStatusTypes.DataMappingFailure, + "Account fail", + "User"); + Assert.IsNotNull(result); + Assert.AreEqual(ingestorRunInfoId, result.IngestorRunInfoId); + Assert.AreEqual(id, result.DocumentProcessingInfoId); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(id), Times.Once); + _mockDocumentProcessingInfoRepository.Verify(x => x.Update(documentProcessingInfo), Times.Once); + _mockProcessingLogService.Verify(x => x.SaveAsync(It.IsAny()), Times.Once); + } + + [Test] + public void UpdateStatusAndAddLog_FindByIdAsync_ThrowsException() + { + var ingestorRunInfoId = Guid.NewGuid(); + var id = 1; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = id, + IngestorRunInfoId = ingestorRunInfoId + }; + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIdAsync(id)).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _documentProcessingInfoService.UpdateStatusAndAddLog(documentProcessingInfo, + ProcessStatusTypes.DataMappingFailure, + "Account fail", + "User")); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(id), Times.Once); + _mockDocumentProcessingInfoRepository.Verify(x => x.Update(documentProcessingInfo), Times.Never); + _mockProcessingLogService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + } + + [Test] + public void UpdateStatusAndAddLog_Update_ThrowsException() + { + var ingestorRunInfoId = Guid.NewGuid(); + var id = 1; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = id, + IngestorRunInfoId = ingestorRunInfoId + }; + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIdAsync(id)).ReturnsAsync(documentProcessingInfo); + _mockDocumentProcessingInfoRepository.Setup(x => x.Update(documentProcessingInfo)).Throws(new Exception("Error")); ; + + var processingLog = new ProcessingLog() + { + DocumentProcessingInfoId = id, + LogTimeStamp = Convert.ToDateTime("1/1/2022"), + LogMessage = "Account fail", + UserName = "User" + }; + _mockProcessingLogService.Setup(x => x.SaveAsync(It.IsAny())).ReturnsAsync(processingLog); + + Assert.ThrowsAsync(async () => await _documentProcessingInfoService.UpdateStatusAndAddLog(documentProcessingInfo, + ProcessStatusTypes.DataMappingFailure, + "Account fail", + "User")); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(id), Times.Once); + _mockDocumentProcessingInfoRepository.Verify(x => x.Update(documentProcessingInfo), Times.Once); + _mockProcessingLogService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + } + + [Test] + public async Task Delete_Success() + { + var ingestorRunInfoId = Guid.NewGuid(); + var id = 1; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = id, + IngestorRunInfoId = ingestorRunInfoId + }; + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIdAsync(id)).ReturnsAsync(documentProcessingInfo); + _mockDocumentProcessingInfoRepository.Setup(x => x.Remove(documentProcessingInfo)); + + await _documentProcessingInfoService.Delete(id); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockDocumentProcessingInfoRepository.Verify(x => x.Remove(It.IsAny()), Times.Once); + } + + [Test] + public void Delete_FindByIdAsync_ThrowsException() + { + var ingestorRunInfoId = Guid.NewGuid(); + var id = 1; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = id, + IngestorRunInfoId = ingestorRunInfoId + }; + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIdAsync(id)).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _documentProcessingInfoService.Delete(id)); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockDocumentProcessingInfoRepository.Verify(x => x.Remove(It.IsAny()), Times.Never); + } + + [Test] + public void Delete_Remove_ThrowsException() + { + var ingestorRunInfoId = Guid.NewGuid(); + var id = 1; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = id, + IngestorRunInfoId = ingestorRunInfoId + }; + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIdAsync(id)).ReturnsAsync(documentProcessingInfo); + _mockDocumentProcessingInfoRepository.Setup(x => x.Remove(documentProcessingInfo)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _documentProcessingInfoService.Delete(id)); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockDocumentProcessingInfoRepository.Verify(x => x.Remove(It.IsAny()), Times.Once); + } + + [Test] + public async Task FilterPaged_Ok() + { + var pagedDocumentProcessingInfoResult = new PagedResult(); + + var filter = new Filter() + { + Page = 1, + Limit = 2, + StatusFilters = null, + SortableFields = null, + DocBusinessName = "EAgreement" + }; + + _mockDocumentProcessingInfoRepository.Setup(repo => repo.FilteredListAsync(filter)) + .ReturnsAsync(pagedDocumentProcessingInfoResult).Verifiable(); + + // Act + var result = await _documentProcessingInfoService.GetFilteredDocumentProcessingInfo(filter); + + // Assert + Assert.NotNull(result); + Assert.AreEqual(pagedDocumentProcessingInfoResult, result); + } + + [Test] + public async Task CountCompletedFirstPassByIngestorRunInfoIdAsync_RepositoryReturnsCount_ReturnsCount() + { + var runId = Guid.NewGuid(); + var count = DateTime.Now.Millisecond; + _mockDocumentProcessingInfoRepository + .Setup(r => r.CountCompletedFirstPassByIngestorRunInfoIdAsync(runId)) + .ReturnsAsync(count); + + var actualCount = await _documentProcessingInfoService.CountCompletedFirstPassByIngestorRunInfoIdAsync(runId); + + Assert.AreEqual(count, actualCount); + } + + [Test] + public void CountCompletedFirstPassByIngestorRunInfoIdAsync_RepositoryThrows_ThrowsServiceException() + { + var runId = Guid.NewGuid(); + _mockDocumentProcessingInfoRepository + .Setup(r => r.CountCompletedFirstPassByIngestorRunInfoIdAsync(runId)) + .ThrowsAsync(new Exception()); + + Assert.ThrowsAsync(() => _documentProcessingInfoService.CountCompletedFirstPassByIngestorRunInfoIdAsync(runId)); + } + + + [Test] + public async Task SetDocumentsToEntityUnknown_Success() + { + var ids = new List() { 1, 2, 3 }; + var documentProcessingInfos = new List() + { + new() + { + DocumentProcessingInfoId = ids[0], + }, + new() + { + DocumentProcessingInfoId = ids[1], + }, + new() + { + DocumentProcessingInfoId = ids[2], + } + }; + var request = new EntityUnknownRequest() + { + UserName = "System", + DocumentProcessingInfoIds = documentProcessingInfos.Select(x => x.DocumentProcessingInfoId).ToList() + }; + var processingLog = new ProcessingLog() + { + DocumentProcessingInfoId = 1, + LogMessage = "Log test", + LogTimeStamp = DateTime.Now, + UserName = "System" + }; + + _mockDocumentProcessingInfoRepository.Setup(x => x.FindListByIdAsync(ids)).ReturnsAsync(documentProcessingInfos); + _mockDocumentProcessingInfoRepository.SetupSequence(x => x.FindByIdAsync(It.IsAny())).ReturnsAsync(documentProcessingInfos[0]) + .ReturnsAsync(documentProcessingInfos[1]) + .ReturnsAsync(documentProcessingInfos[2]); + _mockDocumentProcessingInfoRepository.Setup(x => x.Update(It.IsAny())); + _mockProcessingLogService.Setup(x => x.SaveAsync(It.IsAny())).ReturnsAsync(() => processingLog); + + var result = await _documentProcessingInfoService.SetDocumentsToEntityUnknown(request); + var trueCount = result.Where(x => x.EntityUnknown).ToList().Count(); + Assert.IsNotNull(result); + Assert.AreEqual(documentProcessingInfos.Count, result.Count()); + Assert.AreEqual(documentProcessingInfos.Count(), trueCount); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindListByIdAsync(It.IsAny>()), Times.Once); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Exactly(3)); + _mockDocumentProcessingInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Exactly(3)); + _mockProcessingLogService.Verify(x => x.SaveAsync(It.IsAny()), Times.Exactly(3)); + } + + [Test] + public async Task SetDocumentsToEntityUnknown_ThrowsException_Failure() + { + var ids = new List() { 1, 2, 3 }; + var documentProcessingInfos = new List() + { + new() + { + DocumentProcessingInfoId = ids[0], + }, + new() + { + DocumentProcessingInfoId = ids[1], + }, + new() + { + DocumentProcessingInfoId = ids[2], + } + }; + var request = new EntityUnknownRequest() + { + UserName = "System", + DocumentProcessingInfoIds = documentProcessingInfos.Select(x => x.DocumentProcessingInfoId).ToList() + }; + var processingLog = new ProcessingLog() + { + DocumentProcessingInfoId = 1, + LogMessage = "Log test", + LogTimeStamp = DateTime.Now, + UserName = "System" + }; + + _mockDocumentProcessingInfoRepository.Setup(x => x.FindListByIdAsync(ids)).ReturnsAsync(documentProcessingInfos); + _mockDocumentProcessingInfoRepository.SetupSequence(x => x.FindByIdAsync(It.IsAny())).ReturnsAsync(documentProcessingInfos[0]) + .ReturnsAsync(documentProcessingInfos[1]) + .ReturnsAsync(documentProcessingInfos[2]); + _mockDocumentProcessingInfoRepository.Setup(x => x.Update(It.IsAny())); + _mockProcessingLogService.Setup(x => x.SaveAsync(It.IsAny())).ReturnsAsync(() => processingLog); + + _mockProcessingLogService.Setup(x => x.SaveAsync(It.IsAny())).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _documentProcessingInfoService.SetDocumentsToEntityUnknown(request)); + + _mockDocumentProcessingInfoRepository.Verify(x => x.FindListByIdAsync(It.IsAny>()), Times.Once); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Never); + _mockDocumentProcessingInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Never); + _mockProcessingLogService.Verify(x => x.SaveAsync(It.IsAny()), Times.Once); + } + + // + + [Test] + public async Task UpdateDocumentProcessingInfoStatus_Success() + { + var documentProcessingInfoId = DateTime.Now.Millisecond; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = documentProcessingInfoId, + StatusType = ProcessStatusTypes.ArchiveFailure + }; + var request = new DocumentProcessingInfoStatusRequest() + { + DocumentProcessingInfoId = documentProcessingInfoId, + ProcessStatus = ProcessStatusTypes.Reprocessing, + ReasonMessage = Guid.NewGuid().ToString(), + Username = Guid.NewGuid().ToString() + }; + var processingLog = new ProcessingLog() + { + DocumentProcessingInfoId = documentProcessingInfoId, + LogMessage = request.ReasonMessage, + LogTimeStamp = DateTime.Now, + UserName = request.Username + }; + + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIdAsync(documentProcessingInfoId)).ReturnsAsync(documentProcessingInfo); + _mockDocumentProcessingInfoRepository.Setup(x => x.Update(It.IsAny())); + _mockProcessingLogService.Setup(x => x.SaveAsync(It.IsAny())).ReturnsAsync(() => processingLog); + + var result = await _documentProcessingInfoService.UpdateDocumentProcessingInfoStatus(request); + Assert.IsNotNull(result); + Assert.AreEqual(result?.StatusType, request.ProcessStatus); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Exactly(2)); + _mockDocumentProcessingInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Once); + _mockProcessingLogService.Verify(x => x.SaveAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task UpdateDocumentProcessingInfoStatus_ThrowsException_Failure() + { + var documentProcessingInfoId = DateTime.Now.Millisecond; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = documentProcessingInfoId, + StatusType = ProcessStatusTypes.ArchiveFailure + }; + var request = new DocumentProcessingInfoStatusRequest() + { + DocumentProcessingInfoId = documentProcessingInfoId, + ProcessStatus = ProcessStatusTypes.Reprocessing, + ReasonMessage = Guid.NewGuid().ToString(), + Username = Guid.NewGuid().ToString() + }; + + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIdAsync(documentProcessingInfoId)).ReturnsAsync(documentProcessingInfo); + _mockDocumentProcessingInfoRepository.Setup(x => x.Update(It.IsAny())).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _documentProcessingInfoService.UpdateDocumentProcessingInfoStatus(request)); + + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Exactly(2)); + _mockDocumentProcessingInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Once); + _mockProcessingLogService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + } + + [Test] + public async Task UpdateDocumentProcessingInfoStatus_RejectedStatus_Failure() + { + var documentProcessingInfoId = DateTime.Now.Millisecond; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = documentProcessingInfoId, + StatusType = ProcessStatusTypes.Completed + }; + var request = new DocumentProcessingInfoStatusRequest() + { + DocumentProcessingInfoId = documentProcessingInfoId, + ProcessStatus = ProcessStatusTypes.Reprocessing, + ReasonMessage = Guid.NewGuid().ToString(), + Username = Guid.NewGuid().ToString() + }; + + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIdAsync(documentProcessingInfoId)).ReturnsAsync(documentProcessingInfo); + + Assert.ThrowsAsync(async () => await _documentProcessingInfoService.UpdateDocumentProcessingInfoStatus(request)); + + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockDocumentProcessingInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Never); + _mockProcessingLogService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + } + + [Test] + public async Task UpdateDocumentProcessingInfoStatus_SameStatus_Failure() + { + var documentProcessingInfoId = DateTime.Now.Millisecond; + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = documentProcessingInfoId, + StatusType = ProcessStatusTypes.Reprocessing + }; + var request = new DocumentProcessingInfoStatusRequest() + { + DocumentProcessingInfoId = documentProcessingInfoId, + ProcessStatus = ProcessStatusTypes.Reprocessing, + ReasonMessage = Guid.NewGuid().ToString(), + Username = Guid.NewGuid().ToString() + }; + + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByIdAsync(documentProcessingInfoId)).ReturnsAsync(documentProcessingInfo); + + Assert.ThrowsAsync(async () => await _documentProcessingInfoService.UpdateDocumentProcessingInfoStatus(request)); + + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockDocumentProcessingInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Never); + _mockProcessingLogService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + } + + [Test] + public async Task GetByDocumentIdsAsync_RepositoryReturnsInfoForId_InfoAtIdKey() + { + var ids = Enumerable.Repeat(Guid.NewGuid, 5) + .Select(f => f()) + .ToArray(); + var info = new DocumentProcessingInfo + { + DocumentId = ids[2] + }; + _mockDocumentProcessingInfoRepository + .Setup(dpir => dpir.FindByDocumentIdsAsync(ids)) + .ReturnsAsync(new[] { info }); + + var infoById = await _documentProcessingInfoService.GetByDocumentIdsAsync(ids); + + Assert.AreSame(infoById[info.DocumentId.Value], info); + } + + [Test] + public async Task GetByDocumentIdsAsync_RepositoryDoesNotReturnInfoForId_NullAtIdKey() + { + var ids = Enumerable.Repeat(Guid.NewGuid, 5) + .Select(f => f()) + .ToArray(); + var info = new DocumentProcessingInfo + { + DocumentId = ids[2] + }; + _mockDocumentProcessingInfoRepository + .Setup(dpir => dpir.FindByDocumentIdsAsync(ids)) + .ReturnsAsync(Array.Empty()); + + var infoById = await _documentProcessingInfoService.GetByDocumentIdsAsync(ids); + + Assert.IsNull(infoById[info.DocumentId.Value]); + } + + [Test] + public async Task GetByDocumentIdsAsync_RepositoryThrowsException_ThrowsServiceException() + { + var ids = Enumerable.Repeat(Guid.NewGuid, 5) + .Select(f => f()) + .ToArray(); + _mockDocumentProcessingInfoRepository + .Setup(dpir => dpir.FindByDocumentIdsAsync(ids)) + .ThrowsAsync(new Exception()); + + Assert.ThrowsAsync(() => _documentProcessingInfoService.GetByDocumentIdsAsync(ids)); + } + + [Test] + public async Task GetByDocumentIdsAsync_AllCases_AllInputIdsInDictionaryKeys() + { + var ids = Enumerable.Repeat(Guid.NewGuid, 5) + .Select(f => f()) + .ToArray(); + var info = new DocumentProcessingInfo + { + DocumentId = ids[2] + }; + var otherInfo = new DocumentProcessingInfo + { + DocumentId = ids[4] + }; + _mockDocumentProcessingInfoRepository + .Setup(dpir => dpir.FindByDocumentIdsAsync(ids)) + .ReturnsAsync(new[] { info, otherInfo }); + + var infoById = await _documentProcessingInfoService.GetByDocumentIdsAsync(ids); + + CollectionAssert.AreEquivalent(ids, infoById.Keys); + } + + [Test] + public async Task GetByProcessStatusTypeAsync_Success() + { + var processStatus = ProcessStatusTypes.Processing; + + var documentProcessingInfos = GenerateDocumentProcessingInfos(); + documentProcessingInfos.ForEach(x => x.StatusType.Equals(processStatus)); + + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByProcessStatusTypeAsync(It.IsAny(), null)) + .ReturnsAsync(documentProcessingInfos).Verifiable(); + + var result = await _documentProcessingInfoService.GetByProcessStatusTypeAsync(processStatus); + + Assert.AreSame(result, documentProcessingInfos); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByProcessStatusTypeAsync(It.IsAny(), It.IsAny()), Times.Once); + + } + + [Test] + public void GetByProcessStatusType_Failure_Exception() + { + _mockDocumentProcessingInfoRepository.Setup(x => x.FindByProcessStatusTypeAsync(It.IsAny(), null)) + .ThrowsAsync(new Exception("Test")); + + Assert.ThrowsAsync(() => + _documentProcessingInfoService.GetByProcessStatusTypeAsync(It.IsAny())); + + _mockDocumentProcessingInfoRepository.Verify(x => x.FindByProcessStatusTypeAsync(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task GetCompletedFirstPassByIngestorRunInfoIdAsync_Success() + { + var ingestorRunInfoId = Guid.NewGuid(); + var documentProcessingInfos = GenerateDocumentProcessingInfos(); + documentProcessingInfos.ForEach(x => x.IngestorRunInfoId = ingestorRunInfoId); + + _mockDocumentProcessingInfoRepository.Setup(x => x.FindCompletedFirstPassByIngestorRunInfoIdAsync(It.IsAny())) + .ReturnsAsync(documentProcessingInfos).Verifiable(); + + var result = await _documentProcessingInfoService.GetCompletedFirstPassByIngestorRunInfoIdAsync(ingestorRunInfoId); + + Assert.AreSame(documentProcessingInfos, result); + _mockDocumentProcessingInfoRepository.Verify(x => x.FindCompletedFirstPassByIngestorRunInfoIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public void GetCompletedFirstPassByIngestorRunInfoIdAsync_Failure_Exception() + { + _mockDocumentProcessingInfoRepository.Setup(x => x.FindCompletedFirstPassByIngestorRunInfoIdAsync(It.IsAny())) + .ThrowsAsync(new Exception("Test")); + + Assert.ThrowsAsync(() => + _documentProcessingInfoService.GetCompletedFirstPassByIngestorRunInfoIdAsync(It.IsAny())); + + _mockDocumentProcessingInfoRepository.Verify(x => x.FindCompletedFirstPassByIngestorRunInfoIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task SaveRangeAsync_Success() + { + var documentProcessingInfos = GenerateDocumentProcessingInfos().ToArray(); + await _documentProcessingInfoService.SaveRangeAsync(documentProcessingInfos); + + _mockDocumentProcessingInfoRepository.Verify(x => x.AddRangeAsync(It.IsAny()), Times.Once()); + _unitOfWork.Verify(x => x.CompleteAsync(), Times.Once); + } + + [Test] + public void SaveRangeAsync_Failure_Exception() + { + _mockDocumentProcessingInfoRepository.Setup(x => x.AddRangeAsync(It.IsAny())) + .ThrowsAsync(new Exception("Test")); + + Assert.ThrowsAsync(() => + _documentProcessingInfoService.SaveRangeAsync(It.IsAny())); + + _mockDocumentProcessingInfoRepository.Verify(x => x.AddRangeAsync(It.IsAny()), Times.Once); + _unitOfWork.Verify(x => x.CompleteAsync(), Times.Never); + } + + private List GenerateDocumentProcessingInfos() + => new() + { + GenerateDocumentProcessingInfo(), + GenerateDocumentProcessingInfo(), + GenerateDocumentProcessingInfo() + }; + + private DocumentProcessingInfo GenerateDocumentProcessingInfo(Guid? documentId = null) + => new() + { + DocumentId = documentId ?? Guid.NewGuid() + }; +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/FosDnaDocumentProcessingServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/FosDnaDocumentProcessingServiceTest.cs new file mode 100644 index 0000000..5dc2547 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/FosDnaDocumentProcessingServiceTest.cs @@ -0,0 +1,608 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using NUnit.Framework; +using Moq; +using Newtonsoft.Json; +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Models.Requests.Account; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.DocumentType.Models.Requests.PrimaryOwner; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.DocumentProcessorServices; + +public class FosDnaDocumentProcessingServiceTest +{ + private FosDnaDocumentProcessingService _fosDnaDocumentProcessingService; + private Mock _mockPrimaryOwnerDeterminingService; + private Mock _mockAccountOwnerDeterminingService; + private Mock _mockFileOperationsApiService; + private Mock _mockDocumentTypeUploaderApiService; + + [SetUp] + public void Setup() + { + _mockPrimaryOwnerDeterminingService = new Mock(); + _mockAccountOwnerDeterminingService = new Mock(); + _mockFileOperationsApiService = new Mock(); + _mockDocumentTypeUploaderApiService = new Mock(); + var serviceFactoryConfiguration = new ServicesFactoryConfiguration + { + ServiceFactoryRegistrations = new List + { + new() + { + ServiceInterfaceName = "IIndexParserService", + ServiceRegistrations = new List + { + new() + { + ServiceName = "IndexParserService", + ServiceId = "4" + }, + new() + { + ServiceName = "IndexParserService", + ServiceId = "1" + } + } + } + } + }; + _fosDnaDocumentProcessingService = new FosDnaDocumentProcessingService(_mockPrimaryOwnerDeterminingService.Object, + _mockAccountOwnerDeterminingService.Object, + _mockFileOperationsApiService.Object, + _mockDocumentTypeUploaderApiService.Object, + serviceFactoryConfiguration); + } + + [Test] + public async Task ProcessRequest_ProcessingRequest_Null_ProcessResult_Failure() + { + ProcessingRequest request = null; + var result = await _fosDnaDocumentProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_FosDnaDocument_Null_ProcessResult_Failure() + { + var request = new ProcessingRequest + { + DocumentValuePayload = null + }; + var result = await _fosDnaDocumentProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_FosDnaDocument_OneValidationFailures_Failure() + { + var fosDnaDocument = new FosDnaDocument + { + AccountNumber = "0", + CreationDate = "01232005", + DocName = "Test.pdf", + DocType = "LN_NENT", + EntityName = "Bill B Billson" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(fosDnaDocument) + }; + var result = await _fosDnaDocumentProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.AreEqual(result.ProcessStatusType, ProcessStatusTypes.DataMappingFailure); + Assert.IsNull(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), It.IsAny(), It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + + [Test] + public async Task ProcessRequest_FosDnaDocument_EntityUnknown_PsInfoChangeNotice_Failure() + { + var fosDnaDocument = new FosDnaDocument + { + AccountNumber = "0", + CreationDate = "01232005", + DocName = "Test.pdf", + DocType = "PS_INFOCHANGE_NO", + EntityName = "Bill B Billson" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(fosDnaDocument) + }; + var result = await _fosDnaDocumentProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.AreEqual(result.ProcessStatusType, ProcessStatusTypes.DataMappingFailure); + Assert.IsTrue(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), It.IsAny(), It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_FosDnaDocument_ValidationFailures_Failure() + { + var fosDnaDocument = new FosDnaDocument + { + AccountNumber = "0", + CreationDate = "", + DocName = "", + DocType = "", + EntityName = "" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(fosDnaDocument) + }; + var result = await _fosDnaDocumentProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsNull(result.EntityIsUnknown); + Assert.AreEqual(3, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_FosDnaDocument_NumberIsNull_Failure() + { + var fosDnaDocument = new FosDnaDocument + { + AccountNumber = "1", + CreationDate = "01232005", + DocName = "Test.pdf", + DocType = "PS_INFOCHANGE_NO", + EntityName = "Bill B Billson" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(fosDnaDocument) + }; + + var primaryOwnerAttribute = ErrorCaptureResult.CreateErrorPayload("Error", null); + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(primaryOwnerAttribute); + + var result = await _fosDnaDocumentProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsNull(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), It.IsAny(), It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_FosDnaDocument_DataMappingFailure_CreationDate_Failure() + { + var fosDnaDocument = new FosDnaDocument + { + AccountNumber = "1", + CreationDate = "01T23T2005", + DocName = "Test.pdf", + DocType = "PS_INFOCHANGE_NO", + EntityName = "Bill B Billson" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(fosDnaDocument) + }; + + var primaryOwnerAttribute = ErrorCaptureResult.CreateErrorPayload("Error", null); + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(primaryOwnerAttribute); + + var result = await _fosDnaDocumentProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsNull(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + Assert.AreEqual(ProcessStatusTypes.DataMappingFailure, result.ProcessStatusType); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), It.IsAny(), It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_FosDnaDocumentPrimaryOwner_NumberNotNull_Upload_Success() + { + var fosDnaDocument = new FosDnaDocument + { + AccountNumber = "1", + CreationDate = "03072022", + DocName = "Test.pdf", + DocType = "PS_INFOCHANGE_NO", + EntityName = "Bill B Billson" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(fosDnaDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new PrimaryOwnerAttribute + { + PersonNumber = "2" + }; + + var primaryOwnerAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(primaryOwnerAttribute); + var content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())).ReturnsAsync(content); + + _mockDocumentTypeUploaderApiService.Setup(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny())); + + var result = await _fosDnaDocumentProcessingService.ProcessRequest(request); + Assert.IsTrue(result.Success); + Assert.IsNull(result.EntityIsUnknown); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), It.IsAny(), It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Once); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.Is(request => + request.PrimaryOwnerDocumentMetadata.Source == SourceTypes.FOS && + request.PrimaryOwnerDocumentMetadata.DataSource == DataSourceTypes.DNA), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [Test] + public async Task ProcessRequest_FosDnaDocumentAccountOwner_NumberNotNull_Upload_Success() + { + var fosDnaDocument = new FosDnaDocument + { + AccountNumber = "1", + CreationDate = "01232025", + DocName = "Test.pdf", + DocType = "LN_NENT", + EntityName = "Bill B Billson" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(fosDnaDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new AccountAttribute + { + PersonNumbers = new List { "2", "3", "4" } + }; + + var accountAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + + _mockAccountOwnerDeterminingService.Setup(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(accountAttribute); + var content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())).ReturnsAsync(content); + + _mockDocumentTypeUploaderApiService.Setup(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny())); + + var result = await _fosDnaDocumentProcessingService.ProcessRequest(request); + Assert.IsTrue(result.Success); + Assert.IsNull(result.EntityIsUnknown); + _mockAccountOwnerDeterminingService.Verify(x => x.DetermineAccountOwnerAttribute(It.IsAny(), It.IsAny(), It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Once); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [Test] + public async Task ProcessRequest_FosDnaDocument_NumberNotNull_GetContentBytesThrowException_Failure() + { + var fosDnaDocument = new FosDnaDocument + { + AccountNumber = "1", + CreationDate = "01232005", + DocName = "Test.pdf", + DocType = "PS_INFOCHANGE_NO", + EntityName = "Bill B Billson" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(fosDnaDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new PrimaryOwnerAttribute + { + PersonNumber = "2" + }; + + var primaryOwnerAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(primaryOwnerAttribute); + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())).ThrowsAsync(new Exception("Error")); + + var result = await _fosDnaDocumentProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), It.IsAny(), It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Once); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_FosDnaDocument_NumberNotNull_UploadDocumentThrowException_Failure() + { + var fosDnaDocument = new FosDnaDocument + { + AccountNumber = "1", + CreationDate = "01232005", + DocName = "Test.pdf", + DocType = "PS_INFOCHANGE_NO", + EntityName = "Bill B Billson" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(fosDnaDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new PrimaryOwnerAttribute + { + PersonNumber = "2" + }; + var primaryOwnerAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(primaryOwnerAttribute); + var content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())).ReturnsAsync(content); + + _mockDocumentTypeUploaderApiService.Setup(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny())).ThrowsAsync(new Exception("Error")); + + var result = await _fosDnaDocumentProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Once); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [Test] + public async Task ProcessRequest_FosDnaDocument_SkipAccountNumberPsInfoChangeNoticeOverride_Success() + { + var fosDnaDocument = new FosDnaDocument + { + AccountNumber = "", + CreationDate = "03072022", + DocName = "Test.pdf", + DocType = "PS_INFOCHANGE_NO", + EntityName = "Bill B Billson" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(fosDnaDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf", + OwnerOverrideInfo = new() + { + EntityType = EntityTypes.Person, + EntityId = "123" + } + }; + + var attribute = new PrimaryOwnerAttribute + { + PersonNumber = "2" + }; + + var primaryOwnerAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(primaryOwnerAttribute); + var content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())).ReturnsAsync(content); + + _mockDocumentTypeUploaderApiService.Setup(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny())); + + var result = await _fosDnaDocumentProcessingService.ProcessRequest(request); + Assert.IsTrue(result.Success); + Assert.IsNull(result.EntityIsUnknown); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), It.IsAny(), It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Once); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.Is(request => + request.PrimaryOwnerDocumentMetadata.Source == SourceTypes.FOS && + request.PrimaryOwnerDocumentMetadata.DataSource == DataSourceTypes.DNA), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [Test] + public async Task ProcessRequest_FosDnaDocument_SkipAccountNumberPsInfoChangeNoticeOverride_Failure() + { + var fosDnaDocument = new FosDnaDocument + { + AccountNumber = "", + CreationDate = "03072022", + DocName = "Test.pdf", + DocType = "LN_NENT", + EntityName = "Bill B Billson" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(fosDnaDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf", + OwnerOverrideInfo = new() + { + EntityType = EntityTypes.Person, + EntityId = "123" + } + }; + + var result = await _fosDnaDocumentProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsNull(result.EntityIsUnknown); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), It.IsAny(), It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_FosDnaDocument_GetValueFromName_ExceptionThrown_Failure() + { + var fosDnaDocument = new FosDnaDocument + { + AccountNumber = "1", + CreationDate = "01232005", + DocName = "Test.pdf", + DocType = Guid.NewGuid().ToString(), + EntityName = "Bill B Billson" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(fosDnaDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new PrimaryOwnerAttribute + { + PersonNumber = "2" + }; + var primaryOwnerAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(primaryOwnerAttribute); + var content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())).ReturnsAsync(content); + + var result = await _fosDnaDocumentProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/FosLoanStatementProcessingServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/FosLoanStatementProcessingServiceTest.cs new file mode 100644 index 0000000..be8c36d --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/FosLoanStatementProcessingServiceTest.cs @@ -0,0 +1,426 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using NUnit.Framework; +using Moq; +using Newtonsoft.Json; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Models.Requests.Account; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.DocumentProcessorServices; + +public class FosLoanStatementProcessingServiceTest +{ + private FosLoanStatementProcessingService _fosLoanStatementProcessingService; + private Mock _mockAccountOwnerDeterminingService; + private Mock _mockFileOperationsApiService; + private Mock _mockDocumentTypeUploaderApiService; + + [SetUp] + public void Setup() + { + _mockAccountOwnerDeterminingService = new Mock(); + _mockFileOperationsApiService = new Mock(); + _mockDocumentTypeUploaderApiService = new Mock(); + var serviceFactoryConfiguration = new ServicesFactoryConfiguration + { + ServiceFactoryRegistrations = new List + { + new() + { + ServiceInterfaceName = "IIndexParserService", + ServiceRegistrations = new List + { + new() + { + ServiceName = "IndexParserService", + ServiceId = "4" + }, + new() + { + ServiceName = "IndexParserService", + ServiceId = "3" + } + } + } + } + }; + _fosLoanStatementProcessingService = new FosLoanStatementProcessingService(_mockAccountOwnerDeterminingService.Object, + _mockFileOperationsApiService.Object, + _mockDocumentTypeUploaderApiService.Object, + serviceFactoryConfiguration); + } + + [Test] + public async Task ProcessRequest_ProcessingRequest_Null_ProcessResult_Failure() + { + ProcessingRequest request = null; + var result = await _fosLoanStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_FosLoanStatement_Null_ProcessResult_Failure() + { + var request = new ProcessingRequest + { + DocumentValuePayload = null + }; + var result = await _fosLoanStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + _mockAccountOwnerDeterminingService.Verify(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_FosLoanStatement_OneValidationFailures_Failure() + { + var FosLoanStatement = new FosLoanStatement + { + AccountNumber = "0", + CreationDate = "20230401", + DocName = "test.pdf", + EmailAddress = "test@test.com", + EntityName = "Test Tester", + StartingPage = "2", + NumberOfPages = "3", + DocType = "Mortgage Statement" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(FosLoanStatement) + }; + var result = await _fosLoanStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsNull(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockAccountOwnerDeterminingService.Verify(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_FosLoanStatement_FiveValidationFailures_Failure() + { + var FosLoanStatement = new FosLoanStatement + { + AccountNumber = "0", + CreationDate = "20230401", + DocName = "test.pdf", + EmailAddress = "test@test.com", + EntityName = "Test Tester", + StartingPage = "2", + NumberOfPages = "3", + DocType = "Mortgage Statement" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(FosLoanStatement) + }; + var result = await _fosLoanStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsNull(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockAccountOwnerDeterminingService.Verify(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_FosLoanStatement_NumberIsNull_Failure() + { + var FosLoanStatement = new FosLoanStatement + { + AccountNumber = "111111", + CreationDate = "20230401", + DocName = "test.pdf", + EmailAddress = "test@test.com", + EntityName = "Test Tester", + StartingPage = "2", + NumberOfPages = "3", + DocType = "Mortgage Statement" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(FosLoanStatement) + }; + + AccountAttribute attribute = null; + + var accountAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + _mockAccountOwnerDeterminingService.Setup(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(accountAttribute); + + var result = await _fosLoanStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockAccountOwnerDeterminingService.Verify(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_FosLoanStatement_NumberNotNull_Upload_Success() + { + var FosLoanStatement = new FosLoanStatement + { + AccountNumber = "111111", + CreationDate = "20230401", + DocName = "test.pdf", + EmailAddress = "test@test.com", + EntityName = "Test Tester", + StartingPage = "2", + NumberOfPages = "3", + DocType = "Mortgage Statement" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(FosLoanStatement), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new AccountAttribute + { + PersonNumbers = new List { "2", "3", "4" } + }; + + var accountAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + _mockAccountOwnerDeterminingService.Setup(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(accountAttribute); + byte[] content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ReturnsAsync(content); + _mockDocumentTypeUploaderApiService.Setup(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny())); + + var result = await _fosLoanStatementProcessingService.ProcessRequest(request); + Assert.IsTrue(result.Success); + Assert.IsNull(result.EntityIsUnknown); + _mockAccountOwnerDeterminingService.Verify(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Once); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadAccountDocument(It.Is(request => + request.AccountDocumentMetadata.Source == SourceTypes.FOS && + request.AccountDocumentMetadata.DataSource == DataSourceTypes.DNA), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [Test] + public async Task ProcessRequest_FosLoanStatement_NumberNotNull_GetContentBtyesThrowException_Failure() + { + var FosLoanStatement = new FosLoanStatement + { + AccountNumber = "111111", + CreationDate = "20230401", + DocName = "test.pdf", + EmailAddress = "test@test.com", + EntityName = "Test Tester", + StartingPage = "2", + NumberOfPages = "3", + DocType = "Mortgage Statement" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(FosLoanStatement), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new AccountAttribute + { + PersonNumbers = new List { "2", "3", "4" } + }; + + var accountAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + _mockAccountOwnerDeterminingService.Setup(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(accountAttribute); + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var result = await _fosLoanStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockAccountOwnerDeterminingService.Verify(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Once); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_FosLoanStatement_NumberNotNull_UploadDocumentThrowException_Failure() + { + var FosLoanStatement = new FosLoanStatement + { + AccountNumber = "111111", + CreationDate = "20230401", + DocName = "test.pdf", + EmailAddress = "test@test.com", + EntityName = "Test Tester", + StartingPage = "2", + NumberOfPages = "3", + DocType = "Mortgage Statement" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(FosLoanStatement), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new AccountAttribute + { + PersonNumbers = new List { "2", "3", "4" } + }; + + var accountAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + _mockAccountOwnerDeterminingService.Setup(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(accountAttribute); + byte[] content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())).ReturnsAsync(content); + + _mockDocumentTypeUploaderApiService.Setup(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny())).ThrowsAsync(new Exception("Error")); + + var result = await _fosLoanStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockAccountOwnerDeterminingService.Verify(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Once); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), + Times.Once); + } + + [Test] + public async Task ProcessRequest_FosLoanStatement_GetValueFromName_ExceptionThrown_Failure() + { + var FosLoanStatement = new FosLoanStatement + { + AccountNumber = "111111", + CreationDate = "20230401", + DocName = "test.pdf", + EmailAddress = "test@test.com", + EntityName = "Test Tester", + StartingPage = "2", + NumberOfPages = "3", + DocType = Guid.NewGuid().ToString() + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(FosLoanStatement), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new AccountAttribute + { + PersonNumbers = new List { "2", "3", "4" } + }; + + var accountAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + _mockAccountOwnerDeterminingService.Setup(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(accountAttribute); + byte[] content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ReturnsAsync(content); + + var result = await _fosLoanStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockAccountOwnerDeterminingService.Verify(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/FosTaxStatementProcessingServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/FosTaxStatementProcessingServiceTest.cs new file mode 100644 index 0000000..989c296 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/FosTaxStatementProcessingServiceTest.cs @@ -0,0 +1,473 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using NUnit.Framework; +using Moq; +using Newtonsoft.Json; +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.DocumentType.Models.Requests.PrimaryOwner; +using LCU.Library.DocumentType.Models.Requests.Generic; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.DocumentProcessorServices; + +public class FosTaxStatementProcessingServiceTest +{ + private FosTaxStatementProcessingService _fosTaxStatementProcessingService; + private Mock _mockPrimaryOwnerDeterminingService; + private Mock _mockFileOperationsApiService; + private Mock _mockDocumentTypeUploaderApiService; + + [SetUp] + public void Setup() + { + _mockPrimaryOwnerDeterminingService = new Mock(); + _mockFileOperationsApiService = new Mock(); + _mockDocumentTypeUploaderApiService = new Mock(); + var serviceFactoryConfiguration = new ServicesFactoryConfiguration + { + ServiceFactoryRegistrations = new List + { + new() + { + ServiceInterfaceName = "IIndexParserService", + ServiceRegistrations = new List + { + new() + { + ServiceName = "IndexParserService", + ServiceId = "4" + }, + new() + { + ServiceName = "IndexParserService", + ServiceId = "0" + } + } + } + } + }; + _fosTaxStatementProcessingService = new FosTaxStatementProcessingService(_mockPrimaryOwnerDeterminingService.Object, + _mockFileOperationsApiService.Object, + _mockDocumentTypeUploaderApiService.Object, + serviceFactoryConfiguration); + } + + [Test] + public async Task ProcessRequest_ProcessingRequest_Null_ProcessResult_Failure() + { + ProcessingRequest request = null; + var result = await _fosTaxStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadGenericDocument(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_FosTaxStatementDocument_Null_ProcessResult_Failure() + { + var request = new ProcessingRequest + { + DocumentValuePayload = null + }; + var result = await _fosTaxStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadGenericDocument(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_FosTaxStatementDocument_OneValidationFailures_Failure() + { + var fosTaxStatementDocument = new FosTaxStatementDocument + { + AccountNumber = "0", + FileName = "test", + FullName = "test", + PDF = "test", + PrimaryTIN = "1" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(fosTaxStatementDocument) + }; + var result = await _fosTaxStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsNull(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadGenericDocument(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_FosTaxStatementDocument_FiveValidationFailures_Failure() + { + var fosTaxStatementDocument = new FosTaxStatementDocument + { + AccountNumber = "0", + FileName = "", + FullName = "", + PDF = "", + PrimaryTIN = "" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(fosTaxStatementDocument) + }; + var result = await _fosTaxStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsNull(result.EntityIsUnknown); + Assert.AreEqual(5, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadGenericDocument(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_FosTaxStatementDocument_NumberIsNull_Failure() + { + var fosTaxStatementDocument = new FosTaxStatementDocument + { + AccountNumber = "1", + FileName = "1099-INT", + FullName = "test", + PDF = "test", + PrimaryTIN = "11" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(fosTaxStatementDocument) + }; + + var primaryOwnerAttribute = + ErrorCaptureResult.CreateErrorPayload("Error from unit test", null); + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(primaryOwnerAttribute); + + var result = await _fosTaxStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsNull(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadGenericDocument(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_FosTaxStatementDocument_NumberNotNull_Upload_Success() + { + var fosTaxStatementDocument = new FosTaxStatementDocument + { + AccountNumber = "1", + FileName = "1099-INT", + FullName = "test", + PDF = "test", + PrimaryTIN = "11" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(fosTaxStatementDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new PrimaryOwnerAttribute + { + PersonNumber = "2" + }; + var primaryOwnerAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(primaryOwnerAttribute); + var content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ReturnsAsync(content); + _mockDocumentTypeUploaderApiService.Setup(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny())); + + var result = await _fosTaxStatementProcessingService.ProcessRequest(request); + Assert.IsTrue(result.Success); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Once); + _mockDocumentTypeUploaderApiService.Verify(x => + x.UploadPrimaryOwnerDocument(It.Is(request => + request.PrimaryOwnerDocumentMetadata.Source == SourceTypes.FOS && + request.PrimaryOwnerDocumentMetadata.DataSource == DataSourceTypes.DNA), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [Test] + public async Task ProcessRequest_FosTaxStatementDocument_GenericDocument_NumberNotNull_Upload_Success() + { + var fosTaxStatementDocument = new FosTaxStatementDocument + { + AccountNumber = "1", + FileName = "1099-MISC", + FullName = "test", + PDF = "test", + PrimaryTIN = "11" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(fosTaxStatementDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new GenericDocumentAttribute + { + EntityName = "test" + }; + var genericAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + var content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ReturnsAsync(content); + + var documentTypeArchiveDeleteInfo = new DocumentTypeArchiveDeleteInfo + { + DocumentTypeName = "OneThousandNinetyNineMiscelanneous", + ArchiveDays = 2000, + DeleteDays = 4000 + }; + _mockDocumentTypeUploaderApiService.Setup(x => + x.UploadGenericDocument(It.IsAny(), It.IsAny(), It.IsAny())); + + var result = await _fosTaxStatementProcessingService.ProcessRequest(request); + Assert.IsTrue(result.Success); + Assert.IsNull(result.EntityIsUnknown); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Once); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadGenericDocument(It.Is(request => + request.GenericDocumentMetadata.Source == SourceTypes.FOS && + request.GenericDocumentMetadata.DataSource == DataSourceTypes.DNA), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [Test] + public async Task ProcessRequest_FosTaxStatementDocument_NumberNotNull_GetContentBytesThrowException_Failure() + { + var fosTaxStatementDocument = new FosTaxStatementDocument + { + AccountNumber = "1", + FileName = "1099-INT", + FullName = "test", + PDF = "test", + PrimaryTIN = "11" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(fosTaxStatementDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new PrimaryOwnerAttribute + { + PersonNumber = "2" + }; + var primaryOwnerAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(primaryOwnerAttribute); + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var result = await _fosTaxStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Once); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadGenericDocument(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_FosTaxStatementDocument_NumberNotNull_UploadDocumentThrowException_Failure() + { + var fosTaxStatementDocument = new FosTaxStatementDocument + { + AccountNumber = "1", + FileName = "1099-INT", + FullName = "test", + PDF = "test", + PrimaryTIN = "11" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(fosTaxStatementDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new PrimaryOwnerAttribute + { + PersonNumber = "2" + }; + var primaryOwnerAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(primaryOwnerAttribute); + var content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ReturnsAsync(content); + _mockDocumentTypeUploaderApiService.Setup(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var result = await _fosTaxStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Once); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [Test] + public async Task ProcessRequest_FosTaxStatementDocument_GetCreatedDateFromDocumentType_Success() + { + var createdDate = DateTime.Now.Date; + var fosTaxStatementDocument = new FosTaxStatementDocument + { + AccountNumber = "1", + FileName = "1099-INT", + FullName = "test", + TaxYear = 2021, + PDF = "test", + PrimaryTIN = "11" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(fosTaxStatementDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new PrimaryOwnerAttribute + { + PersonNumber = "2" + }; + var primaryOwnerAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), It.IsAny(), + It.IsAny())).ReturnsAsync(primaryOwnerAttribute); + var content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ReturnsAsync(content); + + var builtRequest = await _fosTaxStatementProcessingService.BuildUploadRequest(request, fosTaxStatementDocument, attribute); + Assert.AreEqual(createdDate, builtRequest.PrimaryOwnerDocumentMetadata.CreatedDate); + + _mockDocumentTypeUploaderApiService.Setup(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny())); + + var result = await _fosTaxStatementProcessingService.ProcessRequest(request); + Assert.IsTrue(result.Success); + Assert.IsNull(result.EntityIsUnknown); + + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), It.IsAny(), + It.IsAny()), Times.Once); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/OsgDnaNoticeSplitProcessingServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/OsgDnaNoticeSplitProcessingServiceTest.cs new file mode 100644 index 0000000..fada91b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/OsgDnaNoticeSplitProcessingServiceTest.cs @@ -0,0 +1,166 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using NUnit.Framework; +using Moq; +using Newtonsoft.Json; +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.DocumentType.Models.Requests.PrimaryOwner; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.DocumentType.Models.Requests.Account; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.DocumentProcessorServices; + +public class OsgDnaNoticeSplitProcessingServiceTest +{ + private OsgDnaNoticeSplitProcessingService _osgDnaNoticeSplitProcessingService; + private Mock _mockAccountOwnerDeterminingService; + private Mock _mockFileOperationsApiService; + private Mock _mockDocumentTypeUploaderApiService; + + [SetUp] + public void Setup() + { + _mockAccountOwnerDeterminingService = new Mock(); + _mockFileOperationsApiService = new Mock(); + _mockDocumentTypeUploaderApiService = new Mock(); + var serviceFactoryConfiguration = new ServicesFactoryConfiguration + { + ServiceFactoryRegistrations = new List + { + new() + { + ServiceInterfaceName = "IIndexParserService", + ServiceRegistrations = new List + { + new() + { + ServiceName = "IndexParserService", + ServiceId = "4" + }, + new() + { + ServiceName = "IndexParserService", + ServiceId = "9" + } + } + } + } + }; + _osgDnaNoticeSplitProcessingService = new OsgDnaNoticeSplitProcessingService(_mockFileOperationsApiService.Object, + _mockDocumentTypeUploaderApiService.Object, + _mockAccountOwnerDeterminingService.Object, + serviceFactoryConfiguration); + } + + [Test] + public async Task ProcessRequest_ProcessingRequest_Null_ProcessResult_Failure() + { + ProcessingRequest request = null; + var result = await _osgDnaNoticeSplitProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + _mockAccountOwnerDeterminingService.Verify(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), DateTime.Now, + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_OsgDnaNoticeSplitStatementDocument_Null_ProcessResult_Failure() + { + var request = new ProcessingRequest + { + DocumentValuePayload = null + }; + var result = await _osgDnaNoticeSplitProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + _mockAccountOwnerDeterminingService.Verify(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), DateTime.Now, + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + + [Test] + public async Task ProcessRequest_OsgDnaNoticeSplitDocument_FiveValidationFailures_Failure() + { + var osgDnaNoticeSplitDocument = new OsgDnaNoticeSplit + { + AccountNumber = "0", + NoticeName = "", + RecipientName = "", + PdfName = "", + MemberNumber = "" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(osgDnaNoticeSplitDocument) + }; + var result = await _osgDnaNoticeSplitProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsNull(result.EntityIsUnknown); + Assert.AreEqual(4, result.MessageStack.Count); + _mockAccountOwnerDeterminingService.Verify(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), DateTime.Now, + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_OsgDnaNoticeSplitDocument_NumberIsNull_Failure() + { + var osgDnaNoticeSplitDocument = new OsgDnaNoticeSplit + { + AccountNumber = "1", + NoticeName = "1099-INT", + RecipientName = "test", + PdfName = "test", + MemberNumber = "11", + CreationDate = DateTime.Now.Date.ToString("MMddyyyy") + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(osgDnaNoticeSplitDocument) + }; + + var primaryOwnerAttribute = + ErrorCaptureResult.CreateErrorPayload("Error from unit test", null); + _mockAccountOwnerDeterminingService.Verify(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), DateTime.Now, + It.IsAny()), Times.Never); + + var result = await _osgDnaNoticeSplitProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockAccountOwnerDeterminingService.Verify(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), DateTime.Now, + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/OsgDnaNoticesProcessingServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/OsgDnaNoticesProcessingServiceTest.cs new file mode 100644 index 0000000..4c92cb6 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/OsgDnaNoticesProcessingServiceTest.cs @@ -0,0 +1,467 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Models.Requests.Account; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.LCUServiceFactory.Configurations; +using Moq; +using Newtonsoft.Json; +using NUnit.Framework; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.DocumentProcessorServices; + +public class OsgDnaNoticesProcessingServiceTest +{ + private OsgDnaNoticesProcessingService _osgDnaNoticesProcessingService; + private Mock _mockAccountOwnerDeterminingService; + private Mock _mockFileOperationsApiService; + private Mock _mockDocumentTypeUploaderApiService; + private Mock _mockPrimaryOwnerDeterminingService; + + [SetUp] + public void Setup() + { + _mockAccountOwnerDeterminingService = new Mock(); + _mockPrimaryOwnerDeterminingService = new Mock(); + _mockFileOperationsApiService = new Mock(); + _mockDocumentTypeUploaderApiService = new Mock(); + var serviceFactoryConfiguration = new ServicesFactoryConfiguration + { + ServiceFactoryRegistrations = new List + { + new() + { + ServiceInterfaceName = "IIndexParserService", + ServiceRegistrations = new List + { + new() + { + ServiceName = "IndexParserService", + ServiceId = "4" + }, + new() + { + ServiceName = "IndexParserService", + ServiceId = "1" + } + } + } + } + }; + _osgDnaNoticesProcessingService = new OsgDnaNoticesProcessingService(_mockPrimaryOwnerDeterminingService.Object, + _mockFileOperationsApiService.Object, + _mockDocumentTypeUploaderApiService.Object, + _mockAccountOwnerDeterminingService.Object, + serviceFactoryConfiguration); + } + + [Test] + public async Task ProcessRequest_ProcessingRequest_Null_ProcessResult_Failure() + { + ProcessingRequest request = null; + + var result = await _osgDnaNoticesProcessingService.ProcessRequest(request); + + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + _mockFileOperationsApiService.Verify( + x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never + ); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadAccountDocument(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + } + + [Test] + public async Task ProcessRequest_OsgDnaNotices_Null_ProcessResult_Failure() + { + var request = new ProcessingRequest + { + DocumentValuePayload = null + }; + + var result = await _osgDnaNoticesProcessingService.ProcessRequest(request); + + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + _mockAccountOwnerDeterminingService.Verify( + x => x.DetermineAccountOwnerAttribute(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + _mockFileOperationsApiService.Verify( + x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never + ); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadAccountDocument(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + } + + [Test] + public async Task ProcessRequest_OsgDnaNotices_OneValidationFailures_Failure() + { + var OsgDnaNotices = new OsgDnaNoticesDocument + { + DocType = "MTG_NT_110_01", + AccountNumber = "1", + MemberNumberOrUserId = "2", + CreationDate = "2", + StartingPage = "1", + NumberOfPages = "3" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(OsgDnaNotices) + }; + + var result = await _osgDnaNoticesProcessingService.ProcessRequest(request); + + Assert.IsFalse(result.Success); + Assert.IsNull(result.EntityIsUnknown); + Assert.AreEqual(result.ProcessStatusType, ProcessStatusTypes.DataMappingFailure); + Assert.AreEqual(1, result.MessageStack.Count); + _mockAccountOwnerDeterminingService.Verify( + x => x.DetermineAccountOwnerAttribute(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + _mockFileOperationsApiService.Verify( + x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never + ); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadAccountDocument(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + } + + [Test] + public async Task ProcessRequest_OsgDnaNotices_ValidationFailures_Failure() + { + var OsgDnaNotices = new OsgDnaNoticesDocument + { + DocType = "MTG_NT_110_01", + AccountNumber = "0", + MemberNumberOrUserId = "2", + CreationDate = "20220823", + StartingPage = "1", + NumberOfPages = "3" + }; + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(OsgDnaNotices) + }; + var result = await _osgDnaNoticesProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsNull(result.EntityIsUnknown); + Assert.AreEqual(result.ProcessStatusType, ProcessStatusTypes.DataMappingFailure); + Assert.AreEqual(1, result.MessageStack.Count); + _mockAccountOwnerDeterminingService.Verify( + x => x.DetermineAccountOwnerAttributeByMemberNumberOrUserId(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + _mockFileOperationsApiService.Verify( + x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never + ); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadAccountDocument(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + } + + [Test] + public async Task ProcessRequest_OsgDnaNotices_NumberIsNull_Failure() + { + var OsgDnaNotices = new OsgDnaNoticesDocument + { + DocType = "MTG_NT_110_01", + AccountNumber = "1", + MemberNumberOrUserId = "2", + CreationDate = "20220823", + StartingPage = "1", + NumberOfPages = "3" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(OsgDnaNotices) + }; + + AccountAttribute attribute = null; + + var accountAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + _mockAccountOwnerDeterminingService.Setup(x => x.DetermineAccountOwnerAttributeByMemberNumberOrUserId(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(accountAttribute); + + var result = await _osgDnaNoticesProcessingService.ProcessRequest(request); + + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockAccountOwnerDeterminingService.Verify( + x => x.DetermineAccountOwnerAttributeByMemberNumberOrUserId(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), + Times.Once + ); + _mockFileOperationsApiService.Verify( + x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never + ); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadAccountDocument(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + } + + [Test] + public async Task ProcessRequest_OsgDnaNotices_NumberNotNull_Upload_Success() + { + var OsgDnaNotices = new OsgDnaNoticesDocument + { + DocType = "MTG_NT_110_01", + AccountNumber = "1", + MemberNumberOrUserId = "2", + CreationDate = "20220823", + StartingPage = "1", + NumberOfPages = "3" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(OsgDnaNotices), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new AccountAttribute + { + PersonNumbers = new List { "2", "3", "4" } + }; + + var accountAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + _mockAccountOwnerDeterminingService.Setup(x => x.DetermineAccountOwnerAttributeByMemberNumberOrUserId(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(accountAttribute); + + byte[] content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ReturnsAsync(content); + + var documentTypeArchiveDeleteInfo = new DocumentTypeArchiveDeleteInfo + { + DocumentTypeName = "MTG_NT_110_01", + ArchiveDays = 2000, + DeleteDays = 4000 + }; + _mockDocumentTypeUploaderApiService.Setup(x => x.UploadAccountDocument(It.IsAny(), It.IsAny(), It.IsAny())); + + var result = await _osgDnaNoticesProcessingService.ProcessRequest(request); + + Assert.IsTrue(result.Success); + Assert.IsNull(result.EntityIsUnknown); + _mockAccountOwnerDeterminingService.Verify( + x => x.DetermineAccountOwnerAttributeByMemberNumberOrUserId(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), + Times.Once + ); + _mockFileOperationsApiService.Verify( + x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Once + ); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadAccountDocument(It.Is(request => + request.AccountDocumentMetadata.Source == SourceTypes.OSG && + request.AccountDocumentMetadata.DataSource == DataSourceTypes.DNA), + It.IsAny(), It.IsAny()), + Times.Once + ); + } + + [Test] + public async Task ProcessRequest_OsgDnaNotices_NumberNotNull_GetContentBtyesThrowException_Failure() + { + var OsgDnaNotices = new OsgDnaNoticesDocument + { + DocType = "MTG_NT_110_01", + AccountNumber = "1", + MemberNumberOrUserId = "2", + CreationDate = "20220823", + StartingPage = "1", + NumberOfPages = "3" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(OsgDnaNotices), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new AccountAttribute + { + PersonNumbers = new List { "2", "3", "4" } + }; + + var accountAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + _mockAccountOwnerDeterminingService.Setup(x => x.DetermineAccountOwnerAttributeByMemberNumberOrUserId(It.IsAny(), + It.IsAny(), + It.IsAny(), It.IsAny(), + It.IsAny())).ReturnsAsync(accountAttribute); + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var result = await _osgDnaNoticesProcessingService.ProcessRequest(request); + + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockAccountOwnerDeterminingService.Verify( + x => x.DetermineAccountOwnerAttributeByMemberNumberOrUserId(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), + Times.Once + ); + _mockFileOperationsApiService.Verify( + x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Once + ); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadAccountDocument(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + } + + [Test] + public async Task ProcessRequest_OsgDnaNotices_NumberNotNull_UploadDocumentThrowException_Failure() + { + var OsgDnaNotices = new OsgDnaNoticesDocument + { + DocType = "MTG_NT_110_01", + AccountNumber = "1", + MemberNumberOrUserId = "2", + CreationDate = "20220823", + StartingPage = "1", + NumberOfPages = "3" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(OsgDnaNotices), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new AccountAttribute + { + PersonNumbers = new List { "2", "3", "4" } + }; + + var accountAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + _mockAccountOwnerDeterminingService.Setup(x => x.DetermineAccountOwnerAttributeByMemberNumberOrUserId(It.IsAny(), + It.IsAny(), + It.IsAny(), It.IsAny(), + It.IsAny())).ReturnsAsync(accountAttribute); + byte[] content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ReturnsAsync(content); + + _mockDocumentTypeUploaderApiService.Setup(x => x.UploadAccountDocument(It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var result = await _osgDnaNoticesProcessingService.ProcessRequest(request); + + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockAccountOwnerDeterminingService.Verify( + x => x.DetermineAccountOwnerAttributeByMemberNumberOrUserId(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), + Times.Once + ); + _mockFileOperationsApiService.Verify( + x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Once + ); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadAccountDocument(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Once + ); + } + + [Test] + public async Task ProcessRequest_OsgDnaNotices_GetValueFromName_ExceptionThrown_Failure() + { + var OsgDnaNotices = new OsgDnaNoticesDocument + { + DocType = Guid.NewGuid().ToString(), + AccountNumber = "1", + MemberNumberOrUserId = "2", + CreationDate = "20220823", + StartingPage = "1", + NumberOfPages = "3" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(OsgDnaNotices), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new AccountAttribute + { + PersonNumbers = new List { "2", "3", "4" } + }; + + var accountAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + _mockAccountOwnerDeterminingService.Setup(x => x.DetermineAccountOwnerAttributeByMemberNumberOrUserId(It.IsAny(), + It.IsAny(), + It.IsAny(), It.IsAny(), + It.IsAny())).ReturnsAsync(accountAttribute); + byte[] content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ReturnsAsync(content); + + var result = await _osgDnaNoticesProcessingService.ProcessRequest(request); + + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockAccountOwnerDeterminingService.Verify( + x => x.DetermineAccountOwnerAttributeByMemberNumberOrUserId(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + _mockFileOperationsApiService.Verify( + x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never + ); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadAccountDocument(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/OsgHistoricalDocumentProcessingServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/OsgHistoricalDocumentProcessingServiceTest.cs new file mode 100644 index 0000000..be2ce8e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/OsgHistoricalDocumentProcessingServiceTest.cs @@ -0,0 +1,485 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.DocumentType.Models.Requests.PrimaryOwner; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.LCUServiceFactory.Configurations; +using Moq; +using Newtonsoft.Json; +using NUnit.Framework; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.DocumentProcessorServices; + +public class OsgHistoricalDocumentProcessingServiceTest +{ + private OsgHistoricalDocumentProcessingService _osgHistoricalDocumentProcessingService; + private Mock _mockFileOperationsApiService; + private Mock _mockDocumentTypeUploaderApiService; + private Mock _mockPrimaryOwnerDeterminingService; + + [SetUp] + public void Setup() + { + _mockPrimaryOwnerDeterminingService = new Mock(); + _mockFileOperationsApiService = new Mock(); + _mockDocumentTypeUploaderApiService = new Mock(); + var serviceFactoryConfiguration = new ServicesFactoryConfiguration + { + ServiceFactoryRegistrations = new List + { + new() + { + ServiceInterfaceName = "IIndexParserService", + ServiceRegistrations = new List + { + new() + { + ServiceName = "IndexParserService", + ServiceId = "4" + }, + new() + { + ServiceName = "IndexParserService", + ServiceId = "6" + } + } + } + } + }; + _osgHistoricalDocumentProcessingService = new OsgHistoricalDocumentProcessingService(_mockPrimaryOwnerDeterminingService.Object, + _mockFileOperationsApiService.Object, + _mockDocumentTypeUploaderApiService.Object, + serviceFactoryConfiguration); + } + + [Test] + public async Task ProcessRequest_ProcessingRequest_Null_ProcessResult_Failure() + { + ProcessingRequest request = null; + + var result = await _osgHistoricalDocumentProcessingService.ProcessRequest(request); + + Assert.IsFalse(result.Success); + _mockFileOperationsApiService.Verify( + x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never + ); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadPrimaryOwnerDocument(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + } + + [Test] + public async Task ProcessRequest_OsgHistoricalDocument_Null_ProcessResult_Failure() + { + var request = new ProcessingRequest + { + DocumentValuePayload = null + }; + + var result = await _osgHistoricalDocumentProcessingService.ProcessRequest(request); + + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + _mockPrimaryOwnerDeterminingService.Verify( + x => x.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + _mockFileOperationsApiService.Verify( + x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never + ); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadPrimaryOwnerDocument(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + } + + [Test] + public async Task ProcessRequest_OsgHistoricalDocument_OneValidationFailures_Failure() + { + var OsgHistoricalDocument = new OsgHistoricalDocument + { + DocType = "MM_STMXT", + EntityName = "", + MemberNumberOrUserId = "2", + CreationDate = "20220823", + StartingPage = "1", + NumberOfPages = "3" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(OsgHistoricalDocument) + }; + + var result = await _osgHistoricalDocumentProcessingService.ProcessRequest(request); + + Assert.IsFalse(result.Success); + Assert.IsNull(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify( + x => x.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + _mockFileOperationsApiService.Verify( + x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never + ); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadPrimaryOwnerDocument(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + } + + [Test] + public async Task ProcessRequest_OsgHistoricalDocument_ValidationFailures_Failure() + { + var OsgHistoricalDocument = new OsgHistoricalDocument + { + DocType = "MTG_NT_110_01", + EntityName = "Jan Jim", + MemberNumberOrUserId = "2", + CreationDate = "20220823", + StartingPage = "1", + NumberOfPages = "3" + }; + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(OsgHistoricalDocument) + }; + var result = await _osgHistoricalDocumentProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify( + x => x.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + _mockFileOperationsApiService.Verify( + x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never + ); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadPrimaryOwnerDocument(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + } + + [Test] + public async Task ProcessRequest_OsgHistoricalDocument_DataMappingFailure_CreationDate_Failure() + { + var OsgHistoricalDocument = new OsgHistoricalDocument + { + DocType = "MTG_NT_110_01", + EntityName = "Jan Jim", + MemberNumberOrUserId = "2", + CreationDate = "2022T08T23", + StartingPage = "1", + NumberOfPages = "3" + }; + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(OsgHistoricalDocument) + }; + var result = await _osgHistoricalDocumentProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsNull(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + Assert.AreEqual(ProcessStatusTypes.DataMappingFailure, result.ProcessStatusType); + _mockPrimaryOwnerDeterminingService.Verify( + x => x.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + _mockFileOperationsApiService.Verify( + x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never + ); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadPrimaryOwnerDocument(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + } + + [Test] + public async Task ProcessRequest_OsgHistoricalDocument_NumberIsNull_Failure() + { + var OsgHistoricalDocument = new OsgHistoricalDocument + { + DocType = "MM_STMXT", + EntityName = "John James", + MemberNumberOrUserId = "2", + CreationDate = "20220823", + StartingPage = "1", + NumberOfPages = "3" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(OsgHistoricalDocument) + }; + + PrimaryOwnerAttribute attribute = null; + + var accountAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(accountAttribute); + + var result = await _osgHistoricalDocumentProcessingService.ProcessRequest(request); + + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify( + x => x.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Once + ); + _mockFileOperationsApiService.Verify( + x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never + ); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadPrimaryOwnerDocument(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + } + + [Test] + public async Task ProcessRequest_OsgHistoricalDocument_NumberNotNull_Upload_Success() + { + var OsgHistoricalDocument = new OsgHistoricalDocument + { + DocType = "MM_STMXT", + EntityName = "Jane Smith", + MemberNumberOrUserId = "2", + CreationDate = "20220823", + StartingPage = "1", + NumberOfPages = "3" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(OsgHistoricalDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new PrimaryOwnerAttribute() + { + PersonNumber = "2" + }; + + var accountAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(accountAttribute); + + byte[] content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ReturnsAsync(content); + + _mockDocumentTypeUploaderApiService.Setup(x => x.UploadPrimaryOwnerDocument(It.IsAny(), It.IsAny(), It.IsAny())); + + var result = await _osgHistoricalDocumentProcessingService.ProcessRequest(request); + + Assert.IsTrue(result.Success); + Assert.IsNull(result.EntityIsUnknown); + _mockPrimaryOwnerDeterminingService.Verify( + x => x.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Once + ); + _mockFileOperationsApiService.Verify( + x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Once + ); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadPrimaryOwnerDocument(It.Is(request => + request.PrimaryOwnerDocumentMetadata.Source == SourceTypes.OSG && + request.PrimaryOwnerDocumentMetadata.DataSource == DataSourceTypes.DNA), + It.IsAny(), It.IsAny()), + Times.Once + ); + } + + [Test] + public async Task ProcessRequest_OsgHistoricalDocument_NumberNotNull_GetContentBtyesThrowException_Failure() + { + var OsgHistoricalDocument = new OsgHistoricalDocument + { + DocType = "MM_STMXT", + EntityName = "John Smith", + MemberNumberOrUserId = "2", + CreationDate = "20220823", + StartingPage = "1", + NumberOfPages = "3" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(OsgHistoricalDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new PrimaryOwnerAttribute() + { + PersonNumber = "2" + }; + + var accountAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(accountAttribute); + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var result = await _osgHistoricalDocumentProcessingService.ProcessRequest(request); + + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify( + x => x.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Once + ); + _mockFileOperationsApiService.Verify( + x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Once + ); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadPrimaryOwnerDocument(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + } + + [Test] + public async Task ProcessRequest_OsgHistoricalDocument_NumberNotNull_UploadDocumentThrowException_Failure() + { + var OsgHistoricalDocument = new OsgHistoricalDocument + { + DocType = "MM_STMXT", + EntityName = "Jan Smith", + MemberNumberOrUserId = "2", + CreationDate = "20220823", + StartingPage = "1", + NumberOfPages = "3" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(OsgHistoricalDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new PrimaryOwnerAttribute + { + PersonNumber = "2" + }; + + var accountAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(accountAttribute); + byte[] content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ReturnsAsync(content); + + _mockDocumentTypeUploaderApiService.Setup(x => x.UploadPrimaryOwnerDocument(It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var result = await _osgHistoricalDocumentProcessingService.ProcessRequest(request); + + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify( + x => x.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Once + ); + _mockFileOperationsApiService.Verify( + x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Once + ); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadPrimaryOwnerDocument(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Once + ); + } + + [Test] + public async Task ProcessRequest_OsgHistoricalDocument_GetValueFromName_ExceptionThrown_Failure() + { + var OsgHistoricalDocument = new OsgHistoricalDocument + { + DocType = Guid.NewGuid().ToString(), + EntityName = "John Jim", + MemberNumberOrUserId = "2", + CreationDate = "20220823", + StartingPage = "1", + NumberOfPages = "3" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(OsgHistoricalDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new PrimaryOwnerAttribute + { + PersonNumber = "2", + }; + + var accountAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(accountAttribute); + byte[] content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ReturnsAsync(content); + + var result = await _osgHistoricalDocumentProcessingService.ProcessRequest(request); + + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify( + x => x.DeterminePrimaryOwnerAttributeByMemberNumberOrUserId(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + _mockFileOperationsApiService.Verify( + x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never + ); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadPrimaryOwnerDocument(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never + ); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/OsgTaxStatementProcessingServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/OsgTaxStatementProcessingServiceTest.cs new file mode 100644 index 0000000..dcaf60e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/OsgTaxStatementProcessingServiceTest.cs @@ -0,0 +1,478 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using NUnit.Framework; +using Moq; +using Newtonsoft.Json; +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.DocumentType.Models.Requests.PrimaryOwner; +using LCU.Library.DocumentType.Models.Requests.Generic; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.DocumentProcessorServices; + +public class OsgTaxStatementProcessingServiceTest +{ + private OsgTaxStatementProcessingService _osgTaxStatementProcessingService; + private Mock _mockPrimaryOwnerDeterminingService; + private Mock _mockFileOperationsApiService; + private Mock _mockDocumentTypeUploaderApiService; + + [SetUp] + public void Setup() + { + _mockPrimaryOwnerDeterminingService = new Mock(); + _mockFileOperationsApiService = new Mock(); + _mockDocumentTypeUploaderApiService = new Mock(); + var serviceFactoryConfiguration = new ServicesFactoryConfiguration + { + ServiceFactoryRegistrations = new List + { + new() + { + ServiceInterfaceName = "IIndexParserService", + ServiceRegistrations = new List + { + new() + { + ServiceName = "IndexParserService", + ServiceId = "8" + }, + new() + { + ServiceName = "IndexParserService", + ServiceId = "1" + } + } + } + } + }; + _osgTaxStatementProcessingService = new OsgTaxStatementProcessingService(_mockPrimaryOwnerDeterminingService.Object, + _mockFileOperationsApiService.Object, + _mockDocumentTypeUploaderApiService.Object, + serviceFactoryConfiguration); + } + + [Test] + public async Task ProcessRequest_ProcessingRequest_Null_ProcessResult_Failure() + { + ProcessingRequest request = null; + var result = await _osgTaxStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadGenericDocument(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_OsgTaxStatementDocument_Null_ProcessResult_Failure() + { + var request = new ProcessingRequest + { + DocumentValuePayload = null + }; + var result = await _osgTaxStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadGenericDocument(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_OsgTaxStatementDocument_OneValidationFailures_Failure() + { + var osgTaxStatementDocument = new OsgTaxStatement + { + AccountNumber = "0", + NoticeName = "test", + RecipientName = "test", + PdfName = "test", + SSN = "1" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(osgTaxStatementDocument) + }; + var result = await _osgTaxStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsNull(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadGenericDocument(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_OsgTaxStatementDocument_FiveValidationFailures_Failure() + { + var osgTaxStatementDocument = new OsgTaxStatement + { + AccountNumber = "0", + NoticeName = "", + RecipientName = "", + PdfName = "", + SSN = "" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(osgTaxStatementDocument) + }; + var result = await _osgTaxStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsNull(result.EntityIsUnknown); + Assert.AreEqual(5, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadGenericDocument(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_OsgTaxStatementDocument_NumberIsNull_Failure() + { + var osgTaxStatementDocument = new OsgTaxStatement + { + AccountNumber = "1", + NoticeName = "1099-INT", + RecipientName = "test", + PdfName = "test", + SSN = "11", + CreationDate = DateTime.Now.Date.ToString("MMddyyyy") + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(osgTaxStatementDocument) + }; + + var primaryOwnerAttribute = + ErrorCaptureResult.CreateErrorPayload("Error from unit test", null); + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(primaryOwnerAttribute); + + var result = await _osgTaxStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsNull(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadGenericDocument(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_OsgTaxStatementDocument_NumberNotNull_Upload_Success() + { + var osgTaxStatementDocument = new OsgTaxStatement + { + AccountNumber = "1", + NoticeName = "1099-INT", + RecipientName = "test", + PdfName = "test", + SSN = "11", + CreationDate = DateTime.Now.Date.ToString("MMddyyyy") + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(osgTaxStatementDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new PrimaryOwnerAttribute + { + PersonNumber = "2" + }; + var primaryOwnerAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(primaryOwnerAttribute); + var content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ReturnsAsync(content); + _mockDocumentTypeUploaderApiService.Setup(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny())); + + var result = await _osgTaxStatementProcessingService.ProcessRequest(request); + Assert.IsTrue(result.Success); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Once); + _mockDocumentTypeUploaderApiService.Verify(x => + x.UploadPrimaryOwnerDocument(It.Is(request => + request.PrimaryOwnerDocumentMetadata.Source == SourceTypes.OSG && + request.PrimaryOwnerDocumentMetadata.DataSource == DataSourceTypes.DNA), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [Test] + public async Task ProcessRequest_OsgTaxStatementDocument_GenericDocument_NumberNotNull_Upload_Success() + { + var osgTaxStatementDocument = new OsgTaxStatement + { + AccountNumber = "1", + NoticeName = "1099-MISC", + RecipientName = "test", + PdfName = "test", + SSN = "11", + CreationDate = DateTime.Now.Date.ToString("MMddyyyy") + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(osgTaxStatementDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new GenericDocumentAttribute + { + EntityName = "test" + }; + var genericAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + var content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ReturnsAsync(content); + + var documentTypeArchiveDeleteInfo = new DocumentTypeArchiveDeleteInfo + { + DocumentTypeName = "OneThousandNinetyNineMiscelanneous", + ArchiveDays = 2000, + DeleteDays = 4000 + }; + _mockDocumentTypeUploaderApiService.Setup(x => + x.UploadGenericDocument(It.IsAny(), It.IsAny(), It.IsAny())); + + var result = await _osgTaxStatementProcessingService.ProcessRequest(request); + Assert.IsTrue(result.Success); + Assert.IsNull(result.EntityIsUnknown); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Once); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadGenericDocument(It.Is(request => + request.GenericDocumentMetadata.Source == SourceTypes.OSG && + request.GenericDocumentMetadata.DataSource == DataSourceTypes.DNA), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [Test] + public async Task ProcessRequest_OsgTaxStatementDocument_NumberNotNull_GetContentBytesThrowException_Failure() + { + var osgTaxStatementDocument = new OsgTaxStatement + { + AccountNumber = "1", + NoticeName = "1099-INT", + RecipientName = "test", + PdfName = "test", + SSN = "11", + CreationDate = DateTime.Now.Date.ToString("MMddyyyy") + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(osgTaxStatementDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new PrimaryOwnerAttribute + { + PersonNumber = "2" + }; + var primaryOwnerAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(primaryOwnerAttribute); + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var result = await _osgTaxStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Once); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadGenericDocument(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_OsgTaxStatementDocument_NumberNotNull_UploadDocumentThrowException_Failure() + { + var osgTaxStatementDocument = new OsgTaxStatement + { + AccountNumber = "1", + NoticeName = "1099-INT", + RecipientName = "test", + PdfName = "test", + SSN = "11", + CreationDate = DateTime.Now.Date.ToString("MMddyyyy") + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(osgTaxStatementDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new PrimaryOwnerAttribute + { + PersonNumber = "2" + }; + var primaryOwnerAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(primaryOwnerAttribute); + var content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ReturnsAsync(content); + _mockDocumentTypeUploaderApiService.Setup(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var result = await _osgTaxStatementProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Once); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [Test] + public async Task ProcessRequest_OsgTaxStatementDocument_GetCreatedDateFromDocumentType_Success() + { + var createdDate = DateTime.Now.Date; + var osgTaxStatementDocument = new OsgTaxStatement + { + AccountNumber = "1", + NoticeName = "1099-INT", + RecipientName = "test", + CreationDate = DateTime.Now.Date.ToString("MMddyyyy"), + PdfName = "test", + SSN = "11" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(osgTaxStatementDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new PrimaryOwnerAttribute + { + PersonNumber = "2" + }; + var primaryOwnerAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + _mockPrimaryOwnerDeterminingService.Setup(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), It.IsAny(), + It.IsAny())).ReturnsAsync(primaryOwnerAttribute); + var content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ReturnsAsync(content); + + var builtRequest = await _osgTaxStatementProcessingService.BuildUploadRequest(request, osgTaxStatementDocument, attribute, DateTime.Now.Date); + Assert.AreEqual(createdDate, builtRequest.PrimaryOwnerDocumentMetadata.CreatedDate); + + _mockDocumentTypeUploaderApiService.Setup(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny())); + + var result = await _osgTaxStatementProcessingService.ProcessRequest(request); + Assert.IsTrue(result.Success); + Assert.IsNull(result.EntityIsUnknown); + + _mockPrimaryOwnerDeterminingService.Verify(x => x.DeterminePrimaryOwnerAttribute(It.IsAny(), + It.IsAny(), It.IsAny(), + It.IsAny()), Times.Once); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/XdiActionNoticeDocumentProcessingServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/XdiActionNoticeDocumentProcessingServiceTest.cs new file mode 100644 index 0000000..357a980 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/XdiActionNoticeDocumentProcessingServiceTest.cs @@ -0,0 +1,242 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Models.Requests.Generic; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.LCUServiceFactory.Configurations; +using Moq; +using Newtonsoft.Json; +using NUnit.Framework; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.DocumentProcessorServices; +public class XdiActionNoticeDocumentProcessingServiceTest +{ + private XdiActionNoticesProcessingService _xdiActionNoticesProcessingService; + private Mock _mockFileOperationsApiService; + private Mock _mockDocumentTypeUploaderApiService; + + [SetUp] + public void Setup() + { + _mockFileOperationsApiService = new Mock(); + _mockDocumentTypeUploaderApiService = new Mock(); + var serviceFactoryConfiguration = new ServicesFactoryConfiguration + { + ServiceFactoryRegistrations = new List + { + new() + { + ServiceInterfaceName = "IIndexParserService", + ServiceRegistrations = new List + { + new() + { + ServiceName = "IndexParserService", + ServiceId = "4" + }, + new() + { + ServiceName = "IndexParserService", + ServiceId = "5" + } + } + } + } + };; + _xdiActionNoticesProcessingService = new XdiActionNoticesProcessingService(_mockFileOperationsApiService.Object, + _mockDocumentTypeUploaderApiService.Object, + serviceFactoryConfiguration); + } + + [Test] + public async Task ProcessRequest_XdiDnaActionNotice_Upload_Success() + { + var xdiActionNoticesDocument = new XdiActionNoticesDocument + { + CreationDate = "01/23/2025", + DocumentName = "Test.pdf", + DocumentType = "ACTion_Consumer Loan Tattle Tale Notice", + PageCount = 2, + EntityName = "Bill B Billson" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(xdiActionNoticesDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ReturnsAsync(content); + + _mockDocumentTypeUploaderApiService.Setup(x => x.UploadGenericDocument(It.IsAny(), + It.IsAny(), + It.IsAny())); + + var result = await _xdiActionNoticesProcessingService.ProcessRequest(request); + + Assert.IsTrue(result.Success); + Assert.IsNull(result.EntityIsUnknown); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Once); + _mockDocumentTypeUploaderApiService.Verify( + x => x.UploadGenericDocument(It.Is(request => + request.GenericDocumentMetadata.Source == SourceTypes.XDI && + request.GenericDocumentMetadata.DataSource == DataSourceTypes.ACTION), request, result), Times.Once); + } + + [Test] + public async Task ProcessRequest_XdiActionNoticeDocument_RequestNull_ThrowsException_Failure() + { + var result = await _xdiActionNoticesProcessingService.ProcessRequest(null); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadGenericDocument(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never); + } + + [Test] + public async Task ProcessRequest_XdiActionNoticeDocument_PayloadNull_ThrowsException_Failure() + { + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(null), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var result = await _xdiActionNoticesProcessingService.ProcessRequest(request); + + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadGenericDocument(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never); + } + + [Test] + public async Task ProcessRequest_XdiActionNoticeDocument_NumberNotNull_GetContentBytesThrowException_Failure() + { + var xdiActionNoticesDocument = new XdiActionNoticesDocument + { + CreationDate = "01/23/2025", + DocumentName = "Test.pdf", + DocumentType = "ACTion_Consumer Loan Tattle Tale Notice", + PageCount = 2, + EntityName = "Bill B Billson" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(xdiActionNoticesDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var result = await _xdiActionNoticesProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Once); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadGenericDocument(It.IsAny(), It.IsAny(), It.IsAny()), + Times.Never); + } + + [Test] + public async Task ProcessRequest_XdiActionNoticeDocument_NumberNotNull_UploadDocumentThrowException_Failure() + { + var xdiActionNoticesDocument = new XdiActionNoticesDocument + { + CreationDate = "01/23/2025", + DocumentName = "Test.pdf", + DocumentType = "ACTion_Consumer Loan Tattle Tale Notice", + PageCount = 2, + EntityName = "Bill B Billson" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(xdiActionNoticesDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ReturnsAsync(content); + + _mockDocumentTypeUploaderApiService.Setup(x => x.UploadGenericDocument(It.IsAny(), + It.IsAny(), + It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var result = await _xdiActionNoticesProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Once); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadGenericDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [Test] + public async Task ProcessRequest_XdiActionNoticeDocument_GetValueFromName_ExceptionThrown_Failure() + { + var xdiActionNoticesDocument = new XdiActionNoticesDocument + { + CreationDate = "01/23/2025", + DocumentName = "Test.pdf", + DocumentType = "ACTion_Consumer Loan Tattle Tale Notice Incorrect", + PageCount = 2, + EntityName = "Bill B Billson" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(xdiActionNoticesDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var result = await _xdiActionNoticesProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadGenericDocument(It.IsAny(), request, result), + Times.Never); + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/XdiDnaNoticeDocumentProcessingServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/XdiDnaNoticeDocumentProcessingServiceTest.cs new file mode 100644 index 0000000..d0523e1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentProcessorServices/XdiDnaNoticeDocumentProcessingServiceTest.cs @@ -0,0 +1,343 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; +using System.Reflection; +using System.Threading.Tasks; +using NUnit.Framework; +using Moq; +using Newtonsoft.Json; +using LCU.Library.DocumentType.Enums; +using LCU.Library.DocumentType.Models.Requests.Account; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.API.Internal.DocumentIngestor.Services.AttributeDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.DocumentProcessorServices; + +public class XdiDnaNoticeDocumentProcessingServiceTest +{ + private XdiDnaNoticeDocumentProcessingService _xdiDnaNoticeDocumentProcessingService; + private Mock _mockAccountOwnerDeterminingService; + private Mock _mockFileOperationsApiService; + private Mock _mockDocumentTypeUploaderApiService; + + [SetUp] + public void Setup() + { + _mockAccountOwnerDeterminingService = new Mock(); + _mockFileOperationsApiService = new Mock(); + _mockDocumentTypeUploaderApiService = new Mock(); + var serviceFactoryConfiguration = new ServicesFactoryConfiguration + { + ServiceFactoryRegistrations = new List + { + new() + { + ServiceInterfaceName = "IIndexParserService", + ServiceRegistrations = new List + { + new() + { + ServiceName = "IndexParserService", + ServiceId = "4" + }, + new() + { + ServiceName = "IndexParserService", + ServiceId = "2" + } + } + } + } + }; + _xdiDnaNoticeDocumentProcessingService = new XdiDnaNoticeDocumentProcessingService(_mockAccountOwnerDeterminingService.Object, + _mockFileOperationsApiService.Object, + _mockDocumentTypeUploaderApiService.Object, + serviceFactoryConfiguration); + } + + [Test] + public async Task ProcessRequest_XdiDnaNoticeDocumentAccountOwner_NumberNotNull_Upload_Success() + { + var xdiDnaDocument = new XdiDnaNoticesDocument + { + AccountNumber = "1", + CreationDate = "01/23/2025", + PDF = "Test.pdf", + DocumentType = "DNA_22 Day Past Due Letter", + PageCount = 2, + EntityName = "Bill B Billson" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(xdiDnaDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new AccountAttribute + { + PersonNumbers = new List { "2", "3", "4" } + }; + + var accountAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + + _mockAccountOwnerDeterminingService.Setup(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(accountAttribute); + var content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())).ReturnsAsync(content); + + _mockDocumentTypeUploaderApiService.Setup(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny())); + + var result = await _xdiDnaNoticeDocumentProcessingService.ProcessRequest(request); + Assert.IsTrue(result.Success); + Assert.IsNull(result.EntityIsUnknown); + _mockAccountOwnerDeterminingService.Verify(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Once); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadAccountDocument(It.Is(request => + request.AccountDocumentMetadata.Source == SourceTypes.XDI && + request.AccountDocumentMetadata.DataSource == DataSourceTypes.DNA), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [Test] + public async Task ProcessRequest_XdiDnaNoticeDocument_AccountOwnerNotDetermined_Failure() + { + var xdiDnaNoticeDocument = new XdiDnaNoticesDocument + { + AccountNumber = "1", + CreationDate = "01/23/2025", + PDF = "Test.pdf", + DocumentType = "DNA_32 Day Past Due Letter", + EntityName = "Bill B Billson" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(xdiDnaNoticeDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new AccountAttribute + { + PersonNumbers = new List { "2", "3", "4" } + }; + + var accountAttribute = ErrorCaptureResult.CreateErrorPayload("Error from test", attribute); + + _mockAccountOwnerDeterminingService.Setup(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(accountAttribute); + + var result = await _xdiDnaNoticeDocumentProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsNull(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + Assert.AreEqual(ProcessStatusTypes.DataMappingFailure, result.ProcessStatusType); + _mockAccountOwnerDeterminingService.Verify(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_XdiDnaNoticeDocument_NumberNotNull_GetContentBytesThrowException_Failure() + { + var xdiDnaNoticeDocument = new XdiDnaNoticesDocument + { + AccountNumber = "1", + CreationDate = "01/23/2025", + PDF = "Test.pdf", + DocumentType = "DNA_32 Day Past Due Letter", + EntityName = "Bill B Billson" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(xdiDnaNoticeDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new AccountAttribute + { + PersonNumbers = new List { "2", "3", "4" } + }; + + var accountAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + + _mockAccountOwnerDeterminingService.Setup(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(accountAttribute); + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var result = await _xdiDnaNoticeDocumentProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockAccountOwnerDeterminingService.Verify(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Once); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_XdiDnaNoticeDocument_NumberNotNull_UploadDocumentThrowException_Failure() + { + var xdiDnaNoticeDocument = new XdiDnaNoticesDocument + { + AccountNumber = "1", + CreationDate = "01/23/2025", + PDF = "Test.pdf", + DocumentType = "ThirtyTwoDayPastDueLetter", + EntityName = "Bill B Billson" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(xdiDnaNoticeDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var attribute = new AccountAttribute + { + PersonNumbers = new List { "2", "3", "4" } + }; + + var accountOwnerAttribute = ErrorCaptureResult.CreateSuccessPayload(attribute); + + _mockAccountOwnerDeterminingService.Setup(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), It.IsAny(), + It.IsAny())).ReturnsAsync(accountOwnerAttribute); + var content = new byte[1024]; + _mockFileOperationsApiService.Setup(x => x.GetContentBytes(It.IsAny(), It.IsAny())) + .ReturnsAsync(content); + + _mockDocumentTypeUploaderApiService.Setup(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var result = await _xdiDnaNoticeDocumentProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockAccountOwnerDeterminingService.Verify(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), + Times.Once); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [Test] + public async Task ProcessRequest_XdiDnaNoticeDocument_GetValueFromName_ExceptionThrown_Failure() + { + var xdiDnaDocument = new XdiDnaNoticesDocument + { + AccountNumber = "1", + CreationDate = "01/23/2005", + PDF = "Test.pdf", + DocumentType = "DNA_32 Day Past Due Letter Incorrect", + EntityName = "Test Entity" + }; + + var request = new ProcessingRequest + { + DocumentValuePayload = JsonConvert.SerializeObject(xdiDnaDocument), + IngestorRequest = new IngestorRequest + { + RootPath = "\\Tester\\" + }, + DocumentFileName = "test.pdf" + }; + + var result = await _xdiDnaNoticeDocumentProcessingService.ProcessRequest(request); + Assert.IsFalse(result.Success); + Assert.IsFalse(result.EntityIsUnknown); + Assert.AreEqual(1, result.MessageStack.Count); + _mockAccountOwnerDeterminingService.Verify(x => x.DetermineAccountOwnerAttribute(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetContentBytes(It.IsAny(), It.IsAny()), Times.Never); + _mockDocumentTypeUploaderApiService.Verify(x => x.UploadAccountDocument(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task ProcessRequest_ValidDate_ParsesDateCorrectly() + { + var date = DateTime.Now; + DateTime? parsedCreationTime = null; + var request = new ProcessingRequest + { + DocumentValuePayload = @"{ + ""CreationDate"":""" + $"{date:MM/dd/yyyy}" + @""", + ""AccountNumber"":""10"", + ""LoanNumber"":""1"", + ""EntityName"":""1"", + ""PageCount"":1, + ""DocumentType"":""" + typeof(AccountDocumentTypes).GetFields().First(f => f.GetCustomAttribute() is not null).GetCustomAttribute().Name + @""", + ""PDF"":""1"" + }" + }; + + _mockAccountOwnerDeterminingService + .Setup(aods => aods.DetermineAccountOwnerAttribute(It.IsAny(), It.IsAny(), + It.IsAny(), It.IsAny())) + .Callback((_, _, creationTime, _) => parsedCreationTime = creationTime); + + await _xdiDnaNoticeDocumentProcessingService.ProcessRequest(request); + + Assert.IsNotNull(parsedCreationTime); + Assert.AreEqual(date.Month, parsedCreationTime.Value.Month); + Assert.AreEqual(date.Day, parsedCreationTime.Value.Day); + Assert.AreEqual(date.Year, parsedCreationTime.Value.Year); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentReprocessingServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentReprocessingServiceTest.cs new file mode 100644 index 0000000..0b78eed --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentReprocessingServiceTest.cs @@ -0,0 +1,537 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Serilog; +using Serilog.Events; +using Moq; +using NUnit.Framework; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; + +using Newtonsoft.Json; + +namespace LCU.API.Internal.DocumentIngestorTests.Services; + +public class DocumentReprocessingServiceTest +{ + private DocumentReprocessingService _documentReprocessingService; + private Mock _mockIngestorRunInfoService; + private Mock _mockDocumentProcessingInfoService; + private Mock _mockQueueDocumentProcessing; + private Mock _mockOwnerOverrideInfoService; + private ApiConfiguration _apiConfiguration; + private readonly Mock _logger = new(); + private readonly ILogger _originalLogger = Log.Logger; + + [SetUp] + public void Setup() + { + Log.Logger = _logger.Object; + + _mockIngestorRunInfoService = new Mock(); + _mockDocumentProcessingInfoService = new Mock(); + _mockQueueDocumentProcessing = new Mock(); + _mockOwnerOverrideInfoService = new Mock(); + _apiConfiguration = new ApiConfiguration(); + _documentReprocessingService = new DocumentReprocessingService(_mockIngestorRunInfoService.Object, + _mockDocumentProcessingInfoService.Object, + _mockOwnerOverrideInfoService.Object, + _mockQueueDocumentProcessing.Object, + _apiConfiguration); + } + + [TearDown] + public void TearDown() + { + Log.Logger = _originalLogger; + } + + [Test] + public async Task QueueReprocessDocumentByDocumentProcessingInfoId_Success() + { + + var documentProcessingInfoId = 1; + var userName = "Test Tester"; + var ingestorRunInfoId = new Guid(); + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = documentProcessingInfoId, + DocumentFileName = "TestDoc", + DocumentValuePayload = "{jsonblah: hello}", + IngestorRunInfoId = ingestorRunInfoId, + CreatedDate = new DateTime(2022, 01, 01), + StatusType = ProcessStatusTypes.ArchiveFailure + }; + var ingestorRunInfo = new IngestorRunInfo() + { + IndexFileName = "Test.txt", + IndexFilePath = "\\\\Test\\Test\\", + IngestorType = IngestorTypes.FosLoanStatement + }; + + _mockDocumentProcessingInfoService.Setup(x => x.GetByIdAsync(documentProcessingInfoId)).ReturnsAsync(documentProcessingInfo); + _mockIngestorRunInfoService.Setup(x => x.GetByIdAsync(ingestorRunInfoId)).ReturnsAsync(ingestorRunInfo); + + await _documentReprocessingService.QueueReprocessDocumentByDocumentProcessingInfoId(documentProcessingInfoId, userName); + + _mockDocumentProcessingInfoService.Verify(x => x.GetByIdAsync(documentProcessingInfoId), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.GetByIdAsync(It.IsAny()), Times.Once); + _mockDocumentProcessingInfoService.Verify(x => x.UpdateStatusAndAddLog(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + null), Times.Once); + _mockQueueDocumentProcessing.Verify(x => x.QueueDocumentProcessingRequest(It.IsAny()), Times.Once); + } + + [Test] + public void QueueReprocessDocumentByDocumentProcessingInfoId_Failure_Exception() + { + var id = 1; + var userName = "Test Tester"; + var ingestorRequest = new IngestorRequest() + { + RootPath = "\\Test\\Test" + }; + + var request = new ProcessingRequest() + { + DocumentFileName = "000001Test.pdf", + IngestorRequest = ingestorRequest + }; + _mockQueueDocumentProcessing.Setup(x => x.QueueDocumentProcessingRequest(request)).ThrowsAsync(new Exception("Test Error")); + Assert.ThrowsAsync(async () => await _documentReprocessingService + .QueueReprocessDocumentByDocumentProcessingInfoId(id, userName)); + + _mockDocumentProcessingInfoService.Verify(x => x.GetByIdAsync(id), Times.Once); + _mockQueueDocumentProcessing.Verify(x => x.QueueDocumentProcessingRequest(It.IsAny()), Times.Never); + } + + [Test] + public void QueueReprocessDocumentByDocumentProcessingInfoId_Failure_ArgumentNullException() + { + var id = 1; + var userName = "Test Tester"; + _mockDocumentProcessingInfoService.Setup(x => x.GetByIdAsync(id)).ThrowsAsync(new ArgumentNullException("Test Error")); + Assert.ThrowsAsync(async () => await _documentReprocessingService + .QueueReprocessDocumentByDocumentProcessingInfoId(id, userName)); + + _mockDocumentProcessingInfoService.Verify(x => x.GetByIdAsync(id), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.GetByIdAsync(It.IsAny()), Times.Never); + _mockDocumentProcessingInfoService.Verify(x => x.UpdateStatusAndAddLog(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + false), Times.Never); + _mockQueueDocumentProcessing.Verify(x => x.QueueDocumentProcessingRequest(It.IsAny()), Times.Never); + } + + private OwnerOverrideInfo OverrideFactory() + { + var info = new OwnerOverrideInfo + { + UserName = Guid.NewGuid().ToString(), + EntityId = Guid.NewGuid().ToString(), + EntityType = Random(), + DocumentProcessingInfoId = DateTime.Now.Millisecond + }; + + _mockOwnerOverrideInfoService + .Setup(s => s.GetByDocumentProcessingInfoIdAsync(info.DocumentProcessingInfoId)) + .ReturnsAsync(new[] { info }); + + return info; + } + + [Test] + public async Task QueueOverrideDocumentByDocumentProcessingInfoId_AllCases_SavesOwnerOverrides() + { + var ownerOverride = OverrideFactory(); + + try + { + await _documentReprocessingService.QueueOverrideDocumentByDocumentProcessingInfoId(ownerOverride); + } + catch { } + + _mockOwnerOverrideInfoService.Verify(s => s.SaveAsync(ownerOverride), Times.Once); + } + + [Test] + public void QueueOverrideDocumentByDocumentProcessingInfoId_OverrideSaveThrowsException_LogsAndThrowsServiceException() + { + var ownerOverride = OverrideFactory(); + var saveException = new Exception(); + var loggedErrors = new List(); + _mockOwnerOverrideInfoService + .Setup(s => s.SaveAsync(ownerOverride)) + .ThrowsAsync(saveException); + _logger + .Setup(l => l.Write(LogEventLevel.Error, saveException, It.IsAny())) + .Callback((_, _, log) => loggedErrors.Add(log)); + + var thrownException = Assert.ThrowsAsync(() => _documentReprocessingService.QueueOverrideDocumentByDocumentProcessingInfoId(ownerOverride)); + + StringAssert.Contains(ownerOverride.DocumentProcessingInfoId.ToString(), thrownException!.Message); + Assert.AreEqual(1, loggedErrors.Count); + var errorLog = loggedErrors.Single(); + StringAssert.Contains(ownerOverride.DocumentProcessingInfoId.ToString(), errorLog); + StringAssert.Contains(ownerOverride.EntityId, errorLog); + StringAssert.Contains(ownerOverride.EntityType.ToString(), errorLog); + } + + [Test] + public async Task QueueOverrideDocumentByDocumentProcessingInfoId_OverrideSaveThrowsException_DoesNotRequeue() + { + var ownerOverride = OverrideFactory(); + _mockOwnerOverrideInfoService + .Setup(s => s.SaveAsync(ownerOverride)) + .ThrowsAsync(new Exception()); + + try + { + await _documentReprocessingService.QueueOverrideDocumentByDocumentProcessingInfoId(ownerOverride); + } + catch { } + + _mockQueueDocumentProcessing.Verify(p => p.QueueDocumentProcessingRequest(It.IsAny()), Times.Never); + } + + [Test] + public void QueueOverrideDocumentByDocumentProcessingInfoId_FetchedDocumentInfoNull_LogsAndThrowsArgumentNull() + { + var ownerOverride = SetupSave(OverrideFactory()); + var loggedErrors = new List<(Exception exception, string log)>(); + _logger + .Setup(l => l.Write(LogEventLevel.Error, It.IsAny(), It.IsAny())) + .Callback((_, exception, log) => loggedErrors.Add((exception, log))); + _mockDocumentProcessingInfoService + .Setup(s => s.GetByIdAsync(ownerOverride.DocumentProcessingInfoId)) + .ReturnsAsync((DocumentProcessingInfo)null); + + var thrownException = Assert.ThrowsAsync(() => _documentReprocessingService.QueueOverrideDocumentByDocumentProcessingInfoId(ownerOverride)); + + Assert.AreEqual(1, loggedErrors.Count); + var (loggedException, log) = loggedErrors.Single(); + Assert.AreSame(loggedException, thrownException); + StringAssert.Contains(ownerOverride.DocumentProcessingInfoId.ToString(), log); + } + + [Test] + public async Task QueueOverrideDocumentByDocumentProcessingInfoId_FetchedDocumentInfoNull_DoesNotRequeue() + { + var ownerOverride = SetupSave(OverrideFactory()); + _mockDocumentProcessingInfoService + .Setup(s => s.GetByIdAsync(ownerOverride.DocumentProcessingInfoId)) + .ReturnsAsync((DocumentProcessingInfo)null); + + try + { + await _documentReprocessingService.QueueOverrideDocumentByDocumentProcessingInfoId(ownerOverride); + } + catch { } + + _mockQueueDocumentProcessing.Verify(p => p.QueueDocumentProcessingRequest(It.IsAny()), Times.Never); + } + + [Test] + public void QueueOverrideDocumentByDocumentProcessingInfoId_FetchedIngestorRunNull_LogsAndThrowsArgumentNull() + { + var ownerOverride = SetupSave(OverrideFactory()); + var info = SetupGetDocumentProcessingInfo(ownerOverride); + var loggedErrors = new List<(Exception exception, string log)>(); + _logger + .Setup(l => l.Write(LogEventLevel.Error, It.IsAny(), It.IsAny())) + .Callback((_, exception, log) => loggedErrors.Add((exception, log))); + _mockIngestorRunInfoService + .Setup(s => s.GetByIdAsync(info.IngestorRunInfoId)) + .ReturnsAsync((IngestorRunInfo)null); + + var thrownException = Assert.ThrowsAsync(() => _documentReprocessingService.QueueOverrideDocumentByDocumentProcessingInfoId(ownerOverride)); + + Assert.AreEqual(1, loggedErrors.Count); + var (loggedException, log) = loggedErrors.Single(); + Assert.AreSame(loggedException, thrownException); + StringAssert.Contains(ownerOverride.DocumentProcessingInfoId.ToString(), log); + } + + [Test] + public async Task QueueOverrideDocumentByDocumentProcessingInfoId_FetchedIngestorRunNull_DoesNotRequeue() + { + var ownerOverride = SetupSave(OverrideFactory()); + var info = SetupGetDocumentProcessingInfo(ownerOverride); + _mockIngestorRunInfoService + .Setup(s => s.GetByIdAsync(info.IngestorRunInfoId)) + .ReturnsAsync((IngestorRunInfo)null); + + try + { + await _documentReprocessingService.QueueOverrideDocumentByDocumentProcessingInfoId(ownerOverride); + } + catch { } + + _mockQueueDocumentProcessing.Verify(p => p.QueueDocumentProcessingRequest(It.IsAny()), Times.Never); + } + + [Test] + public async Task QueueOverrideDocumentByDocumentProcessingInfoId_SaveSucceeds_UpdatesStatusAndLogs() + { + var ownerOverride = SetupSave(OverrideFactory()); + var documentInfo = SetupGetDocumentProcessingInfo(ownerOverride); + SetupGetIngestorRunInfo(documentInfo); + + await _documentReprocessingService.QueueOverrideDocumentByDocumentProcessingInfoId(ownerOverride); + + _mockDocumentProcessingInfoService.Verify + ( + s => s.UpdateStatusAndAddLog + ( + ownerOverride.DocumentProcessingInfoId, + ProcessStatusTypes.Reprocessing, + It.Is(s => s.Contains(ownerOverride.UserName) && s.Contains(JsonConvert.SerializeObject(ownerOverride))), + ownerOverride.UserName, + It.IsAny() + ), + Times.Once + ); + } + + [Test] + public void QueueOverrideDocumentByDocumentProcessingInfoId_UpdateStatusThrowsException_LogsAndThrowsServiceException() + { + var ownerOverride = SetupSave(OverrideFactory()); + var documentInfo = SetupGetDocumentProcessingInfo(ownerOverride); + SetupGetIngestorRunInfo(documentInfo); + var exceptionToThrow = new Exception(); + var loggedErrors = new List(); + _logger + .Setup(l => l.Write(LogEventLevel.Error, It.IsAny(), It.IsAny())) + .Callback((_, _, log) => loggedErrors.Add(log)); + _mockDocumentProcessingInfoService + .Setup + ( + s => s.UpdateStatusAndAddLog + ( + ownerOverride.DocumentProcessingInfoId, + ProcessStatusTypes.Reprocessing, + It.Is(s => + s.Contains(ownerOverride.UserName) && s.Contains(JsonConvert.SerializeObject(ownerOverride))), + ownerOverride.UserName, + null + ) + ) + .ThrowsAsync(exceptionToThrow); + + var thrownException = Assert.ThrowsAsync(() => _documentReprocessingService.QueueOverrideDocumentByDocumentProcessingInfoId(ownerOverride)); + + StringAssert.Contains(ownerOverride.DocumentProcessingInfoId.ToString(), thrownException!.Message); + Assert.AreEqual(1, loggedErrors.Count); + var errorLog = loggedErrors.Single(); + StringAssert.Contains(ownerOverride.DocumentProcessingInfoId.ToString(), errorLog); + StringAssert.Contains(ownerOverride.EntityId, errorLog); + StringAssert.Contains(ownerOverride.EntityType.ToString(), errorLog); + } + + [Test] + public async Task QueueOverrideDocumentByDocumentProcessingInfoId_UpdateStatusThrowsException_DoesNotRequeue() + { + var ownerOverride = SetupSave(OverrideFactory()); + var documentInfo = SetupGetDocumentProcessingInfo(ownerOverride); + SetupGetIngestorRunInfo(documentInfo); + _mockDocumentProcessingInfoService + .Setup + ( + s => s.UpdateStatusAndAddLog + ( + ownerOverride.DocumentProcessingInfoId, + ProcessStatusTypes.Reprocessing, + It.Is(s => + s.Contains(ownerOverride.UserName) && s.Contains(JsonConvert.SerializeObject(ownerOverride))), + ownerOverride.UserName, + null + ) + ) + .ThrowsAsync(new Exception()); + + try + { + await _documentReprocessingService.QueueOverrideDocumentByDocumentProcessingInfoId(ownerOverride); + } + catch { } + + _mockQueueDocumentProcessing.Verify(p => p.QueueDocumentProcessingRequest(It.IsAny()), Times.Never); + } + + [Test] + public async Task QueueOverrideDocumentByDocumentProcessingInfoId_SaveSucceeds_RequeuesProcessing() + { + var ownerOverride = SetupSave(OverrideFactory()); + var documentInfo = SetupGetDocumentProcessingInfo(ownerOverride); + var ingestorInfo = SetupGetIngestorRunInfo(documentInfo); + var requeuedRequests = new List(); + _mockQueueDocumentProcessing + .Setup(p => p.QueueDocumentProcessingRequest(It.IsAny())) + .Callback(requeuedRequests.Add); + + await _documentReprocessingService.QueueOverrideDocumentByDocumentProcessingInfoId(ownerOverride); + + Assert.AreEqual(1, requeuedRequests.Count); + var requeued = requeuedRequests.Single(); + Assert.AreEqual(requeued.DocumentProcessingInfoId, ownerOverride.DocumentProcessingInfoId); + Assert.AreEqual(requeued.IngestorRunInfoId, documentInfo.IngestorRunInfoId); + Assert.AreEqual(requeued.DocumentFileName, documentInfo.DocumentFileName); + Assert.AreEqual(requeued.DocumentValuePayload, documentInfo.DocumentValuePayload); + Assert.AreEqual(requeued.IngestorRequest.IngestorType, ingestorInfo.IngestorType); + Assert.AreEqual(requeued.IngestorRequest.RootPath, ingestorInfo.IndexFilePath + "\\"); + Assert.AreEqual(requeued.IngestorRequest.IndexFileName, ingestorInfo.IndexFileName); + Assert.AreSame(requeued.OwnerOverrideInfo, ownerOverride); + } + + [Test] + public void QueueOverrideDocumentByDocumentProcessingInfoId_RequeueThrowsException_LogsAndThrowsServiceException() + { + var ownerOverride = SetupSave(OverrideFactory()); + var documentInfo = SetupGetDocumentProcessingInfo(ownerOverride); + SetupGetIngestorRunInfo(documentInfo); + var exceptionToThrow = new Exception(); + var loggedErrors = new List(); + _logger + .Setup(l => l.Write(LogEventLevel.Error, It.IsAny(), It.IsAny())) + .Callback((_, _, log) => loggedErrors.Add(log)); + _mockQueueDocumentProcessing + .Setup(p => p.QueueDocumentProcessingRequest(It.IsAny())) + .Throws(exceptionToThrow); + + var thrownException = Assert.ThrowsAsync(() => _documentReprocessingService.QueueOverrideDocumentByDocumentProcessingInfoId(ownerOverride)); + + StringAssert.Contains(ownerOverride.DocumentProcessingInfoId.ToString(), thrownException!.Message); + Assert.AreEqual(1, loggedErrors.Count); + var errorLog = loggedErrors.Single(); + StringAssert.Contains(ownerOverride.DocumentProcessingInfoId.ToString(), errorLog); + StringAssert.Contains(ownerOverride.EntityId, errorLog); + StringAssert.Contains(ownerOverride.EntityType.ToString(), errorLog); + } + + [Test] + public void QueueReprocessAllCriticalFailures_InfoServiceThrowsArgumentNull_ThrowsServiceException() + { + var processStatus = ProcessStatusTypes.CriticalFailure; + + _mockDocumentProcessingInfoService + .Setup(s => s.GetByProcessStatusTypeAsync(processStatus, null)) + .ThrowsAsync(new ArgumentNullException()); + + Assert.ThrowsAsync(() => _documentReprocessingService.QueueReprocessAllCriticalFailures(Guid.NewGuid().ToString())); + } + + [Test] + public async Task QueueReprocessAllCriticalFailures_InfoServiceThrows_ThrowsServiceException() + { + var processStatus = ProcessStatusTypes.CriticalFailure; + + _mockDocumentProcessingInfoService + .Setup(s => s.GetByProcessStatusTypeAsync(processStatus, null)) + .ThrowsAsync(new Exception()); + + Assert.ThrowsAsync(() => _documentReprocessingService.QueueReprocessAllCriticalFailures(Guid.NewGuid().ToString())); + } + + [Test] + public async Task QueueReprocessAllCriticalFailures_InfoServiceReturnsMoreThanLimit_RequeuesUpToLimit() + { + var processStatus = ProcessStatusTypes.CriticalFailure; + var username = Guid.NewGuid().ToString(); + var criticalFailures = Enumerable + .Repeat(() => SetupGetDocumentProcessingInfo(OverrideFactory()), 16) + .Select(f => f()) + .ToArray(); + foreach (var info in criticalFailures) SetupGetIngestorRunInfo(info); + _apiConfiguration.CriticalFailureReprocessLimit = criticalFailures.Length / 2; + _mockDocumentProcessingInfoService + .Setup(s => s.GetByProcessStatusTypeAsync(processStatus, null)) + .ReturnsAsync(criticalFailures); + + await _documentReprocessingService.QueueReprocessAllCriticalFailures(username); + + _mockDocumentProcessingInfoService + .Verify + ( + s => s.UpdateStatusAndAddLog + ( + It.Is(id => criticalFailures.Any(f => f.DocumentProcessingInfoId == id)), + ProcessStatusTypes.Reprocessing, + It.IsAny(), + username, + null + ), + Times.Exactly(_apiConfiguration.CriticalFailureReprocessLimit) + ); + _mockQueueDocumentProcessing + .Verify + ( + dp => dp.QueueDocumentProcessingRequest + ( + It.Is(r => criticalFailures.Any(f => f.DocumentProcessingInfoId == r.DocumentProcessingInfoId)) + ), + Times.Exactly(_apiConfiguration.CriticalFailureReprocessLimit) + ); + } + + private OwnerOverrideInfo SetupSave(OwnerOverrideInfo ownerOverride) + { + _mockOwnerOverrideInfoService + .Setup(s => s.SaveAsync(ownerOverride)) + .ReturnsAsync(ownerOverride); + + return ownerOverride; + } + + private DocumentProcessingInfo SetupGetDocumentProcessingInfo(OwnerOverrideInfo ownerOverride) + { + var info = new DocumentProcessingInfo + { + IngestorRunInfoId = Guid.NewGuid(), + CreatedDate = DateTime.Now, + DocumentValuePayload = Guid.NewGuid().ToString(), + StatusType = Random(), + DocumentFileName = Guid.NewGuid().ToString(), + ProcessCount = DateTime.Now.Millisecond, + DocumentType = Guid.NewGuid().ToString(), + DocumentBusinessName = Guid.NewGuid().ToString(), + DocumentProcessingInfoId = ownerOverride.DocumentProcessingInfoId + }; + + _mockDocumentProcessingInfoService + .Setup(s => s.GetByIdAsync(ownerOverride.DocumentProcessingInfoId)) + .ReturnsAsync(info); + + return info; + } + + private IngestorRunInfo SetupGetIngestorRunInfo(DocumentProcessingInfo ownerOverride) + { + var info = new IngestorRunInfo + { + IngestorRunInfoId = Guid.NewGuid(), + StartTimeStamp = DateTime.Now, + IngestorType = Random(), + IndexFileName = Guid.NewGuid().ToString(), + IndexFilePath = Guid.NewGuid().ToString(), + IndexTotal = DateTime.Now.Millisecond + }; + + _mockIngestorRunInfoService + .Setup(s => s.GetByIdAsync(ownerOverride.IngestorRunInfoId)) + .ReturnsAsync(info); + + return info; + } + + private static T Random() where T : struct, Enum => Enum.GetValues()[DateTime.Now.Millisecond % (Enum.GetValues().Length - 1)]; +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentTypeArchiveDeleteInfoServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentTypeArchiveDeleteInfoServiceTest.cs new file mode 100644 index 0000000..2aa1505 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/DocumentTypeArchiveDeleteInfoServiceTest.cs @@ -0,0 +1,289 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestorLib.Repositories; +using LCU.Library.DocumentType.Enums; + +namespace LCU.API.Internal.DocumentIngestorTests.Services; + +public class DocumentTypeArchiveDeleteInfoServiceTest +{ + private DocumentTypeArchiveDeleteInfoService _documentTypeArchiveDeleteInfoService; + private Mock _unitOfWork; + private Mock _mockDocumentTypeArchiveDeleteInfoRepository; + + [SetUp] + public void Setup() + { + _unitOfWork = new Mock(); + _mockDocumentTypeArchiveDeleteInfoRepository = new Mock(); + _documentTypeArchiveDeleteInfoService = new DocumentTypeArchiveDeleteInfoService(_unitOfWork.Object, _mockDocumentTypeArchiveDeleteInfoRepository.Object); + } + + [Test] + public async Task GetAsync_DocumentTypeArchiveDeleteInfos_Returned() + { + var processingLogs = new List() + { + new DocumentTypeArchiveDeleteInfo() + { + DocumentTypeName = "Test" + } + }; + _mockDocumentTypeArchiveDeleteInfoRepository.Setup(x => x.FindAsync()).ReturnsAsync(processingLogs); + var result = await _documentTypeArchiveDeleteInfoService.GetAsync(); + Assert.IsNotNull(result); + Assert.AreEqual(1, result.Count()); + _mockDocumentTypeArchiveDeleteInfoRepository.Verify(x => x.FindAsync(), Times.Once); + } + + [Test] + public void GetAsync_Exception() + { + _mockDocumentTypeArchiveDeleteInfoRepository.Setup(x => x.FindAsync()).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _documentTypeArchiveDeleteInfoService.GetAsync()); + _mockDocumentTypeArchiveDeleteInfoRepository.Verify(x => x.FindAsync(), Times.Once); + } + + [Test] + public async Task GetByDocumentTypeNameAsync_ByEnum_DocumentTypeArchiveDeleteInfo_Returned() + { + var documentType = PrimaryOwnerDocumentTypes.OneThousandNinetyNineInt; + var documentTypeName = "OneThousandNinetyNineInt"; + var archiveDays = 200; + var deleteDays = 3000; + var documentTypeArchiveDeleteInfo = new DocumentTypeArchiveDeleteInfo() + { + DocumentTypeName = documentTypeName, + ArchiveDays = archiveDays, + DeleteDays = deleteDays + }; + _mockDocumentTypeArchiveDeleteInfoRepository.Setup(x => x.FindByDocumentTypeNameAsync(documentTypeName)).ReturnsAsync(documentTypeArchiveDeleteInfo); + var result = await _documentTypeArchiveDeleteInfoService.GetByDocumentTypeNameAsync(documentType); + Assert.IsNotNull(result); + Assert.AreEqual(documentTypeName, result.DocumentTypeName); + Assert.AreEqual(archiveDays, result.ArchiveDays); + Assert.AreEqual(deleteDays, result.DeleteDays); + _mockDocumentTypeArchiveDeleteInfoRepository.Verify(x => x.FindByDocumentTypeNameAsync(documentTypeName), Times.Once); + } + + [Test] + public void GetByDocumentTypeNameAsync_ByEnum_Exception() + { + var documentType = PrimaryOwnerDocumentTypes.OneThousandNinetyNineInt; + var documentTypeName = "OneThousandNinetyNineInt"; + _mockDocumentTypeArchiveDeleteInfoRepository.Setup(x => x.FindByDocumentTypeNameAsync(documentTypeName)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _documentTypeArchiveDeleteInfoService.GetByDocumentTypeNameAsync(documentType)); + _mockDocumentTypeArchiveDeleteInfoRepository.Verify(x => x.FindByDocumentTypeNameAsync(documentTypeName), Times.Once); + } + + [Test] + public async Task GetByDocumentTypeNameAsync_DocumentTypeArchiveDeleteInfo_Returned() + { + var documentType = "Test"; + var archiveDays = 200; + var deleteDays = 3000; + var documentTypeArchiveDeleteInfo = new DocumentTypeArchiveDeleteInfo() + { + DocumentTypeName = documentType, + ArchiveDays = archiveDays, + DeleteDays = deleteDays + }; + _mockDocumentTypeArchiveDeleteInfoRepository.Setup(x => x.FindByDocumentTypeNameAsync(documentType)).ReturnsAsync(documentTypeArchiveDeleteInfo); + var result = await _documentTypeArchiveDeleteInfoService.GetByDocumentTypeNameAsync(documentType); + Assert.IsNotNull(result); + Assert.AreEqual(documentType, result.DocumentTypeName); + Assert.AreEqual(archiveDays, result.ArchiveDays); + Assert.AreEqual(deleteDays, result.DeleteDays); + _mockDocumentTypeArchiveDeleteInfoRepository.Verify(x => x.FindByDocumentTypeNameAsync(documentType), Times.Once); + } + + [Test] + public void GetByDocumentTypeNameAsync_Exception() + { + var documentType = "Test"; + _mockDocumentTypeArchiveDeleteInfoRepository.Setup(x => x.FindByDocumentTypeNameAsync(documentType)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _documentTypeArchiveDeleteInfoService.GetByDocumentTypeNameAsync(documentType)); + _mockDocumentTypeArchiveDeleteInfoRepository.Verify(x => x.FindByDocumentTypeNameAsync(documentType), Times.Once); + } + + [Test] + public async Task SaveAsync_ProcessingLog_Returned() + { + var documentType = "Test"; + var archiveDays = 200; + var deleteDays = 3000; + var documentTypeArchiveDeleteInfo = new DocumentTypeArchiveDeleteInfo() + { + DocumentTypeName = documentType, + ArchiveDays = archiveDays, + DeleteDays = deleteDays + }; + _mockDocumentTypeArchiveDeleteInfoRepository.Setup(x => x.AddAsync(documentTypeArchiveDeleteInfo)).ReturnsAsync(documentTypeArchiveDeleteInfo); + var result = await _documentTypeArchiveDeleteInfoService.SaveAsync(documentTypeArchiveDeleteInfo); + Assert.IsNotNull(result); + Assert.AreEqual(documentType, result.DocumentTypeName); + Assert.AreEqual(archiveDays, result.ArchiveDays); + Assert.AreEqual(deleteDays, result.DeleteDays); + _mockDocumentTypeArchiveDeleteInfoRepository.Verify(x => x.AddAsync(It.IsAny()), Times.Once); + } + + [Test] + public void SaveAsync_Exception() + { + var documentType = "Test"; + var archiveDays = 200; + var deleteDays = 3000; + var documentTypeArchiveDeleteInfo = new DocumentTypeArchiveDeleteInfo() + { + DocumentTypeName = documentType, + ArchiveDays = archiveDays, + DeleteDays = deleteDays + }; + _mockDocumentTypeArchiveDeleteInfoRepository.Setup(x => x.AddAsync(documentTypeArchiveDeleteInfo)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _documentTypeArchiveDeleteInfoService.SaveAsync(documentTypeArchiveDeleteInfo)); + _mockDocumentTypeArchiveDeleteInfoRepository.Verify(x => x.AddAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task Update_DocumentTypeArchiveDeleteInfo_Returned() + { + var documentType = "Test"; + var archiveDays = 200; + var deleteDays = 3000; + var existingDocumentTypeArchiveDeleteInfo = new DocumentTypeArchiveDeleteInfo() + { + DocumentTypeName = documentType, + ArchiveDays = archiveDays, + DeleteDays = deleteDays + }; + + var documentTypeArchiveDeleteInfo = new DocumentTypeArchiveDeleteInfo() + { + DocumentTypeName = documentType, + ArchiveDays = archiveDays, + DeleteDays = 4000 + }; + _mockDocumentTypeArchiveDeleteInfoRepository.Setup(x => x.FindByDocumentTypeNameAsync(documentType)).ReturnsAsync(existingDocumentTypeArchiveDeleteInfo); + _mockDocumentTypeArchiveDeleteInfoRepository.Setup(x => x.Update(documentTypeArchiveDeleteInfo)); + + var result = await _documentTypeArchiveDeleteInfoService.Update(documentTypeArchiveDeleteInfo); + Assert.IsNotNull(result); + Assert.AreEqual(documentType, result.DocumentTypeName); + Assert.AreEqual(archiveDays, result.ArchiveDays); + Assert.AreEqual(4000, result.DeleteDays); + _mockDocumentTypeArchiveDeleteInfoRepository.Verify(x => x.FindByDocumentTypeNameAsync(It.IsAny()), Times.Once); + _mockDocumentTypeArchiveDeleteInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Once); + } + + [Test] + public void Update_FindByIdAsync_ThrowsException() + { + var documentType = "Test"; + var archiveDays = 200; + + var documentTypeArchiveDeleteInfo = new DocumentTypeArchiveDeleteInfo() + { + DocumentTypeName = documentType, + ArchiveDays = archiveDays, + DeleteDays = 4000 + }; + _mockDocumentTypeArchiveDeleteInfoRepository.Setup(x => x.FindByDocumentTypeNameAsync(documentType)).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _documentTypeArchiveDeleteInfoService.Update(documentTypeArchiveDeleteInfo)); + _mockDocumentTypeArchiveDeleteInfoRepository.Verify(x => x.FindByDocumentTypeNameAsync(It.IsAny()), Times.Once); + _mockDocumentTypeArchiveDeleteInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Never); + } + + [Test] + public void Update_Update_ThrowsException() + { + var documentType = "Test"; + var archiveDays = 200; + var deleteDays = 3000; + var existingDocumentTypeArchiveDeleteInfo = new DocumentTypeArchiveDeleteInfo() + { + DocumentTypeName = documentType, + ArchiveDays = archiveDays, + DeleteDays = deleteDays + }; + + var documentTypeArchiveDeleteInfo = new DocumentTypeArchiveDeleteInfo() + { + DocumentTypeName = documentType, + ArchiveDays = archiveDays, + DeleteDays = 4000 + }; + _mockDocumentTypeArchiveDeleteInfoRepository.Setup(x => x.FindByDocumentTypeNameAsync(documentType)).ReturnsAsync(existingDocumentTypeArchiveDeleteInfo); + _mockDocumentTypeArchiveDeleteInfoRepository.Setup(x => x.Update(existingDocumentTypeArchiveDeleteInfo)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _documentTypeArchiveDeleteInfoService.Update(documentTypeArchiveDeleteInfo)); + _mockDocumentTypeArchiveDeleteInfoRepository.Verify(x => x.FindByDocumentTypeNameAsync(It.IsAny()), Times.Once); + _mockDocumentTypeArchiveDeleteInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Once); + } + + [Test] + public async Task Delete_Success() + { + var documentType = "Test"; + var archiveDays = 200; + var deleteDays = 3000; + var existingDocumentTypeArchiveDeleteInfo = new DocumentTypeArchiveDeleteInfo() + { + DocumentTypeName = documentType, + ArchiveDays = archiveDays, + DeleteDays = deleteDays + }; + _mockDocumentTypeArchiveDeleteInfoRepository.Setup(x => x.FindByDocumentTypeNameAsync(documentType)).ReturnsAsync(existingDocumentTypeArchiveDeleteInfo); + _mockDocumentTypeArchiveDeleteInfoRepository.Setup(x => x.Remove(existingDocumentTypeArchiveDeleteInfo)); + + await _documentTypeArchiveDeleteInfoService.Delete(documentType); + _mockDocumentTypeArchiveDeleteInfoRepository.Verify(x => x.FindByDocumentTypeNameAsync(documentType), Times.Once); + _mockDocumentTypeArchiveDeleteInfoRepository.Verify(x => x.Remove(It.IsAny()), Times.Once); + } + + [Test] + public void Delete_FindByIdAsync_ThrowsException() + { + var documentType = "Test"; + var archiveDays = 200; + var deleteDays = 3000; + var existingDocumentTypeArchiveDeleteInfo = new DocumentTypeArchiveDeleteInfo() + { + DocumentTypeName = documentType, + ArchiveDays = archiveDays, + DeleteDays = deleteDays + }; + _mockDocumentTypeArchiveDeleteInfoRepository.Setup(x => x.FindByDocumentTypeNameAsync(documentType)).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _documentTypeArchiveDeleteInfoService.Delete(documentType)); + _mockDocumentTypeArchiveDeleteInfoRepository.Verify(x => x.FindByDocumentTypeNameAsync(documentType), Times.Once); + _mockDocumentTypeArchiveDeleteInfoRepository.Verify(x => x.Remove(It.IsAny()), Times.Never); + } + + [Test] + public void Delete_Remove_ThrowsException() + { + var documentType = "Test"; + var archiveDays = 200; + var deleteDays = 3000; + var existingDocumentTypeArchiveDeleteInfo = new DocumentTypeArchiveDeleteInfo() + { + DocumentTypeName = documentType, + ArchiveDays = archiveDays, + DeleteDays = deleteDays + }; + _mockDocumentTypeArchiveDeleteInfoRepository.Setup(x => x.FindByDocumentTypeNameAsync(documentType)).ReturnsAsync(existingDocumentTypeArchiveDeleteInfo); + _mockDocumentTypeArchiveDeleteInfoRepository.Setup(x => x.Remove(existingDocumentTypeArchiveDeleteInfo)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _documentTypeArchiveDeleteInfoService.Delete(documentType)); + _mockDocumentTypeArchiveDeleteInfoRepository.Verify(x => x.FindByDocumentTypeNameAsync(documentType), Times.Once); + _mockDocumentTypeArchiveDeleteInfoRepository.Verify(x => x.Remove(It.IsAny()), Times.Once); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/FosDnaDocumentIndexServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/FosDnaDocumentIndexServiceTest.cs new file mode 100644 index 0000000..2653c60 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/FosDnaDocumentIndexServiceTest.cs @@ -0,0 +1,132 @@ +using System; +using System.Threading.Tasks; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using Moq; +using NUnit.Framework; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.IndexParserServices; + +public class FosDnaDocumentIndexServiceTest +{ + private FosDnaDocumentIndexService _fosDnaDocumentIndexService; + private Mock _mockFileOperationsApiService; + + [SetUp] + public void Setup() + { + _mockFileOperationsApiService = new Mock(); + var serviceFactoryConfiguration = new ServicesFactoryConfiguration + { + ServiceFactoryRegistrations = new List + { + new() + { + ServiceInterfaceName = "IIndexParserService", + ServiceRegistrations = new List + { + new() + { + ServiceName = "IndexParserService", + ServiceId = "4" + }, + new() + { + ServiceName = "IndexParserService", + ServiceId = "1" + } + } + } + } + }; + _fosDnaDocumentIndexService = new FosDnaDocumentIndexService(_mockFileOperationsApiService.Object, serviceFactoryConfiguration); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_Null_IngestorResult_Failure() + { + IngestorRequest request = null; + var result = await _fosDnaDocumentIndexService.HandleIndexRequest(request); + Assert.IsTrue(result.FatalFailure); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Never); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_Success() + { + var request = new IngestorRequest + { + RootPath = "\\Test\\", + IndexFileName = "Test.csv" + }; + const string fileContent = "\"220299012291\",\"CURTIS M, MACIK\",\"03072022\",\"LN_NENT\",\"03f6bd41-7aae-4160-8a16-06583f75916c.pdf\""; + _mockFileOperationsApiService.Setup(x => x.GetFileContent(It.IsAny())).ReturnsAsync(fileContent); + + var result = await _fosDnaDocumentIndexService.HandleIndexRequest(request); + Assert.IsFalse(result.FatalFailure); + Assert.AreEqual(1, result.ProcessingRequests.Count); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Once); + + var firstPayloadObject = result.ProcessingRequests.First().DocumentValuePayload; + var fosDnaDocumentRecord = JsonSerializer.Deserialize(firstPayloadObject); + Assert.NotNull(fosDnaDocumentRecord); + Assert.AreEqual("220299012291", fosDnaDocumentRecord.AccountNumber); + Assert.AreEqual("03f6bd41-7aae-4160-8a16-06583f75916c.pdf", fosDnaDocumentRecord.DocName); + Assert.AreEqual("LN_NENT", fosDnaDocumentRecord.DocType); + Assert.AreEqual("CURTIS M, MACIK", fosDnaDocumentRecord.EntityName); + Assert.AreEqual("03072022", fosDnaDocumentRecord.CreationDate); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_GetFileContent_ThrowsException_Failure() + { + var request = new IngestorRequest + { + RootPath = "\\Test\\", + IndexFileName = "Test.csv" + }; + _mockFileOperationsApiService.Setup(x => x.GetFileContent(It.IsAny())).ThrowsAsync(new Exception("Error")); + + var result = await _fosDnaDocumentIndexService.HandleIndexRequest(request); + Assert.IsTrue(result.FatalFailure); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Once); + } + + [Test] + public void PrepareRunInfoAndProcessRequests_IngestorRunInfo_ProcessRequests_Created() + { + var request = new IngestorRequest + { + RootPath = "\\Test\\", + IndexFileName = "Test.csv", + IngestorType = IngestorTypes.FosTaxStatement, + }; + + var documentMetaData = new List + { + new() + { + AccountNumber = "1", + DocType = "1099-INT", + EntityName = "tester", + DocName = "test.pdf", + CreationDate = "01022003" + } + }; + var ingestorResult = new IngestorResult(); + + var result = _fosDnaDocumentIndexService.PrepareRunInfoAndProcessRequests(request, documentMetaData, ingestorResult); + Assert.IsFalse(result.FatalFailure); + Assert.AreEqual(1, result.ProcessingRequests.Count); + Assert.AreEqual("Test.csv", result.IngestorRunInfo.IndexFileName); + Assert.AreEqual(IngestorTypes.FosTaxStatement, result.IngestorRunInfo.IngestorType); + Assert.AreEqual("\\Test\\", result.IngestorRunInfo.IndexFilePath); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/FosLoanStatementIndexServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/FosLoanStatementIndexServiceTest.cs new file mode 100644 index 0000000..87b0e21 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/FosLoanStatementIndexServiceTest.cs @@ -0,0 +1,153 @@ +using System; +using System.Threading.Tasks; +using System.Collections.Generic; +using Moq; +using NUnit.Framework; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.Library.Internal.FileOperationsModels.Models.NameSettings; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.IndexParserServices; + +public class FosLoanStatementIndexServiceTest +{ + private FosLoanStatementIndexService _fosLoanStatementIndexService; + private Mock _mockFileOperationsApiService; + + [SetUp] + public void Setup() + { + _mockFileOperationsApiService = new Mock(); + var serviceFactoryConfiguration = new ServicesFactoryConfiguration + { + ServiceFactoryRegistrations = new List + { + new() + { + ServiceInterfaceName = "IIndexParserService", + ServiceRegistrations = new List + { + new() + { + ServiceName = "IndexParserService", + ServiceId = "4" + }, + new() + { + ServiceName = "IndexParserService", + ServiceId = "3" + } + } + } + } + }; + _fosLoanStatementIndexService = new FosLoanStatementIndexService(_mockFileOperationsApiService.Object, + serviceFactoryConfiguration); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_Null_IngestorResult_Failure() + { + IngestorRequest request = null; + var result = await _fosLoanStatementIndexService.HandleIndexRequest(request); + Assert.IsTrue(result.FatalFailure); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Never); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_Success() + { + var rootPath = "\\Test\\"; + var request = new IngestorRequest() + { + RootPath = rootPath, + IndexFileName = "NAU123456789.91.21.txt", + IngestorType = IngestorTypes.FosLoanStatement + }; + var fileContent = "\"Mortgage Statement\"|\"11111111111111111111111\"|\"11\"|\"N\"|\"1111\"" + + "|\"Test, Tester\"|\"test@test.com\"|\"111111111\"|\"2\"|\"4\"|\"test.pdf\"\n" + + "\"Loan Statement\"|\"11111111111111111111111\"|\"11\"|\"N\"|\"1111\"" + + "|\"Tester Testing\"|\"test1@test.com\"|\"111111111\"|\"1\"|\"3\"|\"tester.pdf\""; + var requestResponse = new RequestResponse() + { + IsSuccessful = true + }; + var dynamicFileRequest = new DynamicFileListRequest() + { + Path = rootPath, + Filename = "replaceTag.pdf", + DynamicFileSettings = new DynamicNameSetting() + { + RegexSettings = new List() + { + new RegexSetting() + { + Tag = "replaceTag", + Regex = ".*" + } + } + } + }; + _mockFileOperationsApiService.Setup(x => x.GetFileContent(It.IsAny())).ReturnsAsync(fileContent); + + var result = await _fosLoanStatementIndexService.HandleIndexRequest(request); + Assert.IsFalse(result.FatalFailure); + Assert.AreEqual(2, result.ProcessingRequests.Count); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Once); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_GetFileContent_ThrowsException_Failure() + { + var request = new IngestorRequest() + { + RootPath = "\\Test\\", + IndexFileName = "Test.csv", + IngestorType = IngestorTypes.FosLoanStatement + }; + _mockFileOperationsApiService.Setup(x => x.GetFileContent(It.IsAny())).ThrowsAsync(new Exception("Error")); + + var result = await _fosLoanStatementIndexService.HandleIndexRequest(request); + Assert.IsTrue(result.FatalFailure); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Once); + } + + [Test] + public void PrepareRunInfoAndProcessRequests_IngestorRunInfo_ProcessRequests_Created() + { + var request = new IngestorRequest() + { + RootPath = "\\Test\\", + IndexFileName = "Test.csv", + IngestorType = IngestorTypes.FosLoanStatement + }; + + var documentMetaData = new List() + { + new FosLoanStatement() + { + AccountNumber = "111111", + CreationDate = "04012023", + DocName = "test.pdf", + EmailAddress = "test@test.com", + EntityName = "Test Tester", + StartingPage = "2", + NumberOfPages = "3", + DocType = "Mortgage Statement" + } + }; + var ingestorResult = new IngestorResult(); + + var result = _fosLoanStatementIndexService.PrepareRunInfoAndProcessRequests(request, documentMetaData, ingestorResult); + Assert.IsFalse(result.FatalFailure); + Assert.AreEqual(1, result.ProcessingRequests.Count); + Assert.AreEqual("Test.csv", result.IngestorRunInfo.IndexFileName); + Assert.AreEqual(IngestorTypes.FosLoanStatement, result.IngestorRunInfo.IngestorType); + Assert.AreEqual("\\Test\\", result.IngestorRunInfo.IndexFilePath); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/FosTaxStatementIndexServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/FosTaxStatementIndexServiceTest.cs new file mode 100644 index 0000000..5efaee9 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/FosTaxStatementIndexServiceTest.cs @@ -0,0 +1,122 @@ +using System; +using System.Threading.Tasks; +using System.Collections.Generic; +using Moq; +using NUnit.Framework; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.IndexParserServices; + +public class FosTaxStatementIndexServiceTest +{ + private FosTaxStatementIndexService _fosTaxStatementIndexService; + private Mock _mockFileOperationsApiService; + + [SetUp] + public void Setup() + { + _mockFileOperationsApiService = new Mock(); + var serviceFactoryConfiguration = new ServicesFactoryConfiguration + { + ServiceFactoryRegistrations = new List + { + new() + { + ServiceInterfaceName = "IIndexParserService", + ServiceRegistrations = new List + { + new() + { + ServiceName = "IndexParserService", + ServiceId = "4" + }, + new() + { + ServiceName = "IndexParserService", + ServiceId = "0" + } + } + } + } + }; + _fosTaxStatementIndexService = new FosTaxStatementIndexService(_mockFileOperationsApiService.Object, + serviceFactoryConfiguration); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_Null_IngestorResult_Failure() + { + IngestorRequest request = null; + var result = await _fosTaxStatementIndexService.HandleIndexRequest(request); + Assert.IsTrue(result.FatalFailure); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Never); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_Success() + { + var request = new IngestorRequest() + { + RootPath = "\\Test\\", + IndexFileName = "Test.csv" + }; + var fileContent = "1099 - INT,999999999,Test Tester T,2012,12345674,0000000001.pdf"; + _mockFileOperationsApiService.Setup(x => x.GetFileContent(It.IsAny())).ReturnsAsync(fileContent); + + var result = await _fosTaxStatementIndexService.HandleIndexRequest(request); + Assert.IsFalse(result.FatalFailure); + Assert.AreEqual(1, result.ProcessingRequests.Count); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Once); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_GetFileContent_ThrowsException_Failure() + { + var request = new IngestorRequest() + { + RootPath = "\\Test\\", + IndexFileName = "Test.csv" + }; + _mockFileOperationsApiService.Setup(x => x.GetFileContent(It.IsAny())).ThrowsAsync(new Exception("Error")); + + var result = await _fosTaxStatementIndexService.HandleIndexRequest(request); + Assert.IsTrue(result.FatalFailure); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Once); + } + + [Test] + public void PrepareRunInfoAndProcessRequests_IngestorRunInfo_ProcessRequests_Created() + { + var request = new IngestorRequest() + { + RootPath = "\\Test\\", + IndexFileName = "Test.csv", + IngestorType = IngestorTypes.FosTaxStatement + }; + + var documentMetaData = new List() + { + new FosTaxStatementDocument() + { + AccountNumber = "1", + FileName = "1099-INT", + PrimaryTIN = "1", + FullName = "tester", + PDF = "test.pdf" + } + }; + var ingestorResult = new IngestorResult(); + + var result = _fosTaxStatementIndexService.PrepareRunInfoAndProcessRequests(request, documentMetaData, ingestorResult); + Assert.IsFalse(result.FatalFailure); + Assert.AreEqual(1, result.ProcessingRequests.Count); + Assert.AreEqual("Test.csv", result.IngestorRunInfo.IndexFileName); + Assert.AreEqual(IngestorTypes.FosTaxStatement, result.IngestorRunInfo.IngestorType); + Assert.AreEqual("\\Test\\", result.IngestorRunInfo.IndexFilePath); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/OsgDnaNoticeSplitIndexServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/OsgDnaNoticeSplitIndexServiceTest.cs new file mode 100644 index 0000000..8216caa --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/OsgDnaNoticeSplitIndexServiceTest.cs @@ -0,0 +1,123 @@ +using System; +using System.Threading.Tasks; +using System.Collections.Generic; +using Moq; +using NUnit.Framework; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.IndexParserServices; + +public class OsgDnaNoticeSplitIndexServiceTest +{ + private OsgDnaNoticeSplitIndexService _osgDnaNoticeSplitIndexService; + private Mock _mockFileOperationsApiService; + + [SetUp] + public void Setup() + { + _mockFileOperationsApiService = new Mock(); + var serviceFactoryConfiguration = new ServicesFactoryConfiguration + { + ServiceFactoryRegistrations = new List + { + new() + { + ServiceInterfaceName = "IIndexParserService", + ServiceRegistrations = new List + { + new() + { + ServiceName = "IndexParserService", + ServiceId = "4" + }, + new() + { + ServiceName = "IndexParserService", + ServiceId = "9" + } + } + } + } + }; + _osgDnaNoticeSplitIndexService = new OsgDnaNoticeSplitIndexService(_mockFileOperationsApiService.Object, + serviceFactoryConfiguration); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_Null_IngestorResult_Failure() + { + IngestorRequest request = null; + var result = await _osgDnaNoticeSplitIndexService.HandleIndexRequest(request); + Assert.IsTrue(result.FatalFailure); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Never); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_Success() + { + var request = new IngestorRequest() + { + RootPath = "\\Test\\", + IndexFileName = "Test.csv" + }; + var fileContent = "1|OPS_NT_129|1234567890||111111|Test Tester||OD Government Funds Notice||02242025|1804777185.pdf"; + _mockFileOperationsApiService.Setup(x => x.GetFileContent(It.IsAny())).ReturnsAsync(fileContent); + + var result = await _osgDnaNoticeSplitIndexService.HandleIndexRequest(request); + Assert.IsFalse(result.FatalFailure); + Assert.AreEqual(1, result.ProcessingRequests.Count); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Once); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_GetFileContent_ThrowsException_Failure() + { + var request = new IngestorRequest() + { + RootPath = "\\Test\\", + IndexFileName = "Test.csv" + }; + _mockFileOperationsApiService.Setup(x => x.GetFileContent(It.IsAny())).ThrowsAsync(new Exception("Error")); + + var result = await _osgDnaNoticeSplitIndexService.HandleIndexRequest(request); + Assert.IsTrue(result.FatalFailure); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Once); + } + + [Test] + public void PrepareRunInfoAndProcessRequests_IngestorRunInfo_ProcessRequests_Created() + { + var request = new IngestorRequest() + { + RootPath = "\\Test\\", + IndexFileName = "Test.csv", + IngestorType = IngestorTypes.OsgDnaNoticeSplit + }; + + var documentMetaData = new List() + { + new OsgDnaNoticeSplit() + { + AccountNumber = "1", + NoticeName = "OPS_NT_129", + MemberNumber = "1", + RecipientName = "tester", + PdfName = "test.pdf" + } + }; + var ingestorResult = new IngestorResult(); + + var result = _osgDnaNoticeSplitIndexService.PrepareRunInfoAndProcessRequests(request, documentMetaData, ingestorResult); + Assert.IsFalse(result.FatalFailure); + Assert.AreEqual(1, result.ProcessingRequests.Count); + Assert.AreEqual("Test.csv", result.IngestorRunInfo.IndexFileName); + Assert.AreEqual(IngestorTypes.OsgDnaNoticeSplit, result.IngestorRunInfo.IngestorType); + Assert.AreEqual("\\Test\\", result.IngestorRunInfo.IndexFilePath); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/OsgDnaNoticesIndexServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/OsgDnaNoticesIndexServiceTest.cs new file mode 100644 index 0000000..30724fc --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/OsgDnaNoticesIndexServiceTest.cs @@ -0,0 +1,153 @@ +using System; +using System.Threading.Tasks; +using System.Collections.Generic; +using Moq; +using NUnit.Framework; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.Library.Internal.FileOperationsModels.Models.NameSettings; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.IndexParserServices; + +public class OsgDnaNoticesIndexServiceTest +{ + private OsgDnaNoticesIndexService _osgDnaNoticesIndexService; + private Mock _mockFileOperationsApiService; + + [SetUp] + public void Setup() + { + _mockFileOperationsApiService = new Mock(); + var serviceFactoryConfiguration = new ServicesFactoryConfiguration + { + ServiceFactoryRegistrations = new List + { + new() + { + ServiceInterfaceName = "IIndexParserService", + ServiceRegistrations = new List + { + new() + { + ServiceName = "IndexParserService", + ServiceId = "4" + }, + new() + { + ServiceName = "IndexParserService", + ServiceId = "1" + } + } + } + } + }; + _osgDnaNoticesIndexService = new OsgDnaNoticesIndexService(_mockFileOperationsApiService.Object, + serviceFactoryConfiguration); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_Null_IngestorResult_Failure() + { + IngestorRequest request = null; + var result = await _osgDnaNoticesIndexService.HandleIndexRequest(request); + Assert.IsTrue(result.FatalFailure); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Never); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_Success() + { + var rootPath = "\\Test\\"; + var request = new IngestorRequest() + { + RootPath = rootPath, + IndexFileName = "PDFXREF.TXT", + IngestorType = IngestorTypes.OsgDnaNoticesDocument + }; + var fileContent = "00000001|LCL_LT_114_03|5651830147|5651830|20220823|1|1\n" + + "00000002|LVI_LT_105_03|19619353841|8996218227|20220823|2|1\n"; + + var requestResponse = new RequestResponse() + { + IsSuccessful = true + }; + var dynamicFileRequest = new DynamicFileListRequest() + { + Path = rootPath, + Filename = "replaceTag.pdf", + DynamicFileSettings = new DynamicNameSetting() + { + RegexSettings = new List() + { + new RegexSetting() + { + Tag = "replaceTag", + Regex = ".*" + } + } + } + }; + _mockFileOperationsApiService.Setup(x => x.GetFileContent(It.IsAny())).ReturnsAsync(fileContent); + + var result = await _osgDnaNoticesIndexService.HandleIndexRequest(request); + + Assert.IsFalse(result.FatalFailure); + Assert.AreEqual(2, result.ProcessingRequests.Count); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Once); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_GetFileContent_ThrowsException_Failure() + { + var request = new IngestorRequest() + { + RootPath = "\\Test\\", + IndexFileName = "PDFXREF.TXT", + IngestorType = IngestorTypes.OsgDnaNoticesDocument + }; + _mockFileOperationsApiService.Setup(x => x.GetFileContent(It.IsAny())).ThrowsAsync(new Exception("Error")); + + var result = await _osgDnaNoticesIndexService.HandleIndexRequest(request); + + Assert.IsTrue(result.FatalFailure); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Once); + } + + [Test] + public void PrepareRunInfoAndProcessRequests_IngestorRunInfo_ProcessRequests_Created() + { + var request = new IngestorRequest() + { + RootPath = "\\Test\\", + IndexFileName = "PDFXREF.TXT", + IngestorType = IngestorTypes.OsgDnaNoticesDocument + }; + + var documentMetaData = new List() + { + new OsgDnaNoticesDocument() + { + DocType = "TestDocType", + AccountNumber = "1", + MemberNumberOrUserId = "2", + CreationDate = "20220823", + StartingPage = "1", + NumberOfPages = "3" + } + }; + var ingestorResult = new IngestorResult(); + + var result = _osgDnaNoticesIndexService.PrepareRunInfoAndProcessRequests(request, documentMetaData, ingestorResult); + + Assert.IsFalse(result.FatalFailure); + Assert.AreEqual(1, result.ProcessingRequests.Count); + Assert.AreEqual("PDFXREF.TXT", result.IngestorRunInfo.IndexFileName); + Assert.AreEqual(IngestorTypes.OsgDnaNoticesDocument, result.IngestorRunInfo.IngestorType); + Assert.AreEqual("\\Test\\", result.IngestorRunInfo.IndexFilePath); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/OsgHistoricalDocumentIndexServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/OsgHistoricalDocumentIndexServiceTest.cs new file mode 100644 index 0000000..245376e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/OsgHistoricalDocumentIndexServiceTest.cs @@ -0,0 +1,153 @@ +using System; +using System.Threading.Tasks; +using System.Collections.Generic; +using Moq; +using NUnit.Framework; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.Library.Internal.FileOperationsModels.Models.NameSettings; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.IndexParserServices; + +public class OsgHistoricalDocumentIndexServiceTest +{ + private OsgHistoricalDocumentIndexService _osgHistoricalDocumentIndexService; + private Mock _mockFileOperationsApiService; + + [SetUp] + public void Setup() + { + _mockFileOperationsApiService = new Mock(); + var serviceFactoryConfiguration = new ServicesFactoryConfiguration + { + ServiceFactoryRegistrations = new List + { + new() + { + ServiceInterfaceName = "IIndexParserService", + ServiceRegistrations = new List + { + new() + { + ServiceName = "IndexParserService", + ServiceId = "4" + }, + new() + { + ServiceName = "IndexParserService", + ServiceId = "6" + } + } + } + } + }; + _osgHistoricalDocumentIndexService = new OsgHistoricalDocumentIndexService(_mockFileOperationsApiService.Object, + serviceFactoryConfiguration); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_Null_IngestorResult_Failure() + { + IngestorRequest request = null; + var result = await _osgHistoricalDocumentIndexService.HandleIndexRequest(request); + Assert.IsTrue(result.FatalFailure); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Never); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_Success() + { + var rootPath = "\\Test\\"; + var request = new IngestorRequest() + { + RootPath = rootPath, + IndexFileName = "PDFXREF.TXT", + IngestorType = IngestorTypes.OsgDnaNoticesDocument + }; + var fileContent = "00000001|LCL_LT_114_03|5651830147|5651830|20220823|1|1\n" + + "00000002|LVI_LT_105_03|19619353841|8996218227|20220823|2|1\n"; + + var requestResponse = new RequestResponse() + { + IsSuccessful = true + }; + var dynamicFileRequest = new DynamicFileListRequest() + { + Path = rootPath, + Filename = "replaceTag.pdf", + DynamicFileSettings = new DynamicNameSetting() + { + RegexSettings = new List() + { + new RegexSetting() + { + Tag = "replaceTag", + Regex = ".*" + } + } + } + }; + _mockFileOperationsApiService.Setup(x => x.GetFileContent(It.IsAny())).ReturnsAsync(fileContent); + + var result = await _osgHistoricalDocumentIndexService.HandleIndexRequest(request); + + Assert.IsFalse(result.FatalFailure); + Assert.AreEqual(2, result.ProcessingRequests.Count); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Once); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_GetFileContent_ThrowsException_Failure() + { + var request = new IngestorRequest() + { + RootPath = "\\Test\\", + IndexFileName = "PDFXREF.TXT", + IngestorType = IngestorTypes.OsgHistoricalDocument + }; + _mockFileOperationsApiService.Setup(x => x.GetFileContent(It.IsAny())).ThrowsAsync(new Exception("Error")); + + var result = await _osgHistoricalDocumentIndexService.HandleIndexRequest(request); + + Assert.IsTrue(result.FatalFailure); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Once); + } + + [Test] + public void PrepareRunInfoAndProcessRequests_IngestorRunInfo_ProcessRequests_Created() + { + var request = new IngestorRequest() + { + RootPath = "\\Test\\", + IndexFileName = "PDFXREF.TXT", + IngestorType = IngestorTypes.OsgHistoricalDocument + }; + + var documentMetaData = new List() + { + new OsgHistoricalDocument() + { + DocType = "TestDocType", + EntityName = "John Jim", + MemberNumberOrUserId = "2", + CreationDate = "20220823", + StartingPage = "1", + NumberOfPages = "3" + } + }; + var ingestorResult = new IngestorResult(); + + var result = _osgHistoricalDocumentIndexService.PrepareRunInfoAndProcessRequests(request, documentMetaData, ingestorResult); + + Assert.IsFalse(result.FatalFailure); + Assert.AreEqual(1, result.ProcessingRequests.Count); + Assert.AreEqual("PDFXREF.TXT", result.IngestorRunInfo.IndexFileName); + Assert.AreEqual(IngestorTypes.OsgHistoricalDocument, result.IngestorRunInfo.IngestorType); + Assert.AreEqual("\\Test\\", result.IngestorRunInfo.IndexFilePath); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/OsgTaxStatementIndexServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/OsgTaxStatementIndexServiceTest.cs new file mode 100644 index 0000000..8d73384 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/OsgTaxStatementIndexServiceTest.cs @@ -0,0 +1,123 @@ +using System; +using System.Threading.Tasks; +using System.Collections.Generic; +using Moq; +using NUnit.Framework; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.IndexParserServices; + +public class OsgTaxStatementIndexServiceTest +{ + private OsgTaxStatementIndexService _osgTaxStatementIndexService; + private Mock _mockFileOperationsApiService; + + [SetUp] + public void Setup() + { + _mockFileOperationsApiService = new Mock(); + var serviceFactoryConfiguration = new ServicesFactoryConfiguration + { + ServiceFactoryRegistrations = new List + { + new() + { + ServiceInterfaceName = "IIndexParserService", + ServiceRegistrations = new List + { + new() + { + ServiceName = "IndexParserService", + ServiceId = "4" + }, + new() + { + ServiceName = "IndexParserService", + ServiceId = "8" + } + } + } + } + }; + _osgTaxStatementIndexService = new OsgTaxStatementIndexService(_mockFileOperationsApiService.Object, + serviceFactoryConfiguration); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_Null_IngestorResult_Failure() + { + IngestorRequest request = null; + var result = await _osgTaxStatementIndexService.HandleIndexRequest(request); + Assert.IsTrue(result.FatalFailure); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Never); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_Success() + { + var request = new IngestorRequest() + { + RootPath = "\\Test\\", + IndexFileName = "Test.csv" + }; + var fileContent = "1||1281|||Test Name Tester|111-11-1111|1098||12162024|TAXFORM_1098_Test Name Tester_1281.PDF"; + _mockFileOperationsApiService.Setup(x => x.GetFileContent(It.IsAny())).ReturnsAsync(fileContent); + + var result = await _osgTaxStatementIndexService.HandleIndexRequest(request); + Assert.IsFalse(result.FatalFailure); + Assert.AreEqual(1, result.ProcessingRequests.Count); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Once); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_GetFileContent_ThrowsException_Failure() + { + var request = new IngestorRequest() + { + RootPath = "\\Test\\", + IndexFileName = "Test.csv" + }; + _mockFileOperationsApiService.Setup(x => x.GetFileContent(It.IsAny())).ThrowsAsync(new Exception("Error")); + + var result = await _osgTaxStatementIndexService.HandleIndexRequest(request); + Assert.IsTrue(result.FatalFailure); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Once); + } + + [Test] + public void PrepareRunInfoAndProcessRequests_IngestorRunInfo_ProcessRequests_Created() + { + var request = new IngestorRequest() + { + RootPath = "\\Test\\", + IndexFileName = "Test.csv", + IngestorType = IngestorTypes.OsgTaxStatement + }; + + var documentMetaData = new List() + { + new OsgTaxStatement() + { + AccountNumber = "1", + NoticeName = "1099-INT", + SSN = "1", + RecipientName = "tester", + PdfName = "test.pdf" + } + }; + var ingestorResult = new IngestorResult(); + + var result = _osgTaxStatementIndexService.PrepareRunInfoAndProcessRequests(request, documentMetaData, ingestorResult); + Assert.IsFalse(result.FatalFailure); + Assert.AreEqual(1, result.ProcessingRequests.Count); + Assert.AreEqual("Test.csv", result.IngestorRunInfo.IndexFileName); + Assert.AreEqual(IngestorTypes.OsgTaxStatement, result.IngestorRunInfo.IngestorType); + Assert.AreEqual("\\Test\\", result.IngestorRunInfo.IndexFilePath); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/XdiActionNoticeDocumentIndexServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/XdiActionNoticeDocumentIndexServiceTest.cs new file mode 100644 index 0000000..8235fdc --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/XdiActionNoticeDocumentIndexServiceTest.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq; +using System.Text.Json; +using Moq; +using NUnit.Framework; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.IndexParserServices; + +public class XdiActionNoticeDocumentIndexServiceTest +{ + private XdiActionNoticeDocumentIndexService _xdiActionNoticeDocumentIndexService; + private Mock _mockFileOperationsApiService; + + [SetUp] + public void Setup() + { + _mockFileOperationsApiService = new Mock(); + var serviceFactoryConfiguration = new ServicesFactoryConfiguration + { + ServiceFactoryRegistrations = new List + { + new() + { + ServiceInterfaceName = "IIndexParserService", + ServiceRegistrations = new List + { + new() + { + ServiceName = "IndexParserService", + ServiceId = "5" + }, + new() + { + ServiceName = "IndexParserService", + ServiceId = "1" + } + } + } + } + }; + _xdiActionNoticeDocumentIndexService = new XdiActionNoticeDocumentIndexService(_mockFileOperationsApiService.Object, + serviceFactoryConfiguration); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_Null_IngestorResult_Failure() + { + IngestorRequest request = null; + var result = await _xdiActionNoticeDocumentIndexService.HandleIndexRequest(request); + Assert.IsTrue(result.FatalFailure); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Never); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_Success() + { + var request = new IngestorRequest + { + RootPath = "\\Test\\", + IndexFileName = "Test.csv", + IngestorType = IngestorTypes.XdiActionNotice + }; + const string fileContent = "08/08/2022|0001853948|00|PRUDENCIANO RAMOS|1|ACTion_Declined Loan Letter|ACTion_Declined Loan Letter|10270_20220808144204_00000023.PDF"; + _mockFileOperationsApiService.Setup(x => x.GetFileContent(It.IsAny())).ReturnsAsync(fileContent); + + var result = await _xdiActionNoticeDocumentIndexService.HandleIndexRequest(request); + Assert.IsFalse(result.FatalFailure); + Assert.AreEqual(1, result.ProcessingRequests.Count); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Once); + + var firstPayloadObject = result.ProcessingRequests.First().DocumentValuePayload; + var xdiActionDocumentRecord = JsonSerializer.Deserialize(firstPayloadObject); + Assert.NotNull(xdiActionDocumentRecord); + Assert.AreEqual("10270_20220808144204_00000023.PDF", xdiActionDocumentRecord.DocumentName); + Assert.AreEqual(1, xdiActionDocumentRecord.PageCount); + Assert.AreEqual("ACTion_Declined Loan Letter", xdiActionDocumentRecord.DocumentType); + Assert.AreEqual("PRUDENCIANO RAMOS", xdiActionDocumentRecord.EntityName); + Assert.AreEqual("08/08/2022", xdiActionDocumentRecord.CreationDate); + + Assert.AreEqual(1, result.ProcessingRequests.Count); + + var initialRunInfo = result.IngestorRunInfo; + Assert.AreEqual(request.IndexFileName, initialRunInfo.IndexFileName); + Assert.AreEqual(request.RootPath, initialRunInfo.IndexFilePath); + Assert.AreEqual(IngestorTypes.XdiActionNotice, initialRunInfo.IngestorType); + Assert.AreEqual(DateTime.Now.Date, initialRunInfo.StartTimeStamp.Date); + Assert.AreEqual("\\Test\\", initialRunInfo.IndexFilePath); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_GetFileContent_ThrowsException_Failure() + { + var request = new IngestorRequest + { + RootPath = "\\Test\\", + IndexFileName = "Test.csv" + }; + _mockFileOperationsApiService.Setup(x => x.GetFileContent(It.IsAny())).ThrowsAsync(new Exception("Error")); + + var result = await _xdiActionNoticeDocumentIndexService.HandleIndexRequest(request); + Assert.IsTrue(result.FatalFailure); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Once); + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/XdiDnaNoticeDocumentIndexServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/XdiDnaNoticeDocumentIndexServiceTest.cs new file mode 100644 index 0000000..b8a3806 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IndexParserServices/XdiDnaNoticeDocumentIndexServiceTest.cs @@ -0,0 +1,112 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq; +using System.Text.Json; +using Moq; +using NUnit.Framework; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.LCUServiceFactory.Configurations; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.IndexParserServices; + +public class XdiDnaNoticeDocumentIndexServiceTest +{ + private XdiDnaNoticeDocumentIndexService _xdiDnaNoticeDocumentIndexService; + private Mock _mockFileOperationsApiService; + + [SetUp] + public void Setup() + { + _mockFileOperationsApiService = new Mock(); + var serviceFactoryConfiguration = new ServicesFactoryConfiguration + { + ServiceFactoryRegistrations = new List + { + new() + { + ServiceInterfaceName = "IIndexParserService", + ServiceRegistrations = new List + { + new() + { + ServiceName = "IndexParserService", + ServiceId = "4" + }, + new() + { + ServiceName = "IndexParserService", + ServiceId = "2" + } + } + } + } + }; + _xdiDnaNoticeDocumentIndexService = new XdiDnaNoticeDocumentIndexService(_mockFileOperationsApiService.Object, serviceFactoryConfiguration); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_Null_IngestorResult_Failure() + { + IngestorRequest request = null; + var result = await _xdiDnaNoticeDocumentIndexService.HandleIndexRequest(request); + Assert.IsTrue(result.FatalFailure); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Never); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_Success() + { + var request = new IngestorRequest + { + RootPath = "\\Test\\", + IndexFileName = "Test.csv", + IngestorType = IngestorTypes.XdiDnaNotice + }; + const string fileContent = "05/12/2022|1748070144|00|Zachary Ps Buth|2|22 Day Past Due Letter|22 Day Past Due Letter|10270_20220512234318_00000011.PDF"; + _mockFileOperationsApiService.Setup(x => x.GetFileContent(It.IsAny())).ReturnsAsync(fileContent); + + var result = await _xdiDnaNoticeDocumentIndexService.HandleIndexRequest(request); + Assert.IsFalse(result.FatalFailure); + Assert.AreEqual(1, result.ProcessingRequests.Count); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Once); + + var firstPayloadObject = result.ProcessingRequests.First().DocumentValuePayload; + var xdiDnaDocumentRecord = JsonSerializer.Deserialize(firstPayloadObject); + Assert.NotNull(xdiDnaDocumentRecord); + Assert.AreEqual("1748070144", xdiDnaDocumentRecord.AccountNumber); + Assert.AreEqual("10270_20220512234318_00000011.PDF", xdiDnaDocumentRecord.PDF); + Assert.AreEqual(2, xdiDnaDocumentRecord.PageCount); + Assert.AreEqual("22 Day Past Due Letter", xdiDnaDocumentRecord.DocumentType); + Assert.AreEqual("Zachary Ps Buth", xdiDnaDocumentRecord.EntityName); + Assert.AreEqual("05/12/2022", xdiDnaDocumentRecord.CreationDate); + + Assert.AreEqual(1, result.ProcessingRequests.Count); + + var initialRunInfo = result.IngestorRunInfo; + Assert.AreEqual(request.IndexFileName, initialRunInfo.IndexFileName); + Assert.AreEqual(request.RootPath, initialRunInfo.IndexFilePath); + Assert.AreEqual(IngestorTypes.XdiDnaNotice, initialRunInfo.IngestorType); + Assert.AreEqual(DateTime.Now.Date, initialRunInfo.StartTimeStamp.Date); + Assert.AreEqual("\\Test\\", initialRunInfo.IndexFilePath); + } + + [Test] + public async Task HandleIndexRequest_IngestorRequest_GetFileContent_ThrowsException_Failure() + { + var request = new IngestorRequest + { + RootPath = "\\Test\\", + IndexFileName = "Test.csv" + }; + _mockFileOperationsApiService.Setup(x => x.GetFileContent(It.IsAny())).ThrowsAsync(new Exception("Error")); + + var result = await _xdiDnaNoticeDocumentIndexService.HandleIndexRequest(request); + Assert.IsTrue(result.FatalFailure); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Once); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/BatchIngestionServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/BatchIngestionServiceTest.cs new file mode 100644 index 0000000..76aa27a --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/BatchIngestionServiceTest.cs @@ -0,0 +1,173 @@ +using System; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using LCU.Api.Internal.DispatcherSharedLib.Utilities; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.Library.Internal.DispatcherModels.Models; +using LCU.Library.Internal.Exceptions; +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.Library.Internal.DispatcherModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Api.Internal.DispatcherSharedLib.BuilderServices; +using LCU.Library.Internal.DispatcherModels.Enums; +using LCU.Library.Internal.FileOperationsModels.Models; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.IngestionOperationServices; + +public class BatchIngestionServiceTest +{ + private BatchIngestionService _batchIngestionService; + private ApiConfiguration _apiConfiguration; + private DispatcherJobCreationConfiguration _dispatcherJobCreationConfiguration; + private Mock _mockFileOperationsApiService; + private Mock _mockDispatcherRequestBuilder; + + + [SetUp] + public void Setup() + { + _apiConfiguration = new ApiConfiguration + { + TimeZone = "America/Chicago" + }; + _dispatcherJobCreationConfiguration = new DispatcherJobCreationConfiguration + { + DocumentIngestorDispatcherErrorRecipients = new List + { + "test@landmarkcu.com" + }, + JobTags = new List + { + new JobTag + { + JobTagId = 0, + JobId = 0, + TagId = 1 + } + } + }; + _mockFileOperationsApiService = new Mock(); + _mockDispatcherRequestBuilder = new Mock(); + _batchIngestionService = new BatchIngestionService + ( + _apiConfiguration, + _dispatcherJobCreationConfiguration, + _mockFileOperationsApiService.Object, + _mockDispatcherRequestBuilder.Object + ); + } + + [Test] + public void HandleBatchIngestion_ArgumentNullException_RequestNull() + { + BatchIngestionRequest request = null; + Assert.ThrowsAsync(async () => await _batchIngestionService.HandleBatchIngestion(request)); + _mockDispatcherRequestBuilder.Verify(x => x.CreateJob(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicDirectoryList(It.IsAny()), Times.Never); + _mockDispatcherRequestBuilder.Verify(x => x.AddWorkItem(It.IsAny(), It.IsAny(), ActionType.CreateDirectory), Times.Never); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Never); + _mockDispatcherRequestBuilder.Verify(x => x.AddWorkItem(It.IsAny(), It.IsAny(), ActionType.DocumentIngestor), Times.Never); + _mockDispatcherRequestBuilder.Verify(x => x.SendDispatcherRequest(null), Times.Never); + } + + [Test] + public void HandleBatchIngestion_ServiceException_BuildDynamicDirectoryList_ThrowsException() + { + var request = new BatchIngestionRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + IngestorType = IngestorTypes.FosTaxStatement + }; + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicDirectoryList(It.IsAny())).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _batchIngestionService.HandleBatchIngestion(request)); + _mockDispatcherRequestBuilder.Verify(x => x.CreateJob(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicDirectoryList(It.IsAny()), Times.Once); + _mockDispatcherRequestBuilder.Verify(x => x.AddWorkItem(It.IsAny(), It.IsAny(), ActionType.CreateDirectory), Times.Never); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Never); + _mockDispatcherRequestBuilder.Verify(x => x.AddWorkItem(It.IsAny(), It.IsAny(), ActionType.DocumentIngestor), Times.Never); + _mockDispatcherRequestBuilder.Verify(x => x.SendDispatcherRequest(null), Times.Never); + } + + [Test] + public async Task HandleBatchIngestion_BuildDynamicFileList_ThrowsException() + { + var request = new BatchIngestionRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + IngestorType = IngestorTypes.FosTaxStatement + }; + + var dynamicDirectoryListResult = new List + { + "TestParentDynamicDirectory1", + "TestParentDynamicDirectory2" + }; + _mockFileOperationsApiService.Setup(x => x.BuildDynamicDirectoryList(It.IsAny())).ReturnsAsync(dynamicDirectoryListResult); + _mockDispatcherRequestBuilder.Setup(x => x.CreateJob(It.IsAny())); + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFile(It.IsAny())).ThrowsAsync(new Exception("Error")); + + await _batchIngestionService.HandleBatchIngestion(request); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicDirectoryList(It.IsAny()), Times.Once); + _mockDispatcherRequestBuilder.Verify(x => x.CreateJob(It.IsAny()), Times.Exactly(2)); + _mockDispatcherRequestBuilder.Verify(x => x.AddWorkItem(It.IsAny(), It.IsAny(), ActionType.CreateDirectory), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFile(It.IsAny()), Times.Exactly(2)); + _mockDispatcherRequestBuilder.Verify(x => x.AddWorkItem(It.IsAny(), It.IsAny(), ActionType.DocumentIngestor), Times.Never); + _mockDispatcherRequestBuilder.Verify(x => x.SendDispatcherRequest(null), Times.Never); + } + + [Test] + public async Task HandleBatchIngestion_Success() + { + var request = new BatchIngestionRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + DynamicIndexFileName = "TestIndexFile", + IngestorType = IngestorTypes.FosTaxStatement, + IngestionDate = Convert.ToDateTime("1/1/2022") + }; + + var dynamicDirectoryListResult = new List + { + "TestParentDynamicDirectory1", + "TestParentDynamicDirectory2" + }; + _mockFileOperationsApiService.Setup(x => x.BuildDynamicDirectoryList(It.IsAny())).ReturnsAsync(dynamicDirectoryListResult); + _mockDispatcherRequestBuilder.Setup(x => x.CreateJob(It.IsAny())); + + var dynamicFileListRequest1 = new DynamicFileListRequest + { + Path = "\\\\Tester\\path\\01012022\\TestParentDynamicDirectory1\\", + Filename = "TestIndexFile", + DynamicFileSettings = null + }; + var dynamicFileResult1 = "TestIndexFile1"; + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFile(It.Is(x => x.Path == dynamicFileListRequest1.Path))).ReturnsAsync(dynamicFileResult1); + + var dynamicFileListRequest2 = new DynamicFileListRequest + { + Path = "\\\\Tester\\path\\01012022\\TestParentDynamicDirectory2\\", + Filename = "TestIndexFile", + DynamicFileSettings = null + }; + var dynamicFileResult2 = "TestIndexFile2"; + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFile(It.Is(x => x.Path == dynamicFileListRequest2.Path))).ReturnsAsync(dynamicFileResult2); + + await _batchIngestionService.HandleBatchIngestion(request); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicDirectoryList(It.IsAny()), Times.Once); + _mockDispatcherRequestBuilder.Verify(x => x.CreateJob(It.IsAny()), Times.Exactly(2)); + _mockDispatcherRequestBuilder.Verify(x => x.AddWorkItem(It.IsAny(), It.IsAny(), ActionType.CreateDirectory), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFile(It.IsAny()), Times.Exactly(2)); + _mockDispatcherRequestBuilder.Verify(x => x.AddWorkItem(It.IsAny(), It.IsAny(), ActionType.DocumentIngestor), Times.Exactly(2)); + _mockDispatcherRequestBuilder.Verify(x => x.SendDispatcherRequest(null), Times.Exactly(2)); + } +} + diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/CompletionServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/CompletionServiceTest.cs new file mode 100644 index 0000000..23bb4f9 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/CompletionServiceTest.cs @@ -0,0 +1,242 @@ +using System; +using System.Threading.Tasks; +using System.Collections.Generic; +using Moq; +using NUnit.Framework; +using Newtonsoft.Json; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.ApiResponse.Models; +using LCU.Library.Internal.DocumentIngestorModels.Constants; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +namespace LCU.API.Internal.DocumentIngestorTests.Services.IngestionOperationServices; + +public class CompletionServiceTest +{ + private CompletionService _completionService; + private Mock _mockIngestorRunInfoService; + private Mock _mockDocumentProcessingInfoService; + private readonly Mock _responseQueue = new(); + + [SetUp] + public void Setup() + { + _mockIngestorRunInfoService = new Mock(); + _mockDocumentProcessingInfoService = new Mock(); + _completionService = new CompletionService(_mockIngestorRunInfoService.Object, _mockDocumentProcessingInfoService.Object, _responseQueue.Object); + } + + [Test] + public void HandleCompletion_Exception_ResponseNull() + { + Response request = null; + Assert.ThrowsAsync(async () => await _completionService.HandleCompletion(null)); + + _mockDocumentProcessingInfoService.Verify(x => x.UpdateStatusAndAddLog(It.IsAny(), + It.IsAny(), + It.IsAny>(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public void HandleCompletion_Exception_RequestNull() + { + var request = new Response(); + Assert.ThrowsAsync(async () => await _completionService.HandleCompletion(new List() { request })); + _mockDocumentProcessingInfoService.Verify(x => x.UpdateStatusAndAddLog(It.IsAny(), + It.IsAny(), + It.IsAny>(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task HandleCompletion_Update_Success_Complete() + { + var documentProcessInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = 1, + IngestorRunInfoId = Guid.NewGuid(), + DocumentValuePayload = "{test}", + StatusType = ProcessStatusTypes.Completed + }; + + var ingestorRunInfo = new IngestorRunInfo() + { + IngestorRunInfoId = documentProcessInfo.IngestorRunInfoId, + IndexFilePath = "\\Test\\", + IndexTotal = 1 + }; + + _mockIngestorRunInfoService.Setup(service => + service.GetListByIdAsync(It.IsAny>())).ReturnsAsync(new List() { ingestorRunInfo }); + + var processResult = new ProcessResult() + { + Success = true, + AttemptToArchive = false, + }; + + var processingRequest = new ProcessingRequest() + { + IngestorRunInfoId = documentProcessInfo.IngestorRunInfoId + }; + + var completionRequest = new CompletionRequest() + { + ProcessingRequest = processingRequest, + ProcessResult = processResult + }; + var response = new Response() + { + Successful = true, + ResponsePayload = JsonConvert.SerializeObject(completionRequest) + }; + + var completionProcessingData = new CompletionProcessingData() + { + DocumentProcessingInfo = documentProcessInfo, + CompletionRequest = completionRequest + }; + + _mockDocumentProcessingInfoService.Setup(service => service.UpdateProcessCountAndStatusAndAddLog( + It.IsAny>())) + .ReturnsAsync(new List() { completionProcessingData}); + + _mockDocumentProcessingInfoService.Setup(service => service.GetCompletedFirstPassByIngestorRunInfoIdAsync( + It.IsAny())).ReturnsAsync( + new List() { documentProcessInfo }); + + await _completionService.HandleCompletion(new List() { response }); + _mockDocumentProcessingInfoService.Verify(x => x.UpdateProcessCountAndStatusAndAddLog(It.IsAny>()), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.GetListByIdAsync(It.IsAny>()), Times.Once); + _mockDocumentProcessingInfoService.Verify(x => x.GetCompletedFirstPassByIngestorRunInfoIdAsync(It.IsAny()), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.Update(It.IsAny()), Times.Once); + } + + [Test] + public async Task HandleCompletion_Update_Success_Incomplete() + { + var documentProcessInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = 1, + IngestorRunInfoId = Guid.NewGuid(), + DocumentValuePayload = "{test}", + StatusType = ProcessStatusTypes.Completed + }; + + var ingestorRunInfo = new IngestorRunInfo() + { + IngestorRunInfoId = documentProcessInfo.IngestorRunInfoId, + IndexFilePath = "\\Test\\", + IndexTotal = 5 + }; + + _mockIngestorRunInfoService.Setup(service => + service.GetListByIdAsync(It.IsAny>())).ReturnsAsync(new List() { ingestorRunInfo }); + + var processResult = new ProcessResult() + { + Success = true, + AttemptToArchive = false, + }; + + var processingRequest = new ProcessingRequest() + { + IngestorRunInfoId = documentProcessInfo.IngestorRunInfoId + }; + + var completionRequest = new CompletionRequest() + { + ProcessingRequest = processingRequest, + ProcessResult = processResult + }; + var response = new Response() + { + Successful = true, + ResponsePayload = JsonConvert.SerializeObject(completionRequest) + }; + + var completionProcessingData = new CompletionProcessingData() + { + DocumentProcessingInfo = documentProcessInfo, + CompletionRequest = completionRequest + }; + + _mockDocumentProcessingInfoService.Setup(service => service.UpdateProcessCountAndStatusAndAddLog( + It.IsAny>())) + .ReturnsAsync(new List() { completionProcessingData }); + + _mockDocumentProcessingInfoService.Setup(service => service.GetCompletedFirstPassByIngestorRunInfoIdAsync( + It.IsAny())).ReturnsAsync( + new List() { documentProcessInfo }); + + await _completionService.HandleCompletion(new List() { response }); + _mockDocumentProcessingInfoService.Verify(x => x.UpdateProcessCountAndStatusAndAddLog(It.IsAny>()), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.GetListByIdAsync(It.IsAny>()), Times.Once); + _mockDocumentProcessingInfoService.Verify(x => x.GetCompletedFirstPassByIngestorRunInfoIdAsync(It.IsAny()), Times.Never); + _mockIngestorRunInfoService.Verify(x => x.Update(It.IsAny()), Times.Once); + } + + [Test] + public void HandleCompletion_UpdateRunInfoStatusById_ThrowsException() + { + var documentProcessInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = 1, + IngestorRunInfoId = Guid.NewGuid(), + DocumentValuePayload = "{test}", + StatusType = ProcessStatusTypes.Completed + }; + + var ingestorRunInfo = new IngestorRunInfo() + { + IngestorRunInfoId = new Guid(), + IndexFilePath = "\\Test\\", + IndexTotal = 1 + }; + + var processResult = new ProcessResult() + { + Success = true, + AttemptToArchive = false, + }; + + var processingRequest = new ProcessingRequest() + { + IngestorRunInfoId = documentProcessInfo.IngestorRunInfoId + }; + + var completionRequest = new CompletionRequest() + { + ProcessingRequest = processingRequest, + ProcessResult = processResult + }; + var response = new Response() + { + Successful = true, + ResponsePayload = JsonConvert.SerializeObject(completionRequest) + }; + + var completionProcessingData = new CompletionProcessingData() + { + DocumentProcessingInfo = documentProcessInfo, + CompletionRequest = completionRequest + }; + + _mockDocumentProcessingInfoService.Setup(service => service.UpdateProcessCountAndStatusAndAddLog( + It.IsAny>())) + .ReturnsAsync(new List() { completionProcessingData }); + + _mockIngestorRunInfoService.Setup(x => x.GetListByIdAsync(It.IsAny>())).ThrowsAsync(new Exception("Test Exception")); + + Assert.ThrowsAsync(async () => await _completionService.HandleCompletion(new List() { response })); + _mockDocumentProcessingInfoService.Verify(x => x.UpdateProcessCountAndStatusAndAddLog(It.IsAny>()), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.Update(It.IsAny()), Times.Never); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/DocumentProcessorServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/DocumentProcessorServiceTest.cs new file mode 100644 index 0000000..a47fd27 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/DocumentProcessorServiceTest.cs @@ -0,0 +1,196 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Moq; +using NUnit.Framework; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.Library.Internal.LCUServiceFactory.Services; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.IngestionOperationServices; + +public class DocumentProcessorServiceTest +{ + private DocumentProcessorService _documentProcessorService; + + private ApiConfiguration _apiConfiguration; + private Mock _mockQueueDocumentProcessingService; + private Mock _mockQueueCompletionService; + private Mock _mockFileOperationsApiService; + private Mock> _mockLcuServiceFactory; + + private IDictionary _handlerServicesByType; + + [SetUp] + public void Setup() + { + _apiConfiguration = new ApiConfiguration + { + DocumentProcessingReQueueCountLimit = 1 + }; + _mockQueueDocumentProcessingService = new Mock(); + _mockQueueCompletionService = new Mock(); + _mockFileOperationsApiService = new Mock(); + _mockLcuServiceFactory = new Mock>(); + _documentProcessorService = new DocumentProcessorService(_apiConfiguration, + _mockQueueDocumentProcessingService.Object, + _mockQueueCompletionService.Object, + _mockFileOperationsApiService.Object, + _mockLcuServiceFactory.Object); + } + + [Test] + public void HandleIngestion_Exception_RequestNull() + { + ProcessingRequest request = null; + Assert.ThrowsAsync(async () => await _documentProcessorService.HandleProcessing(request)); + _mockFileOperationsApiService.Verify(x => x.ValidateFileExistsAndNotArchived(It.IsAny(), It.IsAny()), Times.Never); + _mockQueueCompletionService.Verify(x => x.QueueCompletionRequest(It.IsAny(), It.IsAny()), Times.Never); + _mockLcuServiceFactory.Verify(x => x.GetService(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task HandleIngestion_DocumentDoesNotNeedProcessing_Update_Return() + { + var filePath = "\\Test\\Test\\000001Test.pdf"; + var archiveFilePath = "\\Test\\Test\\Archived\\000001Test.pdf"; + + _mockFileOperationsApiService.Setup(service => service.ValidateFileExistsAndNotArchived(filePath, archiveFilePath)) + .ReturnsAsync(false); + + var ingestorRequest = new IngestorRequest + { + RootPath = "\\Test\\Test" + }; + var request = new ProcessingRequest() + { + DocumentFileName = "000001Test.pdf", + IngestorRequest = ingestorRequest + }; + + await _documentProcessorService.HandleProcessing(request); + _mockFileOperationsApiService.Verify(x => x.ValidateFileExistsAndNotArchived(filePath, + archiveFilePath), Times.Once); + _mockQueueCompletionService.Verify(x => x.QueueCompletionRequest(request, It.Is(y => y.Success == true + && y.AttemptToArchive == false + && y.MessageStack.Count == 1 + && y.ProcessStatusType == ProcessStatusTypes.Completed) + ), Times.Once); + + _mockLcuServiceFactory.Verify(x => x.GetService(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task HandlePostProcessingFailure_ProcessResult_SuccessFalse_QueueDocumentProcessing() + { + var request = new ProcessingRequest + { + IngestorRequest = new() + { + IngestorType = IngestorTypes.FosLoanStatement + }, + RetryCount = 0 + }; + var result = new ProcessResult + { + Success = false, + ProcessStatusType = ProcessStatusTypes.CriticalFailure + }; + + await _documentProcessorService.HandlePostProcessingFailure(request, result); + + _mockQueueDocumentProcessingService.Verify(x => x.QueueDocumentProcessingRequest(It.IsAny()), Times.Once); + _mockQueueCompletionService.Verify(x => x.QueueCompletionRequest(It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task HandlePostProcessingFailure_ProcessResult_SuccessFalse_QueueCompletion() + { + var request = new ProcessingRequest + { + RetryCount = 1 + }; + var result = new ProcessResult + { + Success = false, + ProcessStatusType = ProcessStatusTypes.CriticalFailure + }; + await _documentProcessorService.HandlePostProcessingFailure(request, result); + _mockQueueDocumentProcessingService.Verify(x => x.QueueDocumentProcessingRequest(It.IsAny()), Times.Never); + _mockQueueCompletionService.Verify(x => x.QueueCompletionRequest(It.IsAny(), It.IsAny()), Times.Once); + } + + [TestCase(IngestorTypes.FosTaxStatement, typeof(IDocumentProcessingService))] + [TestCase(IngestorTypes.FosDnaDocument, typeof(IDocumentProcessingService))] + [TestCase(IngestorTypes.FosLoanStatement, typeof(IDocumentProcessingService))] + [TestCase(IngestorTypes.XdiDnaNotice, typeof(IDocumentProcessingService))] + [TestCase(IngestorTypes.OsgDnaNoticesDocument, typeof(IDocumentProcessingService))] + [TestCase(IngestorTypes.XdiActionNotice, typeof(IDocumentProcessingService))] + [TestCase(IngestorTypes.OsgHistoricalDocument, typeof(IDocumentProcessingService))] + [Test] + public async Task HandleProcessing_ByTypedRequest_HandledByMatchingServiceAndArchived(IngestorTypes type, Type handlerType) + { + var request = new ProcessingRequest + { + IngestorRequest = new IngestorRequest + { + IngestorType = type, + RootPath = Guid.NewGuid().ToString(), + }, + DocumentFileName = Guid.NewGuid().ToString() + }; + + var result = new ProcessResult + { + Success = true + }; + + var documentProcessorService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(request.IngestorRequest.IngestorType)).Returns(documentProcessorService.Object); + documentProcessorService.Setup(x => x.ProcessRequest(request)).ReturnsAsync(result); + + _mockFileOperationsApiService + .Setup + ( + fs => fs.ValidateFileExistsAndNotArchived + ( + request.IngestorRequest.RootPath + request.DocumentFileName, + request.IngestorRequest.ArchivePath + request.DocumentFileName + ) + ) + .ReturnsAsync(true); + _mockFileOperationsApiService + .Setup(fs => fs.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(new RequestResponse { IsSuccessful = true }); + + await _documentProcessorService.HandleProcessing(request); + + _mockLcuServiceFactory.Verify(x => x.GetService(request.IngestorRequest.IngestorType), Times.Once); + _mockFileOperationsApiService + .Verify + ( + s => s.DirectMoveFile + ( + request.IngestorRequest.RootPath, + request.DocumentFileName, + request.IngestorRequest.ArchivePath + ), + Times.Once + ); + } + +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/IndexServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/IndexServiceTest.cs new file mode 100644 index 0000000..7ce29df --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/IndexServiceTest.cs @@ -0,0 +1,633 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.LCUServiceFactory.Services; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.IngestionOperationServices; + +public class IndexServiceTest +{ + private IndexService _indexService; + private Mock _mockQueueDocumentProcessing; + private Mock _mockIngestorRunInfoService; + private Mock _mockDocumentProcessingInfoService; + private Mock _mockDocumentTypeRetrieverService; + private Mock> _mockLcuServiceFactory; + + private IDictionary _handlerServicesByType; + + [SetUp] + public void Setup() + { + _mockQueueDocumentProcessing = new Mock(); + _mockIngestorRunInfoService = new Mock(); + _mockDocumentProcessingInfoService = new Mock(); + _mockDocumentTypeRetrieverService = new Mock(); + _mockLcuServiceFactory = new Mock>(); + _indexService = new IndexService(_mockQueueDocumentProcessing.Object, + _mockIngestorRunInfoService.Object, + _mockDocumentProcessingInfoService.Object, + _mockDocumentTypeRetrieverService.Object, + _mockLcuServiceFactory.Object); + } + + [Test] + public void HandleIngestion_Exception_RequestNull() + { + IngestorRequest request = null; + Assert.ThrowsAsync(async () => await _indexService.HandleIngestion(request)); + _mockLcuServiceFactory.Verify(x => x.GetService(It.IsAny()), Times.Never); + _mockIngestorRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + _mockDocumentProcessingInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + _mockQueueDocumentProcessing.Verify(x => x.QueueDocumentProcessingRequest(It.IsAny()), Times.Never); + _mockDocumentProcessingInfoService.Verify(x => x.UpdateStatusAndAddLog(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public void HandleIngestion_Exception_Result_FatalFailure() + { + var request = new IngestorRequest() + { + IngestorType = IngestorTypes.FosTaxStatement, + RootPath = "\\test\\test", + IndexFileName = "TestIndex.csv" + }; + var result = new IngestorResult(true, "fail"); + + var indexParsingService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(request.IngestorType)).Returns(indexParsingService.Object); + indexParsingService.Setup(x => x.HandleIndexRequest(request)).ReturnsAsync(result); + + Assert.ThrowsAsync(async () => await _indexService.HandleIngestion(request)); + indexParsingService.Verify(x => x.HandleIndexRequest(request), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + _mockDocumentProcessingInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + _mockQueueDocumentProcessing.Verify(x => x.QueueDocumentProcessingRequest(It.IsAny()), Times.Never); + _mockDocumentProcessingInfoService.Verify(x => x.UpdateStatusAndAddLog(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public void HandleIngestion_Exception_FosTaxStatementIndexService_ExceptionThrown() + { + var request = new IngestorRequest() + { + IngestorType = IngestorTypes.FosTaxStatement, + RootPath = "\\test\\test", + IndexFileName = "TestIndex.csv" + }; + var ingestorRunInfo = new IngestorRunInfo() + { + IngestorRunInfoId = new Guid(), + IndexFilePath = "\\test\\test\\TestIndex.csv", + IndexTotal = 1 + }; + + var indexParsingService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(request.IngestorType)).Returns(indexParsingService.Object); + + indexParsingService.Setup(x => x.HandleIndexRequest(request)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _indexService.HandleIngestion(request)); + indexParsingService.Verify(x => x.HandleIndexRequest(request), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + _mockDocumentProcessingInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + _mockQueueDocumentProcessing.Verify(x => x.QueueDocumentProcessingRequest(It.IsAny()), Times.Never); + _mockDocumentProcessingInfoService.Verify(x => x.UpdateStatusAndAddLog(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public void HandleIngestion_Exception_FosDnaDocumentIndexService_ExceptionThrown() + { + var request = new IngestorRequest() + { + IngestorType = IngestorTypes.FosDnaDocument, + RootPath = "\\test\\test", + IndexFileName = "TestIndex.csv" + }; + var ingestorRunInfo = new IngestorRunInfo() + { + IngestorRunInfoId = new Guid(), + IndexFilePath = "\\test\\test\\TestIndex.csv", + IndexTotal = 1 + }; + + var indexParsingService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(request.IngestorType)).Returns(indexParsingService.Object); + + indexParsingService.Setup(x => x.HandleIndexRequest(request)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _indexService.HandleIngestion(request)); + indexParsingService.Verify(x => x.HandleIndexRequest(request), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + _mockDocumentProcessingInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + _mockQueueDocumentProcessing.Verify(x => x.QueueDocumentProcessingRequest(It.IsAny()), Times.Never); + _mockDocumentProcessingInfoService.Verify(x => x.UpdateStatusAndAddLog(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task HandleIngestion_Success_ThreeProcessRequest_Queued() + { + var request = new IngestorRequest() + { + IngestorType = IngestorTypes.FosTaxStatement, + RootPath = "\\test\\test", + IndexFileName = "TestIndex.csv" + }; + + var guid = new Guid(); + var ingestorRunInfo = new IngestorRunInfo() + { + IngestorRunInfoId = guid, + IndexFilePath = "\\test\\test\\TestIndex.csv", + IndexTotal = 1 + }; + var result = new IngestorResult(); + result.ProcessingRequests = new List() + { + new ProcessingRequest() + { + IngestorRunInfoId = guid, + IngestorRequest = request, + DocumentFileName = "Test1.pdf", + DocumentValuePayload = "{jsonblah: hello1}", + DocumentTypeDisplayName = "OneThousandNinetyNineInt" + }, + new ProcessingRequest() + { + IngestorRunInfoId = guid, + IngestorRequest = request, + DocumentFileName = "Test2.pdf", + DocumentValuePayload = "{jsonblah: hello2}", + DocumentTypeDisplayName = "OneThousandNinetyNineInt" + }, + new ProcessingRequest() + { + IngestorRunInfoId = guid, + IngestorRequest = request, + DocumentFileName = "Test3.pdf", + DocumentValuePayload = "{jsonblah: hello3}", + DocumentTypeDisplayName = "OneThousandNinetyNineInt" + } + }; + result.IngestorRunInfo = new IngestorRunInfo(Guid.NewGuid(), + Convert.ToDateTime("1/1/2022"), + IngestorTypes.FosTaxStatement, + "\\test\\test\\", + "Test.csv", + 1); + + var documentCodeDetailInfo = new DocumentCodeDetailInfo() + { + DocumentBusinessName = "TestStatement", + DocumentType = "TestDocumentType" + }; + + var indexParsingService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(request.IngestorType)).Returns(indexParsingService.Object); + + indexParsingService.Setup(x => x.HandleIndexRequest(request)).ReturnsAsync(result); + _mockDocumentTypeRetrieverService.Setup(x => x.GetDocumentCodeDetailByDisplayName(It.IsAny())) + .ReturnsAsync(documentCodeDetailInfo); + _mockIngestorRunInfoService.Setup(x => x.SaveAsync(It.IsAny())).ReturnsAsync(result.IngestorRunInfo); + + var documentProcessingInfos = new List() + { + new() + { + IngestorRunInfoId = guid, + DocumentProcessingInfoId = 1, + DocumentFileName = "Test1.pdf", + DocumentValuePayload = "{jsonblah: hello1}" + }, + new() + { + IngestorRunInfoId = guid, + DocumentProcessingInfoId = 2, + DocumentFileName = "Test2.pdf", + DocumentValuePayload = "{jsonblah: hello2}", + }, + new() + { + IngestorRunInfoId = guid, + DocumentProcessingInfoId = 3, + DocumentFileName = "Test3.pdf", + DocumentValuePayload = "{jsonblah: hello3}", + } + }; + + _mockDocumentProcessingInfoService.Setup(x => x.GetByIngestorRunInfoIdAsync(It.IsAny())).ReturnsAsync(documentProcessingInfos); + _mockDocumentProcessingInfoService.Setup(x => x.SaveRangeAsync(It.IsAny())); + + await _indexService.HandleIngestion(request); + indexParsingService.Verify(x => x.HandleIndexRequest(request), Times.Once); + _mockDocumentTypeRetrieverService.Verify(x => x.GetDocumentCodeDetailByDisplayName(It.IsAny()), Times.Exactly(1)); + _mockIngestorRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Once); + _mockDocumentProcessingInfoService.Verify(x => x.SaveRangeAsync(It.IsAny()), Times.Exactly(1)); + _mockQueueDocumentProcessing.Verify(x => x.QueueDocumentProcessingRequest(It.IsAny()), Times.Exactly(3)); + _mockDocumentProcessingInfoService.Verify(x => x.UpdateStatusAndAddLog(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public async Task HandleIngestion_ExceptionThrown_OnQueue() + { + var request = new IngestorRequest() + { + IngestorType = IngestorTypes.FosTaxStatement, + RootPath = "\\test\\test", + IndexFileName = "TestIndex.csv" + }; + + var guid = Guid.NewGuid(); + var ingestorRunInfo = new IngestorRunInfo() + { + IngestorRunInfoId = guid, + IndexFilePath = "\\test\\test\\TestIndex.csv", + IndexTotal = 1 + }; + var result = new IngestorResult(); + + var processRequest1 = new ProcessingRequest() + { + IngestorRunInfoId = guid, + IngestorRequest = request, + DocumentFileName = "Test1.pdf", + DocumentValuePayload = "{jsonblah: hello1}", + DocumentTypeDisplayName = "OneThousandNinetyNineInt" + }; + + var processRequest2 = new ProcessingRequest() + { + IngestorRunInfoId = guid, + IngestorRequest = request, + DocumentFileName = "Test2.pdf", + DocumentValuePayload = "{jsonblah: hello2}", + DocumentTypeDisplayName = "OneThousandNinetyNineInt" + }; + + var processRequest3 = new ProcessingRequest() + { + IngestorRunInfoId = guid, + IngestorRequest = request, + DocumentFileName = "Test3.pdf", + DocumentValuePayload = "{jsonblah: hello3}", + DocumentTypeDisplayName = "OneThousandNinetyNineInt" + }; + + result.ProcessingRequests = new List() + { + processRequest1, + processRequest2, + processRequest3 + }; + + result.IngestorRunInfo = new IngestorRunInfo(guid, + Convert.ToDateTime("1/1/2022"), + IngestorTypes.FosTaxStatement, + "\\test\\test\\", + "Test.csv", + 1); + + var documentCodeDetailInfo = new DocumentCodeDetailInfo() + { + DocumentBusinessName = "TestStatement", + DocumentType = "TestDocumentType" + }; + + var documentProcessingInfos = new List() + { + new() + { + IngestorRunInfoId = guid, + DocumentProcessingInfoId = 1, + DocumentFileName = "Test1.pdf", + DocumentValuePayload = "{jsonblah: hello1}" + }, + new() + { + IngestorRunInfoId = guid, + DocumentProcessingInfoId = 2, + DocumentFileName = "Test2.pdf", + DocumentValuePayload = "{jsonblah: hello2}", + }, + new() + { + IngestorRunInfoId = guid, + DocumentProcessingInfoId = 3, + DocumentFileName = "Test3.pdf", + DocumentValuePayload = "{jsonblah: hello3}", + } + }; + + var indexParsingService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(request.IngestorType)).Returns(indexParsingService.Object); + + indexParsingService.Setup(x => x.HandleIndexRequest(request)).ReturnsAsync(result); + _mockDocumentTypeRetrieverService.Setup(x => x.GetDocumentCodeDetailByDisplayName(It.IsAny())).ReturnsAsync(documentCodeDetailInfo); + _mockDocumentProcessingInfoService.Setup(x => x.SaveRangeAsync(It.IsAny())); + _mockDocumentProcessingInfoService.Setup(x => x.GetByIngestorRunInfoIdAsync(It.IsAny())) + .ReturnsAsync(documentProcessingInfos); + + _mockIngestorRunInfoService.Setup(x => x.SaveAsync(It.IsAny())).ReturnsAsync(result.IngestorRunInfo); + + var documentProcessingInfo1 = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = 1, + IngestorRunInfoId = guid, + StatusType = ProcessStatusTypes.Processing, + DocumentValuePayload = "{jsonblah: hello1}", + DocumentBusinessName = "1099-INT (interest income) (Tax)", + DocumentType = "Statement" + }; + _mockQueueDocumentProcessing.Setup(x => x.QueueDocumentProcessingRequest(processRequest1)).ThrowsAsync(new Exception("Error")); + var documentProcessingInfoUpdated1 = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = 1, + IngestorRunInfoId = guid, + DocumentValuePayload = "{jsonblah: hello1}", + StatusType = ProcessStatusTypes.CriticalFailure, + DocumentBusinessName = "1099-INT (interest income) (Tax)", + DocumentType = "Statement" + }; + _mockDocumentProcessingInfoService.Setup(x => x.UpdateStatusAndAddLog(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(documentProcessingInfoUpdated1); + + var documentProcessingInfo2 = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = 2, + IngestorRunInfoId = guid, + StatusType = ProcessStatusTypes.Processing, + DocumentValuePayload = "{jsonblah: hello2}", + DocumentBusinessName = "1099-INT (interest income) (Tax)", + DocumentType = "Statement" + }; + _mockQueueDocumentProcessing.Setup(x => x.QueueDocumentProcessingRequest(processRequest2)).ThrowsAsync(new Exception("Error")); + var documentProcessingInfoUpdated2 = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = 2, + IngestorRunInfoId = guid, + DocumentValuePayload = "{jsonblah: hello2}", + StatusType = ProcessStatusTypes.CriticalFailure, + DocumentBusinessName = "1099-INT (interest income) (Tax)", + DocumentType = "Statement" + }; + _mockDocumentProcessingInfoService.Setup(x => x.UpdateStatusAndAddLog(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(documentProcessingInfoUpdated2); + + var documentProcessingInfo3 = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = 2, + IngestorRunInfoId = guid, + StatusType = ProcessStatusTypes.Processing, + DocumentValuePayload = "{jsonblah: hello3}", + DocumentBusinessName = "1099-INT (interest income) (Tax)", + DocumentType = "Statement" + }; + _mockQueueDocumentProcessing.Setup(x => x.QueueDocumentProcessingRequest(processRequest3)).ThrowsAsync(new Exception("Error")); + var documentProcessingInfoUpdated3 = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = 3, + IngestorRunInfoId = guid, + DocumentValuePayload = "{jsonblah: hello3}", + StatusType = ProcessStatusTypes.CriticalFailure, + DocumentBusinessName = "1099-INT (interest income) (Tax)", + DocumentType = "Statement" + }; + _mockDocumentProcessingInfoService.Setup(x => x.UpdateStatusAndAddLog(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(documentProcessingInfoUpdated3); + + await _indexService.HandleIngestion(request); + indexParsingService.Verify(x => x.HandleIndexRequest(request), Times.Once); + _mockDocumentTypeRetrieverService.Verify(x => x.GetDocumentCodeDetailByDisplayName(It.IsAny()), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Once); + _mockDocumentProcessingInfoService.Verify(x => x.SaveRangeAsync(It.IsAny()), Times.Once); + _mockQueueDocumentProcessing.Verify(x => x.QueueDocumentProcessingRequest(It.IsAny()), Times.Exactly(3)); + _mockDocumentProcessingInfoService.Verify(x => x.UpdateStatusAndAddLog(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Exactly(3)); + } + + [Test] + public void HandleIngestion_ExceptionThrown_DocumentProcessingInfo_SaveRangeAsync() + { + var request = new IngestorRequest() + { + IngestorType = IngestorTypes.FosTaxStatement, + RootPath = "\\test\\test", + IndexFileName = "TestIndex.csv" + }; + + var guid = new Guid(); + var ingestorRunInfo = new IngestorRunInfo() + { + IngestorRunInfoId = guid, + IndexFilePath = "\\test\\test\\TestIndex.csv", + IndexTotal = 1 + }; + var result = new IngestorResult(); + + var processRequest1 = new ProcessingRequest() + { + IngestorRunInfoId = guid, + IngestorRequest = request, + DocumentFileName = "Test1.pdf", + DocumentValuePayload = "{jsonblah: hello1}", + DocumentTypeDisplayName = "1099-INT" + }; + result.ProcessingRequests = new List() + { + processRequest1, + new ProcessingRequest() + { + IngestorRunInfoId = guid, + IngestorRequest = request, + DocumentFileName = "Test2.pdf", + DocumentValuePayload = "{jsonblah: hello2}", + DocumentTypeDisplayName = "1099-INT" + }, + new ProcessingRequest() + { + IngestorRunInfoId = guid, + IngestorRequest = request, + DocumentFileName = "Test3.pdf", + DocumentValuePayload = "{jsonblah: hello3}", + DocumentTypeDisplayName = "1099-INT" + } + }; + result.IngestorRunInfo = new IngestorRunInfo(Guid.NewGuid(), + Convert.ToDateTime("1/1/2022"), + IngestorTypes.FosTaxStatement, + "\\test\\test\\", + "Test.csv", + 1); + var documentCodeDetailInfo = new DocumentCodeDetailInfo() + { + DocumentBusinessName = "TestStatement", + DocumentType = "TestDocumentType" + }; + + var indexParsingService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(request.IngestorType)).Returns(indexParsingService.Object); + + indexParsingService.Setup(x => x.HandleIndexRequest(request)).ReturnsAsync(result); + _mockDocumentTypeRetrieverService.Setup(x => x.GetDocumentCodeDetailByDisplayName(It.IsAny())) + .ReturnsAsync(documentCodeDetailInfo); + _mockIngestorRunInfoService.Setup(x => x.SaveAsync(It.IsAny())).ReturnsAsync(result.IngestorRunInfo); + + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = 1, + IngestorRunInfoId = Guid.NewGuid(), + DocumentValuePayload = "{Test}", + DocumentBusinessName = "1099-INT (interest income) (Tax)", + DocumentType = "Statement" + }; + _mockDocumentProcessingInfoService.Setup(x => x.SaveRangeAsync(It.IsAny())).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _indexService.HandleIngestion(request)); + indexParsingService.Verify(x => x.HandleIndexRequest(request), Times.Once); + _mockDocumentTypeRetrieverService.Verify(x => x.GetDocumentCodeDetailByDisplayName(It.IsAny()), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Once); + _mockDocumentProcessingInfoService.Verify(x => x.SaveRangeAsync(It.IsAny()), Times.Once); + _mockQueueDocumentProcessing.Verify(x => x.QueueDocumentProcessingRequest(It.IsAny()), Times.Never); + _mockDocumentProcessingInfoService.Verify(x => x.UpdateStatusAndAddLog(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [Test] + public void HandleIngestion_ExceptionThrown_OnIngestorRunInfoSave() + { + var request = new IngestorRequest() + { + IngestorType = IngestorTypes.FosTaxStatement, + RootPath = "\\test\\test", + IndexFileName = "TestIndex.csv" + }; + + var guid = new Guid(); + var ingestorRunInfo = new IngestorRunInfo() + { + IngestorRunInfoId = guid, + IndexFilePath = "\\test\\test\\TestIndex.csv", + IndexTotal = 1 + }; + var result = new IngestorResult(); + + var processRequest1 = new ProcessingRequest() + { + IngestorRunInfoId = guid, + IngestorRequest = request, + DocumentFileName = "Test1.pdf", + DocumentValuePayload = "{jsonblah: hello1}" + }; + result.ProcessingRequests = new List() + { + processRequest1, + new ProcessingRequest() + { + IngestorRunInfoId = guid, + IngestorRequest = request, + DocumentFileName = "Test2.pdf", + DocumentValuePayload = "{jsonblah: hello2}" + }, + new ProcessingRequest() + { + IngestorRunInfoId = guid, + IngestorRequest = request, + DocumentFileName = "Test3.pdf", + DocumentValuePayload = "{jsonblah: hello3}" + } + }; + result.IngestorRunInfo = new IngestorRunInfo(Guid.NewGuid(), + Convert.ToDateTime("1/1/2022"), + IngestorTypes.FosTaxStatement, + "\\test\\test\\", + "Test.csv", + 1); + + var indexParsingService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(request.IngestorType)).Returns(indexParsingService.Object); + _mockIngestorRunInfoService.Setup(x => x.SaveAsync(It.IsAny())).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _indexService.HandleIngestion(request)); + indexParsingService.Verify(x => x.HandleIndexRequest(request), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + _mockDocumentProcessingInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + _mockQueueDocumentProcessing.Verify(x => x.QueueDocumentProcessingRequest(It.IsAny()), Times.Never); + _mockDocumentProcessingInfoService.Verify(x => x.UpdateStatusAndAddLog(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + } + + [TestCase(IngestorTypes.FosTaxStatement, typeof(IIndexParserService))] + [TestCase(IngestorTypes.FosDnaDocument, typeof(IIndexParserService))] + [TestCase(IngestorTypes.FosLoanStatement, typeof(IIndexParserService))] + [TestCase(IngestorTypes.XdiDnaNotice, typeof(IIndexParserService))] + [TestCase(IngestorTypes.OsgDnaNoticesDocument, typeof(IIndexParserService))] + [TestCase(IngestorTypes.XdiActionNotice, typeof(IIndexParserService))] + [TestCase(IngestorTypes.OsgHistoricalDocument, typeof(IIndexParserService))] + public async Task PerformIngestor_ByTypedRequest_HandledByMatchingService(IngestorTypes type, Type handlerType) + { + var request = new IngestorRequest + { + IngestorType = type + }; + + var expectedResult = new IngestorResult(); + + var indexParsingService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(request.IngestorType)).Returns(indexParsingService.Object); + indexParsingService.Setup(x => x.HandleIndexRequest(request)).ReturnsAsync(expectedResult); + + var result = await _indexService.PerformIngestor(request); + + Assert.AreSame(expectedResult, result); + } +} + diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/IngestionFolderCleanUpTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/IngestionFolderCleanUpTest.cs new file mode 100644 index 0000000..29ea3e8 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/IngestionFolderCleanUpTest.cs @@ -0,0 +1,731 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Moq; +using NUnit.Framework; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.FileOperationsModels.Models; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.IngestionOperationServices; + +public class IngestionFolderCleanUpTest +{ + private IngestionFolderCleanUpService _ingestionFolderCleanUpService; + private Mock _mockFileOperationsApiService; + private Mock _mockIngestorRunInfoService; + private Mock _mockDocumentProcessingInfoService; + + + [SetUp] + public void Setup() + { + _mockFileOperationsApiService = new Mock(); + _mockIngestorRunInfoService = new Mock(); + _mockDocumentProcessingInfoService = new Mock(); + + _ingestionFolderCleanUpService = new IngestionFolderCleanUpService + ( + _mockFileOperationsApiService.Object, + _mockIngestorRunInfoService.Object, + _mockDocumentProcessingInfoService.Object + ); + } + + [Test] + public async Task HandleIngestionFolderCleanUp_Success() + { + var now = DateTime.Now.ToString("yyyyMMdd"); + // Arrange + var request = new IngestionFolderCleanUpRequest() + { + ArchiveDate = new DateTime(2023, 03, 30), + ArchiveRootPath = "\\\\zeus\\some\\path\\", + IngestionEndedDate = new DateTime(2023, 3, 30) + }; + + var ingestorRunInfos = new List() + { + new () + { + IngestorRunInfoId = Guid.NewGuid(), + IngestorType = IngestorTypes.FosDnaDocument, + IndexTotal = 5, + IndexFilePath = $"Path1\\{now}\\Path1\\", + IndexFileName = "Filename", + StartTimeStamp = new DateTime(2023, 03, 27), + EndTimeStamp = new DateTime(2023, 03, 27), + ArchiveTimeStamp = null, + }, + new () + { + IngestorRunInfoId = Guid.NewGuid(), + IngestorType = IngestorTypes.FosDnaDocument, + IndexTotal = 5, + IndexFilePath = $"Path2\\{now}\\Path2\\", + IndexFileName = "Filename", + StartTimeStamp = new DateTime(2023, 03, 28), + EndTimeStamp = new DateTime(2023, 03, 28), + ArchiveTimeStamp = null, + }, + new () + { + IngestorRunInfoId = Guid.NewGuid(), + IngestorType = IngestorTypes.FosDnaDocument, + IndexTotal = 5, + IndexFilePath = $"Path3\\{now}\\Path3\\", + IndexFileName = "Filename", + StartTimeStamp = new DateTime(2023, 03, 29), + EndTimeStamp = new DateTime(2023, 03, 29), + ArchiveTimeStamp = null, + } + }; + + var docProcessingInfoFiles = new List() + { + "Filename1.pdf", + "Filename2.pdf", + "Filename3.pdf", + "Filename4.pdf", + "Filename5.pdf" + }; + + var successfulRequestResponse = new RequestResponse() + { + IsSuccessful = true, + MessageStack = null, + ReturnResponse = null + }; + + _mockIngestorRunInfoService.Setup(x => x.FindByIngestionEndDateNotArchived(It.IsAny())) + .Returns(ingestorRunInfos).Verifiable(); + _mockIngestorRunInfoService.Setup(x => x.Update(It.IsAny())).Verifiable(); + + _mockDocumentProcessingInfoService.Setup(x => x.CountCompletedByIngestorRunInfoIdAsync(It.IsAny())) + .ReturnsAsync(docProcessingInfoFiles.Count).Verifiable(); + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ArchiveFiles}")))).ReturnsAsync(docProcessingInfoFiles).Verifiable(); + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ZipFileRegex}")))).ReturnsAsync(new List() { "" }).Verifiable(); + _mockFileOperationsApiService.Setup(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny())).ReturnsAsync(successfulRequestResponse).Verifiable(); + _mockFileOperationsApiService.Setup(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(successfulRequestResponse).Verifiable(); + _mockFileOperationsApiService.Setup(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny())).Verifiable(); + + // Act + await _ingestionFolderCleanUpService.HandleIngestionFolderCleanUp(request); + + // Assert + _mockIngestorRunInfoService.Verify(x => x.FindByIngestionEndDateNotArchived(It.IsAny()), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.Update(It.IsAny()), Times.Exactly(ingestorRunInfos.Count)); + + _mockDocumentProcessingInfoService.Verify(x => x.CountCompletedByIngestorRunInfoIdAsync(It.IsAny()), Times.Exactly(ingestorRunInfos.Count)); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ArchiveFiles}"))), Times.Exactly(ingestorRunInfos.Count)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ZipFileRegex}"))), Times.Exactly(ingestorRunInfos.Count)); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(ingestorRunInfos.Count)); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(ingestorRunInfos.Count)); + } + + [Test] + public async Task HandleIngestionFolderCleanUp_DocumentProcessingInfoCount_IndexTotal_Mismatch() + { + // Arrange + var request = new IngestionFolderCleanUpRequest() + { + ArchiveDate = new DateTime(2023, 03, 30), + ArchiveRootPath = "\\\\zeus\\some\\path\\", + IngestionEndedDate = new DateTime(2023, 3, 30) + }; + + var ingestorRunInfos = new List() + { + new () + { + IngestorRunInfoId = Guid.NewGuid(), + IngestorType = IngestorTypes.FosDnaDocument, + IndexTotal = 5, + IndexFilePath = $"Path1\\{DateTime.Now:yyyyMMdd}\\Path1\\", + IndexFileName = "Filename", + StartTimeStamp = new DateTime(2023, 03, 27), + EndTimeStamp = new DateTime(2023, 03, 27), + ArchiveTimeStamp = null, + } + }; + + var docProcessingInfoFiles = new List() + { + "Filename1.pdf", + "Filename2.pdf", + "Filename3.pdf", + }; + + _mockIngestorRunInfoService.Setup(x => x.FindByIngestionEndDateNotArchived(It.IsAny())) + .Returns(ingestorRunInfos).Verifiable(); + + _mockDocumentProcessingInfoService.Setup(x => x.CountCompletedByIngestorRunInfoIdAsync(It.IsAny())) + .ReturnsAsync(docProcessingInfoFiles.Count).Verifiable(); + + // Act + await _ingestionFolderCleanUpService.HandleIngestionFolderCleanUp(request); + + // Assert + _mockIngestorRunInfoService.Verify(x => x.FindByIngestionEndDateNotArchived(It.IsAny()), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.Update(It.IsAny()), Times.Never); + + _mockDocumentProcessingInfoService.Verify(x => x.CountCompletedByIngestorRunInfoIdAsync(It.IsAny()), Times.Exactly(ingestorRunInfos.Count)); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task HandleIngestionFolderCleanUp_ArchivedFileCount_IndexTotal_Mismatch() + { + // Arrange + var request = new IngestionFolderCleanUpRequest() + { + ArchiveDate = new DateTime(2023, 03, 30), + ArchiveRootPath = "\\\\zeus\\some\\path\\", + IngestionEndedDate = new DateTime(2023, 3, 30) + }; + + var ingestorRunInfos = new List() + { + new () + { + IngestorRunInfoId = Guid.NewGuid(), + IngestorType = IngestorTypes.FosDnaDocument, + IndexTotal = 5, + IndexFilePath = $"Path1\\{DateTime.Now:yyyyMMdd}\\Path1\\", + IndexFileName = "Filename", + StartTimeStamp = new DateTime(2023, 03, 27), + EndTimeStamp = new DateTime(2023, 03, 27), + ArchiveTimeStamp = null, + }, + }; + + var docProcessingInfoFiles = new List() + { + "Filename1.pdf", + "Filename2.pdf", + "Filename3.pdf" + }; + + var successfulRequestResponse = new RequestResponse() + { + IsSuccessful = true, + MessageStack = null, + ReturnResponse = null + }; + + _mockIngestorRunInfoService.Setup(x => x.FindByIngestionEndDateNotArchived(It.IsAny())) + .Returns(ingestorRunInfos).Verifiable(); + + _mockDocumentProcessingInfoService.Setup(x => x.CountCompletedByIngestorRunInfoIdAsync(It.IsAny())) + .ReturnsAsync(5).Verifiable(); + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ArchiveFiles}")))).ReturnsAsync(docProcessingInfoFiles).Verifiable(); + + // Act + await _ingestionFolderCleanUpService.HandleIngestionFolderCleanUp(request); + + // Assert + _mockIngestorRunInfoService.Verify(x => x.FindByIngestionEndDateNotArchived(It.IsAny()), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.Update(It.IsAny()), Times.Never); + + _mockDocumentProcessingInfoService.Verify(x => x.CountCompletedByIngestorRunInfoIdAsync(It.IsAny()), Times.Exactly(ingestorRunInfos.Count)); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ArchiveFiles}"))), Times.Exactly(ingestorRunInfos.Count)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ZipFileRegex}"))), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task HandleIngestionFolderCleanUp_ZipFile_NotFound() + { + // Arrange + var request = new IngestionFolderCleanUpRequest() + { + ArchiveDate = new DateTime(2023, 03, 30), + ArchiveRootPath = "\\\\zeus\\some\\path\\", + IngestionEndedDate = new DateTime(2023, 3, 30) + }; + + var ingestorRunInfos = new List() + { + new () + { + IngestorRunInfoId = Guid.NewGuid(), + IngestorType = IngestorTypes.FosDnaDocument, + IndexTotal = 5, + IndexFilePath = $"Path1\\{DateTime.Now.ToString("yyyyMMdd")}\\Path1\\", + IndexFileName = "Filename", + StartTimeStamp = new DateTime(2023, 03, 27), + EndTimeStamp = new DateTime(2023, 03, 27), + ArchiveTimeStamp = null, + }, + }; + + var docProcessingInfoFiles = new List() + { + "Filename1.pdf", + "Filename2.pdf", + "Filename3.pdf", + "Filename4.pdf", + "Filename5.pdf" + }; + + _mockIngestorRunInfoService.Setup(x => x.FindByIngestionEndDateNotArchived(It.IsAny())) + .Returns(ingestorRunInfos).Verifiable(); + + _mockDocumentProcessingInfoService.Setup(x => x.CountCompletedByIngestorRunInfoIdAsync(It.IsAny())) + .ReturnsAsync(docProcessingInfoFiles.Count).Verifiable(); + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ArchiveFiles}")))).ReturnsAsync(docProcessingInfoFiles).Verifiable(); + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ZipFileRegex}")))).ReturnsAsync(new List()).Verifiable(); + + // Act + await _ingestionFolderCleanUpService.HandleIngestionFolderCleanUp(request); + + // Assert + _mockIngestorRunInfoService.Verify(x => x.FindByIngestionEndDateNotArchived(It.IsAny()), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.Update(It.IsAny()), Times.Never); + + _mockDocumentProcessingInfoService.Verify(x => x.CountCompletedByIngestorRunInfoIdAsync(It.IsAny()), Times.Exactly(ingestorRunInfos.Count)); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ArchiveFiles}"))), Times.Exactly(ingestorRunInfos.Count)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ZipFileRegex}"))), Times.Exactly(ingestorRunInfos.Count)); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task HandleIngestionFolderCleanUp_CreateArchiveDirectory_Exception() + { + var now = DateTime.Now.ToString("yyyyMMdd"); + // Arrange + var request = new IngestionFolderCleanUpRequest() + { + ArchiveDate = new DateTime(2023, 03, 30), + ArchiveRootPath = $"\\\\zeus\\some\\path\\{now}\\", + IngestionEndedDate = new DateTime(2023, 3, 30) + }; + + var ingestorRunInfos = new List() + { + new () + { + IngestorRunInfoId = Guid.NewGuid(), + IngestorType = IngestorTypes.FosDnaDocument, + IndexTotal = 5, + IndexFilePath = $"Path1\\{now}\\Path1\\", + IndexFileName = "Filename", + StartTimeStamp = new DateTime(2023, 03, 27), + EndTimeStamp = new DateTime(2023, 03, 27), + ArchiveTimeStamp = null, + }, + new () + { + IngestorRunInfoId = Guid.NewGuid(), + IngestorType = IngestorTypes.FosDnaDocument, + IndexTotal = 5, + IndexFilePath = $"Path2\\{now}\\Path2\\", + IndexFileName = "Filename", + StartTimeStamp = new DateTime(2023, 03, 28), + EndTimeStamp = new DateTime(2023, 03, 28), + ArchiveTimeStamp = null, + }, + }; + + var docProcessingInfoFiles = new List() + { + "Filename1.pdf", + "Filename2.pdf", + "Filename3.pdf", + "Filename4.pdf", + "Filename5.pdf" + }; + + var successfulRequestResponse = new RequestResponse() + { + IsSuccessful = true, + MessageStack = null, + ReturnResponse = null + }; + + _mockIngestorRunInfoService.Setup(x => x.FindByIngestionEndDateNotArchived(It.IsAny())) + .Returns(ingestorRunInfos).Verifiable(); + + _mockDocumentProcessingInfoService.Setup(x => x.CountCompletedByIngestorRunInfoIdAsync(It.IsAny())) + .ReturnsAsync(docProcessingInfoFiles.Count).Verifiable(); + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ArchiveFiles}")))).ReturnsAsync(docProcessingInfoFiles).Verifiable(); + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ZipFileRegex}")))).ReturnsAsync(new List() { "" }).Verifiable(); + _mockFileOperationsApiService.Setup(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny())).ThrowsAsync(new ServiceException("Exception from test")).Verifiable(); + + // Act + Assert.ThrowsAsync(async () => await _ingestionFolderCleanUpService.HandleIngestionFolderCleanUp(request)); + + // Assert + _mockIngestorRunInfoService.Verify(x => x.FindByIngestionEndDateNotArchived(It.IsAny()), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.Update(It.IsAny()), Times.Never); + + _mockDocumentProcessingInfoService.Verify(x => x.CountCompletedByIngestorRunInfoIdAsync(It.IsAny()), Times.Once); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ArchiveFiles}"))), Times.Once); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ZipFileRegex}"))), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task HandleIngestionFolderCleanUp_MoveZipFile_Exception() + { + var now = DateTime.Now.ToString("yyyyMMdd"); + // Arrange + var request = new IngestionFolderCleanUpRequest() + { + ArchiveDate = new DateTime(2023, 03, 30), + ArchiveRootPath = "\\\\zeus\\some\\path\\", + IngestionEndedDate = new DateTime(2023, 3, 30) + }; + + var ingestorRunInfos = new List() + { + new () + { + IngestorRunInfoId = Guid.NewGuid(), + IngestorType = IngestorTypes.FosDnaDocument, + IndexTotal = 5, + IndexFilePath = $"Path1\\{now}\\Path1\\", + IndexFileName = "Filename", + StartTimeStamp = new DateTime(2023, 03, 27), + EndTimeStamp = new DateTime(2023, 03, 27), + ArchiveTimeStamp = null, + }, + new () + { + IngestorRunInfoId = Guid.NewGuid(), + IngestorType = IngestorTypes.FosDnaDocument, + IndexTotal = 5, + IndexFilePath = $"Path2\\{now}\\Path2\\", + IndexFileName = "Filename", + StartTimeStamp = new DateTime(2023, 03, 28), + EndTimeStamp = new DateTime(2023, 03, 28), + ArchiveTimeStamp = null, + }, + new () + { + IngestorRunInfoId = Guid.NewGuid(), + IngestorType = IngestorTypes.FosDnaDocument, + IndexTotal = 5, + IndexFilePath = $"Path3\\{now}\\Path3\\", + IndexFileName = "Filename", + StartTimeStamp = new DateTime(2023, 03, 29), + EndTimeStamp = new DateTime(2023, 03, 29), + ArchiveTimeStamp = null, + } + }; + + var docProcessingInfoFiles = new List() + { + "Filename1.pdf", + "Filename2.pdf", + "Filename3.pdf", + "Filename4.pdf", + "Filename5.pdf" + }; + + var successfulRequestResponse = new RequestResponse() + { + IsSuccessful = true, + MessageStack = null, + ReturnResponse = null + }; + + _mockIngestorRunInfoService.Setup(x => x.FindByIngestionEndDateNotArchived(It.IsAny())) + .Returns(ingestorRunInfos).Verifiable(); + _mockIngestorRunInfoService.Setup(x => x.Update(It.IsAny())).Verifiable(); + + _mockDocumentProcessingInfoService.Setup(x => x.CountCompletedByIngestorRunInfoIdAsync(It.IsAny())) + .ReturnsAsync(docProcessingInfoFiles.Count).Verifiable(); + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ArchiveFiles}")))).ReturnsAsync(docProcessingInfoFiles).Verifiable(); + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ZipFileRegex}")))).ReturnsAsync(new List() { "" }).Verifiable(); + _mockFileOperationsApiService.Setup(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny())).ReturnsAsync(successfulRequestResponse).Verifiable(); + _mockFileOperationsApiService.Setup(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(successfulRequestResponse).Verifiable(); + _mockFileOperationsApiService.Setup(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny())).ThrowsAsync(new ServiceException("Exception from test")).Verifiable(); + + // Act + await _ingestionFolderCleanUpService.HandleIngestionFolderCleanUp(request); + + // Assert + _mockIngestorRunInfoService.Verify(x => x.FindByIngestionEndDateNotArchived(It.IsAny()), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.Update(It.IsAny()), Times.Exactly(ingestorRunInfos.Count)); + + _mockDocumentProcessingInfoService.Verify(x => x.CountCompletedByIngestorRunInfoIdAsync(It.IsAny()), Times.Exactly(ingestorRunInfos.Count)); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ArchiveFiles}"))), Times.Exactly(ingestorRunInfos.Count)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ZipFileRegex}"))), Times.Exactly(ingestorRunInfos.Count)); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(ingestorRunInfos.Count)); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(ingestorRunInfos.Count)); + } + + [Test] + public async Task HandleIngestionFolderCleanUp_BuildDynamicFileList_Failure() + { + var now = DateTime.Now.ToString("yyyyMMdd"); + // Arrange + var request = new IngestionFolderCleanUpRequest() + { + ArchiveDate = new DateTime(2023, 03, 30), + ArchiveRootPath = "\\\\zeus\\some\\path\\", + IngestionEndedDate = new DateTime(2023, 3, 30) + }; + + var ingestorRunInfos = new List() + { + new () + { + IngestorRunInfoId = Guid.NewGuid(), + IngestorType = IngestorTypes.FosDnaDocument, + IndexTotal = 5, + IndexFilePath = $"Path1\\{now}\\Path1\\", + IndexFileName = "Filename", + StartTimeStamp = new DateTime(2023, 03, 27), + EndTimeStamp = new DateTime(2023, 03, 27), + ArchiveTimeStamp = null, + }, + new () + { + IngestorRunInfoId = Guid.NewGuid(), + IngestorType = IngestorTypes.FosDnaDocument, + IndexTotal = 5, + IndexFilePath = $"Path2\\{now}\\Path2\\", + IndexFileName = "Filename", + StartTimeStamp = new DateTime(2023, 03, 28), + EndTimeStamp = new DateTime(2023, 03, 28), + ArchiveTimeStamp = null, + }, + new () + { + IngestorRunInfoId = Guid.NewGuid(), + IngestorType = IngestorTypes.FosDnaDocument, + IndexTotal = 5, + IndexFilePath = $"Path3\\{now}\\Path3\\", + IndexFileName = "Filename", + StartTimeStamp = new DateTime(2023, 03, 29), + EndTimeStamp = new DateTime(2023, 03, 29), + ArchiveTimeStamp = null, + } + }; + + var docProcessingInfoFiles = new List() + { + "Filename1.pdf", + "Filename2.pdf", + "Filename3.pdf", + "Filename4.pdf", + "Filename5.pdf" + }; + + _mockIngestorRunInfoService.Setup(x => x.FindByIngestionEndDateNotArchived(It.IsAny())) + .Returns(ingestorRunInfos).Verifiable(); + _mockIngestorRunInfoService.Setup(x => x.Update(It.IsAny())).Verifiable(); + + _mockDocumentProcessingInfoService.Setup(x => x.CountCompletedByIngestorRunInfoIdAsync(It.IsAny())) + .ReturnsAsync(docProcessingInfoFiles.Count).Verifiable(); + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ArchiveFiles}")))).ReturnsAsync(docProcessingInfoFiles).Verifiable(); + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ZipFileRegex}")))).ThrowsAsync(new ServiceException("Exception from test")).Verifiable(); + + // Act + await _ingestionFolderCleanUpService.HandleIngestionFolderCleanUp(request); + + // Assert + _mockIngestorRunInfoService.Verify(x => x.FindByIngestionEndDateNotArchived(It.IsAny()), Times.Once); + + _mockDocumentProcessingInfoService.Verify(x => x.CountCompletedByIngestorRunInfoIdAsync(It.IsAny()), Times.Exactly(ingestorRunInfos.Count)); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ArchiveFiles}"))), Times.Exactly(ingestorRunInfos.Count)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ZipFileRegex}"))), Times.Exactly(ingestorRunInfos.Count)); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + _mockIngestorRunInfoService.Verify(x => x.Update(It.IsAny()), Times.Never); + } + + [Test] + public async Task HandleIngestionFolderCleanUp_IncorrectFilePathFormat_Failure() + { + // Arrange + var request = new IngestionFolderCleanUpRequest() + { + ArchiveDate = new DateTime(2023, 03, 30), + ArchiveRootPath = "\\\\zeus\\some\\path\\", + IngestionEndedDate = new DateTime(2023, 3, 30) + }; + + var ingestorRunInfos = new List() + { + new () + { + IngestorRunInfoId = Guid.NewGuid(), + IngestorType = IngestorTypes.FosDnaDocument, + IndexTotal = 5, + IndexFilePath = "Path1", + IndexFileName = "Filename", + StartTimeStamp = new DateTime(2023, 03, 27), + EndTimeStamp = new DateTime(2023, 03, 27), + ArchiveTimeStamp = null, + }, + new () + { + IngestorRunInfoId = Guid.NewGuid(), + IngestorType = IngestorTypes.FosDnaDocument, + IndexTotal = 5, + IndexFilePath = "Path2", + IndexFileName = "Filename", + StartTimeStamp = new DateTime(2023, 03, 28), + EndTimeStamp = new DateTime(2023, 03, 28), + ArchiveTimeStamp = null, + }, + new () + { + IngestorRunInfoId = Guid.NewGuid(), + IngestorType = IngestorTypes.FosDnaDocument, + IndexTotal = 5, + IndexFilePath = "Path3", + IndexFileName = "Filename", + StartTimeStamp = new DateTime(2023, 03, 29), + EndTimeStamp = new DateTime(2023, 03, 29), + ArchiveTimeStamp = null, + } + }; + + _mockIngestorRunInfoService.Setup(x => x.FindByIngestionEndDateNotArchived(It.IsAny())) + .Returns(ingestorRunInfos).Verifiable(); + _mockIngestorRunInfoService.Setup(x => x.Update(It.IsAny())).Verifiable(); + + // Act + await _ingestionFolderCleanUpService.HandleIngestionFolderCleanUp(request); + + // Assert + _mockIngestorRunInfoService.Verify(x => x.FindByIngestionEndDateNotArchived(It.IsAny()), Times.Once); + + _mockIngestorRunInfoService.Verify(x => x.Update(It.IsAny()), Times.Never); + _mockDocumentProcessingInfoService.Verify(x => x.CountCompletedByIngestorRunInfoIdAsync(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ArchiveFiles}"))), Times.Never); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ZipFileRegex}"))), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task HandleIngestionFolderCleanUp_DeleteUnzippedFolder_Exception() + { + var now = DateTime.Now.ToString("yyyyMMdd"); + // Arrange + var request = new IngestionFolderCleanUpRequest() + { + ArchiveDate = new DateTime(2023, 03, 30), + ArchiveRootPath = "\\\\zeus\\some\\path\\", + IngestionEndedDate = new DateTime(2023, 3, 30) + }; + + var ingestorRunInfos = new List() + { + new () + { + IngestorRunInfoId = Guid.NewGuid(), + IngestorType = IngestorTypes.FosDnaDocument, + IndexTotal = 5, + IndexFilePath = $"Path1\\{now}\\Path1\\", + IndexFileName = "Filename", + StartTimeStamp = new DateTime(2023, 03, 27), + EndTimeStamp = new DateTime(2023, 03, 27), + ArchiveTimeStamp = null, + }, + new () + { + IngestorRunInfoId = Guid.NewGuid(), + IngestorType = IngestorTypes.FosDnaDocument, + IndexTotal = 5, + IndexFilePath = $"Path2\\{now}\\Path2\\", + IndexFileName = "Filename", + StartTimeStamp = new DateTime(2023, 03, 28), + EndTimeStamp = new DateTime(2023, 03, 28), + ArchiveTimeStamp = null, + }, + new () + { + IngestorRunInfoId = Guid.NewGuid(), + IngestorType = IngestorTypes.FosDnaDocument, + IndexTotal = 5, + IndexFilePath = $"Path3\\{now}\\Path3\\", + IndexFileName = "Filename", + StartTimeStamp = new DateTime(2023, 03, 29), + EndTimeStamp = new DateTime(2023, 03, 29), + ArchiveTimeStamp = null, + } + }; + + var docProcessingInfoFiles = new List() + { + "Filename1.pdf", + "Filename2.pdf", + "Filename3.pdf", + "Filename4.pdf", + "Filename5.pdf" + }; + + var successfulRequestResponse = new RequestResponse() + { + IsSuccessful = true, + MessageStack = null, + ReturnResponse = null + }; + + _mockIngestorRunInfoService.Setup(x => x.FindByIngestionEndDateNotArchived(It.IsAny())) + .Returns(ingestorRunInfos).Verifiable(); + _mockIngestorRunInfoService.Setup(x => x.Update(It.IsAny())).Verifiable(); + + _mockDocumentProcessingInfoService.Setup(x => x.CountCompletedByIngestorRunInfoIdAsync(It.IsAny())) + .ReturnsAsync(docProcessingInfoFiles.Count).Verifiable(); + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ArchiveFiles}")))).ReturnsAsync(docProcessingInfoFiles).Verifiable(); + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ZipFileRegex}")))).ReturnsAsync(new List() { "" }).Verifiable(); + _mockFileOperationsApiService.Setup(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny())).ReturnsAsync(successfulRequestResponse).Verifiable(); + _mockFileOperationsApiService.Setup(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ThrowsAsync(new ServiceException("Exception from test")).Verifiable(); + _mockFileOperationsApiService.Setup(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny())).Verifiable(); + + // Act + await _ingestionFolderCleanUpService.HandleIngestionFolderCleanUp(request); + + // Assert + _mockIngestorRunInfoService.Verify(x => x.FindByIngestionEndDateNotArchived(It.IsAny()), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.Update(It.IsAny()), Times.Exactly(ingestorRunInfos.Count)); + + _mockDocumentProcessingInfoService.Verify(x => x.CountCompletedByIngestorRunInfoIdAsync(It.IsAny()), Times.Exactly(ingestorRunInfos.Count)); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ArchiveFiles}"))), Times.Exactly(ingestorRunInfos.Count)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.Is(d => d.Filename.Equals("{ZipFileRegex}"))), Times.Exactly(ingestorRunInfos.Count)); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(ingestorRunInfos.Count)); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(ingestorRunInfos.Count)); + } +} + diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/MemberDocumentNotifierServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/MemberDocumentNotifierServiceTest.cs new file mode 100644 index 0000000..6e28242 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/MemberDocumentNotifierServiceTest.cs @@ -0,0 +1,606 @@ +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using LCU.API.Internal.DocumentIngestor.Services.MemberNotificationInfoDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.NotificationsModels.Models; +using LCU.Library.DocumentType.Models.Requests; +using LCU.Library.DocumentType.Models.Responses.External; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.LcuMassTransitModels; +using Moq; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.IngestionOperationServices; + +public class MemberDocumentNotifierServiceTest +{ + private MemberDocumentNotifierService _memberDocumentNotifierService; + private Mock _mockMemberNotificationInfoService; + private Mock _mockDocumentTypeRetrieverService; + private Mock _mockDocumentProcessingInfoService; + private Mock _mockNotificationApiService; + private Mock _mockMemberNotificationInfoDeterminingService; + private Mock _mockQueueMemberNotificationCompletionService; + private ApiConfiguration _apiConfiguration; + private ConnectionConfiguration _connectionConfiguration; + private ReceiveEndpointConfigurations _receiveEndpointConfigurations; + private DigitalBankingConfiguration _digitalBankingConfiguration; + + [SetUp] + public void Setup() + { + _apiConfiguration = new ApiConfiguration + { + MaxMemberNotificationAttempts = 3, + MaliciousFileSearchPaddingHours = 1, + TimeZone = "America/Chicago", + NotificationEmailTemplate = @"../../../../LCU.API.Internal.DocumentIngestor/Templates/NotificationEmailTemplate.html", + NotificationEmailRowTemplate = @"../../../../LCU.API.Internal.DocumentIngestor/Templates/NotificationEmailRowTemplate.html", + FeatureFlags = new FeatureFlags() { RestrictNotificationRecipients = false }, + BatchSkipAmount = 10000, + Notifications = new Notifications + { + AllowedRecipientExpression = "*" + } + }; + _connectionConfiguration = new ConnectionConfiguration() + { + HostUrl = "Test", + UserName = "Test", + Password = "Test" + }; + _receiveEndpointConfigurations = new ReceiveEndpointConfigurations() + { + MemberNotificationCompletionEndpoint = new ReceiveEndpointConfiguration() + { + ReceiveEndpoint = "Test", + ReceiveEndpointType = "Exchange", + PrefetchLimit = 1 + } + }; + + _digitalBankingConfiguration = new DigitalBankingConfiguration() + { + DigitalBankingUrl = "https://digitalbanking.landmarkcu.com/eDocs", + MobileBankingApiKey = "TEST", + MobileBankingBaseUrl = "https://qa-redirect-api.qa.applications.landmarkcu.com/index.html", + MobileBankingLinkId = "a4e648ff-247a-42a8-b153-4b65d4933d1c" + }; + + _mockMemberNotificationInfoService = new Mock(); + _mockDocumentTypeRetrieverService = new Mock(); + _mockDocumentProcessingInfoService = new Mock(); + _mockNotificationApiService = new Mock(); + _mockMemberNotificationInfoDeterminingService = new Mock(); + _mockQueueMemberNotificationCompletionService = new Mock(); + _memberDocumentNotifierService = new MemberDocumentNotifierService(_mockMemberNotificationInfoService.Object, + _mockDocumentTypeRetrieverService.Object, + _mockDocumentProcessingInfoService.Object, + _mockNotificationApiService.Object, + _mockMemberNotificationInfoDeterminingService.Object, + _mockQueueMemberNotificationCompletionService.Object, + _apiConfiguration, + _connectionConfiguration, + _receiveEndpointConfigurations, + _digitalBankingConfiguration); + } + + [Test] + public async Task PrepareAndSendNotifications_Success() + { + var request = new MemberDocumentNotificationRequest() { RunCriticalFailureNotifications = false }; + var memberNotificationInfos = GenerateMemberNotificationInfos(); + var documentProcessingInfos = GenerateDocumentProcessingInfos(); + var documentCodeDetailInfos = GenerateDocumentCodeDetailInfos(); + var deliveryMethod = (memberNotificationInfos[2].EmailAddress, DeliveryMethod.Electronic); + List maliciousDocuments = null; + + _mockMemberNotificationInfoService + .Setup(x => x.GetSendableMemberNotificationInfosAsync(It.IsAny(), _apiConfiguration.MaxMemberNotificationAttempts)) + .ReturnsAsync(memberNotificationInfos); + _mockDocumentProcessingInfoService.Setup(x => x.GetListByIdAsync(It.IsAny>())).ReturnsAsync(documentProcessingInfos); + _mockMemberNotificationInfoDeterminingService.Setup(x => x.DetermineDeliveryMethod(It.IsAny())).ReturnsAsync(deliveryMethod); + _mockDocumentTypeRetrieverService.Setup(x => x.GetListOfMaliciousDocuments(It.IsAny())).ReturnsAsync(maliciousDocuments); + _mockDocumentTypeRetrieverService.SetupSequence(x => x.GetDocumentCodeDetailByBusinessName(It.IsAny())) + .ReturnsAsync(documentCodeDetailInfos[0]) + .ReturnsAsync(documentCodeDetailInfos[1]) + .ReturnsAsync(documentCodeDetailInfos[2]); + + var result = await _memberDocumentNotifierService.PrepareAndSendNotifications(request); + Assert.NotNull(result); + Assert.IsTrue(result.IsSuccessful); + Assert.IsEmpty(result.Messages); + Assert.Zero(result.FailureCount); + _mockMemberNotificationInfoService.Verify(x => x.GetSendableMemberNotificationInfosAsync(It.IsAny(), It.IsAny()), Times.Once); + _mockDocumentProcessingInfoService.Verify(x => x.GetListByIdAsync(It.IsAny>()), Times.Once); + _mockMemberNotificationInfoDeterminingService.Verify(x => x.DetermineDeliveryMethod(It.IsAny()), Times.Once); + _mockDocumentTypeRetrieverService.Verify(x => x.GetListOfMaliciousDocuments(It.IsAny()), Times.Once); + _mockDocumentTypeRetrieverService.Verify(x => x.GetDocumentCodeDetailByBusinessName(It.IsAny()), Times.Exactly(3)); + _mockNotificationApiService.Verify(x => x.SendEmailAsync(It.IsAny()), Times.Exactly(2)); + } + + [Test] + public async Task PrepareAndSendNotifications_Success_NoMemberNotificationsToSend() + { + var request = new MemberDocumentNotificationRequest() { RunCriticalFailureNotifications = false }; + var memberNotificationInfos = new List(); + + _mockMemberNotificationInfoService + .Setup(x => x.GetSendableMemberNotificationInfosAsync(It.IsAny(), _apiConfiguration.MaxMemberNotificationAttempts)) + .ReturnsAsync(memberNotificationInfos); + + var result = await _memberDocumentNotifierService.PrepareAndSendNotifications(request); + Assert.NotNull(result); + Assert.IsTrue(result.IsSuccessful); + Assert.AreEqual(result.Messages.Count, 1); + Assert.Zero(result.FailureCount); + _mockMemberNotificationInfoService.Verify(x => x.GetSendableMemberNotificationInfosAsync(It.IsAny(), It.IsAny()), Times.Once); + _mockDocumentProcessingInfoService.Verify(x => x.GetListByIdAsync(It.IsAny>()), Times.Never); + _mockMemberNotificationInfoDeterminingService.Verify(x => x.DetermineDeliveryMethod(It.IsAny()), Times.Never); + _mockDocumentTypeRetrieverService.Verify(x => x.GetListOfMaliciousDocuments(It.IsAny()), Times.Never); + _mockDocumentTypeRetrieverService.Verify(x => x.GetDocumentCodeDetailByBusinessName(It.IsAny()), Times.Never); + _mockNotificationApiService.Verify(x => x.SendEmailAsync(It.IsAny()), Times.Never); + } + + [Test] + public async Task PrepareAndSendNotifications_FailureCount() + { + var request = new MemberDocumentNotificationRequest() { RunCriticalFailureNotifications = false }; + var memberNotificationInfos = GenerateMemberNotificationInfos(); + var documentProcessingInfos = GenerateDocumentProcessingInfos(); + + _mockMemberNotificationInfoService + .Setup(x => x.GetSendableMemberNotificationInfosAsync(It.IsAny(), _apiConfiguration.MaxMemberNotificationAttempts)) + .ReturnsAsync(memberNotificationInfos); + _mockDocumentProcessingInfoService.Setup(x => x.GetListByIdAsync(It.IsAny>())).ReturnsAsync(documentProcessingInfos); + _mockDocumentProcessingInfoService.Setup(x => x.GetListByIdAsync(It.IsAny>())).ThrowsAsync(new Exception("Failure")); + + var result = await _memberDocumentNotifierService.PrepareAndSendNotifications(request); + Assert.NotNull(result); + Assert.IsTrue(result.IsFailure); + Assert.AreEqual(result.Messages.Count, 1); + Assert.AreEqual(result.FailureCount, 1); + _mockMemberNotificationInfoService.Verify(x => x.GetSendableMemberNotificationInfosAsync(It.IsAny(), It.IsAny()), Times.Once); + _mockDocumentProcessingInfoService.Verify(x => x.GetListByIdAsync(It.IsAny>()), Times.Once); + _mockMemberNotificationInfoDeterminingService.Verify(x => x.DetermineDeliveryMethod(It.IsAny()), Times.Never); + _mockDocumentTypeRetrieverService.Verify(x => x.GetListOfMaliciousDocuments(It.IsAny()), Times.Never); + _mockDocumentTypeRetrieverService.Verify(x => x.GetDocumentCodeDetailByBusinessName(It.IsAny()), Times.Never); + _mockNotificationApiService.Verify(x => x.SendEmailAsync(It.IsAny()), Times.Never); + } + + [Test] + public async Task PrepareAndSendNotifications_Success_MaliciousFile() + { + var request = new MemberDocumentNotificationRequest() { RunCriticalFailureNotifications = false }; + var memberNotificationInfos = GenerateMemberNotificationInfos(); + var documentProcessingInfos = GenerateDocumentProcessingInfos(); + var documentCodeDetailInfos = GenerateDocumentCodeDetailInfos(); + var deliveryMethod = (memberNotificationInfos[2].EmailAddress, DeliveryMethod.Electronic); + var maliciousId = Guid.NewGuid(); + var maliciousDocuments = new List() + { + new() + { + DocumentId = maliciousId + } + }; + documentProcessingInfos[1].DocumentId = maliciousId; + + _mockMemberNotificationInfoService + .Setup(x => x.GetSendableMemberNotificationInfosAsync(It.IsAny(), _apiConfiguration.MaxMemberNotificationAttempts)) + .ReturnsAsync(memberNotificationInfos); + _mockDocumentProcessingInfoService.Setup(x => x.GetListByIdAsync(It.IsAny>())).ReturnsAsync(documentProcessingInfos); + _mockMemberNotificationInfoDeterminingService.Setup(x => x.DetermineDeliveryMethod(It.IsAny())).ReturnsAsync(deliveryMethod); + _mockDocumentTypeRetrieverService.Setup(x => x.GetListOfMaliciousDocuments(It.IsAny())).ReturnsAsync(maliciousDocuments); + _mockDocumentTypeRetrieverService.SetupSequence(x => x.GetDocumentCodeDetailByBusinessName(It.IsAny())) + .ReturnsAsync(documentCodeDetailInfos[0]) + .ReturnsAsync(documentCodeDetailInfos[2]); + + var result = await _memberDocumentNotifierService.PrepareAndSendNotifications(request); + Assert.NotNull(result); + Assert.IsTrue(result.IsSuccessful); + Assert.IsEmpty(result.Messages); + Assert.Zero(result.FailureCount); + _mockMemberNotificationInfoService.Verify(x => x.GetSendableMemberNotificationInfosAsync(It.IsAny(), It.IsAny()), Times.Once); + _mockDocumentProcessingInfoService.Verify(x => x.GetListByIdAsync(It.IsAny>()), Times.Once); + _mockDocumentTypeRetrieverService.Verify(x => x.GetListOfMaliciousDocuments(It.IsAny()), Times.Once); + _mockDocumentTypeRetrieverService.Verify(x => x.GetDocumentCodeDetailByBusinessName(It.IsAny()), Times.Exactly(2)); + _mockNotificationApiService.Verify(x => x.SendEmailAsync(It.IsAny()), Times.Exactly(2)); + } + + [Test] + public async Task PrepareAndSendNotifications_RestrictNotificationRecipientsOff_SendsToAnyEmail() + { + var disallowedRecipient = MemberNotificationFactory(); + _apiConfiguration.FeatureFlags.RestrictNotificationRecipients = false; + _apiConfiguration.Notifications.AllowedRecipientExpression = $"(?!{disallowedRecipient.EmailAddress})\\A"; + var request = new MemberDocumentNotificationRequest + { + RunCriticalFailureNotifications = false + }; + var memberNotificationInfos = Enumerable.Repeat(() => MemberNotificationFactory(), 3) + .Select(f => f()) + .Concat(new[] { disallowedRecipient }) + .ToArray(); + var documentProcessingInfos = Enumerable.Repeat> + ( + i => DocumentProcessingInfoFactory(documentProcessingInfoId: memberNotificationInfos[i].DocumentProcessingInfoId), + memberNotificationInfos.Length + ) + .Select((f, i) => f(i)) + .ToArray(); + var documentCodeDetails = Enumerable.Repeat> + ( + i => DocumentCodeDetailInfoFactory(documentBusinessName: documentProcessingInfos[i].DocumentBusinessName), + documentProcessingInfos.Length + ) + .Select((f, i) => f(i)) + .ToDictionary(dcd => dcd.DocumentBusinessName); + var sentEmails = new List(); + _mockMemberNotificationInfoService + .Setup(mnis => mnis.GetSendableMemberNotificationInfosAsync(It.IsAny(), _apiConfiguration.MaxMemberNotificationAttempts)) + .ReturnsAsync(memberNotificationInfos); + _mockDocumentProcessingInfoService + .Setup(dpis => dpis.GetListByIdAsync(It.IsAny>())) + .ReturnsAsync(documentProcessingInfos); + _mockDocumentTypeRetrieverService + .Setup(dtrs => dtrs.GetListOfMaliciousDocuments(It.IsAny())) + .ReturnsAsync((IEnumerable)null); + _mockDocumentTypeRetrieverService + .Setup(dtrs => dtrs.GetDocumentCodeDetailByBusinessName(It.IsAny())) + .Returns(async businessName => documentCodeDetails.TryGetValue(businessName, out var documentCodeDetail) ? documentCodeDetail : null); + _mockNotificationApiService + .Setup(nas => nas.SendEmailAsync(It.IsAny())) + .Callback(sentEmails.Add); + + var result = await _memberDocumentNotifierService.PrepareAndSendNotifications(request); + + Assert.IsFalse(result.IsFailure); + Assert.IsTrue(result.IsSuccessful); + Assert.AreEqual(0, result.FailureCount); + Assert.AreEqual(memberNotificationInfos.Length, sentEmails.Select(se => se.Recipient).Distinct().Count()); + } + + [Test] + public async Task PrepareAndSendNotifications_RestrictNotificationRecipientsOnAndAnyUnmatched_DoesNotSendToUnmatchedEmails() + { + var disallowedRecipient = MemberNotificationFactory(); + _apiConfiguration.FeatureFlags.RestrictNotificationRecipients = true; + _apiConfiguration.Notifications.AllowedRecipientExpression = $"(?!{disallowedRecipient.EmailAddress})\\A"; + var request = new MemberDocumentNotificationRequest + { + RunCriticalFailureNotifications = false + }; + var memberNotificationInfos = Enumerable.Repeat(() => MemberNotificationFactory(), 3) + .Select(f => f()) + .Concat(new[] { disallowedRecipient }) + .ToArray(); + var documentProcessingInfos = Enumerable.Repeat> + ( + i => DocumentProcessingInfoFactory(documentProcessingInfoId: memberNotificationInfos[i].DocumentProcessingInfoId), + memberNotificationInfos.Length + ) + .Select((f, i) => f(i)) + .ToArray(); + var documentCodeDetails = Enumerable.Repeat> + ( + i => DocumentCodeDetailInfoFactory(documentBusinessName: documentProcessingInfos[i].DocumentBusinessName), + documentProcessingInfos.Length + ) + .Select((f, i) => f(i)) + .ToDictionary(dcd => dcd.DocumentBusinessName); + var sentEmails = new List(); + _mockMemberNotificationInfoService + .Setup(mnis => mnis.GetSendableMemberNotificationInfosAsync(It.IsAny(), _apiConfiguration.MaxMemberNotificationAttempts)) + .ReturnsAsync(memberNotificationInfos); + _mockDocumentProcessingInfoService + .Setup(dpis => dpis.GetListByIdAsync(It.IsAny>())) + .ReturnsAsync(documentProcessingInfos); + _mockDocumentTypeRetrieverService + .Setup(dtrs => dtrs.GetListOfMaliciousDocuments(It.IsAny())) + .ReturnsAsync((IEnumerable)null); + _mockDocumentTypeRetrieverService + .Setup(dtrs => dtrs.GetDocumentCodeDetailByBusinessName(It.IsAny())) + .Returns(async businessName => documentCodeDetails.TryGetValue(businessName, out var documentCodeDetail) ? documentCodeDetail : null); + _mockNotificationApiService + .Setup(nas => nas.SendEmailAsync(It.IsAny())) + .Callback(sentEmails.Add); + + var result = await _memberDocumentNotifierService.PrepareAndSendNotifications(request); + + Assert.IsTrue(result.IsFailure); + Assert.IsFalse(result.IsSuccessful); + Assert.AreEqual(1, result.FailureCount); + Assert.AreEqual(0, sentEmails.Count(se => se.Recipient.Contains(disallowedRecipient.EmailAddress))); + } + + [Test] + public async Task PrepareAndSendNotifications_RestrictNotificationRecipientsOnAndAllMatched_SendsToMatchedEmails() + { + var disallowedRecipient = MemberNotificationFactory(); + _apiConfiguration.FeatureFlags.RestrictNotificationRecipients = true; + _apiConfiguration.Notifications.AllowedRecipientExpression = $"(?!{disallowedRecipient.EmailAddress})\\A"; + var request = new MemberDocumentNotificationRequest + { + RunCriticalFailureNotifications = false + }; + var allowedMemberNotificationInfos = Enumerable.Repeat(() => MemberNotificationFactory(), 3) + .Select(f => f()) + .ToArray(); + var memberNotificationInfos = allowedMemberNotificationInfos + .Concat(new[] { disallowedRecipient }) + .ToArray(); + var documentProcessingInfos = Enumerable.Repeat> + ( + i => DocumentProcessingInfoFactory(documentProcessingInfoId: memberNotificationInfos[i].DocumentProcessingInfoId), + memberNotificationInfos.Length + ) + .Select((f, i) => f(i)) + .ToArray(); + var documentCodeDetails = Enumerable.Repeat> + ( + i => DocumentCodeDetailInfoFactory(documentBusinessName: documentProcessingInfos[i].DocumentBusinessName), + documentProcessingInfos.Length + ) + .Select((f, i) => f(i)) + .ToDictionary(dcd => dcd.DocumentBusinessName); + var sentEmails = new List(); + _mockMemberNotificationInfoService + .Setup(mnis => mnis.GetSendableMemberNotificationInfosAsync(It.IsAny(), _apiConfiguration.MaxMemberNotificationAttempts)) + .ReturnsAsync(memberNotificationInfos); + _mockDocumentProcessingInfoService + .Setup(dpis => dpis.GetListByIdAsync(It.IsAny>())) + .ReturnsAsync(documentProcessingInfos); + _mockDocumentTypeRetrieverService + .Setup(dtrs => dtrs.GetListOfMaliciousDocuments(It.IsAny())) + .ReturnsAsync((IEnumerable)null); + _mockDocumentTypeRetrieverService + .Setup(dtrs => dtrs.GetDocumentCodeDetailByBusinessName(It.IsAny())) + .Returns(async businessName => documentCodeDetails.TryGetValue(businessName, out var documentCodeDetail) ? documentCodeDetail : null); + _mockNotificationApiService + .Setup(nas => nas.SendEmailAsync(It.IsAny())) + .Callback(sentEmails.Add); + + await _memberDocumentNotifierService.PrepareAndSendNotifications(request); + + var allowedEmails = allowedMemberNotificationInfos.Select(mni => mni.EmailAddress); + Assert.AreEqual(allowedMemberNotificationInfos.Length, sentEmails.Count(se => se.Recipient.Any(r => allowedEmails.Contains(r)))); + } + + [Test] + public async Task PrepareAndSendNotifications_Failure_NullEmails() + { + var request = new MemberDocumentNotificationRequest() { RunCriticalFailureNotifications = false }; + var memberNotificationInfos = GenerateMemberNotificationInfos(); + memberNotificationInfos[0].EmailAddress = ""; + memberNotificationInfos[1].EmailAddress = ""; + memberNotificationInfos[2].EmailAddress = ""; + var documentProcessingInfos = GenerateDocumentProcessingInfos(); + var documentCodeDetailInfos = GenerateDocumentCodeDetailInfos(); + var deliveryMethod = (memberNotificationInfos[2].EmailAddress, DeliveryMethod.Electronic); + var maliciousId = Guid.NewGuid(); + List maliciousDocuments = null; + + _mockMemberNotificationInfoService + .Setup(x => x.GetSendableMemberNotificationInfosAsync(It.IsAny(), _apiConfiguration.MaxMemberNotificationAttempts)) + .ReturnsAsync(memberNotificationInfos); + _mockDocumentProcessingInfoService.Setup(x => x.GetListByIdAsync(It.IsAny>())).ReturnsAsync(documentProcessingInfos); + _mockMemberNotificationInfoDeterminingService.Setup(x => x.DetermineDeliveryMethod(It.IsAny())).ReturnsAsync(deliveryMethod); + _mockDocumentTypeRetrieverService.Setup(x => x.GetListOfMaliciousDocuments(It.IsAny())).ReturnsAsync(maliciousDocuments); + + var result = await _memberDocumentNotifierService.PrepareAndSendNotifications(request); + Assert.NotNull(result); + Assert.IsTrue(result.IsSuccessful); + Assert.AreEqual(result.Messages.Count, 0); + Assert.AreEqual(result.FailureCount, 0); + _mockMemberNotificationInfoService.Verify(x => x.GetSendableMemberNotificationInfosAsync(It.IsAny(), It.IsAny()), Times.Once); + _mockDocumentProcessingInfoService.Verify(x => x.GetListByIdAsync(It.IsAny>()), Times.Once); + _mockDocumentTypeRetrieverService.Verify(x => x.GetListOfMaliciousDocuments(It.IsAny()), Times.Once); + _mockDocumentTypeRetrieverService.Verify(x => x.GetDocumentCodeDetailByBusinessName(It.IsAny()), Times.Never); + _mockQueueMemberNotificationCompletionService.Verify(x => x.QueueMemberNotificationCompletionRequest(It.IsAny(), + It.IsAny(), + It.IsAny>()), Times.Exactly(2)); + _mockNotificationApiService.Verify(x => x.SendEmailAsync(It.IsAny()), Times.Never); + } + + [Test] + public void PrepareAndSendNotifications_ArgumentNullException() + { + MemberDocumentNotificationRequest request = null; + Assert.ThrowsAsync(async () => await _memberDocumentNotifierService.HandleMemberDocumentNotification(request)); + _mockMemberNotificationInfoService.Verify(x => x.GetSendableMemberNotificationInfosAsync(It.IsAny(), It.IsAny()), Times.Never); + _mockMemberNotificationInfoDeterminingService.Verify(x => x.DetermineDeliveryMethod(It.IsAny()), Times.Never); + _mockDocumentProcessingInfoService.Verify(x => x.GetListByIdAsync(It.IsAny>()), Times.Never); + _mockNotificationApiService.Verify(x => x.SendEmailAsync(It.IsAny()), Times.Never); + } + + [Test] + public async Task PrepareAndSendNotifications_BreakLargeChunk_Success() + { + var request = new MemberDocumentNotificationRequest() { RunCriticalFailureNotifications = false }; + var repeatAmount = 15000; + + var randomInt = new Random(); + var memberNotificationInfos = Enumerable.Repeat(1, repeatAmount) + .Select(_ => GenerateSingleMemberNotificationInfo(randomInt.Next(1, repeatAmount))).ToList(); + var documentProcessingInfos = Enumerable.Repeat(1, repeatAmount) + .Select(_ => GenerateSingleDocumentProcessingInfo(Guid.NewGuid())).ToList(); + + var documentCodeDetailInfo = GenerateDocumentCodeDetailInfos().FirstOrDefault(); + List maliciousDocuments = null; + + _mockMemberNotificationInfoService + .Setup(x => x.GetSendableMemberNotificationInfosAsync(It.IsAny(), _apiConfiguration.MaxMemberNotificationAttempts)) + .ReturnsAsync(memberNotificationInfos); + _mockDocumentProcessingInfoService.SetupSequence(x => x.GetListByIdAsync(It.IsAny>())) + .ReturnsAsync(documentProcessingInfos.Skip(0).Take(_apiConfiguration.BatchSkipAmount).ToList()) + .ReturnsAsync(documentProcessingInfos.Skip(_apiConfiguration.BatchSkipAmount).Take(_apiConfiguration.BatchSkipAmount).ToList()); + _mockDocumentTypeRetrieverService.Setup(x => x.GetListOfMaliciousDocuments(It.IsAny())).ReturnsAsync(maliciousDocuments); + + _mockDocumentTypeRetrieverService.Setup(x => x.GetDocumentCodeDetailByBusinessName(It.IsAny())) + .ReturnsAsync(() => documentCodeDetailInfo); + + var result = await _memberDocumentNotifierService.PrepareAndSendNotifications(request); + Assert.NotNull(result); + Assert.IsTrue(result.IsSuccessful); + Assert.IsEmpty(result.Messages); + Assert.Zero(result.FailureCount); + _mockMemberNotificationInfoService.Verify(x => x.GetSendableMemberNotificationInfosAsync(It.IsAny(), It.IsAny()), Times.Once); + _mockMemberNotificationInfoService.Verify(x => x.UpdateRange(It.IsAny>()), Times.Exactly(2)); + _mockDocumentProcessingInfoService.Verify(x => x.GetListByIdAsync(It.IsAny>()), Times.Exactly(2)); + _mockMemberNotificationInfoDeterminingService.Verify(x => x.DetermineDeliveryMethod(It.IsAny()), Times.Never); + _mockDocumentTypeRetrieverService.Verify(x => x.GetListOfMaliciousDocuments(It.IsAny()), Times.Once); + _mockDocumentTypeRetrieverService.Verify(x => x.GetDocumentCodeDetailByBusinessName(It.IsAny()), Times.Exactly(repeatAmount)); + _mockNotificationApiService.Verify(x => x.SendEmailAsync(It.IsAny()), Times.Once); + } + + const string letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvqxyz"; + private static readonly Random Random = new(DateTime.Now.Millisecond); + private static string RandomString => new(Enumerable.Repeat(() => letters[Random.Next(letters.Length)], 10).Select(c => c()).ToArray()); + private static Random IdSeries = new(); + + private static MemberNotificationInfo MemberNotificationFactory + ( + string? emailAddress = null, + string? agreeUserId = null, + int? documentProcessingInfoId = null, + NotificationStatusTypes? notificationStatusType = null + ) + => new() + { + MemberNotificationInfoId = IdSeries.Next(), + AgreeUserId = agreeUserId ?? $"{IdSeries.Next()}{IdSeries.Next()}{IdSeries.Next()}", + EmailAddress = emailAddress ?? $"{RandomString}@{RandomString}.com", + EntityName = Guid.NewGuid().ToString(), + DeliveryMethod = DeliveryMethod.Electronic, + DocumentProcessingInfoId = documentProcessingInfoId ?? IdSeries.Next(), + Attempts = 0, + NotificationStatusType = notificationStatusType ?? NotificationStatusTypes.Pending, + SentTimeStamp = DateTime.UtcNow, + UploadDate = DateTime.UtcNow + }; + + private static List GenerateMemberNotificationInfos() + { + return new List + { + MemberNotificationFactory + ( + agreeUserId: "123", + emailAddress: "test@test.com", + documentProcessingInfoId: 5, + notificationStatusType: NotificationStatusTypes.Pending + ), + MemberNotificationFactory + ( + agreeUserId: "123", + emailAddress: "test@test.com", + documentProcessingInfoId: 6, + notificationStatusType: NotificationStatusTypes.Pending + ), + MemberNotificationFactory + ( + agreeUserId: "789", + emailAddress: "test3@test.com", + documentProcessingInfoId: 7, + notificationStatusType: NotificationStatusTypes.Failure + ) + }; + } + + private static DocumentProcessingInfo DocumentProcessingInfoFactory + ( + int? documentProcessingInfoId = null + ) => new() + { + DocumentId = new Guid(), + DocumentProcessingInfoId = documentProcessingInfoId ?? IdSeries.Next(), + DocumentFileName = Guid.NewGuid().ToString(), + DocumentBusinessName = Guid.NewGuid().ToString() + }; + + private static List GenerateDocumentProcessingInfos() + { + return new List() + { + DocumentProcessingInfoFactory + ( + documentProcessingInfoId: 5 + ), + DocumentProcessingInfoFactory + ( + documentProcessingInfoId: 6 + ), + DocumentProcessingInfoFactory + ( + documentProcessingInfoId: 7 + ) + }; + } + + private static DocumentCodeDetailInfo DocumentCodeDetailInfoFactory + ( + string? documentBusinessName = null + ) => new() + { + DocumentBusinessName = documentBusinessName ?? Guid.NewGuid().ToString(), + DocumentMemberFacingName = Guid.NewGuid().ToString() + }; + + private static List GenerateDocumentCodeDetailInfos() + { + return new List + { + DocumentCodeDetailInfoFactory + ( + documentBusinessName: "5498-SA HSA Contributions (Tax)" + ), + DocumentCodeDetailInfoFactory + ( + documentBusinessName: "1099-MISC" + ), + DocumentCodeDetailInfoFactory + ( + documentBusinessName: "5498 (Retirement Plan Contributions) (Tax)" + ) + }; + } + + public MemberNotificationInfo GenerateSingleMemberNotificationInfo(int id) + { + return new MemberNotificationInfo() + { + MemberNotificationInfoId = id, + AgreeUserId = "123", + EmailAddress = "test@test.com", + EntityName = "Fred", + DeliveryMethod = DeliveryMethod.Electronic, + DocumentProcessingInfoId = 5, + Attempts = 1, + NotificationStatusType = NotificationStatusTypes.Pending, + SentTimeStamp = DateTime.UtcNow, + UploadDate = DateTime.UtcNow + + }; + } + + public DocumentProcessingInfo GenerateSingleDocumentProcessingInfo(Guid id) + { + return new DocumentProcessingInfo() + { + DocumentId = id, + DocumentProcessingInfoId = 5, + DocumentFileName = "FileName1", + DocumentBusinessName = "5498-SA HSA Contributions (Tax)" + + }; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/MemberNotificationCompletionServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/MemberNotificationCompletionServiceTest.cs new file mode 100644 index 0000000..7328c51 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/MemberNotificationCompletionServiceTest.cs @@ -0,0 +1,340 @@ +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.ApiResponse.Models; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.Exceptions; +using Moq; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.IngestionOperationServices; + +public class MemberNotificationCompletionServiceTest +{ + private MemberNotificationCompletionService _memberNotificationCompletionService; + private Mock _mockMemberNotificationInfoService; + private Mock _mockMemberPreferencesApiService; + private Mock _mockProcessingLogService; + private ApiConfiguration _apiConfiguration; + + [SetUp] + public void Setup() + { + _mockMemberNotificationInfoService = new Mock(); + _mockMemberPreferencesApiService = new Mock(); + _mockProcessingLogService = new Mock(); + _apiConfiguration = new ApiConfiguration() { MaxMemberNotificationAttempts = 3, TimeZone = "America/Chicago" }; + _memberNotificationCompletionService = new MemberNotificationCompletionService(_mockMemberNotificationInfoService.Object, + _mockMemberPreferencesApiService.Object, + _mockProcessingLogService.Object, + _apiConfiguration); + } + + [Test] + public void HandleMemberNotificationCompletion_ArgumentNullException_ResponseNull() + { + Response response = null; + Assert.ThrowsAsync(async () => await _memberNotificationCompletionService.HandleMemberNotificationCompletion(response)); + } + + [Test] + public async Task CompleteAndUpdateStatuses_Success() + { + var memberNotificationInfoIds = new List { 1, 2, 3, 4, 5 }; + var success = true; + var logs = new List(); + + var memberNotificationInfos = new List() + { + new() + { + MemberNotificationInfoId = memberNotificationInfoIds[0], + NotificationStatusType = NotificationStatusTypes.Pending, + AgreeUserId = "111", + EmailAddress = "test@test.com" + }, + new() + { + MemberNotificationInfoId = memberNotificationInfoIds[1], + NotificationStatusType = NotificationStatusTypes.Pending, + AgreeUserId = "111", + EmailAddress = "test@test.com" + }, + new() + { + MemberNotificationInfoId = memberNotificationInfoIds[2], + NotificationStatusType = NotificationStatusTypes.Pending, + AgreeUserId = "111", + EmailAddress = "test@test.com" + }, + new() + { + MemberNotificationInfoId = memberNotificationInfoIds[3], + NotificationStatusType = NotificationStatusTypes.Failure, + AgreeUserId = "444", + EmailAddress = "test2@test.com" + }, + new() + { + MemberNotificationInfoId = memberNotificationInfoIds[4], + NotificationStatusType = NotificationStatusTypes.Failure, + AgreeUserId = "444", + EmailAddress = "test2@test.com" + }, + }; + + // Get MemberNotificationInfos + _mockMemberNotificationInfoService.Setup(x => x.GetListByIdAsync(memberNotificationInfoIds)).ReturnsAsync(memberNotificationInfos); + + // Update + _mockMemberNotificationInfoService.SetupSequence(x => x.Update(It.IsAny())).ReturnsAsync(memberNotificationInfos[0]) + .ReturnsAsync(memberNotificationInfos[1]) + .ReturnsAsync(memberNotificationInfos[2]) + .ReturnsAsync(memberNotificationInfos[3]) + .ReturnsAsync(memberNotificationInfos[4]); + + await _memberNotificationCompletionService.CompleteAndUpdateStatuses(memberNotificationInfoIds, success, logs); + + var completed = memberNotificationInfos?.Where(x => x.NotificationStatusType == NotificationStatusTypes.Complete).Count(); + Assert.AreEqual(completed, 5); + _mockMemberNotificationInfoService.Verify(x => x.GetListByIdAsync(It.IsAny>()), Times.Once); + _mockMemberPreferencesApiService.Verify(x => x.EmailStatusSend(It.IsAny(), + It.IsAny(), + success), Times.Exactly(2)); + _mockMemberNotificationInfoService.Verify(x => x.Update(It.IsAny()), Times.Exactly(5)); + _mockProcessingLogService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + } + + [Test] + public async Task CompleteAndUpdateStatuses_Failure() + { + var memberNotificationInfoIds = new List { 1, 2, 3, 4, 5 }; + var success = false; + var logs = new List() { "Failure 1", "Failure 2" }; + + var memberNotificationInfos = new List() + { + new() + { + MemberNotificationInfoId = memberNotificationInfoIds[0], + NotificationStatusType = NotificationStatusTypes.Pending, + AgreeUserId = "111", + EmailAddress = "test@test.com", + Attempts = 2 + }, + new() + { + MemberNotificationInfoId = memberNotificationInfoIds[1], + NotificationStatusType = NotificationStatusTypes.Pending, + AgreeUserId = "111", + EmailAddress = "test@test.com", + Attempts = 3 + }, + new() + { + MemberNotificationInfoId = memberNotificationInfoIds[2], + NotificationStatusType = NotificationStatusTypes.Pending, + AgreeUserId = "111", + EmailAddress = "test@test.com", + Attempts = 2 + }, + new() + { + MemberNotificationInfoId = memberNotificationInfoIds[3], + NotificationStatusType = NotificationStatusTypes.Failure, + AgreeUserId = "444", + EmailAddress = "test2@test.com", + Attempts = 2 + }, + new() + { + MemberNotificationInfoId = memberNotificationInfoIds[4], + NotificationStatusType = NotificationStatusTypes.Failure, + AgreeUserId = "444", + EmailAddress = "test2@test.com", + Attempts = 1 + }, + }; + + // Get MemberNotificationInfos + _mockMemberNotificationInfoService.Setup(x => x.GetListByIdAsync(memberNotificationInfoIds)).ReturnsAsync(memberNotificationInfos); + + // Update + _mockMemberNotificationInfoService.SetupSequence(x => x.Update(It.IsAny())).ReturnsAsync(memberNotificationInfos[0]) + .ReturnsAsync(memberNotificationInfos[1]) + .ReturnsAsync(memberNotificationInfos[2]) + .ReturnsAsync(memberNotificationInfos[3]) + .ReturnsAsync(memberNotificationInfos[4]); + + await _memberNotificationCompletionService.CompleteAndUpdateStatuses(memberNotificationInfoIds, success, logs); + + var undeliverable = memberNotificationInfos?.Where(x => x.NotificationStatusType == NotificationStatusTypes.Undeliverable).Count(); + var failure = memberNotificationInfos?.Where(x => x.NotificationStatusType == NotificationStatusTypes.Failure).Count(); + Assert.AreEqual(undeliverable, 1); + Assert.AreEqual(failure, 4); + _mockMemberNotificationInfoService.Verify(x => x.GetListByIdAsync(It.IsAny>()), Times.Once); + _mockMemberPreferencesApiService.Verify(x => x.EmailStatusSend(It.IsAny(), + It.IsAny(), + success), Times.Once); + _mockMemberNotificationInfoService.Verify(x => x.Update(It.IsAny()), Times.Exactly(5)); + _mockProcessingLogService.Verify(x => x.SaveAsync(It.IsAny()), Times.Exactly(10)); + } + + [Test] + public void CompleteAndUpdateStatuses_Exception() + { + var memberNotificationInfoIds = new List { 1, 2, 3, 4, 5 }; + var success = false; + var logs = new List(); + + _mockMemberNotificationInfoService.Setup(x => x.GetListByIdAsync(It.IsAny>())).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _memberNotificationCompletionService.CompleteAndUpdateStatuses(memberNotificationInfoIds, success, logs)); ; + + _mockMemberNotificationInfoService.Verify(x => x.Update(It.IsAny()), Times.Never); + _mockMemberNotificationInfoService.Verify(x => x.GetListByIdAsync(It.IsAny>()), Times.Once); + _mockMemberPreferencesApiService.Verify(x => x.EmailStatusSend(It.IsAny(), + It.IsAny(), + success), Times.Never); + _mockProcessingLogService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + } + + [Test] + public async Task CompleteAndUpdateStatuses_Exception_EmailNotFound() + { + var memberNotificationInfoIds = new List { 1, 2, 3, 4, 5 }; + var success = false; + var logs = new List(); + + var memberNotificationInfos = new List() + { + new() + { + MemberNotificationInfoId = memberNotificationInfoIds[0], + NotificationStatusType = NotificationStatusTypes.Pending, + AgreeUserId = "111", + EmailAddress = "test@test.com", + Attempts = 2 + }, + new() + { + MemberNotificationInfoId = memberNotificationInfoIds[1], + NotificationStatusType = NotificationStatusTypes.Pending, + AgreeUserId = "111", + EmailAddress = "test@test.com", + Attempts = 3 + }, + new() + { + MemberNotificationInfoId = memberNotificationInfoIds[2], + NotificationStatusType = NotificationStatusTypes.Pending, + AgreeUserId = "111", + EmailAddress = "test@test.com", + Attempts = 2 + }, + new() + { + MemberNotificationInfoId = memberNotificationInfoIds[3], + NotificationStatusType = NotificationStatusTypes.Failure, + AgreeUserId = "444", + EmailAddress = "test2@test.com", + Attempts = 2 + }, + new() + { + MemberNotificationInfoId = memberNotificationInfoIds[4], + NotificationStatusType = NotificationStatusTypes.Failure, + AgreeUserId = "444", + EmailAddress = "test2@test.com", + Attempts = 1 + }, + }; + + _mockMemberNotificationInfoService.Setup(x => x.GetListByIdAsync(It.IsAny>())).ReturnsAsync(memberNotificationInfos); + _mockMemberPreferencesApiService.Setup(x => x.EmailStatusSend(It.IsAny(), It.IsAny(), It.IsAny())) + .Throws(new Exception("StatusCode:NotFound")); + + await _memberNotificationCompletionService.CompleteAndUpdateStatuses(memberNotificationInfoIds, success, logs); + + _mockMemberNotificationInfoService.Verify(x => x.GetListByIdAsync(It.IsAny>()), Times.Once); + _mockMemberNotificationInfoService.Verify(x => x.Update(It.IsAny()), Times.Exactly(memberNotificationInfos.Count)); + _mockMemberPreferencesApiService.Verify(x => x.EmailStatusSend(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockProcessingLogService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + + } + + [Test] + public void CompleteAndUpdateStatuses_Exception_EmailOtherError() + { + var memberNotificationInfoIds = new List { 1, 2, 3, 4, 5 }; + var success = false; + var logs = new List(); + + var memberNotificationInfos = new List() + { + new() + { + MemberNotificationInfoId = memberNotificationInfoIds[0], + NotificationStatusType = NotificationStatusTypes.Pending, + AgreeUserId = "111", + EmailAddress = "test@test.com", + Attempts = 2 + }, + new() + { + MemberNotificationInfoId = memberNotificationInfoIds[1], + NotificationStatusType = NotificationStatusTypes.Pending, + AgreeUserId = "111", + EmailAddress = "test@test.com", + Attempts = 3 + }, + new() + { + MemberNotificationInfoId = memberNotificationInfoIds[2], + NotificationStatusType = NotificationStatusTypes.Pending, + AgreeUserId = "111", + EmailAddress = "test@test.com", + Attempts = 2 + }, + new() + { + MemberNotificationInfoId = memberNotificationInfoIds[3], + NotificationStatusType = NotificationStatusTypes.Failure, + AgreeUserId = "444", + EmailAddress = "test2@test.com", + Attempts = 2 + }, + new() + { + MemberNotificationInfoId = memberNotificationInfoIds[4], + NotificationStatusType = NotificationStatusTypes.Failure, + AgreeUserId = "444", + EmailAddress = "test2@test.com", + Attempts = 1 + }, + }; + var pendingCount = memberNotificationInfos.Count(x => x.NotificationStatusType == NotificationStatusTypes.Pending); + + _mockMemberNotificationInfoService.Setup(x => x.GetListByIdAsync(It.IsAny>())).ReturnsAsync(memberNotificationInfos); + _mockMemberPreferencesApiService.Setup(x => x.EmailStatusSend(It.IsAny(), It.IsAny(), It.IsAny())) + .Throws(new Exception("Unexpected Error")); + + Assert.ThrowsAsync(async () => await _memberNotificationCompletionService.CompleteAndUpdateStatuses(memberNotificationInfoIds, success, logs)); + + _mockMemberNotificationInfoService.Verify(x => x.GetListByIdAsync(It.IsAny>()), Times.Once); + _mockMemberNotificationInfoService.Verify(x => x.Update(It.IsAny()), Times.Exactly(pendingCount)); + _mockMemberPreferencesApiService.Verify(x => x.EmailStatusSend(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockProcessingLogService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/OsgPreprocessorServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/OsgPreprocessorServiceTest.cs new file mode 100644 index 0000000..9353dc5 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/OsgPreprocessorServiceTest.cs @@ -0,0 +1,773 @@ +using System; +using System.IO; +using System.Collections.Generic; +using System.Threading.Tasks; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.Library.Internal.FileOperationsModels.Models; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.IngestionOperationServices; + +public class OsgPreprocessorServiceTest +{ + private OsgPreprocessorService _osgPreprocessorService; + private Mock _mockFileOperationsApiService; + private Mock _mockOsgPreprocessorInfoService; + private ApiConfiguration _apiConfiguration; + + [SetUp] + public void Setup() + { + _mockFileOperationsApiService = new Mock(); + _mockOsgPreprocessorInfoService = new Mock(); + _apiConfiguration = new ApiConfiguration() { TimeZone = "America/Chicago" }; + _osgPreprocessorService = new OsgPreprocessorService(_mockFileOperationsApiService.Object, + _mockOsgPreprocessorInfoService.Object, + _apiConfiguration); + } + + public OsgPreprocessorRequest BuildTestOsgPreprocessorRequest() + { + return new OsgPreprocessorRequest() + { + ArchiveStartDate = new DateTime(2020, 10, 1), + SourceBasePath = @"\TEST\SourceBasePath", + WorkingBasePath = Path.GetFullPath(@"..\..\..\TestContent"), + OutputBasePath = @"\TEST\OutputBasePath", + IncompleteOutputBasePath = @"\TEST\IncompleteOutputBasePath" + }; + } + + [Test] + public async Task HandleOsgPreprocessing_Success() + { + var request = BuildTestOsgPreprocessorRequest(); + var allZipsInDirectory = new List() { "Test_OSG_Index_File.ZIP" }; + var pdfList = new List() { "testPdf.1.PDF", "testPdf.2.PDF" }; + var indexFiles = new List() { "Test_OSG_Index_File.XML" }; + var requestResponse = new RequestResponse() { IsSuccessful = true }; + + _mockFileOperationsApiService.SetupSequence(x => x.BuildDynamicFileList(It.IsAny())).ReturnsAsync(allZipsInDirectory) + .ReturnsAsync(indexFiles) + .ReturnsAsync(pdfList); + _mockFileOperationsApiService.SetupSequence(x => x.DirectMoveFile(request.SourceBasePath, allZipsInDirectory[0], request.WorkingBasePath)).ReturnsAsync(requestResponse); + _mockFileOperationsApiService.SetupSequence(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(requestResponse) + .ReturnsAsync(requestResponse); + _mockFileOperationsApiService.SetupSequence(x => x.DirectDeleteFile(It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse) + .ReturnsAsync(requestResponse); + _mockFileOperationsApiService.SetupSequence(x => x.ValidateFileExists(It.IsAny())).ReturnsAsync(false) + .ReturnsAsync(false); + _mockFileOperationsApiService.SetupSequence(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse) + .ReturnsAsync(requestResponse) + .ReturnsAsync(requestResponse); + _mockFileOperationsApiService.SetupSequence(x => x.DirectMoveFile(It.Is(folderPath => folderPath.Contains(request.WorkingBasePath)), + It.IsAny(), + It.Is(targetDirectory => targetDirectory.Contains(request.WorkingBasePath)))).ReturnsAsync(requestResponse) + .ReturnsAsync(requestResponse) + .ReturnsAsync(requestResponse); + _mockFileOperationsApiService.SetupSequence(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse) + .ReturnsAsync(requestResponse) + .ReturnsAsync(requestResponse); + _mockFileOperationsApiService.Setup(x => x.DirectZipDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse); + _mockFileOperationsApiService.Setup(x => x.DirectMoveFile(It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(requestResponse); + _mockFileOperationsApiService.Setup(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse); + + await _osgPreprocessorService.HandleOsgPreprocessing(request); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Exactly(3)); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(4)); + _mockFileOperationsApiService.Verify(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteFile(It.IsAny(), It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Exactly(3)); + _mockFileOperationsApiService.Verify(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(3)); + _mockFileOperationsApiService.Verify(x => x.DirectZipDirectory(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task HandleOsgPreprocessing_Failure_IndexFileDoesNotExist() + { + var request = BuildTestOsgPreprocessorRequest(); + var allZipsInDirectory = new List() { "Test_OSG_Index_File.ZIP" }; + var indexFiles = new List() { }; + var requestResponse = new RequestResponse() { IsSuccessful = true }; + + _mockFileOperationsApiService.SetupSequence(x => x.BuildDynamicFileList(It.IsAny())).ReturnsAsync(allZipsInDirectory) + .ReturnsAsync(indexFiles); + _mockFileOperationsApiService.SetupSequence(x => x.DirectMoveFile(request.SourceBasePath, allZipsInDirectory[0], request.WorkingBasePath)).ReturnsAsync(requestResponse); + _mockFileOperationsApiService.Setup(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(requestResponse); + _mockFileOperationsApiService.Setup(x => x.DirectDeleteFile(It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse); + _mockFileOperationsApiService.Setup(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse); + _mockFileOperationsApiService.Setup(x => x.DirectZipDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse); + _mockFileOperationsApiService.Setup(x => x.DirectMoveFile(It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(requestResponse); + _mockFileOperationsApiService.Setup(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse); + + + await _osgPreprocessorService.HandleOsgPreprocessing(request); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteFile(It.IsAny(), It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectZipDirectory(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + } + + [Test] + public async Task HandleOsgPreprocessing_Failure_ParseReturnedNoRecords() + { + var request = BuildTestOsgPreprocessorRequest(); + var allZipsInDirectory = new List() { "Test_OSG_Index_File.ZIP" }; + var indexFiles = new List() { "Test_OSG_Index_File_1099_MISC.XML" }; + var requestResponse = new RequestResponse() { IsSuccessful = true }; + + _mockFileOperationsApiService.SetupSequence(x => x.BuildDynamicFileList(It.IsAny())).ReturnsAsync(allZipsInDirectory) + .ReturnsAsync(indexFiles); + _mockFileOperationsApiService.SetupSequence(x => x.DirectMoveFile(request.SourceBasePath, allZipsInDirectory[0], request.WorkingBasePath)).ReturnsAsync(requestResponse); + _mockFileOperationsApiService.SetupSequence(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(requestResponse); + _mockFileOperationsApiService.SetupSequence(x => x.DirectDeleteFile(It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse) + .ReturnsAsync(requestResponse); + _mockFileOperationsApiService.SetupSequence(x => x.DirectMoveFile(It.Is(folderPath => folderPath.Contains(request.WorkingBasePath)), + It.IsAny(), + It.Is(targetDirectory => targetDirectory.Contains(request.WorkingBasePath)))).ReturnsAsync(requestResponse) + .ReturnsAsync(requestResponse) + .ReturnsAsync(requestResponse); + _mockFileOperationsApiService.Setup(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse); + _mockFileOperationsApiService.Setup(x => x.DirectZipDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse); + _mockFileOperationsApiService.Setup(x => x.DirectMoveFile(It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(requestResponse); + _mockFileOperationsApiService.Setup(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse); + + await _osgPreprocessorService.HandleOsgPreprocessing(request); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(1)); + _mockFileOperationsApiService.Verify(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteFile(It.IsAny(), It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectZipDirectory(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + } + + + [Test] + public async Task HandleOsgPreprocessing_Failure_NoMatchingPdfsFound() + { + var request = BuildTestOsgPreprocessorRequest(); + var allZipsInDirectory = new List() { "Test_OSG_Index_File.ZIP" }; + var pdfList = new List() { "testPdf.3.PDF", "testPdf.4.PDF" }; + var indexFiles = new List() { "Test_OSG_Index_File.XML" }; + var requestResponse = new RequestResponse() { IsSuccessful = true }; + + _mockFileOperationsApiService.SetupSequence(x => x.BuildDynamicFileList(It.IsAny())).ReturnsAsync(allZipsInDirectory) + .ReturnsAsync(indexFiles) + .ReturnsAsync(pdfList); + _mockFileOperationsApiService.Setup(x => x.DirectMoveFile(request.SourceBasePath, allZipsInDirectory[0], request.WorkingBasePath)).ReturnsAsync(requestResponse); + _mockFileOperationsApiService.Setup(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(requestResponse); + _mockFileOperationsApiService.Setup(x => x.DirectDeleteFile(It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse); + _mockFileOperationsApiService.SetupSequence(x => x.ValidateFileExists(It.IsAny())).ReturnsAsync(false) + .ReturnsAsync(false); + _mockFileOperationsApiService.Setup(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse); + _mockFileOperationsApiService.Setup(x => x.DirectZipDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse); + _mockFileOperationsApiService.Setup(x => x.DirectMoveFile(It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(requestResponse); + _mockFileOperationsApiService.Setup(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse); + + + await _osgPreprocessorService.HandleOsgPreprocessing(request); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Exactly(3)); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteFile(It.IsAny(), It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectZipDirectory(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public void HandleOsgPreprocessing_Failure_FailedToDeleteIndexFile() + { + var request = BuildTestOsgPreprocessorRequest(); + var allZipsInDirectory = new List() { "Test_OSG_Index_File.ZIP" }; + var responseSuccess = new RequestResponse() { IsSuccessful = true }; + var responseFailure = new RequestResponse() { IsSuccessful = false }; + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFileList(It.IsAny())).ReturnsAsync(allZipsInDirectory); + _mockFileOperationsApiService.Setup(x => x.DirectMoveFile(request.SourceBasePath, allZipsInDirectory[0], request.WorkingBasePath)).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.Setup(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.Setup(x => x.DirectDeleteFile(It.IsAny(), It.IsAny())).ReturnsAsync(responseFailure); + + Assert.ThrowsAsync(async () => await _osgPreprocessorService.HandleOsgPreprocessing(request)); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteFile(It.IsAny(), It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectZipDirectory(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + + [Test] + public void HandleOsgPreprocessing_FailureToWriteInfoLog() + { + var request = BuildTestOsgPreprocessorRequest(); + var allZipsInDirectory = new List() { "Test_OSG_Index_File.ZIP" }; + var pdfList = new List() { "testPdf.1.PDF", "testPdf.2.PDF" }; + var indexFiles = new List() { "Test_OSG_Index_File.XML" }; + var responseSuccess = new RequestResponse() { IsSuccessful = true }; + var responseFailure = new RequestResponse() { IsSuccessful = false }; + + _mockFileOperationsApiService.SetupSequence(x => x.BuildDynamicFileList(It.IsAny())).ReturnsAsync(allZipsInDirectory) + .ReturnsAsync(indexFiles) + .ReturnsAsync(pdfList); + _mockFileOperationsApiService.SetupSequence(x => x.DirectMoveFile(request.SourceBasePath, allZipsInDirectory[0], request.WorkingBasePath)).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectDeleteFile(It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.ValidateFileExists(It.IsAny())).ReturnsAsync(false) + .ReturnsAsync(false); + _mockFileOperationsApiService.SetupSequence(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectMoveFile(It.Is(folderPath => folderPath.Contains(request.WorkingBasePath)), + It.IsAny(), + It.Is(targetDirectory => targetDirectory.Contains(request.WorkingBasePath)))).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess) + .ReturnsAsync(responseFailure); + + Assert.ThrowsAsync(async () => await _osgPreprocessorService.HandleOsgPreprocessing(request)); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Exactly(3)); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(3)); + _mockFileOperationsApiService.Verify(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteFile(It.IsAny(), It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(3)); + _mockFileOperationsApiService.Verify(x => x.DirectZipDirectory(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task HandleOsgPreprocessing_WriteParsedRecordGroup_Failure_ParsedFileExists() + { + var request = BuildTestOsgPreprocessorRequest(); + var allZipsInDirectory = new List() { "Test_OSG_Index_File.ZIP" }; + var pdfList = new List() { "testPdf.1.PDF", "testPdf.2.PDF" }; + var indexFiles = new List() { "Test_OSG_Index_File.XML" }; + var responseSuccess = new RequestResponse() { IsSuccessful = true }; + + _mockFileOperationsApiService.SetupSequence(x => x.BuildDynamicFileList(It.IsAny())).ReturnsAsync(allZipsInDirectory) + .ReturnsAsync(indexFiles) + .ReturnsAsync(pdfList); + _mockFileOperationsApiService.SetupSequence(x => x.DirectMoveFile(request.SourceBasePath, allZipsInDirectory[0], request.WorkingBasePath)).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.Setup(x => x.DirectDeleteFile(It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.ValidateFileExists(It.IsAny())).ReturnsAsync(true) + .ReturnsAsync(false); + _mockFileOperationsApiService.SetupSequence(x => x.DirectMoveFile(It.Is(folderPath => folderPath.Contains(request.WorkingBasePath)), + It.IsAny(), + It.Is(targetDirectory => targetDirectory.Contains(request.WorkingBasePath)))).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.Setup(x => x.DirectZipDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.Setup(x => x.DirectMoveFile(It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.Setup(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess); + + await _osgPreprocessorService.HandleOsgPreprocessing(request); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Exactly(3)); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteFile(It.IsAny(), It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectZipDirectory(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task HandleOsgPreprocessing_WriteParsedRecordGroup_Failure_FailedToCreateDirectory() + { + var request = BuildTestOsgPreprocessorRequest(); + var allZipsInDirectory = new List() { "Test_OSG_Index_File.ZIP" }; + var pdfList = new List() { "testPdf.1.PDF", "testPdf.2.PDF" }; + var indexFiles = new List() { "Test_OSG_Index_File.XML" }; + var responseSuccess = new RequestResponse() { IsSuccessful = true }; + var responseFailure = new RequestResponse() { IsSuccessful = false }; + + _mockFileOperationsApiService.SetupSequence(x => x.BuildDynamicFileList(It.IsAny())).ReturnsAsync(allZipsInDirectory) + .ReturnsAsync(indexFiles) + .ReturnsAsync(pdfList); + _mockFileOperationsApiService.SetupSequence(x => x.DirectMoveFile(request.SourceBasePath, allZipsInDirectory[0], request.WorkingBasePath)).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectDeleteFile(It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.ValidateFileExists(It.IsAny())).ReturnsAsync(false) + .ReturnsAsync(false); + _mockFileOperationsApiService.SetupSequence(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny())).ReturnsAsync(responseFailure) + .ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectMoveFile(It.Is(folderPath => folderPath.Contains(request.WorkingBasePath)), + It.IsAny(), + It.Is(targetDirectory => targetDirectory.Contains(request.WorkingBasePath)))).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.Setup(x => x.DirectZipDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.Setup(x => x.DirectMoveFile(It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.Setup(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess); + + + await _osgPreprocessorService.HandleOsgPreprocessing(request); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Exactly(3)); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(3)); + _mockFileOperationsApiService.Verify(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteFile(It.IsAny(), It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectZipDirectory(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task HandleOsgPreprocessing_WriteParsedRecordGroup_Failure_FailedToMovePdf() + { + var request = BuildTestOsgPreprocessorRequest(); + var allZipsInDirectory = new List() { "Test_OSG_Index_File.ZIP" }; + var pdfList = new List() { "testPdf.1.PDF", "testPdf.2.PDF" }; + var indexFiles = new List() { "Test_OSG_Index_File.XML" }; + var responseSuccess = new RequestResponse() { IsSuccessful = true }; + var responseFailure = new RequestResponse() { IsSuccessful = false }; + + _mockFileOperationsApiService.SetupSequence(x => x.BuildDynamicFileList(It.IsAny())).ReturnsAsync(allZipsInDirectory) + .ReturnsAsync(indexFiles) + .ReturnsAsync(pdfList); + _mockFileOperationsApiService.SetupSequence(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectDeleteFile(It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.ValidateFileExists(It.IsAny())).ReturnsAsync(false) + .ReturnsAsync(false); + _mockFileOperationsApiService.SetupSequence(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectMoveFile(It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseFailure) + .ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.Setup(x => x.DirectZipDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.Setup(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess); + + await _osgPreprocessorService.HandleOsgPreprocessing(request); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Exactly(3)); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(4)); + _mockFileOperationsApiService.Verify(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteFile(It.IsAny(), It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectZipDirectory(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task HandleOsgPreprocessing_WriteParsedRecordGroup_Failure_FailedToWriteIndexFile() + { + var request = BuildTestOsgPreprocessorRequest(); + var allZipsInDirectory = new List() { "Test_OSG_Index_File.ZIP" }; + var pdfList = new List() { "testPdf.1.PDF", "testPdf.2.PDF" }; + var indexFiles = new List() { "Test_OSG_Index_File.XML" }; + var responseSuccess = new RequestResponse() { IsSuccessful = true }; + var responseFailure = new RequestResponse() { IsSuccessful = false }; + + _mockFileOperationsApiService.SetupSequence(x => x.BuildDynamicFileList(It.IsAny())).ReturnsAsync(allZipsInDirectory) + .ReturnsAsync(indexFiles) + .ReturnsAsync(pdfList); + _mockFileOperationsApiService.SetupSequence(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectDeleteFile(It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.ValidateFileExists(It.IsAny())).ReturnsAsync(false) + .ReturnsAsync(false); + _mockFileOperationsApiService.SetupSequence(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectMoveFile(It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseFailure) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.Setup(x => x.DirectZipDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.Setup(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess); + + await _osgPreprocessorService.HandleOsgPreprocessing(request); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Exactly(3)); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(4)); + _mockFileOperationsApiService.Verify(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteFile(It.IsAny(), It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(3)); + _mockFileOperationsApiService.Verify(x => x.DirectZipDirectory(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public void HandleOsgPreprocessing_PrepareZipFile_Failure_FailedToMoveZipFile() + { + var request = BuildTestOsgPreprocessorRequest(); + var allZipsInDirectory = new List() { "Test_OSG_Index_File.ZIP" }; + var pdfList = new List() { "testPdf.1.PDF", "testPdf.2.PDF" }; + var indexFiles = new List() { "Test_OSG_Index_File.XML" }; + var responseSuccess = new RequestResponse() { IsSuccessful = true }; + var responseFailure = new RequestResponse() { IsSuccessful = false }; + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFileList(It.IsAny())).ReturnsAsync(allZipsInDirectory); + _mockFileOperationsApiService.Setup(x => x.DirectMoveFile(It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(responseFailure); + + Assert.ThrowsAsync(async () => await _osgPreprocessorService.HandleOsgPreprocessing(request)); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteFile(It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectZipDirectory(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public void HandleOsgPreprocessing_PrepareZipFile_Failure_FailedToUnzipZipFile() + { + var request = BuildTestOsgPreprocessorRequest(); + var allZipsInDirectory = new List() { "Test_OSG_Index_File.ZIP" }; + var pdfList = new List() { "testPdf.1.PDF", "testPdf.2.PDF" }; + var indexFiles = new List() { "Test_OSG_Index_File.XML" }; + var responseSuccess = new RequestResponse() { IsSuccessful = true }; + var responseFailure = new RequestResponse() { IsSuccessful = false }; + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFileList(It.IsAny())).ReturnsAsync(allZipsInDirectory); + _mockFileOperationsApiService.Setup(x => x.DirectMoveFile(It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.Setup(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(responseFailure); + + Assert.ThrowsAsync(async () => await _osgPreprocessorService.HandleOsgPreprocessing(request)); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteFile(It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectZipDirectory(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + + [Test] + public void HandleOsgPreprocessing_PrepareZipFile_Failure_FailedToDeleteZipFile() + { + var request = BuildTestOsgPreprocessorRequest(); + var allZipsInDirectory = new List() { "Test_OSG_Index_File.ZIP" }; + var pdfList = new List() { "testPdf.1.PDF", "testPdf.2.PDF" }; + var indexFiles = new List() { "Test_OSG_Index_File.XML" }; + var responseSuccess = new RequestResponse() { IsSuccessful = true }; + var responseFailure = new RequestResponse() { IsSuccessful = false }; + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFileList(It.IsAny())).ReturnsAsync(allZipsInDirectory); + _mockFileOperationsApiService.Setup(x => x.DirectMoveFile(It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.Setup(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectDeleteFile(It.IsAny(), It.IsAny())).ReturnsAsync(responseFailure); + + Assert.ThrowsAsync(async () => await _osgPreprocessorService.HandleOsgPreprocessing(request)); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteFile(It.IsAny(), It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectZipDirectory(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public void HandleOsgPreprocessing_ZipAndMoveResults_Failure_FailedToZipFiles() + { + var request = BuildTestOsgPreprocessorRequest(); + var allZipsInDirectory = new List() { "Test_OSG_Index_File.ZIP" }; + var pdfList = new List() { "testPdf.1.PDF", "testPdf.2.PDF" }; + var indexFiles = new List() { "Test_OSG_Index_File.XML" }; + var responseSuccess = new RequestResponse() { IsSuccessful = true }; + var responseFailure = new RequestResponse() { IsSuccessful = false }; + + _mockFileOperationsApiService.SetupSequence(x => x.BuildDynamicFileList(It.IsAny())).ReturnsAsync(allZipsInDirectory) + .ReturnsAsync(indexFiles) + .ReturnsAsync(pdfList); + _mockFileOperationsApiService.SetupSequence(x => x.DirectMoveFile(request.SourceBasePath, allZipsInDirectory[0], request.WorkingBasePath)).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectDeleteFile(It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.ValidateFileExists(It.IsAny())).ReturnsAsync(false) + .ReturnsAsync(false); + _mockFileOperationsApiService.SetupSequence(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectMoveFile(It.Is(folderPath => folderPath.Contains(request.WorkingBasePath)), + It.IsAny(), + It.Is(targetDirectory => targetDirectory.Contains(request.WorkingBasePath)))).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.Setup(x => x.DirectZipDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(responseFailure); + _mockFileOperationsApiService.Setup(x => x.DirectMoveFile(It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(responseSuccess); + + Assert.ThrowsAsync(async () => await _osgPreprocessorService.HandleOsgPreprocessing(request)); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Exactly(3)); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(3)); + _mockFileOperationsApiService.Verify(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Exactly(1)); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteFile(It.IsAny(), It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Exactly(3)); + _mockFileOperationsApiService.Verify(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(3)); + _mockFileOperationsApiService.Verify(x => x.DirectZipDirectory(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public void HandleOsgPreprocessing_Failure_FailedToDeleteDirectory() + { + var request = BuildTestOsgPreprocessorRequest(); + var allZipsInDirectory = new List() { "Test_OSG_Index_File.ZIP" }; + var pdfList = new List() { "testPdf.1.PDF", "testPdf.2.PDF" }; + var indexFiles = new List() { "Test_OSG_Index_File.XML" }; + var responseSuccess = new RequestResponse() { IsSuccessful = true }; + var responseFailure = new RequestResponse() { IsSuccessful = false }; + + _mockFileOperationsApiService.SetupSequence(x => x.BuildDynamicFileList(It.IsAny())).ReturnsAsync(allZipsInDirectory) + .ReturnsAsync(indexFiles) + .ReturnsAsync(pdfList); + _mockFileOperationsApiService.SetupSequence(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectDeleteFile(It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.ValidateFileExists(It.IsAny())).ReturnsAsync(false) + .ReturnsAsync(false); + _mockFileOperationsApiService.SetupSequence(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectMoveFile(It.IsAny(), + It.IsAny(), + It.IsAny())).ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess) + .ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.Setup(x => x.DirectZipDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(responseSuccess); + _mockFileOperationsApiService.SetupSequence(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(responseFailure) + .ReturnsAsync(responseFailure); + + Assert.ThrowsAsync(async () => await _osgPreprocessorService.HandleOsgPreprocessing(request)); + + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Exactly(3)); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(4)); + _mockFileOperationsApiService.Verify(x => x.DirectUnzipFile(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteFile(It.IsAny(), It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Exactly(3)); + _mockFileOperationsApiService.Verify(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(3)); + _mockFileOperationsApiService.Verify(x => x.DirectZipDirectory(It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.DirectDeleteDirectory(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public void HandleOsgPreprocessing_ArgumentNullException_RequestNull() + { + OsgPreprocessorRequest request = null; + Assert.ThrowsAsync(async () => await _osgPreprocessorService.HandleOsgPreprocessing(request)); + _mockFileOperationsApiService.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.GetFileContent(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectCreateDirectory(It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.DirectWriteFile(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/PdfPartitionerCompletionServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/PdfPartitionerCompletionServiceTest.cs new file mode 100644 index 0000000..3a2aafb --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/PdfPartitionerCompletionServiceTest.cs @@ -0,0 +1,198 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.LcuMassTransitModels; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.API.Internal.DocumentIngestor.Services.PdfParserServices; +using LCU.Library.Internal.ApiResponse.Models; +using Newtonsoft.Json; +using LCU.Library.Internal.FileOperationsModels.Models.NameSettings; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.IngestionOperationServices; + +public class PdfPartitionerCompletionServiceTest +{ + private PdfPartitionerCompletionService _pdfPartitionerCompletionService; + private Mock _mockPdfPartitionerRunInfoService; + private Mock _mockPdfPartitionerLogService; + + [SetUp] + public void Setup() + { + _mockPdfPartitionerRunInfoService = new Mock(); + _mockPdfPartitionerLogService = new Mock(); + _pdfPartitionerCompletionService = new PdfPartitionerCompletionService(_mockPdfPartitionerRunInfoService.Object, + _mockPdfPartitionerLogService.Object); + } + + [Test] + public void HandlePdfPartitionerCompletion_ArgumentNullException_ResponseNull() + { + Response response = null; + Assert.ThrowsAsync(async () => await _pdfPartitionerCompletionService.HandlePdfPartitionerCompletion(response)); + _mockPdfPartitionerRunInfoService.Verify(x => x.IncreaseCountsAndUpdate(It.IsAny(), It.IsAny()), Times.Never); + _mockPdfPartitionerLogService.Verify(x => x.SaveListAsync(It.IsAny(), It.IsAny>()), Times.Never); + _mockPdfPartitionerLogService.Verify(x => x.GetByPdfPartitionerRunInfoIdAsync(It.IsAny()), Times.Never); + } + + [Test] + public void HandlePdfPartitionerCompletion_ArgumentNullException_PdfPartitionerResultNull() + { + PdfPartitionerResult result = null; + var response = new Response + { + ResponsePayload = JsonConvert.SerializeObject(result) + }; + Assert.ThrowsAsync(async () => await _pdfPartitionerCompletionService.HandlePdfPartitionerCompletion(response)); + _mockPdfPartitionerRunInfoService.Verify(x => x.IncreaseCountsAndUpdate(It.IsAny(), It.IsAny()), Times.Never); + _mockPdfPartitionerLogService.Verify(x => x.SaveListAsync(It.IsAny(), It.IsAny>()), Times.Never); + _mockPdfPartitionerLogService.Verify(x => x.GetByPdfPartitionerRunInfoIdAsync(It.IsAny()), Times.Never); + } + + [Test] + public void HandlePdfPartitionerCompletion_ServiceException_IncreaseCountsAndUpdate_ThrowException() + { + var pdfPartitionerRequest = new PdfPartitionerRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + PdfParserType = PdfParserTypes.FosLoanStatement, + DynamicIndexFileName = "TestDynamicIndexFileName.txt", + DynamicPdfName = "TestDynamicPdfname", + DynamicPdfSettings = new DynamicNameSetting() + }; + var result = new PdfPartitionerResult(Guid.NewGuid(), pdfPartitionerRequest); + var response = new Response + { + ResponsePayload = JsonConvert.SerializeObject(result) + }; + + _mockPdfPartitionerRunInfoService.Setup(x => x.IncreaseCountsAndUpdate(It.IsAny(), It.IsAny())).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _pdfPartitionerCompletionService.HandlePdfPartitionerCompletion(response)); + _mockPdfPartitionerRunInfoService.Verify(x => x.IncreaseCountsAndUpdate(It.IsAny(), It.IsAny()), Times.Once); + _mockPdfPartitionerLogService.Verify(x => x.SaveListAsync(It.IsAny(), It.IsAny>()), Times.Never); + _mockPdfPartitionerLogService.Verify(x => x.GetByPdfPartitionerRunInfoIdAsync(It.IsAny()), Times.Never); + } + + [Test] + public void HandlePdfPartitionerCompletion_ServiceException_PdfPartitionerLogService_SaveListAsync_ThrowException() + { + var pdfPartitionerRequest = new PdfPartitionerRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + PdfParserType = PdfParserTypes.FosLoanStatement, + DynamicIndexFileName = "TestDynamicIndexFileName.txt", + DynamicPdfName = "TestDynamicPdfname", + DynamicPdfSettings = new DynamicNameSetting() + }; + var result = new PdfPartitionerResult(Guid.NewGuid(), pdfPartitionerRequest); + var response = new Response + { + ResponsePayload = JsonConvert.SerializeObject(result) + }; + + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo + { + PdfPartitionerRunInfoId = result.PdfPartitionerRunInfoId, + IndexTotal = 3, + SuccessCount = 1, + FailureCount = 1 + }; + _mockPdfPartitionerRunInfoService.Setup(x => x.IncreaseCountsAndUpdate(It.IsAny(), It.IsAny())).ReturnsAsync(pdfPartitionerRunInfo); + + _mockPdfPartitionerLogService.Setup(x => x.SaveListAsync(It.IsAny(), It.IsAny>())).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _pdfPartitionerCompletionService.HandlePdfPartitionerCompletion(response)); + _mockPdfPartitionerRunInfoService.Verify(x => x.IncreaseCountsAndUpdate(It.IsAny(), It.IsAny()), Times.Once); + _mockPdfPartitionerLogService.Verify(x => x.SaveListAsync(It.IsAny(), It.IsAny>()), Times.Once); + _mockPdfPartitionerLogService.Verify(x => x.GetByPdfPartitionerRunInfoIdAsync(It.IsAny()), Times.Never); + } + + [Test] + public void HandlePdfPartitionerCompletion_ServiceException_PdfPartitionerLogService_GetByPdfPartitionerRunInfoIdAsync_ThrowException() + { + var pdfPartitionerRequest = new PdfPartitionerRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + PdfParserType = PdfParserTypes.FosLoanStatement, + DynamicIndexFileName = "TestDynamicIndexFileName.txt", + DynamicPdfName = "TestDynamicPdfname", + DynamicPdfSettings = new DynamicNameSetting() + }; + var result = new PdfPartitionerResult(Guid.NewGuid(), pdfPartitionerRequest); + var response = new Response + { + ResponsePayload = JsonConvert.SerializeObject(result) + }; + + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo + { + PdfPartitionerRunInfoId = result.PdfPartitionerRunInfoId, + IndexTotal = 3, + SuccessCount = 2, + FailureCount = 1 + }; + _mockPdfPartitionerRunInfoService.Setup(x => x.IncreaseCountsAndUpdate(It.IsAny(), It.IsAny())).ReturnsAsync(pdfPartitionerRunInfo); + + _mockPdfPartitionerLogService.Setup(x => x.SaveListAsync(It.IsAny(), It.IsAny>())); + _mockPdfPartitionerLogService.Setup(x => x.GetByPdfPartitionerRunInfoIdAsync(It.IsAny())).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _pdfPartitionerCompletionService.HandlePdfPartitionerCompletion(response)); + _mockPdfPartitionerRunInfoService.Verify(x => x.IncreaseCountsAndUpdate(It.IsAny(), It.IsAny()), Times.Once); + _mockPdfPartitionerLogService.Verify(x => x.SaveListAsync(It.IsAny(), It.IsAny>()), Times.Once); + _mockPdfPartitionerLogService.Verify(x => x.GetByPdfPartitionerRunInfoIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task HandlePdfPartitionerCompletion_Success() + { + var pdfPartitionerRequest = new PdfPartitionerRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + PdfParserType = PdfParserTypes.FosLoanStatement, + DynamicIndexFileName = "TestDynamicIndexFileName.txt", + DynamicPdfName = "TestDynamicPdfname", + DynamicPdfSettings = new DynamicNameSetting() + }; + var result = new PdfPartitionerResult(Guid.NewGuid(), pdfPartitionerRequest); + result.FailedToQueueToParse = false; + var response = new Response + { + ResponsePayload = JsonConvert.SerializeObject(result), + ResponseStack = new List + { + "Test ResponseStack" + } + }; + + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo + { + PdfPartitionerRunInfoId = result.PdfPartitionerRunInfoId, + IndexTotal = 3, + SuccessCount = 2, + FailureCount = 1 + }; + _mockPdfPartitionerRunInfoService.Setup(x => x.IncreaseCountsAndUpdate(It.IsAny(), It.IsAny())).ReturnsAsync(pdfPartitionerRunInfo); + + _mockPdfPartitionerLogService.Setup(x => x.SaveListAsync(It.IsAny(), It.IsAny>())); + + await _pdfPartitionerCompletionService.HandlePdfPartitionerCompletion(response); + _mockPdfPartitionerRunInfoService.Verify(x => x.IncreaseCountsAndUpdate(It.IsAny(), It.IsAny()), Times.Once); + _mockPdfPartitionerLogService.Verify(x => x.SaveListAsync(It.IsAny(), It.IsAny>()), Times.Once); + _mockPdfPartitionerLogService.Verify(x => x.GetByPdfPartitionerRunInfoIdAsync(It.IsAny()), Times.Once); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/PdfPartitionerServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/PdfPartitionerServiceTest.cs new file mode 100644 index 0000000..a04d3bd --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/PdfPartitionerServiceTest.cs @@ -0,0 +1,579 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.LcuMassTransitModels; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.API.Internal.DocumentIngestor.Services.PdfParserServices; +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.Library.Internal.FileOperationsModels.Models.NameSettings; +using LCU.Library.Internal.LCUServiceFactory.Services; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.IngestionOperationServices; + +public class PdfPartitionerServiceTest +{ + private PdfPartitionerService _pdfPartitionerService; + private ConnectionConfiguration _connectionConfiguration; + private Mock _mockPdfPartitionerRunInfoService; + private Mock _mockFileOperationsApiService; + private Mock _mockQueuePdfPartitionerCompletionService; + private Mock> _mockLcuServiceFactory; + + [SetUp] + public void Setup() + { + _connectionConfiguration = new ConnectionConfiguration + { + HostUrl = "test.com", + UserName = "testUserName", + Password = "testpassword" + }; + var receiveEndpointConfigurations = new ReceiveEndpointConfigurations + { + PdfPartitionerCompletionEndpoint = new ReceiveEndpointConfiguration + { + ReceiveEndpoint = "testCompletionReceiveEndpoint", + ReceiveEndpointType = "exchange" + } + }; + _mockPdfPartitionerRunInfoService = new Mock(); + _mockFileOperationsApiService = new Mock(); + _mockQueuePdfPartitionerCompletionService = new Mock(); + _mockLcuServiceFactory = new Mock>(); + _pdfPartitionerService = new PdfPartitionerService(_connectionConfiguration, + receiveEndpointConfigurations, + _mockPdfPartitionerRunInfoService.Object, + _mockFileOperationsApiService.Object, + _mockQueuePdfPartitionerCompletionService.Object, + _mockLcuServiceFactory.Object); + } + + [Test] + public void HandlePdfPartition_ArgumentNullException_RequestNull() + { + PdfPartitionerRequest request = null; + Assert.ThrowsAsync(async () => await _pdfPartitionerService.HandlePdfPartition(request)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicDirectoryList(It.IsAny()), Times.Never); + _mockPdfPartitionerRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFile(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Never); + _mockLcuServiceFactory.Verify(x => x.GetService(It.IsAny()), Times.Never); + _mockQueuePdfPartitionerCompletionService.Verify(x => x.QueuePdfPartitionerCompletionRequest(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.QueueBatchPdfParser(It.IsAny()), Times.Never); + } + + [Test] + public void HandlePdfPartition_ServiceException_BuildDynamicDirectoryList_ThrowsException() + { + var request = new PdfPartitionerRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + PdfParserType = PdfParserTypes.FosLoanStatement + }; + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicDirectoryList(It.IsAny())).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _pdfPartitionerService.HandlePdfPartition(request)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicDirectoryList(It.IsAny()), Times.Once); + _mockPdfPartitionerRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFile(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Never); + _mockLcuServiceFactory.Verify(x => x.GetService(It.IsAny()), Times.Never); + _mockQueuePdfPartitionerCompletionService.Verify(x => x.QueuePdfPartitionerCompletionRequest(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.QueueBatchPdfParser(It.IsAny()), Times.Never); + } + + [Test] + public void HandlePdfPartition_ServiceException_PartitionerRunInfo_SaveAsync_ThrowsException() + { + var request = new PdfPartitionerRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + PdfParserType = PdfParserTypes.FosLoanStatement + }; + + var dynamicDirectoryListResult = new List + { + "TestParentDynamicDirectory1", + "TestParentDynamicDirectory2" + }; + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicDirectoryList(It.IsAny())).ReturnsAsync(dynamicDirectoryListResult); + + var indexService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(request.PdfParserType)).Returns(indexService.Object); + + _mockPdfPartitionerRunInfoService.Setup(x => x.SaveAsync(It.IsAny())).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _pdfPartitionerService.HandlePdfPartition(request)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicDirectoryList(It.IsAny()), Times.Once); + _mockPdfPartitionerRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFile(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Never); + indexService.Verify(x => x.DetermineBatchParsePdfRequest(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + _mockQueuePdfPartitionerCompletionService.Verify(x => x.QueuePdfPartitionerCompletionRequest(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.QueueBatchPdfParser(It.IsAny()), Times.Never); + } + + [Test] + public async Task HandlePdfPartition_ServiceException_DetermineIndexFile_BuildDynamicFileList_ThrowsException() + { + var request = new PdfPartitionerRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + PdfParserType = PdfParserTypes.FosLoanStatement, + DynamicIndexFileName = "TestDynamicIndexFileName", + DynamicPdfName = "TestDynamicPdfname" + }; + + var dynamicDirectoryListResult = new List + { + "TestParentDynamicDirectory1", + "TestParentDynamicDirectory2" + }; + _mockFileOperationsApiService.Setup(x => x.BuildDynamicDirectoryList(It.IsAny())).ReturnsAsync(dynamicDirectoryListResult); + + var indexService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(request.PdfParserType)).Returns(indexService.Object); + + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo(Convert.ToDateTime("1/1/2022"), PdfParserTypes.FosLoanStatement, "\\\\Tester\\path", 2); + _mockPdfPartitionerRunInfoService.Setup(x => x.SaveAsync(It.IsAny())).ReturnsAsync(pdfPartitionerRunInfo); + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFile(It.Is(dynamicFileListRequest => dynamicFileListRequest.Filename == request.DynamicIndexFileName))) + .ThrowsAsync(new Exception("Error")); + + await _pdfPartitionerService.HandlePdfPartition(request); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicDirectoryList(It.IsAny()), Times.Once); + _mockPdfPartitionerRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFile(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Never); + indexService.Verify(x => x.DetermineBatchParsePdfRequest(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + _mockQueuePdfPartitionerCompletionService.Verify(x => x.QueuePdfPartitionerCompletionRequest(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.QueueBatchPdfParser(It.IsAny()), Times.Never); + } + + [Test] + public async Task HandlePdfPartition_ServiceException_DetermineAllPdfsInDirectory_BuildDynamicFile_ThrowsException() + { + var request = new PdfPartitionerRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + PdfParserType = PdfParserTypes.FosLoanStatement, + DynamicIndexFileName = "TestDynamicIndexFileName", + DynamicPdfName = "TestDynamicPdfname" + }; + + var dynamicDirectoryListResult = new List + { + "TestParentDynamicDirectory1", + "TestParentDynamicDirectory2" + }; + _mockFileOperationsApiService.Setup(x => x.BuildDynamicDirectoryList(It.IsAny())).ReturnsAsync(dynamicDirectoryListResult); + + var indexService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(request.PdfParserType)).Returns(indexService.Object); + + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo(Convert.ToDateTime("1/1/2022"), PdfParserTypes.FosLoanStatement, "\\\\Tester\\path", 2); + _mockPdfPartitionerRunInfoService.Setup(x => x.SaveAsync(It.IsAny())).ReturnsAsync(pdfPartitionerRunInfo); + + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFile(It.Is(dynamicFileListRequest => + dynamicFileListRequest.Filename == request.DynamicIndexFileName))) + .ReturnsAsync("TestDynamicIndexFileName"); + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFile(It.Is(dynamicFileListRequest => dynamicFileListRequest.Filename == "{Regex0}"))) + .ThrowsAsync(new Exception("Error")); + + await _pdfPartitionerService.HandlePdfPartition(request); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicDirectoryList(It.IsAny()), Times.Once); + _mockPdfPartitionerRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFile(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Exactly(2)); + indexService.Verify(x => x.DetermineBatchParsePdfRequest(It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); + _mockQueuePdfPartitionerCompletionService.Verify(x => x.QueuePdfPartitionerCompletionRequest(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.QueueBatchPdfParser(It.IsAny()), Times.Never); + } + + [Test] + public async Task HandlePdfPartition_ServiceException_FosLoanStatementPdfService_DetermineBatchParsePdfRequest_ThrowsException() + { + var request = new PdfPartitionerRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + PdfParserType = PdfParserTypes.FosLoanStatement, + DynamicIndexFileName = "TestDynamicIndexFileName.txt", + DynamicPdfName = "TestDynamicPdfname", + DynamicPdfSettings = new DynamicNameSetting() + }; + + var dynamicDirectoryListResult = new List + { + "TestParentDynamicDirectory1", + "TestParentDynamicDirectory2" + }; + _mockFileOperationsApiService.Setup(x => x.BuildDynamicDirectoryList(It.IsAny())).ReturnsAsync(dynamicDirectoryListResult); + + var indexService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(request.PdfParserType)).Returns(indexService.Object); + + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo(Convert.ToDateTime("1/1/2022"), PdfParserTypes.FosLoanStatement, "\\\\Tester\\path", 2); + _mockPdfPartitionerRunInfoService.Setup(x => x.SaveAsync(It.IsAny())).ReturnsAsync(pdfPartitionerRunInfo); + + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFile(It.Is(dynamicFileListRequest => + dynamicFileListRequest.Filename == request.DynamicIndexFileName))) + .ReturnsAsync("TestDynamicIndexFileName"); + + var pdfFileList = new List + { + "TestDynamicPdfname.pdf" + }; + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFileList(It.Is(dynamicFileListRequest => + dynamicFileListRequest.Filename == "{Regex0}.(?i:pdf)"))) + .ReturnsAsync(pdfFileList); + + indexService.Setup(x => x.DetermineBatchParsePdfRequest(It.IsAny(), It.IsAny(), It.IsAny())).ThrowsAsync(new Exception("Error")); + + await _pdfPartitionerService.HandlePdfPartition(request); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicDirectoryList(It.IsAny()), Times.Once); + _mockPdfPartitionerRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFile(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Exactly(2)); + indexService.Verify(x => x.DetermineBatchParsePdfRequest(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(2)); + _mockQueuePdfPartitionerCompletionService.Verify(x => x.QueuePdfPartitionerCompletionRequest(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.QueueBatchPdfParser(It.IsAny()), Times.Never); + } + + [Test] + public async Task HandlePdfPartition_ServiceException_QueueBatchPdfParser_QueuedTwice() + { + var request = new PdfPartitionerRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + PdfParserType = PdfParserTypes.FosLoanStatement, + DynamicIndexFileName = "TestDynamicIndexFileName", + DynamicPdfName = "TestDynamicPdfname" + }; + + var dynamicDirectoryListResult = new List + { + "TestParentDynamicDirectory1", + "TestParentDynamicDirectory2" + }; + _mockFileOperationsApiService.Setup(x => x.BuildDynamicDirectoryList(It.IsAny())).ReturnsAsync(dynamicDirectoryListResult); + + var indexService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(request.PdfParserType)).Returns(indexService.Object); + + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo(Convert.ToDateTime("1/1/2022"), PdfParserTypes.FosLoanStatement, "\\\\Tester\\path", 2); + _mockPdfPartitionerRunInfoService.Setup(x => x.SaveAsync(It.IsAny())).ReturnsAsync(pdfPartitionerRunInfo); + + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFile(It.Is(dynamicFileListRequest => + dynamicFileListRequest.Filename == request.DynamicIndexFileName))) + .ReturnsAsync("TestDynamicIndexFileName"); + + var pdfFileList = new List + { + "TestDynamicPdfname.pdf" + }; + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFileList(It.Is(dynamicFileListRequest => + dynamicFileListRequest.Filename == "{Regex0}.(?i:pdf)"))) + .ReturnsAsync(pdfFileList); + + var batchPdfParserRequest = new BatchParsePdfRequest + { + RootPath = "\\\\Tester\\path", + PdfName = "TestDynamicPdfname", + BatchPdfs = new List + { + new BatchPdf + { + PageStart = 1, + PageStop = 2, + ParsedPdfname = "TestDynamicPdfname_Test" + } + } + }; + indexService.Setup(x => x.DetermineBatchParsePdfRequest(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(batchPdfParserRequest); + + await _pdfPartitionerService.HandlePdfPartition(request); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicDirectoryList(It.IsAny()), Times.Once); + _mockPdfPartitionerRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFile(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Exactly(2)); + indexService.Verify(x => x.DetermineBatchParsePdfRequest(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(2)); + _mockQueuePdfPartitionerCompletionService.Verify(x => x.QueuePdfPartitionerCompletionRequest(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.QueueBatchPdfParser(It.IsAny()), Times.Exactly(2)); + } + + [Test] + public void Osg_HandlePdfPartition_ArgumentNullException_RequestNull() + { + PdfPartitionerRequest request = null; + Assert.ThrowsAsync(async () => await _pdfPartitionerService.HandlePdfPartition(request)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicDirectoryList(It.IsAny()), Times.Never); + _mockPdfPartitionerRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFile(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Never); + _mockLcuServiceFactory.Verify(x => x.GetService(It.IsAny()), Times.Never); + _mockQueuePdfPartitionerCompletionService.Verify(x => x.QueuePdfPartitionerCompletionRequest(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.QueueBatchPdfParser(It.IsAny()), Times.Never); + } + [Test] + public void Osg_HandlePdfPartition_ServiceException_BuildDynamicDirectoryList_ThrowsException() + { + var request = new PdfPartitionerRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + PdfParserType = PdfParserTypes.OsgDnaNoticesDocument + }; + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicDirectoryList(It.IsAny())).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _pdfPartitionerService.HandlePdfPartition(request)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicDirectoryList(It.IsAny()), Times.Once); + _mockPdfPartitionerRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFile(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Never); + _mockQueuePdfPartitionerCompletionService.Verify(x => x.QueuePdfPartitionerCompletionRequest(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.QueueBatchPdfParser(It.IsAny()), Times.Never); + } + + [Test] + public void Osg_HandlePdfPartition_ServiceException_PartitionerRunInfo_SaveAsync_ThrowsException() + { + var request = new PdfPartitionerRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + PdfParserType = PdfParserTypes.OsgDnaNoticesDocument + }; + + var dynamicDirectoryListResult = new List + { + "TestParentDynamicDirectory1", + "TestParentDynamicDirectory2" + }; + _mockFileOperationsApiService.Setup(x => x.BuildDynamicDirectoryList(It.IsAny())).ReturnsAsync(dynamicDirectoryListResult); + _mockPdfPartitionerRunInfoService.Setup(x => x.SaveAsync(It.IsAny())).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _pdfPartitionerService.HandlePdfPartition(request)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicDirectoryList(It.IsAny()), Times.Once); + _mockPdfPartitionerRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFile(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Never); + _mockLcuServiceFactory.Verify(x => x.GetService(It.IsAny()), Times.Never); + _mockQueuePdfPartitionerCompletionService.Verify(x => x.QueuePdfPartitionerCompletionRequest(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.QueueBatchPdfParser(It.IsAny()), Times.Never); + } + + [Test] + public async Task Osg_HandlePdfPartition_ServiceException_DetermineIndexFile_BuildDynamicFileList_ThrowsException() + { + var request = new PdfPartitionerRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + PdfParserType = PdfParserTypes.OsgDnaNoticesDocument, + DynamicIndexFileName = "TestDynamicIndexFileName", + DynamicPdfName = "TestDynamicPdfname" + }; + + var dynamicDirectoryListResult = new List + { + "TestParentDynamicDirectory1", + "TestParentDynamicDirectory2" + }; + _mockFileOperationsApiService.Setup(x => x.BuildDynamicDirectoryList(It.IsAny())).ReturnsAsync(dynamicDirectoryListResult); + + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo(Convert.ToDateTime("1/1/2022"), PdfParserTypes.OsgDnaNoticesDocument, "\\\\Tester\\path", 2); + _mockPdfPartitionerRunInfoService.Setup(x => x.SaveAsync(It.IsAny())).ReturnsAsync(pdfPartitionerRunInfo); + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFile(It.Is(dynamicFileListRequest => dynamicFileListRequest.Filename == request.DynamicIndexFileName))) + .ThrowsAsync(new Exception("Error")); + + await _pdfPartitionerService.HandlePdfPartition(request); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicDirectoryList(It.IsAny()), Times.Once); + _mockPdfPartitionerRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFile(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Never); + _mockLcuServiceFactory.Verify(x => x.GetService(It.IsAny()), Times.Never); + _mockQueuePdfPartitionerCompletionService.Verify(x => x.QueuePdfPartitionerCompletionRequest(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.QueueBatchPdfParser(It.IsAny()), Times.Never); + } + + [Test] + public async Task Osg_HandlePdfPartition_ServiceException_DetermineAllPdfsInDirectory_BuildDynamicFile_ThrowsException() + { + var request = new PdfPartitionerRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + PdfParserType = PdfParserTypes.OsgDnaNoticesDocument, + DynamicIndexFileName = "TestDynamicIndexFileName", + DynamicPdfName = "TestDynamicPdfname" + }; + + var dynamicDirectoryListResult = new List + { + "TestParentDynamicDirectory1", + "TestParentDynamicDirectory2" + }; + _mockFileOperationsApiService.Setup(x => x.BuildDynamicDirectoryList(It.IsAny())).ReturnsAsync(dynamicDirectoryListResult); + + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo(Convert.ToDateTime("1/1/2022"), PdfParserTypes.OsgDnaNoticesDocument, "\\\\Tester\\path", 2); + _mockPdfPartitionerRunInfoService.Setup(x => x.SaveAsync(It.IsAny())).ReturnsAsync(pdfPartitionerRunInfo); + + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFile(It.Is(dynamicFileListRequest => + dynamicFileListRequest.Filename == request.DynamicIndexFileName))) + .ReturnsAsync("TestDynamicIndexFileName"); + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFile(It.Is(dynamicFileListRequest => dynamicFileListRequest.Filename == "{Regex0}"))) + .ThrowsAsync(new Exception("Error")); + + await _pdfPartitionerService.HandlePdfPartition(request); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicDirectoryList(It.IsAny()), Times.Once); + _mockPdfPartitionerRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFile(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Exactly(2)); + _mockLcuServiceFactory.Verify(x => x.GetService(It.IsAny()), Times.Never); + _mockQueuePdfPartitionerCompletionService.Verify(x => x.QueuePdfPartitionerCompletionRequest(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.QueueBatchPdfParser(It.IsAny()), Times.Never); + } + + [Test] + public async Task HandlePdfPartition_ServiceException_OsgDnaNoticesPdfService_DetermineBatchParsePdfRequest_ThrowsException() + { + var request = new PdfPartitionerRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + PdfParserType = PdfParserTypes.OsgDnaNoticesDocument, + DynamicIndexFileName = "TestDynamicIndexFileName.txt", + DynamicPdfName = "TestDynamicPdfname", + DynamicPdfSettings = new DynamicNameSetting() + }; + + var dynamicDirectoryListResult = new List + { + "TestParentDynamicDirectory1", + "TestParentDynamicDirectory2" + }; + _mockFileOperationsApiService.Setup(x => x.BuildDynamicDirectoryList(It.IsAny())).ReturnsAsync(dynamicDirectoryListResult); + + var indexService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(request.PdfParserType)).Returns(indexService.Object); + + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo(Convert.ToDateTime("1/1/2022"), PdfParserTypes.OsgDnaNoticesDocument, "\\\\Tester\\path", 2); + _mockPdfPartitionerRunInfoService.Setup(x => x.SaveAsync(It.IsAny())).ReturnsAsync(pdfPartitionerRunInfo); + + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFile(It.Is(dynamicFileListRequest => + dynamicFileListRequest.Filename == request.DynamicIndexFileName))) + .ReturnsAsync("TestDynamicIndexFileName"); + + var pdfFileList = new List + { + "TestDynamicPdfname.pdf" + }; + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFileList(It.Is(dynamicFileListRequest => + dynamicFileListRequest.Filename == "{Regex0}.(?i:pdf)"))) + .ReturnsAsync(pdfFileList); + + indexService.Setup(x => x.DetermineBatchParsePdfRequest(It.IsAny(), It.IsAny(), It.IsAny())).ThrowsAsync(new Exception("Error")); + + await _pdfPartitionerService.HandlePdfPartition(request); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicDirectoryList(It.IsAny()), Times.Once); + _mockPdfPartitionerRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFile(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Exactly(2)); + indexService.Verify(x => x.DetermineBatchParsePdfRequest(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(2)); + _mockQueuePdfPartitionerCompletionService.Verify(x => x.QueuePdfPartitionerCompletionRequest(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.QueueBatchPdfParser(It.IsAny()), Times.Never); + } + + [Test] + public async Task Osg_HandlePdfPartition_ServiceException_QueueBatchPdfParser_QueuedTwice() + { + var request = new PdfPartitionerRequest + { + RootBasePath = "\\\\Tester\\path", + ParentDynamicDirectory = "TestParentDynamicDirectory", + PdfParserType = PdfParserTypes.OsgDnaNoticesDocument, + DynamicIndexFileName = "TestDynamicIndexFileName", + DynamicPdfName = "TestDynamicPdfname" + }; + + var dynamicDirectoryListResult = new List + { + "TestParentDynamicDirectory1", + "TestParentDynamicDirectory2" + }; + _mockFileOperationsApiService.Setup(x => x.BuildDynamicDirectoryList(It.IsAny())).ReturnsAsync(dynamicDirectoryListResult); + + var indexService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(request.PdfParserType)).Returns(indexService.Object); + + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo(Convert.ToDateTime("1/1/2022"), PdfParserTypes.OsgDnaNoticesDocument, "\\\\Tester\\path", 2); + _mockPdfPartitionerRunInfoService.Setup(x => x.SaveAsync(It.IsAny())).ReturnsAsync(pdfPartitionerRunInfo); + + + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFile(It.Is(dynamicFileListRequest => + dynamicFileListRequest.Filename == request.DynamicIndexFileName))) + .ReturnsAsync("TestDynamicIndexFileName"); + + var pdfFileList = new List + { + "TestDynamicPdfname.pdf" + }; + _mockFileOperationsApiService.Setup(x => x.BuildDynamicFileList(It.Is(dynamicFileListRequest => + dynamicFileListRequest.Filename == "{Regex0}.(?i:pdf)"))) + .ReturnsAsync(pdfFileList); + + var batchPdfParserRequest = new BatchParsePdfRequest + { + RootPath = "\\\\Tester\\path", + PdfName = "TestDynamicPdfname", + BatchPdfs = new List + { + new BatchPdf + { + PageStart = 1, + PageStop = 2, + ParsedPdfname = "TestDynamicPdfname_Test" + } + } + }; + indexService.Setup(x => x.DetermineBatchParsePdfRequest(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(batchPdfParserRequest); + + await _pdfPartitionerService.HandlePdfPartition(request); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicDirectoryList(It.IsAny()), Times.Once); + _mockPdfPartitionerRunInfoService.Verify(x => x.SaveAsync(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFile(It.IsAny()), Times.Exactly(2)); + _mockFileOperationsApiService.Verify(x => x.BuildDynamicFileList(It.IsAny()), Times.Exactly(2)); + indexService.Verify(x => x.DetermineBatchParsePdfRequest(It.IsAny(), It.IsAny(), It.IsAny()), Times.Exactly(2)); + _mockQueuePdfPartitionerCompletionService.Verify(x => x.QueuePdfPartitionerCompletionRequest(It.IsAny()), Times.Never); + _mockFileOperationsApiService.Verify(x => x.QueueBatchPdfParser(It.IsAny()), Times.Exactly(2)); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/ProcessStatusTypeEmailServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/ProcessStatusTypeEmailServiceTest.cs new file mode 100644 index 0000000..a8cbce5 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/ProcessStatusTypeEmailServiceTest.cs @@ -0,0 +1,104 @@ +using Moq; +using NUnit.Framework; +using System.Collections.Generic; +using System.Threading.Tasks; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.NotificationsModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Requests; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.IngestionOperationServices; + +public class ProcessStatusTypeEmailServiceTest +{ + private ProcessStatusTypeEmailService _processStatusTypeEmailService; + private Mock _mockNotificationApiService; + private Mock _mockDocumentProcessingInfoService; + private ApiConfiguration _apiConfiguration; + + [SetUp] + public void Setup() + { + _mockNotificationApiService = new Mock(); + _mockDocumentProcessingInfoService = new Mock(); + _apiConfiguration = new ApiConfiguration(); + _processStatusTypeEmailService = new ProcessStatusTypeEmailService(_mockNotificationApiService.Object, + _mockDocumentProcessingInfoService.Object, + _apiConfiguration); + } + + [Test] + public async Task SendDataMappingEmailAsync_Success() + { + var request = new ProcessStatusTypeEmailRequest( + new List() { "testuser1@test.com" }, + new List() { ProcessStatusTypes.DataMappingFailure }, + "testurl.com"); + + var documentProcessingInfos = new List + { + new() + { + StatusType = ProcessStatusTypes.DataMappingFailure, + EntityUnknown = false + }, + new() + { + StatusType = ProcessStatusTypes.CriticalFailure, + EntityUnknown = false + }, + new() + { + StatusType = ProcessStatusTypes.NotificationDataFailure, + EntityUnknown = false + } + }; + + _mockDocumentProcessingInfoService.Setup(x => x.GetByProcessStatusTypeAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(documentProcessingInfos).Verifiable(); + + _mockNotificationApiService.Setup(x => x.SendEmailAsync(It.IsAny())).Verifiable(); + + await _processStatusTypeEmailService.SendProcessStatusEmailAsync(documentProcessingInfos, request); + _mockNotificationApiService.Verify(x => x.SendEmailAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task SendDataMappingEmailAsync_Exception() + { + var request = new ProcessStatusTypeEmailRequest( + new List() { "testuser1@test.com" }, + new List() { ProcessStatusTypes.DataMappingFailure }, + "testurl.com"); + + _mockDocumentProcessingInfoService.Setup(x => + x.GetByProcessStatusTypeListAsync(It.IsAny>(), It.IsAny())).ThrowsAsync(new ServiceException("Error")); + + await _processStatusTypeEmailService.HandleProcessStatusTypeEmailRequest(request); + + _mockDocumentProcessingInfoService.Verify(x => x.GetByProcessStatusTypeListAsync(It.IsAny>(), It.IsAny()), Times.Once); + _mockNotificationApiService.Verify(x => x.SendEmailAsync(It.IsAny()), Times.Never); + } + + [Test] + public async Task SendDataMappingEmailAsync_ServiceException() + { + var request = new ProcessStatusTypeEmailRequest( + new List() { "testuser1@test.com" }, + new List() { ProcessStatusTypes.CriticalFailure }, + "testurl.com"); + + _mockDocumentProcessingInfoService.Setup(x => + x.GetByProcessStatusTypeListAsync(It.IsAny>(), It.IsAny())).ThrowsAsync(new ServiceException("Error")); + + await _processStatusTypeEmailService.HandleProcessStatusTypeEmailRequest(request); + + _mockDocumentProcessingInfoService.Verify(x => x.GetByProcessStatusTypeListAsync(It.IsAny>(), It.IsAny()), Times.Once); + _mockNotificationApiService.Verify(x => x.SendEmailAsync(It.IsAny()), Times.Never); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/UploadCompletionServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/UploadCompletionServiceTest.cs new file mode 100644 index 0000000..3b30b20 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestionOperationServices/UploadCompletionServiceTest.cs @@ -0,0 +1,154 @@ +using System; +using System.Threading.Tasks; +using System.Collections.Generic; +using Moq; +using NUnit.Framework; +using Newtonsoft.Json; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using LCU.API.Internal.DocumentIngestor.Services.MemberNotificationInfoDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.QueueServices; +using LCU.API.Internal.DocumentIngestorLib.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.ApiResponse.Models; +using LCU.Library.Internal.DocumentIngestorModels.Constants; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.FileOperationsModels.Models; +namespace LCU.API.Internal.DocumentIngestorTests.Services.IngestionOperationServices; + +public class UploadCompletionServiceTest +{ + private UploadCompletionService _uploadCompletionService; + private Mock _mockQueueCompletionService; + private Mock _mockFileOperationsService; + private Mock _mockDocumentProcessingInfoService; + private Mock _mockMemberNotificationInfoDeterminingService; + private Mock _mockQueueGatherMemberNotificationInfoService; + + [SetUp] + public void Setup() + { + _mockQueueCompletionService = new Mock(); + _mockFileOperationsService = new Mock(); + _mockDocumentProcessingInfoService = new Mock(); + _mockMemberNotificationInfoDeterminingService = new Mock(); + _mockQueueGatherMemberNotificationInfoService = new Mock(); + _uploadCompletionService = new UploadCompletionService(_mockQueueCompletionService.Object, + _mockFileOperationsService.Object, + _mockDocumentProcessingInfoService.Object, + _mockMemberNotificationInfoDeterminingService.Object, + _mockQueueGatherMemberNotificationInfoService.Object); + } + + [Test] + public async Task HandleUploadCompletion_Success() + { + var documentProcessingInfoId = 1234; + var response = GenerateUploadResponse(documentProcessingInfoId); + var deserializedResponse = JsonConvert.DeserializeObject(response.ResponsePayload); + var info = new DocumentProcessingInfo() + { + DocumentProcessingInfoId = documentProcessingInfoId + }; + + var documentProcessingInfo = new List + { + new DocumentProcessingInfo() + { + DocumentProcessingInfoId = documentProcessingInfoId + } + }; + + + + _mockDocumentProcessingInfoService.Setup(x => x.GetListByIdAsync(It.IsAny>())).ReturnsAsync(documentProcessingInfo).Verifiable(); + _mockDocumentProcessingInfoService.Setup(x => x.UpdateRangeAsync(It.IsAny>())).ReturnsAsync(documentProcessingInfo).Verifiable(); + + await _uploadCompletionService.HandleUploadCompletion(new List() { response }); + + _mockDocumentProcessingInfoService.Verify(x => x.GetListByIdAsync(It.IsAny>()), Times.Once); + _mockDocumentProcessingInfoService.Verify(x => x.UpdateRangeAsync(It.IsAny>()), Times.Once); + _mockQueueGatherMemberNotificationInfoService.Verify(x => x.QueueGatherMemberNotificationInfoRequest(It.IsAny()), Times.Once); + _mockQueueCompletionService.Verify(x => x.QueueCompletionRequest(It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task HandleUploadCompletion_Failure_ResponseFailure() + { + var documentProcessingInfoId = 1234; + var uploadResponse = GenerateUploadResponse(documentProcessingInfoId); + uploadResponse.Successful = false; + uploadResponse.ResponseStack = new List { "Test Failure" }; + var moveResponse = new RequestResponse + { + IsSuccessful = true + }; + + _mockFileOperationsService.Setup(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(moveResponse).Verifiable(); + + await _uploadCompletionService.HandleUploadCompletion(new List() { uploadResponse }); + + _mockFileOperationsService.Verify(x => x.DirectMoveFile(It.IsAny(), It.IsAny(), It.IsAny()), Times.Once); + _mockQueueCompletionService.Verify(x => x.QueueCompletionRequest(It.IsAny(), It.IsAny()), Times.Once); + } + + private static CompletionRequest GenerateCompletionRequest() + => new() + { + ProcessingRequest = new ProcessingRequest + { + DocumentFileName = Guid.NewGuid().ToString(), + IngestorRequest = new() + { + RootPath = Guid.NewGuid().ToString() + } + }, + ProcessResult = new ProcessResult + { + ProcessStatusType = ProcessStatusTypes.Processing + } + }; + + private static CompletionRequest GenerateCompletionRequest(int documentProcessingInfoId) + => new() + { + ProcessingRequest = new ProcessingRequest + { + DocumentFileName = Guid.NewGuid().ToString(), + IngestorRequest = new() + { + RootPath = Guid.NewGuid().ToString() + }, + DocumentProcessingInfoId = documentProcessingInfoId + }, + ProcessResult = new ProcessResult + { + ProcessStatusType = ProcessStatusTypes.Processing + } + }; + + private static Response GenerateUploadResponse() + => new() + { + Successful = true, + ResponsePayload = JsonConvert.SerializeObject(GenerateCompletionRequest()), + ReturnCollection = new Dictionary + { + {"DocumentId", Guid.NewGuid().ToString()} + } + }; + + private static Response GenerateUploadResponse(int documentProcessingInfoId) + => new() + { + Successful = true, + ResponsePayload = JsonConvert.SerializeObject(GenerateCompletionRequest(documentProcessingInfoId)), + ReturnCollection = new Dictionary + { + {"DocumentId", Guid.NewGuid().ToString()} + } + }; +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestorRunInfoServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestorRunInfoServiceTest.cs new file mode 100644 index 0000000..56c9447 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/IngestorRunInfoServiceTest.cs @@ -0,0 +1,173 @@ +using System; +using System.Threading.Tasks; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestorLib.Repositories; +namespace LCU.API.Internal.DocumentIngestorTests.Services; + +public class IngestorRunInfoServiceTest +{ + private IngestorRunInfoService _ingestorRunInfoService; + private Mock _unitOfWork; + private Mock _mockIngestorRunInfoRepository; + + [SetUp] + public void Setup() + { + _unitOfWork = new Mock(); + _mockIngestorRunInfoRepository = new Mock(); + _ingestorRunInfoService = new IngestorRunInfoService(_unitOfWork.Object, _mockIngestorRunInfoRepository.Object); + } + + [Test] + public async Task GetByIdAsync_IngestorRunInfo_Returned() + { + var ingestorRunInfoId = Guid.NewGuid(); + var ingestorRunInfo = new IngestorRunInfo() + { + IngestorRunInfoId = ingestorRunInfoId + }; + _mockIngestorRunInfoRepository.Setup(x => x.FindByIdAsync(ingestorRunInfoId)).ReturnsAsync(ingestorRunInfo); + var result = await _ingestorRunInfoService.GetByIdAsync(ingestorRunInfoId); + Assert.IsNotNull(result); + Assert.AreEqual(ingestorRunInfoId, result.IngestorRunInfoId); + _mockIngestorRunInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public void GetByIdAsync_Exception() + { + var ingestorRunInfoId = Guid.NewGuid(); + _mockIngestorRunInfoRepository.Setup(x => x.FindByIdAsync(ingestorRunInfoId)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _ingestorRunInfoService.GetByIdAsync(ingestorRunInfoId)); + _mockIngestorRunInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task SaveAsync_IngestorRunInfo_Returned() + { + var ingestorRunInfoId = Guid.NewGuid(); + var ingestorRunInfo = new IngestorRunInfo() + { + IngestorRunInfoId = ingestorRunInfoId + }; + _mockIngestorRunInfoRepository.Setup(x => x.AddAsync(ingestorRunInfo)).ReturnsAsync(ingestorRunInfo); + var result = await _ingestorRunInfoService.SaveAsync(ingestorRunInfo); + Assert.IsNotNull(result); + Assert.AreEqual(ingestorRunInfoId, result.IngestorRunInfoId); + _mockIngestorRunInfoRepository.Verify(x => x.AddAsync(It.IsAny()), Times.Once); + } + + [Test] + public void SaveAsync_Exception() + { + var ingestorRunInfoId = Guid.NewGuid(); + var ingestorRunInfo = new IngestorRunInfo() + { + IngestorRunInfoId = ingestorRunInfoId + }; + _mockIngestorRunInfoRepository.Setup(x => x.AddAsync(ingestorRunInfo)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _ingestorRunInfoService.SaveAsync(ingestorRunInfo)); + _mockIngestorRunInfoRepository.Verify(x => x.AddAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task Update_IngestorRunInfo_Returned() + { + var ingestorRunInfoId = Guid.NewGuid(); + var ingestorRunInfo = new IngestorRunInfo() + { + IngestorRunInfoId = ingestorRunInfoId + }; + _mockIngestorRunInfoRepository.Setup(x => x.FindByIdAsync(ingestorRunInfoId)).ReturnsAsync(ingestorRunInfo); + _mockIngestorRunInfoRepository.Setup(x => x.Update(ingestorRunInfo)); + + var result = await _ingestorRunInfoService.Update(ingestorRunInfo); + Assert.IsNotNull(result); + Assert.AreEqual(ingestorRunInfoId, result.IngestorRunInfoId); + _mockIngestorRunInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockIngestorRunInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Once); + } + + [Test] + public void Update_FindByIdAsync_ThrowsException() + { + var ingestorRunInfoId = Guid.NewGuid(); + var ingestorRunInfo = new IngestorRunInfo() + { + IngestorRunInfoId = ingestorRunInfoId + }; + _mockIngestorRunInfoRepository.Setup(x => x.FindByIdAsync(ingestorRunInfoId)).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _ingestorRunInfoService.Update(ingestorRunInfo)); + _mockIngestorRunInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockIngestorRunInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Never); + } + + [Test] + public void Update_Update_ThrowsException() + { + var ingestorRunInfoId = Guid.NewGuid(); + var ingestorRunInfo = new IngestorRunInfo() + { + IngestorRunInfoId = ingestorRunInfoId + }; + _mockIngestorRunInfoRepository.Setup(x => x.FindByIdAsync(ingestorRunInfoId)).ReturnsAsync(ingestorRunInfo); + _mockIngestorRunInfoRepository.Setup(x => x.Update(ingestorRunInfo)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _ingestorRunInfoService.Update(ingestorRunInfo)); + _mockIngestorRunInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockIngestorRunInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Once); + } + + [Test] + public async Task Delete_Success() + { + var ingestorRunInfoId = Guid.NewGuid(); + var ingestorRunInfo = new IngestorRunInfo() + { + IngestorRunInfoId = ingestorRunInfoId + }; + _mockIngestorRunInfoRepository.Setup(x => x.FindByIdAsync(ingestorRunInfoId)).ReturnsAsync(ingestorRunInfo); + _mockIngestorRunInfoRepository.Setup(x => x.Remove(ingestorRunInfo)); + + await _ingestorRunInfoService.Delete(ingestorRunInfoId); + _mockIngestorRunInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockIngestorRunInfoRepository.Verify(x => x.Remove(It.IsAny()), Times.Once); + } + + [Test] + public void Delete_FindByIdAsync_ThrowsException() + { + var ingestorRunInfoId = Guid.NewGuid(); + var ingestorRunInfo = new IngestorRunInfo() + { + IngestorRunInfoId = ingestorRunInfoId + }; + _mockIngestorRunInfoRepository.Setup(x => x.FindByIdAsync(ingestorRunInfoId)).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _ingestorRunInfoService.Delete(ingestorRunInfoId)); + _mockIngestorRunInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockIngestorRunInfoRepository.Verify(x => x.Remove(It.IsAny()), Times.Never); + } + + [Test] + public void Delete_Remove_ThrowsException() + { + var ingestorRunInfoId = Guid.NewGuid(); + var ingestorRunInfo = new IngestorRunInfo() + { + IngestorRunInfoId = ingestorRunInfoId + }; + _mockIngestorRunInfoRepository.Setup(x => x.FindByIdAsync(ingestorRunInfoId)).ReturnsAsync(ingestorRunInfo); + _mockIngestorRunInfoRepository.Setup(x => x.Remove(ingestorRunInfo)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _ingestorRunInfoService.Delete(ingestorRunInfoId)); + _mockIngestorRunInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockIngestorRunInfoRepository.Verify(x => x.Remove(It.IsAny()), Times.Once); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MemberNotificationInfoDeterminingServices/AccountNotificationInfoDeterminingServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MemberNotificationInfoDeterminingServices/AccountNotificationInfoDeterminingServiceTest.cs new file mode 100644 index 0000000..4153acc --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MemberNotificationInfoDeterminingServices/AccountNotificationInfoDeterminingServiceTest.cs @@ -0,0 +1,105 @@ +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Services.MemberNotificationInfoDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements; +using LCU.Library.Internal.Exceptions; +using Moq; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.MemberNotificationInfoDeterminingServices; + +public class AccountNotificationInfoDeterminingServiceTest +{ + private AccountNotificationInfoDeterminingService _accountNotificationInfoDeterminingService; + private Mock _mockCoreApiWrapperService; + private ApiConfiguration _apiConfiguration; + + [SetUp] + public void Setup() + { + _mockCoreApiWrapperService = new Mock(); + _apiConfiguration = new ApiConfiguration() { TimeZone = "America/Chicago" }; + _accountNotificationInfoDeterminingService = new AccountNotificationInfoDeterminingService(_mockCoreApiWrapperService.Object, + _apiConfiguration); + } + + [Test] + public async Task DetermineAccountOwnerNotificationInfos_Success() + { + var entityNumber = "123"; + var agreeUserAccounts = new List + { + new AgreeUserAccount + { + UserId = "456" + } + }; + var user = new Agreement() + { + UserId = "456", + OrganizationName = "RugMart" + }; + _mockCoreApiWrapperService.Setup(x => x.GetAgreeUsersByAccount(entityNumber)).ReturnsAsync(agreeUserAccounts); + _mockCoreApiWrapperService.Setup(x => x.GetAgreementByUserId(It.IsAny())).ReturnsAsync(user); + + var result = await _accountNotificationInfoDeterminingService.DetermineAccountOwnerNotificationInfos(entityNumber); + Assert.NotNull(result); + Assert.AreEqual(result.Count, 1); + _mockCoreApiWrapperService.Verify(x => x.GetAgreeUsersByAccount(entityNumber), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Once); + } + + [Test] + public async Task DetermineAccountOwnerNotificationInfos_Success_NoAgreeUserAccounts() + { + var entityNumber = "123"; + List agreeUserAccounts = null; + _mockCoreApiWrapperService.Setup(x => x.GetAgreeUsersByAccount(entityNumber)).ReturnsAsync(agreeUserAccounts); + + var result = await _accountNotificationInfoDeterminingService.DetermineAccountOwnerNotificationInfos(entityNumber); + + Assert.NotNull(result); + Assert.AreEqual(result.Count, 1); + _mockCoreApiWrapperService.Verify(x => x.GetAgreeUsersByAccount(entityNumber), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + } + + [Test] + public void DetermineAccountOwnerNotificationInfos_MultipleAgreeUserAccounts_ExceptionThrown() + { + var entityNumber = "123"; + var agreeUserAccounts = new List + { + new AgreeUserAccount + { + UserId = "456" + }, + new AgreeUserAccount + { + UserId = "457" + } + }; + _mockCoreApiWrapperService.Setup(x => x.GetAgreeUsersByAccount(entityNumber)).ReturnsAsync(agreeUserAccounts); + + Assert.ThrowsAsync(async () => await _accountNotificationInfoDeterminingService + .DetermineAccountOwnerNotificationInfos(entityNumber)); + + _mockCoreApiWrapperService.Verify(x => x.GetAgreeUsersByAccount(entityNumber), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + } + + [Test] + public void DetermineAccountOwnerNotificationInfos_Exception() + { + _mockCoreApiWrapperService.Setup(x => x.GetAgreeUsersByAccount(null)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _accountNotificationInfoDeterminingService + .DetermineAccountOwnerNotificationInfos(null)); + _mockCoreApiWrapperService.Verify(x => x.GetAgreeUsersByAccount(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MemberNotificationInfoDeterminingServices/MemberNotificationInfoDeterminingServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MemberNotificationInfoDeterminingServices/MemberNotificationInfoDeterminingServiceTest.cs new file mode 100644 index 0000000..de61c30 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MemberNotificationInfoDeterminingServices/MemberNotificationInfoDeterminingServiceTest.cs @@ -0,0 +1,386 @@ +using LCU.API.Internal.DocumentIngestor.Models.MemberPreferencesDtos; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestor.Services.MemberNotificationInfoDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.Exceptions; +using Moq; +using NUnit.Framework; +using System; +using System.Threading.Tasks; +using LCU.Library.DocumentType.Extensions; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.MemberNotificationInfoDeterminingServices; + +public class MemberNotificationInfoDeterminingServiceTest +{ + private MemberNotificationInfoDeterminingService _memberNotificationInfoDeterminingService; + private Mock _mockAccountNotificationInfoDeterminingService; + private Mock _mockPrimaryNotificationInfoDeterminingService; + private Mock _mockMemberNotificationInfoService; + private Mock _mockMemberPreferencesApiService; + private Mock _mockDocumentProcessingInfoService; + + [SetUp] + public void Setup() + { + _mockAccountNotificationInfoDeterminingService = new Mock(); + _mockPrimaryNotificationInfoDeterminingService = new Mock(); + _mockMemberNotificationInfoService = new Mock(); + _mockMemberPreferencesApiService = new Mock(); + _mockDocumentProcessingInfoService = new Mock(); + _memberNotificationInfoDeterminingService = new MemberNotificationInfoDeterminingService(_mockAccountNotificationInfoDeterminingService.Object, + _mockPrimaryNotificationInfoDeterminingService.Object, + _mockMemberNotificationInfoService.Object, + _mockMemberPreferencesApiService.Object, + _mockDocumentProcessingInfoService.Object); + } + + [Test] + public async Task DetermineDeliveryMethod_UniversalOptIn_NotNull() + { + var memberNotificationInfoId = 10; + var documentProcessingInfoId = 1; + var userId = "555"; + var memberNotificationInfo = new MemberNotificationInfo() + { + AgreeUserId = userId, + MemberNotificationInfoId = memberNotificationInfoId, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = Convert.ToDateTime("1/1/2022") + }; + + var memberOptInSettings = new MemberOptInInformation() + { + MemberOptinSettings = new MemberOptInSettings() + { + UniversalOptIn = "Electronic", + UnifiedOptInEmail = "test@test.com" + } + }; + + var contact = (EmailAddress: "test@test.com", DeliveryMethod: DeliveryMethod.Electronic); + + _mockMemberPreferencesApiService.Setup(x => x.GetMemberOptInSettingsByUserId(userId)).ReturnsAsync(memberOptInSettings); + + var result = await _memberNotificationInfoDeterminingService.DetermineDeliveryMethod(memberNotificationInfo); + Assert.IsNotNull(result); + Assert.AreEqual(result.DeliveryMethod, contact.DeliveryMethod); + Assert.AreEqual(result.EmailAddress, contact.EmailAddress); + _mockMemberPreferencesApiService.Verify(x => x.GetMemberOptInSettingsByUserId(It.IsAny()), Times.Once); + _mockDocumentProcessingInfoService.Verify(x => x.GetByIdAsync(It.IsAny()), Times.Never); + } + + [Test] + public async Task DetermineDeliveryMethod_UniversalOptIn_UserIdNull() + { + var memberNotificationInfoId = 10; + var documentProcessingInfoId = 1; + var memberNotificationInfo = new MemberNotificationInfo() + { + MemberNotificationInfoId = memberNotificationInfoId, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = Convert.ToDateTime("1/1/2022") + }; + + var contact = (EmailAddress: "", DeliveryMethod: DeliveryMethod.Paper); + + var result = await _memberNotificationInfoDeterminingService.DetermineDeliveryMethod(memberNotificationInfo); + Assert.IsNotNull(result); + Assert.AreEqual(result.DeliveryMethod, contact.DeliveryMethod); + Assert.AreEqual(result.EmailAddress, contact.EmailAddress); + _mockMemberPreferencesApiService.Verify(x => x.GetMemberOptInSettingsByUserId(It.IsAny()), Times.Never); + _mockDocumentProcessingInfoService.Verify(x => x.GetByIdAsync(It.IsAny()), Times.Never); + } + + [Test] + public async Task DetermineDeliveryMethod_UniversalOptInNull_ENotification() + { + var memberNotificationInfoId = 10; + var documentProcessingInfoId = 1; + var userId = "555"; + var memberNotificationInfo = new MemberNotificationInfo() + { + AgreeUserId = userId, + MemberNotificationInfoId = memberNotificationInfoId, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = Convert.ToDateTime("1/1/2022") + }; + + var memberOptInSettings = new MemberOptInInformation() + { + MemberOptinSettings = new MemberOptInSettings() + { + ENotifications = "Electronic", + ENotificationsEmail = "test@test.com" + } + }; + + var documentProcessingInfo = new DocumentProcessingInfo() + { + DocumentType = "1099-NEC" + }; + + var contact = (EmailAddress: "test@test.com", DeliveryMethod: DeliveryMethod.Electronic); + + _mockMemberPreferencesApiService.Setup(x => x.GetMemberOptInSettingsByUserId(userId)).ReturnsAsync(memberOptInSettings); + _mockDocumentProcessingInfoService.Setup(x => x.GetByIdAsync(documentProcessingInfoId)).ReturnsAsync(documentProcessingInfo); + + var result = await _memberNotificationInfoDeterminingService.DetermineDeliveryMethod(memberNotificationInfo); + Assert.IsNotNull(result); + Assert.AreEqual(result.DeliveryMethod, contact.DeliveryMethod); + Assert.AreEqual(result.EmailAddress, contact.EmailAddress); + _mockMemberPreferencesApiService.Verify(x => x.GetMemberOptInSettingsByUserId(It.IsAny()), Times.Once); + _mockDocumentProcessingInfoService.Verify(x => x.GetByIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task DetermineDeliveryMethod_UniversalOptInNull_EStatements_DocTypeNotStatement() + { + var memberNotificationInfoId = 10; + var documentProcessingInfoId = 1; + var userId = "555"; + var memberNotificationInfo = new MemberNotificationInfo + { + AgreeUserId = userId, + MemberNotificationInfoId = memberNotificationInfoId, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = Convert.ToDateTime("1/1/2022") + }; + var memberOptInSettings = new MemberOptInInformation + { + MemberOptinSettings = new MemberOptInSettings + { + ENotifications = "Paper" + } + }; + var documentProcessingInfo = new DocumentProcessingInfo + { + DocumentType = "1099-NEC" + }; + var contact = (EmailAddress: "", DeliveryMethod: DeliveryMethod.Paper); + _mockMemberPreferencesApiService + .Setup(x => x.GetMemberOptInSettingsByUserId(userId)) + .ReturnsAsync(memberOptInSettings); + _mockDocumentProcessingInfoService + .Setup(x => x.GetByIdAsync(documentProcessingInfoId)) + .ReturnsAsync(documentProcessingInfo); + + var result = await _memberNotificationInfoDeterminingService.DetermineDeliveryMethod(memberNotificationInfo); + + Assert.IsNotNull(result); + Assert.AreEqual(result.DeliveryMethod, contact.DeliveryMethod); + Assert.AreEqual(result.EmailAddress, contact.EmailAddress); + } + + [Test] + [TestCase("Paper", "Electronic")] + [TestCase("Electronic", "Paper")] + public async Task DetermineDeliveryMethod_StatementAndUniversalOptInNotNull_ReturnsUniversalOptInPreferences(string universalPreference, string statementPreference) + { + var documentProcessingInfoId = DateTime.Now.Millisecond; + var userId = DateTime.Now.Millisecond.ToString(); + var memberNotificationInfo = new MemberNotificationInfo + { + AgreeUserId = userId, + MemberNotificationInfoId = DateTime.Now.Millisecond, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = DateTime.Now + }; + var memberOptInSettings = new MemberOptInInformation + { + MemberOptinSettings = new MemberOptInSettings + { + UniversalOptIn = universalPreference, + UnifiedOptInEmail = Guid.NewGuid().ToString(), + ENotifications = statementPreference, + ENotificationsEmail = Guid.NewGuid().ToString() + } + }; + var documentProcessingInfo = new DocumentProcessingInfo(); + _mockMemberPreferencesApiService + .Setup(x => x.GetMemberOptInSettingsByUserId(userId)) + .ReturnsAsync(memberOptInSettings); + _mockDocumentProcessingInfoService + .Setup(x => x.GetByIdAsync(documentProcessingInfoId)) + .ReturnsAsync(documentProcessingInfo); + + var result = await _memberNotificationInfoDeterminingService.DetermineDeliveryMethod(memberNotificationInfo); + + Assert.IsNotNull(result); + Assert.AreEqual(result.DeliveryMethod, universalPreference.GetValueFromName()); + Assert.AreEqual(result.EmailAddress, universalPreference == "Paper" ? string.Empty : memberOptInSettings.MemberOptinSettings.UnifiedOptInEmail); + } + + [Test] + [TestCase("Paper")] + [TestCase("Electronic")] + public async Task DetermineDeliveryMethod_StatementAndUniversalOptInNull_ReturnsEStatementPreferences(string statementPreference) + { + var documentProcessingInfoId = DateTime.Now.Millisecond; + var userId = DateTime.Now.Millisecond.ToString(); + var memberNotificationInfo = new MemberNotificationInfo + { + AgreeUserId = userId, + MemberNotificationInfoId = DateTime.Now.Millisecond, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = DateTime.Now + }; + var memberOptInSettings = new MemberOptInInformation + { + MemberOptinSettings = new MemberOptInSettings + { + UniversalOptIn = null!, + EStatements = statementPreference, + EStatementsEmail = Guid.NewGuid().ToString() + } + }; + var documentProcessingInfo = new DocumentProcessingInfo + { + DocumentType = "Statement" + }; + _mockMemberPreferencesApiService + .Setup(x => x.GetMemberOptInSettingsByUserId(userId)) + .ReturnsAsync(memberOptInSettings); + _mockDocumentProcessingInfoService + .Setup(x => x.GetByIdAsync(documentProcessingInfoId)) + .ReturnsAsync(documentProcessingInfo); + + var result = await _memberNotificationInfoDeterminingService.DetermineDeliveryMethod(memberNotificationInfo); + + Assert.IsNotNull(result); + Assert.AreEqual(result.DeliveryMethod, statementPreference.GetValueFromName()); + Assert.AreEqual(result.EmailAddress, statementPreference == "Paper" ? string.Empty : memberOptInSettings.MemberOptinSettings.EStatementsEmail); + } + + [Test] + [TestCase("Paper", "Electronic")] + [TestCase("Electronic", "Paper")] + [TestCase("Electronic", "Electronic")] + public async Task DetermineDeliveryMethod_StatementAndUniversalOptInNullAndENotificationNotNull_ReturnsEStatementPreferences(string statementPreference, string notificationPreference) + { + var documentProcessingInfoId = DateTime.Now.Millisecond; + var userId = DateTime.Now.Millisecond.ToString(); + var memberNotificationInfo = new MemberNotificationInfo + { + AgreeUserId = userId, + MemberNotificationInfoId = DateTime.Now.Millisecond, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = DateTime.Now + }; + var memberOptInSettings = new MemberOptInInformation + { + MemberOptinSettings = new MemberOptInSettings + { + UniversalOptIn = null!, + EStatements = statementPreference, + EStatementsEmail = Guid.NewGuid().ToString(), + ENotifications = notificationPreference, + ENotificationsEmail = Guid.NewGuid().ToString() + } + }; + var documentProcessingInfo = new DocumentProcessingInfo + { + DocumentType = "Statement" + }; + _mockMemberPreferencesApiService + .Setup(x => x.GetMemberOptInSettingsByUserId(userId)) + .ReturnsAsync(memberOptInSettings); + _mockDocumentProcessingInfoService + .Setup(x => x.GetByIdAsync(documentProcessingInfoId)) + .ReturnsAsync(documentProcessingInfo); + + var result = await _memberNotificationInfoDeterminingService.DetermineDeliveryMethod(memberNotificationInfo); + + Assert.IsNotNull(result); + Assert.AreEqual(result.DeliveryMethod, statementPreference.GetValueFromName()); + Assert.AreEqual(result.EmailAddress, statementPreference == "Paper" ? string.Empty : memberOptInSettings.MemberOptinSettings.EStatementsEmail); + } + + [Test] + public async Task DetermineDeliveryMethod_StatementAndAllPreferencesNull_ReturnsPaper() + { + var documentProcessingInfoId = DateTime.Now.Millisecond; + var userId = DateTime.Now.Millisecond.ToString(); + var memberNotificationInfo = new MemberNotificationInfo + { + AgreeUserId = userId, + MemberNotificationInfoId = DateTime.Now.Millisecond, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = DateTime.Now + }; + var memberOptInSettings = new MemberOptInInformation + { + MemberOptinSettings = new MemberOptInSettings + { + UniversalOptIn = null!, + ENotifications = null!, + EStatements = null! + } + }; + var documentProcessingInfo = new DocumentProcessingInfo + { + DocumentType = "Statement" + }; + _mockMemberPreferencesApiService + .Setup(x => x.GetMemberOptInSettingsByUserId(userId)) + .ReturnsAsync(memberOptInSettings); + _mockDocumentProcessingInfoService + .Setup(x => x.GetByIdAsync(documentProcessingInfoId)) + .ReturnsAsync(documentProcessingInfo); + + var result = await _memberNotificationInfoDeterminingService.DetermineDeliveryMethod(memberNotificationInfo); + + Assert.IsNotNull(result); + Assert.AreEqual(result.DeliveryMethod, "Paper".GetValueFromName()); + Assert.AreEqual(result.EmailAddress, string.Empty); + } + + [Test] + public async Task DetermineDeliveryMethod_NotStatementAndAllPreferencesNull_ReturnsPaper() + { + var documentProcessingInfoId = DateTime.Now.Millisecond; + var userId = DateTime.Now.Millisecond.ToString(); + var memberNotificationInfo = new MemberNotificationInfo + { + AgreeUserId = userId, + MemberNotificationInfoId = DateTime.Now.Millisecond, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = DateTime.Now + }; + var memberOptInSettings = new MemberOptInInformation + { + MemberOptinSettings = new MemberOptInSettings + { + UniversalOptIn = null!, + ENotifications = null!, + EStatements = null! + } + }; + var documentProcessingInfo = new DocumentProcessingInfo(); + _mockMemberPreferencesApiService + .Setup(x => x.GetMemberOptInSettingsByUserId(userId)) + .ReturnsAsync(memberOptInSettings); + _mockDocumentProcessingInfoService + .Setup(x => x.GetByIdAsync(documentProcessingInfoId)) + .ReturnsAsync(documentProcessingInfo); + + var result = await _memberNotificationInfoDeterminingService.DetermineDeliveryMethod(memberNotificationInfo); + + Assert.IsNotNull(result); + Assert.AreEqual(result.DeliveryMethod, "Paper".GetValueFromName()); + Assert.AreEqual(result.EmailAddress, string.Empty); + } + + [Test] + public void DetermineDeliveryMethod_Exception() + { + var memberNotificationInfo = new MemberNotificationInfo() { AgreeUserId = "1111" }; + _mockMemberPreferencesApiService.Setup(x => x.GetMemberOptInSettingsByUserId(memberNotificationInfo.AgreeUserId)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _memberNotificationInfoDeterminingService.DetermineDeliveryMethod(memberNotificationInfo)); + _mockMemberPreferencesApiService.Verify(x => x.GetMemberOptInSettingsByUserId(It.IsAny()), Times.Once); + _mockDocumentProcessingInfoService.Verify(x => x.GetByIdAsync(It.IsAny()), Times.Never); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MemberNotificationInfoDeterminingServices/PrimaryNotificationInfoDeterminingServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MemberNotificationInfoDeterminingServices/PrimaryNotificationInfoDeterminingServiceTest.cs new file mode 100644 index 0000000..9ef9fc3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MemberNotificationInfoDeterminingServices/PrimaryNotificationInfoDeterminingServiceTest.cs @@ -0,0 +1,166 @@ +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Services.MemberNotificationInfoDeterminingServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.Exceptions; +using Moq; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.MemberNotificationInfoDeterminingServices; +public class PrimaryNotificationInfoDeterminingServiceTest +{ + private PrimaryNotificationInfoDeterminingService _primaryNotificationInfoDeterminingService; + private Mock _mockCoreApiWrapperService; + private ApiConfiguration _apiConfiguration; + + [SetUp] + public void Setup() + { + _mockCoreApiWrapperService = new Mock(); + _apiConfiguration = new ApiConfiguration() { TimeZone = "America/Chicago" }; + _primaryNotificationInfoDeterminingService = new PrimaryNotificationInfoDeterminingService(_mockCoreApiWrapperService.Object, + _apiConfiguration); + } + + [Test] + public async Task DeterminePrimaryOwnerNotificationInfos_Success_PersonNumber() + { + var entityNumber = "123"; + var userIds = new List { "456", "567", "678" }; + var users = new List() + { + new() + { + UserId = userIds[0], + FirstName = "Tim" + }, + new() + { + UserId = userIds[1], + FirstName = "Fred" + }, + new() + { + UserId = userIds[2], + FirstName = "Randy" + } + }; + + _mockCoreApiWrapperService.Setup(x => x.GetAgreeUsersByPersonNumber(entityNumber)).ReturnsAsync(userIds); + _mockCoreApiWrapperService.SetupSequence(x => x.GetAgreementByUserId(It.IsAny())).ReturnsAsync(users[0]) + .ReturnsAsync(users[1]) + .ReturnsAsync(users[2]); + + var result = await _primaryNotificationInfoDeterminingService.DeterminePrimaryOwnerNotificationInfos("123", EntityTypes.Person); + + Assert.NotNull(result); + Assert.AreEqual(result.Count, 3); + _mockCoreApiWrapperService.Verify(x => x.GetAgreeUsersByPersonNumber(entityNumber), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Exactly(3)); + _mockCoreApiWrapperService.Verify(x => x.GetAgreeUserByOrganizationNumber(It.IsAny()), Times.Never); + } + + [Test] + public async Task DeterminePrimaryOwnerNotificationInfos_Success_OrganizationNumber() + { + var entityNumber = "123"; + var userIds = new List { "456" }; + var user = new Agreement() + { + UserId = userIds[0], + OrganizationName = "RugMart" + }; + + _mockCoreApiWrapperService.Setup(x => x.GetAgreeUserByOrganizationNumber(entityNumber)).ReturnsAsync(userIds[0]); + _mockCoreApiWrapperService.Setup(x => x.GetAgreementByUserId(It.IsAny())).ReturnsAsync(user); + + var result = await _primaryNotificationInfoDeterminingService.DeterminePrimaryOwnerNotificationInfos(entityNumber, EntityTypes.Organization); + Assert.NotNull(result); + Assert.AreEqual(result.Count, 1); + _mockCoreApiWrapperService.Verify(x => x.GetAgreeUserByOrganizationNumber(entityNumber), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreeUsersByPersonNumber(It.IsAny()), Times.Never); + } + + [Test] + public async Task DeterminePrimaryOwnerNotificationInfos_Success_NoAgreemrnt_Organization() + { + var entityNumber = "123"; + string userId = null; + + _mockCoreApiWrapperService.Setup(x => x.GetAgreeUserByOrganizationNumber(entityNumber)).ReturnsAsync(userId); + + var result = await _primaryNotificationInfoDeterminingService.DeterminePrimaryOwnerNotificationInfos(entityNumber, EntityTypes.Organization); + Assert.NotNull(result); + Assert.AreEqual(result.Count, 1); + _mockCoreApiWrapperService.Verify(x => x.GetAgreeUserByOrganizationNumber(entityNumber), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetAgreeUsersByPersonNumber(It.IsAny()), Times.Never); + } + + [Test] + public async Task DeterminePrimaryOwnerNotificationInfos_Success_NullAgreement_Person() + { + var entityNumber = "123"; + var userIds = new List { "456" }; + Agreement user = null; + + _mockCoreApiWrapperService.Setup(x => x.GetAgreeUsersByPersonNumber(entityNumber)).ReturnsAsync(userIds); + _mockCoreApiWrapperService.Setup(x => x.GetAgreementByUserId(It.IsAny())).ReturnsAsync(user); + + var result = await _primaryNotificationInfoDeterminingService.DeterminePrimaryOwnerNotificationInfos(entityNumber, EntityTypes.Person); + Assert.NotNull(result); + Assert.AreEqual(result.Count, 1); + _mockCoreApiWrapperService.Verify(x => x.GetAgreeUsersByPersonNumber(entityNumber), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreeUserByOrganizationNumber(It.IsAny()), Times.Never); + } + + [Test] + public async Task DeterminePrimaryOwnerNotificationInfos_Success_NullAgreeUsers_Person() + { + var entityNumber = "123"; + IEnumerable? userId = null; + + _mockCoreApiWrapperService.Setup(x => x.GetAgreeUsersByPersonNumber(entityNumber)).ReturnsAsync(userId); + + var result = await _primaryNotificationInfoDeterminingService.DeterminePrimaryOwnerNotificationInfos(entityNumber, EntityTypes.Person); + Assert.NotNull(result); + Assert.AreEqual(result.Count, 1); + _mockCoreApiWrapperService.Verify(x => x.GetAgreeUsersByPersonNumber(entityNumber), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetAgreeUserByOrganizationNumber(It.IsAny()), Times.Never); + } + + [Test] + public async Task DeterminePrimaryOwnerNotificationInfos_Success_NoAgreement_Person() + { + var entityNumber = "123"; + IEnumerable userId = new List(); + + _mockCoreApiWrapperService.Setup(x => x.GetAgreeUsersByPersonNumber(entityNumber)).ReturnsAsync(userId); + + var result = await _primaryNotificationInfoDeterminingService.DeterminePrimaryOwnerNotificationInfos(entityNumber, EntityTypes.Person); + Assert.NotNull(result); + Assert.AreEqual(result.Count, 1); + _mockCoreApiWrapperService.Verify(x => x.GetAgreeUsersByPersonNumber(entityNumber), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetAgreeUserByOrganizationNumber(It.IsAny()), Times.Never); + } + + [Test] + public void DeterminePrimaryOwnerNotificationInfos_Exception() + { + _mockCoreApiWrapperService.Setup(x => x.GetAgreeUserByOrganizationNumber(null)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _primaryNotificationInfoDeterminingService + .DeterminePrimaryOwnerNotificationInfos(null, EntityTypes.Organization)); + _mockCoreApiWrapperService.Verify(x => x.GetAgreeUserByOrganizationNumber(It.IsAny()), Times.Once); + _mockCoreApiWrapperService.Verify(x => x.GetAgreementByUserId(It.IsAny()), Times.Never); + _mockCoreApiWrapperService.Verify(x => x.GetAgreeUsersByPersonNumber(It.IsAny()), Times.Never); + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MemberNotificationInfoServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MemberNotificationInfoServiceTest.cs new file mode 100644 index 0000000..50e46c4 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MemberNotificationInfoServiceTest.cs @@ -0,0 +1,627 @@ +using Moq; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestorLib.Repositories; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; +using LCU.Library.Internal.Exceptions; + +namespace LCU.API.Internal.DocumentIngestorTests.Services; + +public class MemberNotificationInfoServiceTest +{ + private MemberNotificationInfoService _memberNotificationInfoService; + + private Mock _unitOfWork; + private ApiConfiguration _apiConfiguration; + private Mock _mockMemberNotificationInfoRepository; + private Mock _mockProcessingLogService; + + [SetUp] + public void Setup() + { + _unitOfWork = new Mock(); + _apiConfiguration = new ApiConfiguration { BatchSkipAmount = 10000 }; + _mockMemberNotificationInfoRepository = new Mock(); + _mockProcessingLogService = new Mock(); + + _memberNotificationInfoService = new MemberNotificationInfoService + ( + _unitOfWork.Object, + _apiConfiguration, + _mockMemberNotificationInfoRepository.Object, + _mockProcessingLogService.Object + ); + } + + [Test] + public async Task GetAsync_MemberNotificationInfos_Returned() + { + var memberNotificationInfoId = 10; + var documentProcessingInfoId = 1; + var documentProcessingInfos = new List() + { + new MemberNotificationInfo() + { + MemberNotificationInfoId = memberNotificationInfoId, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = Convert.ToDateTime("1/1/2022") + } + }; + _mockMemberNotificationInfoRepository.Setup(x => x.FindAsync()).ReturnsAsync(documentProcessingInfos); + var result = await _memberNotificationInfoService.GetAsync(); + Assert.IsNotNull(result); + Assert.AreEqual(1, result.Count()); + _mockMemberNotificationInfoRepository.Verify(x => x.FindAsync(), Times.Once); + } + + [Test] + public void GetAsync_Exception() + { + _mockMemberNotificationInfoRepository.Setup(x => x.FindAsync()).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _memberNotificationInfoService.GetAsync()); + _mockMemberNotificationInfoRepository.Verify(x => x.FindAsync(), Times.Once); + } + + [Test] + public async Task GetByIdAsync_MemberNotificationInfo_Returned() + { + var memberNotificationInfoId = 10; + var documentProcessingInfoId = 1; + var memberNotificationInfo = new MemberNotificationInfo() + { + MemberNotificationInfoId = memberNotificationInfoId, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = Convert.ToDateTime("1/1/2022") + }; + _mockMemberNotificationInfoRepository.Setup(x => x.FindByIdAsync(memberNotificationInfoId)).ReturnsAsync(memberNotificationInfo); + var result = await _memberNotificationInfoService.GetByIdAsync(memberNotificationInfoId); + Assert.IsNotNull(result); + Assert.AreEqual(documentProcessingInfoId, result.DocumentProcessingInfoId); + Assert.AreEqual(memberNotificationInfoId, result.MemberNotificationInfoId); + _mockMemberNotificationInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public void GetByIdAsync_Exception() + { + var id = 1; + _mockMemberNotificationInfoRepository.Setup(x => x.FindByIdAsync(id)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _memberNotificationInfoService.GetByIdAsync(id)); + _mockMemberNotificationInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task GetByDocumentProcessingInfoIdAsync_MemberNotificationInfos_Returned() + { + var memberNotificationInfoId = 10; + var documentProcessingInfoId = 1; + var documentProcessingInfos = new List() + { + new MemberNotificationInfo() + { + MemberNotificationInfoId = memberNotificationInfoId, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = Convert.ToDateTime("1/1/2022") + } + }; + _mockMemberNotificationInfoRepository.Setup(x => x.FindByDocumentProcessingInfoIdAsync(documentProcessingInfoId)).ReturnsAsync(documentProcessingInfos); + var result = await _memberNotificationInfoService.GetByDocumentProcessingInfoIdAsync(documentProcessingInfoId); + Assert.IsNotNull(result); + Assert.AreEqual(1, result.Count()); + _mockMemberNotificationInfoRepository.Verify(x => x.FindByDocumentProcessingInfoIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public void GetByDocumentProcessingInfoIdAsync_Exception() + { + var documentProcessingInfoId = 1; + _mockMemberNotificationInfoRepository.Setup(x => x.FindByDocumentProcessingInfoIdAsync(documentProcessingInfoId)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _memberNotificationInfoService.GetByDocumentProcessingInfoIdAsync(documentProcessingInfoId)); + _mockMemberNotificationInfoRepository.Verify(x => x.FindByDocumentProcessingInfoIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task SaveAsync_MemberNotificationInfo_Returned() + { + var memberNotificationInfoId = 10; + var documentProcessingInfoId = 1; + var memberNotificationInfo = new MemberNotificationInfo() + { + MemberNotificationInfoId = memberNotificationInfoId, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = Convert.ToDateTime("1/1/2022") + }; + _mockMemberNotificationInfoRepository.Setup(x => x.AddAsync(memberNotificationInfo)).ReturnsAsync(memberNotificationInfo); + var result = await _memberNotificationInfoService.SaveAsync(memberNotificationInfo); + Assert.IsNotNull(result); + Assert.AreEqual(documentProcessingInfoId, result.DocumentProcessingInfoId); + Assert.AreEqual(memberNotificationInfoId, result.MemberNotificationInfoId); + _mockMemberNotificationInfoRepository.Verify(x => x.AddAsync(It.IsAny()), Times.Once); + } + + [Test] + public void SaveAsync_Exception() + { + var memberNotificationInfoId = 10; + var documentProcessingInfoId = 1; + var memberNotificationInfo = new MemberNotificationInfo() + { + MemberNotificationInfoId = memberNotificationInfoId, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = Convert.ToDateTime("1/1/2022") + }; + _mockMemberNotificationInfoRepository.Setup(x => x.AddAsync(memberNotificationInfo)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _memberNotificationInfoService.SaveAsync(memberNotificationInfo)); + _mockMemberNotificationInfoRepository.Verify(x => x.AddAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task Update_MemberNotificationInfo_Returned() + { + var memberNotificationInfoId = 10; + var documentProcessingInfoId = 1; + var memberNotificationInfo = new MemberNotificationInfo() + { + MemberNotificationInfoId = memberNotificationInfoId, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = Convert.ToDateTime("1/1/2022") + }; + _mockMemberNotificationInfoRepository.Setup(x => x.Update(memberNotificationInfo)); + + var result = await _memberNotificationInfoService.Update(memberNotificationInfo); + Assert.IsNotNull(result); + Assert.AreEqual(documentProcessingInfoId, result.DocumentProcessingInfoId); + Assert.AreEqual(memberNotificationInfoId, result.MemberNotificationInfoId); + _mockMemberNotificationInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Once); + } + + [Test] + public void Update_FindByIdAsync_ThrowsException() + { + var memberNotificationInfoId = 10; + var documentProcessingInfoId = 1; + var memberNotificationInfo = new MemberNotificationInfo() + { + MemberNotificationInfoId = memberNotificationInfoId, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = Convert.ToDateTime("1/1/2022") + }; + _mockMemberNotificationInfoRepository.Setup(x => x.FindByIdAsync(memberNotificationInfoId)).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _memberNotificationInfoService.GetByIdAsync(memberNotificationInfo.MemberNotificationInfoId)); + _mockMemberNotificationInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockMemberNotificationInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Never); + } + + [Test] + public void Update_Update_ThrowsException() + { + var memberNotificationInfoId = 10; + var documentProcessingInfoId = 1; + var memberNotificationInfo = new MemberNotificationInfo() + { + MemberNotificationInfoId = memberNotificationInfoId, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = Convert.ToDateTime("1/1/2022") + }; + _mockMemberNotificationInfoRepository.Setup(x => x.Update(memberNotificationInfo)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _memberNotificationInfoService.Update(memberNotificationInfo)); + _mockMemberNotificationInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Once); + } + + [Test] + public async Task UpdateRange_MemberNotificationInfo_Returned() + { + var memberNotificationInfoId = 10; + var documentProcessingInfoId = 1; + var memberNotificationInfos = new List() + { + new() + { + MemberNotificationInfoId = memberNotificationInfoId, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = Convert.ToDateTime("1/1/2022") + } + }; + _mockMemberNotificationInfoRepository.Setup(x => x.UpdateRange(memberNotificationInfos)); + + var result = await _memberNotificationInfoService.UpdateRange(memberNotificationInfos); + Assert.IsNotNull(result); + Assert.AreEqual(documentProcessingInfoId, result.FirstOrDefault()?.DocumentProcessingInfoId); + Assert.AreEqual(memberNotificationInfoId, result.FirstOrDefault()?.MemberNotificationInfoId); + _mockMemberNotificationInfoRepository.Verify(x => x.UpdateRange(It.IsAny>()), Times.Once); + } + + [Test] + public void UpdateRange_FindByIdAsync_ThrowsException() + { + var memberNotificationInfoId = 10; + var documentProcessingInfoId = 1; + var memberNotificationInfos = new List() + { + new() + { + MemberNotificationInfoId = memberNotificationInfoId, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = Convert.ToDateTime("1/1/2022") + } + }; + _mockMemberNotificationInfoRepository.Setup(x => x.FindByIdAsync(memberNotificationInfoId)).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _memberNotificationInfoService.GetByIdAsync(memberNotificationInfoId)); + _mockMemberNotificationInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public void UpdateRange_Update_ThrowsException() + { + var memberNotificationInfoId = 10; + var documentProcessingInfoId = 1; + var memberNotificationInfos = new List() + { + new() + { + MemberNotificationInfoId = memberNotificationInfoId, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = Convert.ToDateTime("1/1/2022") + } + }; + _mockMemberNotificationInfoRepository.Setup(x => x.UpdateRange(memberNotificationInfos)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _memberNotificationInfoService.UpdateRange(memberNotificationInfos)); + _mockMemberNotificationInfoRepository.Verify(x => x.UpdateRange(It.IsAny>()), Times.Once); + } + + [Test] + public async Task Delete_Success() + { + var memberNotificationInfoId = 10; + var documentProcessingInfoId = 1; + var memberNotificationInfo = new MemberNotificationInfo() + { + MemberNotificationInfoId = memberNotificationInfoId, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = Convert.ToDateTime("1/1/2022") + }; + _mockMemberNotificationInfoRepository.Setup(x => x.FindByIdAsync(memberNotificationInfoId)).ReturnsAsync(memberNotificationInfo); + _mockMemberNotificationInfoRepository.Setup(x => x.Remove(memberNotificationInfo)); + + await _memberNotificationInfoService.Delete(memberNotificationInfoId); + _mockMemberNotificationInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockMemberNotificationInfoRepository.Verify(x => x.Remove(It.IsAny()), Times.Once); + } + + [Test] + public void Delete_FindByIdAsync_ThrowsException() + { + var id = 1; + _mockMemberNotificationInfoRepository.Setup(x => x.FindByIdAsync(id)).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _memberNotificationInfoService.Delete(id)); + _mockMemberNotificationInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockMemberNotificationInfoRepository.Verify(x => x.Remove(It.IsAny()), Times.Never); + } + + [Test] + public void Delete_Remove_ThrowsException() + { + var memberNotificationInfoId = 10; + var documentProcessingInfoId = 1; + var memberNotificationInfo = new MemberNotificationInfo() + { + MemberNotificationInfoId = memberNotificationInfoId, + DocumentProcessingInfoId = documentProcessingInfoId, + UploadDate = Convert.ToDateTime("1/1/2022") + }; + _mockMemberNotificationInfoRepository.Setup(x => x.FindByIdAsync(memberNotificationInfoId)).ReturnsAsync(memberNotificationInfo); + _mockMemberNotificationInfoRepository.Setup(x => x.Remove(memberNotificationInfo)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _memberNotificationInfoService.Delete(memberNotificationInfoId)); + _mockMemberNotificationInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockMemberNotificationInfoRepository.Verify(x => x.Remove(It.IsAny()), Times.Once); + } + + [Test] + public async Task SetDocumentNotificationStatus_NotificationInfoDoesntExist_ReturnsFalseAndDoesNotUpdateOrLog() + { + var memberNotificationInfo = new MemberNotificationInfo + { MemberNotificationInfoId = DateTime.Now.Millisecond }; + var notificationStatus = NotificationStatusTypes.CriticalFailure; + var userName = Guid.NewGuid().ToString(); + var reason = Guid.NewGuid().ToString(); + _mockMemberNotificationInfoRepository + .Setup(s => s.FindByIdAsync(memberNotificationInfo.MemberNotificationInfoId)) + .ReturnsAsync((MemberNotificationInfo)null); + + var updated = await _memberNotificationInfoService.SetDocumentNotificationStatus + ( + memberNotificationInfo.MemberNotificationInfoId, + notificationStatus, + userName, + reason + ); + + Assert.IsFalse(updated); + _mockMemberNotificationInfoRepository.Verify(r => r.Update(memberNotificationInfo), Times.Never); + _mockProcessingLogService.Verify(s => s.SaveAsync(It.IsAny()), Times.Never); + } + + [Test] + public void SetDocumentNotificationStatus_FindingNotificationInfoThrows_ThrowsServiceException() + { + var memberNotificationInfo = new MemberNotificationInfo + { MemberNotificationInfoId = DateTime.Now.Millisecond }; + var notificationStatus = NotificationStatusTypes.CriticalFailure; + var userName = Guid.NewGuid().ToString(); + var reason = Guid.NewGuid().ToString(); + _mockMemberNotificationInfoRepository + .Setup(s => s.FindByIdAsync(memberNotificationInfo.MemberNotificationInfoId)) + .ThrowsAsync(new Exception()); + + var thrown = Assert.ThrowsAsync(() => _memberNotificationInfoService.SetDocumentNotificationStatus(memberNotificationInfo.MemberNotificationInfoId, notificationStatus, userName, reason)); + + StringAssert.Contains(memberNotificationInfo.MemberNotificationInfoId.ToString(), thrown.Message); + StringAssert.Contains(notificationStatus.ToString(), thrown.Message); + } + + [Test] + public async Task SetDocumentNotificationStatus_SetStatusThrows_ThrowsServiceExceptionAndDoesNotLog() + { + var notificationStatus = NotificationStatusTypes.CriticalFailure; + var memberNotificationInfo = new MemberNotificationInfo + { + MemberNotificationInfoId = DateTime.Now.Millisecond, + DocumentProcessingInfoId = DateTime.Now.Millisecond + 1, + NotificationStatusType = notificationStatus + 1 + }; + var userName = Guid.NewGuid().ToString(); + var reason = Guid.NewGuid().ToString(); + var processingLogs = new List(); + _mockMemberNotificationInfoRepository + .Setup(s => s.FindByIdAsync(memberNotificationInfo.MemberNotificationInfoId)) + .ReturnsAsync(memberNotificationInfo); + _mockMemberNotificationInfoRepository + .Setup(r => r.Update(memberNotificationInfo)) + .Throws(new Exception()); + _mockProcessingLogService + .Setup(s => s.SaveAsync(It.IsAny())) + .Callback(processingLogs.Add); + + var thrown = Assert.ThrowsAsync(() => _memberNotificationInfoService.SetDocumentNotificationStatus(memberNotificationInfo.MemberNotificationInfoId, notificationStatus, userName, reason)); + + StringAssert.Contains(memberNotificationInfo.MemberNotificationInfoId.ToString(), thrown.Message); + StringAssert.Contains(notificationStatus.ToString(), thrown.Message); + CollectionAssert.IsEmpty(processingLogs); + } + + [Test] + public async Task SetDocumentNotificationStatus_SetStatusSuccess_LogsChange() + { + var notificationStatus = NotificationStatusTypes.CriticalFailure; + var originalNotificationStatus = notificationStatus + 1; + var memberNotificationInfo = new MemberNotificationInfo + { + MemberNotificationInfoId = DateTime.Now.Millisecond, + DocumentProcessingInfoId = DateTime.Now.Millisecond + 1, + NotificationStatusType = originalNotificationStatus + }; + var userName = Guid.NewGuid().ToString(); + var reason = Guid.NewGuid().ToString(); + var processingLogs = new List(); + _mockMemberNotificationInfoRepository + .Setup(s => s.FindByIdAsync(memberNotificationInfo.MemberNotificationInfoId)) + .ReturnsAsync(memberNotificationInfo); + _mockProcessingLogService + .Setup(s => s.SaveAsync(It.IsAny())) + .Callback(processingLogs.Add); + var testStart = DateTime.UtcNow; + + await _memberNotificationInfoService.SetDocumentNotificationStatus + ( + memberNotificationInfo.MemberNotificationInfoId, + notificationStatus, + userName, + reason + ); + + var testEnd = DateTime.UtcNow; + Assert.AreEqual(1, processingLogs.Count); + var log = processingLogs.Single(); + Assert.AreEqual(memberNotificationInfo.DocumentProcessingInfoId, log.DocumentProcessingInfoId); + Assert.That(log.LogTimeStamp, Is.InRange(testStart, testEnd)); + StringAssert.Contains(originalNotificationStatus.ToString(), log.LogMessage); + StringAssert.Contains(notificationStatus.ToString(), log.LogMessage); + StringAssert.Contains(reason, log.LogMessage); + } + + [Test] + public async Task SetDocumentNotificationStatus_LoggingChangeThrows_ThrowsServiceException() + { + var notificationStatus = NotificationStatusTypes.CriticalFailure; + var memberNotificationInfo = new MemberNotificationInfo + { + MemberNotificationInfoId = DateTime.Now.Millisecond, + NotificationStatusType = notificationStatus + 1 + }; + var userName = Guid.NewGuid().ToString(); + var reason = Guid.NewGuid().ToString(); + _mockMemberNotificationInfoRepository + .Setup(s => s.FindByIdAsync(memberNotificationInfo.MemberNotificationInfoId)) + .ReturnsAsync(memberNotificationInfo); + _mockProcessingLogService + .Setup(s => s.SaveAsync(It.IsAny())) + .ThrowsAsync(new Exception()); + + var thrown = Assert.ThrowsAsync(() => _memberNotificationInfoService.SetDocumentNotificationStatus(memberNotificationInfo.MemberNotificationInfoId, notificationStatus, userName, reason)); + + StringAssert.Contains(memberNotificationInfo.MemberNotificationInfoId.ToString(), thrown.Message); + StringAssert.Contains(notificationStatus.ToString(), thrown.Message); + } + + [Test] + public async Task SetDocumentNotificationStatus_SetStatusSuccessAndLogSuccess_ReturnsTrue() + { + var notificationStatus = NotificationStatusTypes.CriticalFailure; + var notificationInfo = new MemberNotificationInfo + { + MemberNotificationInfoId = DateTime.Now.Millisecond, + DocumentProcessingInfoId = DateTime.Now.Millisecond + 1, + NotificationStatusType = notificationStatus + }; + var newNotificationStatus = notificationStatus + 1; + var userName = Guid.NewGuid().ToString(); + var reason = Guid.NewGuid().ToString(); + var processingLogs = new List(); + _mockMemberNotificationInfoRepository + .Setup(s => s.FindByIdAsync(notificationInfo.MemberNotificationInfoId)) + .ReturnsAsync(notificationInfo); + _mockMemberNotificationInfoRepository + .Setup(r => r.Update(notificationInfo)) + .Callback(returnedUpdated => + returnedUpdated.NotificationStatusType = notificationInfo.NotificationStatusType); + _mockProcessingLogService + .Setup(s => s.SaveAsync(It.IsAny())) + .Callback(processingLogs.Add); + + var updated = await _memberNotificationInfoService.SetDocumentNotificationStatus + ( + notificationInfo.MemberNotificationInfoId, + newNotificationStatus, + userName, + reason + ); + + Assert.IsTrue(updated); + Assert.AreEqual(newNotificationStatus, notificationInfo.NotificationStatusType); + Assert.AreEqual(1, processingLogs.Count); + } + + [Test] + public async Task BulkSetDocumentNotificationStatus_Success() + { + var notificationInfos = new List + { + new() + { + DocumentProcessingInfoId = DateTime.Now.Millisecond, + NotificationStatusType = NotificationStatusTypes.CriticalFailure + }, + new() + { + DocumentProcessingInfoId = DateTime.Now.Millisecond + 1, + NotificationStatusType = NotificationStatusTypes.CriticalFailure + }, + }; + + var request = new BulkNotificationStatusRequest + { + Filter = new() + { + NotificationStatusFilters = new List + { + NotificationStatusTypes.CriticalFailure + } + }, + NotificationStatus = NotificationStatusTypes.Complete, + ReasonMessage = Guid.NewGuid().ToString() + }; + var userName = Guid.NewGuid().ToString(); + + _mockMemberNotificationInfoRepository + .Setup(s => s.GetMemberNotificationInfosByFilter(request.Filter)) + .ReturnsAsync(notificationInfos); + _mockMemberNotificationInfoRepository + .Setup(r => r.UpdateRange(notificationInfos)); + _mockProcessingLogService + .Setup(s => s.SaveRangeAsync(It.IsAny>())); + + var updated = await _memberNotificationInfoService.BulkSetDocumentNotificationStatus(request, userName); + + Assert.IsTrue(updated); + Assert.AreEqual(request.NotificationStatus, notificationInfos[0].NotificationStatusType); + Assert.AreEqual(request.NotificationStatus, notificationInfos[1].NotificationStatusType); + + _mockMemberNotificationInfoRepository.Verify(x => x.GetMemberNotificationInfosByFilter(It.IsAny()), Times.Once); + _mockMemberNotificationInfoRepository.Verify(x => x.UpdateRange(It.IsAny>()), Times.Once); + _mockProcessingLogService.Verify(x => x.SaveRangeAsync(It.IsAny>()), Times.Once); + } + + [Test] + public async Task BulkSetDocumentNotificationStatus_Bulk_Success() + { + var repeatAmount = 15000; + var randomInt = new Random(); + var notificationInfos = Enumerable.Repeat(1, repeatAmount) + .Select(_ => new MemberNotificationInfo + { + DocumentProcessingInfoId = randomInt.Next(1, repeatAmount), + NotificationStatusType = NotificationStatusTypes.CriticalFailure + }).ToList(); + + var request = new BulkNotificationStatusRequest + { + Filter = new() + { + NotificationStatusFilters = new List + { + NotificationStatusTypes.CriticalFailure + } + }, + NotificationStatus = NotificationStatusTypes.Complete, + ReasonMessage = Guid.NewGuid().ToString() + }; + var userName = Guid.NewGuid().ToString(); + + _mockMemberNotificationInfoRepository + .Setup(s => s.GetMemberNotificationInfosByFilter(request.Filter)) + .ReturnsAsync(notificationInfos); + _mockMemberNotificationInfoRepository.Setup(s => + s.UpdateRange(It.IsAny>())); + _mockProcessingLogService + .Setup(s => s.SaveRangeAsync(It.IsAny>())); + + Assert.IsTrue(await _memberNotificationInfoService.BulkSetDocumentNotificationStatus(request, userName)); + + _mockMemberNotificationInfoRepository.Verify(x => x.GetMemberNotificationInfosByFilter(It.IsAny()), Times.Once); + _mockMemberNotificationInfoRepository.Verify(x => x.UpdateRange(It.IsAny>()), Times.Exactly(2)); + _mockProcessingLogService.Verify(x => x.SaveRangeAsync(It.IsAny>()), Times.Exactly(2)); + } + + [Test] + public Task BulkSetDocumentNotificationStatus_Failure_ServiceException() + { + var request = new BulkNotificationStatusRequest + { + Filter = new() + { + NotificationStatusFilters = new List + { + NotificationStatusTypes.CriticalFailure + } + }, + NotificationStatus = NotificationStatusTypes.Complete, + ReasonMessage = Guid.NewGuid().ToString() + }; + var userName = Guid.NewGuid().ToString(); + + _mockMemberNotificationInfoRepository + .Setup(s => s.GetMemberNotificationInfosByFilter(request.Filter)) + .ThrowsAsync(new Exception()); + + Assert.ThrowsAsync(() => _memberNotificationInfoService.BulkSetDocumentNotificationStatus(request, userName)); + + _mockMemberNotificationInfoRepository.Verify(x => x.GetMemberNotificationInfosByFilter(It.IsAny()), Times.Once); + _mockMemberNotificationInfoRepository.Verify(x => x.UpdateRange(It.IsAny>()), Times.Never); + _mockProcessingLogService.Verify(x => x.SaveRangeAsync(It.IsAny>()), Times.Never); + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/CoreApiWrapperServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/CoreApiWrapperServiceTest.cs new file mode 100644 index 0000000..f1feae6 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/CoreApiWrapperServiceTest.cs @@ -0,0 +1,293 @@ +using System; +using System.Linq; +using System.Collections.Generic; +using System.Threading.Tasks; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Tax; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.DataAccess; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.MemberAgreements; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Agreements; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.MicroApiServices; + +public class CoreApiWrapperServiceTest +{ + private CoreApiWrapperService _coreApiWrapperService; + private Mock _mockCoreApiWrapperDao; + + [SetUp] + public void Setup() + { + _mockCoreApiWrapperDao = new Mock(); + _coreApiWrapperService = new CoreApiWrapperService(_mockCoreApiWrapperDao.Object); + } + + [Test] + public void GetPersonsTaxIdData_Exception() + { + _mockCoreApiWrapperDao.Setup(x => x.GetPersonsTaxIdData(It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _coreApiWrapperService.GetPersonsTaxIdData("12")); + _mockCoreApiWrapperDao.Verify(x => x.GetPersonsTaxIdData(It.IsAny()), Times.Once); + } + + [Test] + public async Task GetUserIdByOrganizationNumber_Return() + { + var personTaxIdDataResponse = new List() + { + new PersonTaxIdDataResponse() + { + PersonNumber = 1 + }, + new PersonTaxIdDataResponse() + { + PersonNumber = 2 + } + }; + _mockCoreApiWrapperDao.Setup(x => x.GetPersonsTaxIdData(It.IsAny())).ReturnsAsync(personTaxIdDataResponse); + + var response = await _coreApiWrapperService.GetPersonsTaxIdData("12"); + Assert.IsNotNull(response); + Assert.AreEqual(2, response.ToList().Count); + _mockCoreApiWrapperDao.Verify(x => x.GetPersonsTaxIdData(It.IsAny()), Times.Once); + } + + [Test] + public void GetOrganizationsTaxIdData_Exception() + { + _mockCoreApiWrapperDao.Setup(x => x.GetOrganizationsTaxIdData(It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _coreApiWrapperService.GetOrganizationsTaxIdData("12")); + _mockCoreApiWrapperDao.Verify(x => x.GetOrganizationsTaxIdData(It.IsAny()), Times.Once); + } + + [Test] + public async Task GetOrganizationsTaxIdData_Return() + { + var personTaxIdDataResponse = new List() + { + new OrganizationTaxIdDataResponse() + { + OrganizationNumber = 1 + }, + new OrganizationTaxIdDataResponse() + { + OrganizationNumber = 2 + } + }; + _mockCoreApiWrapperDao.Setup(x => x.GetOrganizationsTaxIdData(It.IsAny())).ReturnsAsync(personTaxIdDataResponse); + + var response = await _coreApiWrapperService.GetOrganizationsTaxIdData("12"); + Assert.IsNotNull(response); + Assert.AreEqual(2, response.ToList().Count); + _mockCoreApiWrapperDao.Verify(x => x.GetOrganizationsTaxIdData(It.IsAny()), Times.Once); + } + + [Test] + public async Task GetOwnersByAccountNumber_Return() + { + var accountOwnershipsResponse = new List() + { + new AccountOwnership() + { + PersonNumber = 1 + }, + new AccountOwnership() + { + PersonNumber = 2 + } + }; + _mockCoreApiWrapperDao.Setup(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny())).ReturnsAsync(accountOwnershipsResponse); + + var response = await _coreApiWrapperService.GetOwnersByAccountNumber("12", "01022022"); + Assert.IsNotNull(response); + Assert.AreEqual(2, response.ToList().Count); + _mockCoreApiWrapperDao.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public void GetOwnersByAccountNumber_Exception() + { + _mockCoreApiWrapperDao.Setup(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _coreApiWrapperService.GetOwnersByAccountNumber("12", "01022022")); + _mockCoreApiWrapperDao.Verify(x => x.GetOwnersByAccountNumber(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task GetOwnersByPersonName_Return() + { + var accountOwnershipsResponse = new List() + { + new AccountOwnership() + { + PersonNumber = 1 + }, + new AccountOwnership() + { + PersonNumber = 2 + } + }; + _mockCoreApiWrapperDao.Setup(x => x.GetOwnersByPersonName(It.IsAny())).ReturnsAsync(accountOwnershipsResponse); + + var response = await _coreApiWrapperService.GetOwnersByPersonName("Test Tester"); + Assert.IsNotNull(response); + Assert.AreEqual(2, response.ToList().Count); + _mockCoreApiWrapperDao.Verify(x => x.GetOwnersByPersonName(It.IsAny()), Times.Once); + } + + [Test] + public void GetOwnersByPersonName_Exception() + { + _mockCoreApiWrapperDao.Setup(x => x.GetOwnersByPersonName(It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _coreApiWrapperService.GetOwnersByPersonName("Test Tester")); + _mockCoreApiWrapperDao.Verify(x => x.GetOwnersByPersonName(It.IsAny()), Times.Once); + } + + [Test] + public async Task GetOwnersByOrganizationName_Return() + { + var accountOwnershipsResponse = new List() + { + new AccountOwnership() + { + PersonNumber = 1 + }, + new AccountOwnership() + { + PersonNumber = 2 + } + }; + _mockCoreApiWrapperDao.Setup(x => x.GetOwnersByOrganizationName(It.IsAny())).ReturnsAsync(accountOwnershipsResponse); + + var response = await _coreApiWrapperService.GetOwnersByOrganizationName("Test Company"); + Assert.IsNotNull(response); + Assert.AreEqual(2, response.ToList().Count); + _mockCoreApiWrapperDao.Verify(x => x.GetOwnersByOrganizationName(It.IsAny()), Times.Once); + } + + [Test] + public void GetOwnersByOrganization_Exception() + { + _mockCoreApiWrapperDao.Setup(x => x.GetOwnersByOrganizationName(It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _coreApiWrapperService.GetOwnersByOrganizationName("Test Company")); + _mockCoreApiWrapperDao.Verify(x => x.GetOwnersByOrganizationName(It.IsAny()), Times.Once); + } + + [Test] + public async Task GetAgreeUsersByAccount_Return() + { + var returnAgreeUserAccounts = new List + { + new AgreeUserAccount + { + UserId = "1" + } + }; + _mockCoreApiWrapperDao.Setup(x => x.GetAgreeUsersByAccount(It.IsAny())).ReturnsAsync(returnAgreeUserAccounts); + + var response = await _coreApiWrapperService.GetAgreeUsersByAccount("11"); + Assert.IsNotNull(response); + var firstAgreeUserAccount = response.FirstOrDefault(); + Assert.IsNotNull(firstAgreeUserAccount); + Assert.AreEqual("1", firstAgreeUserAccount?.UserId); + _mockCoreApiWrapperDao.Verify(x => x.GetAgreeUsersByAccount(It.IsAny()), Times.Once); + } + + [Test] + public void GetAgreeUsersByAccount_Exception() + { + _mockCoreApiWrapperDao.Setup(x => x.GetAgreeUsersByAccount(It.IsAny())).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _coreApiWrapperService.GetAgreeUsersByAccount("11")); + _mockCoreApiWrapperDao.Verify(x => x.GetAgreeUsersByAccount(It.IsAny()), Times.Once); + } + + [Test] + public async Task GetAgreeUsersByPersonNumber_Return() + { + var userIds = new List { "1", "2" }; + _mockCoreApiWrapperDao.Setup(x => x.GetAgreeUsersByPersonNumber(It.IsAny())).ReturnsAsync(userIds); + + var response = await _coreApiWrapperService.GetAgreeUsersByPersonNumber("11"); + Assert.IsNotNull(response); + Assert.AreEqual(2, response.ToList().Count); + _mockCoreApiWrapperDao.Verify(x => x.GetAgreeUsersByPersonNumber(It.IsAny()), Times.Once); + } + + [Test] + public void GetAgreeUsersByPersonNumber_Exception() + { + _mockCoreApiWrapperDao.Setup(x => x.GetAgreeUsersByPersonNumber(It.IsAny())).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _coreApiWrapperService.GetAgreeUsersByPersonNumber("11")); + _mockCoreApiWrapperDao.Verify(x => x.GetAgreeUsersByPersonNumber(It.IsAny()), Times.Once); + } + + [Test] + public async Task GetAgreeUserByOrganizationNumber_Return() + { + var userIds = "1"; + _mockCoreApiWrapperDao.Setup(x => x.GetAgreeUserByOrganizationNumber(It.IsAny())).ReturnsAsync(userIds); + + var response = await _coreApiWrapperService.GetAgreeUserByOrganizationNumber("11"); + Assert.IsNotNull(response); + Assert.AreEqual("1", response); + _mockCoreApiWrapperDao.Verify(x => x.GetAgreeUserByOrganizationNumber(It.IsAny()), Times.Once); + } + + [Test] + public void GetAgreeUserByOrganizationNumber_Exception() + { + _mockCoreApiWrapperDao.Setup(x => x.GetAgreeUserByOrganizationNumber(It.IsAny())).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _coreApiWrapperService.GetAgreeUserByOrganizationNumber("11")); + _mockCoreApiWrapperDao.Verify(x => x.GetAgreeUserByOrganizationNumber(It.IsAny()), Times.Once); + } + + [Test] + public async Task GetAgreementAccountsByUserId_Return() + { + var agreementAccounts = new List() + { + new () + { + AccountNumber = 1, + AccountDescription = "test", + TaxReportForPersonNumber = 2 + } + }; + + _mockCoreApiWrapperDao.Setup(x => x.GetAgreementAccountsByUserId(It.IsAny())).ReturnsAsync(agreementAccounts); + + var response = await _coreApiWrapperService.GetAgreementAccountsByUserId(It.IsAny()); + var result = response as List; + var first = result.FirstOrDefault(); + Assert.IsNotNull(response); + Assert.AreEqual(1, first?.AccountNumber); + Assert.AreEqual("test", first?.AccountDescription); + Assert.AreEqual(2, first?.TaxReportForPersonNumber); + _mockCoreApiWrapperDao.Verify(x => x.GetAgreementAccountsByUserId(It.IsAny()), Times.Once); + } + + [Test] + public void GetAgreementAccountsByUserId_Exception() + { + _mockCoreApiWrapperDao.Setup(x => x.GetAgreementAccountsByUserId(It.IsAny())).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _coreApiWrapperService.GetAgreementAccountsByUserId("11")); + _mockCoreApiWrapperDao.Verify(x => x.GetAgreementAccountsByUserId(It.IsAny()), Times.Once); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/DocumentTypeRetrieverApiServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/DocumentTypeRetrieverApiServiceTest.cs new file mode 100644 index 0000000..0df9b41 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/DocumentTypeRetrieverApiServiceTest.cs @@ -0,0 +1,106 @@ +using LCU.API.Internal.DocumentIngestor.DataAccess; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.DocumentType.Models.Requests; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +using Microsoft.Extensions.Caching.Memory; +using Moq; +using NUnit.Framework; +using System; +using System.Threading.Tasks; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.MicroApiServices; + +public class DocumentTypeRetrieverApiServiceTest +{ + private DocumentTypeRetrieverService _documentTypeRetrieverApiService; + private Mock _mockDocumentTypeRetrieverDao; + + [SetUp] + public void Setup() + { + _mockDocumentTypeRetrieverDao = new Mock(); + _documentTypeRetrieverApiService = new DocumentTypeRetrieverService(_mockDocumentTypeRetrieverDao.Object); + } + + [Test] + public async Task GetDocumentCodeDetail_Success() + { + var documentCode = "LnNent"; + _mockDocumentTypeRetrieverDao.Setup(x => x.GetDocumentCodeDetail(It.IsAny())); + + await _documentTypeRetrieverApiService.GetDocumentCodeDetail(documentCode); + _mockDocumentTypeRetrieverDao.Verify(x => x.GetDocumentCodeDetail(It.IsAny()), Times.Once); + } + + [Test] + public void GetDocumentCodeDetail_Exception() + { + var documentCode = "LnNent"; + _mockDocumentTypeRetrieverDao.Setup(x => x.GetDocumentCodeDetail(It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _documentTypeRetrieverApiService.GetDocumentCodeDetail(documentCode)); + _mockDocumentTypeRetrieverDao.Verify(x => x.GetDocumentCodeDetail(It.IsAny()), Times.Once); + } + + [Test] + public async Task GetDocumentCodeDetails_Success() + { + _mockDocumentTypeRetrieverDao.Setup(x => x.GetDocumentCodeDetails()); + + await _documentTypeRetrieverApiService.GetDocumentCodeDetails(); + _mockDocumentTypeRetrieverDao.Verify(x => x.GetDocumentCodeDetails(), Times.Once); + } + + [Test] + public void GetDocumentCodeDetails_Exception() + { + _mockDocumentTypeRetrieverDao.Setup(x => x.GetDocumentCodeDetails()) + .ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _documentTypeRetrieverApiService.GetDocumentCodeDetails()); + _mockDocumentTypeRetrieverDao.Verify(x => x.GetDocumentCodeDetails(), Times.Once); + } + + [Test] + public async Task GetDocumentCodeDetailsCache_Success() + { + _mockDocumentTypeRetrieverDao.Setup(x => x.GetDocumentCodeDetailsCache()); + + await _documentTypeRetrieverApiService.GetDocumentCodeDetailByDisplayName(It.IsAny()); + _mockDocumentTypeRetrieverDao.Verify(x => x.GetDocumentCodeDetailsCache(), Times.Once); + } + + [Test] + public void GetDocumentCodeDetailsCache_Exception() + { + _mockDocumentTypeRetrieverDao.Setup(x => x.GetDocumentCodeDetailsCache()) + .ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _documentTypeRetrieverApiService + .GetDocumentCodeDetailByDisplayName(It.IsAny())); + _mockDocumentTypeRetrieverDao.Verify(x => x.GetDocumentCodeDetailsCache(), Times.Once); + } + + [Test] + public async Task GetListOfMaliciousDocuments_Success() + { + var filter = new MaliciousDocumentSearchFilter(); + _mockDocumentTypeRetrieverDao.Setup(x => x.GetListOfMaliciousDocuments(It.IsAny())); + + await _documentTypeRetrieverApiService.GetListOfMaliciousDocuments(filter); + _mockDocumentTypeRetrieverDao.Verify(x => x.GetListOfMaliciousDocuments(It.IsAny()), Times.Once); + } + + [Test] + public void GetListOfMaliciousDocuments_Exception() + { + var filter = new MaliciousDocumentSearchFilter(); + _mockDocumentTypeRetrieverDao.Setup(x => x.GetListOfMaliciousDocuments(It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _documentTypeRetrieverApiService.GetListOfMaliciousDocuments(filter)); + _mockDocumentTypeRetrieverDao.Verify(x => x.GetListOfMaliciousDocuments(It.IsAny()), Times.Once); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/DocumentTypeUploaderApiServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/DocumentTypeUploaderApiServiceTest.cs new file mode 100644 index 0000000..e0ece65 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/DocumentTypeUploaderApiServiceTest.cs @@ -0,0 +1,116 @@ +using System.Threading.Tasks; +using System; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.Exceptions; +using LCU.Library.DocumentType.Models.Requests.PrimaryOwner; +using LCU.Library.DocumentType.Models.Requests.Account; +using LCU.Library.Internal.LcuMassTransitModels; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.DataAccess; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.DocumentType.Models.Requests.Attributes; +using LCU.Library.DocumentType.Models.Requests.Generic; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.MicroApiServices; + +public class DocumentTypeUploaderApiServiceTest +{ + private DocumentTypeUploaderApiService _documentTypeUploaderApiService; + private Mock _mockDocumentTypeUploaderApiDao; + + [SetUp] + public void Setup() + { + var connectionConfiguration = new ConnectionConfiguration() + { + HostUrl = "Test", + UserName = "Test", + Password = "Test" + }; + var receiveEndpointConfigurations = new ReceiveEndpointConfigurations() + { + UploadCompletionEndpoint = new ReceiveEndpointConfiguration() + { + ReceiveEndpoint = "Test", + ReceiveEndpointType = "Exchange", + PrefetchLimit = 1 + } + }; + _mockDocumentTypeUploaderApiDao = new Mock(); + _documentTypeUploaderApiService = new DocumentTypeUploaderApiService(_mockDocumentTypeUploaderApiDao.Object, + connectionConfiguration, + receiveEndpointConfigurations); + } + + [Test] + public void UploadPrimaryOwnerDocument_Exception() + { + _mockDocumentTypeUploaderApiDao.Setup(x => x.UploadPrimaryOwnerDocument(It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var request = new PrimaryOwnerDocumentRequest + { + PrimaryOwnerAttribute = new PrimaryOwnerAttribute + { + PersonNumber = "1" + } + }; + var processRequest = new ProcessingRequest(); + var processResult = new ProcessResult(); + Assert.ThrowsAsync(async () => await _documentTypeUploaderApiService.UploadPrimaryOwnerDocument(request, processRequest, processResult)); + _mockDocumentTypeUploaderApiDao.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny()), Times.Once); + } + + [Test] + public void UploadAccountOwnerDocument_Exception() + { + _mockDocumentTypeUploaderApiDao.Setup(x => x.UploadAccountDocument(It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var request = new AccountDocumentRequest + { + AccountAttribute = new AccountAttribute + { + AccountNumber = "1" + } + }; + var processRequest = new ProcessingRequest(); + var processResult = new ProcessResult(); + Assert.ThrowsAsync(async () => await _documentTypeUploaderApiService.UploadAccountDocument(request, processRequest, processResult)); + _mockDocumentTypeUploaderApiDao.Verify(x => x.UploadAccountDocument(It.IsAny()), Times.Once); + } + + + [Test] + public void UploadGenericDocument_Exception() + { + _mockDocumentTypeUploaderApiDao.Setup(x => x.UploadGenericDocument(It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var request = new GenericDocumentRequest(); + var processRequest = new ProcessingRequest(); + var processResult = new ProcessResult(); + Assert.ThrowsAsync(async () => await _documentTypeUploaderApiService.UploadGenericDocument(request, processRequest, processResult)); + _mockDocumentTypeUploaderApiDao.Verify(x => x.UploadGenericDocument(It.IsAny()), Times.Once); + } + + [Test] + public async Task GetUserIdByOrganizationNumber_Return() + { + _mockDocumentTypeUploaderApiDao.Setup(x => x.UploadPrimaryOwnerDocument(It.IsAny())); + + var request = new PrimaryOwnerDocumentRequest + { + PrimaryOwnerAttribute = new PrimaryOwnerAttribute + { + PersonNumber = "1" + } + }; + var processRequest = new ProcessingRequest(); + var processResult = new ProcessResult(); + await _documentTypeUploaderApiService.UploadPrimaryOwnerDocument(request, processRequest, processResult); + _mockDocumentTypeUploaderApiDao.Verify(x => x.UploadPrimaryOwnerDocument(It.IsAny()), Times.Once); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/FileOperationsApiServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/FileOperationsApiServiceTest.cs new file mode 100644 index 0000000..5af2669 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/FileOperationsApiServiceTest.cs @@ -0,0 +1,358 @@ +using System; +using System.Text; +using System.Threading.Tasks; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.LcuMassTransitModels; +using LCU.Library.Internal.DocumentIngestorModels.Models; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.DataAccess; +using LCU.Library.Internal.FileOperationsModels.Models; +namespace LCU.API.Internal.DocumentIngestorTests.Services.MicroApiServices; + +public class FileOperationsApiServiceTest +{ + private FileOperationsApiService _fileOperationsApiService; + private Mock _mockFileOperationsApiDao; + + [SetUp] + public void Setup() + { + _mockFileOperationsApiDao = new Mock(); + _fileOperationsApiService = new FileOperationsApiService(_mockFileOperationsApiDao.Object); + } + + [Test] + public void DirectMoveFile_Exception() + { + _mockFileOperationsApiDao.Setup(x => x.DirectMoveFile(It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var path = "\\path\\"; + var file = "file.pdf"; + var destination = "\\destination\\"; + var completionRequest = new CompletionRequest(); + Assert.ThrowsAsync(async () => await _fileOperationsApiService.DirectMoveFile(path, file, destination)); + _mockFileOperationsApiDao.Verify(x => x.DirectMoveFile(It.IsAny()), Times.Once); + } + + [Test] + public async Task DirectMoveFile_Success() + { + _mockFileOperationsApiDao.Setup(x => x.DirectMoveFile(It.IsAny())); + + var path = "\\path\\"; + var file = "file.pdf"; + var destination = "\\destination\\"; + var completionRequest = new CompletionRequest(); + await _fileOperationsApiService.DirectMoveFile(path, file, destination); + _mockFileOperationsApiDao.Verify(x => x.DirectMoveFile(It.IsAny()), Times.Once); + } + + [Test] + public void DirectWriteFile_Exception() + { + _mockFileOperationsApiDao.Setup(x => x.DirectWriteFile(It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var fileName = "file"; + var extension = ".csv"; + var fileData = "testFile"; + var destination = "\\destination\\"; + Assert.ThrowsAsync(async () => await _fileOperationsApiService.DirectWriteFile(fileName, extension, fileData, destination)); + _mockFileOperationsApiDao.Verify(x => x.DirectWriteFile(It.IsAny()), Times.Once); + } + + [Test] + public async Task DirectWriteFile_Success() + { + _mockFileOperationsApiDao.Setup(x => x.DirectWriteFile(It.IsAny())); + + var fileName = "file"; + var extension = ".csv"; + var fileData = "testFile"; + var destination = "\\destination\\"; + await _fileOperationsApiService.DirectWriteFile(fileName, extension, fileData, destination); + _mockFileOperationsApiDao.Verify(x => x.DirectWriteFile(It.IsAny()), Times.Once); + } + + [Test] + public void DirectCreateDirectory_Exception() + { + _mockFileOperationsApiDao.Setup(x => x.DirectCreateDirectory(It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var directoryPath = "\\path\\"; + var directoryName = "newFolder"; + Assert.ThrowsAsync(async () => await _fileOperationsApiService.DirectCreateDirectory(directoryPath, directoryName)); + _mockFileOperationsApiDao.Verify(x => x.DirectCreateDirectory(It.IsAny()), Times.Once); + } + + [Test] + public async Task DirectCreateDirectory_Success() + { + _mockFileOperationsApiDao.Setup(x => x.DirectCreateDirectory(It.IsAny())); + + var directoryPath = "\\path\\"; + var directoryName = "newFolder"; + await _fileOperationsApiService.DirectCreateDirectory(directoryPath, directoryName); + _mockFileOperationsApiDao.Verify(x => x.DirectCreateDirectory(It.IsAny()), Times.Once); + } + + [Test] + public void DirectUnzipFile_Exception() + { + _mockFileOperationsApiDao.Setup(x => x.DirectUnzipFile(It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var sourceDirectory = "\\oldPath\\"; + var destinationPath = "\\newPath\\"; + var zipFileName = "newFolder"; + Assert.ThrowsAsync(async () => await _fileOperationsApiService.DirectUnzipFile(sourceDirectory, zipFileName, destinationPath, true)); + _mockFileOperationsApiDao.Verify(x => x.DirectUnzipFile(It.IsAny()), Times.Once); + } + + [Test] + public async Task DirectUnzipFile_Success() + { + _mockFileOperationsApiDao.Setup(x => x.DirectUnzipFile(It.IsAny())); + + var sourceDirectory = "\\oldPath\\"; + var destinationPath = "\\newPath\\"; + var zipFileName = "newFolder"; + await _fileOperationsApiService.DirectUnzipFile(sourceDirectory, zipFileName, destinationPath, true); + _mockFileOperationsApiDao.Verify(x => x.DirectUnzipFile(It.IsAny()), Times.Once); + } + + [Test] + public void DirectZipDirectory_Exception() + { + _mockFileOperationsApiDao.Setup(x => x.DirectZipDirectory(It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var sourceDirectory = "\\oldPath\\"; + var zipPath = "\\newPath\\"; + var zipFileName = "newFolder"; + Assert.ThrowsAsync(async () => await _fileOperationsApiService.DirectZipDirectory(sourceDirectory, zipPath, zipFileName)); + _mockFileOperationsApiDao.Verify(x => x.DirectZipDirectory(It.IsAny()), Times.Once); + } + + [Test] + public async Task DirectZipDirectory_Success() + { + _mockFileOperationsApiDao.Setup(x => x.DirectZipDirectory(It.IsAny())); + + var sourceDirectory = "\\oldPath\\"; + var zipPath = "\\newPath\\"; + var zipFileName = "newFolder"; + await _fileOperationsApiService.DirectZipDirectory(sourceDirectory, zipPath, zipFileName); + _mockFileOperationsApiDao.Verify(x => x.DirectZipDirectory(It.IsAny()), Times.Once); + } + + + [Test] + public void DirectDeleteDirectory_Exception() + { + _mockFileOperationsApiDao.Setup(x => x.DirectDeleteDirectory(It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var directoryName = "folder"; + var directoryRootPath = "\\testPath\\"; + var maxAmountOfDirectories = 1; + Assert.ThrowsAsync(async () => await _fileOperationsApiService.DirectDeleteDirectory(directoryName, directoryRootPath, maxAmountOfDirectories)); + _mockFileOperationsApiDao.Verify(x => x.DirectDeleteDirectory(It.IsAny()), Times.Once); + } + + [Test] + public async Task DirectDeleteDirectory_Success() + { + _mockFileOperationsApiDao.Setup(x => x.DirectDeleteDirectory(It.IsAny())); + + var directoryName = "folder"; + var directoryRootPath = "\\testPath\\"; + var maxAmountOfDirectories = 1; + await _fileOperationsApiService.DirectDeleteDirectory(directoryName, directoryRootPath, maxAmountOfDirectories); + _mockFileOperationsApiDao.Verify(x => x.DirectDeleteDirectory(It.IsAny()), Times.Once); + } + + [Test] + public void GetFileContent_Exception() + { + _mockFileOperationsApiDao.Setup(x => x.GetFileContent(It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var filePath = "\\path\\file.pdf"; + Assert.ThrowsAsync(async () => + await _fileOperationsApiService.GetFileContent(filePath)); + _mockFileOperationsApiDao.Verify(x => x.GetFileContent(It.IsAny()), Times.Once); + } + + [Test] + public async Task GetFileContent_Success() + { + var content = "test, test, test"; + _mockFileOperationsApiDao.Setup(x => x.GetFileContent(It.IsAny())).ReturnsAsync(content); + + var filePath = "\\path\\file.pdf"; + var result = await _fileOperationsApiService.GetFileContent(filePath); + Assert.AreEqual(content, result); + _mockFileOperationsApiDao.Verify(x => x.GetFileContent(It.IsAny()), Times.Once); + } + + + [Test] + public void GetContentBytes_Exception() + { + _mockFileOperationsApiDao.Setup(x => x.GetPdfByteContent(It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var documentPath = "\\path\\"; + var documentFileName = "file.pdf"; + Assert.ThrowsAsync(async () => + await _fileOperationsApiService.GetContentBytes(documentPath, documentFileName)); + _mockFileOperationsApiDao.Verify(x => x.GetPdfByteContent(It.IsAny()), Times.Once); + } + + [Test] + public async Task GetContentBytes_Success() + { + var content = "test, test, test"; + var contentBytes = Encoding.ASCII.GetBytes(content); + _mockFileOperationsApiDao.Setup(x => x.GetPdfByteContent(It.IsAny())).ReturnsAsync(contentBytes); + + var documentPath = "\\path\\"; + var documentFileName = "file.pdf"; + var result = await _fileOperationsApiService.GetContentBytes(documentPath, documentFileName); + Assert.AreEqual(contentBytes, result); + _mockFileOperationsApiDao.Verify(x => x.GetPdfByteContent(It.IsAny()), Times.Once); + } + + [Test] + public void ValidateFileExists_Exception() + { + _mockFileOperationsApiDao.Setup(x => x.ValidateFileExists(It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var filePath = "\\path\\file.pdf"; + Assert.ThrowsAsync(async () => + await _fileOperationsApiService.ValidateFileExists(filePath)); + _mockFileOperationsApiDao.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Once); + } + + [Test] + public async Task ValidateFileExists_Success() + { + _mockFileOperationsApiDao.Setup(x => x.ValidateFileExists(It.IsAny())).ReturnsAsync(true); + + var filePath = "\\path\\file.pdf"; + var result = await _fileOperationsApiService.ValidateFileExists(filePath); + Assert.IsTrue(result); + _mockFileOperationsApiDao.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Once); + } + + [Test] + public void ValidateFileExistsAndNotArchived_ValidateFileExists_FilePath_Exception() + { + var filePath = "\\path\\file.pdf"; + var archiveFilePath = "\\path\\archive\\file.pdf"; + _mockFileOperationsApiDao.Setup(x => x.ValidateFileExists(filePath)) + .ThrowsAsync(new Exception("Error")); + + + Assert.ThrowsAsync(async () => + await _fileOperationsApiService.ValidateFileExistsAndNotArchived(filePath, archiveFilePath)); + _mockFileOperationsApiDao.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Once); + } + + [Test] + public void ValidateFileExistsAndNotArchived_ValidateFileExists_ArchiveFilePath_Exception() + { + var filePath = "\\path\\file.pdf"; + var archiveFilePath = "\\path\\archive\\file.pdf"; + _mockFileOperationsApiDao.Setup(x => x.ValidateFileExists(filePath)).ReturnsAsync(false); + + _mockFileOperationsApiDao.Setup(x => x.ValidateFileExists(archiveFilePath)) + .ThrowsAsync(new Exception("Error")); + + + Assert.ThrowsAsync(async () => + await _fileOperationsApiService.ValidateFileExistsAndNotArchived(filePath, archiveFilePath)); + _mockFileOperationsApiDao.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Exactly(2)); + } + + [Test] + public async Task ValidateFileExistsAndNotArchived_True() + { + var filePath = "\\path\\file.pdf"; + var archiveFilePath = "\\path\\archive\\file.pdf"; + _mockFileOperationsApiDao.Setup(x => x.ValidateFileExists(filePath)).ReturnsAsync(true); + + var result = await _fileOperationsApiService.ValidateFileExistsAndNotArchived(filePath, archiveFilePath); + Assert.IsTrue(result); + _mockFileOperationsApiDao.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Once); + } + + [Test] + public async Task ValidateFileExistsAndNotArchived_False() + { + var filePath = "\\path\\file.pdf"; + var archiveFilePath = "\\path\\archive\\file.pdf"; + _mockFileOperationsApiDao.Setup(x => x.ValidateFileExists(filePath)).ReturnsAsync(false); + + _mockFileOperationsApiDao.Setup(x => x.ValidateFileExists(archiveFilePath)).ReturnsAsync(true); + + + var result = await _fileOperationsApiService.ValidateFileExistsAndNotArchived(filePath, archiveFilePath); + Assert.IsFalse(result); + _mockFileOperationsApiDao.Verify(x => x.ValidateFileExists(It.IsAny()), Times.Exactly(2)); + } + + [Test] + public async Task ValidatePdfPageExists_Success() + { + var requestResponse = new RequestResponse() + { + IsSuccessful = true + }; + _mockFileOperationsApiDao.Setup(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse); + + var filePath = "\\path\\file.pdf"; + var result = await _fileOperationsApiService.ValidatePdfPageExists(filePath, "5"); + _mockFileOperationsApiDao.Verify(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public void ValidatePdfPageExists_Exception() + { + _mockFileOperationsApiDao.Setup(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var filePath = "\\path\\file.pdf"; + Assert.ThrowsAsync(async () => + await _fileOperationsApiService.ValidatePdfPageExists(filePath, "5")); + _mockFileOperationsApiDao.Verify(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny()), Times.Once); + } + + [Test] + public async Task QueueBatchPdfParser_Success() + { + _mockFileOperationsApiDao.Setup(x => x.QueueBatchPdfParser(It.IsAny())); + + var batchParsePdfRequest = new BatchParsePdfRequest(); + await _fileOperationsApiService.QueueBatchPdfParser(batchParsePdfRequest); + _mockFileOperationsApiDao.Verify(x => x.QueueBatchPdfParser(It.IsAny()), Times.Once); + } + + [Test] + public void QueueBatchPdfParser_Exception() + { + _mockFileOperationsApiDao.Setup(x => x.QueueBatchPdfParser(It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var batchParsePdfRequest = new BatchParsePdfRequest(); + Assert.ThrowsAsync(async () => await _fileOperationsApiService.QueueBatchPdfParser(batchParsePdfRequest)); + _mockFileOperationsApiDao.Verify(x => x.QueueBatchPdfParser(It.IsAny()), Times.Once); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/MemberPreferencesApiServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/MemberPreferencesApiServiceTest.cs new file mode 100644 index 0000000..f89ac12 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/MemberPreferencesApiServiceTest.cs @@ -0,0 +1,103 @@ +using System; +using System.Threading.Tasks; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.DataAccess; +using LCU.API.Internal.DocumentIngestor.Models.MemberPreferencesDtos; +namespace LCU.API.Internal.DocumentIngestorTests.Services.MicroApiServices; + +public class MemberPreferencesApiServiceTest +{ + private MemberPreferencesApiService _memberPreferencesApiService; + private Mock _mockMemberPreferencesApiDao; + + [SetUp] + public void Setup() + { + _mockMemberPreferencesApiDao = new Mock(); + _memberPreferencesApiService = new MemberPreferencesApiService(_mockMemberPreferencesApiDao.Object); + } + + [Test] + public async Task GetMemberOptInAgreementInfoByUserId_Return() + { + var memberOptInAgreementInformation = new MemberOptInAgreementInformation(); + _mockMemberPreferencesApiDao.Setup(x => x.GetMemberOptInAgreementInfoByUserId(It.IsAny())).ReturnsAsync(memberOptInAgreementInformation); + + var response = await _memberPreferencesApiService.GetMemberOptInAgreementInfoByUserId("11"); + Assert.IsNotNull(response); + _mockMemberPreferencesApiDao.Verify(x => x.GetMemberOptInAgreementInfoByUserId(It.IsAny()), Times.Once); + } + + [Test] + public void GetMemberOptInAgreementInfoByUserId_Exception() + { + _mockMemberPreferencesApiDao.Setup(x => x.GetMemberOptInAgreementInfoByUserId(It.IsAny())).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _memberPreferencesApiService.GetMemberOptInAgreementInfoByUserId("11")); + _mockMemberPreferencesApiDao.Verify(x => x.GetMemberOptInAgreementInfoByUserId(It.IsAny()), Times.Once); + } + + [Test] + public async Task GetMemberOptInSettingsByUserId_Return() + { + var memberOptInSettings = new MemberOptInInformation(); + _mockMemberPreferencesApiDao.Setup(x => x.GetMemberOptInSettingsByUserId(It.IsAny())).ReturnsAsync(memberOptInSettings); + + var response = await _memberPreferencesApiService.GetMemberOptInSettingsByUserId("11"); + Assert.IsNotNull(response); + _mockMemberPreferencesApiDao.Verify(x => x.GetMemberOptInSettingsByUserId(It.IsAny()), Times.Once); + } + + [Test] + public void GetMemberOptInSettingsByUserId_Exception() + { + _mockMemberPreferencesApiDao.Setup(x => x.GetMemberOptInSettingsByUserId(It.IsAny())).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _memberPreferencesApiService.GetMemberOptInSettingsByUserId("11")); + _mockMemberPreferencesApiDao.Verify(x => x.GetMemberOptInSettingsByUserId(It.IsAny()), Times.Once); + } + + [Test] + public async Task EmailSuccessfulSend_Return() + { + var memberOptInSettings = new MemberOptInInformation(); + _mockMemberPreferencesApiDao.Setup(x => x.EmailSuccessfulSend(It.IsAny(), It.IsAny())); + + await _memberPreferencesApiService.EmailStatusSend("11", "test@test.com", true); + _mockMemberPreferencesApiDao.Verify(x => x.EmailSuccessfulSend(It.IsAny(), It.IsAny()), Times.Once); + _mockMemberPreferencesApiDao.Verify(x => x.EmailFailureSend(It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public void EmailSuccessfulSend_Exception() + { + _mockMemberPreferencesApiDao.Setup(x => x.EmailSuccessfulSend(It.IsAny(), It.IsAny())).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _memberPreferencesApiService.EmailStatusSend("11", "test@test.com", true)); + _mockMemberPreferencesApiDao.Verify(x => x.EmailSuccessfulSend(It.IsAny(), It.IsAny()), Times.Once); + _mockMemberPreferencesApiDao.Verify(x => x.EmailFailureSend(It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public async Task EmailFailureSend_Return() + { + _mockMemberPreferencesApiDao.Setup(x => x.EmailFailureSend(It.IsAny(), It.IsAny())); + + await _memberPreferencesApiService.EmailStatusSend("11", "test@test.com", false); + _mockMemberPreferencesApiDao.Verify(x => x.EmailFailureSend(It.IsAny(), It.IsAny()), Times.Once); + _mockMemberPreferencesApiDao.Verify(x => x.EmailSuccessfulSend(It.IsAny(), It.IsAny()), Times.Never); + } + + [Test] + public void EmailFailureSend_Exception() + { + _mockMemberPreferencesApiDao.Setup(x => x.EmailFailureSend(It.IsAny(), It.IsAny())).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _memberPreferencesApiService.EmailStatusSend("11", "test@test.com", false)); + _mockMemberPreferencesApiDao.Verify(x => x.EmailFailureSend(It.IsAny(), It.IsAny()), Times.Once); + _mockMemberPreferencesApiDao.Verify(x => x.EmailSuccessfulSend(It.IsAny(), It.IsAny()), Times.Never); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/NotificationApiServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/NotificationApiServiceTest.cs new file mode 100644 index 0000000..daa5fa4 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/MicroApiServices/NotificationApiServiceTest.cs @@ -0,0 +1,57 @@ +using LCU.API.Internal.DocumentIngestor.DataAccess; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.NotificationsModels.Models; +using Moq; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.MicroApiServices; + +public class NotificationApiServiceTest +{ + private NotificationApiService _notificationApiService; + private Mock _mockNotificationApiDao; + + [SetUp] + public void Setup() + { + _mockNotificationApiDao = new Mock(); + _notificationApiService = new NotificationApiService(_mockNotificationApiDao.Object); + } + + [Test] + public void SendEmailAsync_Exception() + { + _mockNotificationApiDao.Setup(x => x.SendEmailAsync(It.IsAny())) + .ThrowsAsync(new Exception("Error")); + + var request = new EmailRequest() + { + Subject = "", + Body = "", + Recipient = new List(new string[] { "" }) + }; + + Assert.ThrowsAsync(async () => await _notificationApiService.SendEmailAsync(request)); + _mockNotificationApiDao.Verify(x => x.SendEmailAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task SendEmailAsync_Return() + { + _mockNotificationApiDao.Setup(x => x.SendEmailAsync(It.IsAny())); + + var request = new EmailRequest() + { + Subject = "", + Body = "", + Recipient = new List(new string[] { "" }) + }; + + await _notificationApiService.SendEmailAsync(request); + _mockNotificationApiDao.Verify(x => x.SendEmailAsync(It.IsAny()), Times.Once); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/OsgPreprocessorInfoServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/OsgPreprocessorInfoServiceTest.cs new file mode 100644 index 0000000..e861052 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/OsgPreprocessorInfoServiceTest.cs @@ -0,0 +1,366 @@ +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestorLib.Repositories; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +using Moq; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; + +namespace LCU.API.Internal.DocumentIngestorTests.Services; + +public class OsgPreprocessorInfoServiceTest +{ + private OsgPreprocessorInfoService _osgPreprocessorInfoService; + private Mock _unitOfWork; + private Mock _mockOsgPreprocessorInfoRepository; + + [SetUp] + public void Setup() + { + _unitOfWork = new Mock(); + _mockOsgPreprocessorInfoRepository = new Mock(); + _osgPreprocessorInfoService = new OsgPreprocessorInfoService(_unitOfWork.Object, + _mockOsgPreprocessorInfoRepository.Object); + } + + [Test] + public async Task GetAsync_OsgPreprocessorInfos_Returned() + { + var osgPreprocessorInfoId = 10; + var documentType = "Statement"; + var osgPreprocessorInfos = new List() + { + new OsgPreprocessorInfo() + { + OsgPreprocessorInfoId = osgPreprocessorInfoId, + DocumentType = documentType, + CreatedDate = Convert.ToDateTime("1/1/2022") + } + }; + _mockOsgPreprocessorInfoRepository.Setup(x => x.FindAsync()).ReturnsAsync(osgPreprocessorInfos); + var result = await _osgPreprocessorInfoService.GetAsync(); + Assert.IsNotNull(result); + Assert.AreEqual(1, result.Count()); + _mockOsgPreprocessorInfoRepository.Verify(x => x.FindAsync(), Times.Once); + } + + [Test] + public void GetAsync_Exception() + { + _mockOsgPreprocessorInfoRepository.Setup(x => x.FindAsync()).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _osgPreprocessorInfoService.GetAsync()); + _mockOsgPreprocessorInfoRepository.Verify(x => x.FindAsync(), Times.Once); + } + + [Test] + public async Task GetByIdAsync_OsgPreprocessorInfo_Returned() + { + var osgPreprocessorInfoId = 10; + var documentType = "Statement"; + var osgPreprocessorInfo = new OsgPreprocessorInfo() + { + OsgPreprocessorInfoId = osgPreprocessorInfoId, + DocumentType = documentType, + CreatedDate = Convert.ToDateTime("1/1/2022") + }; + _mockOsgPreprocessorInfoRepository.Setup(x => x.FindByIdAsync(osgPreprocessorInfoId)).ReturnsAsync(osgPreprocessorInfo); + var result = await _osgPreprocessorInfoService.GetByIdAsync(osgPreprocessorInfoId); + Assert.IsNotNull(result); + Assert.AreEqual(osgPreprocessorInfoId, result.OsgPreprocessorInfoId); + Assert.AreEqual(documentType, result.DocumentType); + _mockOsgPreprocessorInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public void GetByIdAsync_Exception() + { + var id = 1; + _mockOsgPreprocessorInfoRepository.Setup(x => x.FindByIdAsync(id)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _osgPreprocessorInfoService.GetByIdAsync(id)); + _mockOsgPreprocessorInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task GetByDocumentTypeAsync_OsgPreprocessorInfos_Returned() + { + var osgPreprocessorInfoId = 10; + var documentType = "Statement"; + var entityName = "John Smith"; + var osgPreprocessorInfos = new List() + { + new OsgPreprocessorInfo() + { + OsgPreprocessorInfoId = osgPreprocessorInfoId, + DocumentType = documentType, + EntityName = entityName, + CreatedDate = Convert.ToDateTime("1/1/2022") + } + }; + _mockOsgPreprocessorInfoRepository.Setup(x => x.FindByDocumentType(documentType)).ReturnsAsync(osgPreprocessorInfos); + var result = await _osgPreprocessorInfoService.GetByDocumentTypeAsync(documentType); + Assert.IsNotNull(result); + Assert.AreEqual(1, result.Count()); + _mockOsgPreprocessorInfoRepository.Verify(x => x.FindByDocumentType(It.IsAny()), Times.Once); + } + + [Test] + public void GetByDocumentTypeAsync_Exception() + { + var documentType = "Statement"; + _mockOsgPreprocessorInfoRepository.Setup(x => x.FindByDocumentType(documentType)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _osgPreprocessorInfoService.GetByDocumentTypeAsync(documentType)); + _mockOsgPreprocessorInfoRepository.Verify(x => x.FindByDocumentType(It.IsAny()), Times.Once); + } + + [Test] + public async Task GetByMemberNumberAsync_OsgPreprocessorInfos_Returned() + { + var osgPreprocessorInfoId = 10; + var documentType = "Statement"; + var memberNumber = "123"; + var osgPreprocessorInfos = new List() + { + new OsgPreprocessorInfo() + { + OsgPreprocessorInfoId = osgPreprocessorInfoId, + DocumentType = documentType, + MemberNumber = memberNumber, + CreatedDate = Convert.ToDateTime("1/1/2022") + } + }; + _mockOsgPreprocessorInfoRepository.Setup(x => x.FindByMemberNumber(memberNumber)).ReturnsAsync(osgPreprocessorInfos); + var result = await _osgPreprocessorInfoService.GetByMemberNumberAsync(memberNumber); + Assert.IsNotNull(result); + Assert.AreEqual(1, result.Count()); + _mockOsgPreprocessorInfoRepository.Verify(x => x.FindByMemberNumber(It.IsAny()), Times.Once); + } + + [Test] + public void GetByMemberNumberAsync_Exception() + { + var memberNumber = "123"; + _mockOsgPreprocessorInfoRepository.Setup(x => x.FindByMemberNumber(memberNumber)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _osgPreprocessorInfoService.GetByMemberNumberAsync(memberNumber)); + _mockOsgPreprocessorInfoRepository.Verify(x => x.FindByMemberNumber(It.IsAny()), Times.Once); + } + + [Test] + public async Task SaveAsync_OsgPreprocessorInfo_Returned() + { + var osgPreprocessorInfoId = 10; + var documentType = "Statement"; + var osgPreprocessorInfo = new OsgPreprocessorInfo() + { + OsgPreprocessorInfoId = osgPreprocessorInfoId, + DocumentType = documentType, + CreatedDate = Convert.ToDateTime("1/1/2022") + }; + _mockOsgPreprocessorInfoRepository.Setup(x => x.AddAsync(osgPreprocessorInfo)).ReturnsAsync(osgPreprocessorInfo); + var result = await _osgPreprocessorInfoService.SaveAsync(osgPreprocessorInfo); + Assert.IsNotNull(result); + Assert.AreEqual(osgPreprocessorInfoId, result.OsgPreprocessorInfoId); + Assert.AreEqual(documentType, result.DocumentType); + _mockOsgPreprocessorInfoRepository.Verify(x => x.AddAsync(It.IsAny()), Times.Once); + } + + [Test] + public void SaveAsync_Exception() + { + var osgPreprocessorInfoId = 10; + var documentType = "Statement"; + var osgPreprocessorInfo = new OsgPreprocessorInfo() + { + OsgPreprocessorInfoId = osgPreprocessorInfoId, + DocumentType = documentType, + CreatedDate = Convert.ToDateTime("1/1/2022") + }; + _mockOsgPreprocessorInfoRepository.Setup(x => x.AddAsync(osgPreprocessorInfo)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _osgPreprocessorInfoService.SaveAsync(osgPreprocessorInfo)); + _mockOsgPreprocessorInfoRepository.Verify(x => x.AddAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task Update_OsgPreprocessorInfo_Returned() + { + var osgPreprocessorInfoId = 10; + var documentType = "Statement"; + var osgPreprocessorInfo = new OsgPreprocessorInfo() + { + OsgPreprocessorInfoId = osgPreprocessorInfoId, + DocumentType = documentType, + CreatedDate = Convert.ToDateTime("1/1/2022") + }; + _mockOsgPreprocessorInfoRepository.Setup(x => x.FindByIdAsync(osgPreprocessorInfoId)).ReturnsAsync(osgPreprocessorInfo); + _mockOsgPreprocessorInfoRepository.Setup(x => x.Update(osgPreprocessorInfo)); + + var result = await _osgPreprocessorInfoService.Update(osgPreprocessorInfo); + Assert.IsNotNull(result); + Assert.AreEqual(documentType, result.DocumentType); + Assert.AreEqual(osgPreprocessorInfoId, result.OsgPreprocessorInfoId); + _mockOsgPreprocessorInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockOsgPreprocessorInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Once); + } + + [Test] + public void Update_FindByIdAsync_ThrowsException() + { + var osgPreprocessorInfoId = 10; + var documentType = "Statement"; + var osgPreprocessorInfo = new OsgPreprocessorInfo() + { + OsgPreprocessorInfoId = osgPreprocessorInfoId, + DocumentType = documentType, + CreatedDate = Convert.ToDateTime("1/1/2022") + }; + _mockOsgPreprocessorInfoRepository.Setup(x => x.FindByIdAsync(osgPreprocessorInfoId)).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _osgPreprocessorInfoService.Update(osgPreprocessorInfo)); + _mockOsgPreprocessorInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockOsgPreprocessorInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Never); + } + + [Test] + public void Update_Update_ThrowsException() + { + var osgPreprocessorInfoId = 10; + var documentType = "Statement"; + var osgPreprocessorInfo = new OsgPreprocessorInfo() + { + OsgPreprocessorInfoId = osgPreprocessorInfoId, + DocumentType = documentType, + CreatedDate = Convert.ToDateTime("1/1/2022") + }; + _mockOsgPreprocessorInfoRepository.Setup(x => x.FindByIdAsync(osgPreprocessorInfoId)).ReturnsAsync(osgPreprocessorInfo); + _mockOsgPreprocessorInfoRepository.Setup(x => x.Update(osgPreprocessorInfo)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _osgPreprocessorInfoService.Update(osgPreprocessorInfo)); + _mockOsgPreprocessorInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockOsgPreprocessorInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Once); + } + + [Test] + public async Task UpdateRange_OsgPreprocessorInfo_Returned() + { + var osgPreprocessorInfoId = 10; + var documentType = "Statement"; + var entityName = "John Smith"; + var osgPreprocessorInfos = new List() + { + new OsgPreprocessorInfo() + { + OsgPreprocessorInfoId = osgPreprocessorInfoId, + DocumentType = documentType, + EntityName = entityName, + CreatedDate = Convert.ToDateTime("1/1/2022") + } + }; + _mockOsgPreprocessorInfoRepository.Setup(x => x.FindByIdAsync(osgPreprocessorInfoId)).ReturnsAsync(osgPreprocessorInfos[0]); + _mockOsgPreprocessorInfoRepository.Setup(x => x.UpdateRange(osgPreprocessorInfos)); + + var result = await _osgPreprocessorInfoService.UpdateRange(osgPreprocessorInfos); + Assert.IsNotNull(result); + Assert.AreEqual(documentType, result.FirstOrDefault()?.DocumentType); + Assert.AreEqual(osgPreprocessorInfoId, result.FirstOrDefault()?.OsgPreprocessorInfoId); + _mockOsgPreprocessorInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockOsgPreprocessorInfoRepository.Verify(x => x.UpdateRange(It.IsAny>()), Times.Once); + } + + [Test] + public void UpdateRange_FindByIdAsync_ThrowsException() + { + var osgPreprocessorInfoId = 10; + var documentType = "Statement"; + var entityName = "John Smith"; + var osgPreprocessorInfos = new List() + { + new OsgPreprocessorInfo() + { + OsgPreprocessorInfoId = osgPreprocessorInfoId, + DocumentType = documentType, + EntityName = entityName, + CreatedDate = Convert.ToDateTime("1/1/2022") + } + }; + _mockOsgPreprocessorInfoRepository.Setup(x => x.FindByIdAsync(osgPreprocessorInfoId)).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _osgPreprocessorInfoService.UpdateRange(osgPreprocessorInfos)); + _mockOsgPreprocessorInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockOsgPreprocessorInfoRepository.Verify(x => x.UpdateRange(It.IsAny>()), Times.Never); + } + + [Test] + public void UpdateRange_Update_ThrowsException() + { + var osgPreprocessorInfoId = 10; + var documentType = "Statement"; + var entityName = "John Smith"; + var osgPreprocessorInfos = new List() + { + new OsgPreprocessorInfo() + { + OsgPreprocessorInfoId = osgPreprocessorInfoId, + DocumentType = documentType, + EntityName = entityName, + CreatedDate = Convert.ToDateTime("1/1/2022") + } + }; + _mockOsgPreprocessorInfoRepository.Setup(x => x.FindByIdAsync(osgPreprocessorInfoId)).ReturnsAsync(osgPreprocessorInfos[0]); + _mockOsgPreprocessorInfoRepository.Setup(x => x.UpdateRange(osgPreprocessorInfos)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _osgPreprocessorInfoService.UpdateRange(osgPreprocessorInfos)); + _mockOsgPreprocessorInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockOsgPreprocessorInfoRepository.Verify(x => x.UpdateRange(It.IsAny>()), Times.Once); + } + + [Test] + public async Task Delete_Success() + { + var osgPreprocessorInfoId = 10; + var documentType = "Statement"; + var osgPreprocessorInfo = new OsgPreprocessorInfo() + { + OsgPreprocessorInfoId = osgPreprocessorInfoId, + DocumentType = documentType, + CreatedDate = Convert.ToDateTime("1/1/2022") + }; + _mockOsgPreprocessorInfoRepository.Setup(x => x.FindByIdAsync(osgPreprocessorInfoId)).ReturnsAsync(osgPreprocessorInfo); + _mockOsgPreprocessorInfoRepository.Setup(x => x.Remove(osgPreprocessorInfo)); + + await _osgPreprocessorInfoService.Delete(osgPreprocessorInfoId); + _mockOsgPreprocessorInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockOsgPreprocessorInfoRepository.Verify(x => x.Remove(It.IsAny()), Times.Once); + } + + [Test] + public void Delete_FindByIdAsync_ThrowsException() + { + var id = 1; + _mockOsgPreprocessorInfoRepository.Setup(x => x.FindByIdAsync(id)).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _osgPreprocessorInfoService.Delete(id)); + _mockOsgPreprocessorInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockOsgPreprocessorInfoRepository.Verify(x => x.Remove(It.IsAny()), Times.Never); + } + + [Test] + public void Delete_Remove_ThrowsException() + { + var osgPreprocessorInfoId = 10; + var documentType = "Statement"; + var osgPreprocessorInfo = new OsgPreprocessorInfo() + { + OsgPreprocessorInfoId = osgPreprocessorInfoId, + DocumentType = documentType, + CreatedDate = Convert.ToDateTime("1/1/2022") + }; + _mockOsgPreprocessorInfoRepository.Setup(x => x.FindByIdAsync(osgPreprocessorInfoId)).ReturnsAsync(osgPreprocessorInfo); + _mockOsgPreprocessorInfoRepository.Setup(x => x.Remove(osgPreprocessorInfo)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _osgPreprocessorInfoService.Delete(osgPreprocessorInfoId)); + _mockOsgPreprocessorInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockOsgPreprocessorInfoRepository.Verify(x => x.Remove(It.IsAny()), Times.Once); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/OwnerOverrideInfoServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/OwnerOverrideInfoServiceTest.cs new file mode 100644 index 0000000..a421714 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/OwnerOverrideInfoServiceTest.cs @@ -0,0 +1,197 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestorLib.Repositories; + +namespace LCU.API.Internal.DocumentIngestorTests.Services; + +public class OwnerOverrideInfoServiceTest +{ + private OwnerOverrideInfoService _ownerOverrideInfoService; + private Mock _unitOfWork; + private Mock _mockOwnerOverrideInfoRepository; + private Mock _mockProcessingLogService; + + [SetUp] + public void Setup() + { + _unitOfWork = new Mock(); + _mockOwnerOverrideInfoRepository = new Mock(); + _mockProcessingLogService = new Mock(); + _ownerOverrideInfoService = new OwnerOverrideInfoService(_unitOfWork.Object, _mockOwnerOverrideInfoRepository.Object); + } + + [Test] + public async Task GetAsync_OwnerOverrideInfos_Returned() + { + var id = 1; + var ownerOverrideInfos = new List() + { + new OwnerOverrideInfo() + { + OwnerOverrideInfoId = id + } + }; + _mockOwnerOverrideInfoRepository.Setup(x => x.FindAsync()).ReturnsAsync(ownerOverrideInfos); + var result = await _ownerOverrideInfoService.GetAsync(); + Assert.IsNotNull(result); + Assert.AreEqual(1, result.Count()); + _mockOwnerOverrideInfoRepository.Verify(x => x.FindAsync(), Times.Once); + } + + [Test] + public void GetAsync_Exception() + { + _mockOwnerOverrideInfoRepository.Setup(x => x.FindAsync()).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _ownerOverrideInfoService.GetAsync()); + _mockOwnerOverrideInfoRepository.Verify(x => x.FindAsync(), Times.Once); + } + + [Test] + public async Task GetByIdAsync_OwnerOverrideInfo_Returned() + { + var id = 1; + var documentProcessingInfoId = 2; + var ownerOverrideInfo = new OwnerOverrideInfo() + { + OwnerOverrideInfoId = id, + DocumentProcessingInfoId = documentProcessingInfoId + }; + _mockOwnerOverrideInfoRepository.Setup(x => x.FindByIdAsync(id)).ReturnsAsync(ownerOverrideInfo); + var result = await _ownerOverrideInfoService.GetByIdAsync(id); + Assert.IsNotNull(result); + Assert.AreEqual(documentProcessingInfoId, result.DocumentProcessingInfoId); + Assert.AreEqual(id, result.OwnerOverrideInfoId); + _mockOwnerOverrideInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public void GetByIdAsync_Exception() + { + var id = 1; + _mockOwnerOverrideInfoRepository.Setup(x => x.FindByIdAsync(id)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _ownerOverrideInfoService.GetByIdAsync(id)); + _mockOwnerOverrideInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task GetByDocumentProcessingInfoIdAsync_OwnerOverrideInfos_Returned() + { + var id = 1; + var documentProcessingInfoId = 2; + var ownerOverrideInfos = new List() + { + new OwnerOverrideInfo() + { + OwnerOverrideInfoId = id, + DocumentProcessingInfoId = documentProcessingInfoId + } + }; + _mockOwnerOverrideInfoRepository.Setup(x => x.FindByDocumentProcessingInfoIdAsync(documentProcessingInfoId)).ReturnsAsync(ownerOverrideInfos); + var result = await _ownerOverrideInfoService.GetByDocumentProcessingInfoIdAsync(documentProcessingInfoId); + Assert.IsNotNull(result); + Assert.AreEqual(1, result.Count()); + _mockOwnerOverrideInfoRepository.Verify(x => x.FindByDocumentProcessingInfoIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public void GetByDocumentProcessingInfoIdAsync_Exception() + { + var documentProcessingInfoId = 2; + _mockOwnerOverrideInfoRepository.Setup(x => x.FindByDocumentProcessingInfoIdAsync(documentProcessingInfoId)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _ownerOverrideInfoService.GetByDocumentProcessingInfoIdAsync(documentProcessingInfoId)); + _mockOwnerOverrideInfoRepository.Verify(x => x.FindByDocumentProcessingInfoIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task SaveAsync_OwnerOverrideInfo_Returned() + { + var id = 1; + var documentProcessingInfoId = 2; + var ownerOverrideInfo = new OwnerOverrideInfo() + { + OwnerOverrideInfoId = id, + DocumentProcessingInfoId = documentProcessingInfoId + }; + _mockOwnerOverrideInfoRepository.Setup(x => x.AddAsync(ownerOverrideInfo)).ReturnsAsync(ownerOverrideInfo); + var result = await _ownerOverrideInfoService.SaveAsync(ownerOverrideInfo); + Assert.IsNotNull(result); + Assert.AreEqual(documentProcessingInfoId, result.DocumentProcessingInfoId); + Assert.AreEqual(id, result.OwnerOverrideInfoId); + _mockOwnerOverrideInfoRepository.Verify(x => x.AddAsync(It.IsAny()), Times.Once); + } + + [Test] + public void SaveAsync_Exception() + { + var id = 1; + var documentProcessingInfoId = 2; + var ownerOverrideInfo = new OwnerOverrideInfo() + { + OwnerOverrideInfoId = id, + DocumentProcessingInfoId = documentProcessingInfoId + }; + _mockOwnerOverrideInfoRepository.Setup(x => x.AddAsync(ownerOverrideInfo)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _ownerOverrideInfoService.SaveAsync(ownerOverrideInfo)); + _mockOwnerOverrideInfoRepository.Verify(x => x.AddAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task Delete_Success() + { + var id = 1; + var documentProcessingInfoId = 2; + var ownerOverrideInfo = new OwnerOverrideInfo() + { + OwnerOverrideInfoId = id, + DocumentProcessingInfoId = documentProcessingInfoId + }; + _mockOwnerOverrideInfoRepository.Setup(x => x.FindByIdAsync(id)).ReturnsAsync(ownerOverrideInfo); + _mockOwnerOverrideInfoRepository.Setup(x => x.Remove(ownerOverrideInfo)); + + await _ownerOverrideInfoService.Delete(id); + _mockOwnerOverrideInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockOwnerOverrideInfoRepository.Verify(x => x.Remove(It.IsAny()), Times.Once); + } + + [Test] + public void Delete_FindByIdAsync_ThrowsException() + { + var id = 1; + var documentProcessingInfoId = 2; + var ownerOverrideInfo = new OwnerOverrideInfo() + { + OwnerOverrideInfoId = id, + DocumentProcessingInfoId = documentProcessingInfoId + }; + _mockOwnerOverrideInfoRepository.Setup(x => x.FindByIdAsync(id)).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _ownerOverrideInfoService.Delete(id)); + _mockOwnerOverrideInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockOwnerOverrideInfoRepository.Verify(x => x.Remove(It.IsAny()), Times.Never); + } + + [Test] + public void Delete_Remove_ThrowsException() + { + var id = 1; + var documentProcessingInfoId = 2; + var ownerOverrideInfo = new OwnerOverrideInfo() + { + OwnerOverrideInfoId = id, + DocumentProcessingInfoId = documentProcessingInfoId + }; + _mockOwnerOverrideInfoRepository.Setup(x => x.FindByIdAsync(id)).ReturnsAsync(ownerOverrideInfo); + _mockOwnerOverrideInfoRepository.Setup(x => x.Remove(ownerOverrideInfo)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _ownerOverrideInfoService.Delete(id)); + _mockOwnerOverrideInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockOwnerOverrideInfoRepository.Verify(x => x.Remove(It.IsAny()), Times.Once); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/PdfParserServices/FosLoanStatementPdfServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/PdfParserServices/FosLoanStatementPdfServiceTest.cs new file mode 100644 index 0000000..07318e8 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/PdfParserServices/FosLoanStatementPdfServiceTest.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections.Generic; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; +using LCU.API.Internal.DocumentIngestor.Services.PdfParserServices; +using System.Threading.Tasks; +using System.Linq; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.Library.Internal.LCUServiceFactory.Configurations; +using LCU.Library.Internal.LCUServiceFactory.Services; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.PdfParserServices; + +public class FosLoanStatementPdfServiceTest +{ + private FosLoanStatementPdfService _fosLoanStatementPdfService; + private Mock> _mockLcuServiceFactory; + private Mock _mockFileOperationsApiService; + + [SetUp] + public void Setup() + { + _mockLcuServiceFactory = new Mock>(); + _mockFileOperationsApiService = new Mock(); + var serviceFactoryConfiguration = new ServicesFactoryConfiguration + { + ServiceFactoryRegistrations = new List + { + new() + { + ServiceInterfaceName = "IPdfIndexParserService", + ServiceRegistrations = new List + { + new() + { + ServiceName = "PdfIndexParserService", + ServiceId = "0" + }, + new() + { + ServiceName = "PdfIndexParserService", + ServiceId = "3" + } + } + } + } + }; + _fosLoanStatementPdfService = new FosLoanStatementPdfService(_mockFileOperationsApiService.Object, + _mockLcuServiceFactory.Object, + serviceFactoryConfiguration); + } + + [Test] + public void DetermineBatchParsePdfRequest_GetFileContentAndParseRecords_ThrowException_Failure() + { + var rootPath = "\\\\Test\\root\\Path\\"; + var indexFile = "TestIndexFile"; + var pdfName = "TestPdfName"; + + var indexService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(IngestorTypes.FosLoanStatement)).Returns(indexService.Object); + indexService.Setup(x => x.GetFileContentAndParseRecords(It.IsAny())).ThrowsAsync(new Exception("Errors")); + + Assert.ThrowsAsync(async () => await _fosLoanStatementPdfService.DetermineBatchParsePdfRequest(rootPath, indexFile, pdfName)); + indexService.Verify(x => x.GetFileContentAndParseRecords(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny()), Times.Never); + indexService.Verify(x => x.CreateParsedPdfName(It.IsAny()), Times.Never); + } + + [Test] + public void DetermineBatchParsePdfRequest_ValidatePdfPageExists_ThrowException_Failure() + { + var rootPath = "\\\\Test\\root\\Path\\"; + var indexFile = "TestIndexFile"; + var pdfName = "TestPdfName"; + var records = new List + { + new FosLoanStatement + { + DocType = "TestDocType", + AccountNumber = "1", + EntityName = "Test EntityName", + EmailAddress = "Test EmailAddress", + CreationDate = "1/1/2022", + StartingPage = "1", + NumberOfPages = "3", + DocName = "Test DocName" + } + }; + + var indexService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(IngestorTypes.FosLoanStatement)).Returns(indexService.Object); + indexService.Setup(x => x.GetFileContentAndParseRecords(It.IsAny())).ReturnsAsync(records); + _mockFileOperationsApiService.Setup(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny())).ThrowsAsync(new Exception("Errors")); + + Assert.ThrowsAsync(async () => await _fosLoanStatementPdfService.DetermineBatchParsePdfRequest(rootPath, indexFile, pdfName)); + indexService.Verify(x => x.GetFileContentAndParseRecords(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny()), Times.Once); + indexService.Verify(x => x.CreateParsedPdfName(It.IsAny()), Times.Never); + } + + [Test] + public void DetermineBatchParsePdfRequest_CreateParsedPdfName_ThrowException_Failure() + { + var rootPath = "\\\\Test\\root\\Path\\"; + var indexFile = "TestIndexFile"; + var pdfName = "TestPdfName"; + var records = new List + { + new FosLoanStatement + { + DocType = "TestDocType", + AccountNumber = "1", + EntityName = "Test EntityName", + EmailAddress = "Test EmailAddress", + CreationDate = "1/1/2022", + StartingPage = "1", + NumberOfPages = "3", + DocName = "Test DocName" + } + }; + + var indexService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(IngestorTypes.FosLoanStatement)).Returns(indexService.Object); + indexService.Setup(x => x.GetFileContentAndParseRecords(It.IsAny())).ReturnsAsync(records); + var requestResponse = new RequestResponse + { + IsSuccessful = true + }; + _mockFileOperationsApiService.Setup(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse); + indexService.Setup(x => x.CreateParsedPdfName(It.IsAny())).Throws(new Exception("Errors")); + + Assert.ThrowsAsync(async () => await _fosLoanStatementPdfService.DetermineBatchParsePdfRequest(rootPath, indexFile, pdfName)); + indexService.Verify(x => x.GetFileContentAndParseRecords(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny()), Times.Once); + indexService.Verify(x => x.CreateParsedPdfName(It.IsAny()), Times.Once); + } + + [Test] + public async Task DetermineBatchParsePdfRequest_Success() + { + var rootPath = "\\\\Test\\root\\Path\\"; + var indexFile = "TestIndexFile"; + var pdfName = "TestPdfName"; + var records = new List + { + new FosLoanStatement + { + DocType = "TestDocType", + AccountNumber = "1", + EntityName = "Test EntityName", + EmailAddress = "Test EmailAddress", + CreationDate = "1/1/2022", + StartingPage = "1", + NumberOfPages = "3", + DocName = "Test DocName" + } + }; + + var indexService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(IngestorTypes.FosLoanStatement)).Returns(indexService.Object); + indexService.Setup(x => x.GetFileContentAndParseRecords(It.IsAny())).ReturnsAsync(records); + var requestResponse = new RequestResponse + { + IsSuccessful = true + }; + _mockFileOperationsApiService.Setup(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse); + + var parsedPdfName = "TestPdfName_Test EntityName_1"; + indexService.Setup(x => x.CreateParsedPdfName(It.IsAny())).Returns(parsedPdfName); + + var batchParsePdfRequest = await _fosLoanStatementPdfService.DetermineBatchParsePdfRequest(rootPath, indexFile, pdfName); + Assert.AreEqual(1, batchParsePdfRequest.BatchPdfs.Count); + var batchPdf = batchParsePdfRequest.BatchPdfs.FirstOrDefault(); + Assert.IsNotNull(batchPdf); + Assert.AreEqual($"{parsedPdfName}.pdf", batchPdf?.ParsedPdfname); + Assert.AreEqual(1, batchPdf?.PageStart); + Assert.AreEqual(3, batchPdf?.PageStop); + indexService.Verify(x => x.GetFileContentAndParseRecords(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny()), Times.Once); + indexService.Verify(x => x.CreateParsedPdfName(It.IsAny()), Times.Once); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/PdfParserServices/OsgDnaNoticesPdfServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/PdfParserServices/OsgDnaNoticesPdfServiceTest.cs new file mode 100644 index 0000000..bee831d --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/PdfParserServices/OsgDnaNoticesPdfServiceTest.cs @@ -0,0 +1,182 @@ +using System; +using System.Collections.Generic; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; +using LCU.API.Internal.DocumentIngestor.Services.PdfParserServices; +using System.Threading.Tasks; +using System.Linq; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.Library.Internal.LCUServiceFactory.Configurations; +using LCU.Library.Internal.LCUServiceFactory.Services; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.PdfParserServices; + +public class OsgDnaNoticesPdfServiceTest +{ + private OsgDnaNoticesPdfService _osgDnaNoticesPdfService; + private Mock> _mockLcuServiceFactory; + private Mock _mockFileOperationsApiService; + + [SetUp] + public void Setup() + { + _mockLcuServiceFactory = new Mock>(); + _mockFileOperationsApiService = new Mock(); + var serviceFactoryConfiguration = new ServicesFactoryConfiguration + { + ServiceFactoryRegistrations = new List + { + new() + { + ServiceInterfaceName = "IPdfIndexParserService", + ServiceRegistrations = new List + { + new() + { + ServiceName = "PdfIndexParserService", + ServiceId = "0" + }, + new() + { + ServiceName = "PdfIndexParserService", + ServiceId = "4" + } + } + } + } + }; + _osgDnaNoticesPdfService = new OsgDnaNoticesPdfService(_mockLcuServiceFactory.Object, + _mockFileOperationsApiService.Object, + serviceFactoryConfiguration); + } + + [Test] + public void DetermineBatchParsePdfRequest_GetFileContentAndParseRecords_ThrowException_Failure() + { + var rootPath = "\\\\Test\\root\\Path\\"; + var indexFile = "TestIndexFile"; + var pdfName = "TestPdfName"; + + var indexService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(IngestorTypes.OsgDnaNoticesDocument)).Returns(indexService.Object); + indexService.Setup(x => x.GetFileContentAndParseRecords(It.IsAny())).ThrowsAsync(new Exception("Errors")); + + Assert.ThrowsAsync(async () => await _osgDnaNoticesPdfService.DetermineBatchParsePdfRequest(rootPath, indexFile, pdfName)); + indexService.Verify(x => x.GetFileContentAndParseRecords(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny()), Times.Never); + indexService.Verify(x => x.CreateParsedPdfName(It.IsAny()), Times.Never); + } + + [Test] + public void DetermineBatchParsePdfRequest_ValidatePdfPageExists_ThrowException_Failure() + { + var rootPath = "\\\\Test\\root\\Path\\"; + var indexFile = "TestIndexFile"; + var pdfName = "TestPdfName"; + var records = new List + { + new OsgDnaNoticesDocument + { + DocType = "TestDocType", + AccountNumber = "1", + MemberNumberOrUserId = "2", + CreationDate = "20220823", + StartingPage = "1", + NumberOfPages = "3" + } + }; + + var indexService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(IngestorTypes.OsgDnaNoticesDocument)).Returns(indexService.Object); + indexService.Setup(x => x.GetFileContentAndParseRecords(It.IsAny())).ReturnsAsync(records); + _mockFileOperationsApiService.Setup(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny())).ThrowsAsync(new Exception("Errors")); + + Assert.ThrowsAsync(async () => await _osgDnaNoticesPdfService.DetermineBatchParsePdfRequest(rootPath, indexFile, pdfName)); + indexService.Verify(x => x.GetFileContentAndParseRecords(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny()), Times.Once); + indexService.Verify(x => x.CreateParsedPdfName(It.IsAny()), Times.Never); + } + + [Test] + public void DetermineBatchParsePdfRequest_CreateParsedPdfName_ThrowException_Failure() + { + var rootPath = "\\\\Test\\root\\Path\\"; + var indexFile = "TestIndexFile"; + var pdfName = "TestPdfName"; + var records = new List + { + new OsgDnaNoticesDocument + { + DocType = "TestDocType", + AccountNumber = "1", + MemberNumberOrUserId = "2", + CreationDate = "20220823", + StartingPage = "1", + NumberOfPages = "3" + } + }; + + var indexService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(IngestorTypes.OsgDnaNoticesDocument)).Returns(indexService.Object); + indexService.Setup(x => x.GetFileContentAndParseRecords(It.IsAny())).ReturnsAsync(records); + var requestResponse = new RequestResponse + { + IsSuccessful = true + }; + _mockFileOperationsApiService.Setup(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse); + indexService.Setup(x => x.CreateParsedPdfName(It.IsAny())).Throws(new Exception("Errors")); + + Assert.ThrowsAsync(async () => await _osgDnaNoticesPdfService.DetermineBatchParsePdfRequest(rootPath, indexFile, pdfName)); + indexService.Verify(x => x.GetFileContentAndParseRecords(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny()), Times.Once); + indexService.Verify(x => x.CreateParsedPdfName(It.IsAny()), Times.Once); + } + + [Test] + public async Task DetermineBatchParsePdfRequest_Success() + { + var rootPath = "\\\\Test\\root\\Path\\"; + var indexFile = "TestIndexFile"; + var pdfName = "TestPdfName"; + var records = new List + { + new OsgDnaNoticesDocument + { + DocType = "TestDocType", + AccountNumber = "1", + MemberNumberOrUserId = "2", + CreationDate = "20220823", + StartingPage = "1", + NumberOfPages = "3" + } + }; + + var indexService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(IngestorTypes.OsgDnaNoticesDocument)).Returns(indexService.Object); + indexService.Setup(x => x.GetFileContentAndParseRecords(It.IsAny())).ReturnsAsync(records); + var requestResponse = new RequestResponse + { + IsSuccessful = true + }; + _mockFileOperationsApiService.Setup(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse); + + var parsedPdfName = "TestPdfName_Test EntityName_1"; + indexService.Setup(x => x.CreateParsedPdfName(It.IsAny())).Returns(parsedPdfName); + + var batchParsePdfRequest = await _osgDnaNoticesPdfService.DetermineBatchParsePdfRequest(rootPath, indexFile, pdfName); + Assert.AreEqual(1, batchParsePdfRequest.BatchPdfs.Count); + var batchPdf = batchParsePdfRequest.BatchPdfs.FirstOrDefault(); + Assert.IsNotNull(batchPdf); + Assert.AreEqual($"{parsedPdfName}.pdf", batchPdf?.ParsedPdfname); + Assert.AreEqual(1, batchPdf?.PageStart); + Assert.AreEqual(3, batchPdf?.PageStop); + indexService.Verify(x => x.GetFileContentAndParseRecords(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny()), Times.Once); + indexService.Verify(x => x.CreateParsedPdfName(It.IsAny()), Times.Once); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/PdfParserServices/OsgHistoricalDocumentPdfServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/PdfParserServices/OsgHistoricalDocumentPdfServiceTest.cs new file mode 100644 index 0000000..0380e5d --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/PdfParserServices/OsgHistoricalDocumentPdfServiceTest.cs @@ -0,0 +1,182 @@ +using System; +using System.Collections.Generic; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.Exceptions; +using LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.API.Internal.DocumentIngestor.Services.IndexParserServices; +using LCU.API.Internal.DocumentIngestor.Services.PdfParserServices; +using System.Threading.Tasks; +using System.Linq; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.FileOperationsModels.Models; +using LCU.Library.Internal.LCUServiceFactory.Configurations; +using LCU.Library.Internal.LCUServiceFactory.Services; + +namespace LCU.API.Internal.DocumentIngestorTests.Services.PdfParserServices; + +public class OsgHistoricalDocumentPdfServiceTest +{ + private OsgHistoricalDocumentPdfService _osgHistoricalDocumentPdfService; + private Mock> _mockLcuServiceFactory; + private Mock _mockFileOperationsApiService; + + [SetUp] + public void Setup() + { + _mockLcuServiceFactory = new Mock>(); + _mockFileOperationsApiService = new Mock(); + var serviceFactoryConfiguration = new ServicesFactoryConfiguration + { + ServiceFactoryRegistrations = new List + { + new() + { + ServiceInterfaceName = "IPdfIndexParserService", + ServiceRegistrations = new List + { + new() + { + ServiceName = "PdfIndexParserService", + ServiceId = "0" + }, + new() + { + ServiceName = "PdfIndexParserService", + ServiceId = "6" + } + } + } + } + }; + _osgHistoricalDocumentPdfService = new OsgHistoricalDocumentPdfService(_mockLcuServiceFactory.Object, + _mockFileOperationsApiService.Object, + serviceFactoryConfiguration); + } + + [Test] + public void DetermineBatchParsePdfRequest_GetFileContentAndParseRecords_ThrowException_Failure() + { + var rootPath = "\\\\Test\\root\\Path\\"; + var indexFile = "TestIndexFile"; + var pdfName = "TestPdfName"; + + var indexService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(IngestorTypes.OsgHistoricalDocument)).Returns(indexService.Object); + indexService.Setup(x => x.GetFileContentAndParseRecords(It.IsAny())).ThrowsAsync(new Exception("Errors")); + + Assert.ThrowsAsync(async () => await _osgHistoricalDocumentPdfService.DetermineBatchParsePdfRequest(rootPath, indexFile, pdfName)); + indexService.Verify(x => x.GetFileContentAndParseRecords(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny()), Times.Never); + indexService.Verify(x => x.CreateParsedPdfName(It.IsAny()), Times.Never); + } + + [Test] + public void DetermineBatchParsePdfRequest_ValidatePdfPageExists_ThrowException_Failure() + { + var rootPath = "\\\\Test\\root\\Path\\"; + var indexFile = "TestIndexFile"; + var pdfName = "TestPdfName"; + var records = new List + { + new OsgHistoricalDocument + { + DocType = "TestDocType", + EntityName = "Jim Jones", + MemberNumberOrUserId = "2", + CreationDate = "20220823", + StartingPage = "1", + NumberOfPages = "3" + } + }; + + var indexService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(IngestorTypes.OsgHistoricalDocument)).Returns(indexService.Object); + indexService.Setup(x => x.GetFileContentAndParseRecords(It.IsAny())).ReturnsAsync(records); + _mockFileOperationsApiService.Setup(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny())).ThrowsAsync(new Exception("Errors")); + + Assert.ThrowsAsync(async () => await _osgHistoricalDocumentPdfService.DetermineBatchParsePdfRequest(rootPath, indexFile, pdfName)); + indexService.Verify(x => x.GetFileContentAndParseRecords(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny()), Times.Once); + indexService.Verify(x => x.CreateParsedPdfName(It.IsAny()), Times.Never); + } + + [Test] + public void DetermineBatchParsePdfRequest_CreateParsedPdfName_ThrowException_Failure() + { + var rootPath = "\\\\Test\\root\\Path\\"; + var indexFile = "TestIndexFile"; + var pdfName = "TestPdfName"; + var records = new List + { + new OsgHistoricalDocument + { + DocType = "TestDocType", + EntityName = "Jan James", + MemberNumberOrUserId = "2", + CreationDate = "20220823", + StartingPage = "1", + NumberOfPages = "3" + } + }; + + var indexService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(IngestorTypes.OsgHistoricalDocument)).Returns(indexService.Object); + indexService.Setup(x => x.GetFileContentAndParseRecords(It.IsAny())).ReturnsAsync(records); + var requestResponse = new RequestResponse + { + IsSuccessful = true + }; + _mockFileOperationsApiService.Setup(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse); + indexService.Setup(x => x.CreateParsedPdfName(It.IsAny())).Throws(new Exception("Errors")); + + Assert.ThrowsAsync(async () => await _osgHistoricalDocumentPdfService.DetermineBatchParsePdfRequest(rootPath, indexFile, pdfName)); + indexService.Verify(x => x.GetFileContentAndParseRecords(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny()), Times.Once); + indexService.Verify(x => x.CreateParsedPdfName(It.IsAny()), Times.Once); + } + + [Test] + public async Task DetermineBatchParsePdfRequest_Success() + { + var rootPath = "\\\\Test\\root\\Path\\"; + var indexFile = "TestIndexFile"; + var pdfName = "TestPdfName"; + var records = new List + { + new OsgHistoricalDocument + { + DocType = "TestDocType", + EntityName = "Jeff June", + MemberNumberOrUserId = "2", + CreationDate = "20220823", + StartingPage = "1", + NumberOfPages = "3" + } + }; + + var indexService = new Mock(); + _mockLcuServiceFactory.Setup(x => x.GetService(IngestorTypes.OsgHistoricalDocument)).Returns(indexService.Object); + indexService.Setup(x => x.GetFileContentAndParseRecords(It.IsAny())).ReturnsAsync(records); + var requestResponse = new RequestResponse + { + IsSuccessful = true + }; + _mockFileOperationsApiService.Setup(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny())).ReturnsAsync(requestResponse); + + var parsedPdfName = "TestPdfName_Test EntityName_1"; + indexService.Setup(x => x.CreateParsedPdfName(It.IsAny())).Returns(parsedPdfName); + + var batchParsePdfRequest = await _osgHistoricalDocumentPdfService.DetermineBatchParsePdfRequest(rootPath, indexFile, pdfName); + Assert.AreEqual(1, batchParsePdfRequest.BatchPdfs.Count); + var batchPdf = batchParsePdfRequest.BatchPdfs.FirstOrDefault(); + Assert.IsNotNull(batchPdf); + Assert.AreEqual($"{parsedPdfName}.pdf", batchPdf?.ParsedPdfname); + Assert.AreEqual(1, batchPdf?.PageStart); + Assert.AreEqual(3, batchPdf?.PageStop); + indexService.Verify(x => x.GetFileContentAndParseRecords(It.IsAny()), Times.Once); + _mockFileOperationsApiService.Verify(x => x.ValidatePdfPageExists(It.IsAny(), It.IsAny()), Times.Once); + indexService.Verify(x => x.CreateParsedPdfName(It.IsAny()), Times.Once); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/PdfPartitionerLogServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/PdfPartitionerLogServiceTest.cs new file mode 100644 index 0000000..7b81de5 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/PdfPartitionerLogServiceTest.cs @@ -0,0 +1,196 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestorLib.Repositories; +namespace LCU.API.Internal.DocumentIngestorTests.Services; + +public class PdfPartitionerLogServiceTest +{ + private PdfPartitionerLogService _pdfPartitionerLogService; + private Mock _unitOfWork; + private Mock _mockIPdfPartitionerLogRepository; + + [SetUp] + public void Setup() + { + _unitOfWork = new Mock(); + _mockIPdfPartitionerLogRepository = new Mock(); + _pdfPartitionerLogService = new PdfPartitionerLogService(_unitOfWork.Object, _mockIPdfPartitionerLogRepository.Object); + } + + [Test] + public async Task GetAsync_PdfPartitionerLogs_Returned() + { + var pdfPartitionerRunInfoId = Guid.NewGuid(); + var pdfPartitionerLogId = 2; + var pdfPartitionerLogs = new List() + { + new PdfPartitionerLog() + { + PdfPartitionerLogId = pdfPartitionerLogId, + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId + } + }; + _mockIPdfPartitionerLogRepository.Setup(x => x.FindAsync()).ReturnsAsync(pdfPartitionerLogs); + var result = await _pdfPartitionerLogService.GetAsync(); + Assert.IsNotNull(result); + Assert.AreEqual(1, result.Count()); + _mockIPdfPartitionerLogRepository.Verify(x => x.FindAsync(), Times.Once); + } + + [Test] + public void GetAsync_Exception() + { + _mockIPdfPartitionerLogRepository.Setup(x => x.FindAsync()).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _pdfPartitionerLogService.GetAsync()); + _mockIPdfPartitionerLogRepository.Verify(x => x.FindAsync(), Times.Once); + } + + [Test] + public async Task GetByIdAsync_PdfPartitionerLog_Returned() + { + var pdfPartitionerRunInfoId = Guid.NewGuid(); + var pdfPartitionerLogId = 2; + var pdfPartitionerLog = new PdfPartitionerLog() + { + PdfPartitionerLogId = pdfPartitionerLogId, + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId + }; + _mockIPdfPartitionerLogRepository.Setup(x => x.FindByIdAsync(pdfPartitionerLogId)).ReturnsAsync(pdfPartitionerLog); + var result = await _pdfPartitionerLogService.GetByIdAsync(pdfPartitionerLogId); + Assert.IsNotNull(result); + Assert.AreEqual(pdfPartitionerRunInfoId, result.PdfPartitionerRunInfoId); + Assert.AreEqual(pdfPartitionerLogId, result.PdfPartitionerLogId); + _mockIPdfPartitionerLogRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public void GetByIdAsync_Exception() + { + var pdfPartitionerLogId = 2; + _mockIPdfPartitionerLogRepository.Setup(x => x.FindByIdAsync(pdfPartitionerLogId)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _pdfPartitionerLogService.GetByIdAsync(pdfPartitionerLogId)); + _mockIPdfPartitionerLogRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task GetByPdfPartitionerRunInfoIdAsync_PdfPartitionerLogs_Returned() + { + var pdfPartitionerRunInfoId = Guid.NewGuid(); + var pdfPartitionerLogId = 2; + var pdfPartitionerLogs = new List() + { + new PdfPartitionerLog() + { + PdfPartitionerLogId = pdfPartitionerLogId, + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId + } + }; + _mockIPdfPartitionerLogRepository.Setup(x => x.FindByPdfPartitionerRunInfoIdAsync(pdfPartitionerRunInfoId)).ReturnsAsync(pdfPartitionerLogs); + var result = await _pdfPartitionerLogService.GetByPdfPartitionerRunInfoIdAsync(pdfPartitionerRunInfoId); + Assert.IsNotNull(result); + Assert.AreEqual(1, result.Count()); + _mockIPdfPartitionerLogRepository.Verify(x => x.FindByPdfPartitionerRunInfoIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public void GetByPdfPartitionerRunInfoIdAsync_Exception() + { + var pdfPartitionerRunInfoId = Guid.NewGuid(); + _mockIPdfPartitionerLogRepository.Setup(x => x.FindByPdfPartitionerRunInfoIdAsync(pdfPartitionerRunInfoId)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _pdfPartitionerLogService.GetByPdfPartitionerRunInfoIdAsync(pdfPartitionerRunInfoId)); + _mockIPdfPartitionerLogRepository.Verify(x => x.FindByPdfPartitionerRunInfoIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task SaveAsync_PdfPartitionerLog_Returned() + { + var pdfPartitionerRunInfoId = Guid.NewGuid(); + var pdfPartitionerLogId = 2; + var pdfPartitionerLog = new PdfPartitionerLog() + { + PdfPartitionerLogId = pdfPartitionerLogId, + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId + }; + _mockIPdfPartitionerLogRepository.Setup(x => x.AddAsync(pdfPartitionerLog)).ReturnsAsync(pdfPartitionerLog); + var result = await _pdfPartitionerLogService.SaveAsync(pdfPartitionerLog); + Assert.IsNotNull(result); + Assert.AreEqual(pdfPartitionerRunInfoId, result.PdfPartitionerRunInfoId); + Assert.AreEqual(pdfPartitionerLogId, result.PdfPartitionerLogId); + _mockIPdfPartitionerLogRepository.Verify(x => x.AddAsync(It.IsAny()), Times.Once); + } + + [Test] + public void SaveAsync_Exception() + { + var pdfPartitionerRunInfoId = Guid.NewGuid(); + var pdfPartitionerLogId = 2; + var pdfPartitionerLog = new PdfPartitionerLog() + { + PdfPartitionerLogId = pdfPartitionerLogId, + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId + }; + _mockIPdfPartitionerLogRepository.Setup(x => x.AddAsync(pdfPartitionerLog)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _pdfPartitionerLogService.SaveAsync(pdfPartitionerLog)); + _mockIPdfPartitionerLogRepository.Verify(x => x.AddAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task Delete_Success() + { + var pdfPartitionerRunInfoId = Guid.NewGuid(); + var pdfPartitionerLogId = 2; + var pdfPartitionerLog = new PdfPartitionerLog() + { + PdfPartitionerLogId = pdfPartitionerLogId, + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId + }; + _mockIPdfPartitionerLogRepository.Setup(x => x.FindByIdAsync(pdfPartitionerLogId)).ReturnsAsync(pdfPartitionerLog); + _mockIPdfPartitionerLogRepository.Setup(x => x.Remove(pdfPartitionerLog)); + + await _pdfPartitionerLogService.Delete(pdfPartitionerLogId); + _mockIPdfPartitionerLogRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockIPdfPartitionerLogRepository.Verify(x => x.Remove(It.IsAny()), Times.Once); + } + + [Test] + public void Delete_FindByIdAsync_ThrowsException() + { + var pdfPartitionerRunInfoId = Guid.NewGuid(); + var pdfPartitionerLogId = 2; + var pdfPartitionerLog = new PdfPartitionerLog() + { + PdfPartitionerLogId = pdfPartitionerLogId, + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId + }; + _mockIPdfPartitionerLogRepository.Setup(x => x.FindByIdAsync(pdfPartitionerLogId)).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _pdfPartitionerLogService.Delete(pdfPartitionerLogId)); + _mockIPdfPartitionerLogRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockIPdfPartitionerLogRepository.Verify(x => x.Remove(It.IsAny()), Times.Never); + } + + [Test] + public void Delete_Remove_ThrowsException() + { + var pdfPartitionerRunInfoId = Guid.NewGuid(); + var pdfPartitionerLogId = 2; + var pdfPartitionerLog = new PdfPartitionerLog() + { + PdfPartitionerLogId = pdfPartitionerLogId, + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId + }; + _mockIPdfPartitionerLogRepository.Setup(x => x.FindByIdAsync(pdfPartitionerLogId)).ReturnsAsync(pdfPartitionerLog); + _mockIPdfPartitionerLogRepository.Setup(x => x.Remove(pdfPartitionerLog)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _pdfPartitionerLogService.Delete(pdfPartitionerLogId)); + _mockIPdfPartitionerLogRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockIPdfPartitionerLogRepository.Verify(x => x.Remove(It.IsAny()), Times.Once); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/PdfPartitionerRunInfoServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/PdfPartitionerRunInfoServiceTest.cs new file mode 100644 index 0000000..1804d67 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/PdfPartitionerRunInfoServiceTest.cs @@ -0,0 +1,209 @@ +using System; +using System.Threading.Tasks; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestorLib.Repositories; +namespace LCU.API.Internal.DocumentIngestorTests.Services; + +public class PdfPartitionerRunInfoServiceTest +{ + private PdfPartitionerRunInfoService _pdfPartitionerRunInfoService; + private Mock _unitOfWork; + private Mock _mockPdfPartitionerRunInfoRepository; + + [SetUp] + public void Setup() + { + _unitOfWork = new Mock(); + _mockPdfPartitionerRunInfoRepository = new Mock(); + _pdfPartitionerRunInfoService = new PdfPartitionerRunInfoService(_unitOfWork.Object, _mockPdfPartitionerRunInfoRepository.Object); + } + + [Test] + public async Task GetByIdAsync_PdfPartitionerRunInfo_Returned() + { + var pdfPartitionerRunInfoId = Guid.NewGuid(); + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo() + { + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId, + StartTimeStamp = Convert.ToDateTime("1/1/2022"), + PdfParserType = PdfParserTypes.FosLoanStatement, + Path = "\\\\Test\\Path", + IndexTotal = 3 + }; + _mockPdfPartitionerRunInfoRepository.Setup(x => x.FindByIdAsync(pdfPartitionerRunInfoId)).ReturnsAsync(pdfPartitionerRunInfo); + var result = await _pdfPartitionerRunInfoService.GetByIdAsync(pdfPartitionerRunInfoId); + Assert.IsNotNull(result); + Assert.AreEqual(pdfPartitionerRunInfoId, result.PdfPartitionerRunInfoId); + _mockPdfPartitionerRunInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public void GetByIdAsync_Exception() + { + var pdfPartitionerRunInfoId = Guid.NewGuid(); + _mockPdfPartitionerRunInfoRepository.Setup(x => x.FindByIdAsync(pdfPartitionerRunInfoId)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _pdfPartitionerRunInfoService.GetByIdAsync(pdfPartitionerRunInfoId)); + _mockPdfPartitionerRunInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task SaveAsync_PdfPartitionerRunInfo_Returned() + { + var pdfPartitionerRunInfoId = Guid.NewGuid(); + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo() + { + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId, + StartTimeStamp = Convert.ToDateTime("1/1/2022"), + PdfParserType = PdfParserTypes.FosLoanStatement, + Path = "\\\\Test\\Path", + IndexTotal = 3 + }; + _mockPdfPartitionerRunInfoRepository.Setup(x => x.AddAsync(pdfPartitionerRunInfo)).ReturnsAsync(pdfPartitionerRunInfo); + var result = await _pdfPartitionerRunInfoService.SaveAsync(pdfPartitionerRunInfo); + Assert.IsNotNull(result); + Assert.AreEqual(pdfPartitionerRunInfoId, result.PdfPartitionerRunInfoId); + _mockPdfPartitionerRunInfoRepository.Verify(x => x.AddAsync(It.IsAny()), Times.Once); + } + + [Test] + public void SaveAsync_Exception() + { + var pdfPartitionerRunInfoId = Guid.NewGuid(); + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo() + { + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId, + StartTimeStamp = Convert.ToDateTime("1/1/2022"), + PdfParserType = PdfParserTypes.FosLoanStatement, + Path = "\\\\Test\\Path", + IndexTotal = 3 + }; + _mockPdfPartitionerRunInfoRepository.Setup(x => x.AddAsync(pdfPartitionerRunInfo)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _pdfPartitionerRunInfoService.SaveAsync(pdfPartitionerRunInfo)); + _mockPdfPartitionerRunInfoRepository.Verify(x => x.AddAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task Update_PdfPartitionerRunInfo_Returned() + { + var pdfPartitionerRunInfoId = Guid.NewGuid(); + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo() + { + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId, + StartTimeStamp = Convert.ToDateTime("1/1/2022"), + PdfParserType = PdfParserTypes.FosLoanStatement, + Path = "\\\\Test\\Path", + IndexTotal = 3 + }; + _mockPdfPartitionerRunInfoRepository.Setup(x => x.FindByIdAsync(pdfPartitionerRunInfoId)).ReturnsAsync(pdfPartitionerRunInfo); + _mockPdfPartitionerRunInfoRepository.Setup(x => x.Update(pdfPartitionerRunInfo)); + + var result = await _pdfPartitionerRunInfoService.Update(pdfPartitionerRunInfo); + Assert.IsNotNull(result); + Assert.AreEqual(pdfPartitionerRunInfoId, result.PdfPartitionerRunInfoId); + _mockPdfPartitionerRunInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockPdfPartitionerRunInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Once); + } + + [Test] + public void Update_FindByIdAsync_ThrowsException() + { + var pdfPartitionerRunInfoId = Guid.NewGuid(); + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo() + { + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId, + StartTimeStamp = Convert.ToDateTime("1/1/2022"), + PdfParserType = PdfParserTypes.FosLoanStatement, + Path = "\\\\Test\\Path", + IndexTotal = 3 + }; + _mockPdfPartitionerRunInfoRepository.Setup(x => x.FindByIdAsync(pdfPartitionerRunInfoId)).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _pdfPartitionerRunInfoService.Update(pdfPartitionerRunInfo)); + _mockPdfPartitionerRunInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockPdfPartitionerRunInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Never); + } + + [Test] + public void Update_Update_ThrowsException() + { + var pdfPartitionerRunInfoId = Guid.NewGuid(); + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo() + { + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId, + StartTimeStamp = Convert.ToDateTime("1/1/2022"), + PdfParserType = PdfParserTypes.FosLoanStatement, + Path = "\\\\Test\\Path", + IndexTotal = 3 + }; + _mockPdfPartitionerRunInfoRepository.Setup(x => x.FindByIdAsync(pdfPartitionerRunInfoId)).ReturnsAsync(pdfPartitionerRunInfo); + _mockPdfPartitionerRunInfoRepository.Setup(x => x.Update(pdfPartitionerRunInfo)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _pdfPartitionerRunInfoService.Update(pdfPartitionerRunInfo)); + _mockPdfPartitionerRunInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockPdfPartitionerRunInfoRepository.Verify(x => x.Update(It.IsAny()), Times.Once); + } + + [Test] + public async Task Delete_Success() + { + var pdfPartitionerRunInfoId = Guid.NewGuid(); + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo() + { + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId, + StartTimeStamp = Convert.ToDateTime("1/1/2022"), + PdfParserType = PdfParserTypes.FosLoanStatement, + Path = "\\\\Test\\Path", + IndexTotal = 3 + }; + _mockPdfPartitionerRunInfoRepository.Setup(x => x.FindByIdAsync(pdfPartitionerRunInfoId)).ReturnsAsync(pdfPartitionerRunInfo); + _mockPdfPartitionerRunInfoRepository.Setup(x => x.Remove(pdfPartitionerRunInfo)); + + await _pdfPartitionerRunInfoService.Delete(pdfPartitionerRunInfoId); + _mockPdfPartitionerRunInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockPdfPartitionerRunInfoRepository.Verify(x => x.Remove(It.IsAny()), Times.Once); + } + + [Test] + public void Delete_FindByIdAsync_ThrowsException() + { + var pdfPartitionerRunInfoId = Guid.NewGuid(); + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo() + { + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId, + StartTimeStamp = Convert.ToDateTime("1/1/2022"), + PdfParserType = PdfParserTypes.FosLoanStatement, + Path = "\\\\Test\\Path", + IndexTotal = 3 + }; + _mockPdfPartitionerRunInfoRepository.Setup(x => x.FindByIdAsync(pdfPartitionerRunInfoId)).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _pdfPartitionerRunInfoService.Delete(pdfPartitionerRunInfoId)); + _mockPdfPartitionerRunInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockPdfPartitionerRunInfoRepository.Verify(x => x.Remove(It.IsAny()), Times.Never); + } + + [Test] + public void Delete_Remove_ThrowsException() + { + var pdfPartitionerRunInfoId = Guid.NewGuid(); + var pdfPartitionerRunInfo = new PdfPartitionerRunInfo() + { + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId, + StartTimeStamp = Convert.ToDateTime("1/1/2022"), + PdfParserType = PdfParserTypes.FosLoanStatement, + Path = "\\\\Test\\Path", + IndexTotal = 3 + }; + _mockPdfPartitionerRunInfoRepository.Setup(x => x.FindByIdAsync(pdfPartitionerRunInfoId)).ReturnsAsync(pdfPartitionerRunInfo); + _mockPdfPartitionerRunInfoRepository.Setup(x => x.Remove(pdfPartitionerRunInfo)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _pdfPartitionerRunInfoService.Delete(pdfPartitionerRunInfoId)); + _mockPdfPartitionerRunInfoRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockPdfPartitionerRunInfoRepository.Verify(x => x.Remove(It.IsAny()), Times.Once); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/ProcessingLogServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/ProcessingLogServiceTest.cs new file mode 100644 index 0000000..3920f2e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/ProcessingLogServiceTest.cs @@ -0,0 +1,304 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using System.Linq; +using Moq; +using NUnit.Framework; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.Exceptions; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.API.Internal.DocumentIngestorLib.Repositories; +namespace LCU.API.Internal.DocumentIngestorTests.Services; + +public class ProcessingLogServiceTest +{ + private ProcessingLogService _processingLogService; + private Mock _unitOfWork; + private Mock _mockProcessingLogRepository; + + [SetUp] + public void Setup() + { + _unitOfWork = new Mock(); + _mockProcessingLogRepository = new Mock(); + _processingLogService = new ProcessingLogService(_unitOfWork.Object, _mockProcessingLogRepository.Object); + } + + [Test] + public async Task GetAsync_ProcessingLogs_Returned() + { + var documentProcessingInfoId = 1; + var processingLogId = 2; + var processingLogs = new List() + { + new ProcessingLog() + { + ProcessingLogId = processingLogId, + DocumentProcessingInfoId = documentProcessingInfoId + } + }; + _mockProcessingLogRepository.Setup(x => x.FindAsync()).ReturnsAsync(processingLogs); + var result = await _processingLogService.GetAsync(); + Assert.IsNotNull(result); + Assert.AreEqual(1, result.Count()); + _mockProcessingLogRepository.Verify(x => x.FindAsync(), Times.Once); + } + + [Test] + public void GetAsync_Exception() + { + _mockProcessingLogRepository.Setup(x => x.FindAsync()).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _processingLogService.GetAsync()); + _mockProcessingLogRepository.Verify(x => x.FindAsync(), Times.Once); + } + + [Test] + public async Task GetByIdAsync_ProcessingLog_Returned() + { + var documentProcessingInfoId = 1; + var processingLogId = 2; + var processingLog = new ProcessingLog() + { + ProcessingLogId = processingLogId, + DocumentProcessingInfoId = documentProcessingInfoId + }; + _mockProcessingLogRepository.Setup(x => x.FindByIdAsync(processingLogId)).ReturnsAsync(processingLog); + var result = await _processingLogService.GetByIdAsync(processingLogId); + Assert.IsNotNull(result); + Assert.AreEqual(documentProcessingInfoId, result.DocumentProcessingInfoId); + Assert.AreEqual(processingLogId, result.ProcessingLogId); + _mockProcessingLogRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public void GetByIdAsync_Exception() + { + var processingLogId = 2; + _mockProcessingLogRepository.Setup(x => x.FindByIdAsync(processingLogId)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _processingLogService.GetByIdAsync(processingLogId)); + _mockProcessingLogRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task GetByDocumentProcessingInfoIdAsync_ProcessingLogs_Returned() + { + var documentProcessingInfoId = 1; + var processingLogId = 2; + var processingLogs = new List() + { + new ProcessingLog() + { + ProcessingLogId = processingLogId, + DocumentProcessingInfoId = documentProcessingInfoId + } + }; + _mockProcessingLogRepository.Setup(x => x.FindByDocumentProcessingInfoIdAsync(documentProcessingInfoId)).ReturnsAsync(processingLogs); + var result = await _processingLogService.GetByDocumentProcessingInfoIdAsync(documentProcessingInfoId); + Assert.IsNotNull(result); + Assert.AreEqual(1, result.Count()); + _mockProcessingLogRepository.Verify(x => x.FindByDocumentProcessingInfoIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public void GetByDocumentProcessingInfoIdAsync_Exception() + { + var documentProcessingInfoId = 1; + _mockProcessingLogRepository.Setup(x => x.FindByDocumentProcessingInfoIdAsync(documentProcessingInfoId)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _processingLogService.GetByDocumentProcessingInfoIdAsync(documentProcessingInfoId)); + _mockProcessingLogRepository.Verify(x => x.FindByDocumentProcessingInfoIdAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task SaveAsync_ProcessingLog_Returned() + { + var documentProcessingInfoId = 1; + var processingLogId = 2; + var processingLog = new ProcessingLog() + { + ProcessingLogId = processingLogId, + DocumentProcessingInfoId = documentProcessingInfoId + }; + _mockProcessingLogRepository.Setup(x => x.AddAsync(processingLog)).ReturnsAsync(processingLog); + var result = await _processingLogService.SaveAsync(processingLog); + Assert.IsNotNull(result); + Assert.AreEqual(documentProcessingInfoId, result.DocumentProcessingInfoId); + Assert.AreEqual(processingLogId, result.ProcessingLogId); + _mockProcessingLogRepository.Verify(x => x.AddAsync(It.IsAny()), Times.Once); + } + + [Test] + public void SaveAsync_Exception() + { + var documentProcessingInfoId = 1; + var processingLogId = 2; + var processingLog = new ProcessingLog() + { + ProcessingLogId = processingLogId, + DocumentProcessingInfoId = documentProcessingInfoId + }; + _mockProcessingLogRepository.Setup(x => x.AddAsync(processingLog)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _processingLogService.SaveAsync(processingLog)); + _mockProcessingLogRepository.Verify(x => x.AddAsync(It.IsAny()), Times.Once); + } + + [Test] + public async Task SaveRangeAsync_ProcessingLog_Returned() + { + var processingLogs = new List + { + new() + { + ProcessingLogId = DateTime.Now.Millisecond, + DocumentProcessingInfoId = DateTime.Now.Millisecond + }, + new() + { + ProcessingLogId = DateTime.Now.Millisecond + 1, + DocumentProcessingInfoId = DateTime.Now.Millisecond + }, + new() + { + ProcessingLogId = DateTime.Now.Millisecond + 2, + DocumentProcessingInfoId = DateTime.Now.Millisecond + } + }; + _mockProcessingLogRepository.Setup(x => x.AddRangeAsync(processingLogs)); + await _processingLogService.SaveRangeAsync(processingLogs); + _mockProcessingLogRepository.Verify(x => x.AddRangeAsync(It.IsAny>()), Times.Once); + } + + [Test] + public void SaveRangeAsync_Exception() + { + var processingLogs = new List + { + new() + { + ProcessingLogId = DateTime.Now.Millisecond, + DocumentProcessingInfoId = DateTime.Now.Millisecond + }, + new() + { + ProcessingLogId = DateTime.Now.Millisecond + 1, + DocumentProcessingInfoId = DateTime.Now.Millisecond + }, + new() + { + ProcessingLogId = DateTime.Now.Millisecond + 2, + DocumentProcessingInfoId = DateTime.Now.Millisecond + } + }; + _mockProcessingLogRepository.Setup(x => x.AddRangeAsync(processingLogs)).ThrowsAsync(new Exception("Error")); + Assert.ThrowsAsync(async () => await _processingLogService.SaveRangeAsync(processingLogs)); + _mockProcessingLogRepository.Verify(x => x.AddRangeAsync(It.IsAny>()), Times.Once); + } + + [Test] + public async Task Update_ProcessingLog_Returned() + { + var documentProcessingInfoId = 1; + var processingLogId = 2; + var processingLog = new ProcessingLog() + { + ProcessingLogId = processingLogId, + DocumentProcessingInfoId = documentProcessingInfoId + }; + _mockProcessingLogRepository.Setup(x => x.FindByIdAsync(processingLogId)).ReturnsAsync(processingLog); + _mockProcessingLogRepository.Setup(x => x.Update(processingLog)); + + var result = await _processingLogService.Update(processingLog); + Assert.IsNotNull(result); + Assert.AreEqual(documentProcessingInfoId, result.DocumentProcessingInfoId); + Assert.AreEqual(processingLogId, result.ProcessingLogId); + _mockProcessingLogRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockProcessingLogRepository.Verify(x => x.Update(It.IsAny()), Times.Once); + } + + [Test] + public void Update_FindByIdAsync_ThrowsException() + { + var documentProcessingInfoId = 1; + var processingLogId = 2; + var processingLog = new ProcessingLog() + { + ProcessingLogId = processingLogId, + DocumentProcessingInfoId = documentProcessingInfoId + }; + _mockProcessingLogRepository.Setup(x => x.FindByIdAsync(processingLogId)).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _processingLogService.Update(processingLog)); + _mockProcessingLogRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockProcessingLogRepository.Verify(x => x.Update(It.IsAny()), Times.Never); + } + + [Test] + public void Update_Update_ThrowsException() + { + var documentProcessingInfoId = 1; + var processingLogId = 2; + var processingLog = new ProcessingLog() + { + ProcessingLogId = processingLogId, + DocumentProcessingInfoId = documentProcessingInfoId + }; + _mockProcessingLogRepository.Setup(x => x.FindByIdAsync(processingLogId)).ReturnsAsync(processingLog); + _mockProcessingLogRepository.Setup(x => x.Update(processingLog)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _processingLogService.Update(processingLog)); + _mockProcessingLogRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockProcessingLogRepository.Verify(x => x.Update(It.IsAny()), Times.Once); + } + + [Test] + public async Task Delete_Success() + { + var documentProcessingInfoId = 1; + var processingLogId = 2; + var processingLog = new ProcessingLog() + { + ProcessingLogId = processingLogId, + DocumentProcessingInfoId = documentProcessingInfoId + }; + _mockProcessingLogRepository.Setup(x => x.FindByIdAsync(processingLogId)).ReturnsAsync(processingLog); + _mockProcessingLogRepository.Setup(x => x.Remove(processingLog)); + + await _processingLogService.Delete(processingLogId); + _mockProcessingLogRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockProcessingLogRepository.Verify(x => x.Remove(It.IsAny()), Times.Once); + } + + [Test] + public void Delete_FindByIdAsync_ThrowsException() + { + var documentProcessingInfoId = 1; + var processingLogId = 2; + var processingLog = new ProcessingLog() + { + ProcessingLogId = processingLogId, + DocumentProcessingInfoId = documentProcessingInfoId + }; + _mockProcessingLogRepository.Setup(x => x.FindByIdAsync(processingLogId)).ThrowsAsync(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _processingLogService.Delete(processingLogId)); + _mockProcessingLogRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockProcessingLogRepository.Verify(x => x.Remove(It.IsAny()), Times.Never); + } + + [Test] + public void Delete_Remove_ThrowsException() + { + var documentProcessingInfoId = 1; + var processingLogId = 2; + var processingLog = new ProcessingLog() + { + ProcessingLogId = processingLogId, + DocumentProcessingInfoId = documentProcessingInfoId + }; + _mockProcessingLogRepository.Setup(x => x.FindByIdAsync(processingLogId)).ReturnsAsync(processingLog); + _mockProcessingLogRepository.Setup(x => x.Remove(processingLog)).Throws(new Exception("Error")); + + Assert.ThrowsAsync(async () => await _processingLogService.Delete(processingLogId)); + _mockProcessingLogRepository.Verify(x => x.FindByIdAsync(It.IsAny()), Times.Once); + _mockProcessingLogRepository.Verify(x => x.Remove(It.IsAny()), Times.Once); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/UploadCompletionReprocessingServiceTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/UploadCompletionReprocessingServiceTest.cs new file mode 100644 index 0000000..c367fd9 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Services/UploadCompletionReprocessingServiceTest.cs @@ -0,0 +1,251 @@ +using System; +using System.Threading.Tasks; +using System.Linq; +using Moq; +using NUnit.Framework; +using LCU.API.Internal.DocumentIngestor.Services; +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.API.Internal.DocumentIngestor.Configurations; +using LCU.API.Internal.DocumentIngestor.Services.IngestionOperationServices; +using LCU.API.Internal.DocumentIngestor.Services.MicroApiServices; +using LCU.Library.DocumentType.Models.Responses.External; +using LCU.Library.Internal.ApiResponse.Models; +using LCU.Library.Internal.Exceptions; +using Serilog; +using System.Collections.Generic; + +namespace LCU.API.Internal.DocumentIngestorTests.Services; + +public class UploadCompletionReprocessingServiceTest +{ + private UploadCompletionReprocessingService _uploadCompletionReprocessingService; + private Mock _mockIngestorRunInfoService; + private Mock _mockDocumentProcessingInfoService; + private Mock _mockUploadCompletionService; + private Mock _mockDocumentTypeRetrieverService; + private ApiConfiguration _apiConfiguration; + private readonly Mock _logger = new(); + private readonly ILogger _originalLogger = Log.Logger; + + [SetUp] + public void Setup() + { + Log.Logger = _logger.Object; + + _mockIngestorRunInfoService = new Mock(); + _mockDocumentProcessingInfoService = new Mock(); + _mockDocumentTypeRetrieverService = new Mock(); + _mockUploadCompletionService = new Mock(); + _apiConfiguration = new ApiConfiguration(); + _uploadCompletionReprocessingService = new UploadCompletionReprocessingService(_mockIngestorRunInfoService.Object, + _mockDocumentProcessingInfoService.Object, + _mockDocumentTypeRetrieverService.Object, + _mockUploadCompletionService.Object, + _apiConfiguration); + } + + [TearDown] + public void TearDown() + { + Log.Logger = _originalLogger; + } + + [Test] + public async Task QueueReprocessUploadCompletionByDocumentProcessingInfoId_Success() + { + + var documentProcessingInfoId = DateTime.Now.Millisecond; + var userName = Guid.NewGuid().ToString(); + var documentProcessingInfo = SetupGetDocumentProcessingInfo(documentProcessingInfoId); + var ingestorRunInfo = SetupGetIngestorRunInfo(documentProcessingInfo.IngestorRunInfoId); + SetupDocumentInformation(documentProcessingInfo.DocumentId); + + _mockDocumentProcessingInfoService.Setup(x => x.UpdateStatusAndAddLog(documentProcessingInfoId, + documentProcessingInfo.StatusType, + It.IsAny(), + userName, + It.IsAny())).ReturnsAsync(documentProcessingInfo); + + await _uploadCompletionReprocessingService.QueueReprocessUploadCompletionByDocumentProcessingInfoId(documentProcessingInfoId, userName); + + _mockDocumentProcessingInfoService.Verify(x => x.GetByIdAsync(documentProcessingInfoId), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.GetByIdAsync(ingestorRunInfo.IngestorRunInfoId), Times.Once); + _mockDocumentTypeRetrieverService.Verify(x => x.GetDocumentInformationById(documentProcessingInfo.DocumentId ?? Guid.Empty), Times.Once); + _mockDocumentProcessingInfoService.Verify(x => x.UpdateStatusAndAddLog(documentProcessingInfoId, + It.IsAny(), + It.IsAny(), + userName, + It.IsAny()), Times.Once); + _mockUploadCompletionService.Verify(x => x.HandleUploadCompletion(It.IsAny>()), Times.Once); + } + + [Test] + public void QueueReprocessUploadCompletionByDocumentProcessingInfoId_Failure_Exception() + { + var id = DateTime.Now.Millisecond; + var userName = Guid.NewGuid().ToString(); + _mockDocumentProcessingInfoService.Setup(x => x.GetByIdAsync(id)).ThrowsAsync(new Exception("Test Error")); + Assert.ThrowsAsync(async () => await _uploadCompletionReprocessingService + .QueueReprocessUploadCompletionByDocumentProcessingInfoId(id, userName)); + _mockDocumentProcessingInfoService.Verify(x => x.GetByIdAsync(It.IsAny()), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.GetByIdAsync(It.IsAny()), Times.Never); + _mockDocumentTypeRetrieverService.Verify(x => x.GetDocumentInformationById(It.IsAny()), Times.Never); + _mockDocumentProcessingInfoService.Verify(x => x.UpdateStatusAndAddLog(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockUploadCompletionService.Verify(x => x.HandleUploadCompletion(It.IsAny>()), Times.Never); + } + + [Test] + public void QueueReprocessUploadCompletionByDocumentProcessingInfoId_Failure_ArgumentNullException() + { + var id = DateTime.Now.Millisecond; + var userName = Guid.NewGuid().ToString(); + _mockDocumentProcessingInfoService.Setup(x => x.GetByIdAsync(id)).ThrowsAsync(new ArgumentNullException("Test Error")); + Assert.ThrowsAsync(async () => await _uploadCompletionReprocessingService + .QueueReprocessUploadCompletionByDocumentProcessingInfoId(id, userName)); + + _mockDocumentProcessingInfoService.Verify(x => x.GetByIdAsync(id), Times.Once); + _mockIngestorRunInfoService.Verify(x => x.GetByIdAsync(It.IsAny()), Times.Never); + _mockDocumentProcessingInfoService.Verify(x => x.UpdateStatusAndAddLog(It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny(), + It.IsAny()), Times.Never); + _mockUploadCompletionService.Verify(x => x.HandleUploadCompletion(It.IsAny>()), Times.Never); + } + + [Test] + public void QueueReprocessAllNotificationDataFailures_InfoServiceThrowsArgumentNull_ThrowsServiceException() + { + var processStatus = ProcessStatusTypes.NotificationDataFailure; + _mockDocumentProcessingInfoService + .Setup(s => s.GetByProcessStatusTypeAsync(processStatus, null)) + .ThrowsAsync(new ArgumentNullException()); + + Assert.ThrowsAsync(() => _uploadCompletionReprocessingService.QueueReprocessAllNotificationDataFailures(Guid.NewGuid().ToString())); + } + + [Test] + public async Task QueueReprocessAllNotificationDataFailures_InfoServiceThrows_ThrowsServiceException() + { + var processStatus = ProcessStatusTypes.NotificationDataFailure; + _mockDocumentProcessingInfoService + .Setup(s => s.GetByProcessStatusTypeAsync(processStatus, null)) + .ThrowsAsync(new Exception()); + + Assert.ThrowsAsync(() => _uploadCompletionReprocessingService.QueueReprocessAllNotificationDataFailures(Guid.NewGuid().ToString())); + } + + [Test] + public async Task QueueReprocessAllNotificationDataFailures_InfoServiceReturnsMoreThanLimit_RequeuesUpToLimit() + { + var id = DateTime.Now.Millisecond; + var username = Guid.NewGuid().ToString(); + var notificationDataFailures = Enumerable + .Repeat(() => SetupGetDocumentProcessingInfo(id), 16) + .Select(f => f()) + .ToArray(); + foreach (var info in notificationDataFailures) + { + SetupGetIngestorRunInfo(info.IngestorRunInfoId); + SetupDocumentInformation(info.DocumentId); + } + + var processStatus = ProcessStatusTypes.NotificationDataFailure; + + _apiConfiguration.NotificationDataFailureReprocessLimit = notificationDataFailures.Length / 2; + _mockDocumentProcessingInfoService + .Setup(s => s.GetByProcessStatusTypeAsync(processStatus, null)) + .ReturnsAsync(notificationDataFailures); + + await _uploadCompletionReprocessingService.QueueReprocessAllNotificationDataFailures(username); + + _mockDocumentProcessingInfoService + .Verify + ( + s => s.UpdateStatusAndAddLog + ( + It.Is(id => notificationDataFailures.Any(f => f.DocumentProcessingInfoId == id)), + ProcessStatusTypes.UploadCompletionReprocessing, + It.IsAny(), + username, + It.IsAny() + ), + Times.Exactly(_apiConfiguration.NotificationDataFailureReprocessLimit) + ); + _mockUploadCompletionService + .Verify + ( + dp => dp.HandleUploadCompletion + ( + It.IsAny>() + ), + Times.Exactly(_apiConfiguration.NotificationDataFailureReprocessLimit) + ); + } + + private DocumentProcessingInfo SetupGetDocumentProcessingInfo(int id) + { + var info = new DocumentProcessingInfo + { + IngestorRunInfoId = Guid.NewGuid(), + CreatedDate = DateTime.Now, + DocumentValuePayload = Guid.NewGuid().ToString(), + StatusType = Random(), + DocumentFileName = Guid.NewGuid().ToString(), + ProcessCount = DateTime.Now.Millisecond, + DocumentType = "EAgreement", + DocumentBusinessName = Guid.NewGuid().ToString(), + DocumentProcessingInfoId = id, + DocumentId = Guid.NewGuid() + }; + + _mockDocumentProcessingInfoService + .Setup(s => s.GetByIdAsync(id)) + .ReturnsAsync(info); + + return info; + } + + private IngestorRunInfo SetupGetIngestorRunInfo(Guid ingestorRunInfoId) + { + var info = new IngestorRunInfo + { + IngestorRunInfoId = ingestorRunInfoId, + StartTimeStamp = DateTime.Now, + IngestorType = Random(), + IndexFileName = Guid.NewGuid().ToString(), + IndexFilePath = Guid.NewGuid().ToString(), + IndexTotal = DateTime.Now.Millisecond + }; + + _mockIngestorRunInfoService + .Setup(s => s.GetByIdAsync(ingestorRunInfoId)) + .ReturnsAsync(info); + + return info; + } + + private EnrichedDocumentMetadataResponse SetupDocumentInformation(Guid? documentId) + { + var info = new EnrichedDocumentMetadataResponse() + { + DocumentId = documentId ?? Guid.Empty, + Type = "LnNent", + PersonNumbers = new[] { "123" }, + AccountNumber = 345 + }; + + _mockDocumentTypeRetrieverService + .Setup(s => s.GetDocumentInformationById(documentId ?? Guid.Empty)) + .ReturnsAsync(info); + + return info; + } + + private static T Random() where T : struct, Enum => Enum.GetValues()[DateTime.Now.Millisecond % (Enum.GetValues().Length - 1)]; +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/TestContent/Test_OSG_Index_File/Test_OSG_Index_File.XML b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/TestContent/Test_OSG_Index_File/Test_OSG_Index_File.XML new file mode 100644 index 0000000..b24f2d7 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/TestContent/Test_OSG_Index_File/Test_OSG_Index_File.XML @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/TestContent/Test_OSG_Index_File/Test_OSG_Index_File_1099_MISC.XML b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/TestContent/Test_OSG_Index_File/Test_OSG_Index_File_1099_MISC.XML new file mode 100644 index 0000000..7814efc --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/TestContent/Test_OSG_Index_File/Test_OSG_Index_File_1099_MISC.XML @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Utilities/ToDetailStringExtensionTest.cs b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Utilities/ToDetailStringExtensionTest.cs new file mode 100644 index 0000000..10264e0 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.API.Internal.DocumentIngestorTests/Utilities/ToDetailStringExtensionTest.cs @@ -0,0 +1,142 @@ +using System; +using LCU.API.Internal.DocumentIngestor.Utilities; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Accounts; +using LCU.Library.Internal.CoreApiWrapperModel.CoreModels.Tax; +using NUnit.Framework; + +namespace LCU.API.Internal.DocumentIngestorTests.Utilities; + +public class ToDetailStringExtensionTest +{ + [Test] + public void ToDetailString_AccountOwnershipPersonNumberNotZero_FormatsPersonDetail() + { + var ownership = PersonOwnershipFactory(); + + var detail = ownership.ToDetailString(); + + StringAssert.Contains(ownership.PersonNumber.ToString(), detail); + StringAssert.Contains(ownership.FirstName, detail); + StringAssert.Contains(ownership.MiddleName, detail); + StringAssert.Contains(ownership.LastName, detail); + } + + [Test] + public void ToDetailString_AccountOwnershipPersonNumberZero_FormatsOrganizationDetail() + { + var ownership = OrganizationOwnershipFactory(); + + var detail = ownership.ToDetailString(); + + StringAssert.Contains(ownership.OrganizationName, detail); + StringAssert.Contains(ownership.ByOrgNbr.ToString(), detail); + } + + [Test] + public void ToDetailString_PersonTaxIdDataResponse_FormatsPersonDetail() + { + var ownership = PersonPersonTaxDataFactory(); + + var detail = ownership.ToDetailString(); + + StringAssert.Contains(ownership.PersonNumber.ToString(), detail); + StringAssert.Contains(ownership.FirstName, detail); + StringAssert.Contains(ownership.MiddleName, detail); + StringAssert.Contains(ownership.LastName, detail); + } + + [Test] + public void ToDetailString_OrganizationTaxIdDataResponse_FormatsOrganizationDetail() + { + var ownership = OrganizationTaxDataFactory(); + + var detail = ownership.ToDetailString(); + + StringAssert.Contains(ownership.Name, detail); + StringAssert.Contains(ownership.OrganizationNumber.ToString(), detail); + } + + [Test] + public void ToDetailString_EnumerableAccountOwnerships_SpacesBetweenEach() + { + var ownerships = new[] + { + PersonOwnershipFactory(), + OrganizationOwnershipFactory(), + PersonOwnershipFactory(), + OrganizationOwnershipFactory() + }; + + var detail = ownerships.ToDetailString(); + + foreach (var owner in ownerships) + { + StringAssert.IsMatch($"{owner.ToDetailString()}(; |$)", detail); + } + } + + [Test] + public void ToDetailString_EnumerablePersonTaxIdDataResponses_SpacesBetweenEach() + { + var ownerships = new[] + { + PersonPersonTaxDataFactory(), + PersonPersonTaxDataFactory(), + PersonPersonTaxDataFactory() + }; + + var detail = ownerships.ToDetailString(); + + foreach (var owner in ownerships) + { + StringAssert.IsMatch($"{owner.ToDetailString()}(; |$)", detail); + } + } + + [Test] + public void ToDetailString_EnumerableOrganizationTaxIdDataResponses_SpacesBetweenEach() + { + var ownerships = new[] + { + OrganizationTaxDataFactory(), + OrganizationTaxDataFactory(), + OrganizationTaxDataFactory() + }; + + var detail = ownerships.ToDetailString(); + + foreach (var owner in ownerships) + { + StringAssert.IsMatch($"{owner.ToDetailString()}(; |$)", detail); + } + } + + private static AccountOwnership PersonOwnershipFactory() => new() + { + PersonNumber = DateTime.Now.Millisecond, + FirstName = Guid.NewGuid().ToString(), + MiddleName = Guid.NewGuid().ToString(), + LastName = Guid.NewGuid().ToString() + }; + + private static AccountOwnership OrganizationOwnershipFactory() => new() + { + PersonNumber = 0, + OrganizationName = Guid.NewGuid().ToString(), + ByOrgNbr = DateTime.Now.Millisecond + }; + + private static PersonTaxIdDataResponse PersonPersonTaxDataFactory() => new() + { + PersonNumber = DateTime.Now.Millisecond, + FirstName = Guid.NewGuid().ToString(), + MiddleName = Guid.NewGuid().ToString(), + LastName = Guid.NewGuid().ToString() + }; + + private static OrganizationTaxIdDataResponse OrganizationTaxDataFactory() => new() + { + Name = Guid.NewGuid().ToString(), + OrganizationNumber = DateTime.Now.Millisecond + }; +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Constants/DocumentProcessingInfoSortableFields.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Constants/DocumentProcessingInfoSortableFields.cs new file mode 100644 index 0000000..6869f84 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Constants/DocumentProcessingInfoSortableFields.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; + +namespace LCU.Library.Internal.DocumentIngestorModels.Constants +{ + public static class DocumentProcessingInfoSortableFields + { + public static readonly List DocumentProcessingInfoFields = new List() + { + CreatedDate, + DocType, + DocBusinessName, + StatusType + }; + + public const string CreatedDate = "CreatedDate"; + public const string DocType = "DocumentType"; + public const string DocBusinessName = "DocumentBusinessName"; + public const string StatusType = "StatusType"; + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Constants/Users.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Constants/Users.cs new file mode 100644 index 0000000..11c3d07 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Constants/Users.cs @@ -0,0 +1,7 @@ +namespace LCU.Library.Internal.DocumentIngestorModels.Constants +{ + public static class Users + { + public const string System = "System"; + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Constants/ValidationMessages.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Constants/ValidationMessages.cs new file mode 100644 index 0000000..8fa2f22 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Constants/ValidationMessages.cs @@ -0,0 +1,13 @@ +namespace LCU.Library.Internal.DocumentIngestorModels.Constants +{ + public static class ValidationMessages + { + public const string AccountInvalidMessage = "The record is missing a valid Account Number"; + public const string FileNameInvalidMessage = "The record is missing a valid File Name"; + public const string FullNameInvalidMessage = "The record is missing a valid Full Name"; + public const string PdfInvalidMessage = "The record is missing a valid PDF"; + public const string TinInvalidMessage = "The record is missing a valid Primary TIN"; + public const string CreationDateInvalidMessage = "The record is missing a valid Creation Date"; + public const string DocumentTypeInvalidMessage = "The record is missing a valid Document Type"; + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/DocumentCodeDetailInfo.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/DocumentCodeDetailInfo.cs new file mode 100644 index 0000000..ff096a8 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/DocumentCodeDetailInfo.cs @@ -0,0 +1,7 @@ +namespace LCU.Library.Internal.DocumentIngestorModels.Entities; +public class DocumentCodeDetailInfo +{ + public string DocumentType { get; set; } + public string DocumentBusinessName { get; set; } + public string DocumentMemberFacingName { get; set; } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/DocumentProcessingInfo.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/DocumentProcessingInfo.cs new file mode 100644 index 0000000..39a6533 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/DocumentProcessingInfo.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using LCU.Library.Internal.DocumentIngestorModels.Enums; + +namespace LCU.Library.Internal.DocumentIngestorModels.Entities +{ + public class DocumentProcessingInfo + { + public DocumentProcessingInfo() + { + } + + public DocumentProcessingInfo(Guid ingestorRunInfoId, + DateTime createdDate, + string documentValuePayload, + ProcessStatusTypes statusType, + string documentFileName, + string documentType, + string documentBusinessName, + bool entityUnknown = false) + { + IngestorRunInfoId = ingestorRunInfoId; + CreatedDate = createdDate; + DocumentValuePayload = documentValuePayload; + StatusType = statusType; + DocumentFileName = documentFileName; + ProcessCount = 0; + DocumentType = documentType; + DocumentBusinessName = documentBusinessName; + EntityUnknown = entityUnknown; + } + + public int DocumentProcessingInfoId { get; set; } + public Guid? DocumentId { get; set; } + public Guid IngestorRunInfoId { get; set; } + public DateTime CreatedDate { get; set; } + public string DocumentValuePayload { get; set; } + public ProcessStatusTypes StatusType { get; set; } + public string DocumentFileName { get; set; } + public int ProcessCount { get; set; } + public string DocumentType { get; set; } + public string DocumentBusinessName { get; set; } + public bool EntityUnknown { get; set; } + + [ForeignKey("IngestorRunInfoId")] + public IngestorRunInfo IngestorRunInfo { get; set; } + + [ForeignKey("DocumentProcessingInfoId")] + public ICollection ProcessingLogs { get; set; } + + [ForeignKey("DocumentProcessingInfoId")] + public ICollection? MemberNotificationInfos { get; set; } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/DocumentTypeArchiveDeleteInfo.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/DocumentTypeArchiveDeleteInfo.cs new file mode 100644 index 0000000..74e4c31 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/DocumentTypeArchiveDeleteInfo.cs @@ -0,0 +1,26 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +namespace LCU.Library.Internal.DocumentIngestorModels.Entities; + +public class DocumentTypeArchiveDeleteInfo +{ + [Required] + public string DocumentTypeName { get; set; } + [Required] + [Range(0, int.MaxValue, ErrorMessage = "Please enter a value larger than {1}")] + public int ArchiveDays { get; set; } + [Required] + [Range(1, int.MaxValue, ErrorMessage = "Please enter a value larger than {1}")] + public int ArchiveMonths { get; set; } + public int? DeleteDays { get; set; } + + [NotMapped] + public DateTime ArchiveDate + { + get + { + return DateTime.Now.AddMonths(ArchiveMonths).AddDays(ArchiveDays); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/IngestorRunInfo.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/IngestorRunInfo.cs new file mode 100644 index 0000000..0e8f5f3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/IngestorRunInfo.cs @@ -0,0 +1,41 @@ +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using System; +using System.ComponentModel.DataAnnotations.Schema; + +namespace LCU.Library.Internal.DocumentIngestorModels.Entities +{ + public class IngestorRunInfo + { + public IngestorRunInfo() + { + + } + + public IngestorRunInfo(Guid ingestorRunInfoId, + DateTime startTimeStamp, + IngestorTypes ingestorType, + string filePath, + string indexFileName, + int indexTotal, + int ingestionRunCount = 0) + { + IngestorRunInfoId = ingestorRunInfoId; + StartTimeStamp = startTimeStamp; + IngestorType = ingestorType; + IndexFileName = indexFileName; + IndexFilePath = filePath; + IndexTotal = indexTotal; + IngestionRunCount = ingestionRunCount; + } + + public Guid IngestorRunInfoId { get; set; } + public DateTime StartTimeStamp { get; set; } + public DateTime? EndTimeStamp { get; set; } + public IngestorTypes IngestorType { get; set; } + public string IndexFilePath { get; set; } + public string IndexFileName { get; set; } + public int IndexTotal { get; set; } + public DateTime? ArchiveTimeStamp { get; set; } + public int IngestionRunCount { get; set; } = 0; + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/MemberNotificationInfo.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/MemberNotificationInfo.cs new file mode 100644 index 0000000..bd8cd62 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/MemberNotificationInfo.cs @@ -0,0 +1,18 @@ +using System; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +namespace LCU.Library.Internal.DocumentIngestorModels.Entities; + +public class MemberNotificationInfo +{ + public int MemberNotificationInfoId { get; set; } + public int DocumentProcessingInfoId { get; set; } + public DateTime UploadDate { get; set;} + public DeliveryMethod DeliveryMethod { get; set; } + public DateTime? SentTimeStamp { get; set; } + public DateTime? ResponseTimeStamp { get; set; } + public string AgreeUserId { get; set; } + public string EntityName { get; set; } + public string EmailAddress { get; set; } + public NotificationStatusTypes NotificationStatusType { get; set; } + public int Attempts { get; set; } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/OsgPreprocessorInfo.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/OsgPreprocessorInfo.cs new file mode 100644 index 0000000..bd5b52d --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/OsgPreprocessorInfo.cs @@ -0,0 +1,18 @@ +using System; +namespace LCU.Library.Internal.DocumentIngestorModels.Entities; + +public class OsgPreprocessorInfo +{ + public int OsgPreprocessorInfoId { get; set; } + public Guid BatchRunInfoId { get; set; } + public DateTime ZipFileStartTime { get; set; } + public DateTime ZipFileEndTime { get; set; } + public string ZipFileName { get; set; } + public string DocumentType { get; set; } + public string EntityName { get; set; } + public string MemberNumber { get; set; } + public DateTime CreatedDate { get; set;} + public int StartingPage { get; set; } + public int NumberOfPages { get; set; } + public string XmlOutput { get; set; } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/OwnerOverrideInfo.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/OwnerOverrideInfo.cs new file mode 100644 index 0000000..109eb22 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/OwnerOverrideInfo.cs @@ -0,0 +1,48 @@ +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; + +namespace LCU.Library.Internal.DocumentIngestorModels.Entities; +public class OwnerOverrideInfo : IValidatableObject +{ + public OwnerOverrideInfo() + { + } + + public OwnerOverrideInfo(string userName, string entityId, EntityTypes entityType, int documentProcessingInfoId) + { + UserName = userName; + EntityId = entityId; + EntityType = entityType; + DocumentProcessingInfoId = documentProcessingInfoId; + } + + public int OwnerOverrideInfoId { get; set; } + public string UserName { get; set; } + public string EntityId { get; set; } + public EntityTypes EntityType { get; set; } + public int DocumentProcessingInfoId { get; set; } + + public IEnumerable Validate(ValidationContext validationContext) + { + if (EntityType == EntityTypes.Unknown && !string.IsNullOrWhiteSpace(EntityId)) + { + yield return new ValidationResult("Cannot assign EntityType of 'Unknown' and assign EntityId."); + } + + if (EntityType != EntityTypes.Unknown && string.IsNullOrWhiteSpace(EntityId)) + { + yield return new ValidationResult("There must be an EntityId if EntityType is not 'Unknown'."); + } + + if (string.IsNullOrWhiteSpace(UserName)) + { + yield return new ValidationResult("UserName cannot be null."); + } + + if (DocumentProcessingInfoId <= 0) + { + yield return new ValidationResult("DocumentProcessingInfoId must be greater than 0."); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/PdfPartitionerLog.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/PdfPartitionerLog.cs new file mode 100644 index 0000000..c4fde5c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/PdfPartitionerLog.cs @@ -0,0 +1,23 @@ +using System; + +namespace LCU.Library.Internal.DocumentIngestorModels.Entities +{ + public class PdfPartitionerLog + { + public PdfPartitionerLog() + { + } + + public PdfPartitionerLog(Guid pdfPartitionerRunInfoId, DateTime logTimeStamp, string logMessage) + { + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId; + LogTimeStamp = logTimeStamp; + LogMessage = logMessage; + } + + public int PdfPartitionerLogId { get; set; } + public Guid PdfPartitionerRunInfoId { get; set; } + public DateTime LogTimeStamp { get; set; } + public string LogMessage { get; set; } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/PdfPartitionerRunInfo.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/PdfPartitionerRunInfo.cs new file mode 100644 index 0000000..a9ddbaa --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/PdfPartitionerRunInfo.cs @@ -0,0 +1,57 @@ +using System; +using System.ComponentModel.DataAnnotations.Schema; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +namespace LCU.Library.Internal.DocumentIngestorModels.Entities; + +public class PdfPartitionerRunInfo +{ + public PdfPartitionerRunInfo() + { + + } + + public PdfPartitionerRunInfo(DateTime startTimeStamp, PdfParserTypes pdfParserType, string path, int indexTotal) + { + PdfPartitionerRunInfoId = Guid.NewGuid(); + StartTimeStamp = startTimeStamp; + PdfParserType = pdfParserType; + Path = path; + IndexTotal = indexTotal; + } + + public Guid PdfPartitionerRunInfoId { get; set; } + public DateTime StartTimeStamp { get; set; } + public DateTime? EndTimeStamp { get; set; } + public PdfParserTypes PdfParserType { get; set; } + public string Path { get; set; } + public int IndexTotal { get; set; } + public int FailureCount { get; set; } + public int SuccessCount { get; set; } + + [NotMapped] + public int FailureAndSuccessCount + { + get + { + return FailureCount + SuccessCount; + } + } + + [NotMapped] + public bool PdfPartitionerCompleted + { + get + { + return IndexTotal == FailureAndSuccessCount; + } + } + + [NotMapped] + public bool WasSuccessful + { + get + { + return FailureCount == 0; + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/ProcessingLog.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/ProcessingLog.cs new file mode 100644 index 0000000..94a219d --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Entities/ProcessingLog.cs @@ -0,0 +1,25 @@ +using System; + +namespace LCU.Library.Internal.DocumentIngestorModels.Entities +{ + public class ProcessingLog + { + public ProcessingLog() + { + } + + public ProcessingLog(int documentProcessingInfoId, DateTime logTimeStamp, string logMessage, string userName) + { + DocumentProcessingInfoId = documentProcessingInfoId; + LogTimeStamp = logTimeStamp; + LogMessage = logMessage; + UserName = userName; + } + + public int ProcessingLogId { get; set; } + public int DocumentProcessingInfoId { get; set; } + public DateTime LogTimeStamp { get; set; } + public string LogMessage { get; set; } + public string UserName { get; set; } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/DeliveryMethod.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/DeliveryMethod.cs new file mode 100644 index 0000000..68f2fc8 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/DeliveryMethod.cs @@ -0,0 +1,12 @@ +using System.ComponentModel.DataAnnotations; + +namespace LCU.Library.Internal.DocumentIngestorModels.Enums +{ + public enum DeliveryMethod + { + [Display(Name = "Paper")] + Paper, + [Display(Name = "Electronic")] + Electronic + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/DocumentOwnerTypes.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/DocumentOwnerTypes.cs new file mode 100644 index 0000000..b3cb4d3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/DocumentOwnerTypes.cs @@ -0,0 +1,8 @@ +namespace LCU.Library.Internal.DocumentIngestorModels.Enums; + +public enum DocumentOwnerTypes +{ + PrimaryOwner, + AccountOwner, + Generic +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/EntityTypes.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/EntityTypes.cs new file mode 100644 index 0000000..afd3d94 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/EntityTypes.cs @@ -0,0 +1,9 @@ +namespace LCU.Library.Internal.DocumentIngestorModels.Enums +{ + public enum EntityTypes + { + Person, + Organization, + Unknown + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/IngestorTypes.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/IngestorTypes.cs new file mode 100644 index 0000000..a86fcc2 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/IngestorTypes.cs @@ -0,0 +1,18 @@ +namespace LCU.Library.Internal.DocumentIngestorModels.Enums +{ + public enum IngestorTypes + { + FosTaxStatement, + FosDnaDocument, + XdiDnaNotice, + FosLoanStatement, + OsgDnaNoticesDocument, + XdiActionNotice, + OsgHistoricalDocument, + OsgWeilandStatement, + OsgTaxStatement, + OsgDnaNoticeSplit, + OsgTemenosNotice, + OsgVehicleTaxStatement + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/NotificationStatusTypes.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/NotificationStatusTypes.cs new file mode 100644 index 0000000..fc9fb11 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/NotificationStatusTypes.cs @@ -0,0 +1,11 @@ +namespace LCU.Library.Internal.DocumentIngestorModels.Enums; + +public enum NotificationStatusTypes +{ + Pending, + Failure, + Undeliverable, + CriticalFailure, + Complete, + WaitingResponse +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/PdfParserTypes.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/PdfParserTypes.cs new file mode 100644 index 0000000..da946b7 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/PdfParserTypes.cs @@ -0,0 +1,9 @@ +namespace LCU.Library.Internal.DocumentIngestorModels.Enums +{ + public enum PdfParserTypes + { + FosLoanStatement, + OsgDnaNoticesDocument, + OsgHistoricalDocument + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/ProcessStatusTypes.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/ProcessStatusTypes.cs new file mode 100644 index 0000000..4242027 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Enums/ProcessStatusTypes.cs @@ -0,0 +1,14 @@ +namespace LCU.Library.Internal.DocumentIngestorModels.Enums +{ + public enum ProcessStatusTypes + { + Processing, + Completed, + ArchiveFailure, + CriticalFailure, + DataMappingFailure, + Reprocessing, + NotificationDataFailure, + UploadCompletionReprocessing + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/LCU.Library.Internal.DocumentIngestorModels.csproj b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/LCU.Library.Internal.DocumentIngestorModels.csproj new file mode 100644 index 0000000..bbe3c5a --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/LCU.Library.Internal.DocumentIngestorModels.csproj @@ -0,0 +1,146 @@ + + + + netstandard2.0 + True + 1.20.3 + + 1.0.0 - Initial Creation of Models Library. + 1.1.0 - Update Models Library to parse based on index not header. + 1.2.0 - Addition of XdiDnaNotices model. + 1.3.0 - Addition of FosLoanStatement model. + 1.3.1 - Update DocumentProcessingInfo to capture documentFileName. + 1.4.0 - Add EntityTypes and add OwnerOverrideInfo to ProcessingRequest + 1.5.0 - Addition of BatchIngestionRequest. IngestorRequest no longer uses archive dates but an Archived Folder. + 1.6.0 - Add DocumentType and DocumentBusinessName to DocumentProcessingInfo + 1.7.0 - Add Filter and Pagination to DocumentProcessingInfo + 1.8.0 - Add IngestorRunInfo to DocumentProcessingInfo as a possible pulled in property + 1.8.1 - Change Filter model datetimes to nullable and sortable field fix + 1.9.0 - Add Process Count. Remove Success, Failure, and Archive Failure Counts + 1.9.1 - Table OwnerOverrideInfo.EntityId column can now be null, remove Filter Page range, and fix spelling of 'Unknown' EntityType + 1.10.0 - Addition of PdfPartitionerLog, PdfPartitionerRunInfo, PdfParserTypes Enum, PdfPartitionerRequest, and PdfPartitionerResult. + 1.10.1 - Fix EntityId NullOrWhiteSpace + 1.10.2 - ProcessRequest adding RetryCount + 1.10.3 - Update DocumentType library + 1.10.4 - Capture FosTaxStatementDocument TaxYear + 1.10.5 - Addition of MemberNotificationInfo, add DocumentMemberFacingName to DocumentCodeDetailInfo + 1.11.0 - Add OsgDnaNotices document and enums to IngestorTypes and PdfParserTypes + 1.12.0 - Add XdiActionNotices enums to IngestorTypes and create XdiActionNotices index file model + 1.13.0 - Add OsgPreprocessorRequest and OsgPreprocessorResult + 1.13.1 - Add OsgPreprocessorInfo + 1.14.0 - Add OsgHistoricalDocument index model and enums. Replace XmlOsgHistoricalDocument and OsgPreprocessorInfo AccountNumber with EntityName + 1.14.1 - Add custom filters for index file json + 1.15.0 - Add EntityUnkown to DocumentProcessingInfo and add EntityUnknownRequest + 1.15.1 - Add IsUnknown to StatusFilter + 1.15.2 - Add UploadCompletionReprocessing to ProcessStatusTypes + 1.15.3 - Add IngestorRunInfoId to Filter + 1.15.4 - Add DocumentProcessingInfoStatusRequest + 1.15.5 - Make Filter.IngestorRunInfoId nullable + 1.16.0 - Attach MemberNotificationInfo to DocumentProcessingInfo if present and add NotificationStatusTypes filter + 1.17.0 - Add BulkNotificationStatusRequest + 1.17.1 - Add EntityIsUnknown to ErrorCaptureResult + 1.17.2 - Set DocumentProcessingInfo.MemberNotificationInfo to list instead of singular + 1.18.0 - Add CustomIndexFileFiltersLike to Filter + 1.18.1 - Change CustomIndexFileFiltersLikeOr to 'Or' + 1.19.0 - Add IngestionFolderCleanUp request and result + 1.19.1 - Fix IngestionFolderCleanUp request's archive root path + 1.19.2 - Update DocumentType library + 1.19.3 - Update DocumentType library + 1.19.4 - Update DocumentType library + 1.19.5 - Update DocumentType library + 1.19.6 - Update DocumentType library + 1.19.7 - Update DocumentType library + 1.19.8 - Update DocumentType library + 1.19.9 - Update DocumentType library + 1.19.10 - Update DocumentType library and add Weiland Document + 1.19.11 - Update DocumentType library + 1.19.12 - Update DocumentType Library and add OSG Tax documents + 1.19.13 - Update DocumentTypeLibrary + 1.19.14 - Update DocumentTypeLibrary + 1.19.15 - Update Osg DNA Notice Split documents + 1.19.16 - Upgraded FileOperations package version + 1.19.17 - Update DocumentTypeLibrary + 1.19.18 - Add DynamicIngestionDate + 1.19.19 - Update DocumentTypeLibrary, OsgTemenosNotice IngestorType + 1.20.0 - New models added for new processing flow and queues + 1.20.1 - New OsgVehicleTaxStatement document and DocumentType Library + 1.20.2 - New model added for ProcessStatusTypeEmailRequest + 1.20.3 - Added Processing to Not Allowed ProcessStatusTypeEmailRequest + + + 1.0.0 - Initial Creation of Models Library. + 1.1.0 - Update Models Library to parse based on index not header. + 1.2.0 - Addition of XdiDnaNotices model. + 1.3.0 - Addition of FosLoanStatement model. + 1.3.1 - Update DocumentProcessingInfo to capture documentFileName. + 1.4.0 - Add EntityTypes and add OwnerOverrideInfo to ProcessingRequest + 1.5.0 - Addition of BatchIngestionRequest. IngestorRequest no longer uses archive dates but an Archived Folder. + 1.6.0 - Add DocumentType and DocumentBusinessName to DocumentProcessingInfo + 1.7.0 - Add Filter and Pagination to DocumentProcessingInfo + 1.8.0 - Add IngestorRunInfo to DocumentProcessingInfo as a possible pulled in property + 1.8.1 - Change Filter model datetimes to nullable and sortable field fix + 1.9.0 - Add Process Count. Remove Success, Failure, and Archive Failure Counts + 1.9.1 - Table OwnerOverrideInfo.EntityId column can now be null, remove Filter Page range, and fix spelling of 'Unknown' EntityType + 1.10.0 - Addition of PdfPartitionerLog, PdfPartitionerRunInfo, PdfParserTypes Enum, PdfPartitionerRequest, and PdfPartitionerResult. + 1.10.1 - Fix EntityId NullOrWhiteSpace + 1.10.2 - ProcessRequest adding RetryCount + 1.10.3 - Update DocumentType library + 1.10.4 - Capture FosTaxStatementDocument TaxYear + 1.10.5 - Addition of MemberNotificationInfo, add DocumentMemberFacingName to DocumentCodeDetailInfo + 1.11.0 - Add OsgDnaNotices document and enums to IngestorTypes and PdfParserTypes + 1.12.0 - Add XdiActionNotices enums to IngestorTypes and create XdiActionNotices index file model + 1.13.0 - Add OsgPreprocessorRequest and OsgPreprocessorResult + 1.13.1 - Add OsgPreprocessorInfo + 1.14.0 - Add OsgHistoricalDocument index model and enums. Replace XmlOsgHistoricalDocument and OsgPreprocessorInfo AccountNumber with EntityName + 1.14.1 - Add custom filters for index file json + 1.15.0 - Add EntityUnkown to DocumentProcessingInfo and add EntityUnknownRequest + 1.15.1 - Add IsUnknown to StatusFilter + 1.15.2 - Add UploadCompletionReprocessing to ProcessStatusTypes + 1.15.3 - Add IngestorRunInfoId to Filter + 1.15.4 - Add DocumentProcessingInfoStatusRequest + 1.15.5 - Make Filter.IngestorRunInfoId nullable + 1.16.0 - Attach MemberNotificationInfo to DocumentProcessingInfo if present and add NotificationStatusTypes filter + 1.17.0 - Add BulkNotificationStatusRequest + 1.17.1 - Add EntityIsUnknown to ErrorCaptureResult + 1.17.2 - Set DocumentProcessingInfo.MemberNotificationInfo to list instead of singular + 1.18.0 - Add CustomIndexFileFiltersLike to Filter + 1.18.1 - Change CustomIndexFileFiltersLikeOr to 'Or' + 1.19.0 - Add IngestionFolderCleanUp request and result + 1.19.1 - Fix IngestionFolderCleanUp request's archive root path + 1.19.2 - Update DocumentType library + 1.19.3 - Update DocumentType library + 1.19.4 - Update DocumentType library + 1.19.5 - Update DocumentType library + 1.19.6 - Update DocumentType library + 1.19.7 - Update DocumentType library + 1.19.8 - Update DocumentType library + 1.19.9 - Update DocumentType library + 1.19.10 - Update DocumentType library and add Weiland Document + 1.19.11 - Update DocumentType + 1.19.12 - Update DocumentType Library and add OSG Tax documents + 1.19.13 - Update DocumentTypeLibrary + 1.19.14 - Update DocumentTypeLibrary + 1.19.15 - Update Osg DNA Notice Split documents + 1.19.16 - Upgraded FileOperations package version + 1.19.17 - Update DocumentTypeLibrary + 1.19.18 - Add DynamicIngestionDate + 1.19.19 - Update DocumentTypeLibrary, OsgTemenosNotice IngestorType + 1.20.0 - New models added for new processing flow and queues + 1.20.1 - New OsgVehicleTaxStatement document and DocumentType Library + 1.20.2 - New model added for ProcessStatusTypeEmailRequest + 1.20.3 - Added Processing to Not Allowed ProcessStatusTypeEmailRequest + + latest + Debug;Release;Test + AnyCPU + + + + + + + + + + + diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/BatchIngestionRequest.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/BatchIngestionRequest.cs new file mode 100644 index 0000000..9fe64ae --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/BatchIngestionRequest.cs @@ -0,0 +1,54 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using LCU.Library.Internal.ApiResponse.Models; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.FileOperationsModels.Models.NameSettings; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models +{ + public class BatchIngestionRequest : ReturnResponse + { + [Required(ErrorMessage = "Ingestor Type is required")] + public IngestorTypes IngestorType { get; set; } + [Required(ErrorMessage = "Root Base Path is required")] + public string RootBasePath { get; set; } + public int DaysIngestionDate { get; set; } + public DateTime? IngestionDate { get; set; } + public DynamicIngestionDate DynamicIngestionDate { get; set; } = new(); + public bool UseDynamicIngestionDate { get; set; } = false; + public string ParentDynamicDirectory { get; set; } = ""; + public string SubDirectoryPath { get; set; } = ""; + [Required(ErrorMessage = "Dynamic Index File Name is required")] + public string DynamicIndexFileName { get; set; } + public DynamicNameSetting DynamicFileSettings { get; set; } + public DynamicNameSetting ParentDynamicDirectorySettings { get; set; } + + [NotMapped] + public DateTime FinalIngestionDate + { + get + { + if (UseDynamicIngestionDate) + { + return new DateTime(DynamicIngestionDate.Year ?? DateTime.Now.Year, + DynamicIngestionDate.Month ?? DateTime.Now.Month, + DynamicIngestionDate.Day ?? DateTime.Now.Day); + + } + + return (IngestionDate ?? DateTime.Now).AddDays(DaysIngestionDate); + } + } + + [NotMapped] + public string FinalRootBasePath + { + get + { + var rootBasePath = RootBasePath.EndsWith("\\") ? RootBasePath : $"{RootBasePath}\\"; + return $"{rootBasePath}{FinalIngestionDate:MMddyyyy}\\"; + } + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/BatchIngestionResult.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/BatchIngestionResult.cs new file mode 100644 index 0000000..cfdfc3e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/BatchIngestionResult.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models +{ + public class BatchIngestionResult + { + public List Messages { get; set; } = new List(); + public int FailureCount { get; set; } = 0; + + + [NotMapped] + public bool IsSuccessfull + { + get + { + return FailureCount == 0; + } + } + + [NotMapped] + public bool IsFailure + { + get + { + return FailureCount > 0; + } + } + + public void AddToFailureCount(string message) + { + Messages.Add(message); + FailureCount++; + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/BatchUpdateMemberNotificationDataRequest.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/BatchUpdateMemberNotificationDataRequest.cs new file mode 100644 index 0000000..b58371e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/BatchUpdateMemberNotificationDataRequest.cs @@ -0,0 +1,18 @@ +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using System.Collections.Generic; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models; + +public class BatchUpdateMemberNotificationDataRequest +{ + public BatchUpdateMemberNotificationDataRequest() { } + public BatchUpdateMemberNotificationDataRequest(List memberNotificationInfos, + GatherMemberNotificationInfoRequest gatherMemberNotificationInfoRequest) + { + MemberNotificationInfos = memberNotificationInfos; + GatherMemberNotificationInfoRequest = gatherMemberNotificationInfoRequest; + } + + public List MemberNotificationInfos { get; set; } + public GatherMemberNotificationInfoRequest GatherMemberNotificationInfoRequest { get; set; } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/BatchUploadCompletionRequest.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/BatchUploadCompletionRequest.cs new file mode 100644 index 0000000..523c1dd --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/BatchUploadCompletionRequest.cs @@ -0,0 +1,11 @@ +using LCU.Library.Internal.DocumentIngestorModels.Entities; +using System.Collections.Generic; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models; + +public class BatchUploadCompletionRequest +{ + public List SuccessfulUploadCompletions { get; set; } + public List UnsuccessfulUploadCompletions { get; set; } + public IEnumerable DocumentProcessingInfos { get; set; } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/BulkNotificationStatusRequest.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/BulkNotificationStatusRequest.cs new file mode 100644 index 0000000..ac7b0c3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/BulkNotificationStatusRequest.cs @@ -0,0 +1,38 @@ +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using LCU.Library.Internal.DocumentIngestorModels.Models.Pagination; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models; +public class BulkNotificationStatusRequest : IValidatableObject +{ + public BulkNotificationStatusRequest() + { + } + + public BulkNotificationStatusRequest(Filter filter, + NotificationStatusTypes notificationStatus, + string reasonMessage) + { + Filter = filter; + NotificationStatus = notificationStatus; + ReasonMessage = reasonMessage; + } + + public Filter Filter { get; set; } + public NotificationStatusTypes NotificationStatus { get; set; } + public string ReasonMessage { get; set; } = string.Empty; + + public IEnumerable Validate(ValidationContext validationContext) + { + if (Filter == null) + { + yield return new ValidationResult("Filter cannot be null."); + } + + if (string.IsNullOrWhiteSpace(ReasonMessage)) + { + yield return new ValidationResult("Must provide a ReasonMessage explaining the reason for the update."); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/CompletionProcessingData.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/CompletionProcessingData.cs new file mode 100644 index 0000000..8595dda --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/CompletionProcessingData.cs @@ -0,0 +1,9 @@ +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models; + +public class CompletionProcessingData +{ + public DocumentProcessingInfo DocumentProcessingInfo { get; set; } + public CompletionRequest CompletionRequest { get; set; } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/CompletionRequest.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/CompletionRequest.cs new file mode 100644 index 0000000..855da05 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/CompletionRequest.cs @@ -0,0 +1,9 @@ +namespace LCU.Library.Internal.DocumentIngestorModels.Models +{ + public class CompletionRequest + { + public ProcessResult ProcessResult { get; set; } + public ProcessingRequest ProcessingRequest { get; set; } + public MemberNotificationInfoRequest MemberNotificationInfoRequest { get; set; } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/DocumentProcessingInfoStatusRequest.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/DocumentProcessingInfoStatusRequest.cs new file mode 100644 index 0000000..ddaf789 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/DocumentProcessingInfoStatusRequest.cs @@ -0,0 +1,46 @@ +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models; +public class DocumentProcessingInfoStatusRequest : IValidatableObject +{ + public DocumentProcessingInfoStatusRequest() + { + } + + public DocumentProcessingInfoStatusRequest(int documentProcessingInfoId, + ProcessStatusTypes processStatus, + string reasonMessage, + string username) + { + DocumentProcessingInfoId = documentProcessingInfoId; + ProcessStatus = processStatus; + ReasonMessage = reasonMessage; + Username = username; + } + + public int DocumentProcessingInfoId { get; set; } + public ProcessStatusTypes ProcessStatus { get; set; } + public string ReasonMessage { get; set; } = string.Empty; + public string Username { get; set; } = string.Empty; + + public IEnumerable Validate(ValidationContext validationContext) + { + if (DocumentProcessingInfoId == 0 || DocumentProcessingInfoId == null) + { + yield return new ValidationResult("DocumentProcessingInfoId cannot be 0 or null."); + } + + if (string.IsNullOrWhiteSpace(ReasonMessage)) + { + yield return new ValidationResult("Must provide a ReasonMessage explaining the reason for the update."); + } + + if (string.IsNullOrWhiteSpace(Username)) + { + yield return new ValidationResult("Must provide a Username."); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/DynamicIngestionDate.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/DynamicIngestionDate.cs new file mode 100644 index 0000000..db63019 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/DynamicIngestionDate.cs @@ -0,0 +1,10 @@ +using System; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models; + +public class DynamicIngestionDate +{ + public int? Month { get; set; } + public int? Day { get; set; } + public int? Year { get; set; } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/EntityUnknownRequest.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/EntityUnknownRequest.cs new file mode 100644 index 0000000..9978805 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/EntityUnknownRequest.cs @@ -0,0 +1,34 @@ +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using System.Linq; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models; +public class EntityUnknownRequest : IValidatableObject +{ + public EntityUnknownRequest() + { + } + + public EntityUnknownRequest(string userName, List documentProcessingInfoIds) + { + UserName = userName; + DocumentProcessingInfoIds = documentProcessingInfoIds; + } + + public string UserName { get; set; } + public List DocumentProcessingInfoIds { get; set; } + + public IEnumerable Validate(ValidationContext validationContext) + { + if (string.IsNullOrWhiteSpace(UserName)) + { + yield return new ValidationResult("UserName cannot be null."); + } + + if (!DocumentProcessingInfoIds.Any()) + { + yield return new ValidationResult("DocumentProcessingInfoIds cannot be empty."); + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/ErrorCaptureResult.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/ErrorCaptureResult.cs new file mode 100644 index 0000000..6ddf0a1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/ErrorCaptureResult.cs @@ -0,0 +1,31 @@ +#nullable enable +namespace LCU.Library.Internal.DocumentIngestorModels.Models; + +public class ErrorCaptureResult where T : class +{ + private ErrorCaptureResult(bool success, string? message, T payload, bool? entityIsUnknown = null) + { + Success = success; + Message = message; + Payload = payload; + EntityIsUnknown = entityIsUnknown; + } + + public bool Success { get; } + + public string? Message { get; } + + public T Payload { get; } + + public bool? EntityIsUnknown { get; } + + public static ErrorCaptureResult CreateErrorPayload(string? message, T payload, bool? entityIsUnknown = null) + { + return new ErrorCaptureResult(false, message, payload, entityIsUnknown); + } + + public static ErrorCaptureResult CreateSuccessPayload(T payload) + { + return new ErrorCaptureResult(true, null, payload); + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/GatherMemberNotificationInfoRequest.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/GatherMemberNotificationInfoRequest.cs new file mode 100644 index 0000000..707a1ce --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/GatherMemberNotificationInfoRequest.cs @@ -0,0 +1,6 @@ +namespace LCU.Library.Internal.DocumentIngestorModels.Models; + +public class GatherMemberNotificationInfoRequest +{ + public CompletionRequest CompletionRequest { get; set; } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/FosDnaDocument.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/FosDnaDocument.cs new file mode 100644 index 0000000..e93e7d1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/FosDnaDocument.cs @@ -0,0 +1,18 @@ +using CsvHelper.Configuration.Attributes; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments +{ + public class FosDnaDocument + { + [Index(0)] + public string AccountNumber { get; set; } + [Index(1)] + public string EntityName { get; set; } + [Index(2)] + public string CreationDate { get; set; } + [Index(3)] + public string DocType { get; set; } + [Index(4)] + public string DocName { get; set; } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/FosLoanStatement.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/FosLoanStatement.cs new file mode 100644 index 0000000..394f02b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/FosLoanStatement.cs @@ -0,0 +1,24 @@ +using CsvHelper.Configuration.Attributes; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments +{ + public class FosLoanStatement + { + [Index(0)] + public string DocType { get; set; } + [Index(4)] + public string AccountNumber { get; set; } + [Index(5)] + public string EntityName { get; set; } + [Index(6)] + public string EmailAddress { get; set; } + [Index(7)] + public string CreationDate { get; set; } + [Index(8)] + public string StartingPage { get; set; } + [Index(9)] + public string NumberOfPages { get; set; } + [Index(10)] + public string DocName { get; set; } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/FosTaxStatementDocument.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/FosTaxStatementDocument.cs new file mode 100644 index 0000000..697b344 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/FosTaxStatementDocument.cs @@ -0,0 +1,24 @@ +using CsvHelper.Configuration.Attributes; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments +{ + /// + /// NOTE: The index annotation denotes the index location of each record in the csv row being processed. + /// The Index record 3 is the tax year identical for each row in a file and not used in the ingestor + /// + public class FosTaxStatementDocument + { + [Index(0)] + public string FileName { get; set; } + [Index(1)] + public string PrimaryTIN { get; set; } + [Index(2)] + public string FullName { get; set; } + [Index(3)] + public int TaxYear { get; set; } + [Index(4)] + public string AccountNumber { get; set; } + [Index(5)] + public string PDF { get; set; } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgDnaNoticeSplit.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgDnaNoticeSplit.cs new file mode 100644 index 0000000..ac9f058 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgDnaNoticeSplit.cs @@ -0,0 +1,40 @@ +using CsvHelper.Configuration.Attributes; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments +{ + public class OsgDnaNoticeSplit + { + [Index(0)] + public string SequenceNumber { get; set; } + + [Index(1)] + public string NoticeId { get; set; } + + [Index(2)] + public string AccountNumber { get; set; } + + [Index(3)] + public string MemberNumber { get; set; } + + [Index(4)] + public string UserId { get; set; } + + [Index(5)] + public string RecipientName { get; set; } + + [Index(6)] + public string SSN { get; set; } + + [Index(7)] + public string NoticeName { get; set; } + + [Index(8)] + public string ApplicationNumber { get; set; } + + [Index(9)] + public string CreationDate { get; set; } + + [Index(10)] + public string PdfName { get; set; } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgDnaNoticesDocument.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgDnaNoticesDocument.cs new file mode 100644 index 0000000..d15d619 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgDnaNoticesDocument.cs @@ -0,0 +1,28 @@ +using CsvHelper.Configuration.Attributes; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments +{ + /// + /// Note: Index record 0 is the SequenceNumber. Created by OSG during creation of documents / Index file - means nothing to our process + /// + public class OsgDnaNoticesDocument + { + [Index(1)] + public string DocType { get; set; } + + [Index(2)] + public string AccountNumber { get; set; } + + [Index(3)] + public string MemberNumberOrUserId { get; set; } + + [Index(4)] + public string CreationDate { get; set; } + + [Index(5)] + public string StartingPage { get; set; } + + [Index(6)] + public string NumberOfPages { get; set; } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgHistoricalDocument.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgHistoricalDocument.cs new file mode 100644 index 0000000..306784a --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgHistoricalDocument.cs @@ -0,0 +1,28 @@ +using CsvHelper.Configuration.Attributes; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments +{ + /// + /// Note: Index record 0 is the SequenceNumber. Created by OSG during creation of documents / Index file - means nothing to our process + /// + public class OsgHistoricalDocument + { + [Index(1)] + public string DocType { get; set; } + + [Index(2)] + public string EntityName { get; set; } + + [Index(3)] + public string MemberNumberOrUserId { get; set; } + + [Index(4)] + public string CreationDate { get; set; } + + [Index(5)] + public string StartingPage { get; set; } + + [Index(6)] + public string NumberOfPages { get; set; } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgTaxStatement.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgTaxStatement.cs new file mode 100644 index 0000000..649653b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgTaxStatement.cs @@ -0,0 +1,40 @@ +using CsvHelper.Configuration.Attributes; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments +{ + public class OsgTaxStatement + { + [Index(0)] + public string SequenceNumber { get; set; } + + [Index(1)] + public string NoticeId { get; set; } + + [Index(2)] + public string AccountNumber { get; set; } + + [Index(3)] + public string MemberNumber { get; set; } + + [Index(4)] + public string UserId { get; set; } + + [Index(5)] + public string RecipientName { get; set; } + + [Index(6)] + public string SSN { get; set; } + + [Index(7)] + public string NoticeName { get; set; } + + [Index(8)] + public string ApplicationNumber { get; set; } + + [Index(9)] + public string CreationDate { get; set; } + + [Index(10)] + public string PdfName { get; set; } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgTemenosNoticesDocument.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgTemenosNoticesDocument.cs new file mode 100644 index 0000000..e6bc6b7 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgTemenosNoticesDocument.cs @@ -0,0 +1,31 @@ +using CsvHelper.Configuration.Attributes; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments +{ + /// + /// Note: Index record 6 is the same as index record 5 (The DocType is repeated from the vendor index) + /// + public class OsgTemenosNoticesDocument + { + [Index(0)] + public string Sequence { get; set; } + + [Index(2)] + public string AccountNumber { get; set; } + + [Index(3)] + public string LoanNumber { get; set; } + + [Index(5)] + public string EntityName { get; set; } + + [Index(7)] + public string DocumentType { get; set; } + + [Index(9)] + public string CreationDate { get; set; } + + [Index(10)] + public string PDF { get; set; } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgWeilandStatement.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgWeilandStatement.cs new file mode 100644 index 0000000..cd15d84 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/OsgWeilandStatement.cs @@ -0,0 +1,28 @@ +using CsvHelper.Configuration.Attributes; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments +{ + public class OsgWeilandStatement + { + [Index(0)] + public string Date { get; set; } + + [Index(1)] + public string Family { get; set; } + + [Index(2)] + public string AccountNumber { get; set; } + + [Index(3)] + public string AccountTitle { get; set; } + + [Index(4)] + public string PdfDate { get; set; } + + [Index(5)] + public string PdfName { get; set; } + + [Index(6)] + public string DocCode { get; set; } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/XdiActionNoticesDocument.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/XdiActionNoticesDocument.cs new file mode 100644 index 0000000..0cecf4d --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/XdiActionNoticesDocument.cs @@ -0,0 +1,28 @@ +using CsvHelper.Configuration.Attributes; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments +{ + public class XdiActionNoticesDocument + { + [Index(0)] + public string CreationDate { get; set; } + + [Index(1)] + public string ApplicationNumber { get; set; } + + [Index(2)] + public string LoanNumber { get; set; } + + [Index(3)] + public string EntityName { get; set; } + + [Index(4)] + public int PageCount { get; set; } + + [Index(5)] + public string DocumentType { get; set; } + + [Index(7)] + public string DocumentName { get; set; } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/XdiDnaNoticesDocument.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/XdiDnaNoticesDocument.cs new file mode 100644 index 0000000..f29d8cf --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IndexFileDocuments/XdiDnaNoticesDocument.cs @@ -0,0 +1,31 @@ +using CsvHelper.Configuration.Attributes; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models.IndexFileDocuments +{ + /// + /// Note: Index record 6 is the same as index record 5 (The DocType is repeated from the vendor index) + /// + public class XdiDnaNoticesDocument + { + [Index(0)] + public string CreationDate { get; set; } + + [Index(1)] + public string AccountNumber { get; set; } + + [Index(2)] + public string LoanNumber { get; set; } + + [Index(3)] + public string EntityName { get; set; } + + [Index(4)] + public int PageCount { get; set; } + + [Index(5)] + public string DocumentType { get; set; } + + [Index(7)] + public string PDF { get; set; } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IngestionFolderCleanUpRequest.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IngestionFolderCleanUpRequest.cs new file mode 100644 index 0000000..a14de59 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IngestionFolderCleanUpRequest.cs @@ -0,0 +1,35 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using LCU.Library.Internal.ApiResponse.Models; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models +{ + public class IngestionFolderCleanUpRequest : ReturnResponse + { + public DateTime? IngestionEndedDate { get; set; } + + public int DaysFromIngestionEndedDate { get; set; } = 0; + + public DateTime? ArchiveDate { get; set; } + + public int DaysFromArchiveDate { get; set; } = 0; + + [Required] public string ArchiveRootPath { get; set; } + + [NotMapped] + public DateTime FinalIngestionEndedDate => IngestionEndedDate ?? DateTime.Today.AddDays(1).AddTicks(-1); + + [NotMapped] + public DateTime FinalArchiveDate => ArchiveDate ?? DateTime.Today.AddDays(1).AddTicks(-1); + + [NotMapped] + public DateTime CleanUpIngestionFoldersUntilDate => FinalIngestionEndedDate.AddDays(DaysFromIngestionEndedDate).Date.AddDays(1).AddTicks(-1); + + [NotMapped] + public string ArchiveFolderName => FinalArchiveDate.AddDays(DaysFromArchiveDate).ToString("yyyy-MM-dd"); + + [NotMapped] + public string ArchiveRootPathAndFolder => (ArchiveRootPath.EndsWith("\\") ? ArchiveRootPath : $"{ArchiveRootPath}\\") + ArchiveFolderName; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IngestionFolderCleanUpResult.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IngestionFolderCleanUpResult.cs new file mode 100644 index 0000000..1d925d6 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IngestionFolderCleanUpResult.cs @@ -0,0 +1,24 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models +{ + public class IngestionFolderCleanUpResult + { + public List Messages { get; set; } = new List(); + + public int FailureCount { get; set; } = 0; + + [NotMapped] + public bool IsSuccessful => FailureCount == 0; + + [NotMapped] + public bool IsFailure => FailureCount > 0; + + public void AddToFailureCount(string message) + { + Messages.Add(message); + FailureCount++; + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IngestorRequest.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IngestorRequest.cs new file mode 100644 index 0000000..4733f84 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IngestorRequest.cs @@ -0,0 +1,44 @@ +using System.ComponentModel.DataAnnotations.Schema; +using LCU.Library.Internal.ApiResponse.Models; +using LCU.Library.Internal.DocumentIngestorModels.Enums; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models +{ + public class IngestorRequest : ReturnResponse + { + private string rootPath; + private const string ArchiveFolder = "Archived"; + + public IngestorTypes IngestorType { get; set; } + public string RootPath + { + get + { + return rootPath; + } + set + { + rootPath = value.EndsWith("\\") ? value : $"{value}\\"; + } + } + public string IndexFileName { get; set; } + + [NotMapped] + public string ArchivePath + { + get + { + return $"{RootPath}{ArchiveFolder}\\"; + } + } + + [NotMapped] + public string FinalIndexFilePath + { + get + { + return RootPath + IndexFileName; + } + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IngestorResult.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IngestorResult.cs new file mode 100644 index 0000000..8df4780 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/IngestorResult.cs @@ -0,0 +1,23 @@ +using System.Collections.Generic; +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models +{ + public class IngestorResult + { + public IngestorResult() + { + MessageStack = new List(); + } + + public IngestorResult(bool fatalFailure, string message) + { + FatalFailure = fatalFailure; + MessageStack = new List() { message }; + } + public bool FatalFailure { get; set; } + public List MessageStack { get; set; } + public IngestorRunInfo IngestorRunInfo { get; set; } + public List ProcessingRequests { get; set; } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/MemberDocumentNotificationRequest.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/MemberDocumentNotificationRequest.cs new file mode 100644 index 0000000..b774698 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/MemberDocumentNotificationRequest.cs @@ -0,0 +1,7 @@ +using LCU.Library.Internal.ApiResponse.Models; +namespace LCU.Library.Internal.DocumentIngestorModels.Models; + +public class MemberDocumentNotificationRequest : ReturnResponse +{ + public bool RunCriticalFailureNotifications { get; set; } = false; +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/MemberDocumentNotificationResult.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/MemberDocumentNotificationResult.cs new file mode 100644 index 0000000..b2b26dd --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/MemberDocumentNotificationResult.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models; + +public class MemberDocumentNotificationResult +{ + public List Messages { get; set; } = new List(); + public int FailureCount { get; set; } = 0; + + [NotMapped] + public bool IsSuccessful + { + get + { + return FailureCount == 0; + } + } + + [NotMapped] + public bool IsFailure + { + get + { + return FailureCount > 0; + } + } + + public void AddToFailureCount(string message) + { + Messages.Add(message); + FailureCount++; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/MemberNotificationCompletionRequest.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/MemberNotificationCompletionRequest.cs new file mode 100644 index 0000000..faf3869 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/MemberNotificationCompletionRequest.cs @@ -0,0 +1,8 @@ +using System.Collections.Generic; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models; + +public class MemberNotificationCompletionRequest +{ + public List MemberNotificationInfoIds { get; set; } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/MemberNotificationInfoRequest.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/MemberNotificationInfoRequest.cs new file mode 100644 index 0000000..55273ef --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/MemberNotificationInfoRequest.cs @@ -0,0 +1,10 @@ +using LCU.Library.Internal.DocumentIngestorModels.Enums; +namespace LCU.Library.Internal.DocumentIngestorModels.Models; + +public class MemberNotificationInfoRequest +{ + public int DocumentProcessingInfoId { get; set; } + public DocumentOwnerTypes DocumentOwnerType { get; set; } + public string DocumentEntityNumber { get; set; } + public EntityTypes EntityType { get; set; } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/OsgPreprocessorRequest.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/OsgPreprocessorRequest.cs new file mode 100644 index 0000000..c58f387 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/OsgPreprocessorRequest.cs @@ -0,0 +1,54 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models; + +[Obsolete("06/02/2023 - Used to prepare historical documents for ingestion. No longer in use.")] +public class OsgPreprocessorRequest +{ + private string workingBasePath; + private string outputBasePath; + private string incompleteOutputBasePath; + [Required(ErrorMessage = "Archive Start Date is required")] + public DateTime ArchiveStartDate { get; set; } + public bool SaveXmlOutput { get; set; } = false; + + [Required(ErrorMessage = "Source Base Path is required")] + public string SourceBasePath { get; set; } + [Required(ErrorMessage = "Working Base Path is required")] + public string WorkingBasePath + { + get + { + return workingBasePath; + } + set + { + workingBasePath = value.EndsWith("\\") ? value : $"{value}\\"; + } + } + [Required(ErrorMessage = "Output Base Path is required")] + public string OutputBasePath + { + get + { + return outputBasePath; + } + set + { + outputBasePath = value.EndsWith("\\") ? value : $"{value}\\"; + } + } + [Required(ErrorMessage = "Incomplete Output Base Path is required")] + public string IncompleteOutputBasePath + { + get + { + return incompleteOutputBasePath; + } + set + { + incompleteOutputBasePath = value.EndsWith("\\") ? value : $"{value}\\"; + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/OsgPreprocessorResult.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/OsgPreprocessorResult.cs new file mode 100644 index 0000000..0c8602a --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/OsgPreprocessorResult.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models; + +[Obsolete("06/02/2023 - Used to prepare historical documents for ingestion. No longer in use.")] +public class OsgPreprocessorResult +{ + public string OutputFile { get; set; } + public bool Success { get; set; } + public List MessageStack { get; set; } = new List(); + + public void AddFailureAndMessage(string message) + { + MessageStack.Add(message); + Success = false; + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/OsgPreprocessorRunInfo.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/OsgPreprocessorRunInfo.cs new file mode 100644 index 0000000..2299580 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/OsgPreprocessorRunInfo.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +namespace LCU.Library.Internal.DocumentIngestorModels.Models; + +[Obsolete("06/02/2023 - Used to prepare historical documents for ingestion. No longer in use.")] +public class OsgPreprocessorRunInfo +{ + + public OsgPreprocessorRunInfo(OsgPreprocessorRequest request) + { + OsgPreprocessorRequest = request; + OsgPreprocessorResults = new List(); + Messages = new List(); + } + + public OsgPreprocessorRequest OsgPreprocessorRequest { get; set; } + public List OsgPreprocessorResults { get; set; } + public string UnZippedFolder { get; set; } + public string DirectoryDate { get; set; } + public string IndexFile { get; set; } + public bool Incomplete { get; set; } = false; + public bool HasStatements { get; set; } = true; + public List Messages { get; set; } + + [NotMapped] + public string FinalWorkingDirectory + { + get + { + return $"{OsgPreprocessorRequest.WorkingBasePath}{UnZippedFolder}\\"; + } + } + + [NotMapped] + public string IndexFilePath + { + get + { + return FinalWorkingDirectory + IndexFile; + } + } + + [NotMapped] + public string FinalOutputDirectory + { + get + { + return Incomplete ? OsgPreprocessorRequest.IncompleteOutputBasePath : $"{OsgPreprocessorRequest.OutputBasePath}{DirectoryDate}\\"; + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/PdfPartitionerRequest.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/PdfPartitionerRequest.cs new file mode 100644 index 0000000..7113ef9 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/PdfPartitionerRequest.cs @@ -0,0 +1,57 @@ +using System; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using LCU.Library.Internal.ApiResponse.Models; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using LCU.Library.Internal.FileOperationsModels.Models.NameSettings; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models +{ + public class PdfPartitionerRequest : ReturnResponse + { + [Required(ErrorMessage = "Pdf Parser Types is required")] + public PdfParserTypes PdfParserType { get; set; } + [Required(ErrorMessage = "Root Base Path is required")] + public string RootBasePath { get; set; } + public int DaysIngestionDate { get; set; } + public DateTime? IngestionDate { get; set; } + public DynamicIngestionDate DynamicIngestionDate { get; set; } = new(); + public bool UseDynamicIngestionDate { get; set; } = false; + public string ParentDynamicDirectory { get; set; } = ""; + public string SubDirectoryPath { get; set; } = ""; + [Required(ErrorMessage = "Dynamic Index File Name is required")] + public string DynamicIndexFileName { get; set; } + public string DynamicPdfName { get; set; } + public bool SkipParseIfCountsMatch { get; set; } + public DynamicNameSetting ParentDynamicDirectorySettings { get; set; } + public DynamicNameSetting DynamicFileSettings { get; set; } + public DynamicNameSetting DynamicPdfSettings { get; set; } + + [NotMapped] + public DateTime FinalIngestionDate + { + get + { + if (UseDynamicIngestionDate) + { + return new DateTime(DynamicIngestionDate.Year ?? DateTime.Now.Year, + DynamicIngestionDate.Month ?? DateTime.Now.Month, + DynamicIngestionDate.Day ?? DateTime.Now.Day); + + } + + return (IngestionDate ?? DateTime.Now).AddDays(DaysIngestionDate); + } + } + + [NotMapped] + public string FinalRootBasePath + { + get + { + var rootBasePath = RootBasePath.EndsWith("\\") ? RootBasePath : $"{RootBasePath}\\"; + return $"{rootBasePath}{FinalIngestionDate.ToString("MMddyyyy")}\\"; + } + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/PdfPartitionerResult.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/PdfPartitionerResult.cs new file mode 100644 index 0000000..3e7ba20 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/PdfPartitionerResult.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models +{ + public class PdfPartitionerResult + { + public PdfPartitionerResult(Guid pdfPartitionerRunInfoId, PdfPartitionerRequest pdfPartitionerRequest) + { + PdfPartitionerRunInfoId = pdfPartitionerRunInfoId; + PdfPartitionerRequest = pdfPartitionerRequest; + MessageStack = new List(); + FailedToQueueToParse = false; + } + + public Guid PdfPartitionerRunInfoId { get; set; } + public PdfPartitionerRequest PdfPartitionerRequest { get; set; } + public List MessageStack { get; set; } + public bool FailedToQueueToParse { get; set; } + + public void AddFailureAndMessage(string message) + { + MessageStack.Add(message); + FailedToQueueToParse = true; + } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/ProcessResult.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/ProcessResult.cs new file mode 100644 index 0000000..85a5a77 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/ProcessResult.cs @@ -0,0 +1,78 @@ +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using System.Collections.Generic; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models +{ + public class ProcessResult + { + public ProcessResult() + { + Success = true; + MessageStack = new List(); + } + + public ProcessResult(bool success, string message) + { + Success = success; + MessageStack = new List() { message }; + } + + public bool Success { get; set; } + public bool AttemptToArchive { get; set; } + public List MessageStack { get; set; } + public ProcessStatusTypes ProcessStatusType { get; set; } + public bool? EntityIsUnknown { get; set; } + + public static ProcessResult ProcessCriticalFailure(ProcessResult processResult, string message) + { + return ProcessCriticalFailure(processResult, new List { message }); + } + + public static ProcessResult ProcessCriticalFailure(ProcessResult processResult, List messages) + { + processResult.ProcessStatusType = ProcessStatusTypes.CriticalFailure; + return ProcessFailure(processResult, messages, false); + } + + public static ProcessResult ProcessDataMappingFailure(ProcessResult processResult, string message) + { + processResult.ProcessStatusType = ProcessStatusTypes.DataMappingFailure; + return ProcessFailure(processResult, message, null); + } + + public static ProcessResult ProcessNotificationDataFailure(ProcessResult processResult, string message) + { + processResult.ProcessStatusType = ProcessStatusTypes.NotificationDataFailure; + return ProcessFailure(processResult, message, false); + } + + public static ProcessResult ProcessCompleted(ProcessResult processResult, string message) + { + processResult.ProcessStatusType = ProcessStatusTypes.Completed; + return ProcessSuccess(processResult, new List { message }, false);; + } + + private static ProcessResult ProcessFailure(ProcessResult processResult, string message, bool? entityIsUnknown) + { + return ProcessFailure(processResult, new List { message }, entityIsUnknown); + } + + private static ProcessResult ProcessFailure(ProcessResult processResult, List messages, bool? entityIsUnknown) + { + processResult.Success = false; + processResult.MessageStack.AddRange(messages); + processResult.EntityIsUnknown = entityIsUnknown; + return processResult; + } + + private static ProcessResult ProcessSuccess(ProcessResult processResult, List messages, bool? entityUnknown) + { + processResult.Success = true; + processResult.MessageStack.AddRange(messages); + processResult.EntityIsUnknown = entityUnknown; + return processResult; + } + } + + +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/ProcessStatusTypeEmailRequest.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/ProcessStatusTypeEmailRequest.cs new file mode 100644 index 0000000..19d5879 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/ProcessStatusTypeEmailRequest.cs @@ -0,0 +1,35 @@ +using LCU.Library.Internal.ApiResponse.Models; +using LCU.Library.Internal.DocumentIngestorModels.Enums; +using System.Collections.Generic; +using System.Linq; + +namespace LCU.Library.Internal.DocumentIngestorModels.Requests +{ + public class ProcessStatusTypeEmailRequest : ReturnResponse + { + private List NotAllowedStatuses => new() { Enums.ProcessStatusTypes.Completed, Enums.ProcessStatusTypes.Processing }; + + public ProcessStatusTypeEmailRequest() + { + } + + public ProcessStatusTypeEmailRequest(List emailAddresses, List processStatusTypes, string processStatusTypeEmailUrl) + { + this.EmailAddresses = emailAddresses; + this.ProcessStatusTypes = processStatusTypes; + this.ProcessStatusTypeEmailUrl = processStatusTypeEmailUrl; + } + + public List EmailAddresses { get; set; } + public List ProcessStatusTypes { get; set; } + public string ProcessStatusTypeEmailUrl { get; set; } + public bool HasInvalidStatuses(out List invalid) + { + invalid = ProcessStatusTypes + .Where(x => NotAllowedStatuses.Contains(x)) + .ToList(); + + return invalid.Any(); + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/ProcessingRequest.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/ProcessingRequest.cs new file mode 100644 index 0000000..1cce1b8 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/ProcessingRequest.cs @@ -0,0 +1,17 @@ +using System; +using LCU.Library.Internal.DocumentIngestorModels.Entities; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models +{ + public class ProcessingRequest + { + public int DocumentProcessingInfoId { get; set; } + public Guid IngestorRunInfoId { get; set; } + public IngestorRequest IngestorRequest { get; set; } + public string DocumentFileName { get; set; } + public string DocumentTypeDisplayName { get; set; } + public string DocumentValuePayload { get; set; } + public OwnerOverrideInfo OwnerOverrideInfo { get; set; } + public int RetryCount { get; set; } = 0; + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/QueueResult/QueueCompletionResult.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/QueueResult/QueueCompletionResult.cs new file mode 100644 index 0000000..fc3aa4e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/QueueResult/QueueCompletionResult.cs @@ -0,0 +1,7 @@ +namespace LCU.Library.Internal.DocumentIngestorModels.Models.QueueResult; + +public class QueueCompletionResult +{ + public bool Success { get; set; } + public CompletionRequest CompletionRequest { get; set; } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/QueueResult/QueueGatherMemberNotificationInfoResult.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/QueueResult/QueueGatherMemberNotificationInfoResult.cs new file mode 100644 index 0000000..1c616ce --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/QueueResult/QueueGatherMemberNotificationInfoResult.cs @@ -0,0 +1,7 @@ +namespace LCU.Library.Internal.DocumentIngestorModels.Models.QueueResult; + +public class QueueGatherMemberNotificationInfoResult +{ + public bool Success { get; set; } + public UploadCompletionRequest OriginalRequest { get; set; } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/UploadCompletionRequest.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/UploadCompletionRequest.cs new file mode 100644 index 0000000..1097896 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/UploadCompletionRequest.cs @@ -0,0 +1,16 @@ +using LCU.Library.Internal.ApiResponse.Models; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models; + +public class UploadCompletionRequest +{ + public UploadCompletionRequest() { } + public UploadCompletionRequest(CompletionRequest completionRequest, Response response) + { + CompletionRequest = completionRequest; + Response = response; + } + + public CompletionRequest CompletionRequest { get; set; } + public Response Response { get; set; } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/XmlParser/XmlOsgHistoricalDocuments.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/XmlParser/XmlOsgHistoricalDocuments.cs new file mode 100644 index 0000000..047451b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Models/XmlParser/XmlOsgHistoricalDocuments.cs @@ -0,0 +1,55 @@ +using System; +using System.ComponentModel; +using System.Xml.Serialization; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models.XmlParser; + +[Serializable] +[XmlType(AnonymousType = true)] +[XmlRoot(ElementName = "DOCUMENT", Namespace = "", IsNullable = false)] +public class XmlOsgHistoricalDocument +{ + [XmlAttribute("accountNumber")] + public string MemberNumberOrUserId { get; set; } + + [XmlAttribute("documentDate")] + public string CreationDate { get; set; } + + [XmlAttribute("documentType")] + public string DocumentType { get; set; } + + [XmlElement("ArchiveOutput")] + public XmlOsgArchiveOutput ArchiveOutput { get; set; } + + [XmlElement("OriginalAddress")] + public XmlOsgOriginalAddress OriginalAddress { get; set; } + + public string XmlOutput { get; set; } +} + +[Serializable] +[DesignerCategory("code")] +[XmlType(AnonymousType = true)] +[XmlRoot("ArchiveOutput", IsNullable = false)] +public class XmlOsgArchiveOutput +{ + [XmlAttribute("startPage")] + public int StartingPage { get; set; } + + [XmlAttribute("numberOfPages")] + public int NumberOfPages { get; set; } + + [XmlAttribute("fileSeq")] + public int PdfIndex { get; set; } +} + + +[Serializable] +[DesignerCategory("code")] +[XmlType(AnonymousType = true)] +[XmlRoot("OriginalAddress", IsNullable = false)] +public class XmlOsgOriginalAddress +{ + [XmlAttribute("addr1")] + public string EntityName { get; set; } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Pagination/Filter.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Pagination/Filter.cs new file mode 100644 index 0000000..c1e4354 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Pagination/Filter.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; +using LCU.Library.Internal.DocumentIngestorModels.Enums; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models.Pagination +{ + public class Filter + { + /// + /// Filter has default of all statuses to CreatedDate Descending for sorting. + /// + public Filter() + { + var listStatus = new List(); + foreach (var item in Enum.GetValues(typeof(ProcessStatusTypes))) + { + var statusFilters = new List + { + new() { IsEnabled = true, StatusType = (ProcessStatusTypes)item, IsUnknown = false }, + new() { IsEnabled = true, StatusType = (ProcessStatusTypes)item, IsUnknown = true } + }; + listStatus.AddRange(statusFilters); + } + + var listSortableFields = new List(); + + SortableField sortField = new SortableField { Field = Constants.DocumentProcessingInfoSortableFields.CreatedDate, IsDescending = true }; + listSortableFields.Add(sortField); + + this.StatusFilters = listStatus; + this.SortableFields = listSortableFields; + this.Page = 1; + this.Limit = 10; + } + public string DocType { get; set; } + public string DocBusinessName { get; set; } + public Guid? IngestorRunInfoId { get; set; } + public DateTime? CreatedDateStart { get; set; } = null; + public DateTime? CreatedDateEnd { get; set; } = null; + public List StatusFilters { get; set; } + public IDictionary CustomIndexFileFiltersEquals { get; set; } = null; + public IDictionary CustomIndexFileFiltersLikeOr { get; set; } = null; + public List SortableFields { get; set; } + public int Page { get; set; } + [Range(1, 1000)] + public int Limit { get; set; } + public List NotificationStatusFilters { get; set; } = null; + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Pagination/PagedResponse.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Pagination/PagedResponse.cs new file mode 100644 index 0000000..b98dac6 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Pagination/PagedResponse.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models.Pagination +{ + public class PagedResponse where T: class + { + public PagedResponse() { } + public PagedResponse(PagedResult pagedResult, Filter filter) + { + TotalItems = pagedResult.Total; + Items = pagedResult.Items; + TotalPages = pagedResult.Total == 0 ? 1 : (int)Math.Ceiling((decimal)pagedResult.Total / filter.Limit); + CurrentPage = filter.Page > this.TotalPages ? this.TotalPages : filter.Page; + + if (pagedResult.Total > (filter.Page * filter.Limit)) + { + NextPage = filter.Page + 1; + } + if (filter.Page > 1) + { + PreviousPage = filter.Page - 1; + } + } + public IEnumerable Items { get; set; } + public int NextPage { get; set; } + public int PreviousPage { get; set; } + public int TotalItems { get; set; } + public int CurrentPage { get; set; } + public int TotalPages { get; set; } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Pagination/PagedResult.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Pagination/PagedResult.cs new file mode 100644 index 0000000..68bc40e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Pagination/PagedResult.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models.Pagination +{ + public class PagedResult where T: class + { + public IEnumerable Items { get; set; } + public int Total { get; set; } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Pagination/SortableField.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Pagination/SortableField.cs new file mode 100644 index 0000000..0e36e5d --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Pagination/SortableField.cs @@ -0,0 +1,9 @@ +namespace LCU.Library.Internal.DocumentIngestorModels.Models.Pagination +{ + public class SortableField + { + public string Field { get; set; } + public int Position { get; set; } + public bool IsDescending { get; set; } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Pagination/StatusFilter.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Pagination/StatusFilter.cs new file mode 100644 index 0000000..0a43b70 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Pagination/StatusFilter.cs @@ -0,0 +1,11 @@ +using LCU.Library.Internal.DocumentIngestorModels.Enums; + +namespace LCU.Library.Internal.DocumentIngestorModels.Models.Pagination +{ + public class StatusFilter + { + public bool IsEnabled { get; set; } + public bool IsUnknown { get; set; } + public ProcessStatusTypes StatusType { get; set; } + } +} diff --git a/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Validations/MetaDataValidation.cs b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Validations/MetaDataValidation.cs new file mode 100644 index 0000000..3a8ac7b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/LCU.Library.Internal.DocumentIngestorModels/Validations/MetaDataValidation.cs @@ -0,0 +1,84 @@ +using System; +using System.Globalization; +using LCU.Library.DocumentType.Extensions; +using LCU.Library.Internal.DocumentIngestorModels.Constants; +using LCU.Library.Internal.DocumentIngestorModels.Models; + +namespace LCU.Library.Internal.DocumentIngestorModels.Validations +{ + public static class MetaDataValidation + { + public static ProcessResult ValidateAccountNumber(ProcessResult processResult, string accountNumber) + { + if (string.IsNullOrWhiteSpace(accountNumber) || accountNumber == "0") + { + processResult = ProcessResult.ProcessDataMappingFailure(processResult, ValidationMessages.AccountInvalidMessage); + } + + return processResult; + } + + public static ProcessResult ValidateFileName(ProcessResult processResult, string fileName) + { + if (string.IsNullOrWhiteSpace(fileName)) + { + processResult = ProcessResult.ProcessDataMappingFailure(processResult, ValidationMessages.FileNameInvalidMessage); + } + + return processResult; + } + + public static ProcessResult ValidateFullName(ProcessResult processResult, string fullName) + { + if (string.IsNullOrWhiteSpace(fullName)) + { + processResult = ProcessResult.ProcessDataMappingFailure(processResult, ValidationMessages.FullNameInvalidMessage); + } + + return processResult; + } + + public static ProcessResult ValidateDocumentType(ProcessResult processResult, string documentType) where T: Enum + { + if (string.IsNullOrWhiteSpace(documentType) || !EnumExtensions.IsDocumentTypeOf(documentType)) + { + processResult = ProcessResult.ProcessCriticalFailure(processResult, $"{ValidationMessages.DocumentTypeInvalidMessage}. Document Type provided was {documentType}, which was not of type {typeof(T).Name}"); + } + + return processResult; + } + + public static ProcessResult ValidatePdf(ProcessResult processResult, string pdf) + { + if (string.IsNullOrWhiteSpace(pdf)) + { + processResult = ProcessResult.ProcessDataMappingFailure(processResult, ValidationMessages.PdfInvalidMessage); + } + + return processResult; + } + + public static ProcessResult ValidateTin(ProcessResult processResult, string tin) + { + if (string.IsNullOrWhiteSpace(tin) || tin == "0") + { + processResult = ProcessResult.ProcessDataMappingFailure(processResult, ValidationMessages.TinInvalidMessage); + } + + return processResult; + } + + public static ProcessResult ValidateDate(ProcessResult processResult, string date, string format) + { + try{ + if (string.IsNullOrEmpty(date) || !DateTime.TryParseExact(date, format, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out _)){ + return ProcessResult.ProcessDataMappingFailure(processResult, $"{ValidationMessages.CreationDateInvalidMessage}. Date provided {date} could not be parsed from format {format}"); + } + } + catch (Exception){ + return ProcessResult.ProcessDataMappingFailure(processResult, ValidationMessages.CreationDateInvalidMessage); + } + return processResult; + } + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/README.md b/LCU.API.Internal.DocumentIngestor/README.md new file mode 100644 index 0000000..35b97e4 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/README.md @@ -0,0 +1,224 @@ +# Introduction + +--- + +The DocumentIngestor API was created to ingest large amounts of documents. These large requests generally come from an Index file which is comprised of many upload document requests. To accomplish this, DocumentIngestor API utilizes Landmarks micro service APIs such as FileOperations API, CoreApiWrapper, and DocumentTypeUploader API. + +# Getting Started + +--- + +The required environment is .NET Core 6.0, Git, Docker Desktop, RabbitMQ, and a local FileOperationsApi instance. + +- To run this API you will need a running RabbitMQ on Docker desktop + - Run the following in a cmd + - docker run -it --rm --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:3-management + - Access rabbitmq management UI http://localhost:15672/# + - UserName: guest, Password: guest +- You will need a local FileOperations and DocumentTypeUploader running + - FileOperations and DocumentTypeUploader are queue based APIs this application will need to be run locally. + For the DocumentIngestor to hear back when this has been performed, it must give the + API a ResponseItem. This uses the localhost rabbitmq set up. This should not use the QA RabbitMQ + as the QA API would then pick up the request and can't communicate to your local rabbitmq. + - FileOperations + - DevOps Repo: https://landmarkcu.visualstudio.com/Platform/_git/LCU.API.Internal.FileOperations + - When a FileOperations request such as MoveFile is requested it is placed on a queue. + - DocumentTypeUploader + - Devops Repo: https://landmarkcu.visualstudio.com/Platform/_git/LCU.API.Internal.DocumentTypeUploader + - After an UploadRequest is completed, DocumentTypeUploader will return a resulting DocumentId to DocumentIngestor + to be saved with its DocumentProcessingInfo. +- If not done already, you will need to publish your local instance of the DocumentIngestorSql database + +### Suggestions for IDE + +- JetBrains Rider +- Visual Studio 2022 + +### Pre Pull Request +Code is checked out from the Azure DevOps Repository. Before submitting your pull request, review the following: + +- Did you commit with a commitizen style message? +- Did you add all needed unit testing, and ensure all existing tests are passing? +- Make sure you didn't accidentally commit secrets or passwords. + +# Configuration + +--- + +Configuration is in appsettings.json, and updated with environment specific fields from vault and config mapping + +### Instances + +Currently, multiple instances of DocumentIngestor are running and need to be updated in configuration: +- DocumentIngestor +- DocumentIngestor-Preprocessor *(Going away)* +- DocumentIngestor-Historical + +# Build and Test + +--- + +Currently unit tests are the only level of testing that exist for this project. + +# Steps For Adding New Document Ingestors + +--- + +## Index file format has already been created: + +1. Add DocumentCode(s) to LCU.Library.DocumentType + - Make sure to put it under the correct ownership type enum. + - Add what it is listed in the index file as the enum's "Name" annotation. +2. Add new DocumentCodeDetail(s) in DocumentManager + +## Index file format has NOT already been created: + +1. Follow steps in "**Index file format has already been created**" + +2. Create new Enum IngestorTypes + - LCU.Library.Internal.DocumentIngestorModels --> Enums +3. Create new IndexFileDocument Model + - This model will reflect what values are pulled from the Index file and is a part of the ProcessingRequest. + - LCU.Library.Internal.DocumentIngestorModels --> Models --> IndexFileDocuments +4. Create a service class to parse the index file, create IngestorRunInfo, and create ProcessingRequest(s) + - This class will house all the custom work to parse index files/get documents that need to be uploaded and to create a list of ProcessingRequest. + - Every IndexParserServices class should contain a main method of HandleIndexRequest that returns a IngestorResult. + - Exceptions should be handled and should log failure and messages to the IngestorResult. + - Namespace: LCU.API.Internal.DocumentIngestor.Services.IndexParserServices + - LCU.API.Internal.DocumentIngestor --> Services --> IndexParserServices + - Example: FosTaxStatementIndexService +5. Add the new IngestorType to the ServicesFactoryConfiguration in the appsettings - IIndexParserService + - This will add the newly created IndexParserService class to the IndexServices.cs --> method PerformIngestor +6. Determine if the documents need a PdfParserService to ingest + - This would be if multiple documents are attached in one larger PDF file. + - If so: + 1. Create PdfParserService for ingestion type + 2. Add the service to the ServicesFactoryConfiguration in appsettings - IPdfIndexParserService +7. Create new service class to handle document processing + - This class will perform all the custom work. + - Validation of the IndexFileDocument Model values + - Calls classes such as PrimaryOwnerDeterminingService to get the Attributes + - Builds out UploadRequest + - Gets pdf content in bytes + - Uploads Document using the DocumentTypeUploaderApiService + - Namespace: LCU.API.Internal.DocumentIngestor.Services.DocumentProcessorServices + - LCU.API.Internal.DocumentIngestor --> Services --> DocumentProcessorServices + - Example: FosTaxStatementProcessingService +8. Add the new IngestorType to the ServicesFactoryConfiguration in the appsettings - IDocumentProcessingService + - This will add the newly created DocumentProcessorService class to the DocumentProcessorService.cs --> method PerformDocumentProcess +9. Add unit tests for any services created +10. Add attributes component to DocumentManager for new ingestion type + +## After adding a new ingestion type: + +1. Update NuGet packages for the following API's: + - LCU.API.Internal.Dispatcher + - LCU.API.Internal.DocumentTypeRetriever + - LCU.API.Internal.DocumentTypeUploader + - LCU.WebApps.Internal.DocumentManager +2. Add or update Dispatcher job to ingest new type + +# Services + +--- + +## IndexService + +The purpose of this service class is to call IngestorType's index parsing classes. + +1. This class is kicked off once an IngestorRequest has been consumed by the IngestorIndexConsumer. +2. The IngestorRequest has an IngestorTypes enum which is used in a switch to determine what Indexing class's HandleIndexRequest will be called. +3. Once the Ingestors Type's HandleIndexRequest was performed, an IngestorResult will be returned. This will contain a FatalFailure if a list of ProcessingRequest was not able to be created. +4. These ProcessingRequests will then be placed on the Processing queue (*LCU.DocumentIngestor.Processing*) with method SendProcessRequest. + +## DocumentProcessorService + +The purpose of this service class is to call IngestorType's processing classes. + +1. This class is kicked off once an IngestorRequest has been consumed by the IngestorProcessingConsumer. +2. The request will be checked if the document exists and isn't already archived. + - If archived, processing complete. The ProcessingRequest and empty ProcessResult can be placed on LCU.DocumentIngestor.Completion queue. +3. The ProcessingRequest's IngestorTypes enum will be used in a switch to determine what Processor class's ProcessRequest method will be called. +4. ProcessingRequest method is called and returns a ProcessResult + - If failed processing, process complete. The ProcessingRequest and ProcessResult can be placed on LCU.DocumentIngestor.Completion queue. +5. Processing successful document is set up to be archived by FileOperations + - FileOperations will place the response on LCU.DocumentIngestor.Completion queue. + - If the call to FileOperations throws an exception, the result is changed to false. The ProcessingRequest and ProcessResult are placed on LCU.DocumentIngestor.Completion queue. + +## CompletionService + +The purpose of this service class is to Update the IngestorRunInfo count and to finalize the IngestorRunInfo if total count is equal to the Success+Failure count. + +1. This class is kicked off once an LCU.Library.Internal.ApiResponse.Models.Response has been consumed by the queue IngestorProcessingConsumer (*LCU.DocumentIngestor.Completion*). + +## BaseOwnerDeterminingService + +The purpose of this service class is to reach out to our micro service APIs to determine the owners of the document based off the information given in the index file. + +- Different methods are available based on the information given for the ingestion type. +- Generally, we need at least two fields of data to verify the ownership of the document. +- Different services are available, based on the ownership type of the document type. + +## PdfPartitionerService + +The purpose of this service is to determine what and how the larger PDF needs to be parsed into smaller documents for ingestion. The request is then sent to FileOperations to process. + +- This service is only required if documents were sent from the vendor in a batch PDF. +- Currently, this process is kicked off by Dispatcher. +- Each ingestion type that requires this service, needs its own service class. *(See ["Steps For Adding New Document Ingestors"](#steps-for-adding-new-document-ingestors))* + +## MemberDocumentNotifierService + +*Resources: [Original MemberDocumentNotifier Workflow Design](https://landmarkcu.sharepoint.com/:u:/r/sites/ITProgrammingDevelopmentTeam/_layouts/15/Doc.aspx?sourcedoc=%7BA8685530-BFA6-4FA0-A19C-5B26B98B78B4%7D&file=MemberDocumentNotifier_Design_Workflow.vsdx&action=default&mobileredirect=true&DefaultItemOpen=1)* + +The purpose of this service is to generate email notifications to the owners of successfully ingested documents. + +1. This class is kicked off in UploadCompletionService once a document has been successfully uploaded, and the resulting DocumentId returned. +2. The request is then sent to MemberNotificationInfoDeterminingService to gather all of the required EAgreeUserIds +3. MemberDocumentNotifierService then takes the request to: + - Obtain the updated email from MemberPreferences + - Update the status of the MemberNotificationInfo + - Send a new email request to NotificationApi, grouped by EAgreeUserId and EmailAddress +4. MemberNotificationCompletionService then takes the response from the email request to: + - Update the status of the MemberNotificationInfo, based on the result + - Updates MemberPreferences if the email was either "Successful" or "Undeliverable" (Failed 3 times) + +## DocumentReprocessingService + +The purpose of this service is to gather DocumentProcessingInfos to resubmit on the DocumentProcessing queue (*LCU.DocumentIngestor.Processing*) as a ProcessingRequest. + +This is most commonly meant to override the owning entity from DocumentManager with an OwnerOverrideInfo. Queuing with an OwnerOverrideInfo will skip the OwnerDeterminingServices and ingest the document with the submitted entity values. + +## UploadCompletionReprocessingService + +The purpose of this service is to gather DocumentInformation for DocumentTypeRetriever and resubmit a CompletionRequest to the UploadCompletion queue (*LCU.DocumentIngestor.UploadCompletion*). Mainly, to reprocess all DocumentProcessingInfos with a ProcessStatus of NotificationDataFailure. + +This will only work if the DocumentProcessingInfo has a DocumentId, meaning the document was uploaded successfully. This will also kick off a new MemberNotificationInfo. + +## IngestionFolderCleanupService + +*Resources: [Original IngestorFolderCleanUp Workflow Design](https://landmarkcu.sharepoint.com/:u:/r/sites/ITProgrammingDevelopmentTeam/_layouts/15/Doc.aspx?sourcedoc=%7B013CB449-1132-4A52-B64E-D6086846C2FB%7D&file=IngestionFolderCleanUp_Workflow.vsdx&action=default&mobileredirect=true)* + +The purpose of this service is to delete zip files and directories that have already been ingested, therefore we no longer need the files. + +# Helpful Documents + +--- + +[DocumentManager Project File Repository](https://landmarkcu.sharepoint.com/sites/ITProgrammingDevelopmentTeam/Shared%20Documents/Forms/AllItems.aspx?id=%2Fsites%2FITProgrammingDevelopmentTeam%2FShared%20Documents%2FGeneral%2FProjects%2F2022%5FDocument%20Manager&viewid=99d45851%2D1c5c%2D483e%2Dbdda%2D7d5bee978feb) + | +[Platform Wiki](https://landmarkcu.visualstudio.com/Platform/_wiki/wikis/Platform.wiki/241/Welcome) + +### Project Files + +- [DocumentManager Overview](https://landmarkcu.sharepoint.com/:p:/r/sites/ITProgrammingDevelopmentTeam/_layouts/15/Doc.aspx?sourcedoc=%7BF7A54712-F5E5-4F9D-9008-3F8CE3BFFA3F%7D&file=Document%20Manager%20Overview.pptx&action=edit&mobileredirect=true) +- [DocumentManager High-Level Workflows](https://landmarkcu.sharepoint.com/:u:/r/sites/ITProgrammingDevelopmentTeam/_layouts/15/Doc.aspx?sourcedoc=%7B51F779B5-843A-4EE7-8404-66BDC4CB798D%7D&file=Document%20Manager%20High%20Level%20WorkFlows.vsdx&action=default&mobileredirect=true) +- [DocumentManager Components](https://landmarkcu.sharepoint.com/sites/ITProgrammingDevelopmentTeam/Shared%20Documents/Forms/AllItems.aspx?id=%2Fsites%2FITProgrammingDevelopmentTeam%2FShared%20Documents%2FGeneral%2FProjects%2F2022%5FDocument%20Manager%2F05%5FDocumentation%2FDocument%5FManager%5FComponents%2Epdf&viewid=99d45851%2D1c5c%2D483e%2Dbdda%2D7d5bee978feb&parent=%2Fsites%2FITProgrammingDevelopmentTeam%2FShared%20Documents%2FGeneral%2FProjects%2F2022%5FDocument%20Manager%2F05%5FDocumentation) +- [DocumentType Attributes](https://landmarkcu.sharepoint.com/:x:/r/sites/ITProgrammingDevelopmentTeam/_layouts/15/Doc.aspx?sourcedoc=%7B39809990-5B33-404B-89D3-6E8EFDDEEA75%7D&file=Document%20Type%20Attributes.xlsx&action=default&mobileredirect=true) +- [DocumentCodeDetails](https://landmarkcu.sharepoint.com/:x:/r/sites/ITProgrammingDevelopmentTeam/_layouts/15/Doc.aspx?sourcedoc=%7B1BE0B75A-8377-437C-A228-5F68588B3761%7D&file=DocTypes.xlsx&action=default&mobileredirect=true) + +### Workflow Designs: + - [Original DocumentIngestor Workflow Design](https://landmarkcu.sharepoint.com/:u:/r/sites/ITProgrammingDevelopmentTeam/_layouts/15/Doc.aspx?sourcedoc=%7BFA3B785D-10DF-46DE-9B66-509B2BA820F5%7D&file=Ingestor_Design_WorkFlow.vsdx&action=default&mobileredirect=true&DefaultItemOpen=1) + - [Original MemberDocumentNotifier Workflow Design](https://landmarkcu.sharepoint.com/:u:/r/sites/ITProgrammingDevelopmentTeam/_layouts/15/Doc.aspx?sourcedoc=%7BA8685530-BFA6-4FA0-A19C-5B26B98B78B4%7D&file=MemberDocumentNotifier_Design_Workflow.vsdx&action=default&mobileredirect=true&DefaultItemOpen=1) + - [Original IngestorFolderCleanUp Workflow Design](https://landmarkcu.sharepoint.com/:u:/r/sites/ITProgrammingDevelopmentTeam/_layouts/15/Doc.aspx?sourcedoc=%7B013CB449-1132-4A52-B64E-D6086846C2FB%7D&file=IngestionFolderCleanUp_Workflow.vsdx&action=default&mobileredirect=true) + - [Original BatchIngestion Workflow Design](https://landmarkcu.sharepoint.com/:u:/r/sites/ITProgrammingDevelopmentTeam/_layouts/15/Doc.aspx?sourcedoc=%7BDF037938-C14E-48F4-9D56-2718B8CEFFA5%7D&file=BatchIngestion_Design_Workflow.vsdx&action=default&mobileredirect=true) \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/_kube_local_testing/kind.cluster.config b/LCU.API.Internal.DocumentIngestor/_kube_local_testing/kind.cluster.config new file mode 100644 index 0000000..e2da28d --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/_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: 81 diff --git a/LCU.API.Internal.DocumentIngestor/_kube_local_testing/linux/setup_and_deploy.sh b/LCU.API.Internal.DocumentIngestor/_kube_local_testing/linux/setup_and_deploy.sh new file mode 100644 index 0000000..5b14d19 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/_kube_local_testing/linux/setup_and_deploy.sh @@ -0,0 +1,29 @@ +APP_NAME="document-ingestor" +APP_VERSION="1.0" +echo "Setting up cluster..." +mkdir -p logs +LOG_FILE="logs/k8s_setup.log" +kind create cluster --config ../kind.cluster.config --wait 300s --name $APP_NAME 2>&1 | tee -a $LOG_FILE +kubectl create namespace landmarkcu --dry-run=client -o yaml | kubectl apply -f - 2>&1 >> $LOG_FILE + +echo "deploying ingress-nginx..." 2>&1 | tee -a $LOG_FILE +helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx 2>&1 >> $LOG_FILE +helm repo update 2>&1 >> $LOG_FILE + +helm upgrade --install my-release ingress-nginx/ingress-nginx \ + --set controller.service.type=LoadBalancer \ + --set controller.service.nodePorts.http=30000 \ + --set controller.service.nodePorts.https=30001 2>&1 >> $LOG_FILE + +echo "...ingress-nginx deployed!" 2>&1 >> $LOG_FILE + +echo "performing docker build..." 2>&1 >> $LOG_FILE +LOG_FILE="logs/docker_build.log" +docker build -t local/$APP_NAME:$APP_VERSION ../.. 2>&1 >> $LOG_FILE +echo "docker build complete!" + +kind load docker-image local/$APP_NAME:$APP_VERSION --name $APP_NAME 2>&1 >> $LOG_FILE + +echo "applying $app_name to kubernetes cluster" 2>&1 | tee -a $LOG_FILE +LOG_FILE="logs/kubectl_apply.log" +kubectl apply -k ../../_deploy/overlays/local 2>&1 >> $LOG_FILE diff --git a/LCU.API.Internal.DocumentIngestor/_kube_local_testing/linux/teardown.sh b/LCU.API.Internal.DocumentIngestor/_kube_local_testing/linux/teardown.sh new file mode 100644 index 0000000..1bfdd7d --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/_kube_local_testing/linux/teardown.sh @@ -0,0 +1,5 @@ +APP_NAME="document-ingestor" +mkdir -p logs +LOG_FILE="logs/cluster_teardown.log" +kind delete cluster --name $APP_NAME 2>&1 | tee -a $LOG_FILE +echo "Deletion complete!" 2>&1 | tee -a $LOG_FILE \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/_kube_local_testing/linux/update_pod.sh b/LCU.API.Internal.DocumentIngestor/_kube_local_testing/linux/update_pod.sh new file mode 100644 index 0000000..6f099e3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/_kube_local_testing/linux/update_pod.sh @@ -0,0 +1,2 @@ +kubectl delete -k ../../_deploy/overlays/local +kubectl apply -k ../../_deploy/overlays/local \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/_kube_local_testing/windows/install_dependencies.ps1 b/LCU.API.Internal.DocumentIngestor/_kube_local_testing/windows/install_dependencies.ps1 new file mode 100644 index 0000000..e9092b8 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/_kube_local_testing/windows/install_dependencies.ps1 @@ -0,0 +1,2 @@ +cinst -y kind +cinst -y kubernetes-helm diff --git a/LCU.API.Internal.DocumentIngestor/_kube_local_testing/windows/setup_and_deploy.ps1 b/LCU.API.Internal.DocumentIngestor/_kube_local_testing/windows/setup_and_deploy.ps1 new file mode 100644 index 0000000..12b2feb --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/_kube_local_testing/windows/setup_and_deploy.ps1 @@ -0,0 +1,19 @@ +$APP_NAME = "blend-api-wrapper" +$APP_VERSION = "1.0" +kind create cluster --config ../kind.cluster.config --wait 300s + +kubectl create namespace landmarkcu + +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/${APP_NAME}:${APP_VERSION} ../.. + +kind load docker-image local/${APP_NAME}:${APP_VERSION} + +kubectl apply -k ..\..\_deploy\overlays\local diff --git a/LCU.API.Internal.DocumentIngestor/_kube_local_testing/windows/teardown.ps1 b/LCU.API.Internal.DocumentIngestor/_kube_local_testing/windows/teardown.ps1 new file mode 100644 index 0000000..330c3d1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/_kube_local_testing/windows/teardown.ps1 @@ -0,0 +1,2 @@ +$APP_NAME="document-ingestor" +kind delete cluster --name $APP_NAME diff --git a/LCU.API.Internal.DocumentIngestor/azdo_pipelines/azure-k8s-pipeline.yaml b/LCU.API.Internal.DocumentIngestor/azdo_pipelines/azure-k8s-pipeline.yaml new file mode 100644 index 0000000..ace5fc0 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/azdo_pipelines/azure-k8s-pipeline.yaml @@ -0,0 +1,78 @@ +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.documentingestor-documentingestor +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' + +# DACPAC BUILD AND PUSH +- template: db-build-deploy.yaml@azdo_pipeline_templates + parameters: + azdo_agent_pool: $(pvar_azdo_agent_pool_db) + azdo_deployment_environment: $(pvar_azdo_deployment_environment_db) + sql_project_path: './LCU.API.Internal.DocumentIngestorSql/LCU.API.Internal.DocumentIngestorSql.sqlproj' + built_sql_dacpac_file_path: './LCU.API.Internal.DocumentIngestorSql/bin/Release/LCU.API.Internal.DocumentIngestorSql.dacpac' + name_of_artifact: LCU_API_Internal_DocumentIngestorSql_dacpac + db_name: $(pvar_LCU_API_Internal_DocumentIngestorSql_db_name) + sql_server_name: $(pvar_LCU_API_Internal_DocumentIngestorSql_sql_server_name) + +# DACPAC BUILD AND PUSH HISTORICAL +- template: db-build-deploy.yaml@azdo_pipeline_templates + parameters: + azdo_agent_pool: $(pvar_azdo_agent_pool_db) + azdo_deployment_environment: $(pvar_azdo_deployment_environment_db) + sql_project_path: './LCU.API.Internal.DocumentIngestorSql/LCU.API.Internal.DocumentIngestorSql.sqlproj' + built_sql_dacpac_file_path: './LCU.API.Internal.DocumentIngestorSql/bin/Release/LCU.API.Internal.DocumentIngestorSql.dacpac' + name_of_artifact: LCU_API_Internal_DocumentIngestorHistoricalSql_dacpac + db_name: $(pvar_LCU_API_Internal_DocumentIngestorHistoricalSql_db_name) + sql_server_name: $(pvar_LCU_API_Internal_DocumentIngestorSql_sql_server_name) + +# 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'], 'master')) + 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.DocumentIngestor/azdo_pipelines/azure-pipelines-feature-branches.yaml b/LCU.API.Internal.DocumentIngestor/azdo_pipelines/azure-pipelines-feature-branches.yaml new file mode 100644 index 0000000..0dd52f4 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/azdo_pipelines/azure-pipelines-feature-branches.yaml @@ -0,0 +1,10 @@ +trigger: + branches: + include: + - '*' + exclude: + - 'master' + - 'develop' +extends: + template: azure-k8s-pipeline.yaml + diff --git a/LCU.API.Internal.DocumentIngestor/azdo_pipelines/azure-pipelines-prd.yaml b/LCU.API.Internal.DocumentIngestor/azdo_pipelines/azure-pipelines-prd.yaml new file mode 100644 index 0000000..bc94844 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/azdo_pipelines/azure-pipelines-prd.yaml @@ -0,0 +1,9 @@ +trigger: + branches: + include: + - 'master' +extends: + template: azure-k8s-pipeline.yaml + parameters: + target_environment: prd + k8s_namespace: landmarkcu diff --git a/LCU.API.Internal.DocumentIngestor/azdo_pipelines/azure-pipelines-qa.yaml b/LCU.API.Internal.DocumentIngestor/azdo_pipelines/azure-pipelines-qa.yaml new file mode 100644 index 0000000..f581dd4 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/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.DocumentIngestor/azdo_pipelines/azure-pipelines-uat.yaml b/LCU.API.Internal.DocumentIngestor/azdo_pipelines/azure-pipelines-uat.yaml new file mode 100644 index 0000000..76ca2ae --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/azdo_pipelines/azure-pipelines-uat.yaml @@ -0,0 +1,9 @@ +trigger: + branches: + include: + - 'master' +extends: + template: azure-k8s-pipeline.yaml + parameters: + target_environment: uat + k8s_namespace: landmarkcu diff --git a/LCU.API.Internal.DocumentIngestor/azdo_pipelines/config-files/prd-pvars.yaml b/LCU.API.Internal.DocumentIngestor/azdo_pipelines/config-files/prd-pvars.yaml new file mode 100644 index 0000000..e7041b5 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/azdo_pipelines/config-files/prd-pvars.yaml @@ -0,0 +1,13 @@ +--- +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 + + pvar_LCU_API_Internal_DocumentIngestorSql_db_name: DocumentIngestor + pvar_LCU_API_Internal_DocumentIngestorHistoricalSql_db_name: DocumentIngestorHistorical + pvar_LCU_API_Internal_DocumentIngestorSql_sql_server_name: D1CLS01P diff --git a/LCU.API.Internal.DocumentIngestor/azdo_pipelines/config-files/qa-pvars.yaml b/LCU.API.Internal.DocumentIngestor/azdo_pipelines/config-files/qa-pvars.yaml new file mode 100644 index 0000000..ac0df83 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/azdo_pipelines/config-files/qa-pvars.yaml @@ -0,0 +1,13 @@ +--- +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 + + pvar_LCU_API_Internal_DocumentIngestorSql_db_name: DocumentIngestor + pvar_LCU_API_Internal_DocumentIngestorHistoricalSql_db_name: DocumentIngestorHistorical + pvar_LCU_API_Internal_DocumentIngestorSql_sql_server_name: DAZCDTBWEB01Q \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/azdo_pipelines/config-files/uat-pvars.yaml b/LCU.API.Internal.DocumentIngestor/azdo_pipelines/config-files/uat-pvars.yaml new file mode 100644 index 0000000..317de87 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/azdo_pipelines/config-files/uat-pvars.yaml @@ -0,0 +1,13 @@ +--- +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 + + pvar_LCU_API_Internal_DocumentIngestorSql_db_name: DocumentIngestor + pvar_LCU_API_Internal_DocumentIngestorHistoricalSql_db_name: DocumentIngestorHistorical + pvar_LCU_API_Internal_DocumentIngestorSql_sql_server_name: WEBCLSU diff --git a/LCU.API.Internal.DocumentIngestor/cleanbuildrun.sh b/LCU.API.Internal.DocumentIngestor/cleanbuildrun.sh new file mode 100644 index 0000000..d39a0db --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/cleanbuildrun.sh @@ -0,0 +1,16 @@ +#!/bin/bash +echo "Building Document Ingestor Docker Image"; +dotnet clean +rm -rf LCU.API.Internal.DocumentIngestor/bin +rm -rf LCU.API.Internal.DocumentIngestor/obj +rm -rf LCU.API.Internal.DocumentIngestorLib/bin +rm -rf LCU.API.Internal.DocumentIngestorLib/obj +rm -rf LCU.Library.Internal.DocumentIngestorModels/bin +rm -rf LCU.Library.Internal.DocumentIngestorModels/obj +rm -rf LCU.API.Internal.DocumentIngestorTest/obj +rm -rf LCU.API.Internal.DocumentIngestorTest/bin +docker build -t landmarkcu/document-ingestor . +echo "Running Document Ingestor Docker Container"; +docker run -p 8080:80 landmarkcu/document-ingestor + + diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/base/Deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/base/Deployment.yaml new file mode 100644 index 0000000..008bebd --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/base/Deployment.yaml @@ -0,0 +1,44 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: document-ingestor-api +spec: + replicas: 1 + selector: + matchLabels: + app: document-ingestor-api + strategy: + rollingUpdate: + maxSurge: 25% + maxUnavailable: 25% + type: RollingUpdate + template: + metadata: + labels: + app: document-ingestor-api + spec: + volumes: [] + containers: + - name: document-ingestor-api + env: [] + volumeMounts: [] + image: document-ingestor-api + resources: + limits: + memory: "1536Mi" + cpu: "500m" + ports: + - containerPort: 8080 + livenessProbe: + initialDelaySeconds: 5 + periodSeconds: 5 + httpGet: + path: /status + port: 8080 + readinessProbe: + initialDelaySeconds: 5 + periodSeconds: 5 + httpGet: + path: /status + port: 8080 diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/base/Service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/base/Service.yaml new file mode 100644 index 0000000..043564c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/base/Service.yaml @@ -0,0 +1,11 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: document-ingestor-api +spec: + selector: + app: document-ingestor-api + ports: + - port: 8080 + targetPort: 8080 diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/base/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/base/kustomization.yaml new file mode 100644 index 0000000..e48cadb --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/base/kustomization.yaml @@ -0,0 +1,9 @@ +resources: + - Deployment.yaml + - Service.yaml + - secrets-provider-class.yaml + - virtual-service.yaml + +images: +- name: document-ingestor-api + newName: landmarkcu/lcu.api.internal.documentingestor-documentingestor \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/base/secrets-provider-class.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/base/secrets-provider-class.yaml new file mode 100644 index 0000000..780227a --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/base/secrets-provider-class.yaml @@ -0,0 +1,11 @@ +--- +apiVersion: secrets-store.csi.x-k8s.io/v1 +kind: SecretProviderClass +metadata: + name: document-ingestor-api-secrets-provider +spec: + provider: azure + parameters: + usePodIdentity: "false" + useVMManagedIdentity: "true" + tenantId: 63cd1554-2783-4a86-ae50-b9e6c21c9499 diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/base/virtual-service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/base/virtual-service.yaml new file mode 100644 index 0000000..321dd5b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/base/virtual-service.yaml @@ -0,0 +1,19 @@ +--- +apiVersion: networking.istio.io/v1beta1 +kind: VirtualService +metadata: + name: document-ingestor-api +spec: + hosts: [] + gateways: + - istio-system/ingress-gateway + http: + - name: document-ingestor-api + match: + - uri: + prefix: / + route: + - destination: + host: document-ingestor-api + port: + number: 8080 diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/historical/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/historical/kustomization.yaml new file mode 100644 index 0000000..0ae1552 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/historical/kustomization.yaml @@ -0,0 +1,10 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +patches: + - target: + kind: Deployment + path: set_secrets_deployment.yaml + - target: + kind: SecretProviderClass + path: set_secrets_provider.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/historical/set_secrets_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/historical/set_secrets_deployment.yaml new file mode 100644 index 0000000..13eefee --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/historical/set_secrets_deployment.yaml @@ -0,0 +1,89 @@ +- op: add + path: /spec/template/spec/volumes/- + value: + name: document-ingestor-api-secrets + csi: + driver: secrets-store.csi.k8s.io + readOnly: true + volumeAttributes: + secretProviderClass: historical-document-ingestor-api-secrets-provider + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: document-ingestor-api-secrets + mountPath: /vault/secrets/document-ingestor-application-insights-instrumentation-key.json + readOnly: true + subPath: document-ingestor-historical-application-insights-instrumentation-key + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: document-ingestor-api-secrets + mountPath: /vault/secrets/document-ingestor-azure-ad-client-secret.json + readOnly: true + subPath: document-ingestor-historical-azure-ad-client-secret + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: document-ingestor-api-secrets + mountPath: /vault/secrets/document-ingestor-database-connection.json + readOnly: true + subPath: document-ingestor-historical-database-connection + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: document-ingestor-api-secrets + mountPath: /vault/secrets/document-ingestor-environment-from-vault.json + readOnly: true + subPath: document-ingestor-historical-environment-from-vault + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: document-ingestor-api-secrets + mountPath: /vault/secrets/document-ingestor-document-ingestor-api-key.json + readOnly: true + subPath: document-ingestor-historical-document-ingestor-api-key + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: document-ingestor-api-secrets + mountPath: /vault/secrets/document-ingestor-document-manager.json + readOnly: true + subPath: document-ingestor-historical-document-manager + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: document-ingestor-api-secrets + mountPath: /vault/secrets/document-ingestor-queue-password.json + readOnly: true + subPath: document-ingestor-historical-queue-password + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: document-ingestor-api-secrets + mountPath: /vault/secrets/document-ingestor-queue-user-name.json + readOnly: true + subPath: document-ingestor-historical-queue-user-name + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: document-ingestor-api-secrets + mountPath: /vault/secrets/document-ingestor-seq-api-key.json + readOnly: true + subPath: document-ingestor-historical-seq-api-key + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: document-ingestor-api-secrets + mountPath: /vault/secrets/document-ingestor-mobile-banking-api-key.json + readOnly: true + subPath: document-ingestor-historical-mobile-banking-api-key diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/historical/set_secrets_provider.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/historical/set_secrets_provider.yaml new file mode 100644 index 0000000..db145bc --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/historical/set_secrets_provider.yaml @@ -0,0 +1,44 @@ +- op: add + path: /spec/parameters/objects + value: | + array: + - | + objectName: document-ingestor-historical-application-insights-instrumentation-key + objectType: secret + objectVersion: "" + - | + objectName: document-ingestor-historical-azure-ad-client-secret + objectType: secret + objectVersion: "" + - | + objectName: document-ingestor-historical-database-connection + objectType: secret + objectVersion: "" + - | + objectName: document-ingestor-historical-document-ingestor-api-key + objectType: secret + objectVersion: "" + - | + objectName: document-ingestor-historical-document-manager + objectType: secret + objectVersion: "" + - | + objectName: document-ingestor-historical-environment-from-vault + objectType: secret + objectVersion: "" + - | + objectName: document-ingestor-historical-queue-password + objectType: secret + objectVersion: "" + - | + objectName: document-ingestor-historical-queue-user-name + objectType: secret + objectVersion: "" + - | + objectName: document-ingestor-historical-seq-api-key + objectType: secret + objectVersion: "" + - | + objectName: document-ingestor-historical-mobile-banking-api-key + objectType: secret + objectVersion: "" diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/normal/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/normal/kustomization.yaml new file mode 100644 index 0000000..0ae1552 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/normal/kustomization.yaml @@ -0,0 +1,10 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +patches: + - target: + kind: Deployment + path: set_secrets_deployment.yaml + - target: + kind: SecretProviderClass + path: set_secrets_provider.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/normal/set_secrets_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/normal/set_secrets_deployment.yaml new file mode 100644 index 0000000..5f68cca --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/normal/set_secrets_deployment.yaml @@ -0,0 +1,89 @@ +- op: add + path: /spec/template/spec/volumes/- + value: + name: document-ingestor-api-secrets + csi: + driver: secrets-store.csi.k8s.io + readOnly: true + volumeAttributes: + secretProviderClass: normal-document-ingestor-api-secrets-provider + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: document-ingestor-api-secrets + mountPath: /vault/secrets/document-ingestor-application-insights-instrumentation-key.json + readOnly: true + subPath: document-ingestor-application-insights-instrumentation-key + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: document-ingestor-api-secrets + mountPath: /vault/secrets/document-ingestor-azure-ad-client-secret.json + readOnly: true + subPath: document-ingestor-azure-ad-client-secret + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: document-ingestor-api-secrets + mountPath: /vault/secrets/document-ingestor-database-connection.json + readOnly: true + subPath: document-ingestor-database-connection + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: document-ingestor-api-secrets + mountPath: /vault/secrets/document-ingestor-environment-from-vault.json + readOnly: true + subPath: document-ingestor-environment-from-vault + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: document-ingestor-api-secrets + mountPath: /vault/secrets/document-ingestor-document-ingestor-api-key.json + readOnly: true + subPath: document-ingestor-document-ingestor-api-key + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: document-ingestor-api-secrets + mountPath: /vault/secrets/document-ingestor-document-manager.json + readOnly: true + subPath: document-ingestor-document-manager + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: document-ingestor-api-secrets + mountPath: /vault/secrets/document-ingestor-queue-password.json + readOnly: true + subPath: document-ingestor-queue-password + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: document-ingestor-api-secrets + mountPath: /vault/secrets/document-ingestor-queue-user-name.json + readOnly: true + subPath: document-ingestor-queue-user-name + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: document-ingestor-api-secrets + mountPath: /vault/secrets/document-ingestor-seq-api-key.json + readOnly: true + subPath: document-ingestor-seq-api-key + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: document-ingestor-api-secrets + mountPath: /vault/secrets/document-ingestor-mobile-banking-api-key.json + readOnly: true + subPath: document-ingestor-mobile-banking-api-key diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/normal/set_secrets_provider.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/normal/set_secrets_provider.yaml new file mode 100644 index 0000000..2374c12 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/keyvaults/normal/set_secrets_provider.yaml @@ -0,0 +1,44 @@ +- op: add + path: /spec/parameters/objects + value: | + array: + - | + objectName: document-ingestor-application-insights-instrumentation-key + objectType: secret + objectVersion: "" + - | + objectName: document-ingestor-azure-ad-client-secret + objectType: secret + objectVersion: "" + - | + objectName: document-ingestor-database-connection + objectType: secret + objectVersion: "" + - | + objectName: document-ingestor-document-ingestor-api-key + objectType: secret + objectVersion: "" + - | + objectName: document-ingestor-document-manager + objectType: secret + objectVersion: "" + - | + objectName: document-ingestor-environment-from-vault + objectType: secret + objectVersion: "" + - | + objectName: document-ingestor-queue-password + objectType: secret + objectVersion: "" + - | + objectName: document-ingestor-queue-user-name + objectType: secret + objectVersion: "" + - | + objectName: document-ingestor-seq-api-key + objectType: secret + objectVersion: "" + - | + objectName: document-ingestor-mobile-banking-api-key + objectType: secret + objectVersion: "" diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-batchupdatemembernotif/appsettings/appsettings.json b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-batchupdatemembernotif/appsettings/appsettings.json new file mode 100644 index 0000000..4830cc5 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-batchupdatemembernotif/appsettings/appsettings.json @@ -0,0 +1,57 @@ +{ + "Primary": { + "FeatureFlags": { + "RunBatchIngestionConsumer": false, + "RunIngestorIndexConsumer": false, + "RunIngestorProcessingConsumer": false, + "RunIngestorCompletionConsumer": false, + "RunIngestionFolderCleanUpConsumer": false, + "RunPdfPartitionerConsumer": false, + "RunPdfPartitionerCompletionConsumer": false, + "RunUploadCompletionConsumer": false, + "RunMemberDocumentNotifierConsumer": false, + "RunMemberNotificationCompletionConsumer": false, + "RunGatherMemberNotificationInfoConsumer": false, + "RunBatchUpdateMemberNotificationDataConsumer": true, + "RestrictNotificationRecipients": false, + "RunProcessStatusTypeSummaryConsumer": false + }, + "IsHistoric": true + }, + "BatchIngestionReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.BatchIngestion" + }, + "DocumentIngestorReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.Indexing" + }, + "DocumentIngestorProcessingReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.Processing" + }, + "DocumentIngestorCompletionReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.Completion" + }, + "IngestionFolderCleanUpReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.IngestionFolderCleanUp" + }, + "PdfPartitionerEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.PdfPartitioner" + }, + "PdfPartitionerCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.PdfPartitioner.Completion" + }, + "UploadCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.UploadCompletion" + }, + "MemberDocumentNotifierEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.MemberDocumentNotifier" + }, + "MemberNotificationCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.MemberNotificationCompletion" + }, + "GatherMemberNotificationInfoReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.GatherMemberNotificationInfo" + }, + "BatchUpdateMemberNotificationDataEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.BatchUpdateMemberNotificationData" + } +} diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-batchupdatemembernotif/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-batchupdatemembernotif/kustomization.yaml new file mode 100644 index 0000000..1559870 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-batchupdatemembernotif/kustomization.yaml @@ -0,0 +1,40 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +namePrefix: historical-batchupdatemembernotif- + +configMapGenerator: + - name: document-ingestor-appsettings + files: + - appsettings/appsettings.json +generatorOptions: + disableNameSuffixHash: true + +patches: + - target: + kind: Deployment + path: set_appsettings_deployment.yaml + +replacements: + - source: + kind: Deployment + fieldPath: metadata.name + targets: + - select: + kind: Deployment + fieldPaths: + - spec.selector.matchLabels.app + - spec.template.metadata.labels.app + - spec.template.spec.containers.*.name + + - select: + kind: Service + fieldPaths: + - spec.selector.app + + - select: + kind: VirtualService + fieldPaths: + - spec.http.*.route.*.destination.host + - spec.http.*.name + diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-batchupdatemembernotif/set_appsettings_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-batchupdatemembernotif/set_appsettings_deployment.yaml new file mode 100644 index 0000000..655b6b1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-batchupdatemembernotif/set_appsettings_deployment.yaml @@ -0,0 +1,12 @@ +- op: add + path: /spec/template/spec/volumes/- + value: + name: volume-appsettings + configMap: + name: document-ingestor-appsettings + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: volume-appsettings + mountPath: /app/config/workload-appsettings diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-completion/appsettings/appsettings.json b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-completion/appsettings/appsettings.json new file mode 100644 index 0000000..3562702 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-completion/appsettings/appsettings.json @@ -0,0 +1,57 @@ +{ + "Primary": { + "FeatureFlags": { + "RunBatchIngestionConsumer": false, + "RunIngestorIndexConsumer": false, + "RunIngestorProcessingConsumer": false, + "RunIngestorCompletionConsumer": true, + "RunIngestionFolderCleanUpConsumer": false, + "RunPdfPartitionerConsumer": false, + "RunPdfPartitionerCompletionConsumer": false, + "RunUploadCompletionConsumer": false, + "RunMemberDocumentNotifierConsumer": false, + "RunMemberNotificationCompletionConsumer": false, + "RunGatherMemberNotificationInfoConsumer": false, + "RunBatchUpdateMemberNotificationDataConsumer": false, + "RestrictNotificationRecipients": false, + "RunProcessStatusTypeSummaryConsumer": false + }, + "IsHistoric": true + }, + "BatchIngestionReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.BatchIngestion" + }, + "DocumentIngestorReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.Indexing" + }, + "DocumentIngestorProcessingReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.Processing" + }, + "DocumentIngestorCompletionReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.Completion" + }, + "IngestionFolderCleanUpReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.IngestionFolderCleanUp" + }, + "PdfPartitionerEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.PdfPartitioner" + }, + "PdfPartitionerCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.PdfPartitioner.Completion" + }, + "UploadCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.UploadCompletion" + }, + "MemberDocumentNotifierEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.MemberDocumentNotifier" + }, + "MemberNotificationCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.MemberNotificationCompletion" + }, + "GatherMemberNotificationInfoReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.GatherMemberNotificationInfo" + }, + "BatchUpdateMemberNotificationDataEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.BatchUpdateMemberNotificationData" + } +} diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-completion/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-completion/kustomization.yaml new file mode 100644 index 0000000..2716cc2 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-completion/kustomization.yaml @@ -0,0 +1,40 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +namePrefix: historical-completion- + +configMapGenerator: + - name: document-ingestor-appsettings + files: + - appsettings/appsettings.json +generatorOptions: + disableNameSuffixHash: true + +patches: + - target: + kind: Deployment + path: set_appsettings_deployment.yaml + +replacements: + - source: + kind: Deployment + fieldPath: metadata.name + targets: + - select: + kind: Deployment + fieldPaths: + - spec.selector.matchLabels.app + - spec.template.metadata.labels.app + - spec.template.spec.containers.*.name + + - select: + kind: Service + fieldPaths: + - spec.selector.app + + - select: + kind: VirtualService + fieldPaths: + - spec.http.*.route.*.destination.host + - spec.http.*.name + diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-completion/set_appsettings_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-completion/set_appsettings_deployment.yaml new file mode 100644 index 0000000..655b6b1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-completion/set_appsettings_deployment.yaml @@ -0,0 +1,12 @@ +- op: add + path: /spec/template/spec/volumes/- + value: + name: volume-appsettings + configMap: + name: document-ingestor-appsettings + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: volume-appsettings + mountPath: /app/config/workload-appsettings diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-gathermembernotificationinfo/appsettings/appsettings.json b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-gathermembernotificationinfo/appsettings/appsettings.json new file mode 100644 index 0000000..9c25f0a --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-gathermembernotificationinfo/appsettings/appsettings.json @@ -0,0 +1,57 @@ +{ + "Primary": { + "FeatureFlags": { + "RunBatchIngestionConsumer": false, + "RunIngestorIndexConsumer": false, + "RunIngestorProcessingConsumer": false, + "RunIngestorCompletionConsumer": false, + "RunIngestionFolderCleanUpConsumer": false, + "RunPdfPartitionerConsumer": false, + "RunPdfPartitionerCompletionConsumer": false, + "RunUploadCompletionConsumer": false, + "RunMemberDocumentNotifierConsumer": false, + "RunMemberNotificationCompletionConsumer": false, + "RunGatherMemberNotificationInfoConsumer": true, + "RunBatchUpdateMemberNotificationDataConsumer": false, + "RestrictNotificationRecipients": false, + "RunProcessStatusTypeSummaryConsumer": false + }, + "IsHistoric": true + }, + "BatchIngestionReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.BatchIngestion" + }, + "DocumentIngestorReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.Indexing" + }, + "DocumentIngestorProcessingReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.Processing" + }, + "DocumentIngestorCompletionReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.Completion" + }, + "IngestionFolderCleanUpReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.IngestionFolderCleanUp" + }, + "PdfPartitionerEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.PdfPartitioner" + }, + "PdfPartitionerCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.PdfPartitioner.Completion" + }, + "UploadCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.UploadCompletion" + }, + "MemberDocumentNotifierEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.MemberDocumentNotifier" + }, + "MemberNotificationCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.MemberNotificationCompletion" + }, + "GatherMemberNotificationInfoReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.GatherMemberNotificationInfo" + }, + "BatchUpdateMemberNotificationDataEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.BatchUpdateMemberNotificationData" + } +} diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-gathermembernotificationinfo/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-gathermembernotificationinfo/kustomization.yaml new file mode 100644 index 0000000..2f198b6 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-gathermembernotificationinfo/kustomization.yaml @@ -0,0 +1,44 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +namePrefix: historical-gathermembernotificationinfo- + +configMapGenerator: + - name: document-ingestor-appsettings + files: + - appsettings/appsettings.json +generatorOptions: + disableNameSuffixHash: true + +patches: + - target: + kind: Deployment + path: set_appsettings_deployment.yaml + + - target: + kind: Deployment + path: set_deployment_replicas.yaml + +replacements: + - source: + kind: Deployment + fieldPath: metadata.name + targets: + - select: + kind: Deployment + fieldPaths: + - spec.selector.matchLabels.app + - spec.template.metadata.labels.app + - spec.template.spec.containers.*.name + + - select: + kind: Service + fieldPaths: + - spec.selector.app + + - select: + kind: VirtualService + fieldPaths: + - spec.http.*.route.*.destination.host + - spec.http.*.name + diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-gathermembernotificationinfo/set_appsettings_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-gathermembernotificationinfo/set_appsettings_deployment.yaml new file mode 100644 index 0000000..655b6b1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-gathermembernotificationinfo/set_appsettings_deployment.yaml @@ -0,0 +1,12 @@ +- op: add + path: /spec/template/spec/volumes/- + value: + name: volume-appsettings + configMap: + name: document-ingestor-appsettings + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: volume-appsettings + mountPath: /app/config/workload-appsettings diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-gathermembernotificationinfo/set_deployment_replicas.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-gathermembernotificationinfo/set_deployment_replicas.yaml new file mode 100644 index 0000000..8aa1c55 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-gathermembernotificationinfo/set_deployment_replicas.yaml @@ -0,0 +1,3 @@ +- op: replace + path: /spec/replicas + value: 2 \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-indexer/appsettings/appsettings.json b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-indexer/appsettings/appsettings.json new file mode 100644 index 0000000..b38cce5 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-indexer/appsettings/appsettings.json @@ -0,0 +1,57 @@ +{ + "Primary": { + "FeatureFlags": { + "RunBatchIngestionConsumer": false, + "RunIngestorIndexConsumer": true, + "RunIngestorProcessingConsumer": false, + "RunIngestorCompletionConsumer": false, + "RunIngestionFolderCleanUpConsumer": false, + "RunPdfPartitionerConsumer": false, + "RunPdfPartitionerCompletionConsumer": false, + "RunUploadCompletionConsumer": false, + "RunMemberDocumentNotifierConsumer": false, + "RunMemberNotificationCompletionConsumer": false, + "RestrictNotificationRecipients": true, + "RunGatherMemberNotificationInfoConsumer": false, + "RunBatchUpdateMemberNotificationDataConsumer": false, + "RunProcessStatusTypeSummaryConsumer": false + }, + "IsHistoric": true + }, + "BatchIngestionReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.BatchIngestion" + }, + "DocumentIngestorReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.Indexing" + }, + "DocumentIngestorProcessingReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.Processing" + }, + "DocumentIngestorCompletionReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.Completion" + }, + "IngestionFolderCleanUpReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.IngestionFolderCleanUp" + }, + "PdfPartitionerEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.PdfPartitioner" + }, + "PdfPartitionerCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.PdfPartitioner.Completion" + }, + "UploadCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.UploadCompletion" + }, + "MemberDocumentNotifierEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.MemberDocumentNotifier" + }, + "MemberNotificationCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.MemberNotificationCompletion" + }, + "GatherMemberNotificationInfoReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.GatherMemberNotificationInfo" + }, + "BatchUpdateMemberNotificationDataEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.BatchUpdateMemberNotificationData" + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-indexer/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-indexer/kustomization.yaml new file mode 100644 index 0000000..631589d --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-indexer/kustomization.yaml @@ -0,0 +1,40 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +namePrefix: historical-indexer- + +configMapGenerator: + - name: document-ingestor-appsettings + files: + - appsettings/appsettings.json +generatorOptions: + disableNameSuffixHash: true + +patches: + - target: + kind: Deployment + path: set_appsettings_deployment.yaml + +replacements: + - source: + kind: Deployment + fieldPath: metadata.name + targets: + - select: + kind: Deployment + fieldPaths: + - spec.selector.matchLabels.app + - spec.template.metadata.labels.app + - spec.template.spec.containers.*.name + + - select: + kind: Service + fieldPaths: + - spec.selector.app + + - select: + kind: VirtualService + fieldPaths: + - spec.http.*.route.*.destination.host + - spec.http.*.name + diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-indexer/set_appsettings_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-indexer/set_appsettings_deployment.yaml new file mode 100644 index 0000000..655b6b1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-indexer/set_appsettings_deployment.yaml @@ -0,0 +1,12 @@ +- op: add + path: /spec/template/spec/volumes/- + value: + name: volume-appsettings + configMap: + name: document-ingestor-appsettings + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: volume-appsettings + mountPath: /app/config/workload-appsettings diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-processor/appsettings/appsettings.json b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-processor/appsettings/appsettings.json new file mode 100644 index 0000000..73ce871 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-processor/appsettings/appsettings.json @@ -0,0 +1,57 @@ +{ + "Primary": { + "FeatureFlags": { + "RunBatchIngestionConsumer": false, + "RunIngestorIndexConsumer": false, + "RunIngestorProcessingConsumer": true, + "RunIngestorCompletionConsumer": false, + "RunIngestionFolderCleanUpConsumer": false, + "RunPdfPartitionerConsumer": false, + "RunPdfPartitionerCompletionConsumer": false, + "RunUploadCompletionConsumer": false, + "RunMemberDocumentNotifierConsumer": false, + "RunMemberNotificationCompletionConsumer": false, + "RunGatherMemberNotificationInfoConsumer": false, + "RunBatchUpdateMemberNotificationDataConsumer": false, + "RestrictNotificationRecipients": true, + "RunProcessStatusTypeSummaryConsumer": false + }, + "IsHistoric": true + }, + "BatchIngestionReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.BatchIngestion" + }, + "DocumentIngestorReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.Indexing" + }, + "DocumentIngestorProcessingReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.Processing" + }, + "DocumentIngestorCompletionReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.Completion" + }, + "IngestionFolderCleanUpReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.IngestionFolderCleanUp" + }, + "PdfPartitionerEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.PdfPartitioner" + }, + "PdfPartitionerCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.PdfPartitioner.Completion" + }, + "UploadCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.UploadCompletion" + }, + "MemberDocumentNotifierEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.MemberDocumentNotifier" + }, + "MemberNotificationCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.MemberNotificationCompletion" + }, + "GatherMemberNotificationInfoReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.GatherMemberNotificationInfo" + }, + "BatchUpdateMemberNotificationDataEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.BatchUpdateMemberNotificationData" + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-processor/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-processor/kustomization.yaml new file mode 100644 index 0000000..e6e0e05 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-processor/kustomization.yaml @@ -0,0 +1,44 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +namePrefix: historical-processor- + +configMapGenerator: + - name: document-ingestor-appsettings + files: + - appsettings/appsettings.json +generatorOptions: + disableNameSuffixHash: true + +patches: + - target: + kind: Deployment + path: set_appsettings_deployment.yaml + + - target: + kind: Deployment + path: set_deployment_replicas.yaml + +replacements: + - source: + kind: Deployment + fieldPath: metadata.name + targets: + - select: + kind: Deployment + fieldPaths: + - spec.selector.matchLabels.app + - spec.template.metadata.labels.app + - spec.template.spec.containers.*.name + + - select: + kind: Service + fieldPaths: + - spec.selector.app + + - select: + kind: VirtualService + fieldPaths: + - spec.http.*.route.*.destination.host + - spec.http.*.name + diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-processor/set_appsettings_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-processor/set_appsettings_deployment.yaml new file mode 100644 index 0000000..655b6b1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-processor/set_appsettings_deployment.yaml @@ -0,0 +1,12 @@ +- op: add + path: /spec/template/spec/volumes/- + value: + name: volume-appsettings + configMap: + name: document-ingestor-appsettings + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: volume-appsettings + mountPath: /app/config/workload-appsettings diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-processor/set_deployment_replicas.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-processor/set_deployment_replicas.yaml new file mode 100644 index 0000000..754401c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-processor/set_deployment_replicas.yaml @@ -0,0 +1,3 @@ +- op: replace + path: /spec/replicas + value: 6 \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-uploadcompletion/appsettings/appsettings.json b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-uploadcompletion/appsettings/appsettings.json new file mode 100644 index 0000000..93021d0 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-uploadcompletion/appsettings/appsettings.json @@ -0,0 +1,57 @@ +{ + "Primary": { + "FeatureFlags": { + "RunBatchIngestionConsumer": false, + "RunIngestorIndexConsumer": false, + "RunIngestorProcessingConsumer": false, + "RunIngestorCompletionConsumer": false, + "RunIngestionFolderCleanUpConsumer": false, + "RunPdfPartitionerConsumer": false, + "RunPdfPartitionerCompletionConsumer": false, + "RunUploadCompletionConsumer": true, + "RunMemberDocumentNotifierConsumer": false, + "RunMemberNotificationCompletionConsumer": false, + "RunGatherMemberNotificationInfoConsumer": false, + "RunBatchUpdateMemberNotificationDataConsumer": false, + "RestrictNotificationRecipients": false, + "RunProcessStatusTypeSummaryConsumer": false + }, + "IsHistoric": true + }, + "BatchIngestionReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.BatchIngestion" + }, + "DocumentIngestorReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.Indexing" + }, + "DocumentIngestorProcessingReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.Processing" + }, + "DocumentIngestorCompletionReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.Completion" + }, + "IngestionFolderCleanUpReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.IngestionFolderCleanUp" + }, + "PdfPartitionerEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.PdfPartitioner" + }, + "PdfPartitionerCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.PdfPartitioner.Completion" + }, + "UploadCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.UploadCompletion" + }, + "MemberDocumentNotifierEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.MemberDocumentNotifier" + }, + "MemberNotificationCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.MemberNotificationCompletion" + }, + "GatherMemberNotificationInfoReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.GatherMemberNotificationInfo" + }, + "BatchUpdateMemberNotificationDataEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.BatchUpdateMemberNotificationData" + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-uploadcompletion/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-uploadcompletion/kustomization.yaml new file mode 100644 index 0000000..6060b86 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-uploadcompletion/kustomization.yaml @@ -0,0 +1,40 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +namePrefix: historical-uploadcompletion- + +configMapGenerator: + - name: document-ingestor-appsettings + files: + - appsettings/appsettings.json +generatorOptions: + disableNameSuffixHash: true + +patches: + - target: + kind: Deployment + path: set_appsettings_deployment.yaml + +replacements: + - source: + kind: Deployment + fieldPath: metadata.name + targets: + - select: + kind: Deployment + fieldPaths: + - spec.selector.matchLabels.app + - spec.template.metadata.labels.app + - spec.template.spec.containers.*.name + + - select: + kind: Service + fieldPaths: + - spec.selector.app + + - select: + kind: VirtualService + fieldPaths: + - spec.http.*.route.*.destination.host + - spec.http.*.name + diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-uploadcompletion/set_appsettings_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-uploadcompletion/set_appsettings_deployment.yaml new file mode 100644 index 0000000..655b6b1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical-uploadcompletion/set_appsettings_deployment.yaml @@ -0,0 +1,12 @@ +- op: add + path: /spec/template/spec/volumes/- + value: + name: volume-appsettings + configMap: + name: document-ingestor-appsettings + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: volume-appsettings + mountPath: /app/config/workload-appsettings diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical/appsettings/appsettings.json b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical/appsettings/appsettings.json new file mode 100644 index 0000000..6189f49 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical/appsettings/appsettings.json @@ -0,0 +1,57 @@ +{ + "Primary": { + "FeatureFlags": { + "RunBatchIngestionConsumer": true, + "RunIngestorIndexConsumer": false, + "RunIngestorProcessingConsumer": true, + "RunIngestorCompletionConsumer": false, + "RunIngestionFolderCleanUpConsumer": true, + "RunPdfPartitionerConsumer": true, + "RunPdfPartitionerCompletionConsumer": true, + "RunUploadCompletionConsumer": false, + "RunMemberDocumentNotifierConsumer": false, + "RunMemberNotificationCompletionConsumer": false, + "RestrictNotificationRecipients": true, + "RunGatherMemberNotificationInfoConsumer": false, + "RunBatchUpdateMemberNotificationDataConsumer": false, + "RunProcessStatusTypeSummaryConsumer": false + }, + "IsHistoric": true + }, + "BatchIngestionReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.BatchIngestion" + }, + "DocumentIngestorReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.Indexing" + }, + "DocumentIngestorProcessingReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.Processing" + }, + "DocumentIngestorCompletionReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.Completion" + }, + "IngestionFolderCleanUpReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.IngestionFolderCleanUp" + }, + "PdfPartitionerEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.PdfPartitioner" + }, + "PdfPartitionerCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.PdfPartitioner.Completion" + }, + "UploadCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.UploadCompletion" + }, + "MemberDocumentNotifierEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.MemberDocumentNotifier" + }, + "MemberNotificationCompletionEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.MemberNotificationCompletion" + }, + "GatherMemberNotificationInfoReceiveEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.GatherMemberNotificationInfo" + }, + "BatchUpdateMemberNotificationDataEndpoint": { + "ReceiveEndpoint": "LCU.DocumentIngestor.Historical.BatchUpdateMemberNotificationData" + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical/kustomization.yaml new file mode 100644 index 0000000..9593cc7 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical/kustomization.yaml @@ -0,0 +1,40 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +namePrefix: historical- + +configMapGenerator: + - name: document-ingestor-appsettings + files: + - appsettings/appsettings.json +generatorOptions: + disableNameSuffixHash: true + +patches: + - target: + kind: Deployment + path: set_appsettings_deployment.yaml + +replacements: + - source: + kind: Deployment + fieldPath: metadata.name + targets: + - select: + kind: Deployment + fieldPaths: + - spec.selector.matchLabels.app + - spec.template.metadata.labels.app + - spec.template.spec.containers.*.name + + - select: + kind: Service + fieldPaths: + - spec.selector.app + + - select: + kind: VirtualService + fieldPaths: + - spec.http.*.route.*.destination.host + - spec.http.*.name + diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical/set_appsettings_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical/set_appsettings_deployment.yaml new file mode 100644 index 0000000..655b6b1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/historical/set_appsettings_deployment.yaml @@ -0,0 +1,12 @@ +- op: add + path: /spec/template/spec/volumes/- + value: + name: volume-appsettings + configMap: + name: document-ingestor-appsettings + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: volume-appsettings + mountPath: /app/config/workload-appsettings diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-batchupdatemembernotif/appsettings/appsettings.json b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-batchupdatemembernotif/appsettings/appsettings.json new file mode 100644 index 0000000..a39f5ef --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-batchupdatemembernotif/appsettings/appsettings.json @@ -0,0 +1,21 @@ +{ + "Primary": { + "FeatureFlags": { + "RunBatchIngestionConsumer": false, + "RunIngestorIndexConsumer": false, + "RunIngestorProcessingConsumer": false, + "RunIngestorCompletionConsumer": false, + "RunIngestionFolderCleanUpConsumer": false, + "RunPdfPartitionerConsumer": false, + "RunPdfPartitionerCompletionConsumer": false, + "RunUploadCompletionConsumer": false, + "RunMemberDocumentNotifierConsumer": false, + "RunMemberNotificationCompletionConsumer": false, + "RunGatherMemberNotificationInfoConsumer": false, + "RunBatchUpdateMemberNotificationDataConsumer": true, + "RestrictNotificationRecipients": false, + "RunProcessStatusTypeSummaryConsumer": false + }, + "IsHistoric": false + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-batchupdatemembernotif/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-batchupdatemembernotif/kustomization.yaml new file mode 100644 index 0000000..f87e649 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-batchupdatemembernotif/kustomization.yaml @@ -0,0 +1,40 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +namePrefix: normal-batchupdatemembernotif- + +configMapGenerator: + - name: document-ingestor-appsettings + files: + - appsettings/appsettings.json +generatorOptions: + disableNameSuffixHash: true + +patches: + - target: + kind: Deployment + path: set_appsettings_deployment.yaml + +replacements: + - source: + kind: Deployment + fieldPath: metadata.name + targets: + - select: + kind: Deployment + fieldPaths: + - spec.selector.matchLabels.app + - spec.template.metadata.labels.app + - spec.template.spec.containers.*.name + + - select: + kind: Service + fieldPaths: + - spec.selector.app + + - select: + kind: VirtualService + fieldPaths: + - spec.http.*.route.*.destination.host + - spec.http.*.name + diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-batchupdatemembernotif/set_appsettings_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-batchupdatemembernotif/set_appsettings_deployment.yaml new file mode 100644 index 0000000..655b6b1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-batchupdatemembernotif/set_appsettings_deployment.yaml @@ -0,0 +1,12 @@ +- op: add + path: /spec/template/spec/volumes/- + value: + name: volume-appsettings + configMap: + name: document-ingestor-appsettings + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: volume-appsettings + mountPath: /app/config/workload-appsettings diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-completion/appsettings/appsettings.json b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-completion/appsettings/appsettings.json new file mode 100644 index 0000000..b600064 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-completion/appsettings/appsettings.json @@ -0,0 +1,21 @@ +{ + "Primary": { + "FeatureFlags": { + "RunBatchIngestionConsumer": false, + "RunIngestorIndexConsumer": false, + "RunIngestorProcessingConsumer": false, + "RunIngestorCompletionConsumer": true, + "RunIngestionFolderCleanUpConsumer": false, + "RunPdfPartitionerConsumer": false, + "RunPdfPartitionerCompletionConsumer": false, + "RunUploadCompletionConsumer": false, + "RunMemberDocumentNotifierConsumer": false, + "RunMemberNotificationCompletionConsumer": false, + "RunGatherMemberNotificationInfoConsumer": false, + "RunBatchUpdateMemberNotificationDataConsumer": false, + "RestrictNotificationRecipients": false, + "RunProcessStatusTypeSummaryConsumer": false + }, + "IsHistoric": false + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-completion/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-completion/kustomization.yaml new file mode 100644 index 0000000..6ed9d64 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-completion/kustomization.yaml @@ -0,0 +1,40 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +namePrefix: normal-completion- + +configMapGenerator: + - name: document-ingestor-appsettings + files: + - appsettings/appsettings.json +generatorOptions: + disableNameSuffixHash: true + +patches: + - target: + kind: Deployment + path: set_appsettings_deployment.yaml + +replacements: + - source: + kind: Deployment + fieldPath: metadata.name + targets: + - select: + kind: Deployment + fieldPaths: + - spec.selector.matchLabels.app + - spec.template.metadata.labels.app + - spec.template.spec.containers.*.name + + - select: + kind: Service + fieldPaths: + - spec.selector.app + + - select: + kind: VirtualService + fieldPaths: + - spec.http.*.route.*.destination.host + - spec.http.*.name + diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-completion/set_appsettings_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-completion/set_appsettings_deployment.yaml new file mode 100644 index 0000000..655b6b1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-completion/set_appsettings_deployment.yaml @@ -0,0 +1,12 @@ +- op: add + path: /spec/template/spec/volumes/- + value: + name: volume-appsettings + configMap: + name: document-ingestor-appsettings + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: volume-appsettings + mountPath: /app/config/workload-appsettings diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-gathermembernotificationinfo/appsettings/appsettings.json b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-gathermembernotificationinfo/appsettings/appsettings.json new file mode 100644 index 0000000..264855e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-gathermembernotificationinfo/appsettings/appsettings.json @@ -0,0 +1,21 @@ +{ + "Primary": { + "FeatureFlags": { + "RunBatchIngestionConsumer": false, + "RunIngestorIndexConsumer": false, + "RunIngestorProcessingConsumer": false, + "RunIngestorCompletionConsumer": false, + "RunIngestionFolderCleanUpConsumer": false, + "RunPdfPartitionerConsumer": false, + "RunPdfPartitionerCompletionConsumer": false, + "RunUploadCompletionConsumer": false, + "RunMemberDocumentNotifierConsumer": false, + "RunMemberNotificationCompletionConsumer": false, + "RunGatherMemberNotificationInfoConsumer": true, + "RunBatchUpdateMemberNotificationDataConsumer": false, + "RestrictNotificationRecipients": false, + "RunProcessStatusTypeSummaryConsumer": false + }, + "IsHistoric": false + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-gathermembernotificationinfo/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-gathermembernotificationinfo/kustomization.yaml new file mode 100644 index 0000000..b143590 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-gathermembernotificationinfo/kustomization.yaml @@ -0,0 +1,44 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +namePrefix: normal-gathermembernotificationinfo- + +configMapGenerator: + - name: document-ingestor-appsettings + files: + - appsettings/appsettings.json +generatorOptions: + disableNameSuffixHash: true + +patches: + - target: + kind: Deployment + path: set_appsettings_deployment.yaml + + - target: + kind: Deployment + path: set_deployment_replicas.yaml + +replacements: + - source: + kind: Deployment + fieldPath: metadata.name + targets: + - select: + kind: Deployment + fieldPaths: + - spec.selector.matchLabels.app + - spec.template.metadata.labels.app + - spec.template.spec.containers.*.name + + - select: + kind: Service + fieldPaths: + - spec.selector.app + + - select: + kind: VirtualService + fieldPaths: + - spec.http.*.route.*.destination.host + - spec.http.*.name + diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-gathermembernotificationinfo/set_appsettings_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-gathermembernotificationinfo/set_appsettings_deployment.yaml new file mode 100644 index 0000000..655b6b1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-gathermembernotificationinfo/set_appsettings_deployment.yaml @@ -0,0 +1,12 @@ +- op: add + path: /spec/template/spec/volumes/- + value: + name: volume-appsettings + configMap: + name: document-ingestor-appsettings + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: volume-appsettings + mountPath: /app/config/workload-appsettings diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-gathermembernotificationinfo/set_deployment_replicas.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-gathermembernotificationinfo/set_deployment_replicas.yaml new file mode 100644 index 0000000..8aa1c55 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-gathermembernotificationinfo/set_deployment_replicas.yaml @@ -0,0 +1,3 @@ +- op: replace + path: /spec/replicas + value: 2 \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-indexer/appsettings/appsettings.json b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-indexer/appsettings/appsettings.json new file mode 100644 index 0000000..778972b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-indexer/appsettings/appsettings.json @@ -0,0 +1,21 @@ +{ + "Primary": { + "FeatureFlags": { + "RunBatchIngestionConsumer": false, + "RunIngestorIndexConsumer": true, + "RunIngestorProcessingConsumer": false, + "RunIngestorCompletionConsumer": false, + "RunIngestionFolderCleanUpConsumer": false, + "RunPdfPartitionerConsumer": false, + "RunPdfPartitionerCompletionConsumer": false, + "RunUploadCompletionConsumer": false, + "RunMemberDocumentNotifierConsumer": false, + "RunMemberNotificationCompletionConsumer": false, + "RunGatherMemberNotificationInfoConsumer": false, + "RunBatchUpdateMemberNotificationDataConsumer": false, + "RestrictNotificationRecipients": true, + "RunProcessStatusTypeSummaryConsumer": false + }, + "IsHistoric": false + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-indexer/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-indexer/kustomization.yaml new file mode 100644 index 0000000..2bf6372 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-indexer/kustomization.yaml @@ -0,0 +1,40 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +namePrefix: normal-indexer- + +configMapGenerator: + - name: document-ingestor-appsettings + files: + - appsettings/appsettings.json +generatorOptions: + disableNameSuffixHash: true + +patches: + - target: + kind: Deployment + path: set_appsettings_deployment.yaml + +replacements: + - source: + kind: Deployment + fieldPath: metadata.name + targets: + - select: + kind: Deployment + fieldPaths: + - spec.selector.matchLabels.app + - spec.template.metadata.labels.app + - spec.template.spec.containers.*.name + + - select: + kind: Service + fieldPaths: + - spec.selector.app + + - select: + kind: VirtualService + fieldPaths: + - spec.http.*.route.*.destination.host + - spec.http.*.name + diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-indexer/set_appsettings_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-indexer/set_appsettings_deployment.yaml new file mode 100644 index 0000000..655b6b1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-indexer/set_appsettings_deployment.yaml @@ -0,0 +1,12 @@ +- op: add + path: /spec/template/spec/volumes/- + value: + name: volume-appsettings + configMap: + name: document-ingestor-appsettings + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: volume-appsettings + mountPath: /app/config/workload-appsettings diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-processor/appsettings/appsettings.json b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-processor/appsettings/appsettings.json new file mode 100644 index 0000000..4f93cba --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-processor/appsettings/appsettings.json @@ -0,0 +1,21 @@ +{ + "Primary": { + "FeatureFlags": { + "RunBatchIngestionConsumer": false, + "RunIngestorIndexConsumer": false, + "RunIngestorProcessingConsumer": true, + "RunIngestorCompletionConsumer": false, + "RunIngestionFolderCleanUpConsumer": false, + "RunPdfPartitionerConsumer": false, + "RunPdfPartitionerCompletionConsumer": false, + "RunUploadCompletionConsumer": false, + "RunMemberDocumentNotifierConsumer": false, + "RunMemberNotificationCompletionConsumer": false, + "RunGatherMemberNotificationInfoConsumer": false, + "RunBatchUpdateMemberNotificationDataConsumer": false, + "RestrictNotificationRecipients": true, + "RunProcessStatusTypeSummaryConsumer": false + }, + "IsHistoric": false + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-processor/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-processor/kustomization.yaml new file mode 100644 index 0000000..6b136d9 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-processor/kustomization.yaml @@ -0,0 +1,43 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +namePrefix: normal-processor- + +configMapGenerator: + - name: document-ingestor-appsettings + files: + - appsettings/appsettings.json +generatorOptions: + disableNameSuffixHash: true + +patches: + - target: + kind: Deployment + path: set_appsettings_deployment.yaml + - target: + kind: Deployment + path: set_deployment_replicas.yaml + +replacements: + - source: + kind: Deployment + fieldPath: metadata.name + targets: + - select: + kind: Deployment + fieldPaths: + - spec.selector.matchLabels.app + - spec.template.metadata.labels.app + - spec.template.spec.containers.*.name + + - select: + kind: Service + fieldPaths: + - spec.selector.app + + - select: + kind: VirtualService + fieldPaths: + - spec.http.*.route.*.destination.host + - spec.http.*.name + diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-processor/set_appsettings_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-processor/set_appsettings_deployment.yaml new file mode 100644 index 0000000..655b6b1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-processor/set_appsettings_deployment.yaml @@ -0,0 +1,12 @@ +- op: add + path: /spec/template/spec/volumes/- + value: + name: volume-appsettings + configMap: + name: document-ingestor-appsettings + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: volume-appsettings + mountPath: /app/config/workload-appsettings diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-processor/set_deployment_replicas.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-processor/set_deployment_replicas.yaml new file mode 100644 index 0000000..754401c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-processor/set_deployment_replicas.yaml @@ -0,0 +1,3 @@ +- op: replace + path: /spec/replicas + value: 6 \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-prod/appsettings/appsettings.json b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-prod/appsettings/appsettings.json new file mode 100644 index 0000000..9d69fb3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-prod/appsettings/appsettings.json @@ -0,0 +1,21 @@ +{ + "Primary": { + "FeatureFlags": { + "RunBatchIngestionConsumer": true, + "RunIngestorIndexConsumer": false, + "RunIngestorProcessingConsumer": false, + "RunIngestorCompletionConsumer": false, + "RunIngestionFolderCleanUpConsumer": true, + "RunPdfPartitionerConsumer": true, + "RunPdfPartitionerCompletionConsumer": true, + "RunUploadCompletionConsumer": false, + "RunMemberDocumentNotifierConsumer": true, + "RunMemberNotificationCompletionConsumer": true, + "RunGatherMemberNotificationInfoConsumer": false, + "RunBatchUpdateMemberNotificationDataConsumer": false, + "RestrictNotificationRecipients": false, + "RunProcessStatusTypeSummaryConsumer": true + }, + "IsHistoric": false + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-prod/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-prod/kustomization.yaml new file mode 100644 index 0000000..de06982 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-prod/kustomization.yaml @@ -0,0 +1,40 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +namePrefix: normal- + +configMapGenerator: + - name: document-ingestor-appsettings + files: + - appsettings/appsettings.json +generatorOptions: + disableNameSuffixHash: true + +patches: + - target: + kind: Deployment + path: set_appsettings_deployment.yaml + +replacements: + - source: + kind: Deployment + fieldPath: metadata.name + targets: + - select: + kind: Deployment + fieldPaths: + - spec.selector.matchLabels.app + - spec.template.metadata.labels.app + - spec.template.spec.containers.*.name + + - select: + kind: Service + fieldPaths: + - spec.selector.app + + - select: + kind: VirtualService + fieldPaths: + - spec.http.*.route.*.destination.host + - spec.http.*.name + diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-prod/set_appsettings_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-prod/set_appsettings_deployment.yaml new file mode 100644 index 0000000..655b6b1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-prod/set_appsettings_deployment.yaml @@ -0,0 +1,12 @@ +- op: add + path: /spec/template/spec/volumes/- + value: + name: volume-appsettings + configMap: + name: document-ingestor-appsettings + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: volume-appsettings + mountPath: /app/config/workload-appsettings diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-uploadcompletion/appsettings/appsettings.json b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-uploadcompletion/appsettings/appsettings.json new file mode 100644 index 0000000..ce51bfc --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-uploadcompletion/appsettings/appsettings.json @@ -0,0 +1,21 @@ +{ + "Primary": { + "FeatureFlags": { + "RunBatchIngestionConsumer": false, + "RunIngestorIndexConsumer": false, + "RunIngestorProcessingConsumer": false, + "RunIngestorCompletionConsumer": false, + "RunIngestionFolderCleanUpConsumer": false, + "RunPdfPartitionerConsumer": false, + "RunPdfPartitionerCompletionConsumer": false, + "RunUploadCompletionConsumer": true, + "RunMemberDocumentNotifierConsumer": false, + "RunMemberNotificationCompletionConsumer": false, + "RunGatherMemberNotificationInfoConsumer": false, + "RunBatchUpdateMemberNotificationDataConsumer": false, + "RestrictNotificationRecipients": false, + "RunProcessStatusTypeSummaryConsumer": false + }, + "IsHistoric": false + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-uploadcompletion/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-uploadcompletion/kustomization.yaml new file mode 100644 index 0000000..95b44ec --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-uploadcompletion/kustomization.yaml @@ -0,0 +1,40 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +namePrefix: normal-uploadcompletion- + +configMapGenerator: + - name: document-ingestor-appsettings + files: + - appsettings/appsettings.json +generatorOptions: + disableNameSuffixHash: true + +patches: + - target: + kind: Deployment + path: set_appsettings_deployment.yaml + +replacements: + - source: + kind: Deployment + fieldPath: metadata.name + targets: + - select: + kind: Deployment + fieldPaths: + - spec.selector.matchLabels.app + - spec.template.metadata.labels.app + - spec.template.spec.containers.*.name + + - select: + kind: Service + fieldPaths: + - spec.selector.app + + - select: + kind: VirtualService + fieldPaths: + - spec.http.*.route.*.destination.host + - spec.http.*.name + diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-uploadcompletion/set_appsettings_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-uploadcompletion/set_appsettings_deployment.yaml new file mode 100644 index 0000000..655b6b1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal-uploadcompletion/set_appsettings_deployment.yaml @@ -0,0 +1,12 @@ +- op: add + path: /spec/template/spec/volumes/- + value: + name: volume-appsettings + configMap: + name: document-ingestor-appsettings + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: volume-appsettings + mountPath: /app/config/workload-appsettings diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal/appsettings/appsettings.json b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal/appsettings/appsettings.json new file mode 100644 index 0000000..6e3bd80 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal/appsettings/appsettings.json @@ -0,0 +1,21 @@ +{ + "Primary": { + "FeatureFlags": { + "RunBatchIngestionConsumer": true, + "RunIngestorIndexConsumer": false, + "RunIngestorProcessingConsumer": false, + "RunIngestorCompletionConsumer": false, + "RunIngestionFolderCleanUpConsumer": true, + "RunPdfPartitionerConsumer": true, + "RunPdfPartitionerCompletionConsumer": true, + "RunUploadCompletionConsumer": false, + "RunMemberDocumentNotifierConsumer": true, + "RunMemberNotificationCompletionConsumer": true, + "RunGatherMemberNotificationInfoConsumer": false, + "RunBatchUpdateMemberNotificationDataConsumer": false, + "RestrictNotificationRecipients": true, + "RunProcessStatusTypeSummaryConsumer": true + }, + "IsHistoric": false + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal/kustomization.yaml new file mode 100644 index 0000000..de06982 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal/kustomization.yaml @@ -0,0 +1,40 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +namePrefix: normal- + +configMapGenerator: + - name: document-ingestor-appsettings + files: + - appsettings/appsettings.json +generatorOptions: + disableNameSuffixHash: true + +patches: + - target: + kind: Deployment + path: set_appsettings_deployment.yaml + +replacements: + - source: + kind: Deployment + fieldPath: metadata.name + targets: + - select: + kind: Deployment + fieldPaths: + - spec.selector.matchLabels.app + - spec.template.metadata.labels.app + - spec.template.spec.containers.*.name + + - select: + kind: Service + fieldPaths: + - spec.selector.app + + - select: + kind: VirtualService + fieldPaths: + - spec.http.*.route.*.destination.host + - spec.http.*.name + diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal/set_appsettings_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal/set_appsettings_deployment.yaml new file mode 100644 index 0000000..655b6b1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/components/workloads/normal/set_appsettings_deployment.yaml @@ -0,0 +1,12 @@ +- op: add + path: /spec/template/spec/volumes/- + value: + name: volume-appsettings + configMap: + name: document-ingestor-appsettings + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: volume-appsettings + mountPath: /app/config/workload-appsettings diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/appsettings/appsettings.json b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/appsettings/appsettings.json new file mode 100644 index 0000000..356ef66 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/appsettings/appsettings.json @@ -0,0 +1,68 @@ +{ + "Primary": { + "SeqUrl": "https://seq.lcu-internal.com", + "CorsAllowedOrigins": [ + "http://lcu-internal.com", + "https://lcu-internal.com", + "https://api.lcu-internal.com" + ] + }, + "ApiHealthCheckConfiguration": { + "VaultStatusConfiguration": { + "RunVaultStatusCheck": true, + "EnvironmentFromConfigmap": "PROD" + } + }, + "AzureAd": { + "ClientId": "2daa775f-3ad6-43e1-9d12-c4708f51d1cb" + }, + "Security": { + "ITRole": "Doc_Mgr_IT_Admin" + }, + "Swagger": { + "OAuthScope": "api://2daa775f-3ad6-43e1-9d12-c4708f51d1cb/user.groups" + }, + "ConnectionConfiguration":{ + "HostUrl": "rabbitmq.lcu-internal.com" + }, + "DocumentTypeUploaderConfiguration": { + "Url": "https://prd-document-type-uploader-api.apps.azure.lcu-internal.com" + }, + "FileOperationsApiConfiguration": { + "Url": "https://fileoperationsapi.lcu-internal.com" + }, + "CoreApiWrapperConfiguration": { + "Url": "https://prd-core-api-wrapper-api.apps.azure.lcu-internal.com" + }, + "NotificationApiConfiguration": { + "Url": "https://prd-notifications-api.apps.azure.lcu-internal.com" + }, + "MemberPreferencesApiConfiguration": { + "Url": "https://prd-member-preferences-api.apps.azure.lcu-internal.com" + }, + "DocumentTypeRetrieverConfiguration": { + "Url": "https://prd-document-type-retriever-api.apps.azure.lcu-internal.com", + "Username": "ven.alkami@landmarkcu.onmicrosoft.com", + "Password": "8ae8796a-b7e6-4c47-881f-e98eacf5e15f" + }, + "DispatcherRequestBuilderConfiguration": { + "Url": "https://prd-dispatcher-api.apps.azure.lcu-internal.com/api/Ingestion" + }, + "DigitalBankingConfiguration": { + "MobileBankingBaseUrl": "https://redirect-api.landmarkcu.com/index.html", + }, + "DispatcherJobCreationConfiguration": { + "JobTags": [ + { + "jobTagId": 0, + "jobId": 0, + "tagId": 17 + }, + { + "jobTagId": 0, + "jobId": 0, + "tagId": 18 + } + ] + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/component/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/component/kustomization.yaml new file mode 100644 index 0000000..7f05869 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/component/kustomization.yaml @@ -0,0 +1,10 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +patches: + - target: + kind: Deployment + path: set_appsettings_deployment.yaml + - target: + kind: SecretProviderClass + path: set_secrets_provider_class.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/component/set_appsettings_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/component/set_appsettings_deployment.yaml new file mode 100644 index 0000000..335b8be --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/component/set_appsettings_deployment.yaml @@ -0,0 +1,5 @@ +- op: add + path: /spec/template/spec/containers/0/env/- + value: + name: ASPNETCORE_ENVIRONMENT + value: "Production" \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/component/set_secrets_provider_class.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/component/set_secrets_provider_class.yaml new file mode 100644 index 0000000..816f14c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/component/set_secrets_provider_class.yaml @@ -0,0 +1,7 @@ +- op: add + path: /spec/parameters/userAssignedIdentityID + value: 9eaefc49-e5d3-48d4-a2b9-b42cf2d8ca03 + +- op: add + path: /spec/parameters/keyvaultName + value: kv-lz-apps-prod-uscz diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-batchupdatemembernotif/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-batchupdatemembernotif/kustomization.yaml new file mode 100644 index 0000000..d799e49 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-batchupdatemembernotif/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/historical + - ../../../components/workloads/historical-batchupdatemembernotif + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-batchupdatemembernotif/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-batchupdatemembernotif/set_virtual_service.yaml new file mode 100644 index 0000000..c4bfee3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-batchupdatemembernotif/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: prd-document-ingestor-historical-batchupdatemembernotif.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-completion/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-completion/kustomization.yaml new file mode 100644 index 0000000..d8e03f2 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-completion/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/historical + - ../../../components/workloads/historical-completion + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-completion/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-completion/set_virtual_service.yaml new file mode 100644 index 0000000..e19976e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-completion/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: prd-document-ingestor-historical-completion.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-gathermembernotificationinfo/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-gathermembernotificationinfo/kustomization.yaml new file mode 100644 index 0000000..f5436b5 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-gathermembernotificationinfo/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/historical + - ../../../components/workloads/historical-gathermembernotificationinfo + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-gathermembernotificationinfo/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-gathermembernotificationinfo/set_virtual_service.yaml new file mode 100644 index 0000000..cb26ee7 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-gathermembernotificationinfo/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: prd-document-ingestor-historical-gathermembernotificationinfo.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-indexer/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-indexer/kustomization.yaml new file mode 100644 index 0000000..35f6691 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-indexer/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/historical + - ../../../components/workloads/historical-indexer + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-indexer/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-indexer/set_virtual_service.yaml new file mode 100644 index 0000000..dd2c984 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-indexer/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: prd-document-ingestor-historical-indexer.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-processor/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-processor/kustomization.yaml new file mode 100644 index 0000000..e5e19f4 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-processor/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/historical + - ../../../components/workloads/historical-processor + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-processor/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-processor/set_virtual_service.yaml new file mode 100644 index 0000000..6162110 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-processor/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: prd-document-ingestor-historical-processor.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-uploadcompletion/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-uploadcompletion/kustomization.yaml new file mode 100644 index 0000000..6e029dd --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-uploadcompletion/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/historical + - ../../../components/workloads/historical-uploadcompletion + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-uploadcompletion/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-uploadcompletion/set_virtual_service.yaml new file mode 100644 index 0000000..d8f9549 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical-uploadcompletion/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: prd-document-ingestor-historical-uploadcompletion.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical/kustomization.yaml new file mode 100644 index 0000000..c925562 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/historical + - ../../../components/workloads/historical + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical/set_virtual_service.yaml new file mode 100644 index 0000000..360a98f --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/historical/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: prd-document-ingestor-historical-api.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/kustomization.yaml new file mode 100644 index 0000000..62ef109 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/kustomization.yaml @@ -0,0 +1,27 @@ +resources: + - normal + - normal-indexer + - normal-processor + - normal-completion + - normal-uploadcompletion + - normal-gathermembernotificationinfo + - normal-batchupdatemembernotif + - historical + - historical-indexer + - historical-processor + - historical-completion + - historical-uploadcompletion + - historical-gathermembernotificationinfo + - historical-batchupdatemembernotif + +configMapGenerator: + - name: document-ingestor-environment-appsettings + files: + - appsettings/appsettings.json +generatorOptions: + disableNameSuffixHash: true + +patches: + - target: + kind: Deployment + path: set_configmap_deployment.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-batchupdatemembernotif/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-batchupdatemembernotif/kustomization.yaml new file mode 100644 index 0000000..91e3d04 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-batchupdatemembernotif/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/normal + - ../../../components/workloads/normal-batchupdatemembernotif + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-batchupdatemembernotif/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-batchupdatemembernotif/set_virtual_service.yaml new file mode 100644 index 0000000..3780fa3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-batchupdatemembernotif/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: prd-document-ingestor-batchupdatemembernotif.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-completion/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-completion/kustomization.yaml new file mode 100644 index 0000000..cbdda77 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-completion/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/normal + - ../../../components/workloads/normal-completion + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-completion/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-completion/set_virtual_service.yaml new file mode 100644 index 0000000..366cc59 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-completion/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: prd-document-ingestor-completion.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-gathermembernotificationinfo/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-gathermembernotificationinfo/kustomization.yaml new file mode 100644 index 0000000..63d0e28 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-gathermembernotificationinfo/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/normal + - ../../../components/workloads/normal-gathermembernotificationinfo + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-gathermembernotificationinfo/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-gathermembernotificationinfo/set_virtual_service.yaml new file mode 100644 index 0000000..ca5da7c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-gathermembernotificationinfo/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: prd-document-ingestor-gathermembernotificationinfo-api.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-indexer/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-indexer/kustomization.yaml new file mode 100644 index 0000000..5994891 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-indexer/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/normal + - ../../../components/workloads/normal-indexer + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-indexer/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-indexer/set_virtual_service.yaml new file mode 100644 index 0000000..b24065e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-indexer/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: prd-document-ingestor-indexer-api.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-processor/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-processor/kustomization.yaml new file mode 100644 index 0000000..45e4bcd --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-processor/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/normal + - ../../../components/workloads/normal-processor + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-processor/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-processor/set_virtual_service.yaml new file mode 100644 index 0000000..ac15781 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-processor/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: prd-document-ingestor-processor-api.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-uploadcompletion/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-uploadcompletion/kustomization.yaml new file mode 100644 index 0000000..1351d08 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-uploadcompletion/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/normal + - ../../../components/workloads/normal-uploadcompletion + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-uploadcompletion/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-uploadcompletion/set_virtual_service.yaml new file mode 100644 index 0000000..e95ce3e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal-uploadcompletion/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: prd-document-ingestor-uploadcompletion.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal/kustomization.yaml new file mode 100644 index 0000000..b74d310 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/normal + - ../../../components/workloads/normal-prod + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal/set_virtual_service.yaml new file mode 100644 index 0000000..8ef883d --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/normal/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: prd-document-ingestor-api.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/set_configmap_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/set_configmap_deployment.yaml new file mode 100644 index 0000000..b3b4de1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/prd/set_configmap_deployment.yaml @@ -0,0 +1,12 @@ +- op: add + path: /spec/template/spec/volumes/- + value: + name: volume-environment-appsettings + configMap: + name: document-ingestor-environment-appsettings + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: volume-environment-appsettings + mountPath: /app/config/environment-appsettings diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/appsettings/appsettings.json b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/appsettings/appsettings.json new file mode 100644 index 0000000..a84d07e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/appsettings/appsettings.json @@ -0,0 +1,68 @@ +{ + "Primary": { + "SeqUrl": "https://qa-seq.lcu-internal.com", + "CorsAllowedOrigins": [ + "http://lcu-internal.com", + "https://lcu-internal.com", + "https://qa-api.lcu-internal.com" + ] + }, + "ApiHealthCheckConfiguration": { + "VaultStatusConfiguration": { + "RunVaultStatusCheck": true, + "EnvironmentFromConfigmap": "QA" + } + }, + "AzureAd": { + "ClientId": "27a3a812-7338-4c55-81ac-33c415e8b401" + }, + "Security": { + "ITRole": "Doc_Mgr_IT_Admin,QA_Testing" + }, + "Swagger": { + "OAuthScope": "api://27a3a812-7338-4c55-81ac-33c415e8b401/user.groups" + }, + "ConnectionConfiguration":{ + "HostUrl": "qa-rabbitmq.lcu-internal.com" + }, + "DocumentTypeUploaderConfiguration": { + "Url": "https://qa-document-type-uploader-api.apps.azure.lcu-internal.com" + }, + "FileOperationsApiConfiguration": { + "Url": "https://qa-fileoperationsapi.lcu-internal.com" + }, + "CoreApiWrapperConfiguration": { + "Url": "https://qa-core-api-wrapper-api.apps.azure.lcu-internal.com" + }, + "NotificationApiConfiguration": { + "Url": "https://qa-notifications-api.apps.azure.lcu-internal.com" + }, + "MemberPreferencesApiConfiguration": { + "Url": "https://qa-member-preferences-api.apps.azure.lcu-internal.com" + }, + "DocumentTypeRetrieverConfiguration": { + "Url": "https://qa-document-type-retriever-api.apps.azure.lcu-internal.com", + "Username": "ven.alkami@landmarkcu.onmicrosoft.com", + "Password": "8ae8796a-b7e6-4c47-881f-e98eacf5e15f" + }, + "DispatcherRequestBuilderConfiguration": { + "Url": "https://qa-dispatcher-api.apps.azure.lcu-internal.com/api/Ingestion" + }, + "DigitalBankingConfiguration": { + "MobileBankingBaseUrl": "https://qa-redirect-api.qa.applications.landmarkcu.com/index.html", + }, + "DispatcherJobCreationConfiguration": { + "JobTags": [ + { + "jobTagId": 0, + "jobId": 0, + "tagId": 16 + }, + { + "jobTagId": 0, + "jobId": 0, + "tagId": 19 + } + ] + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/component/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/component/kustomization.yaml new file mode 100644 index 0000000..7f05869 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/component/kustomization.yaml @@ -0,0 +1,10 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +patches: + - target: + kind: Deployment + path: set_appsettings_deployment.yaml + - target: + kind: SecretProviderClass + path: set_secrets_provider_class.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/component/set_appsettings_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/component/set_appsettings_deployment.yaml new file mode 100644 index 0000000..818dec4 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/component/set_appsettings_deployment.yaml @@ -0,0 +1,5 @@ +- op: add + path: /spec/template/spec/containers/0/env/- + value: + name: ASPNETCORE_ENVIRONMENT + value: Development \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/component/set_secrets_provider_class.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/component/set_secrets_provider_class.yaml new file mode 100644 index 0000000..8719a77 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/component/set_secrets_provider_class.yaml @@ -0,0 +1,7 @@ +- op: add + path: /spec/parameters/userAssignedIdentityID + value: 3286ed9a-f85c-4c50-b742-dbd3c1c3fe1f + +- op: add + path: /spec/parameters/keyvaultName + value: kv-lz-apps-qa-uscz diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-batchupdatemembernotif/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-batchupdatemembernotif/kustomization.yaml new file mode 100644 index 0000000..d799e49 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-batchupdatemembernotif/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/historical + - ../../../components/workloads/historical-batchupdatemembernotif + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-batchupdatemembernotif/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-batchupdatemembernotif/set_virtual_service.yaml new file mode 100644 index 0000000..43913c5 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-batchupdatemembernotif/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: qa-document-ingestor-historical-batchupdatemembernotif.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-completion/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-completion/kustomization.yaml new file mode 100644 index 0000000..d8e03f2 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-completion/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/historical + - ../../../components/workloads/historical-completion + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-completion/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-completion/set_virtual_service.yaml new file mode 100644 index 0000000..dad0dae --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-completion/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: qa-document-ingestor-historical-completion.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-gathermembernotificationinfo/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-gathermembernotificationinfo/kustomization.yaml new file mode 100644 index 0000000..f5436b5 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-gathermembernotificationinfo/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/historical + - ../../../components/workloads/historical-gathermembernotificationinfo + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-gathermembernotificationinfo/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-gathermembernotificationinfo/set_virtual_service.yaml new file mode 100644 index 0000000..bceabc5 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-gathermembernotificationinfo/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: qa-document-ingestor-historical-gathermembernotificationinfo.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-indexer/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-indexer/kustomization.yaml new file mode 100644 index 0000000..35f6691 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-indexer/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/historical + - ../../../components/workloads/historical-indexer + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-indexer/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-indexer/set_virtual_service.yaml new file mode 100644 index 0000000..39461bf --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-indexer/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: qa-document-ingestor-historical-indexer.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-processor/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-processor/kustomization.yaml new file mode 100644 index 0000000..e5e19f4 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-processor/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/historical + - ../../../components/workloads/historical-processor + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-processor/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-processor/set_virtual_service.yaml new file mode 100644 index 0000000..ca81c3c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-processor/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: qa-document-ingestor-historical-processor.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-uploadcompletion/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-uploadcompletion/kustomization.yaml new file mode 100644 index 0000000..6e029dd --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-uploadcompletion/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/historical + - ../../../components/workloads/historical-uploadcompletion + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-uploadcompletion/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-uploadcompletion/set_virtual_service.yaml new file mode 100644 index 0000000..32f48fa --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical-uploadcompletion/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: qa-document-ingestor-historical-uploadcompletion.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical/kustomization.yaml new file mode 100644 index 0000000..c925562 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/historical + - ../../../components/workloads/historical + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical/set_virtual_service.yaml new file mode 100644 index 0000000..a13bf31 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/historical/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: qa-document-ingestor-historical-api.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/kustomization.yaml new file mode 100644 index 0000000..62ef109 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/kustomization.yaml @@ -0,0 +1,27 @@ +resources: + - normal + - normal-indexer + - normal-processor + - normal-completion + - normal-uploadcompletion + - normal-gathermembernotificationinfo + - normal-batchupdatemembernotif + - historical + - historical-indexer + - historical-processor + - historical-completion + - historical-uploadcompletion + - historical-gathermembernotificationinfo + - historical-batchupdatemembernotif + +configMapGenerator: + - name: document-ingestor-environment-appsettings + files: + - appsettings/appsettings.json +generatorOptions: + disableNameSuffixHash: true + +patches: + - target: + kind: Deployment + path: set_configmap_deployment.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-batchupdatemembernotif/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-batchupdatemembernotif/kustomization.yaml new file mode 100644 index 0000000..91e3d04 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-batchupdatemembernotif/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/normal + - ../../../components/workloads/normal-batchupdatemembernotif + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-batchupdatemembernotif/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-batchupdatemembernotif/set_virtual_service.yaml new file mode 100644 index 0000000..e4faa2e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-batchupdatemembernotif/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: qa-document-ingestor-batchupdatemembernotif.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-completion/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-completion/kustomization.yaml new file mode 100644 index 0000000..cbdda77 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-completion/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/normal + - ../../../components/workloads/normal-completion + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-completion/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-completion/set_virtual_service.yaml new file mode 100644 index 0000000..3125a48 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-completion/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: qa-document-ingestor-completion.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-gathermembernotificationinfo/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-gathermembernotificationinfo/kustomization.yaml new file mode 100644 index 0000000..63d0e28 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-gathermembernotificationinfo/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/normal + - ../../../components/workloads/normal-gathermembernotificationinfo + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-gathermembernotificationinfo/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-gathermembernotificationinfo/set_virtual_service.yaml new file mode 100644 index 0000000..afdcbf7 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-gathermembernotificationinfo/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: qa-document-ingestor-gathermembernotificationinfo.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-indexer/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-indexer/kustomization.yaml new file mode 100644 index 0000000..5994891 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-indexer/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/normal + - ../../../components/workloads/normal-indexer + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-indexer/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-indexer/set_virtual_service.yaml new file mode 100644 index 0000000..cfef938 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-indexer/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: qa-document-ingestor-indexer-api.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-processor/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-processor/kustomization.yaml new file mode 100644 index 0000000..45e4bcd --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-processor/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/normal + - ../../../components/workloads/normal-processor + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-processor/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-processor/set_virtual_service.yaml new file mode 100644 index 0000000..2b33fe7 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-processor/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: qa-document-ingestor-processor-api.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-uploadcompletion/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-uploadcompletion/kustomization.yaml new file mode 100644 index 0000000..1351d08 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-uploadcompletion/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/normal + - ../../../components/workloads/normal-uploadcompletion + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-uploadcompletion/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-uploadcompletion/set_virtual_service.yaml new file mode 100644 index 0000000..78dfd77 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal-uploadcompletion/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: qa-document-ingestor-uploadcompletion.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal/kustomization.yaml new file mode 100644 index 0000000..a1e6b06 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/normal + - ../../../components/workloads/normal + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal/set_virtual_service.yaml new file mode 100644 index 0000000..07793b1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/normal/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: qa-document-ingestor-api.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/set_configmap_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/set_configmap_deployment.yaml new file mode 100644 index 0000000..b3b4de1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/qa/set_configmap_deployment.yaml @@ -0,0 +1,12 @@ +- op: add + path: /spec/template/spec/volumes/- + value: + name: volume-environment-appsettings + configMap: + name: document-ingestor-environment-appsettings + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: volume-environment-appsettings + mountPath: /app/config/environment-appsettings diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/appsettings/appsettings.json b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/appsettings/appsettings.json new file mode 100644 index 0000000..3a9e21d --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/appsettings/appsettings.json @@ -0,0 +1,68 @@ +{ + "Primary": { + "SeqUrl": "https://uat-seq.lcu-internal.com", + "CorsAllowedOrigins": [ + "http://lcu-internal.com", + "https://lcu-internal.com", + "https://uat-api.lcu-internal.com" + ] + }, + "ApiHealthCheckConfiguration": { + "VaultStatusConfiguration": { + "RunVaultStatusCheck": true, + "EnvironmentFromConfigmap": "UAT" + } + }, + "AzureAd": { + "ClientId": "54798032-d762-4dc6-9ec3-dc4612b59007" + }, + "Security": { + "ITRole": "Doc_Mgr_IT_Admin" + }, + "Swagger": { + "OAuthScope": "api://54798032-d762-4dc6-9ec3-dc4612b59007/user.groups" + }, + "ConnectionConfiguration":{ + "HostUrl": "uat-rabbitmq.lcu-internal.com" + }, + "DocumentTypeUploaderConfiguration": { + "Url": "https://uat-document-type-uploader-api.apps.azure.lcu-internal.com" + }, + "FileOperationsApiConfiguration": { + "Url": "https://uat-fileoperationsapi.lcu-internal.com" + }, + "CoreApiWrapperConfiguration": { + "Url": "https://uat-core-api-wrapper-api.apps.azure.lcu-internal.com" + }, + "NotificationApiConfiguration": { + "Url": "https://uat-notifications-api.apps.azure.lcu-internal.com" + }, + "MemberPreferencesApiConfiguration": { + "Url": "https://uat-member-preferences-api.apps.azure.lcu-internal.com" + }, + "DocumentTypeRetrieverConfiguration": { + "Url": "https://uat-document-type-retriever-api.apps.azure.lcu-internal.com", + "Username": "ven.alkami@landmarkcu.onmicrosoft.com", + "Password": "8ae8796a-b7e6-4c47-881f-e98eacf5e15f" + }, + "DispatcherRequestBuilderConfiguration": { + "Url": "https://uat-dispatcher-api.apps.azure.lcu-internal.com/api/Ingestion" + }, + "DigitalBankingConfiguration": { + "MobileBankingBaseUrl": "https://uat-redirect-api.landmarkcu.com/index.html", + }, + "DispatcherJobCreationConfiguration": { + "JobTags": [ + { + "jobTagId": 0, + "jobId": 0, + "tagId": 11 + }, + { + "jobTagId": 0, + "jobId": 0, + "tagId": 12 + } + ] + } +} \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/component/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/component/kustomization.yaml new file mode 100644 index 0000000..7f05869 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/component/kustomization.yaml @@ -0,0 +1,10 @@ +apiVersion: kustomize.config.k8s.io/v1alpha1 +kind: Component + +patches: + - target: + kind: Deployment + path: set_appsettings_deployment.yaml + - target: + kind: SecretProviderClass + path: set_secrets_provider_class.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/component/set_appsettings_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/component/set_appsettings_deployment.yaml new file mode 100644 index 0000000..4fd0533 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/component/set_appsettings_deployment.yaml @@ -0,0 +1,5 @@ +- op: add + path: /spec/template/spec/containers/0/env/- + value: + name: ASPNETCORE_ENVIRONMENT + value: "Staging" \ No newline at end of file diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/component/set_secrets_provider_class.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/component/set_secrets_provider_class.yaml new file mode 100644 index 0000000..efe4103 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/component/set_secrets_provider_class.yaml @@ -0,0 +1,7 @@ +- op: add + path: /spec/parameters/userAssignedIdentityID + value: 64ba01ed-1ecc-4c9b-b56e-8d618f2b81ce + +- op: add + path: /spec/parameters/keyvaultName + value: kv-lz-apps-uat-uscz diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-batchupdatemembernotif/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-batchupdatemembernotif/kustomization.yaml new file mode 100644 index 0000000..d799e49 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-batchupdatemembernotif/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/historical + - ../../../components/workloads/historical-batchupdatemembernotif + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-batchupdatemembernotif/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-batchupdatemembernotif/set_virtual_service.yaml new file mode 100644 index 0000000..e0d0f6e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-batchupdatemembernotif/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: uat-document-ingestor-historical-batchupdatemembernotif.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-completion/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-completion/kustomization.yaml new file mode 100644 index 0000000..d8e03f2 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-completion/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/historical + - ../../../components/workloads/historical-completion + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-completion/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-completion/set_virtual_service.yaml new file mode 100644 index 0000000..8f3e2f7 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-completion/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: uat-document-ingestor-historical-completion.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-gathermembernotificationinfo/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-gathermembernotificationinfo/kustomization.yaml new file mode 100644 index 0000000..f5436b5 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-gathermembernotificationinfo/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/historical + - ../../../components/workloads/historical-gathermembernotificationinfo + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-gathermembernotificationinfo/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-gathermembernotificationinfo/set_virtual_service.yaml new file mode 100644 index 0000000..de9f26e --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-gathermembernotificationinfo/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: uat-document-ingestor-historical-gathermembernotificationinfo.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-indexer/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-indexer/kustomization.yaml new file mode 100644 index 0000000..35f6691 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-indexer/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/historical + - ../../../components/workloads/historical-indexer + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-indexer/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-indexer/set_virtual_service.yaml new file mode 100644 index 0000000..673b0c7 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-indexer/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: uat-document-ingestor-historical-indexer.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-processor/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-processor/kustomization.yaml new file mode 100644 index 0000000..e5e19f4 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-processor/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/historical + - ../../../components/workloads/historical-processor + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-processor/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-processor/set_virtual_service.yaml new file mode 100644 index 0000000..75fc04a --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-processor/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: uat-document-ingestor-historical-processor.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-uploadcompletion/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-uploadcompletion/kustomization.yaml new file mode 100644 index 0000000..6e029dd --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-uploadcompletion/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/historical + - ../../../components/workloads/historical-uploadcompletion + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-uploadcompletion/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-uploadcompletion/set_virtual_service.yaml new file mode 100644 index 0000000..050621b --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical-uploadcompletion/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: uat-document-ingestor-historical-uploadcompletion.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical/kustomization.yaml new file mode 100644 index 0000000..c925562 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/historical + - ../../../components/workloads/historical + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical/set_virtual_service.yaml new file mode 100644 index 0000000..dac6876 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/historical/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: uat-document-ingestor-historical-api.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/kustomization.yaml new file mode 100644 index 0000000..62ef109 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/kustomization.yaml @@ -0,0 +1,27 @@ +resources: + - normal + - normal-indexer + - normal-processor + - normal-completion + - normal-uploadcompletion + - normal-gathermembernotificationinfo + - normal-batchupdatemembernotif + - historical + - historical-indexer + - historical-processor + - historical-completion + - historical-uploadcompletion + - historical-gathermembernotificationinfo + - historical-batchupdatemembernotif + +configMapGenerator: + - name: document-ingestor-environment-appsettings + files: + - appsettings/appsettings.json +generatorOptions: + disableNameSuffixHash: true + +patches: + - target: + kind: Deployment + path: set_configmap_deployment.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-batchupdatemembernotif/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-batchupdatemembernotif/kustomization.yaml new file mode 100644 index 0000000..91e3d04 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-batchupdatemembernotif/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/normal + - ../../../components/workloads/normal-batchupdatemembernotif + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-batchupdatemembernotif/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-batchupdatemembernotif/set_virtual_service.yaml new file mode 100644 index 0000000..567e649 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-batchupdatemembernotif/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: uat-document-ingestor-batchupdatemembernotif.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-completion/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-completion/kustomization.yaml new file mode 100644 index 0000000..cbdda77 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-completion/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/normal + - ../../../components/workloads/normal-completion + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-completion/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-completion/set_virtual_service.yaml new file mode 100644 index 0000000..6ff5581 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-completion/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: uat-document-ingestor-completion.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-gathermembernotificationinfo/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-gathermembernotificationinfo/kustomization.yaml new file mode 100644 index 0000000..63d0e28 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-gathermembernotificationinfo/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/normal + - ../../../components/workloads/normal-gathermembernotificationinfo + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-gathermembernotificationinfo/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-gathermembernotificationinfo/set_virtual_service.yaml new file mode 100644 index 0000000..fbc259f --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-gathermembernotificationinfo/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: uat-document-ingestor-gathermembernotificationinfo.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-indexer/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-indexer/kustomization.yaml new file mode 100644 index 0000000..5994891 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-indexer/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/normal + - ../../../components/workloads/normal-indexer + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-indexer/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-indexer/set_virtual_service.yaml new file mode 100644 index 0000000..ebf802c --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-indexer/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: uat-document-ingestor-indexer-api.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-processor/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-processor/kustomization.yaml new file mode 100644 index 0000000..45e4bcd --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-processor/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/normal + - ../../../components/workloads/normal-processor + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-processor/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-processor/set_virtual_service.yaml new file mode 100644 index 0000000..10ba1a3 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-processor/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: uat-document-ingestor-processor-api.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-uploadcompletion/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-uploadcompletion/kustomization.yaml new file mode 100644 index 0000000..1351d08 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-uploadcompletion/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/normal + - ../../../components/workloads/normal-uploadcompletion + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-uploadcompletion/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-uploadcompletion/set_virtual_service.yaml new file mode 100644 index 0000000..b3a182a --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal-uploadcompletion/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: uat-document-ingestor-uploadcompletion.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal/kustomization.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal/kustomization.yaml new file mode 100644 index 0000000..a1e6b06 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal/kustomization.yaml @@ -0,0 +1,12 @@ +resources: + - ../../../base + +components: + - ../component + - ../../../components/keyvaults/normal + - ../../../components/workloads/normal + +patches: + - target: + kind: VirtualService + path: set_virtual_service.yaml diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal/set_virtual_service.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal/set_virtual_service.yaml new file mode 100644 index 0000000..e5c217f --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/normal/set_virtual_service.yaml @@ -0,0 +1,3 @@ +- op: add + path: /spec/hosts/- + value: uat-document-ingestor-api.apps.azure.lcu-internal.com diff --git a/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/set_configmap_deployment.yaml b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/set_configmap_deployment.yaml new file mode 100644 index 0000000..b3b4de1 --- /dev/null +++ b/LCU.API.Internal.DocumentIngestor/kustomize/overlays/uat/set_configmap_deployment.yaml @@ -0,0 +1,12 @@ +- op: add + path: /spec/template/spec/volumes/- + value: + name: volume-environment-appsettings + configMap: + name: document-ingestor-environment-appsettings + +- op: add + path: /spec/template/spec/containers/0/volumeMounts/- + value: + name: volume-environment-appsettings + mountPath: /app/config/environment-appsettings