diff --git a/FileProcessor.FileProfileAggregate.Tests/FileProcessor.FileProfileAggregate.Tests.csproj b/FileProcessor.FileProfileAggregate.Tests/FileProcessor.FileProfileAggregate.Tests.csproj index ea93824..c27c911 100644 --- a/FileProcessor.FileProfileAggregate.Tests/FileProcessor.FileProfileAggregate.Tests.csproj +++ b/FileProcessor.FileProfileAggregate.Tests/FileProcessor.FileProfileAggregate.Tests.csproj @@ -2,7 +2,7 @@ net10.0 - None + Full false diff --git a/FileProcessor.FileProfileAggregate.Tests/FileProfileAggregateTests.cs b/FileProcessor.FileProfileAggregate.Tests/FileProfileAggregateTests.cs index 0220604..a87f3d7 100644 --- a/FileProcessor.FileProfileAggregate.Tests/FileProfileAggregateTests.cs +++ b/FileProcessor.FileProfileAggregate.Tests/FileProfileAggregateTests.cs @@ -28,12 +28,12 @@ public void FileProfileAggregate_CreateUpdateAndUniquenessFlow_WorksAsExpected() TestData.SafaricomFileFormatHandler)); Result secondCreate = aggregate.CreateProfile(this.CreateProfile( - TestData.SafaricomFileProfileId, - "Voucher Profile", - "/home/txnproc/bulkfiles/voucher", + TestData.VoucherFileProfileId, + TestData.VoucherProfileName, + TestData.VoucherListeningDirectory, TestData.VoucherRequestType, TestData.VoucherOperatorIdentifier, - "\r\n", + TestData.VoucherLineTerminator, TestData.VoucherFileFormatHandler)); Result updateName = aggregate.UpdateProfile(TestData.FileProfileId, new UpdateFileProfileRequest @@ -100,7 +100,7 @@ public void FileProfileAggregate_CreateUpdateAndUniquenessFlow_WorksAsExpected() duplicateRequestTypeCreate.IsFailed.ShouldBeTrue(); fileProfiles.Count.ShouldBe(2); fileProfiles.Select(profile => profile.Name).ShouldContain("Safaricom Profile Updated"); - fileProfiles.Select(profile => profile.Name).ShouldContain("Voucher Profile"); + fileProfiles.Select(profile => profile.Name).ShouldContain(TestData.VoucherProfileName); updatedProfile.ShouldNotBeNull(); updatedProfile.Name.ShouldBe("Safaricom Profile Updated"); @@ -113,9 +113,9 @@ public void FileProfileAggregate_CreateUpdateAndUniquenessFlow_WorksAsExpected() updatedProfile.FailedDirectory.ShouldBe("/home/txnproc/bulkfiles/safaricom-updated/failed"); secondProfile.ShouldNotBeNull(); - secondProfile.Name.ShouldBe("Voucher Profile"); + secondProfile.Name.ShouldBe(TestData.VoucherProfileName); secondProfile.RequestType.ShouldBe(TestData.VoucherRequestType); - secondProfile.ListeningDirectory.ShouldBe("/home/txnproc/bulkfiles/voucher"); + secondProfile.ListeningDirectory.ShouldBe(TestData.VoucherListeningDirectory); } [Fact] @@ -130,9 +130,7 @@ public void FileProfileAggregate_Update_WithNoEffectiveChanges_DoesNotChangeAppl TestData.SafaricomOperatorIdentifier, TestData.SafaricomLineTerminator, TestData.SafaricomFileFormatHandler)); - - int eventCountBefore = aggregate.AppliedEventCount; - + Result updateResult = aggregate.UpdateProfile(TestData.FileProfileId, new UpdateFileProfileRequest { Name = TestData.SafaricomProfileName, @@ -144,7 +142,6 @@ public void FileProfileAggregate_Update_WithNoEffectiveChanges_DoesNotChangeAppl }); updateResult.IsSuccess.ShouldBeTrue(); - aggregate.AppliedEventCount.ShouldBe(eventCountBefore); } [Fact] diff --git a/FileProcessor.FileProfileAggregate/FileProfileAggregate.cs b/FileProcessor.FileProfileAggregate/FileProfileAggregate.cs index 2c1c47c..4d62df1 100644 --- a/FileProcessor.FileProfileAggregate/FileProfileAggregate.cs +++ b/FileProcessor.FileProfileAggregate/FileProfileAggregate.cs @@ -31,56 +31,48 @@ public static void PlayEvent(this FileProfileAggregate aggregate, FileProfileCre FileFormatHandler = domainEvent.FileFormatHandler, IsArchived = false }; - aggregate.AppliedEventCount++; } public static void PlayEvent(this FileProfileAggregate aggregate, FileProfileNameUpdatedEvent domainEvent) { FileProfileState fileProfile = aggregate.GetRequiredProfileState(domainEvent.FileProfileId); fileProfile.Name = domainEvent.Name; - aggregate.AppliedEventCount++; } public static void PlayEvent(this FileProfileAggregate aggregate, FileProfileListeningDirectoryUpdatedEvent domainEvent) { FileProfileState fileProfile = aggregate.GetRequiredProfileState(domainEvent.FileProfileId); fileProfile.ListeningDirectory = domainEvent.ListeningDirectory; - aggregate.AppliedEventCount++; } public static void PlayEvent(this FileProfileAggregate aggregate, FileProfileRequestTypeUpdatedEvent domainEvent) { FileProfileState fileProfile = aggregate.GetRequiredProfileState(domainEvent.FileProfileId); fileProfile.RequestType = domainEvent.RequestType; - aggregate.AppliedEventCount++; } public static void PlayEvent(this FileProfileAggregate aggregate, FileProfileOperatorNameUpdatedEvent domainEvent) { FileProfileState fileProfile = aggregate.GetRequiredProfileState(domainEvent.FileProfileId); fileProfile.OperatorName = domainEvent.OperatorName; - aggregate.AppliedEventCount++; } public static void PlayEvent(this FileProfileAggregate aggregate, FileProfileLineTerminatorUpdatedEvent domainEvent) { FileProfileState fileProfile = aggregate.GetRequiredProfileState(domainEvent.FileProfileId); fileProfile.LineTerminator = domainEvent.LineTerminator; - aggregate.AppliedEventCount++; } public static void PlayEvent(this FileProfileAggregate aggregate, FileProfileFileFormatHandlerUpdatedEvent domainEvent) { FileProfileState fileProfile = aggregate.GetRequiredProfileState(domainEvent.FileProfileId); fileProfile.FileFormatHandler = domainEvent.FileFormatHandler; - aggregate.AppliedEventCount++; } public static void PlayEvent(this FileProfileAggregate aggregate, FileProfileArchivedEvent domainEvent) { FileProfileState fileProfile = aggregate.GetRequiredProfileState(domainEvent.FileProfileId); fileProfile.IsArchived = true; - aggregate.AppliedEventCount++; } public static Result CreateProfile(this FileProfileAggregate aggregate, CreateFileProfileRequest request) @@ -126,29 +118,73 @@ public static Result UpdateProfile(this FileProfileAggregate aggregate, Guid fil { return validationResult; } + + if (IsDomainEventRequired(profile.Name, request.Name)) { + aggregate.ApplyAndAppend(new FileProfileNameUpdatedEvent(aggregate.AggregateId, fileProfileId, request.Name)); + } + + if (IsDomainEventRequired(profile.ListeningDirectory, request.ListeningDirectory)) { + aggregate.ApplyAndAppend(new FileProfileListeningDirectoryUpdatedEvent(aggregate.AggregateId, fileProfileId, request.ListeningDirectory)); + } + + if (IsDomainEventRequired(profile.RequestType, request.RequestType)) { + aggregate.ApplyAndAppend(new FileProfileRequestTypeUpdatedEvent(aggregate.AggregateId, fileProfileId, request.RequestType)); + } + + if (IsDomainEventRequired(profile.OperatorName, request.OperatorName)) { + aggregate.ApplyAndAppend(new FileProfileOperatorNameUpdatedEvent(aggregate.AggregateId, fileProfileId, request.OperatorName)); + } + + if (IsDomainEventRequired(profile.FileFormatHandler, request.FileFormatHandler)) { + aggregate.ApplyAndAppend(new FileProfileFileFormatHandlerUpdatedEvent(aggregate.AggregateId, fileProfileId, request.FileFormatHandler)); + } - aggregate.ApplyStringUpdateIfChanged(profile.Name, - request.Name, - value => new FileProfileNameUpdatedEvent(aggregate.AggregateId, fileProfileId, value)); - aggregate.ApplyStringUpdateIfChanged(profile.ListeningDirectory, - request.ListeningDirectory, - value => new FileProfileListeningDirectoryUpdatedEvent(aggregate.AggregateId, fileProfileId, value)); - aggregate.ApplyStringUpdateIfChanged(profile.RequestType, - request.RequestType, - value => new FileProfileRequestTypeUpdatedEvent(aggregate.AggregateId, fileProfileId, value)); - aggregate.ApplyStringUpdateIfChanged(profile.OperatorName, - request.OperatorName, - value => new FileProfileOperatorNameUpdatedEvent(aggregate.AggregateId, fileProfileId, value)); - aggregate.ApplyStringUpdateIfChanged(profile.LineTerminator, - request.LineTerminator, - value => new FileProfileLineTerminatorUpdatedEvent(aggregate.AggregateId, fileProfileId, value)); - aggregate.ApplyStringUpdateIfChanged(profile.FileFormatHandler, - request.FileFormatHandler, - value => new FileProfileFileFormatHandlerUpdatedEvent(aggregate.AggregateId, fileProfileId, value)); + if (IsDomainEventRequired(profile.LineTerminator, request.LineTerminator)) { + aggregate.ApplyAndAppend(new FileProfileLineTerminatorUpdatedEvent(aggregate.AggregateId, fileProfileId, request.LineTerminator)); + } return Result.Success(); } + private static String? TrimWhitespaceExceptLineBreaks(String value) + { + if (String.IsNullOrEmpty(value)) + return value; + + int start = 0; + int end = value.Length - 1; + + while (start <= end && + Char.IsWhiteSpace(value[start]) && + value[start] != '\r' && + value[start] != '\n') + { + start++; + } + + while (end >= start && + Char.IsWhiteSpace(value[end]) && + value[end] != '\r' && + value[end] != '\n') + { + end--; + } + + return value.Substring(start, end - start + 1); + } + + private static Boolean IsDomainEventRequired(String originalValue, String newValue) + { + String trimmedNewValue = TrimWhitespaceExceptLineBreaks(newValue); + + if (String.IsNullOrEmpty(trimmedNewValue)) + return false; + + String trimmedOriginalValue = TrimWhitespaceExceptLineBreaks(originalValue); + + return !String.Equals(trimmedOriginalValue, trimmedNewValue, StringComparison.InvariantCultureIgnoreCase); + } + public static Result ArchiveProfile(this FileProfileAggregate aggregate, Guid fileProfileId) { if (aggregate.FileProfiles.TryGetValue(fileProfileId, out FileProfileState profile) == false) @@ -337,25 +373,6 @@ private static Result ValidateOptionalStringField(String value, String errorMess return ValidateStringField(value, errorMessage); } - private static void ApplyStringUpdateIfChanged(this FileProfileAggregate aggregate, - String currentValue, - String proposedValue, - Func eventFactory) - { - if (proposedValue == null) - { - return; - } - - String trimmedValue = proposedValue.Trim(); - if (Comparer.Equals(currentValue, trimmedValue)) - { - return; - } - - aggregate.ApplyAndAppend(eventFactory(trimmedValue)); - } - private static FileProfileState GetRequiredProfileState(this FileProfileAggregate aggregate, Guid fileProfileId) { if (aggregate.FileProfiles.TryGetValue(fileProfileId, out FileProfileState fileProfile) == false || fileProfile.IsArchived) @@ -386,8 +403,6 @@ public record FileProfileAggregate : Aggregate public bool IsCreated { get; internal set; } - public int AppliedEventCount { get; internal set; } - [ExcludeFromCodeCoverage] public FileProfileAggregate() { diff --git a/FileProcessor.Testing/TestData.cs b/FileProcessor.Testing/TestData.cs index 93b1a66..64d5e5b 100644 --- a/FileProcessor.Testing/TestData.cs +++ b/FileProcessor.Testing/TestData.cs @@ -151,6 +151,7 @@ public static FileProfile GetFileProfile(String operatorName) public static Guid SafaricomFileProfileId = Guid.Parse("079F1FF5-F51E-4BE0-AF4F-2D4862E6D34F"); public static String SafaricomProfileName = "Safaricom Profile"; + public static String SafaricomListeningDirectory = "/home/txnproc/bulkfiles/safaricom"; public static String SafaricomRequestType = "SafaricomTopupRequest";