From cc179f3840dec0a98169bafc8577c77d28932e9d Mon Sep 17 00:00:00 2001 From: Stuart Ferguson Date: Mon, 12 Jun 2023 20:16:31 +0100 Subject: [PATCH] Aggregate refactoring and nuget updates --- .../FileProcessor.BusinessLogic.Tests.csproj | 16 +- .../FileProcessor.BusinessLogic.csproj | 22 +- .../RequestHandlers/FileRequestHandler.cs | 16 +- .../FileProcessor.Client.csproj | 2 +- .../FileProcessor.DataTransferObjects.csproj | 2 +- .../FileProcessor.DomainEvents.Tests.csproj | 10 +- .../FileProcessor.File.DomainEvents.csproj | 2 +- .../FileProcessor.FileAggregate.Tests.csproj | 8 +- FileProcessor.FileAggregate/FileAggregate.cs | 437 +++++++----------- .../FileProcessor.FileAggregate.csproj | 6 +- ...rocessor.FileImportLog.DomainEvents.csproj | 2 +- ...cessor.FileImportLogAggregate.Tests.csproj | 8 +- .../FileImportLogAggregate.cs | 216 +++------ ...ileProcessor.FileImportLogAggregate.csproj | 4 +- .../FileProcessor.IntegrationTests.csproj | 24 +- .../FileProcessor.Tests.csproj | 12 +- .../Bootstrapper/MediatorRegistry.cs | 9 +- FileProcessor/FileProcessor.csproj | 37 +- FileProcessor/Startup.cs | 2 +- 19 files changed, 323 insertions(+), 512 deletions(-) diff --git a/FileProcessor.BusinessLogic.Tests/FileProcessor.BusinessLogic.Tests.csproj b/FileProcessor.BusinessLogic.Tests/FileProcessor.BusinessLogic.Tests.csproj index b42a355..d9641c4 100644 --- a/FileProcessor.BusinessLogic.Tests/FileProcessor.BusinessLogic.Tests.csproj +++ b/FileProcessor.BusinessLogic.Tests/FileProcessor.BusinessLogic.Tests.csproj @@ -7,18 +7,18 @@ - - - - - - - + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/FileProcessor.BusinessLogic/FileProcessor.BusinessLogic.csproj b/FileProcessor.BusinessLogic/FileProcessor.BusinessLogic.csproj index 1eb0fcc..3b17b10 100644 --- a/FileProcessor.BusinessLogic/FileProcessor.BusinessLogic.csproj +++ b/FileProcessor.BusinessLogic/FileProcessor.BusinessLogic.csproj @@ -5,18 +5,18 @@ - - + + - - - - - - - - - + + + + + + + + + diff --git a/FileProcessor.BusinessLogic/RequestHandlers/FileRequestHandler.cs b/FileProcessor.BusinessLogic/RequestHandlers/FileRequestHandler.cs index 2d98054..de26642 100644 --- a/FileProcessor.BusinessLogic/RequestHandlers/FileRequestHandler.cs +++ b/FileProcessor.BusinessLogic/RequestHandlers/FileRequestHandler.cs @@ -59,31 +59,25 @@ public async Task Handle(UploadFileRequest request, return await this.DomainService.UploadFile(request, cancellationToken); } - public async Task Handle(ProcessUploadedFileRequest request, CancellationToken cancellationToken) + public async Task Handle(ProcessUploadedFileRequest request, CancellationToken cancellationToken) { await this.DomainService.ProcessUploadedFile(request, cancellationToken); - - return new Unit(); + } - public async Task Handle(SafaricomTopupRequest request, + public async Task Handle(SafaricomTopupRequest request, CancellationToken cancellationToken) { await this.DomainService.ProcessSafaricomTopup(request, cancellationToken); - - return new Unit(); } - public async Task Handle(ProcessTransactionForFileLineRequest request, + public async Task Handle(ProcessTransactionForFileLineRequest request, CancellationToken cancellationToken) { await this.DomainService.ProcessTransactionForFileLine(request, cancellationToken); - return new Unit(); } - public async Task Handle(VoucherRequest request, + public async Task Handle(VoucherRequest request, CancellationToken cancellationToken) { await this.DomainService.ProcessVoucher(request, cancellationToken); - - return new Unit(); } } } diff --git a/FileProcessor.Client/FileProcessor.Client.csproj b/FileProcessor.Client/FileProcessor.Client.csproj index 8d7f818..7b46fb7 100644 --- a/FileProcessor.Client/FileProcessor.Client.csproj +++ b/FileProcessor.Client/FileProcessor.Client.csproj @@ -6,7 +6,7 @@ - + diff --git a/FileProcessor.DataTransferObjects/FileProcessor.DataTransferObjects.csproj b/FileProcessor.DataTransferObjects/FileProcessor.DataTransferObjects.csproj index 983cee0..e08d255 100644 --- a/FileProcessor.DataTransferObjects/FileProcessor.DataTransferObjects.csproj +++ b/FileProcessor.DataTransferObjects/FileProcessor.DataTransferObjects.csproj @@ -6,7 +6,7 @@ - + diff --git a/FileProcessor.DomainEvents.Tests/FileProcessor.DomainEvents.Tests.csproj b/FileProcessor.DomainEvents.Tests/FileProcessor.DomainEvents.Tests.csproj index 1f63f57..feac5aa 100644 --- a/FileProcessor.DomainEvents.Tests/FileProcessor.DomainEvents.Tests.csproj +++ b/FileProcessor.DomainEvents.Tests/FileProcessor.DomainEvents.Tests.csproj @@ -7,15 +7,15 @@ - - - - + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/FileProcessor.File.DomainEvents/FileProcessor.File.DomainEvents.csproj b/FileProcessor.File.DomainEvents/FileProcessor.File.DomainEvents.csproj index a4d28a6..3fb6bf5 100644 --- a/FileProcessor.File.DomainEvents/FileProcessor.File.DomainEvents.csproj +++ b/FileProcessor.File.DomainEvents/FileProcessor.File.DomainEvents.csproj @@ -5,7 +5,7 @@ - + diff --git a/FileProcessor.FileAggregate.Tests/FileProcessor.FileAggregate.Tests.csproj b/FileProcessor.FileAggregate.Tests/FileProcessor.FileAggregate.Tests.csproj index ee66ebe..f9d2426 100644 --- a/FileProcessor.FileAggregate.Tests/FileProcessor.FileAggregate.Tests.csproj +++ b/FileProcessor.FileAggregate.Tests/FileProcessor.FileAggregate.Tests.csproj @@ -7,14 +7,14 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/FileProcessor.FileAggregate/FileAggregate.cs b/FileProcessor.FileAggregate/FileAggregate.cs index 2fe9d34..280abec 100644 --- a/FileProcessor.FileAggregate/FileAggregate.cs +++ b/FileProcessor.FileAggregate/FileAggregate.cs @@ -13,393 +13,284 @@ namespace FileProcessor.FileAggregate using Shared.Exceptions; using Shared.General; - /// - /// - /// - /// - public class FileAggregate : Aggregate - { - /// - /// The estate identifier - /// - private Guid EstateId; - - /// - /// The merchant identifier - /// - private Guid MerchantId; - - /// - /// The file profile identifier - /// - private Guid FileProfileId; - - /// - /// The file import log identifier - /// - private Guid FileImportLogId; - - /// - /// The file received date time - /// - private DateTime FileReceivedDateTime; - - /// - /// The user identifier - /// - private Guid UserId; - - /// - /// The file location - /// - private String FileLocation; - - /// - /// The is completed - /// - private Boolean IsCompleted; - - /// - /// Initializes a new instance of the class. - /// - [ExcludeFromCodeCoverage] - public FileAggregate() - { - // Nothing here - this.FileLines = new List(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The aggregate identifier. - private FileAggregate(Guid aggregateId) - { - Guard.ThrowIfInvalidGuid(aggregateId, "Aggregate Id cannot be an Empty Guid"); - - this.AggregateId = aggregateId; - this.FileLines = new List(); - } - - /// - /// Creates the specified aggregate identifier. - /// - /// The aggregate identifier. - /// - public static FileAggregate Create(Guid aggregateId) - { - return new FileAggregate(aggregateId); - } - - /// - /// Gets the metadata. - /// - /// - [ExcludeFromCodeCoverage] - protected override Object GetMetadata() - { - return null; - } - - /// - /// Gets a value indicating whether this instance is created. - /// - /// - /// true if this instance is created; otherwise, false. - /// - public Boolean IsCreated { get; private set; } - - /// - /// Plays the event. - /// - /// The domain event. - public override void PlayEvent(IDomainEvent domainEvent) + public static class FileAggregateExtensions{ + public static void PlayEvent(this FileAggregate aggregate, FileCreatedEvent domainEvent) { - this.PlayEvent((dynamic)domainEvent); + aggregate.IsCreated = true; + aggregate.EstateId = domainEvent.EstateId; + aggregate.MerchantId = domainEvent.MerchantId; + aggregate.FileProfileId = domainEvent.FileProfileId; + aggregate.UserId = domainEvent.UserId; + aggregate.FileLocation = domainEvent.FileLocation; + aggregate.FileImportLogId = domainEvent.FileImportLogId; + aggregate.FileReceivedDateTime = domainEvent.FileReceivedDateTime; } - /// - /// Plays the event. - /// - /// The domain event. - private void PlayEvent(FileCreatedEvent domainEvent) - { - this.IsCreated = true; - this.EstateId = domainEvent.EstateId; - this.MerchantId = domainEvent.MerchantId; - this.FileProfileId = domainEvent.FileProfileId; - this.UserId = domainEvent.UserId; - this.FileLocation = domainEvent.FileLocation; - this.FileImportLogId = domainEvent.FileImportLogId; - this.FileReceivedDateTime = domainEvent.FileReceivedDateTime; - } - - /// - /// The file lines - /// - private List FileLines; - - /// - /// Gets the file. - /// - /// - public FileDetails GetFile() + public static FileDetails GetFile(this FileAggregate aggregate) { return new FileDetails - { - FileReceivedDateTime = this.FileReceivedDateTime, - ProcessingCompleted = this.IsCompleted, - FileLines = this.FileLines, - EstateId = this.EstateId, - MerchantId = this.MerchantId, - FileProfileId = this.FileProfileId, - FileId = this.AggregateId, - FileImportLogId = this.FileImportLogId, - FileLocation = this.FileLocation, - UserId = this.UserId, - ProcessingSummary = new ProcessingSummary - { - TotalLines = this.FileLines.Count, - FailedLines = this.FileLines.Count(x => x.ProcessingResult == ProcessingResult.Failed), - IgnoredLines = this.FileLines.Count(x => x.ProcessingResult == ProcessingResult.Ignored), - NotProcessedLines = this.FileLines.Count(x => x.ProcessingResult == ProcessingResult.NotProcessed), - SuccessfullyProcessedLines = this.FileLines.Count(x => x.ProcessingResult == ProcessingResult.Successful), - RejectedLines = this.FileLines.Count(x => x.ProcessingResult == ProcessingResult.Rejected) - } - }; + { + FileReceivedDateTime = aggregate.FileReceivedDateTime, + ProcessingCompleted = aggregate.IsCompleted, + FileLines = aggregate.FileLines, + EstateId = aggregate.EstateId, + MerchantId = aggregate.MerchantId, + FileProfileId = aggregate.FileProfileId, + FileId = aggregate.AggregateId, + FileImportLogId = aggregate.FileImportLogId, + FileLocation = aggregate.FileLocation, + UserId = aggregate.UserId, + ProcessingSummary = new ProcessingSummary + { + TotalLines = aggregate.FileLines.Count, + FailedLines = aggregate.FileLines.Count(x => x.ProcessingResult == ProcessingResult.Failed), + IgnoredLines = aggregate.FileLines.Count(x => x.ProcessingResult == ProcessingResult.Ignored), + NotProcessedLines = aggregate.FileLines.Count(x => x.ProcessingResult == ProcessingResult.NotProcessed), + SuccessfullyProcessedLines = aggregate.FileLines.Count(x => x.ProcessingResult == ProcessingResult.Successful), + RejectedLines = aggregate.FileLines.Count(x => x.ProcessingResult == ProcessingResult.Rejected) + } + }; } - /// - /// Plays the event. - /// - /// The domain event. - private void PlayEvent(FileLineAddedEvent domainEvent) + public static void PlayEvent(this FileAggregate aggregate, FileLineAddedEvent domainEvent) { - this.FileLines.Add(new FileLine - { - LineData = domainEvent.FileLine, - LineNumber = domainEvent.LineNumber - }); + aggregate.FileLines.Add(new FileLine + { + LineData = domainEvent.FileLine, + LineNumber = domainEvent.LineNumber + }); } - /// - /// Plays the event. - /// - /// The domain event. - private void PlayEvent(FileLineProcessingIgnoredEvent domainEvent) + public static void PlayEvent(this FileAggregate aggregate, FileLineProcessingIgnoredEvent domainEvent) { // find the line - FileLine fileLine = this.FileLines.Single(f => f.LineNumber == domainEvent.LineNumber); + FileLine fileLine = aggregate.FileLines.Single(f => f.LineNumber == domainEvent.LineNumber); fileLine.ProcessingResult = ProcessingResult.Ignored; } - private void PlayEvent(FileLineProcessingRejectedEvent domainEvent) + public static void PlayEvent(this FileAggregate aggregate, FileLineProcessingRejectedEvent domainEvent) { // find the line - FileLine fileLine = this.FileLines.Single(f => f.LineNumber == domainEvent.LineNumber); + FileLine fileLine = aggregate.FileLines.Single(f => f.LineNumber == domainEvent.LineNumber); fileLine.ProcessingResult = ProcessingResult.Rejected; fileLine.RejectedReason = domainEvent.Reason; } - /// - /// Plays the event. - /// - /// The domain event. - private void PlayEvent(FileLineProcessingSuccessfulEvent domainEvent) + public static void PlayEvent(this FileAggregate aggregate, FileLineProcessingSuccessfulEvent domainEvent) { // find the line - FileLine fileLine = this.FileLines.Single(f => f.LineNumber == domainEvent.LineNumber); + FileLine fileLine = aggregate.FileLines.Single(f => f.LineNumber == domainEvent.LineNumber); fileLine.TransactionId = domainEvent.TransactionId; fileLine.ProcessingResult = ProcessingResult.Successful; } - - /// - /// Plays the event. - /// - /// The domain event. - private void PlayEvent(FileLineProcessingFailedEvent domainEvent) + + public static void PlayEvent(this FileAggregate aggregate, FileLineProcessingFailedEvent domainEvent) { - FileLine fileLine = this.FileLines.Single(f => f.LineNumber == domainEvent.LineNumber); + FileLine fileLine = aggregate.FileLines.Single(f => f.LineNumber == domainEvent.LineNumber); fileLine.TransactionId = domainEvent.TransactionId; fileLine.ProcessingResult = ProcessingResult.Failed; } - /// - /// Plays the event. - /// - /// The domain event. - private void PlayEvent(FileProcessingCompletedEvent domainEvent) + public static void PlayEvent(this FileAggregate aggregate, FileProcessingCompletedEvent domainEvent) { - this.IsCompleted = true; + aggregate.IsCompleted = true; } - /// - /// Uploads the file. - /// - /// The file import log identifier. - /// The estate identifier. - /// The merchant identifier. - /// The user identifier. - /// The file profile identifier. - /// The file location. - /// The file received date time. - /// File Id {this.AggregateId} has already been created - /// File Id {this.AggregateId} has already been uploaded - public void CreateFile(Guid fileImportLogId, Guid estateId, Guid merchantId, Guid userId, Guid fileProfileId, String fileLocation, DateTime fileReceivedDateTime) + public static void CreateFile(this FileAggregate aggregate, Guid fileImportLogId, Guid estateId, Guid merchantId, Guid userId, Guid fileProfileId, String fileLocation, DateTime fileReceivedDateTime) { - if (this.IsCreated) + if (aggregate.IsCreated) return; - FileCreatedEvent fileCreatedEvent = new FileCreatedEvent(this.AggregateId, fileImportLogId, estateId, merchantId, userId, fileProfileId, fileLocation, fileReceivedDateTime); + FileCreatedEvent fileCreatedEvent = new FileCreatedEvent(aggregate.AggregateId, fileImportLogId, estateId, merchantId, userId, fileProfileId, fileLocation, fileReceivedDateTime); - this.ApplyAndAppend(fileCreatedEvent); + aggregate.ApplyAndAppend(fileCreatedEvent); } - /// - /// Adds the file line. - /// - /// The file line. - /// File Id {this.AggregateId} has not been uploaded yet - public void AddFileLine(String fileLine) + public static void AddFileLine(this FileAggregate aggregate, String fileLine) { - if (this.IsCreated == false) + if (aggregate.IsCreated == false) { - throw new InvalidOperationException($"File Id {this.AggregateId} has not been uploaded yet"); + throw new InvalidOperationException($"File Id {aggregate.AggregateId} has not been uploaded yet"); } - Boolean lineAlreadyExists = this.FileLines.Any(f => f.LineData == fileLine); + Boolean lineAlreadyExists = aggregate.FileLines.Any(f => f.LineData == fileLine); // We already have this line so just return if (lineAlreadyExists) return; - Int32 lineNumber = this.FileLines.Count + 1; - - FileLineAddedEvent fileLineAddedEvent = new FileLineAddedEvent(this.AggregateId, this.EstateId, lineNumber, fileLine); - this.ApplyAndAppend(fileLineAddedEvent); + Int32 lineNumber = aggregate.FileLines.Count + 1; + + FileLineAddedEvent fileLineAddedEvent = new FileLineAddedEvent(aggregate.AggregateId, aggregate.EstateId, lineNumber, fileLine); + aggregate.ApplyAndAppend(fileLineAddedEvent); } - /// - /// Records the file line as ignored. - /// - /// The line number. - /// File has no lines to mark as successful - /// File line with number {lineNumber} not found to mark as successful - public void RecordFileLineAsIgnored(Int32 lineNumber) + public static void RecordFileLineAsIgnored(this FileAggregate aggregate, Int32 lineNumber) { - if (this.FileLines.Any() == false) + if (aggregate.FileLines.Any() == false) { throw new InvalidOperationException("File has no lines to mark as ignored"); } - if (this.FileLines.SingleOrDefault(l => l.LineNumber == lineNumber) == null) + if (aggregate.FileLines.SingleOrDefault(l => l.LineNumber == lineNumber) == null) { throw new NotFoundException($"File line with number {lineNumber} not found to mark as ignored"); } FileLineProcessingIgnoredEvent fileLineProcessingIgnoredEvent = - new FileLineProcessingIgnoredEvent(this.AggregateId, this.EstateId, lineNumber); + new FileLineProcessingIgnoredEvent(aggregate.AggregateId, aggregate.EstateId, lineNumber); - this.ApplyAndAppend(fileLineProcessingIgnoredEvent); + aggregate.ApplyAndAppend(fileLineProcessingIgnoredEvent); - this.CompletedChecks(); + aggregate.CompletedChecks(); } - /// - /// Records the file line as rejected. - /// - /// The line number. - /// The reason. - /// File has no lines to mark as rejected - /// File line with number {lineNumber} not found to mark as rejected - public void RecordFileLineAsRejected(Int32 lineNumber, String reason) + public static void RecordFileLineAsRejected(this FileAggregate aggregate, Int32 lineNumber, String reason) { - if (this.FileLines.Any() == false) + if (aggregate.FileLines.Any() == false) { throw new InvalidOperationException("File has no lines to mark as rejected"); } - if (this.FileLines.SingleOrDefault(l => l.LineNumber == lineNumber) == null) + if (aggregate.FileLines.SingleOrDefault(l => l.LineNumber == lineNumber) == null) { throw new NotFoundException($"File line with number {lineNumber} not found to mark as rejected"); } FileLineProcessingRejectedEvent fileLineProcessingRejectedEvent = - new FileLineProcessingRejectedEvent(this.AggregateId, this.EstateId, lineNumber, reason); + new FileLineProcessingRejectedEvent(aggregate.AggregateId, aggregate.EstateId, lineNumber, reason); - this.ApplyAndAppend(fileLineProcessingRejectedEvent); + aggregate.ApplyAndAppend(fileLineProcessingRejectedEvent); - this.CompletedChecks(); + aggregate.CompletedChecks(); } - /// - /// Records the file line as successful. - /// - /// The line number. - /// The transaction identifier. - /// File has no lines to mark as successful - /// File line with number {lineNumber} not found to mark as successful - public void RecordFileLineAsSuccessful(Int32 lineNumber, Guid transactionId) + public static void RecordFileLineAsSuccessful(this FileAggregate aggregate, Int32 lineNumber, Guid transactionId) { - if (this.FileLines.Any() == false) + if (aggregate.FileLines.Any() == false) { throw new InvalidOperationException("File has no lines to mark as successful"); } - if (this.FileLines.SingleOrDefault(l => l.LineNumber == lineNumber) == null) + if (aggregate.FileLines.SingleOrDefault(l => l.LineNumber == lineNumber) == null) { throw new NotFoundException($"File line with number {lineNumber} not found to mark as successful"); } FileLineProcessingSuccessfulEvent fileLineProcessingSuccessfulEvent = - new FileLineProcessingSuccessfulEvent(this.AggregateId, this.EstateId, lineNumber, transactionId); + new FileLineProcessingSuccessfulEvent(aggregate.AggregateId, aggregate.EstateId, lineNumber, transactionId); - this.ApplyAndAppend(fileLineProcessingSuccessfulEvent); + aggregate.ApplyAndAppend(fileLineProcessingSuccessfulEvent); - this.CompletedChecks(); + aggregate.CompletedChecks(); } - - /// - /// Records the file line as failed. - /// - /// The line number. - /// The transaction identifier. - /// The response code. - /// The response message. - /// File has no lines to mark as failed - /// File line with number {lineNumber} not found to mark as failed - public void RecordFileLineAsFailed(Int32 lineNumber, Guid transactionId, String responseCode, String responseMessage) + + public static void RecordFileLineAsFailed(this FileAggregate aggregate,Int32 lineNumber, Guid transactionId, String responseCode, String responseMessage) { - if (this.FileLines.Any() == false) + if (aggregate.FileLines.Any() == false) { throw new InvalidOperationException("File has no lines to mark as failed"); } - if (this.FileLines.SingleOrDefault(l => l.LineNumber == lineNumber) == null) + if (aggregate.FileLines.SingleOrDefault(l => l.LineNumber == lineNumber) == null) { throw new NotFoundException($"File line with number {lineNumber} not found to mark as failed"); } FileLineProcessingFailedEvent fileLineProcessingFailedEvent = - new FileLineProcessingFailedEvent(this.AggregateId, this.EstateId, lineNumber, transactionId, responseCode,responseMessage); + new FileLineProcessingFailedEvent(aggregate.AggregateId, aggregate.EstateId, lineNumber, transactionId, responseCode, responseMessage); - this.ApplyAndAppend(fileLineProcessingFailedEvent); + aggregate.ApplyAndAppend(fileLineProcessingFailedEvent); - this.CompletedChecks(); + aggregate.CompletedChecks(); } /// /// Completeds the checks. /// - private void CompletedChecks() + private static void CompletedChecks(this FileAggregate aggregate) { - if (this.FileLines.Any(f => f.ProcessingResult == ProcessingResult.NotProcessed) == false) + if (aggregate.FileLines.Any(f => f.ProcessingResult == ProcessingResult.NotProcessed) == false) { // All lines have been processed, write out a completed event - FileProcessingCompletedEvent fileProcessingCompletedEvent = new FileProcessingCompletedEvent(this.AggregateId, this.EstateId, DateTime.Now); + FileProcessingCompletedEvent fileProcessingCompletedEvent = new FileProcessingCompletedEvent(aggregate.AggregateId, aggregate.EstateId, DateTime.Now); - this.ApplyAndAppend(fileProcessingCompletedEvent); + aggregate.ApplyAndAppend(fileProcessingCompletedEvent); } } } + + /// + public record FileAggregate : Aggregate + { + internal Guid EstateId; + + internal Guid MerchantId; + + internal Guid FileProfileId; + + internal Guid FileImportLogId; + + internal DateTime FileReceivedDateTime; + + internal Guid UserId; + + internal String FileLocation; + + internal Boolean IsCompleted; + + /// + /// Initializes a new instance of the class. + /// + [ExcludeFromCodeCoverage] + public FileAggregate() + { + // Nothing here + this.FileLines = new List(); + } + + /// + /// Initializes a new instance of the class. + /// + /// The aggregate identifier. + private FileAggregate(Guid aggregateId) + { + Guard.ThrowIfInvalidGuid(aggregateId, "Aggregate Id cannot be an Empty Guid"); + + this.AggregateId = aggregateId; + this.FileLines = new List(); + } + + /// + /// Creates the specified aggregate identifier. + /// + /// The aggregate identifier. + /// + public static FileAggregate Create(Guid aggregateId) + { + return new FileAggregate(aggregateId); + } + + /// + /// Gets the metadata. + /// + /// + [ExcludeFromCodeCoverage] + protected override Object GetMetadata() + { + return null; + } + + public Boolean IsCreated{ get; internal set; } + + /// + /// Plays the event. + /// + /// The domain event. + public override void PlayEvent(IDomainEvent domainEvent) => FileAggregateExtensions.PlayEvent(this, (dynamic)domainEvent); + + internal List FileLines; + + + } } diff --git a/FileProcessor.FileAggregate/FileProcessor.FileAggregate.csproj b/FileProcessor.FileAggregate/FileProcessor.FileAggregate.csproj index 6cc5f57..28d8ebe 100644 --- a/FileProcessor.FileAggregate/FileProcessor.FileAggregate.csproj +++ b/FileProcessor.FileAggregate/FileProcessor.FileAggregate.csproj @@ -5,9 +5,9 @@ - - - + + + diff --git a/FileProcessor.FileImportLog.DomainEvents/FileProcessor.FileImportLog.DomainEvents.csproj b/FileProcessor.FileImportLog.DomainEvents/FileProcessor.FileImportLog.DomainEvents.csproj index 79e6932..bd44cc7 100644 --- a/FileProcessor.FileImportLog.DomainEvents/FileProcessor.FileImportLog.DomainEvents.csproj +++ b/FileProcessor.FileImportLog.DomainEvents/FileProcessor.FileImportLog.DomainEvents.csproj @@ -5,7 +5,7 @@ - + diff --git a/FileProcessor.FileImportLogAggregate.Tests/FileProcessor.FileImportLogAggregate.Tests.csproj b/FileProcessor.FileImportLogAggregate.Tests/FileProcessor.FileImportLogAggregate.Tests.csproj index 2deb83e..11d89fa 100644 --- a/FileProcessor.FileImportLogAggregate.Tests/FileProcessor.FileImportLogAggregate.Tests.csproj +++ b/FileProcessor.FileImportLogAggregate.Tests/FileProcessor.FileImportLogAggregate.Tests.csproj @@ -7,14 +7,14 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/FileProcessor.FileImportLogAggregate/FileImportLogAggregate.cs b/FileProcessor.FileImportLogAggregate/FileImportLogAggregate.cs index 3dffdb2..7d359ab 100644 --- a/FileProcessor.FileImportLogAggregate/FileImportLogAggregate.cs +++ b/FileProcessor.FileImportLogAggregate/FileImportLogAggregate.cs @@ -12,179 +12,107 @@ namespace FileProcessor.FileImportLogAggregate using Shared.EventStore.Aggregate; using Shared.General; - /// - /// - /// - /// - public class FileImportLogAggregate : Aggregate - { - /// - /// Gets the metadata. - /// - /// - [ExcludeFromCodeCoverage] - protected override Object GetMetadata() - { - return null; - } - - /// - /// Plays the event. - /// - /// The domain event. - public override void PlayEvent(IDomainEvent domainEvent) - { - this.PlayEvent((dynamic)domainEvent); - } - - /// - /// Initializes a new instance of the class. - /// - [ExcludeFromCodeCoverage] - public FileImportLogAggregate() - { - this.Files = new List(); - } - - /// - /// Initializes a new instance of the class. - /// - /// The aggregate identifier. - private FileImportLogAggregate(Guid aggregateId) - { - Guard.ThrowIfInvalidGuid(aggregateId, "Aggregate Id cannot be an Empty Guid"); - - this.AggregateId = aggregateId; - this.Files = new List(); - } - - /// - /// Creates the specified aggregate identifier. - /// - /// The aggregate identifier. - /// - public static FileImportLogAggregate Create(Guid aggregateId) - { - return new FileImportLogAggregate(aggregateId); - } - - /// - /// Creates the import log. - /// - /// The estate identifier. - /// The import log date time. - public void CreateImportLog(Guid estateId, DateTime importLogDateTime) + public static class FileImportLogAggregateExtensions{ + public static void CreateImportLog(this FileImportLogAggregate aggregate, Guid estateId, DateTime importLogDateTime) { // Silently handle a duplicate create - if (this.IsCreated) + if (aggregate.IsCreated) return; - ImportLogCreatedEvent importLogCreatedEvent = new ImportLogCreatedEvent(this.AggregateId, estateId, importLogDateTime); + ImportLogCreatedEvent importLogCreatedEvent = new ImportLogCreatedEvent(aggregate.AggregateId, estateId, importLogDateTime); - this.ApplyAndAppend(importLogCreatedEvent); + aggregate.ApplyAndAppend(importLogCreatedEvent); } - - /// - /// Adds the imported file. - /// - /// The file identifier. - /// The merchant identifier. - /// The user identifier. - /// The file profile identifier. - /// Name of the original file. - /// The file path. - /// The file uploaded date time. - /// - /// Import log has not been created - /// or - /// Duplicate file {originalFileName} detected File Id [{fileId}] - /// - public void AddImportedFile(Guid fileId, Guid merchantId,Guid userId, Guid fileProfileId, String originalFileName, String filePath, DateTime fileUploadedDateTime) + + public static void AddImportedFile(this FileImportLogAggregate aggregate, Guid fileId, Guid merchantId, Guid userId, Guid fileProfileId, String originalFileName, String filePath, DateTime fileUploadedDateTime) { - if (this.IsCreated == false) + if (aggregate.IsCreated == false) { throw new InvalidOperationException("Import log has not been created"); } - if (this.Files.Any(f => f.FileId == fileId)) + if (aggregate.Files.Any(f => f.FileId == fileId)) { throw new InvalidOperationException($"Duplicate file {originalFileName} detected File Id [{fileId}]"); } FileAddedToImportLogEvent fileAddedToImportLogEvent = - new FileAddedToImportLogEvent(this.AggregateId, fileId, this.EstateId, merchantId, userId, fileProfileId, originalFileName, filePath, fileUploadedDateTime); + new FileAddedToImportLogEvent(aggregate.AggregateId, fileId, aggregate.EstateId, merchantId, userId, fileProfileId, originalFileName, filePath, fileUploadedDateTime); - this.ApplyAndAppend(fileAddedToImportLogEvent); + aggregate.ApplyAndAppend(fileAddedToImportLogEvent); } - /// - /// Gets a value indicating whether this instance is created. - /// - /// - /// true if this instance is created; otherwise, false. - /// - public Boolean IsCreated { get; private set; } - /// - /// Gets the estate identifier. - /// - /// - /// The estate identifier. - /// - public Guid EstateId { get; private set; } - /// - /// Gets the import log date time. - /// - /// - /// The import log date time. - /// - public DateTime ImportLogDateTime { get; private set; } - /// - /// The files - /// - private List Files; - - /// - /// Plays the event. - /// - /// The domain event. - private void PlayEvent(ImportLogCreatedEvent domainEvent) + public static void PlayEvent(this FileImportLogAggregate aggregate, ImportLogCreatedEvent domainEvent) { - this.IsCreated = true; - this.EstateId = domainEvent.EstateId; - this.ImportLogDateTime = domainEvent.ImportLogDateTime; + aggregate.IsCreated = true; + aggregate.EstateId = domainEvent.EstateId; + aggregate.ImportLogDateTime = domainEvent.ImportLogDateTime; } - /// - /// Plays the event. - /// - /// The domain event. - private void PlayEvent(FileAddedToImportLogEvent domainEvent) + public static void PlayEvent(this FileImportLogAggregate aggregate, FileAddedToImportLogEvent domainEvent) { - this.Files.Add(new ImportLogFile - { - EstateId = domainEvent.EstateId, - FileId = domainEvent.FileId, - FileProfileId = domainEvent.FileProfileId, - MerchantId = domainEvent.MerchantId, - FilePath = domainEvent.FilePath, - OriginalFileName = domainEvent.OriginalFileName, - UserId = domainEvent.UserId - }); + aggregate.Files.Add(new ImportLogFile + { + EstateId = domainEvent.EstateId, + FileId = domainEvent.FileId, + FileProfileId = domainEvent.FileProfileId, + MerchantId = domainEvent.MerchantId, + FilePath = domainEvent.FilePath, + OriginalFileName = domainEvent.OriginalFileName, + UserId = domainEvent.UserId + }); } - /// - /// Gets the file import log. - /// - /// - public FileImportLog GetFileImportLog() + public static FileImportLog GetFileImportLog(this FileImportLogAggregate aggregate) { return new FileImportLog { - EstateId = this.EstateId, - FileImportLogId = this.AggregateId, - Files = this.Files, - FileImportLogDateTime = this.ImportLogDateTime + EstateId = aggregate.EstateId, + FileImportLogId = aggregate.AggregateId, + Files = aggregate.Files, + FileImportLogDateTime = aggregate.ImportLogDateTime }; } } + + + public record FileImportLogAggregate : Aggregate + { + [ExcludeFromCodeCoverage] + protected override Object GetMetadata() + { + return null; + } + + public override void PlayEvent(IDomainEvent domainEvent) => FileImportLogAggregateExtensions.PlayEvent(this, (dynamic)domainEvent); + + [ExcludeFromCodeCoverage] + public FileImportLogAggregate() + { + this.Files = new List(); + } + + private FileImportLogAggregate(Guid aggregateId) + { + Guard.ThrowIfInvalidGuid(aggregateId, "Aggregate Id cannot be an Empty Guid"); + + this.AggregateId = aggregateId; + this.Files = new List(); + } + + public static FileImportLogAggregate Create(Guid aggregateId) + { + return new FileImportLogAggregate(aggregateId); + } + + public Boolean IsCreated { get; internal set; } + + public Guid EstateId { get; internal set; } + + public DateTime ImportLogDateTime { get; internal set; } + + internal List Files; + + + } } diff --git a/FileProcessor.FileImportLogAggregate/FileProcessor.FileImportLogAggregate.csproj b/FileProcessor.FileImportLogAggregate/FileProcessor.FileImportLogAggregate.csproj index 778e2e4..957bc2e 100644 --- a/FileProcessor.FileImportLogAggregate/FileProcessor.FileImportLogAggregate.csproj +++ b/FileProcessor.FileImportLogAggregate/FileProcessor.FileImportLogAggregate.csproj @@ -5,8 +5,8 @@ - - + + diff --git a/FileProcessor.IntegrationTests/FileProcessor.IntegrationTests.csproj b/FileProcessor.IntegrationTests/FileProcessor.IntegrationTests.csproj index 6717ffa..ecab325 100644 --- a/FileProcessor.IntegrationTests/FileProcessor.IntegrationTests.csproj +++ b/FileProcessor.IntegrationTests/FileProcessor.IntegrationTests.csproj @@ -14,26 +14,26 @@ - + - - - - - - - - + + + + + + + + - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/FileProcessor.Tests/FileProcessor.Tests.csproj b/FileProcessor.Tests/FileProcessor.Tests.csproj index e32b78c..5491cf5 100644 --- a/FileProcessor.Tests/FileProcessor.Tests.csproj +++ b/FileProcessor.Tests/FileProcessor.Tests.csproj @@ -7,17 +7,17 @@ - + - - - - + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/FileProcessor/Bootstrapper/MediatorRegistry.cs b/FileProcessor/Bootstrapper/MediatorRegistry.cs index bb91c48..41664a5 100644 --- a/FileProcessor/Bootstrapper/MediatorRegistry.cs +++ b/FileProcessor/Bootstrapper/MediatorRegistry.cs @@ -20,13 +20,12 @@ public MediatorRegistry() { this.AddSingleton(); // request & notification handlers - this.AddTransient(context => { return t => context.GetService(t); }); 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/FileProcessor.csproj b/FileProcessor/FileProcessor.csproj index 7ffbe4a..4ef652f 100644 --- a/FileProcessor/FileProcessor.csproj +++ b/FileProcessor/FileProcessor.csproj @@ -6,30 +6,29 @@ - - - + + + - - - + + + - - - - - + + + + + - - - - - - - - + + + + + + + diff --git a/FileProcessor/Startup.cs b/FileProcessor/Startup.cs index 47d8f01..42ae3bb 100644 --- a/FileProcessor/Startup.cs +++ b/FileProcessor/Startup.cs @@ -30,8 +30,8 @@ namespace FileProcessor using FileImportLog.DomainEvents; using FIleProcessor.Models; using HealthChecks.UI.Client; + using JasperFx.Core; using Lamar; - using LamarCodeGeneration.Util; using MediatR; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Diagnostics.HealthChecks;