diff --git a/FIleProcessor.Models/FileDetails.cs b/FIleProcessor.Models/FileDetails.cs index a089afd..43b87f7 100644 --- a/FIleProcessor.Models/FileDetails.cs +++ b/FIleProcessor.Models/FileDetails.cs @@ -1,4 +1,4 @@ -namespace FIleProcessor.Models +namespace FileProcessor.Models { using System; using System.Collections.Generic; diff --git a/FIleProcessor.Models/FileImportLog.cs b/FIleProcessor.Models/FileImportLog.cs index 525ab30..c5c4d5c 100644 --- a/FIleProcessor.Models/FileImportLog.cs +++ b/FIleProcessor.Models/FileImportLog.cs @@ -1,4 +1,4 @@ -namespace FIleProcessor.Models +namespace FileProcessor.Models { using System; using System.Collections.Generic; diff --git a/FIleProcessor.Models/FileLine.cs b/FIleProcessor.Models/FileLine.cs index 53d3514..29a0d81 100644 --- a/FIleProcessor.Models/FileLine.cs +++ b/FIleProcessor.Models/FileLine.cs @@ -1,4 +1,4 @@ -namespace FIleProcessor.Models +namespace FileProcessor.Models { using System; diff --git a/FIleProcessor.Models/FileProfile.cs b/FIleProcessor.Models/FileProfile.cs index 05a35bb..f75194e 100644 --- a/FIleProcessor.Models/FileProfile.cs +++ b/FIleProcessor.Models/FileProfile.cs @@ -1,4 +1,4 @@ -namespace FIleProcessor.Models +namespace FileProcessor.Models { using System; diff --git a/FIleProcessor.Models/ImportLogFile.cs b/FIleProcessor.Models/ImportLogFile.cs index 2a9858a..299236a 100644 --- a/FIleProcessor.Models/ImportLogFile.cs +++ b/FIleProcessor.Models/ImportLogFile.cs @@ -1,4 +1,4 @@ -namespace FIleProcessor.Models +namespace FileProcessor.Models { using System; diff --git a/FIleProcessor.Models/ProcessingResult.cs b/FIleProcessor.Models/ProcessingResult.cs index 6fd52d6..9f6e553 100644 --- a/FIleProcessor.Models/ProcessingResult.cs +++ b/FIleProcessor.Models/ProcessingResult.cs @@ -1,4 +1,4 @@ -namespace FIleProcessor.Models +namespace FileProcessor.Models { /// /// diff --git a/FIleProcessor.Models/ProcessingSummary.cs b/FIleProcessor.Models/ProcessingSummary.cs index 19f7890..e817963 100644 --- a/FIleProcessor.Models/ProcessingSummary.cs +++ b/FIleProcessor.Models/ProcessingSummary.cs @@ -1,4 +1,4 @@ -namespace FIleProcessor.Models +namespace FileProcessor.Models { using System; diff --git a/FileProcessor.BusinessLogic.Tests/DummyFileProcessorDomainService.cs b/FileProcessor.BusinessLogic.Tests/DummyFileProcessorDomainService.cs index e350589..30b752f 100644 --- a/FileProcessor.BusinessLogic.Tests/DummyFileProcessorDomainService.cs +++ b/FileProcessor.BusinessLogic.Tests/DummyFileProcessorDomainService.cs @@ -1,4 +1,7 @@ -namespace FileProcessor.BusinessLogic.Tests; +using FileProcessor.DataTransferObjects; +using SimpleResults; + +namespace FileProcessor.BusinessLogic.Tests; using System; using System.Threading; @@ -6,18 +9,15 @@ using Requests; using Services; -public class DummyFileProcessorDomainService : IFileProcessorDomainService -{ - public async Task UploadFile(UploadFileRequest request, - CancellationToken cancellationToken) { - return Guid.NewGuid(); - } +public class DummyFileProcessorDomainService : IFileProcessorDomainService { + + public async Task> UploadFile(FileCommands.UploadFileCommand command, + CancellationToken cancellationToken) => + Result.Success(Guid.NewGuid()); + + public async Task ProcessUploadedFile(FileCommands.ProcessUploadedFileCommand command, + CancellationToken cancellationToken) => Result.Success(); - public async Task ProcessUploadedFile(ProcessUploadedFileRequest request, - CancellationToken cancellationToken) { - } - - public async Task ProcessTransactionForFileLine(ProcessTransactionForFileLineRequest request, - CancellationToken cancellationToken) { - } + public async Task ProcessTransactionForFileLine(FileCommands.ProcessTransactionForFileLineCommand command, + CancellationToken cancellationToken) => Result.Success(); } \ No newline at end of file diff --git a/FileProcessor.BusinessLogic.Tests/FileProcessingManagerTests.cs b/FileProcessor.BusinessLogic.Tests/FileProcessingManagerTests.cs index c7c9af8..a00845d 100644 --- a/FileProcessor.BusinessLogic.Tests/FileProcessingManagerTests.cs +++ b/FileProcessor.BusinessLogic.Tests/FileProcessingManagerTests.cs @@ -3,6 +3,8 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using FileProcessor.Models; +using SimpleResults; namespace FileProcessor.BusinessLogic.Tests { @@ -11,7 +13,7 @@ namespace FileProcessor.BusinessLogic.Tests using EstateManagement.Database.Contexts; using EstateManagement.Database.Entities; using FileAggregate; - using FIleProcessor.Models; + using FileProcessor.Models; using Managers; using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Diagnostics; @@ -23,8 +25,8 @@ namespace FileProcessor.BusinessLogic.Tests using Shouldly; using Testing; using Xunit; - using FileImportLog = FIleProcessor.Models.FileImportLog; - using FileLine = FIleProcessor.Models.FileLine; + using FileImportLog = FileProcessor.Models.FileImportLog; + using FileLine = FileProcessor.Models.FileLine; public class FileProcessingManagerTests { @@ -40,7 +42,8 @@ public async Task FileProcessingManager_GetAllFileProfiles_AllFileProfilesReturn var allFileProfiles = await manager.GetAllFileProfiles(CancellationToken.None); allFileProfiles.ShouldNotBeNull(); - allFileProfiles.ShouldNotBeEmpty(); + allFileProfiles.IsSuccess.ShouldBeTrue(); + allFileProfiles.Data.ShouldNotBeEmpty(); } [Fact] @@ -55,7 +58,8 @@ public async Task FileProcessingManager_GetFileProfile_FIleProfileReturned() var fileProfile = await manager.GetFileProfile(TestData.SafaricomFileProfileId, CancellationToken.None); fileProfile.ShouldNotBeNull(); - fileProfile.FileProfileId.ShouldBe(TestData.SafaricomFileProfileId); + fileProfile.IsSuccess.ShouldBeTrue(); + fileProfile.Data.FileProfileId.ShouldBe(TestData.SafaricomFileProfileId); } [Fact] @@ -161,15 +165,16 @@ public async Task FileProcessingManager_GetFile_FileReturned() Mock> fileAggregateRepository = new Mock>(); - fileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetFileAggregateWithLines); + fileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetFileAggregateWithLines())); FileProcessorManager manager = new FileProcessorManager(fileProfiles, contextFactory.Object, modelFactory, fileAggregateRepository.Object); - var fileDetails = await manager.GetFile(TestData.FileId, TestData.EstateId, CancellationToken.None); + Result fileDetails = await manager.GetFile(TestData.FileId, TestData.EstateId, CancellationToken.None); + fileDetails.IsSuccess.ShouldBeTrue(); this.VerifyFile(TestData.GetFileAggregateWithLines(), fileDetails); - fileDetails.MerchantName.ShouldBeNull(); - fileDetails.UserEmailAddress.ShouldBeNull(); - fileDetails.FileProfileName.ShouldBeNull(); + fileDetails.Data.MerchantName.ShouldBeNull(); + fileDetails.Data.UserEmailAddress.ShouldBeNull(); + fileDetails.Data.FileProfileName.ShouldBeNull(); } [Fact] @@ -191,13 +196,14 @@ public async Task FileProcessingManager_GetFile_FileReturnedWithMerchantName() Mock> fileAggregateRepository = new Mock>(); - fileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetFileAggregateWithLines); + fileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetFileAggregateWithLines())); FileProcessorManager manager = new FileProcessorManager(fileProfiles, contextFactory.Object, modelFactory, fileAggregateRepository.Object); var fileDetails = await manager.GetFile(TestData.FileId, TestData.EstateId, CancellationToken.None); + fileDetails.IsSuccess.ShouldBeTrue(); this.VerifyFile(TestData.GetFileAggregateWithLines(), fileDetails); - fileDetails.MerchantName.ShouldBe(TestData.MerchantName); + fileDetails.Data.MerchantName.ShouldBe(TestData.MerchantName); } [Fact] @@ -218,13 +224,13 @@ public async Task FileProcessingManager_GetFile_FileReturnedWithUserEmailAddress Mock> fileAggregateRepository = new Mock>(); - fileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetFileAggregateWithLines); + fileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetFileAggregateWithLines())); FileProcessorManager manager = new FileProcessorManager(fileProfiles, contextFactory.Object, modelFactory, fileAggregateRepository.Object); var fileDetails = await manager.GetFile(TestData.FileId, TestData.EstateId, CancellationToken.None); - + fileDetails.IsSuccess.ShouldBeTrue(); this.VerifyFile(TestData.GetFileAggregateWithLines(), fileDetails); - fileDetails.UserEmailAddress.ShouldBe(TestData.UserEmailAddress); + fileDetails.Data.UserEmailAddress.ShouldBe(TestData.UserEmailAddress); } [Fact] @@ -254,13 +260,13 @@ public async Task FileProcessingManager_GetFile_FileReturnedWithFileProfileName( Mock> fileAggregateRepository = new Mock>(); - fileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetFileAggregateWithLines); + fileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetFileAggregateWithLines())); FileProcessorManager manager = new FileProcessorManager(fileProfiles, contextFactory.Object, modelFactory, fileAggregateRepository.Object); var fileDetails = await manager.GetFile(TestData.FileId, TestData.EstateId, CancellationToken.None); - + fileDetails.IsSuccess.ShouldBeTrue(); this.VerifyFile(TestData.GetFileAggregateWithLines(), fileDetails); - fileDetails.FileProfileName.ShouldBe(TestData.SafaricomProfileName); + fileDetails.Data.FileProfileName.ShouldBe(TestData.SafaricomProfileName); } [Fact] @@ -274,39 +280,38 @@ public async Task FileProcessingManager_GetFile_FileNotFound_ErrorThrown() Mock> fileAggregateRepository = new Mock>(); - fileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEmptyFileAggregate); + fileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetEmptyFileAggregate())); FileProcessorManager manager = new FileProcessorManager(fileProfiles, contextFactory.Object, modelFactory, fileAggregateRepository.Object); - Should.Throw(async () => - { - await manager.GetFile(TestData.FileId, TestData.EstateId, CancellationToken.None); - }); + var result = await manager.GetFile(TestData.FileId, TestData.EstateId, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.NotFound); } - private void VerifyFile(FileAggregate source, FileDetails fileDetails) + private void VerifyFile(FileAggregate source, Result fileDetails) { var fileModel = source.GetFile(); - fileDetails.FileId.ShouldBe(fileModel.FileId); - fileDetails.FileImportLogId.ShouldBe(fileModel.FileImportLogId); - fileDetails.FileLocation.ShouldBe(fileModel.FileLocation); - fileDetails.FileProfileId.ShouldBe(fileModel.FileProfileId); - fileDetails.MerchantId.ShouldBe(fileModel.MerchantId); - fileDetails.ProcessingCompleted.ShouldBe(fileModel.ProcessingCompleted); - fileDetails.UserId.ShouldBe(fileModel.UserId); - fileDetails.EstateId.ShouldBe(fileModel.EstateId); - - fileDetails.ProcessingSummary.ShouldNotBeNull(); - fileDetails.ProcessingSummary.FailedLines.ShouldBe(fileModel.ProcessingSummary.FailedLines); - fileDetails.ProcessingSummary.IgnoredLines.ShouldBe(fileModel.ProcessingSummary.IgnoredLines); - fileDetails.ProcessingSummary.NotProcessedLines.ShouldBe(fileModel.ProcessingSummary.NotProcessedLines); - fileDetails.ProcessingSummary.SuccessfullyProcessedLines.ShouldBe(fileModel.ProcessingSummary.SuccessfullyProcessedLines); - fileDetails.ProcessingSummary.TotalLines.ShouldBe(fileModel.ProcessingSummary.TotalLines); + fileDetails.Data.FileId.ShouldBe(fileModel.FileId); + fileDetails.Data.FileImportLogId.ShouldBe(fileModel.FileImportLogId); + fileDetails.Data.FileLocation.ShouldBe(fileModel.FileLocation); + fileDetails.Data.FileProfileId.ShouldBe(fileModel.FileProfileId); + fileDetails.Data.MerchantId.ShouldBe(fileModel.MerchantId); + fileDetails.Data.ProcessingCompleted.ShouldBe(fileModel.ProcessingCompleted); + fileDetails.Data.UserId.ShouldBe(fileModel.UserId); + fileDetails.Data.EstateId.ShouldBe(fileModel.EstateId); + + fileDetails.Data.ProcessingSummary.ShouldNotBeNull(); + fileDetails.Data.ProcessingSummary.FailedLines.ShouldBe(fileModel.ProcessingSummary.FailedLines); + fileDetails.Data.ProcessingSummary.IgnoredLines.ShouldBe(fileModel.ProcessingSummary.IgnoredLines); + fileDetails.Data.ProcessingSummary.NotProcessedLines.ShouldBe(fileModel.ProcessingSummary.NotProcessedLines); + fileDetails.Data.ProcessingSummary.SuccessfullyProcessedLines.ShouldBe(fileModel.ProcessingSummary.SuccessfullyProcessedLines); + fileDetails.Data.ProcessingSummary.TotalLines.ShouldBe(fileModel.ProcessingSummary.TotalLines); foreach (FileLine fileModelFileLine in fileModel.FileLines) { - FileLine? fileLineToVerify = fileDetails.FileLines.SingleOrDefault(f => f.LineNumber == fileModelFileLine.LineNumber); + FileLine? fileLineToVerify = fileDetails.Data.FileLines.SingleOrDefault(f => f.LineNumber == fileModelFileLine.LineNumber); fileLineToVerify.ShouldNotBeNull(); fileLineToVerify.LineData.ShouldBe(fileModelFileLine.LineData); fileLineToVerify.TransactionId.ShouldBe(fileModelFileLine.TransactionId); @@ -314,25 +319,24 @@ private void VerifyFile(FileAggregate source, FileDetails fileDetails) } } - private void VerifyImportLogs(List source, List importLogs, Guid? merchantId = null) + private void VerifyImportLogs(List source, Result> importLogs, Guid? merchantId = null) { - importLogs.ShouldNotBeNull(); - importLogs.ShouldNotBeEmpty(); - importLogs.Count.ShouldBe(TestData.FileImportLogs.Count); + importLogs.Data.ShouldNotBeNull(); + importLogs.Data.ShouldNotBeEmpty(); + importLogs.Data.Count.ShouldBe(TestData.FileImportLogs.Count); foreach (EstateManagement.Database.Entities.FileImportLog fileImportLog in source) { - var importLog = importLogs.SingleOrDefault(i => i.FileImportLogId == fileImportLog.FileImportLogId); + var importLog = importLogs.Data.SingleOrDefault(i => i.FileImportLogId == fileImportLog.FileImportLogId); VerifyImportLog(fileImportLog, importLog, merchantId); } } - private void VerifyImportLog(EstateManagement.Database.Entities.FileImportLog source, FIleProcessor.Models.FileImportLog importLog, Guid? merchantId = null) + private void VerifyImportLog(EstateManagement.Database.Entities.FileImportLog source, Result importLog, Guid? merchantId = null) { - importLog.ShouldNotBeNull(); - importLog.FileImportLogDateTime.ShouldBe(source.ImportLogDateTime); - importLog.Files.Count.ShouldBe(importLog.Files.Count); - - List filesToVerify = importLog.Files; + importLog.Data.ShouldNotBeNull(); + importLog.Data.FileImportLogDateTime.ShouldBe(source.ImportLogDateTime); + + List filesToVerify = importLog.Data.Files; if (merchantId.HasValue) { filesToVerify = filesToVerify.Where(f => f.MerchantId == merchantId.Value).ToList(); @@ -340,7 +344,7 @@ private void VerifyImportLog(EstateManagement.Database.Entities.FileImportLog so foreach (ImportLogFile importLogFile in filesToVerify) { - var file = importLog.Files.SingleOrDefault(impfile => impfile.FileId == importLogFile.FileId); + var file = importLog.Data.Files.SingleOrDefault(impfile => impfile.FileId == importLogFile.FileId); file.ShouldNotBeNull(); file.MerchantId.ShouldBe(importLogFile.MerchantId); file.FilePath.ShouldBe(importLogFile.FilePath); diff --git a/FileProcessor.BusinessLogic.Tests/FileProcessorDomainServiceTests.cs b/FileProcessor.BusinessLogic.Tests/FileProcessorDomainServiceTests.cs index b94e816..aa28dec 100644 --- a/FileProcessor.BusinessLogic.Tests/FileProcessorDomainServiceTests.cs +++ b/FileProcessor.BusinessLogic.Tests/FileProcessorDomainServiceTests.cs @@ -1,4 +1,6 @@ -namespace FileProcessor.BusinessLogic.Tests; +using SimpleResults; + +namespace FileProcessor.BusinessLogic.Tests; using System; using System.IO; @@ -85,54 +87,41 @@ public async Task FileRequestHandler_UploadFileRequest_RequestIsHandled() { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileSafaricom); - this.FileImportLogAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEmptyFileImportLogAggregate); - + this.FileImportLogAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetEmptyFileImportLogAggregate())); + this.FileImportLogAggregateRepository.Setup(f => f.SaveChanges(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success()); + this.FileSystem.AddFile(TestData.FilePathWithName, new MockFileData("D,1,1,1")); this.FileSystem.AddDirectory("home/txnproc/bulkfiles/safaricom"); - - UploadFileRequest uploadFileRequest = - new UploadFileRequest(TestData.EstateId, TestData.MerchantId, TestData.UserId, TestData.FilePathWithName, TestData.FileProfileId, TestData.FileUploadedDateTime); - - Should.NotThrow(async () => - { - await this.FileProcessorDomainService.UploadFile(uploadFileRequest, CancellationToken.None); - }); + + Result result = await this.FileProcessorDomainService.UploadFile(TestData.UploadFileCommand, CancellationToken.None); + result.IsSuccess.ShouldBeTrue(); + result.Data.ShouldNotBe(Guid.Empty); } [Fact] - public async Task FileRequestHandler_UploadFileRequest_MerchantIdNotProvided_ErrorThrown() - { - UploadFileRequest uploadFileRequest = - new UploadFileRequest(TestData.EstateId, Guid.Empty, TestData.UserId, TestData.FilePathWithName, TestData.FileProfileId, TestData.FileUploadedDateTime); - - Should.Throw(async () => - { - await this.FileProcessorDomainService.UploadFile(uploadFileRequest, CancellationToken.None); - }); + public async Task FileRequestHandler_UploadFileRequest_MerchantIdNotProvided_ErrorThrown() { + FileCommands.UploadFileCommand command = TestData.UploadFileCommand with { MerchantId = Guid.Empty }; + Result result = await this.FileProcessorDomainService.UploadFile(command, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Fact] public async Task FileRequestHandler_UploadFileRequest_FileProfileIdNotProvided_ErrorThrown() { - UploadFileRequest uploadFileRequest = - new UploadFileRequest(TestData.EstateId, TestData.MerchantId, TestData.UserId, TestData.FilePathWithName, Guid.Empty, TestData.FileUploadedDateTime); - - Should.Throw(async () => - { - await this.FileProcessorDomainService.UploadFile(uploadFileRequest, CancellationToken.None); - }); + FileCommands.UploadFileCommand command = TestData.UploadFileCommand with { FileProfileId = Guid.Empty }; + Result result = await this.FileProcessorDomainService.UploadFile(command, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Fact] public async Task FileRequestHandler_UploadFileRequest_UserIdNotProvided_ErrorThrown() { - UploadFileRequest uploadFileRequest = - new UploadFileRequest(TestData.EstateId, TestData.MerchantId, Guid.Empty, TestData.FilePathWithName, TestData.FileProfileId, TestData.FileUploadedDateTime); - - Should.Throw(async () => - { - await this.FileProcessorDomainService.UploadFile(uploadFileRequest, CancellationToken.None); - }); + FileCommands.UploadFileCommand command = TestData.UploadFileCommand with { UserId = Guid.Empty }; + Result result = await this.FileProcessorDomainService.UploadFile(command, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } [Fact] @@ -140,18 +129,15 @@ public async Task FileRequestHandler_UploadFileRequest_ImportLogAlreadyCreated_R { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileSafaricom); - this.FileImportLogAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetCreatedFileImportLogAggregate); - + this.FileImportLogAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetCreatedFileImportLogAggregate())); + this.FileImportLogAggregateRepository.Setup(f => f.SaveChanges(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success()); + this.FileSystem.AddFile(TestData.FilePathWithName, new MockFileData("D,1,1,1")); this.FileSystem.AddDirectory("home/txnproc/bulkfiles/safaricom"); - - UploadFileRequest uploadFileRequest = - new UploadFileRequest(TestData.EstateId, TestData.MerchantId, TestData.UserId, TestData.FilePathWithName, TestData.FileProfileId, TestData.FileUploadedDateTime); - Should.NotThrow(async () => - { - await this.FileProcessorDomainService.UploadFile(uploadFileRequest, CancellationToken.None); - }); + Result result = await this.FileProcessorDomainService.UploadFile(TestData.UploadFileCommand, CancellationToken.None); + result.IsSuccess.ShouldBeTrue(); + result.Data.ShouldNotBe(Guid.Empty); } [Fact] @@ -159,15 +145,11 @@ public async Task FileRequestHandler_UploadFileRequest_NoFileProfiles_RequestIsH { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileNull); - this.FileImportLogAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetCreatedFileImportLogAggregate); - - UploadFileRequest uploadFileRequest = - new UploadFileRequest(TestData.EstateId, TestData.MerchantId, TestData.UserId, TestData.FilePathWithName, TestData.FileProfileId, TestData.FileUploadedDateTime); + this.FileImportLogAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetCreatedFileImportLogAggregate())); - Should.Throw(async () => - { - await this.FileProcessorDomainService.UploadFile(uploadFileRequest, CancellationToken.None); - }); + Result result = await this.FileProcessorDomainService.UploadFile(TestData.UploadFileCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.NotFound); } [Fact] @@ -175,15 +157,11 @@ public async Task FileRequestHandler_UploadFileRequest_FileNotFound_RequestIsHan { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileSafaricom); - this.FileImportLogAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetCreatedFileImportLogAggregate); - - UploadFileRequest uploadFileRequest = - new UploadFileRequest(TestData.EstateId, TestData.MerchantId, TestData.UserId, TestData.FilePathWithName, TestData.FileProfileId, TestData.FileUploadedDateTime); + this.FileImportLogAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetCreatedFileImportLogAggregate())); - Should.Throw(async () => - { - await this.FileProcessorDomainService.UploadFile(uploadFileRequest, CancellationToken.None); - }); + Result result = await this.FileProcessorDomainService.UploadFile(TestData.UploadFileCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.NotFound); } [Fact] @@ -191,26 +169,25 @@ public async Task FileRequestHandler_UploadFileRequest_DestinationDirectoryNotFo { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileSafaricom); - this.FileImportLogAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetCreatedFileImportLogAggregate); + this.FileImportLogAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetCreatedFileImportLogAggregate())); this.FileSystem.AddFile(TestData.FilePathWithName, new MockFileData("D,1,1,1")); Logger.Initialise(NullLogger.Instance); - UploadFileRequest uploadFileRequest = - new UploadFileRequest(TestData.EstateId, TestData.MerchantId, TestData.UserId, TestData.FilePathWithName, TestData.FileProfileId, TestData.FileUploadedDateTime); - - Should.Throw(async () => - { - await this.FileProcessorDomainService.UploadFile(uploadFileRequest, CancellationToken.None); - }); + Result result = await this.FileProcessorDomainService.UploadFile(TestData.UploadFileCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.NotFound); } - + [Fact] - public void FileRequestHandler_ProcessUploadedFileRequest_RequestIsHandled() + public async Task FileRequestHandler_ProcessUploadedFileRequest_RequestIsHandled() { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileSafaricom); - this.FileAggregateRepository.SetupSequence(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEmptyFileAggregate).ReturnsAsync(TestData.GetCreatedFileAggregate); + this.FileAggregateRepository.SetupSequence(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetEmptyFileAggregate())) + .ReturnsAsync(Result.Success(TestData.GetCreatedFileAggregate())); + this.FileAggregateRepository.Setup(f => f.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); this.FileSystem.AddFile(TestData.FilePathWithName, new MockFileData("D,1,1,1")); @@ -221,22 +198,19 @@ public void FileRequestHandler_ProcessUploadedFileRequest_RequestIsHandled() this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); this.EstateClient.Setup(e => e.GetOperators(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.OperatorList); - - ProcessUploadedFileRequest processUploadedFileRequest = - new ProcessUploadedFileRequest(TestData.EstateId, TestData.MerchantId, TestData.FileImportLogId, TestData.FileId, TestData.UserId, TestData.FilePathWithName, TestData.FileProfileId, TestData.FileUploadedDateTime); - - Should.NotThrow(async () => - { - await this.FileProcessorDomainService.ProcessUploadedFile(processUploadedFileRequest, CancellationToken.None); - }); + + Result result = await this.FileProcessorDomainService.ProcessUploadedFile(TestData.ProcessUploadedFileCommand, CancellationToken.None); + result.IsSuccess.ShouldBeTrue(); } - + [Fact] - public void FileRequestHandler_ProcessUploadedFileRequest_FileNotFound_RequestIsHandled() + public async Task FileRequestHandler_ProcessUploadedFileRequest_FileNotFound_RequestIsHandled() { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileSafaricom); - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetCreatedFileAggregate); + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetCreatedFileAggregate())); + this.FileAggregateRepository.Setup(f => f.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); this.FileSystem.AddDirectory("home/txnproc/bulkfiles/safaricom/inprogress"); this.FileSystem.AddDirectory("home/txnproc/bulkfiles/safaricom/processed"); @@ -246,24 +220,21 @@ public void FileRequestHandler_ProcessUploadedFileRequest_FileNotFound_RequestIs this.EstateClient.Setup(e => e.GetOperators(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.OperatorList); - ProcessUploadedFileRequest processUploadedFileRequest = - new ProcessUploadedFileRequest(TestData.EstateId, TestData.MerchantId, TestData.FileImportLogId, TestData.FileId, TestData.UserId, TestData.FilePathWithName, TestData.FileProfileId, TestData.FileUploadedDateTime); - - Should.Throw(async () => - { - await this.FileProcessorDomainService.ProcessUploadedFile(processUploadedFileRequest, CancellationToken.None); - }); + Result result = await this.FileProcessorDomainService.ProcessUploadedFile(TestData.ProcessUploadedFileCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.NotFound); } - + [Fact] public async Task FileRequestHandler_ProcessUploadedFileRequest_NoFileProfiles_RequestIsHandled() { - this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileNull); + this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(Result.NotFound()); this.FileImportLogAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetEmptyFileImportLogAggregate); - - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetCreatedFileAggregate); + .ReturnsAsync(Result.Success(TestData.GetEmptyFileImportLogAggregate())); + this.FileAggregateRepository.Setup(f => f.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetCreatedFileAggregate())); this.FileSystem.AddFile(TestData.FilePathWithName, new MockFileData("D,1,1,1")); @@ -271,71 +242,62 @@ public async Task FileRequestHandler_ProcessUploadedFileRequest_NoFileProfiles_R this.EstateClient.Setup(e => e.GetOperators(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.OperatorList); - ProcessUploadedFileRequest processUploadedFileRequest = - new ProcessUploadedFileRequest(TestData.EstateId, TestData.MerchantId, TestData.FileImportLogId, TestData.FileId, TestData.UserId, TestData.FilePathWithName, TestData.FileProfileId, TestData.FileUploadedDateTime); - - Should.Throw(async () => - { - await this.FileProcessorDomainService.ProcessUploadedFile(processUploadedFileRequest, CancellationToken.None); - }); + Result result = await this.FileProcessorDomainService.ProcessUploadedFile(TestData.ProcessUploadedFileCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.NotFound); } - + [Fact] public async Task FileRequestHandler_ProcessUploadedFileRequest_OperatorNotFound_RequestIsHandled() { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileSafaricom); this.FileImportLogAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetEmptyFileImportLogAggregate); - - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetCreatedFileAggregate); + .ReturnsAsync(Result.Success(TestData.GetEmptyFileImportLogAggregate())); + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetCreatedFileAggregate())); + this.FileAggregateRepository.Setup(f => f.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); this.FileSystem.AddFile(TestData.FilePathWithName, new MockFileData("D,1,1,1")); this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - this.EstateClient.Setup(e => e.GetOperators(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.EmptyOperatorList); - - ProcessUploadedFileRequest processUploadedFileRequest = - new ProcessUploadedFileRequest(TestData.EstateId, TestData.MerchantId, TestData.FileImportLogId, TestData.FileId, TestData.UserId, TestData.FilePathWithName, TestData.FileProfileId, TestData.FileUploadedDateTime); + this.EstateClient.Setup(e => e.GetOperators(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.NotFound()); - Should.Throw(async () => - { - await this.FileProcessorDomainService.ProcessUploadedFile(processUploadedFileRequest, CancellationToken.None); - }); + Result result = await this.FileProcessorDomainService.ProcessUploadedFile(TestData.ProcessUploadedFileCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.NotFound); } - + [Fact] public async Task FileRequestHandler_ProcessUploadedFileRequest_NullOperatorList_RequestIsHandled() { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileSafaricom); this.FileImportLogAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetEmptyFileImportLogAggregate); + .ReturnsAsync(Result.Success(TestData.GetEmptyFileImportLogAggregate())); - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetCreatedFileAggregate); + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetCreatedFileAggregate())); this.FileSystem.AddFile(TestData.FilePathWithName, new MockFileData("D,1,1,1")); this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); - this.EstateClient.Setup(e => e.GetOperators(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.NullOperatorList); - - ProcessUploadedFileRequest processUploadedFileRequest = - new ProcessUploadedFileRequest(TestData.EstateId, TestData.MerchantId, TestData.FileImportLogId, TestData.FileId, TestData.UserId, TestData.FilePathWithName, TestData.FileProfileId, TestData.FileUploadedDateTime); + this.EstateClient.Setup(e => e.GetOperators(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.NotFound()); - Should.Throw(async () => - { - await this.FileProcessorDomainService.ProcessUploadedFile(processUploadedFileRequest, CancellationToken.None); - }); + Result result = await this.FileProcessorDomainService.ProcessUploadedFile(TestData.ProcessUploadedFileCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.NotFound); } - + [Fact] public async Task FileRequestHandler_ProcessUploadedFileRequest_ProcessedDirectoryNotFound_RequestIsHandled() { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileSafaricom); - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetCreatedFileAggregate); + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetCreatedFileAggregate())); + this.FileAggregateRepository.Setup(f => f.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); this.FileSystem.AddFile(TestData.FilePathWithName, new MockFileData("D,1,1,1")); @@ -345,13 +307,9 @@ public async Task FileRequestHandler_ProcessUploadedFileRequest_ProcessedDirecto this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse); this.EstateClient.Setup(e => e.GetOperators(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.OperatorList); - ProcessUploadedFileRequest processUploadedFileRequest = - new ProcessUploadedFileRequest(TestData.EstateId, TestData.MerchantId, TestData.FileImportLogId, TestData.FileId, TestData.UserId, TestData.FilePathWithName, TestData.FileProfileId, TestData.FileUploadedDateTime); + Result result = await this.FileProcessorDomainService.ProcessUploadedFile(TestData.ProcessUploadedFileCommand, CancellationToken.None); + result.IsSuccess.ShouldBeTrue(); - Should.NotThrow(async () => - { - await this.FileProcessorDomainService.ProcessUploadedFile(processUploadedFileRequest, CancellationToken.None); - }); this.VerifyFileProcessing("home/txnproc/bulkfiles/safaricom/processed"); } @@ -360,7 +318,9 @@ public async Task FileRequestHandler_ProcessUploadedFileRequest_FailedDirectoryN { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileSafaricom); - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetCreatedFileAggregate); + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetCreatedFileAggregate())); + this.FileAggregateRepository.Setup(f => f.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); this.FileSystem.AddFile(TestData.FilePathWithName, new MockFileData("D,1,1,1")); @@ -371,22 +331,20 @@ public async Task FileRequestHandler_ProcessUploadedFileRequest_FailedDirectoryN this.EstateClient.Setup(e => e.GetOperators(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.OperatorList); - ProcessUploadedFileRequest processUploadedFileRequest = - new ProcessUploadedFileRequest(TestData.EstateId, TestData.MerchantId, TestData.FileImportLogId, TestData.FileId, TestData.UserId, TestData.FilePathWithName, TestData.FileProfileId, TestData.FileUploadedDateTime); - - Should.NotThrow(async () => - { - await this.FileProcessorDomainService.ProcessUploadedFile(processUploadedFileRequest, CancellationToken.None); - }); + Result result = await this.FileProcessorDomainService.ProcessUploadedFile(TestData.ProcessUploadedFileCommand, CancellationToken.None); + result.IsSuccess.ShouldBeTrue(); this.VerifyFileProcessing("home/txnproc/bulkfiles/safaricom/processed"); } + [Fact] - public void FileRequestHandler_ProcessUploadedFileRequest_FileIsEmpty_RequestIsHandled() + public async Task FileRequestHandler_ProcessUploadedFileRequest_FileIsEmpty_RequestIsHandled() { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileSafaricom); - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetCreatedFileAggregate); + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetCreatedFileAggregate())); + this.FileAggregateRepository.Setup(f => f.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); this.FileSystem.AddFile(TestData.FilePathWithName, new MockFileData(String.Empty)); @@ -398,28 +356,25 @@ public void FileRequestHandler_ProcessUploadedFileRequest_FileIsEmpty_RequestIsH this.EstateClient.Setup(e => e.GetOperators(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.OperatorList); - ProcessUploadedFileRequest processUploadedFileRequest = - new ProcessUploadedFileRequest(TestData.EstateId, TestData.MerchantId, TestData.FileImportLogId, TestData.FileId, TestData.UserId, TestData.FilePathWithName, TestData.FileProfileId, TestData.FileUploadedDateTime); + Result result = await this.FileProcessorDomainService.ProcessUploadedFile(TestData.ProcessUploadedFileCommand, CancellationToken.None); + result.IsSuccess.ShouldBeTrue(); - Should.NotThrow(async () => - { - await this.FileProcessorDomainService.ProcessUploadedFile(processUploadedFileRequest, CancellationToken.None); - }); - - this.FileAggregateRepository.Verify(f => f.SaveChanges(It.IsAny(), It.IsAny()), Times.Once); + this.FileAggregateRepository.Verify(f => f.SaveChanges(It.IsAny(), It.IsAny()), Times.Exactly(2)); this.VerifyFileProcessing("home/txnproc/bulkfiles/safaricom/processed"); } - + [Theory] [InlineData("Safaricom")] [InlineData("Voucher")] - public void FileRequestHandler_ProcessTransactionForFileLineRequest_RequestIsHandled(String operatorName) + public async Task FileRequestHandler_ProcessTransactionForFileLineRequest_RequestIsHandled(String operatorName) { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetFileProfile(operatorName)); - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetFileAggregateWithLines); - + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetFileAggregateWithLines())); + this.FileAggregateRepository.Setup(f => f.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); + this.TransactionProcessorClient.Setup(t => t.PerformTransaction(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.SerialisedMessageResponseSale); @@ -427,28 +382,26 @@ public void FileRequestHandler_ProcessTransactionForFileLineRequest_RequestIsHan .ReturnsAsync(TestData.GetMerchantResponseWithOperator); this.EstateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantContractsResponse); + .ReturnsAsync(Result.Success(TestData.GetMerchantContractsResponse())); this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse()); this.FileFormatHandler.Setup(f => f.FileLineCanBeIgnored(It.IsAny())).Returns(false); this.FileFormatHandler.Setup(f => f.ParseFileLine(It.IsAny())).Returns(TestData.TransactionMetadata); - ProcessTransactionForFileLineRequest processTransactionForFileLineRequest = - new ProcessTransactionForFileLineRequest(TestData.FileId, TestData.LineNumber, TestData.FileLine); - - Should.NotThrow(async () => - { - await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest, CancellationToken.None); - }); + Result result = await this.FileProcessorDomainService.ProcessTransactionForFileLine(TestData.ProcessTransactionForFileLineCommand, CancellationToken.None); + result.IsSuccess.ShouldBeTrue(); } + [Fact] - public void FileRequestHandler_ProcessTransactionForFileLineRequest_WithOperatorName_RequestIsHandled() + public async Task FileRequestHandler_ProcessTransactionForFileLineRequest_WithOperatorName_RequestIsHandled() { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileVoucher); - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetFileAggregateWithLines); + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetFileAggregateWithLines())); + this.FileAggregateRepository.Setup(f => f.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); this.TransactionProcessorClient.Setup(t => t.PerformTransaction(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.SerialisedMessageResponseSale); @@ -457,112 +410,100 @@ public void FileRequestHandler_ProcessTransactionForFileLineRequest_WithOperator .ReturnsAsync(TestData.GetMerchantResponseWithOperator); this.EstateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantContractsResponse); + .ReturnsAsync(Result.Success(TestData.GetMerchantContractsResponse())); this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse()); this.FileFormatHandler.Setup(f => f.FileLineCanBeIgnored(It.IsAny())).Returns(false); this.FileFormatHandler.Setup(f => f.ParseFileLine(It.IsAny())).Returns(TestData.TransactionMetadataWithOperatorName); - - ProcessTransactionForFileLineRequest processTransactionForFileLineRequest = - new ProcessTransactionForFileLineRequest(TestData.FileId, TestData.LineNumber, TestData.FileLine); - Should.NotThrow(async () => - { - await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest, CancellationToken.None); - }); + Result result = await this.FileProcessorDomainService.ProcessTransactionForFileLine(TestData.ProcessTransactionForFileLineCommand, CancellationToken.None); + result.IsSuccess.ShouldBeTrue(); } + [Fact] - public void FileRequestHandler_ProcessTransactionLineForFileRequest_FileAggregateNotFound_RequestHandled() + public async Task FileRequestHandler_ProcessTransactionLineForFileRequest_FileAggregateNotFound_RequestHandled() { - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetEmptyFileAggregate); + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.NotFound()); - ProcessTransactionForFileLineRequest processTransactionForFileLineRequest = - new ProcessTransactionForFileLineRequest(TestData.FileId, TestData.LineNumber, TestData.FileLine); - - Should.Throw(async () => - { - await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest, CancellationToken.None); - }); + var result = await this.FileProcessorDomainService.ProcessTransactionForFileLine(TestData.ProcessTransactionForFileLineCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.NotFound); } - + [Fact] - public void FileRequestHandler_ProcessTransactionLineForFileRequest_FileAggregateWithNoLines_RequestHandled() + public async Task FileRequestHandler_ProcessTransactionLineForFileRequest_FileAggregateWithNoLines_RequestHandled() { - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetCreatedFileAggregate); - - ProcessTransactionForFileLineRequest processTransactionForFileLineRequest = - new ProcessTransactionForFileLineRequest(TestData.FileId, TestData.LineNumber, TestData.FileLine); + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetCreatedFileAggregate())); - Should.Throw(async () => - { - await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest, CancellationToken.None); - }); + var result = await this.FileProcessorDomainService.ProcessTransactionForFileLine(TestData.ProcessTransactionForFileLineCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Invalid); } - + [Fact] - public void FileRequestHandler_ProcessTransactionLineForFileRequest_LineInRequestNotFoundInFileAggregate_RequestHandled() + public async Task FileRequestHandler_ProcessTransactionLineForFileRequest_LineInRequestNotFoundInFileAggregate_RequestHandled() { - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetFileAggregateWithLines); + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetFileAggregateWithLines())); IConfigurationRoot configurationRoot = new ConfigurationBuilder().AddInMemoryCollection(TestData.DefaultAppSettings).Build(); ConfigurationReader.Initialise(configurationRoot); Logger.Initialise(NullLogger.Instance); - - ProcessTransactionForFileLineRequest processTransactionForFileLineRequest = - new ProcessTransactionForFileLineRequest(TestData.FileId, TestData.NotFoundLineNumber, TestData.FileLine); - Should.Throw(async () => - { - await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest, CancellationToken.None); - }); + var command = TestData.ProcessTransactionForFileLineCommand with { LineNumber = TestData.NotFoundLineNumber }; + var result = await this.FileProcessorDomainService.ProcessTransactionForFileLine(command, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.NotFound); } - + [Fact] - public void FileRequestHandler_ProcessTransactionLineForFileRequest_LineInRequestAlreadyProcessed_RequestHandled() - { - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetFileAggregateWithLinesAlreadyProcessed); - - ProcessTransactionForFileLineRequest processTransactionForFileLineRequest1 = - new ProcessTransactionForFileLineRequest(TestData.FileId, 1, TestData.FileLine1); - ProcessTransactionForFileLineRequest processTransactionForFileLineRequest2 = - new ProcessTransactionForFileLineRequest(TestData.FileId, 1, TestData.FileLine2); - ProcessTransactionForFileLineRequest processTransactionForFileLineRequest3 = - new ProcessTransactionForFileLineRequest(TestData.FileId, 3, TestData.FileLine3); - ProcessTransactionForFileLineRequest processTransactionForFileLineRequest4 = - new ProcessTransactionForFileLineRequest(TestData.FileId, 4, TestData.FileLine4); - - Should.NotThrow(async () => - { - await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest1, CancellationToken.None); - await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest2, CancellationToken.None); - await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest3, CancellationToken.None); - await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest4, CancellationToken.None); - }); - } - + public async Task FileRequestHandler_ProcessTransactionLineForFileRequest_LineInRequestAlreadyProcessed_RequestHandled() + { + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetFileAggregateWithLinesAlreadyProcessed())); + this.FileAggregateRepository.Setup(f => f.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); + FileCommands.ProcessTransactionForFileLineCommand processTransactionForFileLineRequest1 = + new (TestData.FileId, 1, TestData.FileLine1); + FileCommands.ProcessTransactionForFileLineCommand processTransactionForFileLineRequest2 = + new (TestData.FileId, 1, TestData.FileLine2); + FileCommands.ProcessTransactionForFileLineCommand processTransactionForFileLineRequest3 = + new (TestData.FileId, 3, TestData.FileLine3); + FileCommands.ProcessTransactionForFileLineCommand processTransactionForFileLineRequest4 = + new (TestData.FileId, 4, TestData.FileLine4); + + var result1 = await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest1, CancellationToken.None); + var result2 = await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest2, CancellationToken.None); + var result3 = await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest3, CancellationToken.None); + var result4 = + await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest4, + CancellationToken.None); + result1.IsSuccess.ShouldBeTrue(); + result2.IsSuccess.ShouldBeTrue(); + result3.IsSuccess.ShouldBeTrue(); + result4.IsSuccess.ShouldBeTrue(); + } + [Fact] - public void FileRequestHandler_ProcessTransactionForFileLineRequest_FileProfileNotFound_RequestIsHandled() + public async Task FileRequestHandler_ProcessTransactionForFileLineRequest_FileProfileNotFound_RequestIsHandled() { - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetFileAggregateWithLines); - - ProcessTransactionForFileLineRequest processTransactionForFileLineRequest = - new ProcessTransactionForFileLineRequest(TestData.FileId, TestData.LineNumber, TestData.FileLine); - - Should.Throw(async () => - { - await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest, CancellationToken.None); - }); + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetFileAggregateWithLines())); + this.FileProcessorManager.Setup(fpm => fpm.GetFileProfile(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.NotFound()); + var result = await this.FileProcessorDomainService.ProcessTransactionForFileLine( + TestData.ProcessTransactionForFileLineCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.NotFound); } - + [Fact] - public void FileRequestHandler_ProcessTransactionForFileLineRequest_FileLineIgnored_RequestIsHandled() + public async Task FileRequestHandler_ProcessTransactionForFileLineRequest_FileLineIgnored_RequestIsHandled() { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileSafaricom); - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetFileAggregateWithLines); - + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetFileAggregateWithLines())); + this.FileAggregateRepository.Setup(f => f.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); this.TransactionProcessorClient.Setup(t => t.PerformTransaction(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.SerialisedMessageResponseSale); @@ -570,29 +511,24 @@ public void FileRequestHandler_ProcessTransactionForFileLineRequest_FileLineIgno .ReturnsAsync(TestData.GetMerchantResponseWithOperator); this.EstateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantContractsResponse); + .ReturnsAsync(Result.Success(TestData.GetMerchantContractsResponse())); this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse()); this.FileFormatHandler.Setup(f => f.FileLineCanBeIgnored(It.IsAny())).Returns(true); - ProcessTransactionForFileLineRequest processTransactionForFileLineRequest = - new ProcessTransactionForFileLineRequest(TestData.FileId, TestData.LineNumber, TestData.FileLine); - - Should.NotThrow(async () => - { - await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest, CancellationToken.None); - }); + Result result = await this.FileProcessorDomainService.ProcessTransactionForFileLine(TestData.ProcessTransactionForFileLineCommand, CancellationToken.None); + result.IsSuccess.ShouldBeTrue(); this.FileFormatHandler.Verify(f => f.ParseFileLine(It.IsAny()), Times.Never); } - + [Fact] - public void FileRequestHandler_ProcessTransactionForFileLineRequest_EmptyFileLineIgnored_RequestIsHandled() + public async Task FileRequestHandler_ProcessTransactionForFileLineRequest_EmptyFileLineIgnored_RequestIsHandled() { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileSafaricom); - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetFileAggregateWithBlankLine); - + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetFileAggregateWithBlankLine())); + this.TransactionProcessorClient.Setup(t => t.PerformTransaction(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.SerialisedMessageResponseSale); @@ -600,27 +536,21 @@ public void FileRequestHandler_ProcessTransactionForFileLineRequest_EmptyFileLin .ReturnsAsync(TestData.GetMerchantResponseWithOperator); this.EstateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantContractsResponse); + .ReturnsAsync(Result.Success( TestData.GetMerchantContractsResponse())); this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse()); - - ProcessTransactionForFileLineRequest processTransactionForFileLineRequest = - new ProcessTransactionForFileLineRequest(TestData.FileId, TestData.LineNumber, TestData.FileLine); - - Should.NotThrow(async () => - { - await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest, CancellationToken.None); - }); +var result = await this.FileProcessorDomainService.ProcessTransactionForFileLine(TestData.ProcessTransactionForFileLineCommand, CancellationToken.None); this.FileFormatHandler.Verify(f => f.ParseFileLine(It.IsAny()), Times.Never); } [Fact] - public void FileRequestHandler_ProcessTransactionForFileLineRequest_FileParsingFailed_RequestIsHandled() + public async Task FileRequestHandler_ProcessTransactionForFileLineRequest_FileParsingFailed_RequestIsHandled() { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileSafaricom); - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetFileAggregateWithLines); - + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetFileAggregateWithLines())); + this.FileAggregateRepository.Setup(f => f.SaveChanges(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success); this.TransactionProcessorClient.Setup(t => t.PerformTransaction(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.SerialisedMessageResponseSale); @@ -628,56 +558,50 @@ public void FileRequestHandler_ProcessTransactionForFileLineRequest_FileParsingF .ReturnsAsync(TestData.GetMerchantResponseWithOperator); this.EstateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantContractsResponse); + .ReturnsAsync(Result.Success(TestData.GetMerchantContractsResponse())); this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse()); this.FileFormatHandler.Setup(f => f.FileLineCanBeIgnored(It.IsAny())).Returns(false); this.FileFormatHandler.Setup(f => f.ParseFileLine(It.IsAny())).Throws(); - ProcessTransactionForFileLineRequest processTransactionForFileLineRequest = - new ProcessTransactionForFileLineRequest(TestData.FileId, TestData.LineNumber, TestData.FileLine); - - Should.NotThrow(async () => - { - await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest, CancellationToken.None); - }); + var result = await this.FileProcessorDomainService.ProcessTransactionForFileLine(TestData.ProcessTransactionForFileLineCommand, CancellationToken.None); + result.IsSuccess.ShouldBeTrue(); this.EstateClient.Verify(f => f.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny()), Times.Never); } [Fact] - public void FileRequestHandler_ProcessTransactionForFileLineRequest_MerchantNotFound_RequestIsHandled() + public async Task FileRequestHandler_ProcessTransactionForFileLineRequest_MerchantNotFound_RequestIsHandled() { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileSafaricom); - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetFileAggregateWithLines); + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetFileAggregateWithLines())); this.TransactionProcessorClient.Setup(t => t.PerformTransaction(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.SerialisedMessageResponseSale); + this.EstateClient + .Setup(e => e.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), + It.IsAny())).ReturnsAsync(Result.NotFound()); this.EstateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantContractsResponse); + .ReturnsAsync(Result.Success(TestData.GetMerchantContractsResponse())); this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse()); this.FileFormatHandler.Setup(f => f.FileLineCanBeIgnored(It.IsAny())).Returns(false); this.FileFormatHandler.Setup(f => f.ParseFileLine(It.IsAny())).Returns(TestData.TransactionMetadata); - ProcessTransactionForFileLineRequest processTransactionForFileLineRequest = - new ProcessTransactionForFileLineRequest(TestData.FileId, TestData.LineNumber, TestData.FileLine); - - Should.Throw(async () => - { - await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest, CancellationToken.None); - }); + var result =await this.FileProcessorDomainService.ProcessTransactionForFileLine(TestData.ProcessTransactionForFileLineCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.NotFound); } [Fact] - public void FileRequestHandler_ProcessTransactionForFileLineRequest_NoMerchantContractsFound_RequestIsHandled() + public async Task FileRequestHandler_ProcessTransactionForFileLineRequest_NoMerchantContractsFound_RequestIsHandled() { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileSafaricom); - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetFileAggregateWithLines); + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetFileAggregateWithLines())); this.TransactionProcessorClient.Setup(t => t.PerformTransaction(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.SerialisedMessageResponseSale); @@ -686,28 +610,24 @@ public void FileRequestHandler_ProcessTransactionForFileLineRequest_NoMerchantCo .ReturnsAsync(TestData.GetMerchantResponseWithOperator); this.EstateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetEmptyMerchantContractsResponse); + .ReturnsAsync(Result.NotFound()); this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse()); this.FileFormatHandler.Setup(f => f.FileLineCanBeIgnored(It.IsAny())).Returns(false); this.FileFormatHandler.Setup(f => f.ParseFileLine(It.IsAny())).Returns(TestData.TransactionMetadata); - - ProcessTransactionForFileLineRequest processTransactionForFileLineRequest = - new ProcessTransactionForFileLineRequest(TestData.FileId, TestData.LineNumber, TestData.FileLine); - Should.Throw(async () => - { - await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest, CancellationToken.None); - }); + var result = await this.FileProcessorDomainService.ProcessTransactionForFileLine(TestData.ProcessTransactionForFileLineCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.NotFound); } [Fact] - public void FileRequestHandler_ProcessTransactionForFileLineRequest_NoMerchantContractForFileOperatorFound_RequestIsHandled() + public async Task FileRequestHandler_ProcessTransactionForFileLineRequest_NoMerchantContractForFileOperatorFound_RequestIsHandled() { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileSafaricom); - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetFileAggregateWithLines); + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetFileAggregateWithLines())); this.TransactionProcessorClient.Setup(t => t.PerformTransaction(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.SerialisedMessageResponseSale); @@ -716,28 +636,24 @@ public void FileRequestHandler_ProcessTransactionForFileLineRequest_NoMerchantCo .ReturnsAsync(TestData.GetMerchantResponseWithOperator); this.EstateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantContractsNoFileOperatorResponse); + .ReturnsAsync(Result.NotFound()); this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse()); this.FileFormatHandler.Setup(f => f.FileLineCanBeIgnored(It.IsAny())).Returns(false); this.FileFormatHandler.Setup(f => f.ParseFileLine(It.IsAny())).Returns(TestData.TransactionMetadata); - - ProcessTransactionForFileLineRequest processTransactionForFileLineRequest = - new ProcessTransactionForFileLineRequest(TestData.FileId, TestData.LineNumber, TestData.FileLine); - Should.Throw(async () => - { - await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest, CancellationToken.None); - }); + var result = await this.FileProcessorDomainService.ProcessTransactionForFileLine(TestData.ProcessTransactionForFileLineCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.NotFound); } [Fact] - public void FileRequestHandler_ProcessTransactionForFileLineRequest_MerchantContractProductNotFound_RequestIsHandled() + public async Task FileRequestHandler_ProcessTransactionForFileLineRequest_MerchantContractProductNotFound_RequestIsHandled() { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileSafaricom); - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetFileAggregateWithLines); + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetFileAggregateWithLines())); this.TransactionProcessorClient.Setup(t => t.PerformTransaction(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.SerialisedMessageResponseSale); @@ -746,28 +662,24 @@ public void FileRequestHandler_ProcessTransactionForFileLineRequest_MerchantCont .ReturnsAsync(TestData.GetMerchantResponseWithOperator); this.EstateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantContractsResponseNoNullValueProduct); + .ReturnsAsync(Result.Success(TestData.GetMerchantContractsResponseNoNullValueProduct())); this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse()); this.FileFormatHandler.Setup(f => f.FileLineCanBeIgnored(It.IsAny())).Returns(false); this.FileFormatHandler.Setup(f => f.ParseFileLine(It.IsAny())).Returns(TestData.TransactionMetadata); - - ProcessTransactionForFileLineRequest processTransactionForFileLineRequest = - new ProcessTransactionForFileLineRequest(TestData.FileId, TestData.LineNumber, TestData.FileLine); - Should.Throw(async () => - { - await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest, CancellationToken.None); - }); + var result = await this.FileProcessorDomainService.ProcessTransactionForFileLine(TestData.ProcessTransactionForFileLineCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.NotFound); } [Fact] - public void FileRequestHandler_ProcessTransactionForFileLineRequest_TransactionNotSuccessful_RequestIsHandled() + public async Task FileRequestHandler_ProcessTransactionForFileLineRequest_TransactionNotSuccessful_RequestIsHandled() { this.FileProcessorManager.Setup(f => f.GetFileProfile(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.FileProfileSafaricom); - this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(TestData.GetFileAggregateWithLines); + this.FileAggregateRepository.Setup(f => f.GetLatestVersion(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.GetFileAggregateWithLines())); this.TransactionProcessorClient.Setup(t => t.PerformTransaction(It.IsAny(), It.IsAny(), It.IsAny())) .ReturnsAsync(TestData.SerialisedMessageResponseFailedSale); @@ -776,21 +688,18 @@ public void FileRequestHandler_ProcessTransactionForFileLineRequest_TransactionN .ReturnsAsync(TestData.GetMerchantResponseWithOperator); this.EstateClient.Setup(e => e.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ReturnsAsync(TestData.GetMerchantContractsResponse); + .ReturnsAsync(Result.Success(TestData.GetMerchantContractsResponse())); this.SecurityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(TestData.TokenResponse()); this.FileFormatHandler.Setup(f => f.FileLineCanBeIgnored(It.IsAny())).Returns(false); this.FileFormatHandler.Setup(f => f.ParseFileLine(It.IsAny())).Returns(TestData.TransactionMetadata); - - ProcessTransactionForFileLineRequest processTransactionForFileLineRequest = - new ProcessTransactionForFileLineRequest(TestData.FileId, TestData.LineNumber, TestData.FileLine); - Should.NotThrow(async () => - { - await this.FileProcessorDomainService.ProcessTransactionForFileLine(processTransactionForFileLineRequest, CancellationToken.None); - }); + var result = await this.FileProcessorDomainService.ProcessTransactionForFileLine(TestData.ProcessTransactionForFileLineCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + result.Status.ShouldBe(ResultStatus.Failure); } + private void VerifyFileProcessing(String filePath) { diff --git a/FileProcessor.BusinessLogic.Tests/FileRequestHandlerTests.cs b/FileProcessor.BusinessLogic.Tests/FileRequestHandlerTests.cs index e145335..bb0d9ea 100644 --- a/FileProcessor.BusinessLogic.Tests/FileRequestHandlerTests.cs +++ b/FileProcessor.BusinessLogic.Tests/FileRequestHandlerTests.cs @@ -2,6 +2,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using FileProcessor.BusinessLogic.Managers; using MediatR; namespace FileProcessor.BusinessLogic.Tests @@ -17,44 +18,32 @@ public class FileRequestHandlerTests { private Mock FileProcessorDomainService; private FileRequestHandler FileRequestHandler; + private Mock Manager; public FileRequestHandlerTests() { this.FileProcessorDomainService = new Mock(); - this.FileRequestHandler = new FileRequestHandler(this.FileProcessorDomainService.Object); + this.Manager = new Mock(); + this.FileRequestHandler = new FileRequestHandler(this.FileProcessorDomainService.Object, this.Manager.Object); } public async Task FileRequestHandler_HandleUploadFileRequest_RequestHandled() { Should.NotThrow(async () => { - await this.FileRequestHandler.Handle(TestData.UploadFileRequest, CancellationToken.None); + await this.FileRequestHandler.Handle(TestData.UploadFileCommand, CancellationToken.None); }); } public async Task FileRequestHandler_ProcessUploadedFileRequest_RequestHandled() { Should.NotThrow(async () => { - await this.FileRequestHandler.Handle(TestData.ProcessUploadedFileRequest, CancellationToken.None); + await this.FileRequestHandler.Handle(TestData.ProcessUploadedFileCommand, CancellationToken.None); }); } - //public async Task FileRequestHandler_SafaricomTopupRequest_RequestHandled() - //{ - // Should.NotThrow(async () => { - // await this.FileRequestHandler.Handle(TestData.SafaricomTopupRequest, CancellationToken.None); - // }); - //} - public async Task FileRequestHandler_ProcessTransactionForFileLineRequest_RequestHandled() { Should.NotThrow(async () => { - await this.FileRequestHandler.Handle(TestData.ProcessTransactionForFileLineRequest, CancellationToken.None); + await this.FileRequestHandler.Handle(TestData.ProcessTransactionForFileLineCommand, CancellationToken.None); }); } - - //public async Task FileRequestHandler_VoucherRequest_RequestHandled() - //{ - // Should.NotThrow(async () => { - // await this.FileRequestHandler.Handle(TestData.VoucherRequest, CancellationToken.None); - // }); - //} } } diff --git a/FileProcessor.BusinessLogic.Tests/MediatorTests.cs b/FileProcessor.BusinessLogic.Tests/MediatorTests.cs index 56055ce..9cdeac4 100644 --- a/FileProcessor.BusinessLogic.Tests/MediatorTests.cs +++ b/FileProcessor.BusinessLogic.Tests/MediatorTests.cs @@ -24,9 +24,9 @@ public class MediatorTests public MediatorTests() { - this.Requests.Add(TestData.UploadFileRequest); - this.Requests.Add(TestData.ProcessUploadedFileRequest); - this.Requests.Add(TestData.ProcessTransactionForFileLineRequest); + this.Requests.Add(TestData.UploadFileCommand); + this.Requests.Add(TestData.ProcessUploadedFileCommand); + this.Requests.Add(TestData.ProcessTransactionForFileLineCommand); } [Fact] diff --git a/FileProcessor.BusinessLogic.Tests/ModelFactoryTests.cs b/FileProcessor.BusinessLogic.Tests/ModelFactoryTests.cs index ac0fffb..6a373a2 100644 --- a/FileProcessor.BusinessLogic.Tests/ModelFactoryTests.cs +++ b/FileProcessor.BusinessLogic.Tests/ModelFactoryTests.cs @@ -3,7 +3,7 @@ using System.Linq; using Common; using EstateManagement.Database.Entities; - using FIleProcessor.Models; + using FileProcessor.Models; using Shouldly; using Testing; using Xunit; @@ -17,7 +17,7 @@ public void ModelFactory_ConvertFrom_FileImportLog_IsConverted(){ IModelFactory modelFactory = new ModelFactory(); List<(FileImportLogFile, File, Merchant)> files = new List<(FileImportLogFile, File, Merchant)>(); files.Add((TestData.FileImportLog1Files[0], TestData.Files1[0], TestData.Merchant)); - FIleProcessor.Models.FileImportLog result = modelFactory.ConvertFrom(TestData.EstateId, TestData.FileImportLogs.First(), files); + FileProcessor.Models.FileImportLog result = modelFactory.ConvertFrom(TestData.EstateId, TestData.FileImportLogs.First(), files); this.VerifyImportLog(TestData.FileImportLogs.First(), files, result); } @@ -25,7 +25,7 @@ public void ModelFactory_ConvertFrom_FileImportLog_IsConverted(){ public void ModelFactory_ConvertFrom_FileImportLog_NoFiles_IsConverted(){ IModelFactory modelFactory = new ModelFactory(); List<(FileImportLogFile, File, Merchant)> files = new List<(FileImportLogFile, File, Merchant)>(); - FIleProcessor.Models.FileImportLog result = modelFactory.ConvertFrom(TestData.EstateId, TestData.FileImportLogs.First(), files); + FileProcessor.Models.FileImportLog result = modelFactory.ConvertFrom(TestData.EstateId, TestData.FileImportLogs.First(), files); this.VerifyImportLog(TestData.FileImportLogs.First(), files, result); } @@ -36,7 +36,7 @@ public void ModelFactory_ConvertFrom_FileImportLog_NoImportLogs_IsConverted(){ List fileImportLogs = new List(); List<(FileImportLogFile, File, Merchant)> files = new List<(FileImportLogFile, File, Merchant)>(); - List result = modelFactory.ConvertFrom(TestData.EstateId, fileImportLogs, files); + List result = modelFactory.ConvertFrom(TestData.EstateId, fileImportLogs, files); result.ShouldNotBeNull(); result.ShouldBeEmpty(); @@ -48,7 +48,7 @@ public void ModelFactory_ConvertFrom_FileImportLogs_IsConverted(){ List<(FileImportLogFile, File, Merchant)> files = new List<(FileImportLogFile, File, Merchant)>(); files.Add((TestData.FileImportLog1Files[0], TestData.Files1[0], TestData.Merchant)); files.Add((TestData.FileImportLog1Files[1], TestData.Files1[1], TestData.Merchant)); - List result = modelFactory.ConvertFrom(TestData.EstateId, TestData.FileImportLogs, files); + List result = modelFactory.ConvertFrom(TestData.EstateId, TestData.FileImportLogs, files); this.VerifyImportLogs(TestData.FileImportLogs, files, result); } @@ -57,12 +57,12 @@ public void ModelFactory_ConvertFrom_FileImportLogs_IsConverted(){ public void ModelFactory_ConvertFrom_FileImportLogs_NoFiles_IsConverted(){ IModelFactory modelFactory = new ModelFactory(); List<(FileImportLogFile, File, Merchant)> files = new List<(FileImportLogFile, File, Merchant)>(); - List result = modelFactory.ConvertFrom(TestData.EstateId, TestData.FileImportLogs, files); + List result = modelFactory.ConvertFrom(TestData.EstateId, TestData.FileImportLogs, files); this.VerifyImportLogs(TestData.FileImportLogs, files, result); } - private void VerifyImportLog(FileImportLog sourceImportLog, List<(FileImportLogFile, File, Merchant)> sourceFiles, FIleProcessor.Models.FileImportLog importLog){ + private void VerifyImportLog(FileImportLog sourceImportLog, List<(FileImportLogFile, File, Merchant)> sourceFiles, FileProcessor.Models.FileImportLog importLog){ importLog.ShouldNotBeNull(); importLog.FileImportLogDateTime.ShouldBe(sourceImportLog.ImportLogDateTime); importLog.Files.Count.ShouldBe(sourceFiles.Count); @@ -78,12 +78,12 @@ private void VerifyImportLog(FileImportLog sourceImportLog, List<(FileImportLogF } } - private void VerifyImportLogs(List sourceImportLogs, List<(FileImportLogFile, File, Merchant)> sourceImportLogFiles, List importLogs){ + private void VerifyImportLogs(List sourceImportLogs, List<(FileImportLogFile, File, Merchant)> sourceImportLogFiles, List importLogs){ importLogs.ShouldNotBeNull(); importLogs.ShouldNotBeEmpty(); importLogs.Count.ShouldBe(TestData.FileImportLogs.Count); foreach (FileImportLog fileImportLog in sourceImportLogs){ - FIleProcessor.Models.FileImportLog importLog = importLogs.SingleOrDefault(i => i.FileImportLogId == fileImportLog.FileImportLogId); + FileProcessor.Models.FileImportLog importLog = importLogs.SingleOrDefault(i => i.FileImportLogId == fileImportLog.FileImportLogId); List<(FileImportLogFile, File, Merchant)> sourceFiles = sourceImportLogFiles.Where(s => s.Item1.FileImportLogId == fileImportLog.FileImportLogId).ToList(); this.VerifyImportLog(fileImportLog, sourceFiles, importLog); } diff --git a/FileProcessor.BusinessLogic.Tests/RequestTests.cs b/FileProcessor.BusinessLogic.Tests/RequestTests.cs deleted file mode 100644 index ad70818..0000000 --- a/FileProcessor.BusinessLogic.Tests/RequestTests.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using Xunit; - -namespace FileProcessor.BusinessLogic.Tests -{ - using Requests; - using Shouldly; - using Testing; - - public class RequestTests - { - [Fact] - public void UploadFileRequest_CanBeCreated_IsCreated() - { - UploadFileRequest uploadFileRequest = - new UploadFileRequest(TestData.EstateId, TestData.MerchantId, TestData.UserId, TestData.FilePath, TestData.FileProfileId, TestData.FileUploadedDateTime); - - uploadFileRequest.EstateId.ShouldBe(TestData.EstateId); - uploadFileRequest.MerchantId.ShouldBe(TestData.MerchantId); - uploadFileRequest.UserId.ShouldBe(TestData.UserId); - uploadFileRequest.FilePath.ShouldBe(TestData.FilePath); - uploadFileRequest.FileProfileId.ShouldBe(TestData.FileProfileId); - uploadFileRequest.FileUploadedDateTime.ShouldBe(TestData.FileUploadedDateTime); - } - - [Fact] - public void ProcessUploadedFileRequest_CanBeCreated_IsCreated() - { - ProcessUploadedFileRequest processUploadedFileRequest = - new ProcessUploadedFileRequest(TestData.EstateId, TestData.MerchantId, TestData.FileImportLogId, TestData.FileId, TestData.UserId, TestData.FilePath, TestData.FileProfileId, - TestData.FileUploadedDateTime); - - processUploadedFileRequest.EstateId.ShouldBe(TestData.EstateId); - processUploadedFileRequest.MerchantId.ShouldBe(TestData.MerchantId); - processUploadedFileRequest.FileImportLogId.ShouldBe(TestData.FileImportLogId); - processUploadedFileRequest.FileId.ShouldBe(TestData.FileId); - processUploadedFileRequest.UserId.ShouldBe(TestData.UserId); - processUploadedFileRequest.FilePath.ShouldBe(TestData.FilePath); - processUploadedFileRequest.FileProfileId.ShouldBe(TestData.FileProfileId); - processUploadedFileRequest.FileUploadedDateTime.ShouldBe(TestData.FileUploadedDateTime); - } - - [Fact] - public void ProcessTransactionForFileLineRequest_CanBeCreated_IsCreated() - { - ProcessTransactionForFileLineRequest processTransactionForFileLineRequest = - new ProcessTransactionForFileLineRequest(TestData.FileId, TestData.LineNumber, TestData.FileLine); - - processTransactionForFileLineRequest.FileId.ShouldBe(TestData.FileId); - processTransactionForFileLineRequest.LineNumber.ShouldBe(TestData.LineNumber); - processTransactionForFileLineRequest.FileLine.ShouldBe(TestData.FileLine); - } - } - - -} diff --git a/FileProcessor.BusinessLogic/Common/IModelFactory.cs b/FileProcessor.BusinessLogic/Common/IModelFactory.cs index bd8ac39..66b5d8d 100644 --- a/FileProcessor.BusinessLogic/Common/IModelFactory.cs +++ b/FileProcessor.BusinessLogic/Common/IModelFactory.cs @@ -3,7 +3,7 @@ using System; using System.Collections.Generic; using EstateManagement.Database.Entities; - using FileImportLogModel = FIleProcessor.Models.FileImportLog; + using FileImportLogModel = FileProcessor.Models.FileImportLog; /// /// diff --git a/FileProcessor.BusinessLogic/Common/ModelFactory.cs b/FileProcessor.BusinessLogic/Common/ModelFactory.cs index 615a287..b7dc80f 100644 --- a/FileProcessor.BusinessLogic/Common/ModelFactory.cs +++ b/FileProcessor.BusinessLogic/Common/ModelFactory.cs @@ -4,8 +4,8 @@ using System.Collections.Generic; using System.Linq; using EstateManagement.Database.Entities; - using FIleProcessor.Models; - using FileImportLog = FIleProcessor.Models.FileImportLog; + using FileProcessor.Models; + using FileImportLog = FileProcessor.Models.FileImportLog; /// /// diff --git a/FileProcessor.BusinessLogic/EventHandling/FileDomainEventHandler.cs b/FileProcessor.BusinessLogic/EventHandling/FileDomainEventHandler.cs index 5867fde..518b816 100644 --- a/FileProcessor.BusinessLogic/EventHandling/FileDomainEventHandler.cs +++ b/FileProcessor.BusinessLogic/EventHandling/FileDomainEventHandler.cs @@ -1,6 +1,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; +using SimpleResults; namespace FileProcessor.BusinessLogic.EventHandling { @@ -59,10 +60,10 @@ public FileDomainEventHandler(IMediator mediator) /// /// The domain event. /// The cancellation token. - public async Task Handle(IDomainEvent domainEvent, - CancellationToken cancellationToken) + public async Task Handle(IDomainEvent domainEvent, + CancellationToken cancellationToken) { - await this.HandleSpecificDomainEvent((dynamic)domainEvent, cancellationToken); + return await this.HandleSpecificDomainEvent((dynamic)domainEvent, cancellationToken); } //private static Int32 TransactionNumber = 0; @@ -72,12 +73,12 @@ public async Task Handle(IDomainEvent domainEvent, /// /// The domain event. /// The cancellation token. - private async Task HandleSpecificDomainEvent(FileLineAddedEvent domainEvent, + private async Task HandleSpecificDomainEvent(FileLineAddedEvent domainEvent, CancellationToken cancellationToken) { - ProcessTransactionForFileLineRequest request = new ProcessTransactionForFileLineRequest(domainEvent.FileId, domainEvent.LineNumber, domainEvent.FileLine); + FileCommands.ProcessTransactionForFileLineCommand command = new (domainEvent.FileId, domainEvent.LineNumber, domainEvent.FileLine); - await this.Mediator.Send(request, cancellationToken); + return await this.Mediator.Send(command, cancellationToken); } /// @@ -85,10 +86,10 @@ private async Task HandleSpecificDomainEvent(FileLineAddedEvent domainEvent, /// /// The domain event. /// The cancellation token. - private async Task HandleSpecificDomainEvent(FileAddedToImportLogEvent domainEvent, - CancellationToken cancellationToken) + private async Task HandleSpecificDomainEvent(FileAddedToImportLogEvent domainEvent, + CancellationToken cancellationToken) { - ProcessUploadedFileRequest request = new ProcessUploadedFileRequest(domainEvent.EstateId, + FileCommands.ProcessUploadedFileCommand command = new (domainEvent.EstateId, domainEvent.MerchantId, domainEvent.FileImportLogId, domainEvent.FileId, @@ -97,7 +98,7 @@ private async Task HandleSpecificDomainEvent(FileAddedToImportLogEvent domainEve domainEvent.FileProfileId, domainEvent.FileUploadedDateTime); - await this.Mediator.Send(request, cancellationToken); + return await this.Mediator.Send(command, cancellationToken); } #endregion diff --git a/FileProcessor.BusinessLogic/FileProcessor.BusinessLogic.csproj b/FileProcessor.BusinessLogic/FileProcessor.BusinessLogic.csproj index d462764..76e9318 100644 --- a/FileProcessor.BusinessLogic/FileProcessor.BusinessLogic.csproj +++ b/FileProcessor.BusinessLogic/FileProcessor.BusinessLogic.csproj @@ -5,16 +5,16 @@ - + - + - - + + - + - + diff --git a/FileProcessor.BusinessLogic/Managers/FileProcessorManager.cs b/FileProcessor.BusinessLogic/Managers/FileProcessorManager.cs index aab9030..8c879bb 100644 --- a/FileProcessor.BusinessLogic/Managers/FileProcessorManager.cs +++ b/FileProcessor.BusinessLogic/Managers/FileProcessorManager.cs @@ -1,4 +1,7 @@ -namespace FileProcessor.BusinessLogic.Managers +using FileProcessor.Models; +using SimpleResults; + +namespace FileProcessor.BusinessLogic.Managers { using System; using System.Collections.Generic; @@ -10,12 +13,12 @@ using EstateManagement.Database.Contexts; using EstateManagement.Database.Entities; using FileAggregate; - using FIleProcessor.Models; + using FileProcessor.Models; using Microsoft.EntityFrameworkCore; using Shared.DomainDrivenDesign.EventSourcing; using Shared.EventStore.Aggregate; using Shared.Exceptions; - using FileImportLog = FIleProcessor.Models.FileImportLog; + using FileImportLog = FileProcessor.Models.FileImportLog; /// /// @@ -63,38 +66,23 @@ public FileProcessorManager(List fileProfiles, #region Methods - /// - /// Gets all file profiles. - /// - /// The cancellation token. - /// - public async Task> GetAllFileProfiles(CancellationToken cancellationToken) + public async Task>> GetAllFileProfiles(CancellationToken cancellationToken) { - return this.FileProfiles; + return Result.Success(this.FileProfiles); } - /// - /// Gets the file profile. - /// - /// The file profile identifier. - /// The cancellation token. - /// - public async Task GetFileProfile(Guid fileProfileId, - CancellationToken cancellationToken) + public async Task> GetFileProfile(Guid fileProfileId, + CancellationToken cancellationToken) { - return this.FileProfiles.SingleOrDefault(f => f.FileProfileId == fileProfileId); + FileProfile fileProfile = this.FileProfiles.SingleOrDefault(f => f.FileProfileId == fileProfileId); + if (fileProfile == null) + return Result.NotFound($"No file profile found for File Profile Id {fileProfileId}"); + + return Result.Success(fileProfile); + } - /// - /// Gets the file import logs. - /// - /// - /// The start date time. - /// The end date time. - /// The merchant identifier. - /// The cancellation token. - /// - public async Task> GetFileImportLogs(Guid estateId, + public async Task>> GetFileImportLogs(Guid estateId, DateTime startDateTime, DateTime endDateTime, Guid? merchantId, @@ -134,18 +122,11 @@ public async Task> GetFileImportLogs(Guid estateId, entityData.Add((file.file.fileImportLogFile, file.file.file, file.merchant)); } - return this.ModelFactory.ConvertFrom(estateId, importLogQuery, entityData); + List model = this.ModelFactory.ConvertFrom(estateId, importLogQuery, entityData); + return Result.Success(model); } - /// - /// Gets the file import log files. - /// - /// The file import log identifier. - /// The estate identifier. - /// The merchant identifier. - /// The cancellation token. - /// - public async Task GetFileImportLog(Guid fileImportLogId, + public async Task> GetFileImportLog(Guid fileImportLogId, Guid estateId, Guid? merchantId, CancellationToken cancellationToken) @@ -189,23 +170,20 @@ public async Task GetFileImportLog(Guid fileImportLogId, return this.ModelFactory.ConvertFrom(estateId, importLogQuery, entityData); } - /// - /// Gets the file. - /// - /// The file identifier. - /// The estate identifier. - /// The cancellation token. - /// - public async Task GetFile(Guid fileId, + public async Task> GetFile(Guid fileId, Guid estateId, CancellationToken cancellationToken) { - FileAggregate fileAggregate = + Result fileAggregateResult= await this.FileAggregateRepository.GetLatestVersion(fileId, cancellationToken); + if (fileAggregateResult.IsFailed) + return ResultHelpers.CreateFailure(fileAggregateResult); + + FileAggregate fileAggregate = fileAggregateResult.Data; if (fileAggregate.IsCreated == false) { - throw new NotFoundException($"File with Id [{fileId}] not found"); + return Result.NotFound($"File with Id [{fileId}] not found"); } FileDetails fileDetails = fileAggregate.GetFile(); @@ -221,7 +199,7 @@ public async Task GetFile(Guid fileId, } EstateSecurityUser userDetails = await context.EstateSecurityUsers.AsAsyncEnumerable() - .SingleOrDefaultAsync(u => u.SecurityUserId == fileDetails.UserId); + .SingleOrDefaultAsync(u => u.SecurityUserId == fileDetails.UserId, cancellationToken: cancellationToken); if (userDetails != null) { fileDetails.UserEmailAddress = userDetails.EmailAddress; @@ -233,7 +211,7 @@ public async Task GetFile(Guid fileId, fileDetails.FileProfileName = fileProfile.Name; } - return fileDetails; + return Result.Success(fileDetails); } #endregion diff --git a/FileProcessor.BusinessLogic/Managers/IFileProcessorManager.cs b/FileProcessor.BusinessLogic/Managers/IFileProcessorManager.cs index 70753d0..cefa0e8 100644 --- a/FileProcessor.BusinessLogic/Managers/IFileProcessorManager.cs +++ b/FileProcessor.BusinessLogic/Managers/IFileProcessorManager.cs @@ -1,11 +1,13 @@ -namespace FileProcessor.BusinessLogic.Managers +using FileProcessor.Models; +using SimpleResults; + +namespace FileProcessor.BusinessLogic.Managers { using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; - using FIleProcessor.Models; - + /// /// /// @@ -13,54 +15,15 @@ public interface IFileProcessorManager { #region Methods - /// - /// Gets all file profiles. - /// - /// The cancellation token. - /// - Task> GetAllFileProfiles(CancellationToken cancellationToken); - - /// - /// Gets the file profile. - /// - /// The file profile identifier. - /// The cancellation token. - /// - Task GetFileProfile(Guid fileProfileId, - CancellationToken cancellationToken); + Task>> GetAllFileProfiles(CancellationToken cancellationToken); - /// - /// Gets the file import logs. - /// - /// - /// The start date time. - /// The end date time. - /// The merchant identifier. - /// The cancellation token. - /// - Task> GetFileImportLogs(Guid estateId, DateTime startDateTime, DateTime endDateTime, Guid? merchantId, CancellationToken cancellationToken); + Task> GetFileProfile(Guid fileProfileId, CancellationToken cancellationToken); + Task>> GetFileImportLogs(Guid estateId, DateTime startDateTime, DateTime endDateTime, Guid? merchantId, CancellationToken cancellationToken); - /// - /// Gets the file import log files. - /// - /// The file import log identifier. - /// The estate identifier. - /// The merchant identifier. - /// The cancellation token. - /// - Task GetFileImportLog(Guid fileImportLogId, Guid estateId, Guid? merchantId, CancellationToken cancellationToken); + Task> GetFileImportLog(Guid fileImportLogId, Guid estateId, Guid? merchantId, CancellationToken cancellationToken); - /// - /// Gets the file. - /// - /// The file identifier. - /// The estate identifier. - /// The cancellation token. - /// - Task GetFile(Guid fileId, - Guid estateId, - CancellationToken cancellationToken); + Task> GetFile(Guid fileId, Guid estateId, CancellationToken cancellationToken); #endregion } diff --git a/FileProcessor.BusinessLogic/RequestHandlers/FileRequestHandler.cs b/FileProcessor.BusinessLogic/RequestHandlers/FileRequestHandler.cs index 2f4d410..70db5b7 100644 --- a/FileProcessor.BusinessLogic/RequestHandlers/FileRequestHandler.cs +++ b/FileProcessor.BusinessLogic/RequestHandlers/FileRequestHandler.cs @@ -1,69 +1,61 @@ using System; using System.Collections.Generic; -using System.ComponentModel; -using System.Linq; -using System.Text; using System.Threading.Tasks; +using FileProcessor.Models; +using SimpleResults; namespace FileProcessor.BusinessLogic.RequestHandlers { - using System.IO; - using System.IO.Abstractions; - using System.Security.Cryptography; using MediatR; using System.Threading; - using Common; - using EstateManagement.Client; - using EstateManagement.DataTransferObjects.Responses; - using EventHandling; - using FileAggregate; - using FileFormatHandlers; - using FileImportLogAggregate; - using FIleProcessor.Models; - using Managers; - using Newtonsoft.Json; using Requests; - using SecurityService.Client; - using SecurityService.DataTransferObjects.Responses; using Services; - using Shared.DomainDrivenDesign.EventSourcing; - using Shared.EventStore.Aggregate; - using Shared.Exceptions; - using Shared.General; - using Shared.Logger; - using TransactionProcessor.Client; - using TransactionProcessor.DataTransferObjects; - using Exception = System.Exception; + using FileProcessor.BusinessLogic.Managers; + using EstateManagement.Database.Entities; - /// - /// - /// - /// - /// - public class FileRequestHandler : IRequestHandler, - IRequestHandler, - IRequestHandler + public class FileRequestHandler : IRequestHandler, + IRequestHandler, + IRequestHandler>, + IRequestHandler>, + IRequestHandler>>, + IRequestHandler> { private readonly IFileProcessorDomainService DomainService; + private readonly IFileProcessorManager Manager; - public FileRequestHandler(IFileProcessorDomainService domainService) - { + public FileRequestHandler(IFileProcessorDomainService domainService, IFileProcessorManager manager) { this.DomainService = domainService; + this.Manager = manager; } - public async Task Handle(UploadFileRequest request, - CancellationToken cancellationToken) { - return await this.DomainService.UploadFile(request, cancellationToken); + public async Task> Handle(FileCommands.UploadFileCommand command, + CancellationToken cancellationToken) { + return await this.DomainService.UploadFile(command, cancellationToken); } - public async Task Handle(ProcessUploadedFileRequest request, CancellationToken cancellationToken) + public async Task Handle(FileCommands.ProcessUploadedFileCommand command, CancellationToken cancellationToken) { - await this.DomainService.ProcessUploadedFile(request, cancellationToken); + return await this.DomainService.ProcessUploadedFile(command, cancellationToken); } - public async Task Handle(ProcessTransactionForFileLineRequest request, - CancellationToken cancellationToken) { - await this.DomainService.ProcessTransactionForFileLine(request, cancellationToken); + public async Task Handle(FileCommands.ProcessTransactionForFileLineCommand command, + CancellationToken cancellationToken) { + return await this.DomainService.ProcessTransactionForFileLine(command, cancellationToken); + } + + public async Task> Handle(FileQueries.GetFileQuery query, + CancellationToken cancellationToken) { + return await this.Manager.GetFile(query.FileId, query.EstateId, cancellationToken); + } + + public async Task>> Handle(FileQueries.GetImportLogsQuery query, + CancellationToken cancellationToken) { + return await this.Manager.GetFileImportLogs(query.EstateId, query.StartDateTime, query.EndDateTime, query.MerchantId, cancellationToken); + } + + public async Task> Handle(FileQueries.GetImportLogQuery query, + CancellationToken cancellationToken) { + return await this.Manager.GetFileImportLog(query.FileImportLogId, query.EstateId, query.MerchantId, cancellationToken); } } } diff --git a/FileProcessor.BusinessLogic/Requests/FileCommands.cs b/FileProcessor.BusinessLogic/Requests/FileCommands.cs new file mode 100644 index 0000000..1f0e7a8 --- /dev/null +++ b/FileProcessor.BusinessLogic/Requests/FileCommands.cs @@ -0,0 +1,26 @@ +using System; +using MediatR; +using SimpleResults; + +namespace FileProcessor.BusinessLogic.Requests; + +public record FileCommands { + public record ProcessTransactionForFileLineCommand(Guid FileId, Int32 LineNumber, String FileLine) + : IRequest; + + public record ProcessUploadedFileCommand(Guid EstateId, + Guid MerchantId, + Guid FileImportLogId, + Guid FileId, + Guid UserId, + String FilePath, + Guid FileProfileId, + DateTime FileUploadedDateTime) : IRequest; + + public record UploadFileCommand(Guid EstateId, + Guid MerchantId, + Guid UserId, + String FilePath, + Guid FileProfileId, + DateTime FileUploadedDateTime) : IRequest>; +} \ No newline at end of file diff --git a/FileProcessor.BusinessLogic/Requests/FileQueries.cs b/FileProcessor.BusinessLogic/Requests/FileQueries.cs new file mode 100644 index 0000000..fff80c1 --- /dev/null +++ b/FileProcessor.BusinessLogic/Requests/FileQueries.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using FileProcessor.Models; +using MediatR; +using SimpleResults; + +namespace FileProcessor.BusinessLogic.Requests; + +public record FileQueries { + public record GetFileQuery(Guid FileId, Guid EstateId) : IRequest>; + + public record GetImportLogsQuery(Guid EstateId, DateTime StartDateTime, DateTime EndDateTime, Guid? MerchantId) : IRequest>>; + + public record GetImportLogQuery(Guid FileImportLogId, + Guid EstateId, + Guid? MerchantId) : IRequest>; +} \ No newline at end of file diff --git a/FileProcessor.BusinessLogic/Requests/ProcessTransactionForFileLineRequest.cs b/FileProcessor.BusinessLogic/Requests/ProcessTransactionForFileLineRequest.cs deleted file mode 100644 index d90a464..0000000 --- a/FileProcessor.BusinessLogic/Requests/ProcessTransactionForFileLineRequest.cs +++ /dev/null @@ -1,62 +0,0 @@ -namespace FileProcessor.BusinessLogic.Requests -{ - using System; - using MediatR; - - /// - /// - /// - /// - /// - /// - /// - public record ProcessTransactionForFileLineRequest : IRequest - { - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The file identifier. - /// The line number. - /// The file line. - public ProcessTransactionForFileLineRequest(Guid fileId, - Int32 lineNumber, - String fileLine) - { - this.FileId = fileId; - this.LineNumber = lineNumber; - this.FileLine = fileLine; - } - - #endregion - - #region Properties - - /// - /// Gets or sets the file identifier. - /// - /// - /// The file identifier. - /// - public Guid FileId { get; init; } - - /// - /// Gets or sets the file line. - /// - /// - /// The file line. - /// - public String FileLine { get; init; } - - /// - /// Gets or sets the line number. - /// - /// - /// The line number. - /// - public Int32 LineNumber { get; init; } - - #endregion - } -} \ No newline at end of file diff --git a/FileProcessor.BusinessLogic/Requests/ProcessUploadedFileRequest.cs b/FileProcessor.BusinessLogic/Requests/ProcessUploadedFileRequest.cs deleted file mode 100644 index cef6347..0000000 --- a/FileProcessor.BusinessLogic/Requests/ProcessUploadedFileRequest.cs +++ /dev/null @@ -1,109 +0,0 @@ -namespace FileProcessor.BusinessLogic.Requests -{ - using System; - using MediatR; - - public record ProcessUploadedFileRequest : IRequest - { - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The estate identifier. - /// The merchant identifier. - /// The file identifier. - /// The user identifier. - /// The file path. - /// The file profile identifier. - /// The file uploaded date time. - public ProcessUploadedFileRequest(Guid estateId, - Guid merchantId, - Guid fileImportLogId, - Guid fileId, - Guid userId, - String filePath, - Guid fileProfileId, - DateTime fileUploadedDateTime) - { - this.FileUploadedDateTime = fileUploadedDateTime; - this.EstateId = estateId; - this.MerchantId = merchantId; - this.FileId = fileId; - this.UserId = userId; - this.FilePath = filePath; - this.FileProfileId = fileProfileId; - this.FileImportLogId = fileImportLogId; - } - - #endregion - - #region Properties - - /// - /// Gets or sets the estate identifier. - /// - /// - /// The estate identifier. - /// - public Guid EstateId { get; init; } - - /// - /// Gets or sets the file uploaded date time. - /// - /// - /// The file uploaded date time. - /// - public DateTime FileUploadedDateTime { get; init; } - - /// - /// Gets or sets the file identifier. - /// - /// - /// The file identifier. - /// - public Guid FileId { get; init; } - - /// - /// Gets or sets the file path. - /// - /// - /// The file path. - /// - public String FilePath { get; init; } - - /// - /// Gets or sets the file profile identifier. - /// - /// - /// The file profile identifier. - /// - public Guid FileProfileId { get; init; } - - /// - /// Gets or sets the file import log identifier. - /// - /// - /// The file import log identifier. - /// - public Guid FileImportLogId { get; init; } - - /// - /// Gets or sets the merchant identifier. - /// - /// - /// The merchant identifier. - /// - public Guid MerchantId { get; init; } - - /// - /// Gets or sets the user identifier. - /// - /// - /// The user identifier. - /// - public Guid UserId { get; init; } - - #endregion - } -} \ No newline at end of file diff --git a/FileProcessor.BusinessLogic/Requests/UploadFileRequest.cs b/FileProcessor.BusinessLogic/Requests/UploadFileRequest.cs deleted file mode 100644 index 103563d..0000000 --- a/FileProcessor.BusinessLogic/Requests/UploadFileRequest.cs +++ /dev/null @@ -1,96 +0,0 @@ -namespace FileProcessor.BusinessLogic.Requests -{ - using System; - using MediatR; - - /// - /// - /// - /// - /// - /// - /// - /// - public record UploadFileRequest : IRequest - { - #region Constructors - - /// - /// Initializes a new instance of the class. - /// - /// The estate identifier. - /// The merchant identifier. - /// The user identifier. - /// The file path. - /// The file profile identifier. - /// The file uploaded date time. - public UploadFileRequest(Guid estateId, - Guid merchantId, - Guid userId, - String filePath, - Guid fileProfileId, - DateTime fileUploadedDateTime) - { - this.EstateId = estateId; - this.MerchantId = merchantId; - this.UserId = userId; - this.FilePath = filePath; - this.FileProfileId = fileProfileId; - this.FileUploadedDateTime = fileUploadedDateTime; - } - - #endregion - - #region Properties - - /// - /// Gets or sets the estate identifier. - /// - /// - /// The estate identifier. - /// - public Guid EstateId { get; init; } - - /// - /// Gets or sets the file uploaded date time. - /// - /// - /// The file uploaded date time. - /// - public DateTime FileUploadedDateTime { get; init; } - - /// - /// Gets or sets the file path. - /// - /// - /// The file path. - /// - public String FilePath { get; init; } - - /// - /// Gets or sets the file profile identifier. - /// - /// - /// The file profile identifier. - /// - public Guid FileProfileId { get; init; } - - /// - /// Gets or sets the merchant identifier. - /// - /// - /// The merchant identifier. - /// - public Guid MerchantId { get; init; } - - /// - /// Gets or sets the user identifier. - /// - /// - /// The user identifier. - /// - public Guid UserId { get; init; } - - #endregion - } -} \ No newline at end of file diff --git a/FileProcessor.BusinessLogic/Services/FileProcessorDomainService.cs b/FileProcessor.BusinessLogic/Services/FileProcessorDomainService.cs index 309e34c..227016e 100644 --- a/FileProcessor.BusinessLogic/Services/FileProcessorDomainService.cs +++ b/FileProcessor.BusinessLogic/Services/FileProcessorDomainService.cs @@ -1,4 +1,8 @@ -namespace FileProcessor.BusinessLogic.Services; +using System.Reflection.Metadata.Ecma335; +using FileProcessor.Models; +using SimpleResults; + +namespace FileProcessor.BusinessLogic.Services; using System; using System.Collections.Generic; @@ -19,8 +23,9 @@ using FileFormatHandlers; using FileImportLogAggregate; using FileProcessor.DataTransferObjects.Responses; -using FIleProcessor.Models; +using FileProcessor.Models; using Managers; +using MediatR; using Newtonsoft.Json; using Requests; using SecurityService.Client; @@ -32,9 +37,10 @@ using Shared.Logger; using TransactionProcessor.Client; using TransactionProcessor.DataTransferObjects; -using FileDetails = FIleProcessor.Models.FileDetails; -using FileLine = FIleProcessor.Models.FileLine; +using FileDetails = FileProcessor.Models.FileDetails; +using FileLine = FileProcessor.Models.FileLine; using MerchantResponse = EstateManagement.DataTransferObjects.Responses.Merchant.MerchantResponse; +using ResultHelpers = Shared.EventStore.Aggregate.ResultHelpers; public class FileProcessorDomainService : IFileProcessorDomainService { @@ -72,363 +78,433 @@ public FileProcessorDomainService(IFileProcessorManager fileProcessorManager, this.FileSystem = fileSystem; } - public async Task UploadFile(UploadFileRequest request, - CancellationToken cancellationToken) { - DateTime importLogDateTime = request.FileUploadedDateTime; + private async Task ApplyFileUpdates(Func> action, + Guid fileId, + CancellationToken cancellationToken, + Boolean isNotFoundError = true) + { + try + { + Result getFileResult = await this.FileAggregateRepository.GetLatestVersion(fileId, cancellationToken); + Result fileAggregateResult = + DomainServiceHelper.HandleGetAggregateResult(getFileResult, fileId, isNotFoundError); + if (fileAggregateResult.IsFailed) + return Shared.EventStore.Aggregate.ResultHelpers.CreateFailure(fileAggregateResult); + FileAggregate fileAggregate = fileAggregateResult.Data; + Result result = await action(fileAggregate); + if (result.IsFailed) + return Shared.EventStore.Aggregate.ResultHelpers.CreateFailure(result); + Logger.LogWarning("About to save"); + Result saveResult = await this.FileAggregateRepository.SaveChanges(fileAggregate, cancellationToken); + if (saveResult.IsFailed) + return Shared.EventStore.Aggregate.ResultHelpers.CreateFailure(saveResult); + Logger.LogWarning("About to return success after save"); + return Result.Success(); + } + catch (Exception ex) + { + Logger.LogError(ex); + return Result.Failure(ex.GetExceptionMessages()); + } + } - this.ValidateRequest(request); + private async Task> ApplyFileImportLogUpdates(Func>> action, + Guid fileImportLogId, + CancellationToken cancellationToken, + Boolean isNotFoundError = true) + { + try + { - // This will now create the import log and add an event for the file being uploaded - Guid importLogId = Helpers.CalculateFileImportLogAggregateId(importLogDateTime.Date, request.EstateId); + Result getFileImportLogResult = await this.FileImportLogAggregateRepository.GetLatestVersion(fileImportLogId, cancellationToken); + Result fileImportLogAggregateResult = + DomainServiceHelper.HandleGetAggregateResult(getFileImportLogResult, fileImportLogId, isNotFoundError); - // Get the import log - FileImportLogAggregate fileImportLogAggregate = await this.FileImportLogAggregateRepository.GetLatestVersion(importLogId, cancellationToken); + FileImportLogAggregate fileImportLogAggregate = fileImportLogAggregateResult.Data; + Result result = await action(fileImportLogAggregate); + if (result.IsFailed) + return Shared.EventStore.Aggregate.ResultHelpers.CreateFailure(result); - if (fileImportLogAggregate.IsCreated == false) + Result saveResult = await this.FileImportLogAggregateRepository.SaveChanges(fileImportLogAggregate, cancellationToken); + if (saveResult.IsFailed) + return Shared.EventStore.Aggregate.ResultHelpers.CreateFailure(saveResult); + return Result.Success(result.Data); + } + catch (Exception ex) { - // First file of the day so create - fileImportLogAggregate.CreateImportLog(request.EstateId, importLogDateTime); + return Result.Failure(ex.GetExceptionMessages()); } + } - // Move the file - FileProfile fileProfile = await this.FileProcessorManager.GetFileProfile(request.FileProfileId, cancellationToken); + public async Task> UploadFile(FileCommands.UploadFileCommand command, + CancellationToken cancellationToken) { + DateTime importLogDateTime = command.FileUploadedDateTime; - if (fileProfile == null) - { - throw new NotFoundException($"No file profile found with Id {request.FileProfileId}"); - } + Result validateResult = this.ValidateRequest(command); + if (validateResult.IsFailed) + return validateResult; - // Copy file from the temp location to file processing listening directory - IFileInfo file = this.FileSystem.FileInfo.New(request.FilePath); - if (file.Exists == false) - { - throw new FileNotFoundException($"File {file.FullName} not found"); - } - String originalName = file.Name; + // This will now create the import log and add an event for the file being uploaded + Guid importLogId = Helpers.CalculateFileImportLogAggregateId(importLogDateTime.Date, command.EstateId); - if (this.FileSystem.Directory.Exists(fileProfile.ListeningDirectory) == false) - { - throw new DirectoryNotFoundException($"Directory {fileProfile.ListeningDirectory} not found"); - } + Result result = await ApplyFileImportLogUpdates(async (fileImportLogAggregate) => { + if (fileImportLogAggregate.IsCreated == false) + { + // First file of the day so create + fileImportLogAggregate.CreateImportLog(command.EstateId, importLogDateTime); + } - // Read the file data - String fileContent = null; - //Open file for Read\Write - using (Stream fs = file.Open(FileMode.OpenOrCreate, FileAccess.Read, FileShare.Read)) - { - //Create object of StreamReader by passing FileStream object on which it needs to operates on - using (StreamReader sr = new StreamReader(fs)) + // Move the file + FileProfile fileProfile = await this.FileProcessorManager.GetFileProfile(command.FileProfileId, cancellationToken); + + if (fileProfile == null) { - //Use ReadToEnd method to read all the content from file - fileContent = await sr.ReadToEndAsync(); + return Result.NotFound($"No file profile found with Id {command.FileProfileId}"); } - } - Guid fileId = this.CreateGuidFromFileData(fileContent); + // Copy file from the temp location to file processing listening directory + IFileInfo file = this.FileSystem.FileInfo.New(command.FilePath); + if (file.Exists == false) + { + return Result.NotFound($"File {file.FullName} not found"); + } + String originalName = file.Name; + + if (this.FileSystem.Directory.Exists(fileProfile.ListeningDirectory) == false) + { + return Result.NotFound($"Directory {fileProfile.ListeningDirectory} not found"); + } - String fileDestination = $"{fileProfile.ListeningDirectory}//{request.EstateId:N}-{fileId:N}"; - file.MoveTo(fileDestination, overwrite: true); + // Read the file data + String fileContent = null; + //Open file for Read\Write + using (Stream fs = file.Open(FileMode.OpenOrCreate, FileAccess.Read, FileShare.Read)) + { + //Create object of StreamReader by passing FileStream object on which it needs to operates on + using (StreamReader sr = new StreamReader(fs)) + { + //Use ReadToEnd method to read all the content from file + fileContent = await sr.ReadToEndAsync(cancellationToken); + } + } - // Update Import log aggregate - fileImportLogAggregate.AddImportedFile(fileId, request.MerchantId, request.UserId, request.FileProfileId, originalName, fileDestination, request.FileUploadedDateTime); + Guid fileId = this.CreateGuidFromFileData(fileContent); - // Save changes - await this.FileImportLogAggregateRepository.SaveChanges(fileImportLogAggregate, cancellationToken); + String fileDestination = $"{fileProfile.ListeningDirectory}//{command.EstateId:N}-{fileId:N}"; + file.MoveTo(fileDestination, overwrite: true); - return fileId; + // Update Import log aggregate + fileImportLogAggregate.AddImportedFile(fileId, command.MerchantId, command.UserId, command.FileProfileId, originalName, fileDestination, command.FileUploadedDateTime); + + return Result.Success(fileId); + }, importLogId, cancellationToken, false); + + return result; } - private void ValidateRequest(UploadFileRequest request){ - if (request.UserId == Guid.Empty){ - throw new InvalidDataException("No User Id provided with file upload"); + private Result ValidateRequest(FileCommands.UploadFileCommand command) { + if (command.UserId == Guid.Empty) { + return Result.Invalid("No User Id provided with file upload"); } - if (request.MerchantId == Guid.Empty) - { - throw new InvalidDataException("No Merchant Id provided with file upload"); + if (command.MerchantId == Guid.Empty) { + return Result.Invalid("No Merchant Id provided with file upload"); } - if (request.FileProfileId == Guid.Empty) - { - throw new InvalidDataException("No File Profile Id provided with file upload"); + if (command.FileProfileId == Guid.Empty) { + return Result.Invalid("No File Profile Id provided with file upload"); } + + return Result.Success(); } - public async Task ProcessUploadedFile(ProcessUploadedFileRequest request, - CancellationToken cancellationToken) { + public async Task ProcessUploadedFile(FileCommands.ProcessUploadedFileCommand command, + CancellationToken cancellationToken) { // TODO: Should the file id be generated from the file uploaded to protect against duplicate files??? - FileAggregate fileAggregate = await this.FileAggregateRepository.GetLatestVersion(request.FileId, cancellationToken); + Result result = await ApplyFileUpdates(async (FileAggregate fileAggregate) => { + Logger.LogWarning("In ProcessUploadedFile action"); + Result operatorIdResult = await GetOperatorIdForFileProfile(command.EstateId, command.FileProfileId, cancellationToken); + if (operatorIdResult.IsFailed) + return ResultHelpers.CreateFailure(operatorIdResult); - Guid operatorId = await GetOperatorIdForFileProfile(request.EstateId, request.FileProfileId, cancellationToken); + Logger.LogWarning("About to Create File"); + fileAggregate.CreateFile(command.FileImportLogId, command.EstateId, command.MerchantId, command.UserId, command.FileProfileId, command.FilePath, command.FileUploadedDateTime, operatorIdResult.Data); + Logger.LogWarning("About to return success"); + return Result.Success(); - fileAggregate.CreateFile(request.FileImportLogId, request.EstateId, request.MerchantId, request.UserId, request.FileProfileId, request.FilePath, request.FileUploadedDateTime, operatorId); + }, command.FileId, cancellationToken, false ); - await this.FileAggregateRepository.SaveChanges(fileAggregate, cancellationToken); - - await this.ProcessFile(request.FileId, request.FileProfileId, request.FilePath, cancellationToken); + if (result.IsFailed) + return result; + + Result processResult = await this.ProcessFile(command.FileId, command.FileProfileId, command.FilePath, cancellationToken); + + return processResult; } - private async Task GetOperatorIdForFileProfile(Guid estateId, Guid fileProfileId, CancellationToken cancellationToken){ + private async Task> GetOperatorIdForFileProfile(Guid estateId, Guid fileProfileId, CancellationToken cancellationToken){ - FileProfile fileProfile = await this.FileProcessorManager.GetFileProfile(fileProfileId, cancellationToken); + Result fileProfileResult = await this.FileProcessorManager.GetFileProfile(fileProfileId, cancellationToken); - if (fileProfile == null){ + if (fileProfileResult.IsFailed){ Logger.LogInformation($"file profile {fileProfileId} not found"); - throw new NotFoundException($"file profile {fileProfileId} not found"); + return ResultHelpers.CreateFailure(fileProfileResult); } + var fileProfile = fileProfileResult.Data; this.TokenResponse = await this.GetToken(cancellationToken); - List operatorList = await this.EstateClient.GetOperators(this.TokenResponse.AccessToken, estateId, cancellationToken); - if (operatorList == null){ - throw new NotFoundException($"No operators returned from API Call"); + Result> getOperatorsResult = await this.EstateClient.GetOperators(this.TokenResponse.AccessToken, estateId, cancellationToken); + if (getOperatorsResult.IsFailed) { + return ResultHelpers.CreateFailure(getOperatorsResult); } + List operatorList = getOperatorsResult.Data; OperatorResponse @operator = operatorList.SingleOrDefault(o => o.Name == fileProfile.OperatorName); if (@operator == null){ - throw new NotFoundException($"No operator record found with name [{fileProfile.OperatorName}]"); + return Result.NotFound($"No operator record found with name [{fileProfile.OperatorName}]"); } - return @operator.OperatorId; + return Result.Success(@operator.OperatorId); } - public async Task ProcessTransactionForFileLine(ProcessTransactionForFileLineRequest request, - CancellationToken cancellationToken) { - // Get the file aggregate, this tells us the file profile information - FileAggregate fileAggregate = await this.FileAggregateRepository.GetLatestVersion(request.FileId, cancellationToken); + public async Task ProcessTransactionForFileLine(FileCommands.ProcessTransactionForFileLineCommand command, + CancellationToken cancellationToken) { + Result result = await ApplyFileUpdates(async (FileAggregate fileAggregate) => { + FileDetails fileDetails = fileAggregate.GetFile(); - FileDetails fileDetails = fileAggregate.GetFile(); + if (fileDetails.FileLines.Any() == false) + { + return Result.Invalid($"File Id [{command.FileId}] has no lines added"); + } - if (fileDetails.FileLines.Any() == false) - { - throw new NotSupportedException($"File Id [{request.FileId}] has no lines added"); - } + FileLine fileLine = fileDetails.FileLines.SingleOrDefault(f => f.LineNumber == command.LineNumber); - FileLine fileLine = fileDetails.FileLines.SingleOrDefault(f => f.LineNumber == request.LineNumber); + if (fileLine == null) + { + return Result.NotFound($"File Line Number {command.LineNumber} not found in File Id {command.FileId}"); + } - if (fileLine == null) - { - throw new NotFoundException($"File Line Number {request.LineNumber} not found in File Id {request.FileId}"); - } + if (fileLine.ProcessingResult != ProcessingResult.NotProcessed) + { + // Line already processed + return Result.Success(); + } - if (fileLine.ProcessingResult != ProcessingResult.NotProcessed) - { - // Line already processed - return; - } + Result fileProfileResult = await this.FileProcessorManager.GetFileProfile(fileDetails.FileProfileId, cancellationToken); - FileProfile fileProfile = await this.FileProcessorManager.GetFileProfile(fileDetails.FileProfileId, cancellationToken); + if (fileProfileResult.IsFailed) + return ResultHelpers.CreateFailure(fileProfileResult); - if (fileProfile == null) - { - throw new NotFoundException($"No file profile found with Id {fileDetails.FileProfileId}"); - } + FileProfile fileProfile = fileProfileResult.Data; - // Determine if we need to actually process this file line - if (this.FileLineCanBeIgnored(fileLine.LineData, fileProfile.FileFormatHandler)) - { - // Write something to aggregate to say line was explicity ignored - fileAggregate.RecordFileLineAsIgnored(fileLine.LineNumber); - await this.FileAggregateRepository.SaveChanges(fileAggregate, cancellationToken); - return; - } + // Determine if we need to actually process this file line + if (this.FileLineCanBeIgnored(fileLine.LineData, fileProfile.FileFormatHandler)) + { + // Write something to aggregate to say line was explicity ignored + fileAggregate.RecordFileLineAsIgnored(fileLine.LineNumber); + return Result.Success(); + } - // need to now parse the line (based on the file format), this builds the metadata - Dictionary transactionMetadata = this.ParseFileLine(fileLine.LineData, fileProfile.FileFormatHandler); + // need to now parse the line (based on the file format), this builds the metadata + Dictionary transactionMetadata = this.ParseFileLine(fileLine.LineData, fileProfile.FileFormatHandler); - if (transactionMetadata == null) - { - // Line failed to parse so record this - fileAggregate.RecordFileLineAsRejected(fileLine.LineNumber, "Invalid Format"); - await this.FileAggregateRepository.SaveChanges(fileAggregate, cancellationToken); - return; - } + if (transactionMetadata == null) + { + // Line failed to parse so record this + fileAggregate.RecordFileLineAsRejected(fileLine.LineNumber, "Invalid Format"); + return Result.Success(); + } - // Add the file data to the request metadata - transactionMetadata.Add("FileId", request.FileId.ToString()); - transactionMetadata.Add("FileLineNumber", fileLine.LineNumber.ToString()); + // Add the file data to the request metadata + transactionMetadata.Add("FileId", command.FileId.ToString()); + transactionMetadata.Add("FileLineNumber", fileLine.LineNumber.ToString()); - String operatorName = fileProfile.OperatorName; - if (transactionMetadata.ContainsKey("OperatorName")) - { - // extract the value - operatorName = transactionMetadata["OperatorName"]; - transactionMetadata = transactionMetadata.Where(x => x.Key != "OperatorName").ToDictionary(x => x.Key, x => x.Value); - } + String operatorName = fileProfile.OperatorName; + if (transactionMetadata.ContainsKey("OperatorName")) + { + // extract the value + operatorName = transactionMetadata["OperatorName"]; + transactionMetadata = transactionMetadata.Where(x => x.Key != "OperatorName").ToDictionary(x => x.Key, x => x.Value); + } - this.TokenResponse = await this.GetToken(cancellationToken); + this.TokenResponse = await this.GetToken(cancellationToken); - Interlocked.Increment(ref FileProcessorDomainService.TransactionNumber); + Interlocked.Increment(ref FileProcessorDomainService.TransactionNumber); - // Get the merchant details - MerchantResponse merchant = await this.EstateClient.GetMerchant(this.TokenResponse.AccessToken, fileDetails.EstateId, fileDetails.MerchantId, cancellationToken); - if (merchant == null) - { - throw new NotFoundException($"Merchant not found with Id {fileDetails.MerchantId} on estate Id {fileDetails.EstateId}"); - } - List contracts = await this.EstateClient.GetMerchantContracts(this.TokenResponse.AccessToken, fileDetails.EstateId, fileDetails.MerchantId, cancellationToken); + // Get the merchant details + var getMerchantResult = await this.EstateClient.GetMerchant(this.TokenResponse.AccessToken, fileDetails.EstateId, fileDetails.MerchantId, cancellationToken); + if (getMerchantResult.IsFailed) + { + return ResultHelpers.CreateFailure(getMerchantResult); + } - if (contracts.Any() == false) - { - throw new NotFoundException($"No contracts found for Merchant Id {fileDetails.MerchantId} on estate Id {fileDetails.EstateId}"); - } + var merchant = getMerchantResult.Data; - ContractResponse? contract = null; - if (fileProfile.OperatorName == "Voucher") - { - contract = contracts.SingleOrDefault(c => c.Description.Contains(operatorName)); - } - else - { - contract = contracts.SingleOrDefault(c => c.OperatorName == operatorName); - } + var getContractsResult = await this.EstateClient.GetMerchantContracts(this.TokenResponse.AccessToken, fileDetails.EstateId, fileDetails.MerchantId, cancellationToken); + if (getContractsResult.IsFailed) + { + return ResultHelpers.CreateFailure(getContractsResult); + } - if (contract == null) - { - throw new NotFoundException($"No merchant contract for operator Id {operatorName} found for Merchant Id {merchant.MerchantId}"); - } + var contracts = getContractsResult.Data; - ContractProduct? product = contract.Products.SingleOrDefault(p => p.Value == null); // TODO: Is this enough or should the name be used and stored in file profile?? + if (contracts.Any() == false) + { + throw new NotFoundException($"No contracts found for Merchant Id {fileDetails.MerchantId} on estate Id {fileDetails.EstateId}"); + } - if (product == null) - { - throw new NotFoundException($"No variable value product found on the merchant contract for operator Id {fileProfile.OperatorName} and Merchant Id {merchant.MerchantId}"); - } + ContractResponse? contract = null; + if (fileProfile.OperatorName == "Voucher") + { + contract = contracts.SingleOrDefault(c => c.Description.Contains(operatorName)); + } + else + { + contract = contracts.SingleOrDefault(c => c.OperatorName == operatorName); + } - // Build a transaction request message - SaleTransactionRequest saleTransactionRequest = new SaleTransactionRequest - { - EstateId = fileDetails.EstateId, - MerchantId = fileDetails.MerchantId, - TransactionDateTime = fileDetails.FileReceivedDateTime, - TransactionNumber = FileProcessorDomainService.TransactionNumber.ToString(), - TransactionType = "Sale", - ContractId = contract.ContractId, - DeviceIdentifier = merchant.Devices.First().Value, - OperatorId = contract.OperatorId, - ProductId = product.ProductId, - AdditionalTransactionMetadata = transactionMetadata, - TransactionSource = 2 // File based transaction - }; - - SerialisedMessage serialisedRequestMessage = new SerialisedMessage - { - Metadata = new Dictionary + if (contract == null) + { + return Result.NotFound($"No merchant contract for operator Id {operatorName} found for Merchant Id {merchant.MerchantId}"); + } + + ContractProduct? product = contract.Products.SingleOrDefault(p => p.Value == null); // TODO: Is this enough or should the name be used and stored in file profile?? + + if (product == null) + { + return Result.NotFound($"No variable value product found on the merchant contract for operator Id {fileProfile.OperatorName} and Merchant Id {merchant.MerchantId}"); + } + + // Build a transaction request message + SaleTransactionRequest saleTransactionRequest = new SaleTransactionRequest + { + EstateId = fileDetails.EstateId, + MerchantId = fileDetails.MerchantId, + TransactionDateTime = fileDetails.FileReceivedDateTime, + TransactionNumber = FileProcessorDomainService.TransactionNumber.ToString(), + TransactionType = "Sale", + ContractId = contract.ContractId, + DeviceIdentifier = merchant.Devices.First().Value, + OperatorId = contract.OperatorId, + ProductId = product.ProductId, + AdditionalTransactionMetadata = transactionMetadata, + TransactionSource = 2 // File based transaction + }; + + SerialisedMessage serialisedRequestMessage = new SerialisedMessage + { + Metadata = new Dictionary { {"estate_id", fileDetails.EstateId.ToString()}, {"merchant_id", fileDetails.MerchantId.ToString()} }, - SerialisedData = JsonConvert.SerializeObject(saleTransactionRequest, new JsonSerializerSettings - { - TypeNameHandling = TypeNameHandling.All - }) - }; + SerialisedData = JsonConvert.SerializeObject(saleTransactionRequest, new JsonSerializerSettings + { + TypeNameHandling = TypeNameHandling.All + }) + }; - Logger.LogDebug(serialisedRequestMessage.SerialisedData); + Logger.LogDebug(serialisedRequestMessage.SerialisedData); - // Send request to transaction processor - SerialisedMessage serialisedResponseMessage = await this.TransactionProcessorClient.PerformTransaction(this.TokenResponse.AccessToken, serialisedRequestMessage, cancellationToken); + // Send request to transaction processor + Result result= await this.TransactionProcessorClient.PerformTransaction(this.TokenResponse.AccessToken, serialisedRequestMessage, cancellationToken); + if (result.IsFailed) + return ResultHelpers.CreateFailure(result); + var serialisedResponseMessage = result.Data; - // Get the sale transaction response - SaleTransactionResponse saleTransactionResponse = JsonConvert.DeserializeObject(serialisedResponseMessage.SerialisedData); + // Get the sale transaction response + SaleTransactionResponse saleTransactionResponse = JsonConvert.DeserializeObject(serialisedResponseMessage.SerialisedData); - if (saleTransactionResponse.ResponseCode == "0000") - { - // record response against file line in file aggregate - fileAggregate.RecordFileLineAsSuccessful(request.LineNumber, saleTransactionResponse.TransactionId); - } - else - { - fileAggregate.RecordFileLineAsFailed(request.LineNumber, saleTransactionResponse.TransactionId, saleTransactionResponse.ResponseCode, saleTransactionResponse.ResponseMessage); - } + if (saleTransactionResponse.ResponseCode == "0000") + { + // record response against file line in file aggregate + fileAggregate.RecordFileLineAsSuccessful(command.LineNumber, saleTransactionResponse.TransactionId); + } + else + { + fileAggregate.RecordFileLineAsFailed(command.LineNumber, saleTransactionResponse.TransactionId, saleTransactionResponse.ResponseCode, saleTransactionResponse.ResponseMessage); + } + + return Result.Success(); + + }, command.FileId, cancellationToken); - // Save changes to file aggregate - // TODO: Add retry round this save (maybe 3 retries) - await this.FileAggregateRepository.SaveChanges(fileAggregate, cancellationToken); + return result; } - private async Task ProcessFile(Guid fileId, - Guid fileProfileId, - String fileName, - CancellationToken cancellationToken) - { + private async Task ProcessFile(Guid fileId, + Guid fileProfileId, + String fileName, + CancellationToken cancellationToken) { IFileInfo inProgressFile = null; FileProfile fileProfile = null; - try - { - fileProfile = await this.FileProcessorManager.GetFileProfile(fileProfileId, cancellationToken); - if (fileProfile == null) - { - throw new NotFoundException($"No file profile found with Id {fileProfileId}"); - } + Result fileProfileResult = + await this.FileProcessorManager.GetFileProfile(fileProfileId, cancellationToken); - // Check the processed/failed directories exist - if (this.FileSystem.Directory.Exists(fileProfile.ProcessedDirectory) == false) - { - Logger.LogInformation($"Creating Directory {fileProfile.ProcessedDirectory} as not found"); - this.FileSystem.Directory.CreateDirectory(fileProfile.ProcessedDirectory); - } + if (fileProfileResult.IsFailed) + return ResultHelpers.CreateFailure(fileProfileResult); + fileProfile = fileProfileResult.Data; + // Check the processed/failed directories exist + if (this.FileSystem.Directory.Exists(fileProfile.ProcessedDirectory) == false) { + Logger.LogInformation($"Creating Directory {fileProfile.ProcessedDirectory} as not found"); + this.FileSystem.Directory.CreateDirectory(fileProfile.ProcessedDirectory); + } - if (this.FileSystem.Directory.Exists(fileProfile.FailedDirectory) == false) - { - Logger.LogInformation($"Creating Directory {fileProfile.FailedDirectory} as not found"); - this.FileSystem.Directory.CreateDirectory(fileProfile.FailedDirectory); - } + if (this.FileSystem.Directory.Exists(fileProfile.FailedDirectory) == false) { + Logger.LogInformation($"Creating Directory {fileProfile.FailedDirectory} as not found"); + this.FileSystem.Directory.CreateDirectory(fileProfile.FailedDirectory); + } - inProgressFile = this.FileSystem.FileInfo.New(fileName); + inProgressFile = this.FileSystem.FileInfo.New(fileName); - if (inProgressFile.Exists == false) - { - // We also want to check the failed folder incase this is an event replay - IFileInfo failedFileInfo = this.FileSystem.FileInfo.New($"{fileProfile.FailedDirectory}/{inProgressFile.Name}"); + if (inProgressFile.Exists == false) { + // We also want to check the failed folder incase this is an event replay + IFileInfo failedFileInfo = + this.FileSystem.FileInfo.New($"{fileProfile.FailedDirectory}/{inProgressFile.Name}"); - if (failedFileInfo.Exists == false){ - throw new FileNotFoundException($"File {inProgressFile.FullName} not found"); - } - // Overwrite the inprogress file info object with the file found in the failed folder - inProgressFile = failedFileInfo; + if (failedFileInfo.Exists == false) { + return Result.NotFound($"File {inProgressFile.FullName} not found"); } - FileAggregate fileAggregate = - await this.FileAggregateRepository.GetLatestVersion(fileId, cancellationToken); - + // Overwrite the inprogress file info object with the file found in the failed folder + inProgressFile = failedFileInfo; + } + + Result result = await ApplyFileUpdates(async (FileAggregate fileAggregate) => { + String fileContent = null; //Open file for Read\Write - using (Stream fs = inProgressFile.Open(FileMode.OpenOrCreate, FileAccess.Read, FileShare.Read)) - { + using (Stream fs = inProgressFile.Open(FileMode.OpenOrCreate, FileAccess.Read, FileShare.Read)) { //Create object of StreamReader by passing FileStream object on which it needs to operates on - using (StreamReader sr = new StreamReader(fs)) - { + using (StreamReader sr = new StreamReader(fs)) { //Use ReadToEnd method to read all the content from file fileContent = await sr.ReadToEndAsync(cancellationToken); } } - if (String.IsNullOrEmpty(fileContent) == false) - { + if (String.IsNullOrEmpty(fileContent) == false) { String[] fileLines = fileContent.Split(fileProfile.LineTerminator); - foreach (String fileLine in fileLines) - { + foreach (String fileLine in fileLines) { fileAggregate.AddFileLine(fileLine.Trim()); } - - await this.FileAggregateRepository.SaveChanges(fileAggregate, cancellationToken); } + return Result.Success(); + }, fileId, cancellationToken); + + if (result.IsSuccess) { Logger.LogInformation($"About to move file {inProgressFile.Name} to [{fileProfile.ProcessedDirectory}]"); - // TODO: Move file now + // Move file now inProgressFile.MoveTo($"{fileProfile.ProcessedDirectory}/{inProgressFile.Name}"); } - catch (Exception e) - { - if (inProgressFile != null && fileProfile != null) - inProgressFile.MoveTo($"{fileProfile.FailedDirectory}/{inProgressFile.Name}"); - - Logger.LogError(e); - throw; + else { + inProgressFile.MoveTo($"{fileProfile.FailedDirectory}/{inProgressFile.Name}"); } + + return result; } private static Int32 TransactionNumber = 0; @@ -500,4 +576,35 @@ private async Task GetToken(CancellationToken cancellationToken) return this.TokenResponse; } +} + +public static class DomainServiceHelper +{ + public static Result HandleGetAggregateResult(Result result, Guid aggregateId, bool isNotFoundError = true) + where T : Aggregate, new() // Constraint: T is a subclass of Aggregate and has a parameterless constructor + { + Logger.LogWarning($"Result is {JsonConvert.SerializeObject(result)}"); + Logger.LogWarning($"aggregateId is {aggregateId}"); + Logger.LogWarning($"isNotFoundError is {isNotFoundError}"); + + if (result.IsFailed && result.Status != ResultStatus.NotFound) { + Logger.LogWarning("In here 1"); + return Shared.EventStore.Aggregate.ResultHelpers.CreateFailure(result); + } + + if (result.Status == ResultStatus.NotFound && isNotFoundError) + { + Logger.LogWarning("In here 2"); + return Shared.EventStore.Aggregate.ResultHelpers.CreateFailure(result); + } + + Logger.LogWarning("In here 3"); + T aggregate = result.Status switch + { + ResultStatus.NotFound => new T { AggregateId = aggregateId }, // Set AggregateId when creating a new instance + _ => result.Data + }; + + return Result.Success(aggregate); + } } \ No newline at end of file diff --git a/FileProcessor.BusinessLogic/Services/IFileProcessorDomainService.cs b/FileProcessor.BusinessLogic/Services/IFileProcessorDomainService.cs index 3519af4..665ae2a 100644 --- a/FileProcessor.BusinessLogic/Services/IFileProcessorDomainService.cs +++ b/FileProcessor.BusinessLogic/Services/IFileProcessorDomainService.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using SimpleResults; namespace FileProcessor.BusinessLogic.Services { @@ -10,12 +11,12 @@ namespace FileProcessor.BusinessLogic.Services public interface IFileProcessorDomainService { - Task UploadFile(UploadFileRequest request, CancellationToken cancellationToken); + Task> UploadFile(FileCommands.UploadFileCommand command, CancellationToken cancellationToken); - Task ProcessUploadedFile(ProcessUploadedFileRequest request, - CancellationToken cancellationToken); + Task ProcessUploadedFile(FileCommands.ProcessUploadedFileCommand command, + CancellationToken cancellationToken); - Task ProcessTransactionForFileLine(ProcessTransactionForFileLineRequest request, + Task ProcessTransactionForFileLine(FileCommands.ProcessTransactionForFileLineCommand command, CancellationToken cancellationToken); } } diff --git a/FileProcessor.Client/FileProcessor.Client.csproj b/FileProcessor.Client/FileProcessor.Client.csproj index 95bc0ae..87cf823 100644 --- a/FileProcessor.Client/FileProcessor.Client.csproj +++ b/FileProcessor.Client/FileProcessor.Client.csproj @@ -1,12 +1,12 @@  - net8.0;netstandard2.1 + net8.0 $(TargetsForTfmSpecificBuildOutput);IncludeP2PAssets - + diff --git a/FileProcessor.Client/FileProcessorClient.cs b/FileProcessor.Client/FileProcessorClient.cs index 186e657..9b3ac3d 100644 --- a/FileProcessor.Client/FileProcessorClient.cs +++ b/FileProcessor.Client/FileProcessorClient.cs @@ -1,6 +1,6 @@ -namespace FileProcessor.Client -{ +namespace FileProcessor.Client { using System; + using System.Collections.Generic; using System.Net.Http; using System.Net.Http.Headers; using System.Threading; @@ -9,14 +9,14 @@ using DataTransferObjects; using DataTransferObjects.Responses; using Newtonsoft.Json; + using SimpleResults; /// /// /// /// /// - public class FileProcessorClient : ClientProxyBase, IFileProcessorClient - { + public class FileProcessorClient : ClientProxyBase, IFileProcessorClient { #region Fields /// @@ -34,8 +34,7 @@ public class FileProcessorClient : ClientProxyBase, IFileProcessorClient /// The base address resolver. /// The HTTP client. public FileProcessorClient(Func baseAddressResolver, - HttpClient httpClient) : base(httpClient) - { + HttpClient httpClient) : base(httpClient) { this.BaseAddressResolver = baseAddressResolver; // Add the API version header @@ -54,38 +53,42 @@ public FileProcessorClient(Func baseAddressResolver, /// The file identifier. /// The cancellation token. /// - public async Task GetFile(String accessToken, + public async Task> GetFile(String accessToken, Guid estateId, Guid fileId, - CancellationToken cancellationToken) - { + CancellationToken cancellationToken) { FileDetails response = null; String requestUri = this.BuildRequestUrl($"/api/files/{fileId}?estateId={estateId}"); - try - { + try { // Add the access token header - this.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); + this.HttpClient.DefaultRequestHeaders.Authorization = + new AuthenticationHeaderValue("Bearer", accessToken); // Make the Http Call here HttpResponseMessage httpResponse = await this.HttpClient.GetAsync(requestUri, cancellationToken); // Process the response - String content = await this.HandleResponse(httpResponse, cancellationToken); + Result result = await this.HandleResponseX(httpResponse, cancellationToken); + + if (result.IsFailed) + return ResultHelpers.CreateFailure(result); + + ResponseData responseData = + JsonConvert.DeserializeObject>(result.Data.StringData); // call was successful so now deserialise the body to the response object - response = JsonConvert.DeserializeObject(content); + response = responseData.Data; } - catch(Exception ex) - { + catch (Exception ex) { // An exception has occurred, add some additional information to the message Exception exception = new Exception($"Error getting file with Id {fileId}.", ex); throw exception; } - return response; + return Result.Success(response); } /// @@ -97,44 +100,47 @@ public async Task GetFile(String accessToken, /// The merchant identifier. /// The cancellation token. /// - public async Task GetFileImportLog(String accessToken, + public async Task> GetFileImportLog(String accessToken, Guid fileImportLogId, Guid estateId, Guid? merchantId, - CancellationToken cancellationToken) - { + CancellationToken cancellationToken) { FileImportLog response = null; String requestUri = this.BuildRequestUrl($"/api/fileImportLogs/{fileImportLogId}?estateId={estateId}"); - if (merchantId.HasValue) - { + if (merchantId.HasValue) { requestUri += $"&merchantId={merchantId}"; } - try - { + try { // Add the access token header - this.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); + this.HttpClient.DefaultRequestHeaders.Authorization = + new AuthenticationHeaderValue("Bearer", accessToken); // Make the Http Call here HttpResponseMessage httpResponse = await this.HttpClient.GetAsync(requestUri, cancellationToken); // Process the response - String content = await this.HandleResponse(httpResponse, cancellationToken); + Result result = await this.HandleResponseX(httpResponse, cancellationToken); + + if (result.IsFailed) + return ResultHelpers.CreateFailure(result); + + ResponseData responseData = + JsonConvert.DeserializeObject>(result.Data.StringData); // call was successful so now deserialise the body to the response object - response = JsonConvert.DeserializeObject(content); + response = responseData.Data; } - catch(Exception ex) - { + catch (Exception ex) { // An exception has occurred, add some additional information to the message Exception exception = new Exception("Error getting file import log.", ex); throw exception; } - return response; + return Result.Success(response); } /// @@ -147,46 +153,49 @@ public async Task GetFileImportLog(String accessToken, /// The merchant identifier. /// The cancellation token. /// - public async Task GetFileImportLogs(String accessToken, + public async Task> GetFileImportLogs(String accessToken, Guid estateId, DateTime startDateTime, DateTime endDateTime, Guid? merchantId, - CancellationToken cancellationToken) - { + CancellationToken cancellationToken) { FileImportLogList response = null; String requestUri = - this.BuildRequestUrl($"/api/fileImportLogs?estateId={estateId}&startDateTime={startDateTime.Date:yyyy-MM-dd}&endDateTime={endDateTime.Date:yyyy-MM-dd}"); + this.BuildRequestUrl( + $"/api/fileImportLogs?estateId={estateId}&startDateTime={startDateTime.Date:yyyy-MM-dd}&endDateTime={endDateTime.Date:yyyy-MM-dd}"); - if (merchantId.HasValue) - { + if (merchantId.HasValue) { requestUri += $"&merchantId={merchantId}"; } - try - { + try { // Add the access token header - this.HttpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); + this.HttpClient.DefaultRequestHeaders.Authorization = + new AuthenticationHeaderValue("Bearer", accessToken); // Make the Http Call here HttpResponseMessage httpResponse = await this.HttpClient.GetAsync(requestUri, cancellationToken); // Process the response - String content = await this.HandleResponse(httpResponse, cancellationToken); + var result = await this.HandleResponseX(httpResponse, cancellationToken); + if (result.IsFailed) + return ResultHelpers.CreateFailure(result); + + ResponseData responseData = + JsonConvert.DeserializeObject>(result.Data.StringData); // call was successful so now deserialise the body to the response object - response = JsonConvert.DeserializeObject(content); + response = responseData.Data; } - catch(Exception ex) - { + catch (Exception ex) { // An exception has occurred, add some additional information to the message Exception exception = new Exception("Error getting list of file import logs.", ex); throw exception; } - return response; + return Result.Success(response); } /// @@ -198,15 +207,13 @@ public async Task GetFileImportLogs(String accessToken, /// The upload file request. /// The cancellation token. /// - public async Task UploadFile(String accessToken, - String fileName, - Byte[] fileData, - UploadFileRequest uploadFileRequest, - CancellationToken cancellationToken) - { + public async Task> UploadFile(String accessToken, + String fileName, + Byte[] fileData, + UploadFileRequest uploadFileRequest, + CancellationToken cancellationToken) { Guid response = Guid.Empty; - try - { + try { String requestUri = this.BuildRequestUrl("/api/files"); HttpRequestMessage httpRequest = new HttpRequestMessage(HttpMethod.Post, requestUri); @@ -219,7 +226,8 @@ public async Task UploadFile(String accessToken, formData.Add(new StringContent(uploadFileRequest.MerchantId.ToString()), "request.MerchantId"); formData.Add(new StringContent(uploadFileRequest.FileProfileId.ToString()), "request.FileProfileId"); formData.Add(new StringContent(uploadFileRequest.UserId.ToString()), "request.UserId"); - formData.Add(new StringContent(uploadFileRequest.UploadDateTime.ToString("yyyy-MM-dd HH:mm:ss")), "request.UploadDateTime"); + formData.Add(new StringContent(uploadFileRequest.UploadDateTime.ToString("yyyy-MM-dd HH:mm:ss")), + "request.UploadDateTime"); httpRequest.Content = formData; httpRequest.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); @@ -227,20 +235,25 @@ public async Task UploadFile(String accessToken, HttpResponseMessage httpResponse = await this.HttpClient.SendAsync(httpRequest, cancellationToken); // Process the response - String content = await this.HandleResponse(httpResponse, cancellationToken); + Result result = await this.HandleResponseX(httpResponse, cancellationToken); + + if (result.IsFailed) + return ResultHelpers.CreateFailure(result); + + ResponseData responseData = + JsonConvert.DeserializeObject>(result.Data.StringData); // call was successful so now deserialise the body to the response object - response = JsonConvert.DeserializeObject(content); + response = responseData.Data; } - catch(Exception ex) - { + catch (Exception ex) { // An exception has occurred, add some additional information to the message Exception exception = new Exception($"Error uploading file {fileName}.", ex); throw exception; } - return response; + return Result.Success(response); } /// @@ -248,8 +261,7 @@ public async Task UploadFile(String accessToken, /// /// The route. /// - private String BuildRequestUrl(String route) - { + private String BuildRequestUrl(String route) { String baseAddress = this.BaseAddressResolver("FileProcessorApi"); String requestUri = $"{baseAddress}{route}"; @@ -259,4 +271,89 @@ private String BuildRequestUrl(String route) #endregion } + + internal class ResponseData { + public T Data { get; set; } + } + + public static class ResultHelpers { + public static Result CreateFailure(Result result) { + if (result.IsFailed) { + return BuildResult(result.Status, result.Message, result.Errors); + } + + return Result.Failure("Unknown Failure"); + } + + public static Result CreateFailure(Result result) { + if (result.IsFailed) { + return BuildResult(result.Status, result.Message, result.Errors); + } + + return Result.Failure("Unknown Failure"); + } + + private static Result BuildResult(ResultStatus status, + String messageValue, + IEnumerable errorList) { + return (status, messageValue, errorList) switch { + // If the status is NotFound and there are errors, return the errors + (ResultStatus.NotFound, _, List errors) when errors is { Count: > 0 } => + Result.NotFound(errors), + + // If the status is NotFound and the message is not null or empty, return the message + (ResultStatus.NotFound, string message, _) when !string.IsNullOrEmpty(message) => Result.NotFound( + message), + + // If the status is Failure and there are errors, return the errors + (ResultStatus.Failure, _, List errors) when errors is { Count: > 0 } => Result.Failure(errors), + + // If the status is Failure and the message is not null or empty, return the message + (ResultStatus.Failure, string message, _) when !string.IsNullOrEmpty(message) => + Result.Failure(message), + + // If the status is Forbidden and there are errors, return the errors + (ResultStatus.Forbidden, _, List errors) when errors is { Count: > 0 } => Result.Forbidden( + errors), + + // If the status is Forbidden and the message is not null or empty, return the message + (ResultStatus.Forbidden, string message, _) when !string.IsNullOrEmpty(message) => Result.NotFound( + message), + //### + // If the status is Invalid and there are errors, return the errors + (ResultStatus.Invalid, _, List errors) when errors is { Count: > 0 } => Result.Invalid(errors), + + // If the status is Invalid and the message is not null or empty, return the message + (ResultStatus.Invalid, string message, _) when !string.IsNullOrEmpty(message) => + Result.Invalid(message), + + // If the status is Unauthorized and there are errors, return the errors + (ResultStatus.Unauthorized, _, List errors) when errors is { Count: > 0 } => + Result.Unauthorized(errors), + + // If the status is Unauthorized and the message is not null or empty, return the message + (ResultStatus.Unauthorized, string message, _) when !string.IsNullOrEmpty(message) => Result + .Unauthorized(message), + + // If the status is Conflict and there are errors, return the errors + (ResultStatus.Conflict, _, List errors) when errors is { Count: > 0 } => + Result.Conflict(errors), + + // If the status is Conflict and the message is not null or empty, return the message + (ResultStatus.Conflict, string message, _) when !string.IsNullOrEmpty(message) => Result.Conflict( + message), + + // If the status is CriticalError and there are errors, return the errors + (ResultStatus.CriticalError, _, List errors) when errors is { Count: > 0 } => Result + .CriticalError(errors), + + // If the status is CriticalError and the message is not null or empty, return the message + (ResultStatus.CriticalError, string message, _) when !string.IsNullOrEmpty(message) => Result + .CriticalError(message), + + // Default case, return a generic failure message + _ => Result.Failure("An unexpected error occurred.") + }; + } + } } \ No newline at end of file diff --git a/FileProcessor.Client/IFileProcessorClient.cs b/FileProcessor.Client/IFileProcessorClient.cs index 829afe3..555df46 100644 --- a/FileProcessor.Client/IFileProcessorClient.cs +++ b/FileProcessor.Client/IFileProcessorClient.cs @@ -1,4 +1,6 @@ -namespace FileProcessor.Client +using SimpleResults; + +namespace FileProcessor.Client { using System; using System.Threading; @@ -21,7 +23,7 @@ public interface IFileProcessorClient /// The file identifier. /// The cancellation token. /// - Task GetFile(String accessToken, + Task> GetFile(String accessToken, Guid estateId, Guid fileId, CancellationToken cancellationToken); @@ -35,7 +37,7 @@ Task GetFile(String accessToken, /// The merchant identifier. /// The cancellation token. /// - Task GetFileImportLog(String accessToken, + Task> GetFileImportLog(String accessToken, Guid fileImportLogId, Guid estateId, Guid? merchantId, @@ -51,7 +53,7 @@ Task GetFileImportLog(String accessToken, /// The merchant identifier. /// The cancellation token. /// - Task GetFileImportLogs(String accessToken, + Task> GetFileImportLogs(String accessToken, Guid estateId, DateTime startDateTime, DateTime endDateTime, @@ -67,7 +69,7 @@ Task GetFileImportLogs(String accessToken, /// The upload file request. /// The cancellation token. /// - Task UploadFile(String accessToken, + Task> UploadFile(String accessToken, String fileName, Byte[] fileData, UploadFileRequest uploadFileRequest, diff --git a/FileProcessor.File.DomainEvents/FileProcessor.File.DomainEvents.csproj b/FileProcessor.File.DomainEvents/FileProcessor.File.DomainEvents.csproj index 596c44f..0d7d1b4 100644 --- a/FileProcessor.File.DomainEvents/FileProcessor.File.DomainEvents.csproj +++ b/FileProcessor.File.DomainEvents/FileProcessor.File.DomainEvents.csproj @@ -6,7 +6,7 @@ - + diff --git a/FileProcessor.FileAggregate.Tests/FileAggregateTests.cs b/FileProcessor.FileAggregate.Tests/FileAggregateTests.cs index 662399a..6a0b268 100644 --- a/FileProcessor.FileAggregate.Tests/FileAggregateTests.cs +++ b/FileProcessor.FileAggregate.Tests/FileAggregateTests.cs @@ -4,7 +4,7 @@ namespace FileProcessor.FileAggregate.Tests { using System.Linq; - using FIleProcessor.Models; + using FileProcessor.Models; using Shared.Exceptions; using Shouldly; using Testing; diff --git a/FileProcessor.FileAggregate/FileAggregate.cs b/FileProcessor.FileAggregate/FileAggregate.cs index 3f94058..8bee122 100644 --- a/FileProcessor.FileAggregate/FileAggregate.cs +++ b/FileProcessor.FileAggregate/FileAggregate.cs @@ -1,4 +1,5 @@ using System; +using FileProcessor.Models; namespace FileProcessor.FileAggregate { @@ -7,7 +8,7 @@ namespace FileProcessor.FileAggregate using System.Linq; using System.Runtime.InteropServices.ComTypes; using File.DomainEvents; - using FIleProcessor.Models; + using FileProcessor.Models; using Shared.DomainDrivenDesign.EventSourcing; using Shared.EventStore.Aggregate; using Shared.Exceptions; diff --git a/FileProcessor.FileAggregate/FileProcessor.FileAggregate.csproj b/FileProcessor.FileAggregate/FileProcessor.FileAggregate.csproj index 3fd6a64..8a1dd41 100644 --- a/FileProcessor.FileAggregate/FileProcessor.FileAggregate.csproj +++ b/FileProcessor.FileAggregate/FileProcessor.FileAggregate.csproj @@ -6,8 +6,8 @@ - - + + diff --git a/FileProcessor.FileImportLog.DomainEvents/FileProcessor.FileImportLog.DomainEvents.csproj b/FileProcessor.FileImportLog.DomainEvents/FileProcessor.FileImportLog.DomainEvents.csproj index c021906..58b6c71 100644 --- a/FileProcessor.FileImportLog.DomainEvents/FileProcessor.FileImportLog.DomainEvents.csproj +++ b/FileProcessor.FileImportLog.DomainEvents/FileProcessor.FileImportLog.DomainEvents.csproj @@ -6,7 +6,7 @@ - + diff --git a/FileProcessor.FileImportLogAggregate.Tests/FileImportLogAggregateTests.cs b/FileProcessor.FileImportLogAggregate.Tests/FileImportLogAggregateTests.cs index 54a4f46..8b6c762 100644 --- a/FileProcessor.FileImportLogAggregate.Tests/FileImportLogAggregateTests.cs +++ b/FileProcessor.FileImportLogAggregate.Tests/FileImportLogAggregateTests.cs @@ -4,7 +4,7 @@ namespace FileProcessor.FileImportLogAggregate.Tests { using System.Linq; - using FIleProcessor.Models; + using FileProcessor.Models; using Shouldly; using Testing; diff --git a/FileProcessor.FileImportLogAggregate/FileImportLogAggregate.cs b/FileProcessor.FileImportLogAggregate/FileImportLogAggregate.cs index 7d359ab..29d078e 100644 --- a/FileProcessor.FileImportLogAggregate/FileImportLogAggregate.cs +++ b/FileProcessor.FileImportLogAggregate/FileImportLogAggregate.cs @@ -1,4 +1,5 @@ using System; +using FileProcessor.Models; namespace FileProcessor.FileImportLogAggregate { @@ -6,7 +7,7 @@ namespace FileProcessor.FileImportLogAggregate using System.Diagnostics.CodeAnalysis; using System.Linq; using FileImportLog.DomainEvents; - using FIleProcessor.Models; + using FileProcessor.Models; using Microsoft.AspNetCore.Mvc.Rendering; using Shared.DomainDrivenDesign.EventSourcing; using Shared.EventStore.Aggregate; @@ -63,9 +64,9 @@ public static void PlayEvent(this FileImportLogAggregate aggregate, FileAddedToI }); } - public static FileImportLog GetFileImportLog(this FileImportLogAggregate aggregate) + public static Models.FileImportLog GetFileImportLog(this FileImportLogAggregate aggregate) { - return new FileImportLog + return new Models.FileImportLog { EstateId = aggregate.EstateId, FileImportLogId = aggregate.AggregateId, diff --git a/FileProcessor.FileImportLogAggregate/FileProcessor.FileImportLogAggregate.csproj b/FileProcessor.FileImportLogAggregate/FileProcessor.FileImportLogAggregate.csproj index 5e034cc..30e3de3 100644 --- a/FileProcessor.FileImportLogAggregate/FileProcessor.FileImportLogAggregate.csproj +++ b/FileProcessor.FileImportLogAggregate/FileProcessor.FileImportLogAggregate.csproj @@ -6,7 +6,7 @@ - + diff --git a/FileProcessor.IntegrationTesting.Helpers/FileProcessor.IntegrationTesting.Helpers.csproj b/FileProcessor.IntegrationTesting.Helpers/FileProcessor.IntegrationTesting.Helpers.csproj index 4a0dfcd..e092764 100644 --- a/FileProcessor.IntegrationTesting.Helpers/FileProcessor.IntegrationTesting.Helpers.csproj +++ b/FileProcessor.IntegrationTesting.Helpers/FileProcessor.IntegrationTesting.Helpers.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/FileProcessor.IntegrationTesting.Helpers/FileProcessorSteps.cs b/FileProcessor.IntegrationTesting.Helpers/FileProcessorSteps.cs index a38b99d..513364a 100644 --- a/FileProcessor.IntegrationTesting.Helpers/FileProcessorSteps.cs +++ b/FileProcessor.IntegrationTesting.Helpers/FileProcessorSteps.cs @@ -51,15 +51,12 @@ await Retry.For(async () => return fileId; } - public async Task GivenIUploadThisFileForProcessingAnErrorShouldBeReturnedIndicatingTheFileIsADuplicate(String accessToken, String filePath, Byte[] fileData, UploadFileRequest uploadFileRequest) - { - Should.Throw(async () => { - await this.FileProcessorClient.UploadFile(accessToken, - Path.GetFileName(filePath), - fileData, - uploadFileRequest, - CancellationToken.None); - }); + public async Task GivenIUploadThisFileForProcessingAnErrorShouldBeReturnedIndicatingTheFileIsADuplicate(String accessToken, + String filePath, + Byte[] fileData, + UploadFileRequest uploadFileRequest) { + var result = await this.FileProcessorClient.UploadFile(accessToken, Path.GetFileName(filePath), fileData, uploadFileRequest, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); } public async Task WhenIGetTheImportLogsBetweenAndTheFollowingDataIsReturned(String accessToken, String startDateString, String endDateString, String estateName, List estateDetailsList, List<(DateTime, Int32)> expectedImportLogs) diff --git a/FileProcessor.IntegrationTests/Common/DockerHelper.cs b/FileProcessor.IntegrationTests/Common/DockerHelper.cs index b68b23b..fd4909e 100644 --- a/FileProcessor.IntegrationTests/Common/DockerHelper.cs +++ b/FileProcessor.IntegrationTests/Common/DockerHelper.cs @@ -115,7 +115,7 @@ public override async Task StartContainersForScenarioRun(String scenarioName, Do } }; HttpClient httpClient = new HttpClient(httpMessageHandler); - this.EstateClient = new EstateClient(EstateManagementBaseAddressResolver, httpClient); + this.EstateClient = new EstateClient(EstateManagementBaseAddressResolver, httpClient, 2); this.SecurityServiceClient = new SecurityServiceClient(SecurityServiceBaseAddressResolver, httpClient); this.FileProcessorClient = new FileProcessorClient(FileProcessorBaseAddressResolver, httpClient); this.TransactionProcessorClient = new TransactionProcessorClient(TransactionProcessorBaseAddressResolver, httpClient); diff --git a/FileProcessor.IntegrationTests/FileProcessor.IntegrationTests.csproj b/FileProcessor.IntegrationTests/FileProcessor.IntegrationTests.csproj index 6d261e8..1166ea2 100644 --- a/FileProcessor.IntegrationTests/FileProcessor.IntegrationTests.csproj +++ b/FileProcessor.IntegrationTests/FileProcessor.IntegrationTests.csproj @@ -11,12 +11,12 @@ - + - + - + @@ -26,11 +26,11 @@ - - + + - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/FileProcessor.IntegrationTests/Steps/SharedSteps.cs b/FileProcessor.IntegrationTests/Steps/SharedSteps.cs index f0ebac0..a465e85 100644 --- a/FileProcessor.IntegrationTests/Steps/SharedSteps.cs +++ b/FileProcessor.IntegrationTests/Steps/SharedSteps.cs @@ -210,6 +210,11 @@ public async Task GivenICreateAContractWithTheFollowingValues(DataTable table) var estates = this.TestingContext.Estates.Select(e => e.EstateDetails).ToList(); List<(EstateDetails, CreateContractRequest)> requests = table.Rows.ToCreateContractRequests(estates); List responses = await this.EstateManagementSteps.GivenICreateAContractWithTheFollowingValues(this.TestingContext.AccessToken, requests); + foreach (ContractResponse contractResponse in responses) + { + EstateDetails1 estate = this.TestingContext.Estates.Single(e => e.EstateDetails.EstateId == contractResponse.EstateId); + estate.EstateDetails.AddContract(contractResponse.ContractId, contractResponse.Description, contractResponse.OperatorId); + } } [When(@"I create the following Products")] diff --git a/FileProcessor.Testing/TestData.cs b/FileProcessor.Testing/TestData.cs index d52be70..7467601 100644 --- a/FileProcessor.Testing/TestData.cs +++ b/FileProcessor.Testing/TestData.cs @@ -13,7 +13,7 @@ namespace FileProcessor.Testing using FileImportLog.DomainEvents; using FileAggregate; using FileImportLogAggregate; - using FIleProcessor.Models; + using FileProcessor.Models; using Newtonsoft.Json; using SecurityService.DataTransferObjects.Responses; using TransactionProcessor.DataTransferObjects; @@ -598,72 +598,72 @@ public static List GetMerchantContractsResponseNoNullValueProd SuccessfullyProcessedLines = 4, RejectedLines = 1 }, - FileLines = new List + FileLines = new List { - new FIleProcessor.Models.FileLine + new FileProcessor.Models.FileLine { ProcessingResult = ProcessingResult.Ignored, LineNumber = 1, LineData = "H", TransactionId = Guid.Empty }, - new FIleProcessor.Models.FileLine + new FileProcessor.Models.FileLine { ProcessingResult = ProcessingResult.Successful, LineNumber = 2, LineData = TestData.GetSafaricomDetailLine("2","200"), TransactionId = Guid.NewGuid() }, - new FIleProcessor.Models.FileLine + new FileProcessor.Models.FileLine { ProcessingResult = ProcessingResult.Successful, LineNumber = 3, LineData = TestData.GetSafaricomDetailLine("3","300"), TransactionId = Guid.NewGuid() }, - new FIleProcessor.Models.FileLine + new FileProcessor.Models.FileLine { ProcessingResult = ProcessingResult.Successful, LineNumber = 4, LineData = TestData.GetSafaricomDetailLine("4","400"), TransactionId = Guid.NewGuid() }, - new FIleProcessor.Models.FileLine + new FileProcessor.Models.FileLine { ProcessingResult = ProcessingResult.Successful, LineNumber = 5, LineData = TestData.GetSafaricomDetailLine("5","500"), TransactionId = Guid.NewGuid() }, - new FIleProcessor.Models.FileLine + new FileProcessor.Models.FileLine { ProcessingResult = ProcessingResult.Failed, LineNumber = 6, LineData = TestData.GetSafaricomDetailLine("6","600"), TransactionId = Guid.Empty }, - new FIleProcessor.Models.FileLine + new FileProcessor.Models.FileLine { ProcessingResult = ProcessingResult.NotProcessed, LineNumber = 7, LineData = TestData.GetSafaricomDetailLine("7","700"), TransactionId = Guid.Empty }, - new FIleProcessor.Models.FileLine + new FileProcessor.Models.FileLine { ProcessingResult = ProcessingResult.Rejected, LineNumber = 8, LineData = TestData.GetSafaricomDetailLine("7","700"), TransactionId = Guid.Empty }, - new FIleProcessor.Models.FileLine + new FileProcessor.Models.FileLine { ProcessingResult = (ProcessingResult)99, // Invalid status LineNumber = 9, LineData = TestData.GetSafaricomDetailLine("8","800"), TransactionId = Guid.Empty }, - new FIleProcessor.Models.FileLine + new FileProcessor.Models.FileLine { ProcessingResult = ProcessingResult.Ignored, LineNumber = 10, @@ -680,15 +680,15 @@ public static List GetMerchantContractsResponseNoNullValueProd TestData.FileImportLog2 }; - public static List FileImportLogModels => - new List + public static List FileImportLogModels => + new List { TestData.FileImportLogModel1, TestData.FileImportLogModel2 }; - public static FIleProcessor.Models.FileImportLog FileImportLogModel1 => - new FIleProcessor.Models.FileImportLog + public static FileProcessor.Models.FileImportLog FileImportLogModel1 => + new FileProcessor.Models.FileImportLog { Files = TestData.FileImportLogModel1Files, FileImportLogId = TestData.FileImportLogId1, @@ -723,8 +723,8 @@ public static List GetMerchantContractsResponseNoNullValueProd } }; - public static FIleProcessor.Models.FileImportLog FileImportLogModel2 => - new FIleProcessor.Models.FileImportLog + public static FileProcessor.Models.FileImportLog FileImportLogModel2 => + new FileProcessor.Models.FileImportLog { Files = FileImportLogModel2Files, FileImportLogId = TestData.FileImportLogId2, @@ -851,15 +851,15 @@ public static List GetMerchantContractsResponseNoNullValueProd }; - public static UploadFileRequest UploadFileRequest => - new UploadFileRequest(TestData.EstateId, TestData.MerchantId, TestData.UserId, TestData.FilePath, TestData.FileProfileId, TestData.FileUploadedDateTime); - - public static ProcessUploadedFileRequest ProcessUploadedFileRequest => - new ProcessUploadedFileRequest(TestData.EstateId, TestData.MerchantId, TestData.FileImportLogId, TestData.FileId, TestData.UserId, TestData.FilePath, TestData.FileProfileId, + public static FileCommands.UploadFileCommand UploadFileCommand => + new (TestData.EstateId, TestData.MerchantId, TestData.UserId, FilePathWithName, TestData.FileProfileId, TestData.FileUploadedDateTime); + + public static FileCommands.ProcessUploadedFileCommand ProcessUploadedFileCommand => + new (TestData.EstateId, TestData.MerchantId, TestData.FileImportLogId, TestData.FileId, TestData.UserId, TestData.FilePathWithName, TestData.FileProfileId, TestData.FileUploadedDateTime); - public static ProcessTransactionForFileLineRequest ProcessTransactionForFileLineRequest => - new ProcessTransactionForFileLineRequest(TestData.FileId, TestData.LineNumber, TestData.FileLine); + public static FileCommands.ProcessTransactionForFileLineCommand ProcessTransactionForFileLineCommand => + new (TestData.FileId, TestData.LineNumber, TestData.FileLine); } } diff --git a/FileProcessor.Tests/ModelFactoryTests.cs b/FileProcessor.Tests/ModelFactoryTests.cs index 71e1376..97aa23a 100644 --- a/FileProcessor.Tests/ModelFactoryTests.cs +++ b/FileProcessor.Tests/ModelFactoryTests.cs @@ -8,21 +8,21 @@ namespace FileProcessor.Tests { using Common; using DataTransferObjects.Responses; - using FIleProcessor.Models; + using FileProcessor.Models; using Microsoft.EntityFrameworkCore.Infrastructure; using Shouldly; using Testing; using Xunit; - using FileDetails = FIleProcessor.Models.FileDetails; - using FileImportLog = FIleProcessor.Models.FileImportLog; - using FileLine = FIleProcessor.Models.FileLine; + using FileDetails = FileProcessor.Models.FileDetails; + using FileImportLog = FileProcessor.Models.FileImportLog; + using FileLine = FileProcessor.Models.FileLine; public class ModelFactoryTests { [Fact] public void ModelFactory_ConvertFrom_FileImportLogList_IsConverted() { - List importLogs = TestData.FileImportLogModels; + List importLogs = TestData.FileImportLogModels; ModelFactory modelFactory = new ModelFactory(); @@ -34,7 +34,7 @@ public void ModelFactory_ConvertFrom_FileImportLogList_IsConverted() [Fact] public void ModelFactory_ConvertFrom_FileImportLogList_WithNoFiles_IsConverted() { - List importLogs = TestData.FileImportLogModels; + List importLogs = TestData.FileImportLogModels; foreach (FileImportLog fileImportLog in importLogs) { @@ -51,7 +51,7 @@ public void ModelFactory_ConvertFrom_FileImportLogList_WithNoFiles_IsConverted() [Fact] public void ModelFactory_ConvertFrom_FileImportLog_IsConverted() { - FIleProcessor.Models.FileImportLog importLog = TestData.FileImportLogModel1; + FileProcessor.Models.FileImportLog importLog = TestData.FileImportLogModel1; ModelFactory modelFactory = new ModelFactory(); @@ -63,7 +63,7 @@ public void ModelFactory_ConvertFrom_FileImportLog_IsConverted() [Fact] public void ModelFactory_ConvertFrom_FileImportLog_WithNoFiles_IsConverted() { - FIleProcessor.Models.FileImportLog importLog = TestData.FileImportLogModel1; + FileProcessor.Models.FileImportLog importLog = TestData.FileImportLogModel1; importLog.Files = new List(); ModelFactory modelFactory = new ModelFactory(); @@ -130,7 +130,7 @@ private void VerifyFileDetails(FileDetails source, } } - private void VerifyFileImportLogList(List source, FileImportLogList fileImportLogList) + private void VerifyFileImportLogList(List source, FileImportLogList fileImportLogList) { fileImportLogList.ShouldNotBeNull(); fileImportLogList.FileImportLogs.ShouldNotBeNull(); @@ -143,7 +143,7 @@ private void VerifyFileImportLogList(List so } } - private void VerifyFileImportLog(FIleProcessor.Models.FileImportLog source, + private void VerifyFileImportLog(FileProcessor.Models.FileImportLog source, DataTransferObjects.Responses.FileImportLog fileImportLog) { fileImportLog.ShouldNotBeNull(); diff --git a/FileProcessor/Bootstrapper/ClientRegistry.cs b/FileProcessor/Bootstrapper/ClientRegistry.cs index 3c7492e..c09c57a 100644 --- a/FileProcessor/Bootstrapper/ClientRegistry.cs +++ b/FileProcessor/Bootstrapper/ClientRegistry.cs @@ -20,11 +20,16 @@ public class ClientRegistry : ServiceRegistry /// public ClientRegistry() { this.AddSingleton(); - this.AddSingleton(); + //this.AddSingleton(); + this.AddSingleton(); - this.AddSingleton>(container => serviceName => { return ConfigurationReader.GetBaseServerUri(serviceName).OriginalString; }); + //this.AddSingleton>(container => serviceName => { return ConfigurationReader.GetBaseServerUri(serviceName).OriginalString; }); + Func resolver(IServiceProvider container) => serviceName => { return ConfigurationReader.GetBaseServerUri(serviceName).OriginalString; }; + Func resolver1() => serviceName => { return ConfigurationReader.GetBaseServerUri(serviceName).OriginalString; }; + this.AddSingleton>(resolver); + SocketsHttpHandler httpMessageHandler = new SocketsHttpHandler { SslOptions = { RemoteCertificateValidationCallback = (sender, @@ -36,6 +41,8 @@ public ClientRegistry() { HttpClient httpClient = new(httpMessageHandler); this.AddSingleton(httpClient); + + this.AddSingleton(new EstateClient(resolver1(), httpClient, 2)); } #endregion diff --git a/FileProcessor/Bootstrapper/FileRegistry.cs b/FileProcessor/Bootstrapper/FileRegistry.cs index a9855ef..85e01ee 100644 --- a/FileProcessor/Bootstrapper/FileRegistry.cs +++ b/FileProcessor/Bootstrapper/FileRegistry.cs @@ -6,7 +6,7 @@ using System.IO.Abstractions; using System.Linq; using BusinessLogic.FileFormatHandlers; -using FIleProcessor.Models; +using FileProcessor.Models; using Lamar; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; diff --git a/FileProcessor/Bootstrapper/MediatorRegistry.cs b/FileProcessor/Bootstrapper/MediatorRegistry.cs index 207e013..b2f9f48 100644 --- a/FileProcessor/Bootstrapper/MediatorRegistry.cs +++ b/FileProcessor/Bootstrapper/MediatorRegistry.cs @@ -1,4 +1,8 @@ -namespace FileProcessor.Bootstrapper; +using System.Collections.Generic; +using FileProcessor.Models; +using SimpleResults; + +namespace FileProcessor.Bootstrapper; using System; using System.Diagnostics.CodeAnalysis; @@ -21,11 +25,13 @@ public MediatorRegistry() this.AddSingleton(); // request & notification handlers - this.AddSingleton, FileRequestHandler>(); - this.AddSingleton, FileRequestHandler>(); - //this.AddSingleton, FileRequestHandler>(); - //this.AddSingleton, FileRequestHandler>(); - this.AddSingleton, FileRequestHandler>(); + this.AddSingleton, FileRequestHandler>(); + this.AddSingleton, FileRequestHandler>(); + this.AddSingleton>, FileRequestHandler>(); + + this.AddSingleton>, FileRequestHandler>(); + this.AddSingleton>, FileRequestHandler>(); + this.AddSingleton>>, FileRequestHandler>(); } #endregion diff --git a/FileProcessor/Common/Extensions.cs b/FileProcessor/Common/Extensions.cs index f81d331..deadea3 100644 --- a/FileProcessor/Common/Extensions.cs +++ b/FileProcessor/Common/Extensions.cs @@ -1,3 +1,5 @@ +using SimpleResults; + namespace FileProcessor.Common; using System; @@ -10,7 +12,7 @@ namespace FileProcessor.Common; using System.Threading.Tasks; using EventStore.Client; using FileProcessor.BusinessLogic.Managers; -using FIleProcessor.Models; +using FileProcessor.Models; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -68,8 +70,14 @@ public static void PreWarm(this IApplicationBuilder applicationBuilder){ fileSystem.Directory.CreateDirectory(temporaryFileLocation); Logger.LogInformation($"Created TemporaryFileLocation at [{temporaryFileLocation}]"); - var fileProfiles = fileProcessorManager.GetAllFileProfiles(CancellationToken.None).Result; + Result> fileProfilesResult = fileProcessorManager.GetAllFileProfiles(CancellationToken.None).Result; + + if (fileProfilesResult.IsFailed) { + Logger.LogWarning($"Error getting file profiles {fileProfilesResult.Message}"); + throw new Exception(fileProfilesResult.Message); + } + List fileProfiles = fileProfilesResult.Data; foreach (FileProfile fileProfile in fileProfiles){ fileSystem.Directory.CreateDirectory($"{fileProfile.ListeningDirectory}//inprogress"); Logger.LogInformation($"Created in progress at [{fileProfile.ListeningDirectory}//inprogress"); diff --git a/FileProcessor/Common/IModelFactory.cs b/FileProcessor/Common/IModelFactory.cs index f86f42a..205bd58 100644 --- a/FileProcessor/Common/IModelFactory.cs +++ b/FileProcessor/Common/IModelFactory.cs @@ -2,9 +2,6 @@ { using System.Collections.Generic; using DataTransferObjects.Responses; - using FIleProcessor.Models; - using FileDetails = FIleProcessor.Models.FileDetails; - using FileImportLog = FIleProcessor.Models.FileImportLog; using FileImportLogResponse = DataTransferObjects.Responses.FileImportLog; using FileDetailsResponse = DataTransferObjects.Responses.FileDetails; @@ -20,21 +17,21 @@ public interface IModelFactory /// /// The import logs. /// - FileImportLogList ConvertFrom(List importLogs); + FileImportLogList ConvertFrom(List importLogs); /// /// Converts from. /// /// The file import log. /// - FileImportLogResponse ConvertFrom(FileImportLog fileImportLog); + FileImportLogResponse ConvertFrom(Models.FileImportLog fileImportLog); /// /// Converts from. /// /// The file details. /// - FileDetailsResponse ConvertFrom(FileDetails fileDetails); + FileDetailsResponse ConvertFrom(Models.FileDetails fileDetails); #endregion } diff --git a/FileProcessor/Common/ModelFactory.cs b/FileProcessor/Common/ModelFactory.cs index f38d577..340e7ed 100644 --- a/FileProcessor/Common/ModelFactory.cs +++ b/FileProcessor/Common/ModelFactory.cs @@ -1,12 +1,10 @@ -namespace FileProcessor.Common +using FileProcessor.Models; + +namespace FileProcessor.Common { using System.Collections.Generic; using System.Linq; using DataTransferObjects.Responses; - using FIleProcessor.Models; - using FileDetails = FIleProcessor.Models.FileDetails; - using FileImportLog = FIleProcessor.Models.FileImportLog; - using FileLine = FIleProcessor.Models.FileLine; using FileImportLogResponse = DataTransferObjects.Responses.FileImportLog; using FileDetailsResponse = DataTransferObjects.Responses.FileDetails; using FileLineResponse = DataTransferObjects.Responses.FileLine; @@ -24,11 +22,11 @@ public class ModelFactory : IModelFactory /// /// The file import logs. /// - public FileImportLogList ConvertFrom(List fileImportLogs) + public FileImportLogList ConvertFrom(List fileImportLogs) { FileImportLogList result = new FileImportLogList(); result.FileImportLogs = new List(); - foreach (FileImportLog fileImportLog in fileImportLogs) + foreach (Models.FileImportLog fileImportLog in fileImportLogs) { result.FileImportLogs.Add(this.ConvertFrom(fileImportLog)); } @@ -41,7 +39,7 @@ public FileImportLogList ConvertFrom(List fileImportLogs) /// /// The file import log. /// - public FileImportLogResponse ConvertFrom(FileImportLog fileImportLog) + public FileImportLogResponse ConvertFrom(Models.FileImportLog fileImportLog) { FileImportLogResponse fileImportLogResponse = new FileImportLogResponse { @@ -63,7 +61,7 @@ public FileImportLogResponse ConvertFrom(FileImportLog fileImportLog) return fileImportLogResponse; } - public FileDetailsResponse ConvertFrom(FileDetails fileDetails) + public FileDetailsResponse ConvertFrom(Models.FileDetails fileDetails) { FileDetailsResponse fileDetailsResponse = new FileDetailsResponse { @@ -81,7 +79,7 @@ public FileDetailsResponse ConvertFrom(FileDetails fileDetails) FileLines = new List() }; - foreach (FileLine fileDetailsFileLine in fileDetails.FileLines) + foreach (Models.FileLine fileDetailsFileLine in fileDetails.FileLines) { fileDetailsResponse.FileLines.Add(new FileLineResponse { diff --git a/FileProcessor/Controllers/FileController.cs b/FileProcessor/Controllers/FileController.cs index 446935c..38eeab4 100644 --- a/FileProcessor/Controllers/FileController.cs +++ b/FileProcessor/Controllers/FileController.cs @@ -1,24 +1,23 @@ -namespace FileProcessor.Controllers +using FileProcessor.BusinessLogic.Requests; +using Shared.EventStore.Aggregate; +using SimpleResults; + +namespace FileProcessor.Controllers { using System; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; - using System.Net.Http; using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; - using BusinessLogic.Managers; using Common; using DataTransferObjects; - using FIleProcessor.Models; + using Models; using MediatR; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; - using Newtonsoft.Json; - using NLog; - using SecurityService.Client; using Shared.General; /// @@ -38,10 +37,6 @@ public class FileController : ControllerBase /// private readonly IMediator Mediator; - /// - /// The manager - /// - private readonly IFileProcessorManager Manager; private readonly IModelFactory ModelFactory; @@ -54,10 +49,9 @@ public class FileController : ControllerBase /// /// The mediator. /// The manager. - public FileController(IMediator mediator, IFileProcessorManager manager, IModelFactory modelFactory) + public FileController(IMediator mediator, IModelFactory modelFactory) { this.Mediator = mediator; - this.Manager = manager; this.ModelFactory = modelFactory; } @@ -98,16 +92,16 @@ public async Task UploadFile([FromForm] UploadFileRequest request } // Create a command with the file in it - BusinessLogic.Requests.UploadFileRequest uploadFileRequest = - new BusinessLogic.Requests.UploadFileRequest(request.EstateId, request.MerchantId, request.UserId, fullPath, request.FileProfileId, request.UploadDateTime); + FileCommands.UploadFileCommand command = + new (request.EstateId, request.MerchantId, request.UserId, fullPath, request.FileProfileId, request.UploadDateTime); - Guid fileId = await this.Mediator.Send(uploadFileRequest, cancellationToken); + Result result= await this.Mediator.Send(command, cancellationToken); Shared.Logger.Logger.LogDebug($"Day is {request.UploadDateTime.Day}"); Shared.Logger.Logger.LogDebug($"Month is {request.UploadDateTime.Month}"); Shared.Logger.Logger.LogDebug($"Year is {request.UploadDateTime.Year}"); - return this.Accepted(fileId); + return result.ToActionResultX(); } /// @@ -122,9 +116,18 @@ public async Task UploadFile([FromForm] UploadFileRequest request public async Task GetFile([FromRoute] Guid fileId, [FromQuery] Guid estateId, CancellationToken cancellationToken) { - FileDetails fileDetailsModel = await this.Manager.GetFile(fileId, estateId, cancellationToken); + //FileDetails fileDetailsModel = await this.Manager.GetFile(fileId, estateId, cancellationToken); + FileQueries.GetFileQuery query = new FileQueries.GetFileQuery(fileId, estateId); + + Result result = await this.Mediator.Send(query, cancellationToken); + + if (result.IsFailed) + return ResultHelpers.CreateFailure(result).ToActionResultX(); + + var response = this.ModelFactory.ConvertFrom(result.Data); + + return Result.Success(response).ToActionResultX(); - return this.Ok(this.ModelFactory.ConvertFrom(fileDetailsModel)); } #endregion diff --git a/FileProcessor/Controllers/FileImportLogController.cs b/FileProcessor/Controllers/FileImportLogController.cs index 925ae03..3106e77 100644 --- a/FileProcessor/Controllers/FileImportLogController.cs +++ b/FileProcessor/Controllers/FileImportLogController.cs @@ -1,15 +1,21 @@ -namespace FileProcessor.Controllers +using FileProcessor.BusinessLogic.Requests; +using FileProcessor.DataTransferObjects.Responses; +using MediatR; +using Shared.EventStore.Aggregate; +using SimpleResults; + +namespace FileProcessor.Controllers { using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Threading; using System.Threading.Tasks; - using BusinessLogic.Managers; using Common; - using FIleProcessor.Models; + using Models; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; + using static Microsoft.EntityFrameworkCore.DbLoggerCategory; /// /// @@ -22,11 +28,8 @@ public class FileImportLogController : ControllerBase { #region Fields - - /// - /// The manager - /// - private readonly IFileProcessorManager Manager; + + private readonly IMediator Mediator; /// /// The model factory @@ -42,10 +45,10 @@ public class FileImportLogController : ControllerBase /// /// The manager. /// The model factory. - public FileImportLogController(IFileProcessorManager manager, - IModelFactory modelFactory) + public FileImportLogController(IMediator mediator, + IModelFactory modelFactory) { - this.Manager = manager; + this.Mediator = mediator; this.ModelFactory = modelFactory; } @@ -67,11 +70,17 @@ public async Task GetImportLogs([FromQuery] Guid estateId, [FromQuery] DateTime startDateTime, [FromQuery] DateTime endDateTime, [FromQuery] Guid? merchantId, - CancellationToken cancellationToken) - { - List fileImportLogs = await this.Manager.GetFileImportLogs(estateId, startDateTime, endDateTime, merchantId, cancellationToken); + CancellationToken cancellationToken) { + FileQueries.GetImportLogsQuery query = new(estateId, startDateTime, endDateTime, merchantId); + + Result> result = await this.Mediator.Send(query, cancellationToken); + + if (result.IsFailed) + return ResultHelpers.CreateFailure(result).ToActionResultX(); - return this.Ok(this.ModelFactory.ConvertFrom(fileImportLogs)); + FileImportLogList response = this.ModelFactory.ConvertFrom(result.Data); + + return Result.Success(response).ToActionResultX(); } [HttpGet] @@ -81,18 +90,25 @@ public async Task GetImportLog([FromRoute] Guid fileImportLogId, [FromQuery] Guid? merchantId, CancellationToken cancellationToken) { - FileImportLog fileImportLog = await this.Manager.GetFileImportLog(fileImportLogId, estateId, merchantId, cancellationToken); + FileQueries.GetImportLogQuery query = new(fileImportLogId, estateId, merchantId); + + Result result = await this.Mediator.Send(query, cancellationToken); + + if (result.IsFailed) + return ResultHelpers.CreateFailure(result).ToActionResultX(); - return this.Ok(this.ModelFactory.ConvertFrom(fileImportLog)); + DataTransferObjects.Responses.FileImportLog response = this.ModelFactory.ConvertFrom(result.Data); + + return Result.Success(response).ToActionResultX(); } #endregion - #region Others + #region Others - /// - /// The controller name - /// + /// + /// The controller name + /// public const String ControllerName = "fileImportLogs"; /// diff --git a/FileProcessor/Controllers/ResultExtensions.cs b/FileProcessor/Controllers/ResultExtensions.cs new file mode 100644 index 0000000..1e22c9e --- /dev/null +++ b/FileProcessor/Controllers/ResultExtensions.cs @@ -0,0 +1,61 @@ +using System; +using System.Net; +using Microsoft.AspNetCore.Mvc; +using SimpleResults; + +public static class ResultExtensions +{ + public static IActionResult ToActionResultX(this Result result) + { + if (result.IsSuccess) + return new OkObjectResult(result); + + return result.Status switch + { + ResultStatus.Invalid => new BadRequestObjectResult(result), + ResultStatus.NotFound => new NotFoundObjectResult(result), + ResultStatus.Unauthorized => new UnauthorizedObjectResult(result), + ResultStatus.Conflict => new ConflictObjectResult(result), + ResultStatus.Failure => CreateObjectResult(result, HttpStatusCode.InternalServerError), + ResultStatus.CriticalError => CreateObjectResult(result, HttpStatusCode.InternalServerError), + ResultStatus.Forbidden => new ForbidResult(), + _ => CreateObjectResult(result, HttpStatusCode.NotImplemented) + + }; + } + + internal static IActionResult ToActionResultX(this Result result) + { + if (result.IsSuccess) + return new OkObjectResult(result); + + return result.Status switch + { + ResultStatus.Invalid => new BadRequestObjectResult(result), + ResultStatus.NotFound => new NotFoundObjectResult(result), + ResultStatus.Unauthorized => new UnauthorizedObjectResult(result), + ResultStatus.Conflict => new ConflictObjectResult(result), + ResultStatus.Failure => CreateObjectResult(result, HttpStatusCode.InternalServerError), + ResultStatus.CriticalError => CreateObjectResult(result, HttpStatusCode.InternalServerError), + ResultStatus.Forbidden => new ForbidResult(), + _ => CreateObjectResult(result, HttpStatusCode.NotImplemented) + + }; + } + + internal static ObjectResult CreateObjectResult(Result result, + HttpStatusCode statusCode) + { + ObjectResult or = new ObjectResult(result); + or.StatusCode = (Int32)statusCode; + return or; + } + + internal static ObjectResult CreateObjectResult(Result result, + HttpStatusCode statusCode) + { + ObjectResult or = new ObjectResult(result); + or.StatusCode = (Int32)statusCode; + return or; + } +} \ No newline at end of file diff --git a/FileProcessor/FileProcessor.csproj b/FileProcessor/FileProcessor.csproj index ebb89f5..bd58aa5 100644 --- a/FileProcessor/FileProcessor.csproj +++ b/FileProcessor/FileProcessor.csproj @@ -18,7 +18,7 @@ - + diff --git a/FileProcessor/Program.cs b/FileProcessor/Program.cs index ea8652e..e2ebb86 100644 --- a/FileProcessor/Program.cs +++ b/FileProcessor/Program.cs @@ -55,49 +55,8 @@ public static IHostBuilder CreateHostBuilder(string[] args) webBuilder.UseConfiguration(config); webBuilder.UseKestrel(); }); - //hostBuilder.ConfigureServices(services => - // { - // services.AddHostedService(provider => - // { - // IFileProcessorManager fileProcessorManager = - // provider.GetRequiredService(); - // IMediator mediator = provider.GetRequiredService(); - // IFileSystem fileSystem = provider.GetRequiredService(); - // FileProcessingWorker worker = - // new FileProcessingWorker(fileProcessorManager, - // mediator, - // fileSystem); - // worker.TraceGenerated += Worker_TraceGenerated; - // return worker; - // }); - // }); return hostBuilder; } - - private static void Worker_TraceGenerated(string trace, LogLevel logLevel) - { - switch (logLevel) - { - case LogLevel.Trace: - Logger.LogTrace(trace); - break; - case LogLevel.Debug: - Logger.LogDebug(trace); - break; - case LogLevel.Information: - Logger.LogInformation(trace); - break; - case LogLevel.Warning: - Logger.LogWarning(trace); - break; - case LogLevel.Error: - Logger.LogError(new Exception(trace)); - break; - case LogLevel.Critical: - Logger.LogCritical(new Exception(trace)); - break; - } - } } } diff --git a/FileProcessor/Startup.cs b/FileProcessor/Startup.cs index 023c6fe..ef4eada 100644 --- a/FileProcessor/Startup.cs +++ b/FileProcessor/Startup.cs @@ -27,7 +27,7 @@ namespace FileProcessor using EventStore.Client; using File.DomainEvents; using FileImportLog.DomainEvents; - using FIleProcessor.Models; + using FileProcessor.Models; using HealthChecks.UI.Client; using JasperFx.Core; using Lamar;