From cedba45ba92abf195fc5a22c8266263d8decc0c0 Mon Sep 17 00:00:00 2001 From: CengoleFHV Date: Wed, 5 Jun 2024 01:17:46 +0200 Subject: [PATCH 01/18] added properties to Member --- Domain/Models/Member.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Domain/Models/Member.cs b/Domain/Models/Member.cs index cd75bdf..f771f0e 100644 --- a/Domain/Models/Member.cs +++ b/Domain/Models/Member.cs @@ -7,6 +7,10 @@ public class Member { public Guid Id { get; set; } public Guid ClubId { get; set; } + + public string? Email { get; set; } + public string? FullName { get; set; } + public string? ClubName { get; set; } public Status Status { get; set; } From abedb217f7f40511e38f36440b9b70bdfd2137dc Mon Sep 17 00:00:00 2001 From: CengoleFHV Date: Wed, 5 Jun 2024 01:17:46 +0200 Subject: [PATCH 02/18] added properties to Member --- Domain/Models/Member.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Domain/Models/Member.cs b/Domain/Models/Member.cs index cd75bdf..f771f0e 100644 --- a/Domain/Models/Member.cs +++ b/Domain/Models/Member.cs @@ -7,6 +7,10 @@ public class Member { public Guid Id { get; set; } public Guid ClubId { get; set; } + + public string? Email { get; set; } + public string? FullName { get; set; } + public string? ClubName { get; set; } public Status Status { get; set; } From ad9fd81af9ef5ae92303759e8961daef537cffee Mon Sep 17 00:00:00 2001 From: CengoleFHV Date: Wed, 5 Jun 2024 20:56:42 +0200 Subject: [PATCH 03/18] expanded Member props and added MEMBER_UPDATED Event --- Application/RedisMemberStreamService.cs | 8 ++++++-- Domain/Events/DomainEvent.cs | 1 + Domain/Events/EventType.cs | 1 + Domain/Events/Member/MemberUpdatedEvent.cs | 13 +++++++++++++ Domain/Models/Member.cs | 22 +++++++++++++++++++--- 5 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 Domain/Events/Member/MemberUpdatedEvent.cs diff --git a/Application/RedisMemberStreamService.cs b/Application/RedisMemberStreamService.cs index 9a72278..5a43b0c 100644 --- a/Application/RedisMemberStreamService.cs +++ b/Application/RedisMemberStreamService.cs @@ -67,10 +67,14 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) var eventType = eventInfo["eventType"].GetValue(); var entityType = eventInfo["entityType"].GetValue(); - if ((eventType != "MEMBER_REGISTERED" + if ( + (eventType != "MEMBER_REGISTERED" && eventType != "MEMBER_DELETED" && eventType != "MEMBER_LOCKED" - && eventType != "MEMBER_UNLOCKED") || entityType != "MEMBER") + && eventType != "MEMBER_UNLOCKED" + && eventType != "MEMBER_UPDATED") + || entityType != "MEMBER" + ) { return null; } diff --git a/Domain/Events/DomainEvent.cs b/Domain/Events/DomainEvent.cs index 6955268..19ebba9 100644 --- a/Domain/Events/DomainEvent.cs +++ b/Domain/Events/DomainEvent.cs @@ -14,6 +14,7 @@ namespace PlayOfferService.Domain.Events; [JsonDerivedType(typeof(MemberLockedEvent), typeDiscriminator: "MEMBER_LOCKED")] [JsonDerivedType(typeof(MemberUnlockedEvent), typeDiscriminator: "MEMBER_UNLOCKED")] [JsonDerivedType(typeof(MemberDeletedEvent), typeDiscriminator: "MEMBER_DELETED")] +[JsonDerivedType(typeof(MemberUpdatedEvent), typeDiscriminator: "MEMBER_UPDATED")] [JsonDerivedType(typeof(PlayOfferCreatedEvent), typeDiscriminator: "PLAYOFFER_CREATED")] [JsonDerivedType(typeof(PlayOfferJoinedEvent), typeDiscriminator: "PLAYOFFER_JOINED")] [JsonDerivedType(typeof(PlayOfferCancelledEvent), typeDiscriminator: "PLAYOFFER_CANCELLED")] diff --git a/Domain/Events/EventType.cs b/Domain/Events/EventType.cs index 451867f..3318e30 100644 --- a/Domain/Events/EventType.cs +++ b/Domain/Events/EventType.cs @@ -15,6 +15,7 @@ public enum EventType MEMBER_LOCKED, MEMBER_UNLOCKED, MEMBER_DELETED, + MEMBER_UPDATED, ReservationCreatedEvent, ReservationRejectedEvent, ReservationLimitExceeded diff --git a/Domain/Events/Member/MemberUpdatedEvent.cs b/Domain/Events/Member/MemberUpdatedEvent.cs new file mode 100644 index 0000000..b47bb43 --- /dev/null +++ b/Domain/Events/Member/MemberUpdatedEvent.cs @@ -0,0 +1,13 @@ +using PlayOfferService.Domain.Models; +using PlayOfferService.Domain.ValueObjects; + +namespace PlayOfferService.Domain.Events.Member; + +public class MemberUpdatedEvent : DomainEvent +{ + public MemberId MemberId { get; set; } + public FullName Name { get; set; } + public string Email { get; set; } + public TennisClubId TennisClubId { get; set; } + public Status Status { get; set; } +} \ No newline at end of file diff --git a/Domain/Models/Member.cs b/Domain/Models/Member.cs index f771f0e..2d88320 100644 --- a/Domain/Models/Member.cs +++ b/Domain/Models/Member.cs @@ -9,8 +9,8 @@ public class Member public Guid ClubId { get; set; } public string? Email { get; set; } - public string? FullName { get; set; } - public string? ClubName { get; set; } + public string? FirstName { get; set; } + public string? LastName { get; set; } public Status Status { get; set; } @@ -32,15 +32,31 @@ public void Apply(List baseEvents) case EventType.MEMBER_DELETED: ApplyMemberDeletedEvent(); break; + case EventType.MEMBER_UPDATED: + ApplyMemberUpdatedEvent((MemberUpdatedEvent) baseEvent.EventData); + break; default: throw new ArgumentOutOfRangeException($"{nameof(baseEvent.EventType)} is not supported for the entity Member!"); } } } - + + private void ApplyMemberUpdatedEvent(MemberUpdatedEvent baseEventData) + { + Id = baseEventData.MemberId.Id; + Email = baseEventData.Email; + FirstName = baseEventData.Name.FirstName; + LastName = baseEventData.Name.LastName; + ClubId = baseEventData.TennisClubId.Id; + Status = baseEventData.Status; + } + private void Apply(MemberCreatedEvent domainEvent) { Id = domainEvent.MemberId.Id; + Email = domainEvent.Email; + FirstName = domainEvent.Name.FirstName; + LastName = domainEvent.Name.LastName; ClubId = domainEvent.TennisClubId.Id; Status = domainEvent.Status; } From 5497c10856ad4aa5917167dcfde0e335b19c7f1e Mon Sep 17 00:00:00 2001 From: CengoleFHV Date: Wed, 5 Jun 2024 21:50:27 +0200 Subject: [PATCH 04/18] changed fom updatedEvent to Email and FullName Event --- Application/RedisMemberStreamService.cs | 4 +- Domain/Events/DomainEvent.cs | 3 +- Domain/Events/EventType.cs | 3 +- .../Events/Member/MemberEmailChangedEvent.cs | 6 +++ .../Member/MemberFullNameChangedEvent.cs | 8 ++++ Domain/Events/Member/MemberUpdatedEvent.cs | 13 ------- Domain/Models/Member.cs | 37 ++++++++++--------- 7 files changed, 41 insertions(+), 33 deletions(-) create mode 100644 Domain/Events/Member/MemberEmailChangedEvent.cs create mode 100644 Domain/Events/Member/MemberFullNameChangedEvent.cs delete mode 100644 Domain/Events/Member/MemberUpdatedEvent.cs diff --git a/Application/RedisMemberStreamService.cs b/Application/RedisMemberStreamService.cs index 5a43b0c..8f2bdcf 100644 --- a/Application/RedisMemberStreamService.cs +++ b/Application/RedisMemberStreamService.cs @@ -72,7 +72,9 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) && eventType != "MEMBER_DELETED" && eventType != "MEMBER_LOCKED" && eventType != "MEMBER_UNLOCKED" - && eventType != "MEMBER_UPDATED") + && eventType != "MEMBER_EMAIL_CHANGED" + && eventType != "MEMBER_FULL_NAME_CHANGED" + ) || entityType != "MEMBER" ) { diff --git a/Domain/Events/DomainEvent.cs b/Domain/Events/DomainEvent.cs index 19ebba9..d23e922 100644 --- a/Domain/Events/DomainEvent.cs +++ b/Domain/Events/DomainEvent.cs @@ -14,7 +14,8 @@ namespace PlayOfferService.Domain.Events; [JsonDerivedType(typeof(MemberLockedEvent), typeDiscriminator: "MEMBER_LOCKED")] [JsonDerivedType(typeof(MemberUnlockedEvent), typeDiscriminator: "MEMBER_UNLOCKED")] [JsonDerivedType(typeof(MemberDeletedEvent), typeDiscriminator: "MEMBER_DELETED")] -[JsonDerivedType(typeof(MemberUpdatedEvent), typeDiscriminator: "MEMBER_UPDATED")] +[JsonDerivedType(typeof(MemberEmailChangedEvent), typeDiscriminator: "MEMBER_EMAIL_CHANGED")] +[JsonDerivedType(typeof(MemberFullNameChangedEvent), typeDiscriminator: "MEMBER_FULL_NAME_CHANGED")] [JsonDerivedType(typeof(PlayOfferCreatedEvent), typeDiscriminator: "PLAYOFFER_CREATED")] [JsonDerivedType(typeof(PlayOfferJoinedEvent), typeDiscriminator: "PLAYOFFER_JOINED")] [JsonDerivedType(typeof(PlayOfferCancelledEvent), typeDiscriminator: "PLAYOFFER_CANCELLED")] diff --git a/Domain/Events/EventType.cs b/Domain/Events/EventType.cs index 3318e30..132802b 100644 --- a/Domain/Events/EventType.cs +++ b/Domain/Events/EventType.cs @@ -15,7 +15,8 @@ public enum EventType MEMBER_LOCKED, MEMBER_UNLOCKED, MEMBER_DELETED, - MEMBER_UPDATED, + MEMBER_EMAIL_CHANGED, + MEMBER_FULL_NAME_CHANGED, ReservationCreatedEvent, ReservationRejectedEvent, ReservationLimitExceeded diff --git a/Domain/Events/Member/MemberEmailChangedEvent.cs b/Domain/Events/Member/MemberEmailChangedEvent.cs new file mode 100644 index 0000000..bbe8ac3 --- /dev/null +++ b/Domain/Events/Member/MemberEmailChangedEvent.cs @@ -0,0 +1,6 @@ +namespace PlayOfferService.Domain.Events.Member; + +public class MemberEmailChangedEvent : DomainEvent +{ + public string Email { get; set; } +} \ No newline at end of file diff --git a/Domain/Events/Member/MemberFullNameChangedEvent.cs b/Domain/Events/Member/MemberFullNameChangedEvent.cs new file mode 100644 index 0000000..4bb30e4 --- /dev/null +++ b/Domain/Events/Member/MemberFullNameChangedEvent.cs @@ -0,0 +1,8 @@ +using PlayOfferService.Domain.ValueObjects; + +namespace PlayOfferService.Domain.Events.Member; + +public class MemberFullNameChangedEvent : DomainEvent +{ + public FullName FullName { get; set; } +} \ No newline at end of file diff --git a/Domain/Events/Member/MemberUpdatedEvent.cs b/Domain/Events/Member/MemberUpdatedEvent.cs deleted file mode 100644 index b47bb43..0000000 --- a/Domain/Events/Member/MemberUpdatedEvent.cs +++ /dev/null @@ -1,13 +0,0 @@ -using PlayOfferService.Domain.Models; -using PlayOfferService.Domain.ValueObjects; - -namespace PlayOfferService.Domain.Events.Member; - -public class MemberUpdatedEvent : DomainEvent -{ - public MemberId MemberId { get; set; } - public FullName Name { get; set; } - public string Email { get; set; } - public TennisClubId TennisClubId { get; set; } - public Status Status { get; set; } -} \ No newline at end of file diff --git a/Domain/Models/Member.cs b/Domain/Models/Member.cs index 2d88320..c548031 100644 --- a/Domain/Models/Member.cs +++ b/Domain/Models/Member.cs @@ -11,17 +11,16 @@ public class Member public string? Email { get; set; } public string? FirstName { get; set; } public string? LastName { get; set; } - + public Status Status { get; set; } public void Apply(List baseEvents) { foreach (var baseEvent in baseEvents) - { switch (baseEvent.EventType) { case EventType.MEMBER_REGISTERED: - Apply((MemberCreatedEvent) baseEvent.EventData); + Apply((MemberCreatedEvent)baseEvent.EventData); break; case EventType.MEMBER_LOCKED: ApplyMemberLockedEvent(); @@ -32,23 +31,27 @@ public void Apply(List baseEvents) case EventType.MEMBER_DELETED: ApplyMemberDeletedEvent(); break; - case EventType.MEMBER_UPDATED: - ApplyMemberUpdatedEvent((MemberUpdatedEvent) baseEvent.EventData); + case EventType.MEMBER_EMAIL_CHANGED: + ApplyMemberEmailChangedEvent((MemberEmailChangedEvent)baseEvent.EventData); + break; + case EventType.MEMBER_FULL_NAME_CHANGED: + ApplyMemberFullNameChangedEvent((MemberFullNameChangedEvent)baseEvent.EventData); break; default: - throw new ArgumentOutOfRangeException($"{nameof(baseEvent.EventType)} is not supported for the entity Member!"); + throw new ArgumentOutOfRangeException( + $"{nameof(baseEvent.EventType)} is not supported for the entity Member!"); } - } } - private void ApplyMemberUpdatedEvent(MemberUpdatedEvent baseEventData) + private void ApplyMemberEmailChangedEvent(MemberEmailChangedEvent baseEventEventData) + { + Email = baseEventEventData.Email; + } + + private void ApplyMemberFullNameChangedEvent(MemberFullNameChangedEvent baseEventEventData) { - Id = baseEventData.MemberId.Id; - Email = baseEventData.Email; - FirstName = baseEventData.Name.FirstName; - LastName = baseEventData.Name.LastName; - ClubId = baseEventData.TennisClubId.Id; - Status = baseEventData.Status; + FirstName = baseEventEventData.FullName.FirstName; + LastName = baseEventEventData.FullName.LastName; } private void Apply(MemberCreatedEvent domainEvent) @@ -60,17 +63,17 @@ private void Apply(MemberCreatedEvent domainEvent) ClubId = domainEvent.TennisClubId.Id; Status = domainEvent.Status; } - + private void ApplyMemberLockedEvent() { Status = Status.LOCKED; } - + private void ApplyMemberUnlockedEvent() { Status = Status.ACTIVE; } - + private void ApplyMemberDeletedEvent() { Status = Status.DELETED; From 93bff8cf61f0525eb26be7f53e5866a2c89e72b5 Mon Sep 17 00:00:00 2001 From: CengoleFHV Date: Wed, 5 Jun 2024 01:17:46 +0200 Subject: [PATCH 05/18] added properties to Member --- Domain/Models/Member.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Domain/Models/Member.cs b/Domain/Models/Member.cs index cd75bdf..f771f0e 100644 --- a/Domain/Models/Member.cs +++ b/Domain/Models/Member.cs @@ -7,6 +7,10 @@ public class Member { public Guid Id { get; set; } public Guid ClubId { get; set; } + + public string? Email { get; set; } + public string? FullName { get; set; } + public string? ClubName { get; set; } public Status Status { get; set; } From e0bc0f3980926f6044469b818f98aafded7e8b47 Mon Sep 17 00:00:00 2001 From: CengoleFHV Date: Wed, 5 Jun 2024 20:56:42 +0200 Subject: [PATCH 06/18] expanded Member props and added MEMBER_UPDATED Event --- Application/RedisMemberStreamService.cs | 8 ++++++-- Domain/Events/DomainEvent.cs | 1 + Domain/Events/EventType.cs | 1 + Domain/Events/Member/MemberUpdatedEvent.cs | 13 +++++++++++++ Domain/Models/Member.cs | 22 +++++++++++++++++++--- 5 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 Domain/Events/Member/MemberUpdatedEvent.cs diff --git a/Application/RedisMemberStreamService.cs b/Application/RedisMemberStreamService.cs index 9a72278..5a43b0c 100644 --- a/Application/RedisMemberStreamService.cs +++ b/Application/RedisMemberStreamService.cs @@ -67,10 +67,14 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) var eventType = eventInfo["eventType"].GetValue(); var entityType = eventInfo["entityType"].GetValue(); - if ((eventType != "MEMBER_REGISTERED" + if ( + (eventType != "MEMBER_REGISTERED" && eventType != "MEMBER_DELETED" && eventType != "MEMBER_LOCKED" - && eventType != "MEMBER_UNLOCKED") || entityType != "MEMBER") + && eventType != "MEMBER_UNLOCKED" + && eventType != "MEMBER_UPDATED") + || entityType != "MEMBER" + ) { return null; } diff --git a/Domain/Events/DomainEvent.cs b/Domain/Events/DomainEvent.cs index e912bc2..86d2f01 100644 --- a/Domain/Events/DomainEvent.cs +++ b/Domain/Events/DomainEvent.cs @@ -15,6 +15,7 @@ namespace PlayOfferService.Domain.Events; [JsonDerivedType(typeof(MemberLockedEvent), typeDiscriminator: "MEMBER_LOCKED")] [JsonDerivedType(typeof(MemberUnlockedEvent), typeDiscriminator: "MEMBER_UNLOCKED")] [JsonDerivedType(typeof(MemberDeletedEvent), typeDiscriminator: "MEMBER_DELETED")] +[JsonDerivedType(typeof(MemberUpdatedEvent), typeDiscriminator: "MEMBER_UPDATED")] [JsonDerivedType(typeof(PlayOfferCreatedEvent), typeDiscriminator: "PLAYOFFER_CREATED")] [JsonDerivedType(typeof(PlayOfferJoinedEvent), typeDiscriminator: "PLAYOFFER_JOINED")] [JsonDerivedType(typeof(PlayOfferCancelledEvent), typeDiscriminator: "PLAYOFFER_CANCELLED")] diff --git a/Domain/Events/EventType.cs b/Domain/Events/EventType.cs index a4d6e04..d0ed879 100644 --- a/Domain/Events/EventType.cs +++ b/Domain/Events/EventType.cs @@ -15,6 +15,7 @@ public enum EventType MEMBER_LOCKED, MEMBER_UNLOCKED, MEMBER_DELETED, + MEMBER_UPDATED, ReservationCreatedEvent, ReservationRejectedEvent, ReservationLimitExceeded, diff --git a/Domain/Events/Member/MemberUpdatedEvent.cs b/Domain/Events/Member/MemberUpdatedEvent.cs new file mode 100644 index 0000000..b47bb43 --- /dev/null +++ b/Domain/Events/Member/MemberUpdatedEvent.cs @@ -0,0 +1,13 @@ +using PlayOfferService.Domain.Models; +using PlayOfferService.Domain.ValueObjects; + +namespace PlayOfferService.Domain.Events.Member; + +public class MemberUpdatedEvent : DomainEvent +{ + public MemberId MemberId { get; set; } + public FullName Name { get; set; } + public string Email { get; set; } + public TennisClubId TennisClubId { get; set; } + public Status Status { get; set; } +} \ No newline at end of file diff --git a/Domain/Models/Member.cs b/Domain/Models/Member.cs index f771f0e..2d88320 100644 --- a/Domain/Models/Member.cs +++ b/Domain/Models/Member.cs @@ -9,8 +9,8 @@ public class Member public Guid ClubId { get; set; } public string? Email { get; set; } - public string? FullName { get; set; } - public string? ClubName { get; set; } + public string? FirstName { get; set; } + public string? LastName { get; set; } public Status Status { get; set; } @@ -32,15 +32,31 @@ public void Apply(List baseEvents) case EventType.MEMBER_DELETED: ApplyMemberDeletedEvent(); break; + case EventType.MEMBER_UPDATED: + ApplyMemberUpdatedEvent((MemberUpdatedEvent) baseEvent.EventData); + break; default: throw new ArgumentOutOfRangeException($"{nameof(baseEvent.EventType)} is not supported for the entity Member!"); } } } - + + private void ApplyMemberUpdatedEvent(MemberUpdatedEvent baseEventData) + { + Id = baseEventData.MemberId.Id; + Email = baseEventData.Email; + FirstName = baseEventData.Name.FirstName; + LastName = baseEventData.Name.LastName; + ClubId = baseEventData.TennisClubId.Id; + Status = baseEventData.Status; + } + private void Apply(MemberCreatedEvent domainEvent) { Id = domainEvent.MemberId.Id; + Email = domainEvent.Email; + FirstName = domainEvent.Name.FirstName; + LastName = domainEvent.Name.LastName; ClubId = domainEvent.TennisClubId.Id; Status = domainEvent.Status; } From eaba781a1b8f68d8c05fdb35015818b2fe2fcbed Mon Sep 17 00:00:00 2001 From: CengoleFHV Date: Wed, 5 Jun 2024 21:50:27 +0200 Subject: [PATCH 07/18] changed fom updatedEvent to Email and FullName Event --- Application/RedisMemberStreamService.cs | 4 +- Domain/Events/DomainEvent.cs | 3 +- Domain/Events/EventType.cs | 3 +- .../Events/Member/MemberEmailChangedEvent.cs | 6 +++ .../Member/MemberFullNameChangedEvent.cs | 8 ++++ Domain/Events/Member/MemberUpdatedEvent.cs | 13 ------- Domain/Models/Member.cs | 37 ++++++++++--------- 7 files changed, 41 insertions(+), 33 deletions(-) create mode 100644 Domain/Events/Member/MemberEmailChangedEvent.cs create mode 100644 Domain/Events/Member/MemberFullNameChangedEvent.cs delete mode 100644 Domain/Events/Member/MemberUpdatedEvent.cs diff --git a/Application/RedisMemberStreamService.cs b/Application/RedisMemberStreamService.cs index 5a43b0c..8f2bdcf 100644 --- a/Application/RedisMemberStreamService.cs +++ b/Application/RedisMemberStreamService.cs @@ -72,7 +72,9 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) && eventType != "MEMBER_DELETED" && eventType != "MEMBER_LOCKED" && eventType != "MEMBER_UNLOCKED" - && eventType != "MEMBER_UPDATED") + && eventType != "MEMBER_EMAIL_CHANGED" + && eventType != "MEMBER_FULL_NAME_CHANGED" + ) || entityType != "MEMBER" ) { diff --git a/Domain/Events/DomainEvent.cs b/Domain/Events/DomainEvent.cs index 86d2f01..35d9a06 100644 --- a/Domain/Events/DomainEvent.cs +++ b/Domain/Events/DomainEvent.cs @@ -15,7 +15,8 @@ namespace PlayOfferService.Domain.Events; [JsonDerivedType(typeof(MemberLockedEvent), typeDiscriminator: "MEMBER_LOCKED")] [JsonDerivedType(typeof(MemberUnlockedEvent), typeDiscriminator: "MEMBER_UNLOCKED")] [JsonDerivedType(typeof(MemberDeletedEvent), typeDiscriminator: "MEMBER_DELETED")] -[JsonDerivedType(typeof(MemberUpdatedEvent), typeDiscriminator: "MEMBER_UPDATED")] +[JsonDerivedType(typeof(MemberEmailChangedEvent), typeDiscriminator: "MEMBER_EMAIL_CHANGED")] +[JsonDerivedType(typeof(MemberFullNameChangedEvent), typeDiscriminator: "MEMBER_FULL_NAME_CHANGED")] [JsonDerivedType(typeof(PlayOfferCreatedEvent), typeDiscriminator: "PLAYOFFER_CREATED")] [JsonDerivedType(typeof(PlayOfferJoinedEvent), typeDiscriminator: "PLAYOFFER_JOINED")] [JsonDerivedType(typeof(PlayOfferCancelledEvent), typeDiscriminator: "PLAYOFFER_CANCELLED")] diff --git a/Domain/Events/EventType.cs b/Domain/Events/EventType.cs index d0ed879..2654cd6 100644 --- a/Domain/Events/EventType.cs +++ b/Domain/Events/EventType.cs @@ -15,7 +15,8 @@ public enum EventType MEMBER_LOCKED, MEMBER_UNLOCKED, MEMBER_DELETED, - MEMBER_UPDATED, + MEMBER_EMAIL_CHANGED, + MEMBER_FULL_NAME_CHANGED, ReservationCreatedEvent, ReservationRejectedEvent, ReservationLimitExceeded, diff --git a/Domain/Events/Member/MemberEmailChangedEvent.cs b/Domain/Events/Member/MemberEmailChangedEvent.cs new file mode 100644 index 0000000..bbe8ac3 --- /dev/null +++ b/Domain/Events/Member/MemberEmailChangedEvent.cs @@ -0,0 +1,6 @@ +namespace PlayOfferService.Domain.Events.Member; + +public class MemberEmailChangedEvent : DomainEvent +{ + public string Email { get; set; } +} \ No newline at end of file diff --git a/Domain/Events/Member/MemberFullNameChangedEvent.cs b/Domain/Events/Member/MemberFullNameChangedEvent.cs new file mode 100644 index 0000000..4bb30e4 --- /dev/null +++ b/Domain/Events/Member/MemberFullNameChangedEvent.cs @@ -0,0 +1,8 @@ +using PlayOfferService.Domain.ValueObjects; + +namespace PlayOfferService.Domain.Events.Member; + +public class MemberFullNameChangedEvent : DomainEvent +{ + public FullName FullName { get; set; } +} \ No newline at end of file diff --git a/Domain/Events/Member/MemberUpdatedEvent.cs b/Domain/Events/Member/MemberUpdatedEvent.cs deleted file mode 100644 index b47bb43..0000000 --- a/Domain/Events/Member/MemberUpdatedEvent.cs +++ /dev/null @@ -1,13 +0,0 @@ -using PlayOfferService.Domain.Models; -using PlayOfferService.Domain.ValueObjects; - -namespace PlayOfferService.Domain.Events.Member; - -public class MemberUpdatedEvent : DomainEvent -{ - public MemberId MemberId { get; set; } - public FullName Name { get; set; } - public string Email { get; set; } - public TennisClubId TennisClubId { get; set; } - public Status Status { get; set; } -} \ No newline at end of file diff --git a/Domain/Models/Member.cs b/Domain/Models/Member.cs index 2d88320..c548031 100644 --- a/Domain/Models/Member.cs +++ b/Domain/Models/Member.cs @@ -11,17 +11,16 @@ public class Member public string? Email { get; set; } public string? FirstName { get; set; } public string? LastName { get; set; } - + public Status Status { get; set; } public void Apply(List baseEvents) { foreach (var baseEvent in baseEvents) - { switch (baseEvent.EventType) { case EventType.MEMBER_REGISTERED: - Apply((MemberCreatedEvent) baseEvent.EventData); + Apply((MemberCreatedEvent)baseEvent.EventData); break; case EventType.MEMBER_LOCKED: ApplyMemberLockedEvent(); @@ -32,23 +31,27 @@ public void Apply(List baseEvents) case EventType.MEMBER_DELETED: ApplyMemberDeletedEvent(); break; - case EventType.MEMBER_UPDATED: - ApplyMemberUpdatedEvent((MemberUpdatedEvent) baseEvent.EventData); + case EventType.MEMBER_EMAIL_CHANGED: + ApplyMemberEmailChangedEvent((MemberEmailChangedEvent)baseEvent.EventData); + break; + case EventType.MEMBER_FULL_NAME_CHANGED: + ApplyMemberFullNameChangedEvent((MemberFullNameChangedEvent)baseEvent.EventData); break; default: - throw new ArgumentOutOfRangeException($"{nameof(baseEvent.EventType)} is not supported for the entity Member!"); + throw new ArgumentOutOfRangeException( + $"{nameof(baseEvent.EventType)} is not supported for the entity Member!"); } - } } - private void ApplyMemberUpdatedEvent(MemberUpdatedEvent baseEventData) + private void ApplyMemberEmailChangedEvent(MemberEmailChangedEvent baseEventEventData) + { + Email = baseEventEventData.Email; + } + + private void ApplyMemberFullNameChangedEvent(MemberFullNameChangedEvent baseEventEventData) { - Id = baseEventData.MemberId.Id; - Email = baseEventData.Email; - FirstName = baseEventData.Name.FirstName; - LastName = baseEventData.Name.LastName; - ClubId = baseEventData.TennisClubId.Id; - Status = baseEventData.Status; + FirstName = baseEventEventData.FullName.FirstName; + LastName = baseEventEventData.FullName.LastName; } private void Apply(MemberCreatedEvent domainEvent) @@ -60,17 +63,17 @@ private void Apply(MemberCreatedEvent domainEvent) ClubId = domainEvent.TennisClubId.Id; Status = domainEvent.Status; } - + private void ApplyMemberLockedEvent() { Status = Status.LOCKED; } - + private void ApplyMemberUnlockedEvent() { Status = Status.ACTIVE; } - + private void ApplyMemberDeletedEvent() { Status = Status.DELETED; From 9baa887ac6aca7f339248239fb5b16c9da48ec0c Mon Sep 17 00:00:00 2001 From: CengoleFHV Date: Thu, 6 Jun 2024 23:45:37 +0200 Subject: [PATCH 08/18] added Club Name Changed Event --- Application/RedisClubStreamService.cs | 25 +++++++++++----------- Domain/Events/Club/ClubNameChangedEvent.cs | 6 ++++++ Domain/Events/DomainEvent.cs | 4 +++- Domain/Events/EventType.cs | 1 + Domain/Models/Club.cs | 22 +++++++++++++------ 5 files changed, 39 insertions(+), 19 deletions(-) create mode 100644 Domain/Events/Club/ClubNameChangedEvent.cs diff --git a/Application/RedisClubStreamService.cs b/Application/RedisClubStreamService.cs index 6cc0b50..a54356c 100644 --- a/Application/RedisClubStreamService.cs +++ b/Application/RedisClubStreamService.cs @@ -1,8 +1,7 @@ -using System.Text.Json.Nodes; using MediatR; using PlayOfferService.Domain.Events; -using PlayOfferService.Domain.Repositories; using StackExchange.Redis; +using System.Text.Json.Nodes; namespace PlayOfferService.Application; @@ -13,8 +12,8 @@ public class RedisClubStreamService : BackgroundService private readonly IDatabase _db; private const string StreamName = "club_service_events.public.DomainEvent"; private const string GroupName = "pos.club.events.group"; - - + + public RedisClubStreamService(IServiceScopeFactory serviceScopeFactory) { _serviceScopeFactory = serviceScopeFactory; @@ -28,13 +27,13 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) { using IServiceScope scope = _serviceScopeFactory.CreateScope(); IMediator mediator = scope.ServiceProvider.GetRequiredService(); - + if (!(await _db.KeyExistsAsync(StreamName)) || - (await _db.StreamGroupInfoAsync(StreamName)).All(x=>x.Name!=GroupName)) + (await _db.StreamGroupInfoAsync(StreamName)).All(x => x.Name != GroupName)) { await _db.StreamCreateConsumerGroupAsync(StreamName, GroupName, "0-0"); } - + var id = string.Empty; while (!_cancellationToken.IsCancellationRequested) @@ -58,24 +57,26 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) } } - + private TechnicalClubEvent? FilterandParseEvent(StreamEntry value) { var dict = value.Values.ToDictionary(x => x.Name.ToString(), x => x.Value.ToString()); var jsonContent = JsonNode.Parse(dict.Values.First()); var eventInfo = jsonContent["payload"]["after"]; - + var eventType = eventInfo["eventType"].GetValue(); var entityType = eventInfo["entityType"].GetValue(); - + if ((eventType != "TENNIS_CLUB_REGISTERED" && eventType != "TENNIS_CLUB_LOCKED" && eventType != "TENNIS_CLUB_UNLOCKED" - && eventType != "TENNIS_CLUB_DELETED") || entityType != "TENNIS_CLUB") + && eventType != "TENNIS_CLUB_DELETED" + && eventType != "TENNIS_CLUB_NAME_CHANGED" + ) || entityType != "TENNIS_CLUB") { return null; } - + return EventParser.ParseEvent(eventInfo); } } \ No newline at end of file diff --git a/Domain/Events/Club/ClubNameChangedEvent.cs b/Domain/Events/Club/ClubNameChangedEvent.cs new file mode 100644 index 0000000..4f908a3 --- /dev/null +++ b/Domain/Events/Club/ClubNameChangedEvent.cs @@ -0,0 +1,6 @@ +namespace PlayOfferService.Domain.Events.Club; + +public class ClubNameChangedEvent : DomainEvent +{ + public string Name { get; set; } +} diff --git a/Domain/Events/DomainEvent.cs b/Domain/Events/DomainEvent.cs index 35d9a06..6773c77 100644 --- a/Domain/Events/DomainEvent.cs +++ b/Domain/Events/DomainEvent.cs @@ -1,8 +1,9 @@ -using System.Text.Json.Serialization; +using PlayOfferService.Domain.Events.Club; using PlayOfferService.Domain.Events.Court; using PlayOfferService.Domain.Events.Member; using PlayOfferService.Domain.Events.PlayOffer; using PlayOfferService.Domain.Events.Reservation; +using System.Text.Json.Serialization; namespace PlayOfferService.Domain.Events; @@ -11,6 +12,7 @@ namespace PlayOfferService.Domain.Events; [JsonDerivedType(typeof(ClubLockedEvent), typeDiscriminator: "TENNIS_CLUB_LOCKED")] [JsonDerivedType(typeof(ClubUnlockedEvent), typeDiscriminator: "TENNIS_CLUB_UNLOCKED")] [JsonDerivedType(typeof(ClubDeletedEvent), typeDiscriminator: "TENNIS_CLUB_DELETED")] +[JsonDerivedType(typeof(ClubNameChangedEvent), typeDiscriminator: "TENNIS_CLUB_NAME_CHANGED")] [JsonDerivedType(typeof(MemberCreatedEvent), typeDiscriminator: "MEMBER_REGISTERED")] [JsonDerivedType(typeof(MemberLockedEvent), typeDiscriminator: "MEMBER_LOCKED")] [JsonDerivedType(typeof(MemberUnlockedEvent), typeDiscriminator: "MEMBER_UNLOCKED")] diff --git a/Domain/Events/EventType.cs b/Domain/Events/EventType.cs index 2654cd6..d56fefd 100644 --- a/Domain/Events/EventType.cs +++ b/Domain/Events/EventType.cs @@ -11,6 +11,7 @@ public enum EventType TENNIS_CLUB_LOCKED, TENNIS_CLUB_UNLOCKED, TENNIS_CLUB_DELETED, + TENNIS_CLUB_NAME_CHANGED, MEMBER_REGISTERED, MEMBER_LOCKED, MEMBER_UNLOCKED, diff --git a/Domain/Models/Club.cs b/Domain/Models/Club.cs index 84fabae..2adbf47 100644 --- a/Domain/Models/Club.cs +++ b/Domain/Models/Club.cs @@ -1,5 +1,6 @@ -using System.ComponentModel.DataAnnotations.Schema; using PlayOfferService.Domain.Events; +using PlayOfferService.Domain.Events.Club; +using System.ComponentModel.DataAnnotations.Schema; namespace PlayOfferService.Domain.Models; @@ -7,6 +8,7 @@ public class Club { [DatabaseGenerated(DatabaseGeneratedOption.None)] public Guid Id { get; set; } + public string Name { get; set; } public Status Status { get; set; } public void Apply(List baseEvents) @@ -16,7 +18,7 @@ public void Apply(List baseEvents) switch (baseEvent.EventType) { case EventType.TENNIS_CLUB_REGISTERED: - ApplyClubCreatedEvent((ClubCreatedEvent) baseEvent.EventData); + ApplyClubCreatedEvent((ClubCreatedEvent)baseEvent.EventData); break; case EventType.TENNIS_CLUB_LOCKED: ApplyClubLockedEvent(); @@ -27,29 +29,37 @@ public void Apply(List baseEvents) case EventType.TENNIS_CLUB_DELETED: ApplyClubDeletedEvent(); break; + case EventType.TENNIS_CLUB_NAME_CHANGED: + ApplyClubNameChangedEvent((ClubNameChangedEvent)baseEvent.EventData); + break; default: throw new ArgumentOutOfRangeException($"{nameof(baseEvent.EventType)} is not supported for the entity Club!"); } } } - + private void ApplyClubCreatedEvent(ClubCreatedEvent domainEvent) { Id = domainEvent.TennisClubId.Id; } - + private void ApplyClubLockedEvent() { Status = Status.LOCKED; } - + private void ApplyClubUnlockedEvent() { Status = Status.ACTIVE; } - + private void ApplyClubDeletedEvent() { Status = Status.DELETED; } + + private void ApplyClubNameChangedEvent(ClubNameChangedEvent domainEvent) + { + Name = domainEvent.Name; + } } \ No newline at end of file From 7c6882816513087c84c56af637820cbdad7a32a6 Mon Sep 17 00:00:00 2001 From: CengoleFHV Date: Wed, 5 Jun 2024 01:17:46 +0200 Subject: [PATCH 09/18] added properties to Member --- Domain/Models/Member.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Domain/Models/Member.cs b/Domain/Models/Member.cs index cd75bdf..f771f0e 100644 --- a/Domain/Models/Member.cs +++ b/Domain/Models/Member.cs @@ -7,6 +7,10 @@ public class Member { public Guid Id { get; set; } public Guid ClubId { get; set; } + + public string? Email { get; set; } + public string? FullName { get; set; } + public string? ClubName { get; set; } public Status Status { get; set; } From 9e41f2e99d8f3c5c642822c826788860a870d986 Mon Sep 17 00:00:00 2001 From: CengoleFHV Date: Wed, 5 Jun 2024 20:56:42 +0200 Subject: [PATCH 10/18] expanded Member props and added MEMBER_UPDATED Event --- Application/RedisMemberStreamService.cs | 8 ++++++-- Domain/Events/DomainEvent.cs | 1 + Domain/Events/EventType.cs | 1 + Domain/Events/Member/MemberUpdatedEvent.cs | 13 +++++++++++++ Domain/Models/Member.cs | 22 +++++++++++++++++++--- 5 files changed, 40 insertions(+), 5 deletions(-) create mode 100644 Domain/Events/Member/MemberUpdatedEvent.cs diff --git a/Application/RedisMemberStreamService.cs b/Application/RedisMemberStreamService.cs index 9a72278..5a43b0c 100644 --- a/Application/RedisMemberStreamService.cs +++ b/Application/RedisMemberStreamService.cs @@ -67,10 +67,14 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) var eventType = eventInfo["eventType"].GetValue(); var entityType = eventInfo["entityType"].GetValue(); - if ((eventType != "MEMBER_REGISTERED" + if ( + (eventType != "MEMBER_REGISTERED" && eventType != "MEMBER_DELETED" && eventType != "MEMBER_LOCKED" - && eventType != "MEMBER_UNLOCKED") || entityType != "MEMBER") + && eventType != "MEMBER_UNLOCKED" + && eventType != "MEMBER_UPDATED") + || entityType != "MEMBER" + ) { return null; } diff --git a/Domain/Events/DomainEvent.cs b/Domain/Events/DomainEvent.cs index e912bc2..86d2f01 100644 --- a/Domain/Events/DomainEvent.cs +++ b/Domain/Events/DomainEvent.cs @@ -15,6 +15,7 @@ namespace PlayOfferService.Domain.Events; [JsonDerivedType(typeof(MemberLockedEvent), typeDiscriminator: "MEMBER_LOCKED")] [JsonDerivedType(typeof(MemberUnlockedEvent), typeDiscriminator: "MEMBER_UNLOCKED")] [JsonDerivedType(typeof(MemberDeletedEvent), typeDiscriminator: "MEMBER_DELETED")] +[JsonDerivedType(typeof(MemberUpdatedEvent), typeDiscriminator: "MEMBER_UPDATED")] [JsonDerivedType(typeof(PlayOfferCreatedEvent), typeDiscriminator: "PLAYOFFER_CREATED")] [JsonDerivedType(typeof(PlayOfferJoinedEvent), typeDiscriminator: "PLAYOFFER_JOINED")] [JsonDerivedType(typeof(PlayOfferCancelledEvent), typeDiscriminator: "PLAYOFFER_CANCELLED")] diff --git a/Domain/Events/EventType.cs b/Domain/Events/EventType.cs index a4d6e04..d0ed879 100644 --- a/Domain/Events/EventType.cs +++ b/Domain/Events/EventType.cs @@ -15,6 +15,7 @@ public enum EventType MEMBER_LOCKED, MEMBER_UNLOCKED, MEMBER_DELETED, + MEMBER_UPDATED, ReservationCreatedEvent, ReservationRejectedEvent, ReservationLimitExceeded, diff --git a/Domain/Events/Member/MemberUpdatedEvent.cs b/Domain/Events/Member/MemberUpdatedEvent.cs new file mode 100644 index 0000000..b47bb43 --- /dev/null +++ b/Domain/Events/Member/MemberUpdatedEvent.cs @@ -0,0 +1,13 @@ +using PlayOfferService.Domain.Models; +using PlayOfferService.Domain.ValueObjects; + +namespace PlayOfferService.Domain.Events.Member; + +public class MemberUpdatedEvent : DomainEvent +{ + public MemberId MemberId { get; set; } + public FullName Name { get; set; } + public string Email { get; set; } + public TennisClubId TennisClubId { get; set; } + public Status Status { get; set; } +} \ No newline at end of file diff --git a/Domain/Models/Member.cs b/Domain/Models/Member.cs index f771f0e..2d88320 100644 --- a/Domain/Models/Member.cs +++ b/Domain/Models/Member.cs @@ -9,8 +9,8 @@ public class Member public Guid ClubId { get; set; } public string? Email { get; set; } - public string? FullName { get; set; } - public string? ClubName { get; set; } + public string? FirstName { get; set; } + public string? LastName { get; set; } public Status Status { get; set; } @@ -32,15 +32,31 @@ public void Apply(List baseEvents) case EventType.MEMBER_DELETED: ApplyMemberDeletedEvent(); break; + case EventType.MEMBER_UPDATED: + ApplyMemberUpdatedEvent((MemberUpdatedEvent) baseEvent.EventData); + break; default: throw new ArgumentOutOfRangeException($"{nameof(baseEvent.EventType)} is not supported for the entity Member!"); } } } - + + private void ApplyMemberUpdatedEvent(MemberUpdatedEvent baseEventData) + { + Id = baseEventData.MemberId.Id; + Email = baseEventData.Email; + FirstName = baseEventData.Name.FirstName; + LastName = baseEventData.Name.LastName; + ClubId = baseEventData.TennisClubId.Id; + Status = baseEventData.Status; + } + private void Apply(MemberCreatedEvent domainEvent) { Id = domainEvent.MemberId.Id; + Email = domainEvent.Email; + FirstName = domainEvent.Name.FirstName; + LastName = domainEvent.Name.LastName; ClubId = domainEvent.TennisClubId.Id; Status = domainEvent.Status; } From 5d29c3ed5f12f5126ae8347d5dee5c98b8a81ece Mon Sep 17 00:00:00 2001 From: CengoleFHV Date: Wed, 5 Jun 2024 21:50:27 +0200 Subject: [PATCH 11/18] changed fom updatedEvent to Email and FullName Event --- Application/RedisMemberStreamService.cs | 4 +- Domain/Events/DomainEvent.cs | 3 +- Domain/Events/EventType.cs | 3 +- .../Events/Member/MemberEmailChangedEvent.cs | 6 +++ .../Member/MemberFullNameChangedEvent.cs | 8 ++++ Domain/Events/Member/MemberUpdatedEvent.cs | 13 ------- Domain/Models/Member.cs | 37 ++++++++++--------- 7 files changed, 41 insertions(+), 33 deletions(-) create mode 100644 Domain/Events/Member/MemberEmailChangedEvent.cs create mode 100644 Domain/Events/Member/MemberFullNameChangedEvent.cs delete mode 100644 Domain/Events/Member/MemberUpdatedEvent.cs diff --git a/Application/RedisMemberStreamService.cs b/Application/RedisMemberStreamService.cs index 5a43b0c..8f2bdcf 100644 --- a/Application/RedisMemberStreamService.cs +++ b/Application/RedisMemberStreamService.cs @@ -72,7 +72,9 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) && eventType != "MEMBER_DELETED" && eventType != "MEMBER_LOCKED" && eventType != "MEMBER_UNLOCKED" - && eventType != "MEMBER_UPDATED") + && eventType != "MEMBER_EMAIL_CHANGED" + && eventType != "MEMBER_FULL_NAME_CHANGED" + ) || entityType != "MEMBER" ) { diff --git a/Domain/Events/DomainEvent.cs b/Domain/Events/DomainEvent.cs index 86d2f01..35d9a06 100644 --- a/Domain/Events/DomainEvent.cs +++ b/Domain/Events/DomainEvent.cs @@ -15,7 +15,8 @@ namespace PlayOfferService.Domain.Events; [JsonDerivedType(typeof(MemberLockedEvent), typeDiscriminator: "MEMBER_LOCKED")] [JsonDerivedType(typeof(MemberUnlockedEvent), typeDiscriminator: "MEMBER_UNLOCKED")] [JsonDerivedType(typeof(MemberDeletedEvent), typeDiscriminator: "MEMBER_DELETED")] -[JsonDerivedType(typeof(MemberUpdatedEvent), typeDiscriminator: "MEMBER_UPDATED")] +[JsonDerivedType(typeof(MemberEmailChangedEvent), typeDiscriminator: "MEMBER_EMAIL_CHANGED")] +[JsonDerivedType(typeof(MemberFullNameChangedEvent), typeDiscriminator: "MEMBER_FULL_NAME_CHANGED")] [JsonDerivedType(typeof(PlayOfferCreatedEvent), typeDiscriminator: "PLAYOFFER_CREATED")] [JsonDerivedType(typeof(PlayOfferJoinedEvent), typeDiscriminator: "PLAYOFFER_JOINED")] [JsonDerivedType(typeof(PlayOfferCancelledEvent), typeDiscriminator: "PLAYOFFER_CANCELLED")] diff --git a/Domain/Events/EventType.cs b/Domain/Events/EventType.cs index d0ed879..2654cd6 100644 --- a/Domain/Events/EventType.cs +++ b/Domain/Events/EventType.cs @@ -15,7 +15,8 @@ public enum EventType MEMBER_LOCKED, MEMBER_UNLOCKED, MEMBER_DELETED, - MEMBER_UPDATED, + MEMBER_EMAIL_CHANGED, + MEMBER_FULL_NAME_CHANGED, ReservationCreatedEvent, ReservationRejectedEvent, ReservationLimitExceeded, diff --git a/Domain/Events/Member/MemberEmailChangedEvent.cs b/Domain/Events/Member/MemberEmailChangedEvent.cs new file mode 100644 index 0000000..bbe8ac3 --- /dev/null +++ b/Domain/Events/Member/MemberEmailChangedEvent.cs @@ -0,0 +1,6 @@ +namespace PlayOfferService.Domain.Events.Member; + +public class MemberEmailChangedEvent : DomainEvent +{ + public string Email { get; set; } +} \ No newline at end of file diff --git a/Domain/Events/Member/MemberFullNameChangedEvent.cs b/Domain/Events/Member/MemberFullNameChangedEvent.cs new file mode 100644 index 0000000..4bb30e4 --- /dev/null +++ b/Domain/Events/Member/MemberFullNameChangedEvent.cs @@ -0,0 +1,8 @@ +using PlayOfferService.Domain.ValueObjects; + +namespace PlayOfferService.Domain.Events.Member; + +public class MemberFullNameChangedEvent : DomainEvent +{ + public FullName FullName { get; set; } +} \ No newline at end of file diff --git a/Domain/Events/Member/MemberUpdatedEvent.cs b/Domain/Events/Member/MemberUpdatedEvent.cs deleted file mode 100644 index b47bb43..0000000 --- a/Domain/Events/Member/MemberUpdatedEvent.cs +++ /dev/null @@ -1,13 +0,0 @@ -using PlayOfferService.Domain.Models; -using PlayOfferService.Domain.ValueObjects; - -namespace PlayOfferService.Domain.Events.Member; - -public class MemberUpdatedEvent : DomainEvent -{ - public MemberId MemberId { get; set; } - public FullName Name { get; set; } - public string Email { get; set; } - public TennisClubId TennisClubId { get; set; } - public Status Status { get; set; } -} \ No newline at end of file diff --git a/Domain/Models/Member.cs b/Domain/Models/Member.cs index 2d88320..c548031 100644 --- a/Domain/Models/Member.cs +++ b/Domain/Models/Member.cs @@ -11,17 +11,16 @@ public class Member public string? Email { get; set; } public string? FirstName { get; set; } public string? LastName { get; set; } - + public Status Status { get; set; } public void Apply(List baseEvents) { foreach (var baseEvent in baseEvents) - { switch (baseEvent.EventType) { case EventType.MEMBER_REGISTERED: - Apply((MemberCreatedEvent) baseEvent.EventData); + Apply((MemberCreatedEvent)baseEvent.EventData); break; case EventType.MEMBER_LOCKED: ApplyMemberLockedEvent(); @@ -32,23 +31,27 @@ public void Apply(List baseEvents) case EventType.MEMBER_DELETED: ApplyMemberDeletedEvent(); break; - case EventType.MEMBER_UPDATED: - ApplyMemberUpdatedEvent((MemberUpdatedEvent) baseEvent.EventData); + case EventType.MEMBER_EMAIL_CHANGED: + ApplyMemberEmailChangedEvent((MemberEmailChangedEvent)baseEvent.EventData); + break; + case EventType.MEMBER_FULL_NAME_CHANGED: + ApplyMemberFullNameChangedEvent((MemberFullNameChangedEvent)baseEvent.EventData); break; default: - throw new ArgumentOutOfRangeException($"{nameof(baseEvent.EventType)} is not supported for the entity Member!"); + throw new ArgumentOutOfRangeException( + $"{nameof(baseEvent.EventType)} is not supported for the entity Member!"); } - } } - private void ApplyMemberUpdatedEvent(MemberUpdatedEvent baseEventData) + private void ApplyMemberEmailChangedEvent(MemberEmailChangedEvent baseEventEventData) + { + Email = baseEventEventData.Email; + } + + private void ApplyMemberFullNameChangedEvent(MemberFullNameChangedEvent baseEventEventData) { - Id = baseEventData.MemberId.Id; - Email = baseEventData.Email; - FirstName = baseEventData.Name.FirstName; - LastName = baseEventData.Name.LastName; - ClubId = baseEventData.TennisClubId.Id; - Status = baseEventData.Status; + FirstName = baseEventEventData.FullName.FirstName; + LastName = baseEventEventData.FullName.LastName; } private void Apply(MemberCreatedEvent domainEvent) @@ -60,17 +63,17 @@ private void Apply(MemberCreatedEvent domainEvent) ClubId = domainEvent.TennisClubId.Id; Status = domainEvent.Status; } - + private void ApplyMemberLockedEvent() { Status = Status.LOCKED; } - + private void ApplyMemberUnlockedEvent() { Status = Status.ACTIVE; } - + private void ApplyMemberDeletedEvent() { Status = Status.DELETED; From 1f04ba96ddb11b5ebb608a8234330ac3c5a4c398 Mon Sep 17 00:00:00 2001 From: CengoleFHV Date: Wed, 5 Jun 2024 20:56:42 +0200 Subject: [PATCH 12/18] expanded Member props and added MEMBER_UPDATED Event --- Domain/Events/Member/MemberUpdatedEvent.cs | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 Domain/Events/Member/MemberUpdatedEvent.cs diff --git a/Domain/Events/Member/MemberUpdatedEvent.cs b/Domain/Events/Member/MemberUpdatedEvent.cs new file mode 100644 index 0000000..b47bb43 --- /dev/null +++ b/Domain/Events/Member/MemberUpdatedEvent.cs @@ -0,0 +1,13 @@ +using PlayOfferService.Domain.Models; +using PlayOfferService.Domain.ValueObjects; + +namespace PlayOfferService.Domain.Events.Member; + +public class MemberUpdatedEvent : DomainEvent +{ + public MemberId MemberId { get; set; } + public FullName Name { get; set; } + public string Email { get; set; } + public TennisClubId TennisClubId { get; set; } + public Status Status { get; set; } +} \ No newline at end of file From 107660ce0761fe90ab7e5a16e207b8393b447798 Mon Sep 17 00:00:00 2001 From: CengoleFHV Date: Wed, 5 Jun 2024 21:50:27 +0200 Subject: [PATCH 13/18] changed fom updatedEvent to Email and FullName Event --- Domain/Events/Member/MemberUpdatedEvent.cs | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 Domain/Events/Member/MemberUpdatedEvent.cs diff --git a/Domain/Events/Member/MemberUpdatedEvent.cs b/Domain/Events/Member/MemberUpdatedEvent.cs deleted file mode 100644 index b47bb43..0000000 --- a/Domain/Events/Member/MemberUpdatedEvent.cs +++ /dev/null @@ -1,13 +0,0 @@ -using PlayOfferService.Domain.Models; -using PlayOfferService.Domain.ValueObjects; - -namespace PlayOfferService.Domain.Events.Member; - -public class MemberUpdatedEvent : DomainEvent -{ - public MemberId MemberId { get; set; } - public FullName Name { get; set; } - public string Email { get; set; } - public TennisClubId TennisClubId { get; set; } - public Status Status { get; set; } -} \ No newline at end of file From b0d6332604f4b8478ebe5662f67cb47129e4beab Mon Sep 17 00:00:00 2001 From: CengoleFHV Date: Thu, 6 Jun 2024 23:45:37 +0200 Subject: [PATCH 14/18] added Club Name Changed Event --- Application/RedisClubStreamService.cs | 25 +++++++++++----------- Domain/Events/Club/ClubNameChangedEvent.cs | 6 ++++++ Domain/Events/DomainEvent.cs | 4 +++- Domain/Events/EventType.cs | 1 + Domain/Models/Club.cs | 22 +++++++++++++------ 5 files changed, 39 insertions(+), 19 deletions(-) create mode 100644 Domain/Events/Club/ClubNameChangedEvent.cs diff --git a/Application/RedisClubStreamService.cs b/Application/RedisClubStreamService.cs index 6cc0b50..a54356c 100644 --- a/Application/RedisClubStreamService.cs +++ b/Application/RedisClubStreamService.cs @@ -1,8 +1,7 @@ -using System.Text.Json.Nodes; using MediatR; using PlayOfferService.Domain.Events; -using PlayOfferService.Domain.Repositories; using StackExchange.Redis; +using System.Text.Json.Nodes; namespace PlayOfferService.Application; @@ -13,8 +12,8 @@ public class RedisClubStreamService : BackgroundService private readonly IDatabase _db; private const string StreamName = "club_service_events.public.DomainEvent"; private const string GroupName = "pos.club.events.group"; - - + + public RedisClubStreamService(IServiceScopeFactory serviceScopeFactory) { _serviceScopeFactory = serviceScopeFactory; @@ -28,13 +27,13 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) { using IServiceScope scope = _serviceScopeFactory.CreateScope(); IMediator mediator = scope.ServiceProvider.GetRequiredService(); - + if (!(await _db.KeyExistsAsync(StreamName)) || - (await _db.StreamGroupInfoAsync(StreamName)).All(x=>x.Name!=GroupName)) + (await _db.StreamGroupInfoAsync(StreamName)).All(x => x.Name != GroupName)) { await _db.StreamCreateConsumerGroupAsync(StreamName, GroupName, "0-0"); } - + var id = string.Empty; while (!_cancellationToken.IsCancellationRequested) @@ -58,24 +57,26 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken) } } - + private TechnicalClubEvent? FilterandParseEvent(StreamEntry value) { var dict = value.Values.ToDictionary(x => x.Name.ToString(), x => x.Value.ToString()); var jsonContent = JsonNode.Parse(dict.Values.First()); var eventInfo = jsonContent["payload"]["after"]; - + var eventType = eventInfo["eventType"].GetValue(); var entityType = eventInfo["entityType"].GetValue(); - + if ((eventType != "TENNIS_CLUB_REGISTERED" && eventType != "TENNIS_CLUB_LOCKED" && eventType != "TENNIS_CLUB_UNLOCKED" - && eventType != "TENNIS_CLUB_DELETED") || entityType != "TENNIS_CLUB") + && eventType != "TENNIS_CLUB_DELETED" + && eventType != "TENNIS_CLUB_NAME_CHANGED" + ) || entityType != "TENNIS_CLUB") { return null; } - + return EventParser.ParseEvent(eventInfo); } } \ No newline at end of file diff --git a/Domain/Events/Club/ClubNameChangedEvent.cs b/Domain/Events/Club/ClubNameChangedEvent.cs new file mode 100644 index 0000000..4f908a3 --- /dev/null +++ b/Domain/Events/Club/ClubNameChangedEvent.cs @@ -0,0 +1,6 @@ +namespace PlayOfferService.Domain.Events.Club; + +public class ClubNameChangedEvent : DomainEvent +{ + public string Name { get; set; } +} diff --git a/Domain/Events/DomainEvent.cs b/Domain/Events/DomainEvent.cs index 35d9a06..6773c77 100644 --- a/Domain/Events/DomainEvent.cs +++ b/Domain/Events/DomainEvent.cs @@ -1,8 +1,9 @@ -using System.Text.Json.Serialization; +using PlayOfferService.Domain.Events.Club; using PlayOfferService.Domain.Events.Court; using PlayOfferService.Domain.Events.Member; using PlayOfferService.Domain.Events.PlayOffer; using PlayOfferService.Domain.Events.Reservation; +using System.Text.Json.Serialization; namespace PlayOfferService.Domain.Events; @@ -11,6 +12,7 @@ namespace PlayOfferService.Domain.Events; [JsonDerivedType(typeof(ClubLockedEvent), typeDiscriminator: "TENNIS_CLUB_LOCKED")] [JsonDerivedType(typeof(ClubUnlockedEvent), typeDiscriminator: "TENNIS_CLUB_UNLOCKED")] [JsonDerivedType(typeof(ClubDeletedEvent), typeDiscriminator: "TENNIS_CLUB_DELETED")] +[JsonDerivedType(typeof(ClubNameChangedEvent), typeDiscriminator: "TENNIS_CLUB_NAME_CHANGED")] [JsonDerivedType(typeof(MemberCreatedEvent), typeDiscriminator: "MEMBER_REGISTERED")] [JsonDerivedType(typeof(MemberLockedEvent), typeDiscriminator: "MEMBER_LOCKED")] [JsonDerivedType(typeof(MemberUnlockedEvent), typeDiscriminator: "MEMBER_UNLOCKED")] diff --git a/Domain/Events/EventType.cs b/Domain/Events/EventType.cs index 2654cd6..d56fefd 100644 --- a/Domain/Events/EventType.cs +++ b/Domain/Events/EventType.cs @@ -11,6 +11,7 @@ public enum EventType TENNIS_CLUB_LOCKED, TENNIS_CLUB_UNLOCKED, TENNIS_CLUB_DELETED, + TENNIS_CLUB_NAME_CHANGED, MEMBER_REGISTERED, MEMBER_LOCKED, MEMBER_UNLOCKED, diff --git a/Domain/Models/Club.cs b/Domain/Models/Club.cs index 84fabae..2adbf47 100644 --- a/Domain/Models/Club.cs +++ b/Domain/Models/Club.cs @@ -1,5 +1,6 @@ -using System.ComponentModel.DataAnnotations.Schema; using PlayOfferService.Domain.Events; +using PlayOfferService.Domain.Events.Club; +using System.ComponentModel.DataAnnotations.Schema; namespace PlayOfferService.Domain.Models; @@ -7,6 +8,7 @@ public class Club { [DatabaseGenerated(DatabaseGeneratedOption.None)] public Guid Id { get; set; } + public string Name { get; set; } public Status Status { get; set; } public void Apply(List baseEvents) @@ -16,7 +18,7 @@ public void Apply(List baseEvents) switch (baseEvent.EventType) { case EventType.TENNIS_CLUB_REGISTERED: - ApplyClubCreatedEvent((ClubCreatedEvent) baseEvent.EventData); + ApplyClubCreatedEvent((ClubCreatedEvent)baseEvent.EventData); break; case EventType.TENNIS_CLUB_LOCKED: ApplyClubLockedEvent(); @@ -27,29 +29,37 @@ public void Apply(List baseEvents) case EventType.TENNIS_CLUB_DELETED: ApplyClubDeletedEvent(); break; + case EventType.TENNIS_CLUB_NAME_CHANGED: + ApplyClubNameChangedEvent((ClubNameChangedEvent)baseEvent.EventData); + break; default: throw new ArgumentOutOfRangeException($"{nameof(baseEvent.EventType)} is not supported for the entity Club!"); } } } - + private void ApplyClubCreatedEvent(ClubCreatedEvent domainEvent) { Id = domainEvent.TennisClubId.Id; } - + private void ApplyClubLockedEvent() { Status = Status.LOCKED; } - + private void ApplyClubUnlockedEvent() { Status = Status.ACTIVE; } - + private void ApplyClubDeletedEvent() { Status = Status.DELETED; } + + private void ApplyClubNameChangedEvent(ClubNameChangedEvent domainEvent) + { + Name = domainEvent.Name; + } } \ No newline at end of file From c512c3d7136e64f456f24716e99ed5cf7bfdcb8f Mon Sep 17 00:00:00 2001 From: CengoleFHV Date: Fri, 7 Jun 2024 13:45:27 +0200 Subject: [PATCH 15/18] fixed tests --- Domain/DbReadContext.cs | 16 +- Domain/Models/Club.cs | 1 + ...20240607112446_memberExpansion.Designer.cs | 259 ++++++++++++++++++ Migrations/20240607112446_memberExpansion.cs | 101 +++++++ Migrations/DbReadContextModelSnapshot.cs | 24 +- .../IntegrationTests/ClubEventHandlerTest.cs | 24 +- .../IntegrationTests/ClubRepositoryTest.cs | 18 +- .../MemberEventHandlerTest.cs | 37 +-- .../UnitTests/MemberUnitTest.cs | 27 +- 9 files changed, 446 insertions(+), 61 deletions(-) create mode 100644 Migrations/20240607112446_memberExpansion.Designer.cs create mode 100644 Migrations/20240607112446_memberExpansion.cs diff --git a/Domain/DbReadContext.cs b/Domain/DbReadContext.cs index 351cb4c..9ac7fc2 100644 --- a/Domain/DbReadContext.cs +++ b/Domain/DbReadContext.cs @@ -10,28 +10,28 @@ public class DbReadContext : DbContext public DbReadContext(DbContextOptions options) : base(options) { } - + public DbSet PlayOffers { get; set; } public DbSet Clubs { get; set; } public DbSet Members { get; set; } public DbSet Reservations { get; set; } public DbSet Courts { get; set; } public DbSet AppliedEvents { get; set; } - + protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.ApplyConfiguration(new BaseEventConfiguration()); - + // TODO: Remove before coop testing - var testClub = new Club{Id = Guid.Parse("06b812a7-5131-4510-82ff-bffac33e0f3e"), Status = Status.ACTIVE}; - var testMemberIds = new List {Guid.Parse("40c0981d-e2f8-4af3-ae6c-17f79f3ba8c2"), Guid.Parse("ccc1c8fc-89b5-4026-b190-9d9e7e7bc18d")}; - + var testClub = new Club { Id = Guid.Parse("06b812a7-5131-4510-82ff-bffac33e0f3e"), Name = "Test Club", Status = Status.ACTIVE }; + var testMemberIds = new List { Guid.Parse("40c0981d-e2f8-4af3-ae6c-17f79f3ba8c2"), Guid.Parse("ccc1c8fc-89b5-4026-b190-9d9e7e7bc18d") }; + var testMembers = new List{ new {Id = testMemberIds[0], ClubId = testClub.Id, Status = Status.ACTIVE}, new {Id = testMemberIds[1], ClubId = testClub.Id, Status = Status.ACTIVE} }; - + // Need to directly specify foreign keys for seeding var testPlayOffer = new { @@ -42,7 +42,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) ProposedEndTime = DateTime.UtcNow.AddHours(1), IsCancelled = false }; - + modelBuilder.Entity().HasData(testClub); foreach (var testMember in testMembers) { diff --git a/Domain/Models/Club.cs b/Domain/Models/Club.cs index 2adbf47..6c44814 100644 --- a/Domain/Models/Club.cs +++ b/Domain/Models/Club.cs @@ -41,6 +41,7 @@ public void Apply(List baseEvents) private void ApplyClubCreatedEvent(ClubCreatedEvent domainEvent) { Id = domainEvent.TennisClubId.Id; + Name = domainEvent.Name; } private void ApplyClubLockedEvent() diff --git a/Migrations/20240607112446_memberExpansion.Designer.cs b/Migrations/20240607112446_memberExpansion.Designer.cs new file mode 100644 index 0000000..5cf0c7b --- /dev/null +++ b/Migrations/20240607112446_memberExpansion.Designer.cs @@ -0,0 +1,259 @@ +// +using System; +using System.Collections.Generic; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using PlayOfferService.Domain; + +#nullable disable + +namespace PlayOfferService.Migrations +{ + [DbContext(typeof(DbReadContext))] + [Migration("20240607112446_memberExpansion")] + partial class memberExpansion + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.2") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("PlayOfferService.Domain.Events.BaseEvent", b => + { + b.Property("EventId") + .HasColumnType("uuid") + .HasColumnName("eventId"); + + b.Property("CorrelationId") + .HasColumnType("uuid") + .HasColumnName("correlationId"); + + b.Property("EntityId") + .HasColumnType("uuid") + .HasColumnName("entityId"); + + b.Property("EntityType") + .IsRequired() + .HasColumnType("text") + .HasColumnName("entityType"); + + b.Property("EventData") + .IsRequired() + .HasColumnType("text") + .HasColumnName("eventData"); + + b.Property("EventType") + .IsRequired() + .HasColumnType("text") + .HasColumnName("eventType"); + + b.Property("Timestamp") + .HasColumnType("timestamp with time zone") + .HasColumnName("timestamp"); + + b.HasKey("EventId") + .HasName("pK_events"); + + b.ToTable("events", (string)null); + }); + + modelBuilder.Entity("PlayOfferService.Domain.Models.Club", b => + { + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.Property("Status") + .HasColumnType("integer") + .HasColumnName("status"); + + b.HasKey("Id") + .HasName("pK_clubs"); + + b.ToTable("clubs", (string)null); + + b.HasData( + new + { + Id = new Guid("06b812a7-5131-4510-82ff-bffac33e0f3e"), + Name = "Test Club", + Status = 0 + }); + }); + + modelBuilder.Entity("PlayOfferService.Domain.Models.Court", b => + { + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ClubId") + .HasColumnType("uuid") + .HasColumnName("clubId"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + + b.HasKey("Id") + .HasName("pK_courts"); + + b.ToTable("courts", (string)null); + }); + + modelBuilder.Entity("PlayOfferService.Domain.Models.Member", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("ClubId") + .HasColumnType("uuid") + .HasColumnName("clubId"); + + b.Property("Email") + .HasColumnType("text") + .HasColumnName("email"); + + b.Property("FirstName") + .HasColumnType("text") + .HasColumnName("firstName"); + + b.Property("LastName") + .HasColumnType("text") + .HasColumnName("lastName"); + + b.Property("Status") + .HasColumnType("integer") + .HasColumnName("status"); + + b.HasKey("Id") + .HasName("pK_members"); + + b.ToTable("members", (string)null); + + b.HasData( + new + { + Id = new Guid("40c0981d-e2f8-4af3-ae6c-17f79f3ba8c2"), + ClubId = new Guid("06b812a7-5131-4510-82ff-bffac33e0f3e"), + Status = 0 + }, + new + { + Id = new Guid("ccc1c8fc-89b5-4026-b190-9d9e7e7bc18d"), + ClubId = new Guid("06b812a7-5131-4510-82ff-bffac33e0f3e"), + Status = 0 + }); + }); + + modelBuilder.Entity("PlayOfferService.Domain.Models.PlayOffer", b => + { + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property("AcceptedStartTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("acceptedStartTime"); + + b.Property("ClubId") + .HasColumnType("uuid") + .HasColumnName("clubId"); + + b.Property("CreatorId") + .HasColumnType("uuid") + .HasColumnName("creatorId"); + + b.Property("IsCancelled") + .HasColumnType("boolean") + .HasColumnName("isCancelled"); + + b.Property("OpponentId") + .HasColumnType("uuid") + .HasColumnName("opponentId"); + + b.Property("ProposedEndTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("proposedEndTime"); + + b.Property("ProposedStartTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("proposedStartTime"); + + b.Property("ReservationId") + .HasColumnType("uuid") + .HasColumnName("reservationId"); + + b.HasKey("Id") + .HasName("pK_playOffers"); + + b.ToTable("playOffers", (string)null); + + b.HasData( + new + { + Id = new Guid("7d079edb-d4c8-4e63-9c5b-35b80eaa69f6"), + ClubId = new Guid("06b812a7-5131-4510-82ff-bffac33e0f3e"), + CreatorId = new Guid("40c0981d-e2f8-4af3-ae6c-17f79f3ba8c2"), + IsCancelled = false, + ProposedEndTime = new DateTime(2024, 6, 7, 12, 24, 44, 893, DateTimeKind.Utc).AddTicks(6493), + ProposedStartTime = new DateTime(2024, 6, 7, 11, 24, 44, 893, DateTimeKind.Utc).AddTicks(6491) + }); + }); + + modelBuilder.Entity("PlayOfferService.Domain.Models.Reservation", b => + { + b.Property("Id") + .HasColumnType("uuid") + .HasColumnName("id"); + + b.Property>("CourtIds") + .IsRequired() + .HasColumnType("uuid[]") + .HasColumnName("courtIds"); + + b.Property("EndTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("endTime"); + + b.Property("IsCancelled") + .HasColumnType("boolean") + .HasColumnName("isCancelled"); + + b.Property>("ParticipantsIds") + .HasColumnType("uuid[]") + .HasColumnName("participantsIds"); + + b.Property("ReservantId") + .HasColumnType("uuid") + .HasColumnName("reservantId"); + + b.Property("StartTime") + .HasColumnType("timestamp with time zone") + .HasColumnName("startTime"); + + b.HasKey("Id") + .HasName("pK_reservations"); + + b.ToTable("reservations", (string)null); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20240607112446_memberExpansion.cs b/Migrations/20240607112446_memberExpansion.cs new file mode 100644 index 0000000..9f923d2 --- /dev/null +++ b/Migrations/20240607112446_memberExpansion.cs @@ -0,0 +1,101 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace PlayOfferService.Migrations +{ + /// + public partial class memberExpansion : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DeleteData( + table: "playOffers", + keyColumn: "id", + keyValue: new Guid("c0f37db0-4c51-4bd3-86ab-48d6c78eb9c2")); + + migrationBuilder.AddColumn( + name: "email", + table: "members", + type: "text", + nullable: true); + + migrationBuilder.AddColumn( + name: "firstName", + table: "members", + type: "text", + nullable: true); + + migrationBuilder.AddColumn( + name: "lastName", + table: "members", + type: "text", + nullable: true); + + migrationBuilder.AddColumn( + name: "name", + table: "clubs", + type: "text", + nullable: false, + defaultValue: ""); + + migrationBuilder.UpdateData( + table: "clubs", + keyColumn: "id", + keyValue: new Guid("06b812a7-5131-4510-82ff-bffac33e0f3e"), + column: "name", + value: "Test Club"); + + migrationBuilder.UpdateData( + table: "members", + keyColumn: "id", + keyValue: new Guid("40c0981d-e2f8-4af3-ae6c-17f79f3ba8c2"), + columns: new[] { "email", "firstName", "lastName" }, + values: new object[] { null, null, null }); + + migrationBuilder.UpdateData( + table: "members", + keyColumn: "id", + keyValue: new Guid("ccc1c8fc-89b5-4026-b190-9d9e7e7bc18d"), + columns: new[] { "email", "firstName", "lastName" }, + values: new object[] { null, null, null }); + + migrationBuilder.InsertData( + table: "playOffers", + columns: new[] { "id", "acceptedStartTime", "clubId", "creatorId", "isCancelled", "opponentId", "proposedEndTime", "proposedStartTime", "reservationId" }, + values: new object[] { new Guid("7d079edb-d4c8-4e63-9c5b-35b80eaa69f6"), null, new Guid("06b812a7-5131-4510-82ff-bffac33e0f3e"), new Guid("40c0981d-e2f8-4af3-ae6c-17f79f3ba8c2"), false, null, new DateTime(2024, 6, 7, 12, 24, 44, 893, DateTimeKind.Utc).AddTicks(6493), new DateTime(2024, 6, 7, 11, 24, 44, 893, DateTimeKind.Utc).AddTicks(6491), null }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DeleteData( + table: "playOffers", + keyColumn: "id", + keyValue: new Guid("7d079edb-d4c8-4e63-9c5b-35b80eaa69f6")); + + migrationBuilder.DropColumn( + name: "email", + table: "members"); + + migrationBuilder.DropColumn( + name: "firstName", + table: "members"); + + migrationBuilder.DropColumn( + name: "lastName", + table: "members"); + + migrationBuilder.DropColumn( + name: "name", + table: "clubs"); + + migrationBuilder.InsertData( + table: "playOffers", + columns: new[] { "id", "acceptedStartTime", "clubId", "creatorId", "isCancelled", "opponentId", "proposedEndTime", "proposedStartTime", "reservationId" }, + values: new object[] { new Guid("c0f37db0-4c51-4bd3-86ab-48d6c78eb9c2"), null, new Guid("06b812a7-5131-4510-82ff-bffac33e0f3e"), new Guid("40c0981d-e2f8-4af3-ae6c-17f79f3ba8c2"), false, null, new DateTime(2024, 6, 6, 19, 10, 3, 28, DateTimeKind.Utc).AddTicks(4637), new DateTime(2024, 6, 6, 18, 10, 3, 28, DateTimeKind.Utc).AddTicks(4634), null }); + } + } +} diff --git a/Migrations/DbReadContextModelSnapshot.cs b/Migrations/DbReadContextModelSnapshot.cs index ff39f79..f30a568 100644 --- a/Migrations/DbReadContextModelSnapshot.cs +++ b/Migrations/DbReadContextModelSnapshot.cs @@ -68,6 +68,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("uuid") .HasColumnName("id"); + b.Property("Name") + .IsRequired() + .HasColumnType("text") + .HasColumnName("name"); + b.Property("Status") .HasColumnType("integer") .HasColumnName("status"); @@ -81,6 +86,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) new { Id = new Guid("06b812a7-5131-4510-82ff-bffac33e0f3e"), + Name = "Test Club", Status = 0 }); }); @@ -117,6 +123,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) .HasColumnType("uuid") .HasColumnName("clubId"); + b.Property("Email") + .HasColumnType("text") + .HasColumnName("email"); + + b.Property("FirstName") + .HasColumnType("text") + .HasColumnName("firstName"); + + b.Property("LastName") + .HasColumnType("text") + .HasColumnName("lastName"); + b.Property("Status") .HasColumnType("integer") .HasColumnName("status"); @@ -187,12 +205,12 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasData( new { - Id = new Guid("c0f37db0-4c51-4bd3-86ab-48d6c78eb9c2"), + Id = new Guid("7d079edb-d4c8-4e63-9c5b-35b80eaa69f6"), ClubId = new Guid("06b812a7-5131-4510-82ff-bffac33e0f3e"), CreatorId = new Guid("40c0981d-e2f8-4af3-ae6c-17f79f3ba8c2"), IsCancelled = false, - ProposedEndTime = new DateTime(2024, 6, 6, 19, 10, 3, 28, DateTimeKind.Utc).AddTicks(4637), - ProposedStartTime = new DateTime(2024, 6, 6, 18, 10, 3, 28, DateTimeKind.Utc).AddTicks(4634) + ProposedEndTime = new DateTime(2024, 6, 7, 12, 24, 44, 893, DateTimeKind.Utc).AddTicks(6493), + ProposedStartTime = new DateTime(2024, 6, 7, 11, 24, 44, 893, DateTimeKind.Utc).AddTicks(6491) }); }); diff --git a/PlayOfferService.Tests/IntegrationTests/ClubEventHandlerTest.cs b/PlayOfferService.Tests/IntegrationTests/ClubEventHandlerTest.cs index 266d4d8..132035a 100644 --- a/PlayOfferService.Tests/IntegrationTests/ClubEventHandlerTest.cs +++ b/PlayOfferService.Tests/IntegrationTests/ClubEventHandlerTest.cs @@ -12,12 +12,13 @@ public async Task ClubSetup() var existingClub = new Club { Id = Guid.Parse("8aa54411-32fe-4b4c-a017-aa9710cb3bfa"), + Name = "Existing Club", Status = Status.ACTIVE }; TestClubRepository.CreateClub(existingClub); await TestClubRepository.Update(); } - + [Test] public async Task ClubCreatedEvent_ProjectionTest() { @@ -31,16 +32,17 @@ public async Task ClubCreatedEvent_ProjectionTest() EventType = EventType.TENNIS_CLUB_REGISTERED, EventData = new ClubCreatedEvent { - TennisClubId = new TennisClubId {Id = clubId} + TennisClubId = new TennisClubId { Id = clubId }, + Name = "Test Club", } }; - + //When await Mediator.Send(clubCreationEvent); - + //Then var projectedClub = await TestClubRepository.GetClubById(clubId); - + Assert.That(projectedClub, Is.Not.Null); Assert.Multiple(() => { @@ -48,7 +50,7 @@ public async Task ClubCreatedEvent_ProjectionTest() Assert.That(projectedClub.Status, Is.EqualTo(Status.ACTIVE)); }); } - + [Test] public async Task ClubLockedEvent_ProjectionTest() { @@ -61,13 +63,13 @@ public async Task ClubLockedEvent_ProjectionTest() EventType = EventType.TENNIS_CLUB_LOCKED, EventData = new ClubLockedEvent() }; - + //When await Mediator.Send(clubLockedEvent); - + //Then var projectedClub = await TestClubRepository.GetClubById(Guid.Parse("8aa54411-32fe-4b4c-a017-aa9710cb3bfa")); - + Assert.That(projectedClub, Is.Not.Null); Assert.Multiple(() => { @@ -75,7 +77,7 @@ public async Task ClubLockedEvent_ProjectionTest() Assert.That(projectedClub.Status, Is.EqualTo(Status.LOCKED)); }); } - + [Test] public async Task ClubUnlockedEvent_ProjectionTest() { @@ -102,7 +104,7 @@ public async Task ClubUnlockedEvent_ProjectionTest() Assert.That(projectedClub.Status, Is.EqualTo(Status.ACTIVE)); }); } - + [Test] public async Task ClubDeletedEvent_ProjectionTest() { diff --git a/PlayOfferService.Tests/IntegrationTests/ClubRepositoryTest.cs b/PlayOfferService.Tests/IntegrationTests/ClubRepositoryTest.cs index 9ad3d36..a636bae 100644 --- a/PlayOfferService.Tests/IntegrationTests/ClubRepositoryTest.cs +++ b/PlayOfferService.Tests/IntegrationTests/ClubRepositoryTest.cs @@ -11,6 +11,7 @@ public async Task ClubSetup() var existingClub = new Club { Id = Guid.Parse("67bc285f-1b28-40f9-8b9e-564b3d9c1297"), + Name = "Test Club", Status = Status.ACTIVE }; TestClubRepository.CreateClub(existingClub); @@ -22,28 +23,28 @@ public async Task GetExistingClubByIdTest() { //Given var clubId = Guid.Parse("67bc285f-1b28-40f9-8b9e-564b3d9c1297"); - + //When var club = await TestClubRepository.GetClubById(clubId); - + //Then Assert.That(club, Is.Not.Null); Assert.That(club!.Id, Is.EqualTo(clubId)); } - + [Test] public async Task GetNonExistingClubByIdTest() { //Given var clubId = Guid.NewGuid(); - + //When var club = await TestClubRepository.GetClubById(clubId); - + //Then Assert.That(club, Is.Null); } - + [Test] public async Task CreateClubTest() { @@ -52,13 +53,14 @@ public async Task CreateClubTest() var newClub = new Club { Id = clubId, + Name = "Test Club", Status = Status.ACTIVE }; - + //When TestClubRepository.CreateClub(newClub); await TestClubRepository.Update(); - + //Then var club = await TestClubRepository.GetClubById(clubId); Assert.That(club, Is.Not.Null); diff --git a/PlayOfferService.Tests/IntegrationTests/MemberEventHandlerTest.cs b/PlayOfferService.Tests/IntegrationTests/MemberEventHandlerTest.cs index 4a44b8b..8af4d26 100644 --- a/PlayOfferService.Tests/IntegrationTests/MemberEventHandlerTest.cs +++ b/PlayOfferService.Tests/IntegrationTests/MemberEventHandlerTest.cs @@ -19,7 +19,7 @@ public async Task MemberSetup() TestMemberRepository.CreateMember(existingMember); await TestMemberRepository.Update(); } - + [Test] public async Task MemberCreatedEvent_ProjectionTest() { @@ -33,17 +33,18 @@ public async Task MemberCreatedEvent_ProjectionTest() EventType = EventType.MEMBER_REGISTERED, EventData = new MemberCreatedEvent { - MemberId = new MemberId{Id=memberId}, - TennisClubId = new TennisClubId{Id=Guid.Parse("bf7f59db-e2bf-4a4f-95fe-baeabe948b81")} + MemberId = new MemberId { Id = memberId }, + Name = new FullName { FirstName = "Test", LastName = "Member" }, + TennisClubId = new TennisClubId { Id = Guid.Parse("bf7f59db-e2bf-4a4f-95fe-baeabe948b81") } } }; - + //When await Mediator.Send(memberCreatedEvent); - + //Then var projectedMember = await TestMemberRepository.GetMemberById(memberId); - + Assert.That(projectedMember, Is.Not.Null); Assert.Multiple(() => { @@ -52,7 +53,7 @@ public async Task MemberCreatedEvent_ProjectionTest() Assert.That(projectedMember.Status, Is.EqualTo(Status.ACTIVE)); }); } - + [Test] public async Task MemberLockEvent_ProjectionTest() { @@ -66,13 +67,13 @@ public async Task MemberLockEvent_ProjectionTest() EventType = EventType.MEMBER_LOCKED, EventData = new MemberLockedEvent() }; - + //When await Mediator.Send(memberLockEvent); - + //Then var projectedMember = await TestMemberRepository.GetMemberById(existingMember.Id); - + Assert.That(projectedMember, Is.Not.Null); Assert.Multiple(() => { @@ -80,7 +81,7 @@ public async Task MemberLockEvent_ProjectionTest() Assert.That(projectedMember.Status, Is.EqualTo(Status.LOCKED)); }); } - + [Test] public async Task MemberUnlockEvent_ProjectionTest() { @@ -94,13 +95,13 @@ public async Task MemberUnlockEvent_ProjectionTest() EventType = EventType.MEMBER_UNLOCKED, EventData = new MemberUnlockedEvent() }; - + //When await Mediator.Send(memberUnlockEvent); - + //Then var projectedMember = await TestMemberRepository.GetMemberById(existingMember.Id); - + Assert.That(projectedMember, Is.Not.Null); Assert.Multiple(() => { @@ -108,7 +109,7 @@ public async Task MemberUnlockEvent_ProjectionTest() Assert.That(projectedMember.Status, Is.EqualTo(Status.ACTIVE)); }); } - + [Test] public async Task MemberDeletedEvent_ProjectionTest() { @@ -122,13 +123,13 @@ public async Task MemberDeletedEvent_ProjectionTest() EventType = EventType.MEMBER_DELETED, EventData = new MemberDeletedEvent() }; - + //When await Mediator.Send(memberDeleteEvent); - + //Then var projectedMember = await TestMemberRepository.GetMemberById(existingMember.Id); - + Assert.That(projectedMember, Is.Not.Null); Assert.Multiple(() => { diff --git a/PlayOfferService.Tests/UnitTests/MemberUnitTest.cs b/PlayOfferService.Tests/UnitTests/MemberUnitTest.cs index c57d8d7..5848ce7 100644 --- a/PlayOfferService.Tests/UnitTests/MemberUnitTest.cs +++ b/PlayOfferService.Tests/UnitTests/MemberUnitTest.cs @@ -22,21 +22,22 @@ public void ApplyMemberCreatedEventTest() EventType = EventType.MEMBER_REGISTERED, EventData = new MemberCreatedEvent { - MemberId = new MemberId{Id=memberId}, - TennisClubId = new TennisClubId{Id=clubId} + MemberId = new MemberId { Id = memberId }, + Name = new FullName { FirstName = "John", LastName = "Doe" }, + TennisClubId = new TennisClubId { Id = clubId } } }; - + // When var member = new Member(); member.Apply([memberCreationEvent]); - + // Then Assert.That(member.Id, Is.EqualTo(memberId)); Assert.That(member.ClubId, Is.EqualTo(clubId)); Assert.That(member.Status, Is.EqualTo(Status.ACTIVE)); } - + [Test] public void ApplyMemberLockEventTest() { @@ -54,14 +55,14 @@ public void ApplyMemberLockEventTest() EventData = new MemberLockedEvent() } }; - + // When member.Apply(memberEvents); - + // Then Assert.That(member.Status, Is.EqualTo(Status.LOCKED)); } - + [Test] public void ApplyMemberUnlockEventTest() { @@ -79,14 +80,14 @@ public void ApplyMemberUnlockEventTest() EventData = new MemberUnlockedEvent() } }; - + // When member.Apply(memberEvents); - + // Then Assert.That(member.Status, Is.EqualTo(Status.ACTIVE)); } - + [Test] public void ApplyMemberDeleteEventTest() { @@ -104,10 +105,10 @@ public void ApplyMemberDeleteEventTest() EventData = new MemberDeletedEvent() } }; - + // When member.Apply(memberEvents); - + // Then Assert.That(member.Status, Is.EqualTo(Status.DELETED)); } From a148ea34b653fb51a7028e2239efae46c997293b Mon Sep 17 00:00:00 2001 From: CengoleFHV Date: Fri, 7 Jun 2024 14:00:30 +0200 Subject: [PATCH 16/18] fixed tests (again) --- .../IntegrationTests/ClubEventHandlerTest.cs | 32 ++++++++++++------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/PlayOfferService.Tests/IntegrationTests/ClubEventHandlerTest.cs b/PlayOfferService.Tests/IntegrationTests/ClubEventHandlerTest.cs index 6021246..e9850e8 100644 --- a/PlayOfferService.Tests/IntegrationTests/ClubEventHandlerTest.cs +++ b/PlayOfferService.Tests/IntegrationTests/ClubEventHandlerTest.cs @@ -11,18 +11,26 @@ public async Task ClubSetup() { var existingClubs = new List { - - Id = Guid.Parse("8aa54411-32fe-4b4c-a017-aa9710cb3bfa"), - Name = "Existing Club", - Status = Status.ACTIVE + new() + { + Id = Guid.Parse("8aa54411-32fe-4b4c-a017-aa9710cb3bfa"), + Name = "Test Club 1", + Status = Status.ACTIVE + }, + new() + { + Id = Guid.Parse("2db387f0-5792-4cb5-91a6-6317437b3432"), + Name = "Test Club 2", + Status = Status.ACTIVE + } }; - + foreach (var club in existingClubs) { TestClubRepository.CreateClub(club); } await TestClubRepository.Update(); - + var existingPlayOffers = new List { new() @@ -44,12 +52,12 @@ public async Task ClubSetup() IsCancelled = false }, }; - + foreach (var playOffer in existingPlayOffers) { TestPlayOfferRepository.CreatePlayOffer(playOffer); } - + await TestPlayOfferRepository.Update(); } @@ -110,10 +118,10 @@ public async Task ClubLockedEvent_ProjectionTest() Assert.That(projectedClub!.Id, Is.EqualTo(Guid.Parse("8aa54411-32fe-4b4c-a017-aa9710cb3bfa"))); Assert.That(projectedClub.Status, Is.EqualTo(Status.LOCKED)); }); - + var playOfferEvents = await TestWriteEventRepository.GetEventByEntityId(Guid.Parse("d9afd6dd-8836-47dd-86be-3467a7db0fe5")); Assert.That(playOfferEvents, Has.Count.EqualTo(1)); - + Assert.Multiple(() => { Assert.That(playOfferEvents.First().EntityId, Is.EqualTo(Guid.Parse("d9afd6dd-8836-47dd-86be-3467a7db0fe5"))); @@ -174,10 +182,10 @@ public async Task ClubDeletedEvent_ProjectionTest() Assert.That(projectedClub!.Id, Is.EqualTo(Guid.Parse("2db387f0-5792-4cb5-91a6-6317437b3432"))); Assert.That(projectedClub.Status, Is.EqualTo(Status.DELETED)); }); - + var playOfferEvents = await TestWriteEventRepository.GetEventByEntityId(Guid.Parse("9ee6d9d7-d4a6-4904-a20b-be026de53c4f")); Assert.That(playOfferEvents, Has.Count.EqualTo(1)); - + Assert.Multiple(() => { Assert.That(playOfferEvents.First().EntityId, Is.EqualTo(Guid.Parse("9ee6d9d7-d4a6-4904-a20b-be026de53c4f"))); From ce1cdbe94731ea432f1cd088e4bc2cdc614d11f2 Mon Sep 17 00:00:00 2001 From: CengoleFHV Date: Fri, 7 Jun 2024 14:07:54 +0200 Subject: [PATCH 17/18] added Unit Tests --- .../UnitTests/ClubUnitTest.cs | 34 +++++++++- .../UnitTests/MemberUnitTest.cs | 63 +++++++++++++++++++ 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/PlayOfferService.Tests/UnitTests/ClubUnitTest.cs b/PlayOfferService.Tests/UnitTests/ClubUnitTest.cs index 14cef99..7e9fcab 100644 --- a/PlayOfferService.Tests/UnitTests/ClubUnitTest.cs +++ b/PlayOfferService.Tests/UnitTests/ClubUnitTest.cs @@ -1,4 +1,5 @@ using PlayOfferService.Domain.Events; +using PlayOfferService.Domain.Events.Club; using PlayOfferService.Domain.Models; using PlayOfferService.Domain.ValueObjects; @@ -20,7 +21,7 @@ public void ApplyClubCreatedEventTest() EventType = EventType.TENNIS_CLUB_REGISTERED, EventData = new ClubCreatedEvent { - TennisClubId = new TennisClubId{Id=clubId} + TennisClubId = new TennisClubId { Id = clubId } } }; @@ -81,7 +82,7 @@ public void ApplyClubUnlockEventTest() // Then Assert.That(club.Status, Is.EqualTo(Status.ACTIVE)); } - + [Test] public void ApplyClubDeletedEventTest() { @@ -105,4 +106,33 @@ public void ApplyClubDeletedEventTest() // Then Assert.That(club.Status, Is.EqualTo(Status.DELETED)); } + + [Test] + public void ApplyClubNameChangedEventTest() + { + // Given + var club = new Club + { + Id = Guid.NewGuid(), + Name = "Test Club" + }; + var clubEvents = new List + { + new() + { + EventType = EventType.TENNIS_CLUB_NAME_CHANGED, + EventData = new ClubNameChangedEvent + { + Name = "New Club Name" + } + } + }; + + // When + club.Apply(clubEvents); + + // Then + Assert.That(club.Name, Is.EqualTo("New Club Name")); + } + } \ No newline at end of file diff --git a/PlayOfferService.Tests/UnitTests/MemberUnitTest.cs b/PlayOfferService.Tests/UnitTests/MemberUnitTest.cs index 5848ce7..a18c9ea 100644 --- a/PlayOfferService.Tests/UnitTests/MemberUnitTest.cs +++ b/PlayOfferService.Tests/UnitTests/MemberUnitTest.cs @@ -112,4 +112,67 @@ public void ApplyMemberDeleteEventTest() // Then Assert.That(member.Status, Is.EqualTo(Status.DELETED)); } + + [Test] + public void ApplyMemberNameChangedEventTest() + { + // Given + var member = new Member + { + Id = Guid.NewGuid(), + FirstName = "John", + LastName = "Doe" + }; + + var memberEvents = new List + { + new() + { + EventType = EventType.MEMBER_FULL_NAME_CHANGED, + EventData = new MemberFullNameChangedEvent + { + FullName = new FullName { FirstName = "Jane", LastName = "Doe" } + } + } + }; + + // When + member.Apply(memberEvents); + + // Then + Assert.That(member.FirstName, Is.EqualTo("Jane")); + Assert.That(member.LastName, Is.EqualTo("Doe")); + } + + [Test] + public void ApplyMemberEmailChangedEvent() + { + // Given + var member = new Member + { + Id = Guid.NewGuid(), + FirstName = "John", + LastName = "Doe", + Email = "test@test.test" + }; + + var memberEvents = new List + { + new() + { + EventType = EventType.MEMBER_EMAIL_CHANGED, + EventData = new MemberEmailChangedEvent + { + Email = "changedEmail@com.com" + } + + } + }; + + //When + member.Apply(memberEvents); + + //Then + Assert.That(member.Email, Is.EqualTo("changedEmail@com.com")); + } } \ No newline at end of file From f3a70935604edc51e7f1a0c0032342aa6d80d792 Mon Sep 17 00:00:00 2001 From: CengoleFHV Date: Fri, 7 Jun 2024 17:01:23 +0200 Subject: [PATCH 18/18] added Handles for new Member and Club Events --- .../Handlers/Events/ClubEventHandler.cs | 28 +++++++++------ .../Handlers/Events/MemberEventHandler.cs | 34 ++++++++++++++----- 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/Application/Handlers/Events/ClubEventHandler.cs b/Application/Handlers/Events/ClubEventHandler.cs index 535d729..f530869 100644 --- a/Application/Handlers/Events/ClubEventHandler.cs +++ b/Application/Handlers/Events/ClubEventHandler.cs @@ -1,5 +1,4 @@ using MediatR; -using PlayOfferService.Application.Exceptions; using PlayOfferService.Domain.Events; using PlayOfferService.Domain.Events.PlayOffer; using PlayOfferService.Domain.Models; @@ -13,7 +12,7 @@ public class ClubEventHandler : IRequestHandler private readonly ReadEventRepository _readEventRepository; private readonly WriteEventRepository _writeEventRepository; private readonly PlayOfferRepository _playOfferRepository; - + public ClubEventHandler(ClubRepository clubRepository, ReadEventRepository readEventRepository, WriteEventRepository writeEventRepository, PlayOfferRepository playOfferRepository) { _clubRepository = clubRepository; @@ -21,7 +20,7 @@ public ClubEventHandler(ClubRepository clubRepository, ReadEventRepository readE _writeEventRepository = writeEventRepository; _playOfferRepository = playOfferRepository; } - + public async Task Handle(TechnicalClubEvent clubEvent, CancellationToken cancellationToken) { Console.WriteLine("ClubEventHandler received event: " + clubEvent.EventType); @@ -31,7 +30,7 @@ public async Task Handle(TechnicalClubEvent clubEvent, CancellationToken cancell Console.WriteLine("Event already applied, skipping"); return; } - + switch (clubEvent.EventType) { case EventType.TENNIS_CLUB_REGISTERED: @@ -46,8 +45,11 @@ public async Task Handle(TechnicalClubEvent clubEvent, CancellationToken cancell case EventType.TENNIS_CLUB_DELETED: await HandleTennisClubDeletedEvent(clubEvent); break; + case EventType.TENNIS_CLUB_NAME_CHANGED: + await HandleTennisClubNameChangedEvent(clubEvent); + break; } - + await _clubRepository.Update(); await _readEventRepository.AppendEvent(clubEvent); await _readEventRepository.Update(); @@ -56,7 +58,7 @@ public async Task Handle(TechnicalClubEvent clubEvent, CancellationToken cancell private async Task HandleTennisClubDeletedEvent(TechnicalClubEvent clubEvent) { await CreatePlayOfferCancelledEventsByClubId(clubEvent); - + var existingClub = await _clubRepository.GetClubById(clubEvent.EntityId); existingClub!.Apply([clubEvent]); } @@ -70,7 +72,7 @@ private async Task HandleTennisClubUnlockedEvent(TechnicalClubEvent clubEvent) private async Task HandleTennisClubLockedEvent(TechnicalClubEvent clubEvent) { await CreatePlayOfferCancelledEventsByClubId(clubEvent); - + var existingClub = await _clubRepository.GetClubById(clubEvent.EntityId); existingClub!.Apply([clubEvent]); } @@ -81,12 +83,12 @@ private async Task HandleTennisClubRegisteredEvent(TechnicalClubEvent clubEvent) newClub.Apply([clubEvent]); _clubRepository.CreateClub(newClub); } - + private async Task CreatePlayOfferCancelledEventsByClubId(TechnicalClubEvent clubEvent) { // Get all play offers by club id var existingPlayOffer = await _playOfferRepository.GetPlayOffersByIds(null, null, clubEvent.EntityId); - + // Create PlayOfferCancelled events for each play offer foreach (var playOffer in existingPlayOffer) { @@ -100,9 +102,15 @@ private async Task CreatePlayOfferCancelledEventsByClubId(TechnicalClubEvent clu EventData = new PlayOfferCancelledEvent(), CorrelationId = clubEvent.EventId }; - + await _writeEventRepository.AppendEvent(cancelledEvent); } await _writeEventRepository.Update(); } + + private async Task HandleTennisClubNameChangedEvent(TechnicalClubEvent clubEvent) + { + var existingClub = await _clubRepository.GetClubById(clubEvent.EntityId); + existingClub!.Apply([clubEvent]); + } } \ No newline at end of file diff --git a/Application/Handlers/Events/MemberEventHandler.cs b/Application/Handlers/Events/MemberEventHandler.cs index 849ea77..44effb5 100644 --- a/Application/Handlers/Events/MemberEventHandler.cs +++ b/Application/Handlers/Events/MemberEventHandler.cs @@ -13,7 +13,7 @@ public class MemberEventHandler : IRequestHandler private readonly ReadEventRepository _eventRepository; private readonly WriteEventRepository _writeEventRepository; private readonly PlayOfferRepository _playOfferRepository; - + public MemberEventHandler(MemberRepository memberRepository, ReadEventRepository eventRepository, PlayOfferRepository playOfferRepository, WriteEventRepository writeEventRepository) { _memberRepository = memberRepository; @@ -21,7 +21,7 @@ public MemberEventHandler(MemberRepository memberRepository, ReadEventRepository _playOfferRepository = playOfferRepository; _writeEventRepository = writeEventRepository; } - + public async Task Handle(TechnicalMemberEvent memberEvent, CancellationToken cancellationToken) { Console.WriteLine("MemberEventHandler received event: " + memberEvent.EventType); @@ -31,7 +31,7 @@ public async Task Handle(TechnicalMemberEvent memberEvent, CancellationToken can Console.WriteLine("Event already applied, skipping"); return; } - + switch (memberEvent.EventType) { case EventType.MEMBER_REGISTERED: @@ -46,8 +46,14 @@ public async Task Handle(TechnicalMemberEvent memberEvent, CancellationToken can case EventType.MEMBER_DELETED: await HandleMemberDeletedEvent(memberEvent); break; + case EventType.MEMBER_FULL_NAME_CHANGED: + await HandleMemberFullNameChangedEvent(memberEvent); + break; + case EventType.MEMBER_EMAIL_CHANGED: + await HandleMemberEmailChangedEvent(memberEvent); + break; } - + await _memberRepository.Update(); await _eventRepository.AppendEvent(memberEvent); await _eventRepository.Update(); @@ -56,7 +62,7 @@ public async Task Handle(TechnicalMemberEvent memberEvent, CancellationToken can private async Task HandleMemberDeletedEvent(TechnicalMemberEvent memberEvent) { await CreatePlayOfferCancelledEventsByCreatorId(memberEvent); - + var existingMember = await _memberRepository.GetMemberById(memberEvent.EntityId); existingMember!.Apply([memberEvent]); } @@ -70,7 +76,7 @@ private async Task HandleMemberUnlockedEvent(TechnicalMemberEvent memberEvent) private async Task HandleMemberLockedEvent(TechnicalMemberEvent memberEvent) { await CreatePlayOfferCancelledEventsByCreatorId(memberEvent); - + var existingMember = await _memberRepository.GetMemberById(memberEvent.EntityId); existingMember!.Apply([memberEvent]); } @@ -86,7 +92,7 @@ private async Task CreatePlayOfferCancelledEventsByCreatorId(TechnicalMemberEven { // Get all play offers by creator id var existingPlayOffer = await _playOfferRepository.GetPlayOffersByIds(null, memberEvent.EntityId); - + // Create PlayOfferCancelled events for each play offer foreach (var playOffer in existingPlayOffer) { @@ -100,9 +106,21 @@ private async Task CreatePlayOfferCancelledEventsByCreatorId(TechnicalMemberEven EventData = new PlayOfferCancelledEvent(), CorrelationId = memberEvent.EventId }; - + await _writeEventRepository.AppendEvent(cancelledEvent); } await _writeEventRepository.Update(); } + + private async Task HandleMemberFullNameChangedEvent(TechnicalMemberEvent memberEvent) + { + var existingMember = await _memberRepository.GetMemberById(memberEvent.EntityId); + existingMember!.Apply([memberEvent]); + } + + private async Task HandleMemberEmailChangedEvent(TechnicalMemberEvent memberEvent) + { + var existingMember = await _memberRepository.GetMemberById(memberEvent.EntityId); + existingMember!.Apply([memberEvent]); + } } \ No newline at end of file