-
Notifications
You must be signed in to change notification settings - Fork 13
New functionality of Calendar Events #2521
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: release/1.2.3
Are you sure you want to change the base?
Conversation
WalkthroughThis pull request introduces comprehensive event management features. New DTOs, MediatR commands/handlers, and validators have been added to facilitate event creation, updates, retrieval, and deletion. The changes also include new Entity Framework Core configurations, repository interfaces/implementations, and an EventsController with REST endpoints. Additionally, localized resource entries, unit tests, and integration test clients have been extended to support event-specific operations and error handling. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant Controller as EventsController
participant Mediator
participant Handler as CreateEventHandler
participant Factory as EventFactory
participant Repo as Repository
Client->>Controller: POST /api/events\nwith CreateUpdateEventDTO
Controller->>Mediator: Send(CreateEventCommand)
Mediator->>Handler: Invoke Handle()
Handler->>Factory: CreateEvent(eventType)
Factory-->>Handler: Event instance
Handler->>Repo: Save event and streetcodes
Repo-->>Handler: Persisted result
Handler-->>Mediator: Return Result(event ID)
Mediator-->>Controller: Return event ID
Controller-->>Client: HTTP 200 OK\nwith event ID
Poem
✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
🔭 Outside diff range comments (1)
Streetcode/Streetcode.BLL/MediatR/Event/GetAllShort/GetAllEventsShortHandler.cs (1)
1-46
: 💡 Verification agent🧩 Analysis chain
Verify namespace consistency with file location
I notice that the file appears to be in the
GetAllShort
directory based on the import on line 8, but the namespace isStreetcode.BLL.MediatR.Event.GetAll
. This inconsistency might cause confusion when navigating the codebase. Consider ensuring the namespace matches the file's location.
🏁 Script executed:
#!/bin/bash # Check the actual file location to verify if there's a namespace/directory mismatch find . -name "GetAllEventsShortHandler.cs" | grep -i streetcode # Check related query class location find . -name "*GetAllEventsShort*.cs" | grep -v GetAllEventsShortHandler.cs | grep -i streetcodeLength of output: 324
Namespace Inconsistency: Update Required
The
GetAllEventsShortHandler.cs
file is located in theStreetcode/Streetcode.BLL/MediatR/Event/GetAllShort/
directory, yet its namespace is declared asStreetcode.BLL.MediatR.Event.GetAll
. This mismatch could cause confusion during navigation and maintenance.Suggestions:
- Option 1: Update the namespace in the file (and any related files, such as
GetAllEventsShortQuery.cs
) toStreetcode.BLL.MediatR.Event.GetAllShort
so it aligns with the directory structure.- Option 2: If the intended design is for the namespace to remain as
GetAll
, consider moving the file and related classes to a directory that reflects this, for example,Streetcode/Streetcode.BLL/MediatR/Event/GetAll
.Please review the overall organization of the project to decide the best approach. Collaboration on this change will help ensure consistency across the codebase.
🧹 Nitpick comments (55)
Streetcode/Streetcode.BLL/MediatR/Event/GetById/GetEventByIdQuery.cs (1)
1-9
: Well-structured query class using MediatR patternThe implementation of
GetEventByIdQuery
follows the CQRS pattern appropriately, using MediatR and FluentResults for a clean separation of concerns. This approach will provide a good foundation for implementing event retrieval functionality.I notice that the handler class mentioned in the summary (
GetEventByIdHandler
) isn't included in this file. While it's perfectly valid to separate the query and handler into different files, for simpler queries like this, it's sometimes more maintainable to keep related components together.Consider whether you want to follow a consistent organization pattern across your codebase - either keeping handlers with their queries in the same file, or maintaining separate files for each.
Streetcode/Streetcode.BLL/Resources/SharedResource.FailedToValidateSharedResource.en-US.resx (1)
213-215
: Minor formatting issue in the English message.There should be a space between the single quote and the word "characters" in the English version to ensure proper formatting when displayed to users.
- <value>The field must be between '{0}' and '{1}'characters.</value> + <value>The field must be between '{0}' and '{1}' characters.</value>Streetcode/Streetcode.BLL/Resources/SharedResource.CannotFindSharedResource.en-US.resx (1)
330-335
: Consider pluralization consistency in error message.The error message entries have been added correctly with proper XML structure and following the existing pattern. However, there's a minor inconsistency: the key "CannotFindAnyEvents" (plural) has a message "Cannot find any event" (singular). While this won't affect functionality, consistent pluralization would improve code clarity.
Consider changing either:
- The message to "Cannot find any events" (plural to match the key), or
- The key to "CannotFindAnyEvent" (singular to match the message)
Streetcode/Streetcode.BLL/Validators/Event/UpdateEventValidator.cs (1)
1-11
: Well-structured validator implementation with clean dependency injection.The
UpdateEventValidator
class follows good practices for FluentValidation by using dependency injection to receive theBaseEventValidator
and delegating validation of theEvent
property to it. This promotes code reuse and follows the Single Responsibility Principle.A few enhancement suggestions:
Consider adding XML documentation to describe the purpose of this validator and its relationship with
BaseEventValidator
.Depending on the requirements for updating events, you might want to add specific validation rules for update operations beyond just validating the Event property (e.g., ensuring the ID exists).
If there are different validation requirements between creating and updating events, you could add conditional validation rules here.
using FluentValidation; using Streetcode.BLL.MediatR.Event.Update; namespace Streetcode.BLL.Validators.Event; +/// <summary> +/// Validator for the UpdateEventCommand that handles validation +/// of event update operations. +/// </summary> public class UpdateEventValidator : AbstractValidator<UpdateEventCommand> { + /// <summary> + /// Initializes a new instance of the UpdateEventValidator. + /// </summary> + /// <param name="baseEventValidator">The base validator for common event validation rules.</param> public UpdateEventValidator(BaseEventValidator baseEventValidator) { RuleFor(e => e.Event).SetValidator(baseEventValidator); + + // Consider additional update-specific validation if needed + // Example: RuleFor(e => e.Event.Id).GreaterThan(0).WithMessage("Event ID must be provided for updates"); } }Streetcode/Streetcode.DAL/Repositories/Realizations/Event/EventRepository.cs (1)
10-19
: Consider enhancing the repository with documentation and specialized methodsThe repository implementation follows good practices with proper inheritance and dependency injection. However, I recommend a few improvements:
- Add XML documentation to describe the purpose and responsibilities of this repository
- Consider adding event-specific query methods based on your application requirements (e.g., filtering events by date range, type, or searching by title)
- The fully qualified type name
DAL.Entities.Event.Event
creates verbosity - consider using a namespace alias directive at the top of the file:using EventEntity = Streetcode.DAL.Entities.Event.Event; // Then use: public class EventRepository : RepositoryBase<EventEntity>, IEventRepositoryThese enhancements would improve code readability and provide more specialized functionality for event-related operations beyond the basic CRUD methods inherited from the base repository.
Streetcode/Streetcode.BLL/MediatR/Event/GetAllShort/GetAllEventsShortHandler.cs (2)
1-13
: Consider removing unused importThe import for
Streetcode.BLL.DTO.Partners
on line 7 appears to be unused in this handler. Removing unnecessary imports helps keep the code cleaner and avoids potential confusion.- using Streetcode.BLL.DTO.Partners;
31-43
: Consider enhancing error handling and adding paginationThe implementation works well for retrieving all events, but there are a few considerations:
The method handles null results but doesn't address empty collections. While an empty collection is a valid result rather than an error, it might be worth considering whether your application needs to distinguish between "no events exist" and "error retrieving events".
As the application grows, retrieving all events without pagination could lead to performance issues. Consider adding pagination support.
public async Task<Result<IEnumerable<EventShortDTO>>> Handle(GetAllEventsShortQuery request, CancellationToken cancellationToken) { - var events = await _repositoryWrapper.EventRepository.GetAllAsync(); + var events = await _repositoryWrapper.EventRepository.GetAllAsync(cancellationToken); + + // If pagination is needed in the future: + // var pagedEvents = await _repositoryWrapper.EventRepository.GetPagedAsync( + // request.PageNumber, + // request.PageSize, + // cancellationToken); if (events is null) { string errorMsg = _stringLocalizeCannotFind["CannotFindAnyEvents"].Value; _logger.LogError(request, errorMsg); return Result.Fail(new Error(errorMsg)); } return Result.Ok(_mapper.Map<IEnumerable<EventShortDTO>>(events)); }Streetcode/Streetcode.DAL/Repositories/Realizations/Event/EventStreetcodesRepository.cs (1)
8-14
: Consider adding XML documentation for better code maintainability.While the implementation is straightforward, adding XML documentation to describe the purpose of this repository and how it relates to the Event entity would improve long-term maintainability, especially for new developers who might work on this codebase.
+/// <summary> +/// Repository for managing associations between events and streetcodes. +/// Implements the base repository pattern for CRUD operations. +/// </summary> internal class EventStreetcodesRepository : RepositoryBase<EventStreetcodes>, IEventStreetcodesRepository { + /// <summary> + /// Initializes a new instance of the <see cref="EventStreetcodesRepository"/> class. + /// </summary> + /// <param name="context">Database context for event streetcodes operations.</param> public EventStreetcodesRepository(StreetcodeDbContext context) : base(context) { } }Streetcode/Streetcode.DAL/Entities/Event/CustomEvent.cs (2)
10-18
: Good implementation of CustomEvent entityThe CustomEvent class properly inherits from the base Event class and includes appropriate MaxLength constraints for its string properties. This implementation aligns with the Table Per Hierarchy (TPH) approach mentioned in the PR objectives.
Consider whether any of these nullable properties should be required for a valid CustomEvent. If so, validation logic should be implemented in the corresponding validators.
1-7
: Consider using more specific importsSeveral of the imported namespaces don't appear to be used in this class. Consider removing unused imports to improve code clarity.
-using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.ComponentModel.DataAnnotations;Streetcode/Streetcode.BLL/DTO/Event/EventDTO.cs (1)
6-14
: Consider using enum for EventTypeThe EventDTO is well-structured with appropriate properties for representing events. However, using a string for EventType might be less type-safe than using an enum.
-public string EventType { get; set; } +public EventTypeEnum EventType { get; set; }This would provide compile-time checking and prevent invalid event types from being assigned. If you need string representation for serialization purposes, you can still convert between the enum and string when needed.
Streetcode/Streetcode.DAL/Configurations/HistoricalEventMap.cs (2)
1-9
: Consider removing unused using directivesSeveral of the imported namespaces (System, System.Collections.Generic, System.Linq, System.Text, System.Threading.Tasks) aren't being used in this file.
-using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.Metadata.Builders; using Microsoft.EntityFrameworkCore; using Streetcode.DAL.Entities.Event;
16-19
: Consider using property expressions instead of string literals for foreign keysUsing string literals for foreign key names is prone to errors and makes refactoring more difficult. Consider using a property expression instead:
- builder.HasOne(e => e.TimelineItem) - .WithMany() - .HasForeignKey("TimelineItemId") - .OnDelete(DeleteBehavior.SetNull); + builder.HasOne(e => e.TimelineItem) + .WithMany() + .HasForeignKey(e => e.TimelineItemId) + .OnDelete(DeleteBehavior.SetNull);Also, if the TimelineItem entity has a corresponding navigation property for HistoricalEvents, consider specifying it in the WithMany() call for better clarity and complete relationship mapping.
Streetcode/Streetcode.BLL/DTO/Event/EventShortDTO.cs (2)
1-6
: Consider removing unused namespacesThis code imports several namespaces (System.Collections.Generic, System.Linq, System.Text, System.Threading.Tasks) that aren't being used in this simple DTO. Clean code practices suggest removing unused imports to improve code clarity and reduce unnecessary dependencies.
- using System.Collections.Generic; - using System.Linq; - using System.Text; - using System.Threading.Tasks;
9-14
: Well-structured DTO with appropriate nullable propertyThe EventShortDTO class is well-designed with appropriate property types and a correctly marked nullable Title property. Consider adding XML documentation comments to provide more context about the purpose of each property, especially for API documentation purposes.
public class EventShortDTO { + /// <summary> + /// Unique identifier for the event + /// </summary> public int Id { get; set; } + /// <summary> + /// Date when the event occurred + /// </summary> public DateTime Date { get; set; } + /// <summary> + /// Optional title of the event + /// </summary> public string? Title { get; set; } }Streetcode/Streetcode.BLL/MediatR/Event/GetAllShort/GetAllEventsShortQuery.cs (1)
1-8
: Clean implementation of MediatR queryThis query record follows best practices for the MediatR and CQRS patterns. It's concise, uses modern C# features (record type), and properly implements the IRequest interface with a Result wrapper for the return type.
Consider adding a brief XML documentation comment to describe the query's purpose and expected behavior:
+/// <summary> +/// Query to retrieve all events in a shortened format. +/// </summary> public record GetAllEventsShortQuery : IRequest<Result<IEnumerable<EventShortDTO>>>;Streetcode/Streetcode.BLL/Validators/Event/BaseEventValidator.cs (1)
23-24
: Consider additional date validationCurrently, you're only validating that the Date field is not empty. Depending on your business requirements, you might want to add validation for future/past dates or specific date formats.
RuleFor(e => e.Date) .NotEmpty().WithMessage(localizer["CannotBeEmpty", fieldLocalizer["Date"]]); + // .Must(date => date > DateTime.Now).WithMessage(localizer["DateMustBeInFuture"]) + // Or other date-specific validation as neededStreetcode/Streetcode.BLL/MediatR/Event/Delete/DeleteEventHandler.cs (1)
39-41
: Add explicit exception handling for SaveChangesAsyncThe current implementation checks if the result is > 0 but doesn't handle potential exceptions that might be thrown during the save operation.
_repositoryWrapper.EventRepository.Delete(eventToDelete); - var resultIsSuccess = await _repositoryWrapper.SaveChangesAsync() > 0; + bool resultIsSuccess; + try + { + resultIsSuccess = await _repositoryWrapper.SaveChangesAsync() > 0; + } + catch (Exception ex) + { + var errorMessage = _stringLocalizerFailedToDelete["FailedToDeleteEvent"].Value; + _logger.LogError(request, $"{errorMessage}. Exception: {ex.Message}"); + return Result.Fail(new Error(errorMessage)); + }Streetcode/Streetcode.XIntegrationTest/ControllerTests/Utils/Client/Event/EventClient.cs (1)
1-27
: Add UpdateAsync method for complete CRUD operationsThe client implements Get, Create, and Delete operations but is missing an Update method. For complete test coverage, consider adding an UpdateAsync method.
public async Task<RestResponse> DeleteAsync(int id, string authToken = "") { var dto = new { Id = id }; return await this.SendCommand($"/Delete/{id}", Method.Delete, dto, authToken); } + + public async Task<RestResponse> UpdateAsync(UpdateEventDTO eventDto, string authToken = "") + => await this.SendCommand($"/Update", Method.Put, eventDto, authToken);Streetcode/Streetcode.BLL/DTO/Event/CustomEventDTO.cs (1)
7-14
: Consider adding XML documentation comments.Adding XML documentation comments would improve code readability and provide better IntelliSense support for developers using this DTO.
namespace Streetcode.BLL.DTO.Event { + /// <summary> + /// Data Transfer Object for custom events with additional location and organizer information. + /// </summary> public class CustomEventDTO : EventDTO { + /// <summary> + /// Gets or sets the location where the custom event takes place. + /// </summary> public string? Location { get; set; } + /// <summary> + /// Gets or sets the name of the person or organization responsible for the event. + /// </summary> public string? Organizer { get; set; } } }Streetcode/Streetcode.BLL/DTO/Event/GetAllEventsResponseDTO.cs (1)
3-7
: Add XML documentation comments for better API documentation.Including XML documentation would improve the usability of this DTO and provide better context for developers.
+/// <summary> +/// Response DTO for retrieving all events with pagination information. +/// </summary> public class GetAllEventsResponseDTO { + /// <summary> + /// Gets or sets the total number of events available. + /// </summary> public int TotalAmount { get; set; } + /// <summary> + /// Gets or sets the collection of events for the current page. + /// </summary> public IEnumerable<object> Events { get; set; } = new List<object>(); }Streetcode/Streetcode.BLL/MediatR/Event/Delete/DeleteEventCommand.cs (1)
1-8
: Remove unused namespaces to keep the code cleanThere are several unused namespaces imported in this file. Consider removing the ones that aren't being used (System.Collections.Generic, System.Linq, System.Text, etc.) to maintain clean code.
using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using System.Threading.Tasks; using FluentResults; using MediatR;Streetcode/Streetcode.XUnitTest/Factories/Event/EventFactoryTests.cs (1)
23-23
: Fix typo in test method nameThere's a typo in the test method name:
-public void CreateEvent_CustomlEventType_ReturnCustomEvent() +public void CreateEvent_CustomEventType_ReturnCustomEvent()Streetcode/Streetcode.BLL/MediatR/Event/GetAll/GetAllEventsQuery.cs (1)
8-9
: Consider using enum instead of string for EventTypeUsing a string parameter for
EventType
could lead to runtime errors if invalid values are provided. Consider using an enum type fromStreetcode.DAL.Enums
since you're already importing this namespace. This would provide compile-time safety and better IntelliSense support.- public record GetAllEventsQuery(string? EventType, ushort? page = null, ushort? pageSize = null) + public record GetAllEventsQuery(EventType? EventType, ushort? page = null, ushort? pageSize = null)If you need string values for API compatibility, consider performing the conversion in the handler instead.
Streetcode/Streetcode.WebApi/Extensions/SeedingLocalExtension.cs (1)
3-3
: Unused import detectedThe
Mono.TextTemplating
namespace is imported but doesn't appear to be used in this file.Consider removing this unused import:
-using Mono.TextTemplating;
Streetcode/Streetcode.BLL/Mapping/Event/EventProfile.cs (1)
18-20
: Remove redundant ReverseMap callThere's a redundant call to
.ReverseMap()
on line 19 after an initial ReverseMap.Apply this fix:
- CreateMap<CustomEvent, CustomEventDTO>().ReverseMap() - .ReverseMap(); + CreateMap<CustomEvent, CustomEventDTO>().ReverseMap();Streetcode/Streetcode.XUnitTest/MediatRTests/Event/GetEventByIdTests.cs (3)
39-64
: Expand verification within the positive scenario test
While this test confirms basic properties (such as Id and EventType) are mapped correctly, consider verifying additional mapped fields (e.g., descriptions, timestamps, or related references) if available. This ensures deeper coverage and prevents regressions.
66-87
: Consider adding more edge case tests
The negative scenario is well covered here. However, you could add a test that ensures correct behavior for an unrecognized event type (e.g., neither "Historical" nor "Custom"), which may trigger the default branch in the handler.
89-95
: Refine the naming of the mock setup for clarity
SetupRepositoryMock
is descriptive, but if you plan to include more services, consider naming it more generically (e.g.,ArrangeRepositoryDependency
) to make it clear this is a setup method for all repository interactions. This is a minor detail but can aid readability at scale.Streetcode/Streetcode.BLL/MediatR/Event/GetById/GetEventByIdHandler.cs (1)
48-61
: Good use of switch expressions for event differentiation
Switching oneventEntity.EventType
ensures maintainable extension for future event types. Consider referencing a dedicated enum or constants (already in use withEventTypeDiscriminators
) if you want to avoid string-based checks.Streetcode/Streetcode.DAL/Enums/EventTypeDiscriminators.cs (1)
16-24
: Suggest verifying future extensibility
TheGetEventType
method works well now. If you plan to add more event types, consider using an enum-based look-up or dictionary to manage expansions cleanly. This will keep the class maintainable over time.Streetcode/Streetcode.BLL/MediatR/Event/GetAll/GetAllEventsHandler.cs (3)
35-54
: Robust pagination handling
Retrieving paginated data helps scalability. Ensurerequest.page
andrequest.pageSize
are validated or sanitized to avoid unexpected paging results (e.g., negative values).
58-85
: Dynamic mapping by event type is a nice touch
Using the pattern-based approach forHistoricalEvent
vs.CustomEvent
ensures the correct DTO. If more event types are introduced, confirm you have coverage for them. Optionally, consider delegating this mapping logic to your AutoMapper profiles to reduce complexity here.
87-93
: Comprehensive response structure
TheTotalAmount
andEvents
fields provide essential info. If you need more pagination data returned (e.g., total pages, current page), consider extending the response for better front-end integration.Streetcode/Streetcode.XUnitTest/MediatRTests/Event/GetAllEventsTests.cs (4)
46-47
: Consider parameterizing the test data.The hardcoded values for page and pageSize (1 and 10) would be better as test parameters, allowing you to test different pagination scenarios with minimal code duplication.
90-101
: Consider making repository mock setup more explicit.The current setup passes
null
for multiple parameters. For improved test clarity, consider specifying meaningful values for these parameters to more accurately reflect how the repository would be used in production code.private void SetupRepositoryMock(PaginationResponse<EventEntity>? paginationResponse) { _mockRepository.Setup(r => r.EventRepository.GetAllPaginated( It.IsAny<ushort?>(), It.IsAny<ushort?>(), - null, - null, + It.IsAny<Expression<Func<EventEntity, bool>>>(), + It.IsAny<Func<IQueryable<EventEntity>, IOrderedQueryable<EventEntity>>>(), It.IsAny<Func<IQueryable<EventEntity>, IIncludableQueryable<EventEntity, object>>?>(), - null, + It.IsAny<bool>(), It.IsAny<Expression<Func<EventEntity, object>>?>())) .Returns(paginationResponse); }
137-138
: Avoid using null-forgiving operator in test code.The
null!
pattern is using the null-forgiving operator, which could mask potential null reference issues. Consider a safer approach to handle this case:else { - return null!; + return new EventDTO(); // Return empty object or handle more explicitly }
142-151
: Improve test helper method organization.The
MapStreetcodes
method contains business logic that makes the test harder to maintain. Consider:
- Simplifying this test-only mapper implementation
- Or moving it to a shared test utility class if it's reused across multiple test files
Streetcode/Streetcode.XUnitTest/MediatRTests/Event/DeleteEventTests.cs (1)
107-108
: Make repository mock setup more specific.The current setup uses a generic pattern for
GetFirstOrDefaultAsync
. Consider making it more specific by verifying the actual query expression:_mockRepository - .Setup(repo => repo.EventRepository.GetFirstOrDefaultAsync(It.IsAny<Expression<Func<EventEntity, bool>>>(), null)) + .Setup(repo => repo.EventRepository.GetFirstOrDefaultAsync( + It.Is<Expression<Func<EventEntity, bool>>>(expr => + // Verify that we're querying for the correct event ID + ExpressionMatchesEventId(expr, eventEntity?.Id ?? 0)), + null)) .ReturnsAsync(eventEntity); // Add a helper method to verify the expression private bool ExpressionMatchesEventId(Expression<Func<EventEntity, bool>> expr, int eventId) { // Simple implementation - in real tests you might want a more robust solution var eventToTest = new EventEntity { Id = eventId }; var func = expr.Compile(); return func(eventToTest); }Streetcode/Streetcode.XUnitTest/MediatRTests/Event/CreateEventTests.cs (3)
59-60
: Be consistent with verification method call counts.You're using
Times.Once()
for the Create method butTimes.AtLeastOnce()
for SaveChangesAsync. For better test precision, be consistent with your expectations:_mockRepository.Verify(r => r.EventRepository.Create(It.IsAny<HistoricalEvent>()), Times.Once); -_mockRepository.Verify(r => r.SaveChangesAsync(), Times.AtLeastOnce); +_mockRepository.Verify(r => r.SaveChangesAsync(), Times.Once);
103-104
: Remove console output from the test.The
Console.WriteLine(result)
statement appears to be a debugging artifact and should be removed from the final test code.Assert.Multiple(() => { Assert.NotNull(result); - Console.WriteLine(result); Assert.False(result.IsSuccess); Assert.Contains(expectedErrorValue, result.Errors.First().Message); });
111-112
: Mock the transaction instead of using a real TransactionScope.In unit tests, it's generally better to mock all external dependencies rather than using real implementations:
-_mockRepository.Setup(r => r.BeginTransaction()).Returns(new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)); +var mockTransaction = new Mock<IDbContextTransaction>(); +_mockRepository.Setup(r => r.BeginTransaction()).Returns(mockTransaction.Object);This would require adding a mock implementation of IDbContextTransaction or whatever transaction interface your repository uses.
Streetcode/Streetcode.XIntegrationTest/ControllerTests/Event/EventControllerTests.cs (3)
39-40
: Remove empty line in Assert.Multiple block.There's an unnecessary empty line in the Assert.Multiple block that should be removed:
Assert.Multiple(() => { - Assert.True(response.IsSuccessStatusCode, $"Expected success status code, but got {response.StatusCode}. Response: {response.Content}"); Assert.NotNull(returnedValue); });
57-65
: Extract duplicated ID parsing logic to a helper method.The same code for parsing and validating the created event ID appears in two test methods. Consider extracting this to a helper method:
+private int ParseCreatedEventId(string createContent) +{ + if (string.IsNullOrEmpty(createContent)) + { + Assert.Fail("Create response content is empty."); + } + + if (!int.TryParse(createContent, out int createdEventId)) + { + Assert.Fail($"Failed to parse created event ID from response. Content: {createContent}"); + } + + return createdEventId; +} // Then use it in both test methods: -var createContent = createResponse.Content; -if (string.IsNullOrEmpty(createContent)) -{ - Assert.Fail("Create response content is empty."); -} - -if (!int.TryParse(createContent, out int createdEventId)) -{ - Assert.Fail($"Failed to parse created event ID from response. Content: {createContent}"); -} +int createdEventId = ParseCreatedEventId(createResponse.Content);Also applies to: 117-125
127-130
: Move admin token validation earlier in the test.The admin token null check occurs quite late in the test flow. For better "fail fast" behavior, validate this prerequisite earlier:
[Fact] public async Task Delete_ReturnsSuccess_WithAdminToken() { + if (_tokenStorage.AdminAccessToken == null) + { + Assert.Fail("Admin token is null"); + return; + } + var createResponse = await this.Client.CreateAsync(new CreateUpdateEventDTO { Title = _testEvent.Title, EventType = _testEvent.EventType }, _tokenStorage.AdminAccessToken); // Rest of the test... - if (_tokenStorage.AdminAccessToken == null) - { - Assert.Fail("Admin token is null"); - } var response = await this.Client.DeleteAsync(createdEventId, _tokenStorage.AdminAccessToken); Assert.Equal(HttpStatusCode.OK, response.StatusCode); }Streetcode/Streetcode.XUnitTest/MediatRTests/Event/UpdateEventTests.cs (2)
59-63
: Use ofAssert.Multiple
in xUnit tests.
Assert.Multiple
is typically not part of the core xUnit framework. Ensure the entire team is aligned on using the related extension library or consider individual assertions if sticking closely to xUnit’s standard practices.
141-152
: Consider verifying transaction rollback behavior.When mocking transaction scopes, it can be beneficial to confirm that an exception triggers a rollback, preserving data integrity. You can include an additional test or assertion to validate that the transaction scope is properly reversed on errors.
Streetcode/Streetcode.BLL/MediatR/Event/Create/CreateEventHandler.cs (2)
43-44
: Avoid calling_mapper.Map
twice for the same object.The method invokes
_mapper.Map(request.Event, eventEntity)
in the main flow and again inSetSpecialEventFields
. If the second call isn’t necessary, removing it can reduce redundant operations and improve maintainability.// Example removal of redundant mapping in SetSpecialEventFields (lines 75-76) -private void SetSpecialEventFields(EventEntity eventToCreate, CreateEventCommand request) -{ - _mapper.Map(request.Event, eventToCreate); - // ... +private void SetSpecialEventFields(EventEntity eventToCreate, CreateEventCommand request) +{ + // ...Also applies to: 75-76
73-86
: Ensure handling of additional or future event types.Currently,
SetSpecialEventFields
checks only forHistoricalEvent
orCustomEvent
. If other types are planned, consider making this logic more generic or extensible to accommodate future needs.Streetcode/Streetcode.BLL/MediatR/Event/Update/UpdateEventHandler.cs (2)
64-66
: Eliminate redundant_mapper.Map
calls.
_mapper.Map(request.Event, eventToUpdate);
is invoked in both the primary update logic andUpdateSpecialEventFields
, potentially duplicating entity mapping. Consolidate them to simplify the code and avoid accidental overwrites.Also applies to: 119-120
134-139
: Clarify in-memory vs. DB removal inUpdateEventStreetcodes
.Clearing the
EventStreetcodes
collection (line 134) and later removing them from the database (line 158) can be redundant. Confirm if both are needed or if one approach is sufficient to maintain data consistency and clarity.Also applies to: 149-159
Streetcode/Streetcode.WebApi/Controllers/Event/EventsController.cs (4)
24-29
: Evaluate whether these endpoints can be combined or if separate “short” data is truly necessary.
TheGetAllShort
endpoint is useful, but there might be potential duplication with theGetAll
endpoint. You could consider an optional query parameter in a single GET method that toggles between full results and short results.
38-46
: Adopt HTTP 201 Created for new resource creation.
Currently, the Create endpoint returns 200 OK. For REST best practices, returning 201 (Created) and including the new resource’s URI in the Location header is common.Here’s a possible diff for the attribute if you want to adopt 201 Created:
[HttpPost] [Authorize(Roles = nameof(UserRole.Admin))] - [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(int))] + [ProducesResponseType(StatusCodes.Status201Created, Type = typeof(int))]
48-56
: Consider placing the event ID in the route for consistency with usual REST patterns.
In many REST conventions, an update uses a PUT endpoint such as[HttpPut("{id:int}")]
, withid
passed separately. This helps keep the resource path consistent and unambiguous. Using the body to pass theId
is still valid but might deviate from standard patterns.
58-66
: Check if returning the entire deleted event is necessary.
Some APIs simply return a 204 (No Content) in response to a DELETE, or they return minimal information. If returning the entireEventDTO
is essential for the UI or logging, that’s fine; otherwise, consider returning a simpler response or 204 to avoid overhead.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
Streetcode/Streetcode.DAL/Persistence/Migrations/20250213203537_AddEventTable.Designer.cs
is excluded by!**/Migrations/**
,!**/*.Designer.cs
Streetcode/Streetcode.DAL/Persistence/Migrations/20250213203537_AddEventTable.cs
is excluded by!**/Migrations/**
Streetcode/Streetcode.DAL/Persistence/Migrations/StreetcodeDbContextModelSnapshot.cs
is excluded by!**/Migrations/**
📒 Files selected for processing (70)
Streetcode/Streetcode.BLL/DTO/Event/CreateUpdate/CreateUpdateEventDTO.cs
(1 hunks)Streetcode/Streetcode.BLL/DTO/Event/CustomEventDTO.cs
(1 hunks)Streetcode/Streetcode.BLL/DTO/Event/EventDTO.cs
(1 hunks)Streetcode/Streetcode.BLL/DTO/Event/EventShortDTO.cs
(1 hunks)Streetcode/Streetcode.BLL/DTO/Event/GetAllEventsResponseDTO.cs
(1 hunks)Streetcode/Streetcode.BLL/DTO/Event/HistoricalEventDTO.cs
(1 hunks)Streetcode/Streetcode.BLL/DTO/Event/UpdateEventDTO.cs
(1 hunks)Streetcode/Streetcode.BLL/Factories/Event/EventFactory.cs
(1 hunks)Streetcode/Streetcode.BLL/Mapping/Event/EventProfile.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/Create/CreateEventCommand.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/Create/CreateEventHandler.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/Delete/DeleteEventCommand.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/Delete/DeleteEventHandler.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/GetAll/GetAllEventsHandler.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/GetAll/GetAllEventsQuery.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/GetAllShort/GetAllEventsShortHandler.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/GetAllShort/GetAllEventsShortQuery.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/GetById/GetEventByIdHandler.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/GetById/GetEventByIdQuery.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/Update/UpdateEventCommand.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/Update/UpdateEventHandler.cs
(1 hunks)Streetcode/Streetcode.BLL/Resources/SharedResource.AnErrorOccurredSharedResource.en-US.resx
(1 hunks)Streetcode/Streetcode.BLL/Resources/SharedResource.AnErrorOccurredSharedResource.uk-UA.resx
(1 hunks)Streetcode/Streetcode.BLL/Resources/SharedResource.CannotFindSharedResource.en-US.resx
(1 hunks)Streetcode/Streetcode.BLL/Resources/SharedResource.CannotFindSharedResource.uk-UA.resx
(1 hunks)Streetcode/Streetcode.BLL/Resources/SharedResource.FailedToCreateSharedResource.en-US.resx
(1 hunks)Streetcode/Streetcode.BLL/Resources/SharedResource.FailedToCreateSharedResource.uk-UA.resx
(1 hunks)Streetcode/Streetcode.BLL/Resources/SharedResource.FailedToDeleteSharedResource.en-US.resx
(1 hunks)Streetcode/Streetcode.BLL/Resources/SharedResource.FailedToDeleteSharedResource.uk-UA.resx
(1 hunks)Streetcode/Streetcode.BLL/Resources/SharedResource.FailedToUpdateSharedResource.en-US.resx
(1 hunks)Streetcode/Streetcode.BLL/Resources/SharedResource.FailedToUpdateSharedResource.uk-UA.resx
(1 hunks)Streetcode/Streetcode.BLL/Resources/SharedResource.FailedToValidateSharedResource.en-US.resx
(1 hunks)Streetcode/Streetcode.BLL/Resources/SharedResource.FailedToValidateSharedResource.uk-UA.resx
(1 hunks)Streetcode/Streetcode.BLL/Resources/SharedResource.FieldNamesSharedResource.en-US.resx
(1 hunks)Streetcode/Streetcode.BLL/Resources/SharedResource.FieldNamesSharedResource.uk-UA.resx
(1 hunks)Streetcode/Streetcode.BLL/Validators/Event/BaseEventValidator.cs
(1 hunks)Streetcode/Streetcode.BLL/Validators/Event/CreateEventValidator.cs
(1 hunks)Streetcode/Streetcode.BLL/Validators/Event/UpdateEventValidator.cs
(1 hunks)Streetcode/Streetcode.DAL/Configurations/EventMap.cs
(1 hunks)Streetcode/Streetcode.DAL/Configurations/EventStreetcodesMap.cs
(1 hunks)Streetcode/Streetcode.DAL/Configurations/HistoricalEventMap.cs
(1 hunks)Streetcode/Streetcode.DAL/Entities/Event/CustomEvent.cs
(1 hunks)Streetcode/Streetcode.DAL/Entities/Event/Event.cs
(1 hunks)Streetcode/Streetcode.DAL/Entities/Event/EventStreetcodes.cs
(1 hunks)Streetcode/Streetcode.DAL/Entities/Event/HistoricalEvent.cs
(1 hunks)Streetcode/Streetcode.DAL/Entities/Streetcode/StreetcodeContent.cs
(3 hunks)Streetcode/Streetcode.DAL/Enums/EventType.cs
(1 hunks)Streetcode/Streetcode.DAL/Enums/EventTypeDiscriminators.cs
(1 hunks)Streetcode/Streetcode.DAL/Persistence/StreetcodeDbContext.cs
(2 hunks)Streetcode/Streetcode.DAL/Repositories/Interfaces/Base/IRepositoryWrapper.cs
(2 hunks)Streetcode/Streetcode.DAL/Repositories/Interfaces/Event/IEventRepository.cs
(1 hunks)Streetcode/Streetcode.DAL/Repositories/Interfaces/Event/IEventStreetcodesRepository.cs
(1 hunks)Streetcode/Streetcode.DAL/Repositories/Realizations/Base/RepositoryWrapper.cs
(4 hunks)Streetcode/Streetcode.DAL/Repositories/Realizations/Event/EventRepository.cs
(1 hunks)Streetcode/Streetcode.DAL/Repositories/Realizations/Event/EventStreetcodesRepository.cs
(1 hunks)Streetcode/Streetcode.WebApi/Controllers/Event/EventsController.cs
(1 hunks)Streetcode/Streetcode.WebApi/Extensions/SeedingLocalExtension.cs
(2 hunks)Streetcode/Streetcode.XIntegrationTest/ControllerTests/Event/EventControllerTests.cs
(1 hunks)Streetcode/Streetcode.XIntegrationTest/ControllerTests/Utils/Client/Event/EventClient.cs
(1 hunks)Streetcode/Streetcode.XUnitTest/Factories/Event/EventFactoryTests.cs
(1 hunks)Streetcode/Streetcode.XUnitTest/MediatRTests/Event/CreateEventTests.cs
(1 hunks)Streetcode/Streetcode.XUnitTest/MediatRTests/Event/DeleteEventTests.cs
(1 hunks)Streetcode/Streetcode.XUnitTest/MediatRTests/Event/GetAllEventsTests.cs
(1 hunks)Streetcode/Streetcode.XUnitTest/MediatRTests/Event/GetEventByIdTests.cs
(1 hunks)Streetcode/Streetcode.XUnitTest/MediatRTests/Event/UpdateEventTests.cs
(1 hunks)Streetcode/Streetcode.XUnitTest/Mocks/MockAnErrorOccurredLocalizer.cs
(1 hunks)Streetcode/Streetcode.XUnitTest/Mocks/MockCannotFindLocalizer.cs
(2 hunks)Streetcode/Streetcode.XUnitTest/Mocks/MockFailedToCreateLocalizer.cs
(1 hunks)Streetcode/Streetcode.XUnitTest/Mocks/MockFailedToDeleteLocalizer.cs
(1 hunks)Streetcode/Streetcode.XUnitTest/Mocks/MockFailedToUpdateLocalizer.cs
(1 hunks)
🔇 Additional comments (66)
Streetcode/Streetcode.BLL/Resources/SharedResource.FailedToValidateSharedResource.en-US.resx (1)
213-218
: Good addition of validation resources.These new validation messages align well with the PR objectives for implementing Events validation. The messages are clear and provide appropriate guidance to users about length constraints and title formatting requirements.
Streetcode/Streetcode.BLL/Resources/SharedResource.FailedToValidateSharedResource.uk-UA.resx (1)
213-218
: Proper localization consistency.The Ukrainian translations are well-crafted and maintain consistent meaning with the English versions. This ensures a good user experience across both language options.
Streetcode/Streetcode.XUnitTest/Mocks/MockCannotFindLocalizer.cs (1)
21-21
: Well-integrated error messages for the new Events functionality.The new error message keys "CannotFindAnyEvents" and "CannotFindEventWithCorrespondingId" are properly integrated into their respective error groups, maintaining consistency with the existing pattern. This ensures that the mock localizer can handle the new event-related error scenarios in unit tests.
Also applies to: 35-35
Streetcode/Streetcode.BLL/Resources/SharedResource.CannotFindSharedResource.uk-UA.resx (1)
327-332
: Well-localized event error messages.The Ukrainian translations for the event-related error messages are properly structured and follow the established patterns in the resource file. The translated content correctly conveys the meaning of the original English messages.
Streetcode/Streetcode.BLL/MediatR/Event/GetAllShort/GetAllEventsShortHandler.cs (1)
14-29
: Code structure and dependency injection look goodThe handler is well-structured with proper dependency injection through the constructor. All dependencies are correctly initialized and their purposes are clear. The use of interfaces rather than concrete implementations follows good dependency inversion principles.
Streetcode/Streetcode.DAL/Repositories/Realizations/Event/EventStreetcodesRepository.cs (2)
1-15
: Well-structured repository implementation following established patterns.The repository follows a clean implementation of the repository pattern and properly inherits from the base repository class, which is consistent with the architecture described in the PR objectives. This implementation will seamlessly integrate with the MediatR pattern mentioned in the PR.
8-8
:✅ Verification successful
Ensure IEventStreetcodesRepository is properly defined.
The repository implements IEventStreetcodesRepository, which should define any specific operations needed for EventStreetcodes beyond the standard CRUD operations provided by the base repository. While this implementation is correct, verify that the interface contains all necessary methods for your business requirements.
🏁 Script executed:
#!/bin/bash # Check the definition of IEventStreetcodesRepository find . -name "IEventStreetcodesRepository.cs" -type f -exec cat {} \;Length of output: 318
Interface Verification for IEventStreetcodesRepository
- Verified via the script output that the interface is defined correctly, inheriting from
IRepositoryBase<EventStreetcodes>
.- Currently, no additional methods are declared, which is acceptable if your business logic relies solely on the generic CRUD operations provided by the base repository.
- If future requirements call for custom operations specific to EventStreetcodes, consider extending this interface accordingly.
Streetcode/Streetcode.DAL/Repositories/Interfaces/Event/IEventRepository.cs (1)
1-13
: Repository interface follows the established patternThe IEventRepository interface follows the repository pattern structure used throughout the project and extends the generic IRepositoryBase with the Event entity type. This ensures consistency with the rest of the data access layer.
As the project grows, consider whether you'll need to add any custom query methods specific to Event retrieval that go beyond the base repository functionality.
Streetcode/Streetcode.DAL/Enums/EventType.cs (1)
7-14
: Clean enum implementation for event categorizationThe EventType enum provides a clear categorization mechanism for the two types of events mentioned in the PR (Historical and Custom). This will work well with the Table Per Hierarchy approach you're implementing.
If you anticipate adding more event types in the future, you might want to consider adding XML documentation comments to describe each enum value's purpose and use cases.
Streetcode/Streetcode.DAL/Entities/Event/HistoricalEvent.cs (1)
8-15
: Entity inheritance structure is appropriate, but consider nullability designThe HistoricalEvent class properly inherits from the Event base class as part of your TPH implementation. This provides a clean way to handle different event types.
I notice that both TimelineItemId and TimelineItem are nullable. Is this intentional? Consider whether a HistoricalEvent should always be associated with a TimelineItem. If so, these properties should potentially be non-nullable to enforce that relationship at the data model level.
Streetcode/Streetcode.DAL/Repositories/Interfaces/Event/IEventStreetcodesRepository.cs (1)
4-9
: Repository interface for junction entity follows established patternThe IEventStreetcodesRepository interface properly extends the base repository interface for the EventStreetcodes entity, which appears to be a junction entity connecting Events to Streetcodes.
As the implementation progresses, you might need to add specific methods for retrieving events by streetcode or vice versa. Consider whether specialized query methods would be beneficial for common access patterns.
Streetcode/Streetcode.BLL/Resources/SharedResource.FailedToCreateSharedResource.en-US.resx (1)
129-131
: Well-structured resource additionThe new error message for event creation failure has been properly added following the consistent pattern of other resource entries. This aligns well with the implementation of the new Events functionality described in the PR objectives.
Streetcode/Streetcode.BLL/Resources/SharedResource.FailedToUpdateSharedResource.uk-UA.resx (1)
129-131
: Appropriate localization for event update failureThe Ukrainian translation for the event update failure message has been added correctly, maintaining consistency with other resource entries in the file.
Streetcode/Streetcode.DAL/Entities/Event/EventStreetcodes.cs (1)
4-14
: Good implementation of the mapping entityThe
EventStreetcodes
class correctly defines the relationship between events and streetcodes. The usage of[Required]
attributes on ID properties and nullable navigation properties follows good practices for Entity Framework Core.One suggestion to consider for future refactoring:
- The composite primary key configuration is likely defined in the corresponding mapping class. Consider using Fluent API exclusively for all configurations to maintain consistency.
Streetcode/Streetcode.BLL/Resources/SharedResource.FailedToCreateSharedResource.uk-UA.resx (1)
159-161
: Resource entry properly addedThe new localized error message for event creation follows the established pattern in the resource file and maintains consistency with other entity error messages.
Streetcode/Streetcode.BLL/Resources/SharedResource.FailedToDeleteSharedResource.uk-UA.resx (1)
126-128
: Resource entry properly addedThe error message for event deletion has been correctly added, following the same pattern as other entity error messages in the resource file.
Streetcode/Streetcode.DAL/Configurations/HistoricalEventMap.cs (1)
19-19
: Verify that TimelineItemId is nullableThe
DeleteBehavior.SetNull
implies that theTimelineItemId
property inHistoricalEvent
is nullable. Ensure that this property is properly defined as nullable in the entity class to avoid runtime exceptions.Streetcode/Streetcode.BLL/Resources/SharedResource.FailedToDeleteSharedResource.en-US.resx (1)
126-128
: Consistent error message formattingThe added error message follows the established pattern and maintains consistency with other error messages in the resource file. The message is clear and concise, which is excellent for user experience.
Streetcode/Streetcode.DAL/Repositories/Interfaces/Base/IRepositoryWrapper.cs (2)
5-5
: Appropriate namespace importThe added import statement correctly references the Event namespace that contains the new repository interfaces.
64-65
: Well-integrated repository propertiesThe new event-related repository properties follow the established pattern in the codebase and are properly positioned within the interface. This addition maintains the consistency of the repository wrapper design while extending its functionality to support event management.
Streetcode/Streetcode.BLL/Resources/SharedResource.FailedToUpdateSharedResource.en-US.resx (1)
129-131
: Resource addition looks goodThe new error message for event updates follows the established naming pattern and message format used throughout the resource file.
Streetcode/Streetcode.DAL/Entities/Streetcode/StreetcodeContent.cs (2)
17-17
: Adding Event namespace reference is appropriateThe new using directive correctly imports the Event namespace needed for the relationship.
115-115
: Navigation property correctly implements many-to-many relationshipThe EventStreetcodes property is properly implemented as a nullable collection with initialization. This establishes the appropriate relationship between StreetcodeContent and Event entities.
Streetcode/Streetcode.BLL/Resources/SharedResource.AnErrorOccurredSharedResource.uk-UA.resx (2)
123-125
: Event creation error resource looks goodThe Ukrainian localization for event creation errors follows the established pattern and includes the placeholder for detailed error messages.
129-131
: Event update error resource looks goodThe Ukrainian localization for event update errors follows the established pattern and includes the placeholder for detailed error messages.
Streetcode/Streetcode.DAL/Configurations/EventStreetcodesMap.cs (1)
7-26
: Well-structured configuration classThe EventStreetcodesMap follows Entity Framework Core best practices with a properly configured composite key and clearly defined relationships. The cascade delete behavior is appropriate for this join entity.
Streetcode/Streetcode.BLL/Resources/SharedResource.FieldNamesSharedResource.uk-UA.resx (1)
327-335
: Appropriate localization additionsThe new Ukrainian translations for "Date", "Location", and "Organizer" are properly formatted and maintain consistency with the existing resource entries. These strings will support the UI elements for the new Event functionality.
Streetcode/Streetcode.DAL/Repositories/Realizations/Base/RepositoryWrapper.cs (3)
7-7
: Appropriate imports for new event functionalityThe added using directives correctly reference the new event-related interfaces and implementations.
Also applies to: 24-24
126-129
: Well-structured repository field declarationsThe private fields for event repositories follow the established nullable pattern used throughout the class.
644-668
: Consistent repository property implementationThe EventRepository and EventStreetcodesRepository properties follow the same lazy initialization pattern used throughout the class, maintaining consistency with the existing architecture.
Streetcode/Streetcode.BLL/Resources/SharedResource.FieldNamesSharedResource.en-US.resx (1)
327-335
: Appropriate English localization entriesThe English localization entries for "Date", "Location", and "Organizer" are properly formatted and align with the Ukrainian translations. These strings support internationalization for the new Event functionality.
Streetcode/Streetcode.BLL/Validators/Event/BaseEventValidator.cs (1)
8-35
: Well-structured validator implementationThe validator follows best practices with FluentValidation:
- Constants for length constraints
- Localized error messages
- Separate validation rules for each property
- Clear, maintainable structure
Streetcode/Streetcode.BLL/MediatR/Event/Delete/DeleteEventHandler.cs (1)
28-52
: Well-implemented command handler with proper error handlingThe handler follows the mediator pattern correctly and includes appropriate error handling for event not found and unsuccessful deletion scenarios. Good use of localization for error messages and proper logging.
Streetcode/Streetcode.BLL/DTO/Event/UpdateEventDTO.cs (1)
5-8
: Clean and well-designed DTO implementationThe DTO properly extends the base
CreateUpdateEventDTO
by adding the necessaryId
property for update operations. This approach maintains code reuse while adding the specific property needed for updates.Streetcode/Streetcode.BLL/DTO/Event/CustomEventDTO.cs (1)
9-13
: Clean implementation of the CustomEventDTO class.The class properly inherits from EventDTO and includes nullable string properties for Location and Organizer, which aligns with the requirements for custom event functionality.
Streetcode/Streetcode.XUnitTest/Mocks/MockFailedToUpdateLocalizer.cs (1)
18-18
: Well-integrated error message for event updates.The new error message "FailedToUpdateEvent" follows the established pattern and integrates seamlessly with the existing error messages in the mock localizer.
Streetcode/Streetcode.XUnitTest/Mocks/MockFailedToDeleteLocalizer.cs (1)
20-20
: Well-integrated error message for event deletions.The new error message "FailedToDeleteEvent" aligns with the existing pattern and complements the event management functionality being added to the system.
Streetcode/Streetcode.BLL/DTO/Event/HistoricalEventDTO.cs (1)
1-13
: Well-designed DTO class that follows inheritance patternThe
HistoricalEventDTO
is properly implemented as a subclass ofEventDTO
, which aligns with the TPH (Table Per Hierarchy) approach mentioned in the PR objectives. The class includes a specificTimelineItemId
property that allows historical events to be associated with timeline items.This implementation supports the separation of different event types while maintaining a common base structure, which is a good design practice for extensibility.
Streetcode/Streetcode.XUnitTest/Mocks/MockFailedToCreateLocalizer.cs (1)
21-21
: Error message addition aligns with new event functionalityThe addition of the "FailedToCreateEvent" error message to the mock localizer is consistent with the new event functionality being implemented. This ensures proper error handling and localization for event creation failures in tests.
The message follows the naming pattern of existing entries, which maintains consistency in the codebase.
Streetcode/Streetcode.XUnitTest/Mocks/MockAnErrorOccurredLocalizer.cs (1)
15-16
: Consistent error message additions for event operationsThe addition of "AnErrorOccurredWhileCreatingEvent" and "AnErrorOccurredWhileUpdatingEvent" error messages properly extends the error handling capabilities for the new event functionality. These messages follow the established naming pattern and provide specific feedback for different event operations.
These additions ensure comprehensive test coverage for error scenarios related to event management.
Streetcode/Streetcode.DAL/Persistence/StreetcodeDbContext.cs (2)
7-7
: Appropriate import for new entity namespaceThe addition of the
Streetcode.DAL.Entities.Event
namespace import is necessary to support the new Event entity being introduced. This import follows the existing pattern for entity namespace imports.
78-78
: DbSet property added for Events entityThe addition of the
Events
DbSet property is essential for Entity Framework Core to manage the new Event entities. The property follows the naming conventions used throughout the class (plural form for collections) and is positioned appropriately among the other entity DbSet declarations.This change enables the data access layer to perform CRUD operations on Event entities, supporting the new functionality described in the PR objectives.
Streetcode/Streetcode.BLL/MediatR/Event/Delete/DeleteEventCommand.cs (1)
9-13
: Command definition looks well-structuredGood implementation of the MediatR command pattern. The record syntax is concise and appropriate for this use case, implementing the IRequest interface with FluentResults for proper error handling.
Streetcode/Streetcode.BLL/MediatR/Event/Create/CreateEventCommand.cs (1)
1-9
: Well-structured command implementationThe command is correctly implemented using the MediatR pattern with FluentResults for proper error handling. The record syntax provides a clean, concise way to define the command.
Streetcode/Streetcode.BLL/DTO/Event/CreateUpdate/CreateUpdateEventDTO.cs (1)
7-10
: Well-defined properties with appropriate nullabilityGood job defining the required properties with null forgiving operator and marking optional properties as nullable. This makes the contract clear for consumers of this DTO.
Streetcode/Streetcode.XUnitTest/Factories/Event/EventFactoryTests.cs (2)
9-20
: Test follows good Arrange-Act-Assert patternThe test is well-structured following the standard Arrange-Act-Assert pattern, making it clear and easy to understand.
22-33
: Test follows good Arrange-Act-Assert patternThe test is well-structured following the standard Arrange-Act-Assert pattern, making it clear and easy to understand.
Streetcode/Streetcode.BLL/Validators/Event/CreateEventValidator.cs (1)
6-12
: Well-structured validator implementationThe validator implementation follows good practices by:
- Using dependency injection for the
BaseEventValidator
- Applying composition to reuse validation logic
- Following the FluentValidation pattern with clear rule definition
This approach promotes code reuse and maintainability.
Streetcode/Streetcode.BLL/MediatR/Event/Update/UpdateEventCommand.cs (1)
7-8
: Command structure looks goodThe command structure follows the MediatR pattern correctly and returns an appropriate result type. The design indicates that a successful update will return the ID of the updated entity.
Streetcode/Streetcode.DAL/Configurations/EventMap.cs (1)
14-23
: Good implementation of TPH pattern for Event entityThe Entity Framework Core configuration correctly sets up the Table Per Hierarchy inheritance pattern for the Event entity. This approach allows storing different event types (HistoricalEvent and CustomEvent) in a single table with a discriminator column, which is an efficient design choice.
Streetcode/Streetcode.BLL/Resources/SharedResource.AnErrorOccurredSharedResource.en-US.resx (2)
123-125
: Good addition of localized error messageThe new resource entry for event creation errors follows the established pattern for error messages in the application. This will help with consistent error reporting and localization.
129-131
: Good addition of localized error messageThe new resource entry for event updating errors follows the established pattern for error messages in the application. This will help with consistent error reporting and localization.
Streetcode/Streetcode.WebApi/Extensions/SeedingLocalExtension.cs (1)
1140-1172
: Good implementation of Event data seedingThe code properly checks for existing events before adding sample data, which prevents duplicate records during multiple application starts. The samples include both CustomEvent and HistoricalEvent types with various properties, providing good test data for development and testing.
I particularly like how the HistoricalEvent "Підрозділ Протасового" links to a TimelineItem, which shows the relationship between events and timeline items.
Streetcode/Streetcode.BLL/Mapping/Event/EventProfile.cs (1)
23-34
: Good implementation of inheritance mappingThe mapping configuration correctly handles inheritance for the UpdateEventDTO to different event types. The specific property mappings for CustomEvent and HistoricalEvent ensure that the appropriate properties are mapped to each derived type.
Streetcode/Streetcode.XUnitTest/MediatRTests/Event/GetEventByIdTests.cs (1)
18-22
: Solid use of mock fields for the test class
These mocks clearly separate concerns and help with isolating dependencies, making your tests more robust. Keep it up!Streetcode/Streetcode.BLL/MediatR/Event/GetById/GetEventByIdHandler.cs (3)
21-31
: Thumbs up for clear constructor-based DI
This approach makes dependencies explicit and fosters good testing practices. Keep ensuring that only relevant services are injected for single-responsibility.
33-46
: Well-handled not-found logic
Returning a fail result with an informative, localized message is a great pattern for clarity and user feedback. Ensure the resource key remains consistent across different error states.
63-79
: Defensive consideration for null references
Using the null check onEventStreetcodes
is solid. Continue verifying the entire object graph for potential null references (for instance,StreetcodeContent
usage) to minimize runtime surprises in future expansions.Streetcode/Streetcode.DAL/Enums/EventTypeDiscriminators.cs (1)
11-14
: Clear definition of event type properties
These static properties serve as a reliable reference for TPH (Table Per Hierarchy) discrimination. Ensure they remain in sync with the rest of the system to avoid mismatches.Streetcode/Streetcode.BLL/MediatR/Event/GetAll/GetAllEventsHandler.cs (1)
23-33
: Constructor DI pattern is consistent
Your injection of mapper, repository, logger, and localizer keeps the class cohesive. This consistency benefits unit testing and maintainability.Streetcode/Streetcode.XUnitTest/MediatRTests/Event/DeleteEventTests.cs (1)
35-56
: LGTM! Well-structured test for successful event deletion.The test follows good practices for unit testing:
- Clear AAA (Arrange-Act-Assert) structure
- Specific expectations for repository method calls
- Comprehensive assertions to validate the result
Streetcode/Streetcode.BLL/MediatR/Event/Create/CreateEventHandler.cs (1)
36-71
: Overall logic looks consistent.The transactional flow, error handling, and logging appear correct. This design should work well for event creation.
Streetcode/Streetcode.BLL/MediatR/Event/Update/UpdateEventHandler.cs (2)
59-62
: Review EF tracking when changing event type.Creating a new entity with the same ID and discarding the old reference could cause EF to track multiple objects with the same key. Verify that entity state transitions are handled properly to avoid conflicts or unexpected behavior.
41-93
: Good use of transaction handling and error reporting.The update flow is well-organized: retrieving, mapping, validating, and saving changes with robust error handling. This should help ensure reliable event updates.
Streetcode/Streetcode.WebApi/Controllers/Event/EventsController.cs (2)
17-22
: Consider adding explicit handling for empty results or invalid pagination.
TheGetAll
method allowspage
andpageSize
to be null, but the current code does not explicitly validate them or handle invalid values (e.g., zero). If a query returns no events, does the Mediator return an empty list or a 404? Make sure to confirm or document the behavior for clarity.Would you like to verify how
GetAllEventsQuery
handles these scenarios? I can generate a script to inspect the query logic and search for potential edge cases.
31-36
: Verify not found behavior for the requested ID.
GetById
handles the retrieval of a single event, but the code currently does not advertise any 404 response. Confirm thatHandleResult
orGetEventByIdQuery
properly returns a 404 or a suitable response when the ID is invalid or not found.
using Streetcode.DAL.Enums; | ||
using Streetcode.BLL.DTO.Streetcode; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Check namespace import
The import for Streetcode.DAL.Enums
suggests that there might be an enum type that could be used for EventType instead of a string.
🏁 Script executed:
#!/bin/bash
# Check if there's an enum type that could be used for EventType
rg -A 5 "namespace.*Enums" --glob "*.cs"
Length of output: 4886
Action Required: Consider Using the EventType Enum in EventDTO
After confirming the available enum types, we found that there is an EventType
enum defined in Streetcode.DAL/Enums/EventType.cs
with the values Historical
and Custom
. This suggests that instead of exposing event types as strings in your DTO, you might benefit from using the type-safe enum.
- Verify if a property in EventDTO intended for event type is currently a string.
- If so, consider switching its type to the
EventType
enum to leverage compile-time checks and reduce potential errors. - If you intentionally prefer using a string (e.g., for legacy compatibility or specific serialization concerns), please add a clarifying comment explaining the choice.
namespace Streetcode.DAL.Entities.Event | ||
{ | ||
[Table("event", Schema = "events")] | ||
public class Event | ||
{ | ||
[Key] | ||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] | ||
public int Id { get; set; } | ||
|
||
[Required] | ||
[DataType(DataType.Date)] | ||
public DateTime Date { get; set; } | ||
|
||
[Required] | ||
[MaxLength(100)] | ||
public string? Title { get; set; } | ||
|
||
[MaxLength(600)] | ||
public string? Description { get; set; } | ||
|
||
[Required] | ||
public string EventType { get; set; } | ||
public List<EventStreetcodes> EventStreetcodes { get; set; } = new(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Event entity implementation looks good, but has some inconsistencies with nullable properties
The Event entity is well-structured with appropriate database annotations and relationships. However, there's a contradiction between nullability annotations and validation attributes:
-
On lines 26 and 29, the
Title
andDescription
properties are marked as nullable withstring?
, butTitle
also has a[Required]
attribute. This creates a mixed message - either the property should be required (and not nullable) or optional. -
The
EventType
property on line 32 is required but doesn't have constraints on valid values. Consider using an enum or adding validation to ensure only valid event types are accepted.
- [Required]
- [MaxLength(100)]
- public string? Title { get; set; }
+ [Required]
+ [MaxLength(100)]
+ public string Title { get; set; }
- [MaxLength(600)]
- public string? Description { get; set; }
+ [MaxLength(600)]
+ public string? Description { get; set; }
RuleFor(e => e.Title) | ||
.NotEmpty().WithMessage(localizer["CannotBeEmpty", fieldLocalizer["Title"]]) | ||
.Length(TitleMinLength, TitleMaxLength).WithMessage(localizer["LengthBetween", TitleMinLength, TitleMaxLength]) | ||
.Matches(@"^[A-Za-zА-Яа-яІіЇїЄєҐґ0-9{L}\d\s\-'-]+$").WithMessage(localizer["TitleFormat"]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix regex pattern for title validation
The regex pattern contains an error: {L}
is not a valid regex construct. If you intended to match any Unicode letter character, you should use \p{L}
instead.
- .Matches(@"^[A-Za-zА-Яа-яІіЇїЄєҐґ0-9{L}\d\s\-'-]+$").WithMessage(localizer["TitleFormat"]);
+ .Matches(@"^[A-Za-zА-Яа-яІіЇїЄєҐґ0-9\p{L}\d\s\-'-]+$").WithMessage(localizer["TitleFormat"]);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
.Matches(@"^[A-Za-zА-Яа-яІіЇїЄєҐґ0-9{L}\d\s\-'-]+$").WithMessage(localizer["TitleFormat"]); | |
.Matches(@"^[A-Za-zА-Яа-яІіЇїЄєҐґ0-9\p{L}\d\s\-'-]+$").WithMessage(localizer["TitleFormat"]); |
public async Task<RestResponse> DeleteAsync(int id, string authToken = "") | ||
{ | ||
var dto = new { Id = id }; | ||
return await this.SendCommand($"/Delete/{id}", Method.Delete, dto, authToken); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Consider revising the DeleteAsync method implementation
There appears to be redundancy in how the ID is passed. You're including it in both the URL path ($"/Delete/{id}"
) and in the request body as an anonymous object. Check your API endpoint implementation to ensure this is the expected format.
🏁 Script executed:
#!/bin/bash
# Find the endpoint implementation for Delete in the EventsController
rg -A 10 "Delete.*Event.*" --type cs
Length of output: 14466
Action Required: Eliminate redundant ID passing in DeleteAsync
It appears that the method currently sends the event ID both in the URL (via /Delete/{id}
) and in the request body as an anonymous object. The API endpoint—and its corresponding DeleteEventCommand and handler—only expect the ID from the URL. To avoid confusion and potential mismatches with the API contract, please consider one of the following adjustments:
-
Remove the redundant request body:
Update the method to simply pass the ID in the URL. For example:public async Task<RestResponse> DeleteAsync(int id, string authToken = "") { return await this.SendCommand($"/Delete/{id}", Method.Delete, null, authToken); }
-
Alternatively, if the API is intended to accept additional data from the body:
Confirm the endpoint’s expected payload, and modify the API contract to process both the URL and body values consistently.
Please verify the API’s design requirements and update accordingly.
public class GetAllEventsResponseDTO | ||
{ | ||
public int TotalAmount { get; set; } | ||
public IEnumerable<object> Events { get; set; } = new List<object>(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Reconsider using generic object type for the Events collection.
Using IEnumerable<object>
for the Events property is not type-safe and could lead to runtime errors during serialization/deserialization or when accessing properties. Consider using a specific event type or interface instead.
public class GetAllEventsResponseDTO
{
public int TotalAmount { get; set; }
- public IEnumerable<object> Events { get; set; } = new List<object>();
+ public IEnumerable<EventDTO> Events { get; set; } = new List<EventDTO>();
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
public class GetAllEventsResponseDTO | |
{ | |
public int TotalAmount { get; set; } | |
public IEnumerable<object> Events { get; set; } = new List<object>(); | |
} | |
public class GetAllEventsResponseDTO | |
{ | |
public int TotalAmount { get; set; } | |
public IEnumerable<EventDTO> Events { get; set; } = new List<EventDTO>(); | |
} |
using Streetcode.DAL.Enums; | ||
|
||
namespace Streetcode.BLL.DTO.Event.CreateUpdate | ||
{ | ||
public class CreateUpdateEventDTO | ||
{ | ||
public string Title { get; set; } = null!; | ||
public DateTime Date { get; set; } | ||
public string? Description { get; set; } | ||
public List<int>? StreetcodeIds { get; set; } | ||
public string EventType { get; set; } | ||
public string? Location { get; set; } | ||
public string? Organizer { get; set; } | ||
public int? TimelineItemId { get; set; } | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider using an enum instead of string for EventType
The EventType property is defined as a string, but since it appears to have specific discriminators (as seen in the test file with EventTypeDiscriminators enum), consider using an enum type instead. This would provide type safety and prevent errors from invalid string values.
public string Title { get; set; } = null!;
public DateTime Date { get; set; }
public string? Description { get; set; }
public List<int>? StreetcodeIds { get; set; }
-public string EventType { get; set; }
+public EventTypeDiscriminators EventType { get; set; }
public string? Location { get; set; }
public string? Organizer { get; set; }
public int? TimelineItemId { get; set; }
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
using Streetcode.DAL.Enums; | |
namespace Streetcode.BLL.DTO.Event.CreateUpdate | |
{ | |
public class CreateUpdateEventDTO | |
{ | |
public string Title { get; set; } = null!; | |
public DateTime Date { get; set; } | |
public string? Description { get; set; } | |
public List<int>? StreetcodeIds { get; set; } | |
public string EventType { get; set; } | |
public string? Location { get; set; } | |
public string? Organizer { get; set; } | |
public int? TimelineItemId { get; set; } | |
} | |
using Streetcode.DAL.Enums; | |
namespace Streetcode.BLL.DTO.Event.CreateUpdate | |
{ | |
public class CreateUpdateEventDTO | |
{ | |
public string Title { get; set; } = null!; | |
public DateTime Date { get; set; } | |
public string? Description { get; set; } | |
public List<int>? StreetcodeIds { get; set; } | |
public EventTypeDiscriminators EventType { get; set; } | |
public string? Location { get; set; } | |
public string? Organizer { get; set; } | |
public int? TimelineItemId { get; set; } | |
} | |
} |
public static DAL.Entities.Event.Event CreateEvent(string eventType) | ||
{ | ||
switch(eventType) | ||
{ | ||
case "Custom": | ||
return new CustomEvent(); | ||
case "Historical": | ||
return new HistoricalEvent(); | ||
default: | ||
throw new ArgumentException($"Unsupported streetcode type: {eventType}", nameof(eventType)); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Recommend using enum for event types instead of string literals
Using string literals for event types is error-prone and doesn't leverage compile-time checking. Consider:
- Using an enum from
Streetcode.DAL.Enums
since you're already importing this namespace - Fixing the error message which incorrectly references "streetcode type" instead of "event type"
- Adding a null check for the
eventType
parameter
- public static DAL.Entities.Event.Event CreateEvent(string eventType)
+ public static DAL.Entities.Event.Event CreateEvent(string eventType)
{
+ if (string.IsNullOrEmpty(eventType))
+ {
+ throw new ArgumentException("Event type cannot be null or empty", nameof(eventType));
+ }
+
switch(eventType)
{
case "Custom":
return new CustomEvent();
case "Historical":
return new HistoricalEvent();
default:
- throw new ArgumentException($"Unsupported streetcode type: {eventType}", nameof(eventType));
+ throw new ArgumentException($"Unsupported event type: {eventType}", nameof(eventType));
}
}
// Even better approach with enum:
+ public static DAL.Entities.Event.Event CreateEvent(EventType eventType)
+ {
+ switch(eventType)
+ {
+ case EventType.Custom:
+ return new CustomEvent();
+ case EventType.Historical:
+ return new HistoricalEvent();
+ default:
+ throw new ArgumentException($"Unsupported event type: {eventType}", nameof(eventType));
+ }
+ }
This would make the code more robust and maintainable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (8)
Streetcode/Streetcode.BLL/MediatR/Event/Create/CreateEventHandler.cs (4)
38-39
: Consider using explicit braces for the using statementWhile this code works perfectly, adding explicit braces for the using statement would enhance readability and help prevent potential future errors if additional code is added later.
- using(var transactionScope = _repositoryWrapper.BeginTransaction()) - { + using (var transactionScope = _repositoryWrapper.BeginTransaction()) + {Also, consider adding a space after
using
for consistent code style.
89-102
: Consider combining save operations and validating StreetcodeIdsThe current implementation performs a separate save operation for the event streetcodes. Consider combining this with the previous save operation for better efficiency. Additionally, there's no validation that the provided streetcode IDs actually exist.
- private async Task SetEventStreetcodes(EventEntity eventEntity, CreateEventCommand request) + private async Task SetEventStreetcodes(EventEntity eventEntity, IEnumerable<int> streetcodeIds) { - if (request.Event.StreetcodeIds == null) + if (streetcodeIds == null || !streetcodeIds.Any()) { return; } + // Optional: Validate that all streetcodeIds exist + var existingStreetcodeIds = await _repositoryWrapper.StreetcodeRepository + .GetAllAsync(s => streetcodeIds.Contains(s.Id)) + .Select(s => s.Id) + .ToListAsync(); + + if (existingStreetcodeIds.Count != streetcodeIds.Count()) + { + var nonExistentIds = streetcodeIds.Except(existingStreetcodeIds); + _logger.LogWarning($"Some streetcodes were not found: {string.Join(", ", nonExistentIds)}"); + } - var eventStreetcodes = request.Event.StreetcodeIds + var eventStreetcodes = existingStreetcodeIds .Select(id => new EventStreetcodes { EventId = eventEntity.Id, StreetcodeId = id }) .ToList(); await _repositoryWrapper.EventStreetcodesRepository.CreateRangeAsync(eventStreetcodes); - await _repositoryWrapper.SaveChangesAsync(); }Then update the call in the Handle method:
- await SetEventStreetcodes(eventEntity, request); + await SetEventStreetcodes(eventEntity, request.Event.StreetcodeIds); + await _repositoryWrapper.SaveChangesAsync();This changes would:
- Make the method more focused by accepting only what it needs
- Add validation for streetcode IDs existence
- Combine save operations for better efficiency
36-71
: Consider implementing optimistic concurrency for event creationThe current implementation doesn't handle potential concurrency issues, which could arise if multiple users attempt to create similar events simultaneously.
Consider implementing optimistic concurrency control either through EF Core's built-in mechanisms or through business-level validation to prevent duplicate events.
// Example validation in the Handle method var existingEvent = await _repositoryWrapper.EventRepository .GetFirstOrDefaultAsync(e => e.Title == request.Event.Title && e.EventType == request.Event.EventType); if (existingEvent != null) { string errorMsg = _stringLocalizerFailedToCreate["EventAlreadyExists"].Value; _logger.LogWarning(request, errorMsg); return Result.Fail(new Error(errorMsg)); }
36-71
: Enhance error messages with more context for better troubleshootingWhile the current error messages use localization (which is excellent), they could be enhanced with more specific context about what failed during event creation.
Consider adding more detailed context to error messages:
- string errorMsg = _stringLocalizerAnErrorOccurred["AnErrorOccurredWhileCreatingEvent", ex.Message].Value; + string errorMsg = _stringLocalizerAnErrorOccurred["AnErrorOccurredWhileCreatingEvent", + $"Event type: {request.Event.EventType}, Error: {ex.Message}"].Value;This additional context would make troubleshooting easier by providing more specific information about what failed.
Streetcode/Streetcode.BLL/MediatR/Event/Update/UpdateEventHandler.cs (4)
41-44
: Add concurrency checks for robust transaction handling
The approach of wrapping the update in a transaction is excellent. However, consider handling concurrency issues explicitly (e.g., using row versioning or concurrency tokens) to avoid overwriting changes made concurrently.
64-64
: Avoid redundant AutoMapper calls
_mapper.Map(request.Event, eventToUpdate)
is called at lines 64 and 120, which could lead to confusion or potential overwriting of data. Consolidating the calls or removing duplicates could simplify logic.Also applies to: 120-120
100-111
: Plan for extending new event types
Currently, only "HistoricalEvent" and "CustomEvent" are handled. Future additions will require updating this switch. Consider using polymorphic resolution or an extensible pattern for new event types.
70-72
: Evaluate multiple database saves
The code saves changes twice: once for streetcodes (line 163) and once for event updates (line 71). This pattern can create partial updates if the first save succeeds and the second fails. Consider a single commit for consistency and performance.Also applies to: 163-164
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (2)
Streetcode/Streetcode.DAL/Persistence/Migrations/20250213203537_AddEventTable.cs
is excluded by!**/Migrations/**
Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/AddEventTable.sql
is excluded by!**/ScriptsMigration/**
,!**/Streetcode/Streetcode.DAL/Persistence/ScriptsMigration/**
📒 Files selected for processing (4)
Streetcode/Streetcode.BLL/DTO/Event/CreateUpdate/CreateUpdateEventDTO.cs
(1 hunks)Streetcode/Streetcode.BLL/DTO/Event/CustomEventDTO.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/Create/CreateEventHandler.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/Update/UpdateEventHandler.cs
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- Streetcode/Streetcode.BLL/DTO/Event/CustomEventDTO.cs
- Streetcode/Streetcode.BLL/DTO/Event/CreateUpdate/CreateUpdateEventDTO.cs
🧰 Additional context used
🧬 Code Definitions (1)
Streetcode/Streetcode.BLL/MediatR/Event/Update/UpdateEventHandler.cs (2)
Streetcode/Streetcode.BLL/Factories/Event/EventFactory.cs (2) (2)
DAL
(8-19)EventFactory
(6-20)Streetcode/Streetcode.DAL/Repositories/Realizations/Event/EventRepository.cs (2) (2)
EventRepository
(12-18)EventRepository
(14-17)
🔇 Additional comments (4)
Streetcode/Streetcode.BLL/MediatR/Event/Create/CreateEventHandler.cs (2)
1-14
: The imports and namespace structure look appropriateThe imports cover all necessary dependencies for the functionality being implemented, and the namespace follows the project's convention correctly.
15-34
: Good use of dependency injection and immutable fieldsThe class properly implements the
IRequestHandler
interface and follows good practices for dependency injection. All injected dependencies are stored in private readonly fields, which helps ensure they're not accidentally modified.Streetcode/Streetcode.BLL/MediatR/Event/Update/UpdateEventHandler.cs (2)
59-63
: Good approach to handle event type changes
The check for changed event type before updating is clear and helps ensure the correct entity subtype is used.
136-141
: Confirm intended behavior whenStreetcodeIds
is null
ClearingEventStreetcodes
before early returning might inadvertently remove all associations if it's not the intended outcome for a null or missing StreetcodeIds array.Do you intend to remove all streetcode links when
StreetcodeIds
isnull
? If not, you may want to skip clearing the collection in this scenario.
var eventEntity = EventFactory.CreateEvent(request.Event.EventType); | ||
_mapper.Map(request.Event, eventEntity); | ||
|
||
SetSpecialEventFields(eventEntity, request); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Avoid duplicate mapping in SetSpecialEventFields
The code maps properties from the request to the entity twice - once here and again in the SetSpecialEventFields
method (line 75). This redundancy could lead to inconsistencies if mappings are modified in one place but not the other.
var eventEntity = EventFactory.CreateEvent(request.Event.EventType);
_mapper.Map(request.Event, eventEntity);
- SetSpecialEventFields(eventEntity, request);
+ SetSpecialEventFields(eventEntity, request.Event);
Then update the SetSpecialEventFields
method signature and implementation to remove the duplicate mapping.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
var eventEntity = EventFactory.CreateEvent(request.Event.EventType); | |
_mapper.Map(request.Event, eventEntity); | |
SetSpecialEventFields(eventEntity, request); | |
var eventEntity = EventFactory.CreateEvent(request.Event.EventType); | |
_mapper.Map(request.Event, eventEntity); | |
SetSpecialEventFields(eventEntity, request.Event); |
private void SetSpecialEventFields(EventEntity eventToCreate, CreateEventCommand request) | ||
{ | ||
_mapper.Map(request.Event, eventToCreate); | ||
|
||
if (eventToCreate is HistoricalEvent historicalEvent) | ||
{ | ||
historicalEvent.TimelineItemId = request.Event.TimelineItemId; | ||
} | ||
else if (eventToCreate is CustomEvent customEvent) | ||
{ | ||
customEvent.DateString = request.Event.DateString; | ||
customEvent.Location = request.Event.Location; | ||
customEvent.Organizer = request.Event.Organizer; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Refactor SetSpecialEventFields to avoid duplicate mapping
This method currently duplicates the mapping that's already done in the Handle method. Consider refactoring to avoid redundant mapping and explicitly focus on setting type-specific fields.
- private void SetSpecialEventFields(EventEntity eventToCreate, CreateEventCommand request)
+ private void SetSpecialEventFields(EventEntity eventToCreate, CreateUpdateEventDTO eventDto)
{
- _mapper.Map(request.Event, eventToCreate);
if (eventToCreate is HistoricalEvent historicalEvent)
{
- historicalEvent.TimelineItemId = request.Event.TimelineItemId;
+ historicalEvent.TimelineItemId = eventDto.TimelineItemId;
}
else if (eventToCreate is CustomEvent customEvent)
{
- customEvent.DateString = request.Event.DateString;
- customEvent.Location = request.Event.Location;
- customEvent.Organizer = request.Event.Organizer;
+ customEvent.DateString = eventDto.DateString;
+ customEvent.Location = eventDto.Location;
+ customEvent.Organizer = eventDto.Organizer;
}
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
private void SetSpecialEventFields(EventEntity eventToCreate, CreateEventCommand request) | |
{ | |
_mapper.Map(request.Event, eventToCreate); | |
if (eventToCreate is HistoricalEvent historicalEvent) | |
{ | |
historicalEvent.TimelineItemId = request.Event.TimelineItemId; | |
} | |
else if (eventToCreate is CustomEvent customEvent) | |
{ | |
customEvent.DateString = request.Event.DateString; | |
customEvent.Location = request.Event.Location; | |
customEvent.Organizer = request.Event.Organizer; | |
} | |
} | |
private void SetSpecialEventFields(EventEntity eventToCreate, CreateUpdateEventDTO eventDto) | |
{ | |
if (eventToCreate is HistoricalEvent historicalEvent) | |
{ | |
historicalEvent.TimelineItemId = eventDto.TimelineItemId; | |
} | |
else if (eventToCreate is CustomEvent customEvent) | |
{ | |
customEvent.DateString = eventDto.DateString; | |
customEvent.Location = eventDto.Location; | |
customEvent.Organizer = eventDto.Organizer; | |
} | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
🧹 Nitpick comments (23)
Streetcode/Streetcode.BLL/MediatR/Event/GetAllShort/GetAllEventsShortHandler.cs (2)
14-17
: Ensure namespace alignment with file location
The namespace isStreetcode.BLL.MediatR.Event.GetAll
, but the file path includesGetAllShort
. Consider adjusting the namespace or file path naming to maintain consistency and improve discoverability.
31-33
: Consider handling large result sets
This code retrieves all events in one go. If the database grows, this might result in performance issues. Implement pagination or filtering strategies to optimize retrieval of a potentially large dataset.Streetcode/Streetcode.BLL/Validators/Event/BaseEventValidator.cs (2)
22-23
: Consider additional date validation.The current validation only checks if the date is not empty. Consider adding validation for:
- Date format validation
- Reasonable date range validation (e.g., not too far in the past or future)
RuleFor(e => e.Date) .NotEmpty().WithMessage(localizer["CannotBeEmpty", fieldLocalizer["Date"]]) + .Must(date => date > DateTime.MinValue && date < DateTime.MaxValue) + .WithMessage(localizer["InvalidDateRange"]);
1-35
: Consider validation for remaining DTO properties.The DTO includes additional properties that aren't validated in this class:
StreetcodeIds
(List of integers)TimelineItemId
(Nullable integer)DateString
(Nullable string)If these properties have specific validation requirements, consider adding appropriate rules for them.
Streetcode/Streetcode.BLL/DTO/Event/EventShortDTO.cs (1)
9-15
: Consider introducing an enum or validation forEventType
.
While the current string approach is flexible, using an enum (or a validated string) can help ensure only supported event types are allowed.Streetcode/Streetcode.XIntegrationTest/ControllerTests/Event/EventControllerTests.cs (5)
13-30
: Potential enhancement for test initialization.
Consider adding a default date to_testEvent
if a date is mandatory or relevant to test coverage. Providing a complete set of event properties can help detect issues earlier.
32-44
: Enhance verification inGetAll_ReturnsSuccess
.
The test checks for a successful response but could include additional assertions. For example, verify thatreturnedValue.TotalAmount
or the contents ofreturnedValue.Events
meet expectations.
46-86
: Expand validation inGetById_ReturnsSuccess
.
Currently, the test ensures a successful status and matches IDs. You could also verify whether other fields (e.g.,Title
,EventType
) match what was created.
96-104
: Consider verifying response details inCreate_ReturnsUnauthorized_WithoutToken
.
The current check ensures the status isUnauthorized
. You might also validate any relevant response body or error message to confirm the response is as expected.
105-135
: Confirm completeness of the delete operation inDelete_ReturnsSuccess_WithAdminToken
.
After deleting, you could optionally attempt to retrieve the event to ensure it's truly gone, increasing confidence in end-to-end correctness.Streetcode/Streetcode.WebApi/Controllers/Event/EventsController.cs (4)
17-22
: Check default parameter handling inGetAll
.
Ifpage
orpageSize
are null, consider whether you want to apply defaults. Handling them gracefully can prevent unexpected query failures or 500 errors.
24-29
: Optionally enhanceGetAllShort
with filters or pagination.
Filtering or basic pagination might be beneficial if the short list can grow large. This would help clients retrieve only relevant subsets.
38-46
: Consider returning 201 for resource creation.
Using HTTP 201 (Created) is a more conventional approach for newly created resources instead of 200 (OK).-[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(int))] +[ProducesResponseType(StatusCodes.Status201Created, Type = typeof(int))]
48-56
: Ensure consistent status codes for updates.
Returning 200 is valid, but if there's an application convention for updated resources (e.g., 200 vs. 204), maintain consistency across all CRUD endpoints.Streetcode/Streetcode.XUnitTest/MediatRTests/Event/GetEventByIdTests.cs (3)
39-64
: Verify Streetcodes collection mappingThe test verifies basic properties like Id and EventType, but doesn't verify that the Streetcodes collection is properly populated. Consider adding assertions for this important part of the handler's functionality.
// Assert Assert.Multiple(() => { Assert.NotNull(result); Assert.True(result.IsSuccess); Assert.Equal(testEventDto.Id, result.Value.Id); Assert.Equal(testEventDto.EventType, result.Value.EventType); + Assert.NotNull(result.Value.Streetcodes); + Assert.Empty(result.Value.Streetcodes); // or Assert.Equal(expectedCount, result.Value.Streetcodes.Count) });
44-45
: Initialize EventStreetcodes propertyThe test creates a HistoricalEvent but doesn't initialize the EventStreetcodes collection. Since the handler accesses this property (as seen in the relevant code snippets), consider initializing it to avoid potential null reference issues in your tests.
-var testEvent = new HistoricalEvent { Id = 1, EventType = "Historical" }; +var testEvent = new HistoricalEvent +{ + Id = 1, + EventType = "Historical", + EventStreetcodes = new List<EventStreetcodes>() +};
66-87
: Add verification for logger callsThe test correctly verifies the error result, but doesn't verify that the logger is called with the error message when the event is not found. Consider adding verification for logger interactions.
// Assert Assert.Multiple(() => { Assert.NotNull(result); Assert.False(result.IsSuccess); Assert.Contains(expectedErrorValue, result.Errors.Single().Message); + _mockLogger.Verify(logger => logger.LogError( + It.IsAny<GetEventByIdQuery>(), + It.Is<string>(s => s.Contains(expectedErrorValue))), + Times.Once); });Streetcode/Streetcode.XUnitTest/MediatRTests/Event/UpdateEventTests.cs (3)
47-64
: Add mapper verification in successful update testThe test verifies successful update but doesn't check that the mapper is called to update the entity properties. Adding this verification would ensure the mapping logic is tested.
// Assert Assert.Multiple(() => { Assert.True(result.IsSuccess); Assert.Equal(1, result.Value); + _mockMapper.Verify(m => m.Map(It.IsAny<UpdateEventDto>(), It.IsAny<EventEntity>()), Times.Once); });
115-139
: Verify transaction rollback on exceptionWhen testing exceptions during streetcode updates, verify that the transaction is properly disposed to ensure changes are rolled back.
// Act var result = await _handler.Handle(request, CancellationToken.None); // Assert Assert.Multiple(() => { Assert.False(result.IsSuccess); Assert.Contains(expectedErrorValue, result.Errors.Single().Message); + _mockRepository.Verify(repo => repo.DisposeTransaction(), Times.Once); });
141-152
: Consider adding transaction disposal in repository mock setupThe setup for transaction handling doesn't include mocking the disposal of the transaction. Consider adding this to ensure complete transaction handling is tested.
private void SetupRepositoryMock(EventEntity? eventEntity, bool saveSuccess) { _mockRepository.Setup(r => r.BeginTransaction()).Returns(new TransactionScope(TransactionScopeAsyncFlowOption.Enabled)); + _mockRepository.Setup(r => r.DisposeTransaction()); _mockRepository.Setup(repo => repo.EventRepository.Update(It.IsAny<EventEntity>())); // Rest of the method...
Streetcode/Streetcode.XUnitTest/MediatRTests/Event/CreateEventTests.cs (3)
45-46
: Remove unused variableThe
historicalEvent
variable is declared but never used. Consider removing it to improve code clarity.// Arrange var request = new CreateEventCommand(new CreateUpdateEventDto { EventType = "Historical", TimelineItemId = 1 }); -var historicalEvent = new HistoricalEvent();
71-71
: Add descriptive comment for the false parameterThe meaning of
false
parameter might not be immediately clear. Consider using a named variable or adding a comment.- SetupRepositoryMock(false); + // Set saveSuccess to false to simulate event creation failure + SetupRepositoryMock(saveSuccess: false);
103-104
: Remove debug Console.WriteLine statementDebug statements should be removed before committing code.
Assert.Multiple(() => { Assert.NotNull(result); - Console.WriteLine(result); Assert.False(result.IsSuccess); Assert.Contains(expectedErrorValue, result.Errors.First().Message); });
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (24)
Streetcode/Streetcode.BLL/DTO/Event/CreateUpdate/CreateUpdateEventDTO.cs
(1 hunks)Streetcode/Streetcode.BLL/DTO/Event/CustomEventDTO.cs
(1 hunks)Streetcode/Streetcode.BLL/DTO/Event/EventDTO.cs
(1 hunks)Streetcode/Streetcode.BLL/DTO/Event/EventShortDTO.cs
(1 hunks)Streetcode/Streetcode.BLL/DTO/Event/GetAllEventsResponseDTO.cs
(1 hunks)Streetcode/Streetcode.BLL/DTO/Event/HistoricalEventDTO.cs
(1 hunks)Streetcode/Streetcode.BLL/DTO/Event/UpdateEventDTO.cs
(1 hunks)Streetcode/Streetcode.BLL/Mapping/Event/EventProfile.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/Create/CreateEventCommand.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/GetAll/GetAllEventsHandler.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/GetAll/GetAllEventsQuery.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/GetAllShort/GetAllEventsShortHandler.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/GetAllShort/GetAllEventsShortQuery.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/GetById/GetEventByIdHandler.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/GetById/GetEventByIdQuery.cs
(1 hunks)Streetcode/Streetcode.BLL/MediatR/Event/Update/UpdateEventCommand.cs
(1 hunks)Streetcode/Streetcode.BLL/Validators/Event/BaseEventValidator.cs
(1 hunks)Streetcode/Streetcode.WebApi/Controllers/Event/EventsController.cs
(1 hunks)Streetcode/Streetcode.XIntegrationTest/ControllerTests/Event/EventControllerTests.cs
(1 hunks)Streetcode/Streetcode.XIntegrationTest/ControllerTests/Utils/Client/Event/EventClient.cs
(1 hunks)Streetcode/Streetcode.XUnitTest/MediatRTests/Event/CreateEventTests.cs
(1 hunks)Streetcode/Streetcode.XUnitTest/MediatRTests/Event/GetAllEventsTests.cs
(1 hunks)Streetcode/Streetcode.XUnitTest/MediatRTests/Event/GetEventByIdTests.cs
(1 hunks)Streetcode/Streetcode.XUnitTest/MediatRTests/Event/UpdateEventTests.cs
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (14)
- Streetcode/Streetcode.BLL/DTO/Event/GetAllEventsResponseDTO.cs
- Streetcode/Streetcode.BLL/DTO/Event/UpdateEventDTO.cs
- Streetcode/Streetcode.BLL/DTO/Event/CustomEventDTO.cs
- Streetcode/Streetcode.BLL/DTO/Event/HistoricalEventDTO.cs
- Streetcode/Streetcode.BLL/DTO/Event/EventDTO.cs
- Streetcode/Streetcode.BLL/MediatR/Event/Create/CreateEventCommand.cs
- Streetcode/Streetcode.BLL/MediatR/Event/GetById/GetEventByIdQuery.cs
- Streetcode/Streetcode.BLL/DTO/Event/CreateUpdate/CreateUpdateEventDTO.cs
- Streetcode/Streetcode.BLL/MediatR/Event/GetAllShort/GetAllEventsShortQuery.cs
- Streetcode/Streetcode.BLL/MediatR/Event/GetAll/GetAllEventsQuery.cs
- Streetcode/Streetcode.BLL/MediatR/Event/Update/UpdateEventCommand.cs
- Streetcode/Streetcode.BLL/Mapping/Event/EventProfile.cs
- Streetcode/Streetcode.BLL/MediatR/Event/GetAll/GetAllEventsHandler.cs
- Streetcode/Streetcode.XUnitTest/MediatRTests/Event/GetAllEventsTests.cs
🧰 Additional context used
🧬 Code Definitions (6)
Streetcode/Streetcode.BLL/MediatR/Event/GetById/GetEventByIdHandler.cs (7)
Streetcode/Streetcode.BLL/DTO/Event/EventDTO.cs (1)
EventDto
(6-14)Streetcode/Streetcode.DAL/Repositories/Interfaces/Base/IRepositoryWrapper.cs (1)
Task
(68-68)Streetcode/Streetcode.DAL/Repositories/Realizations/Base/RepositoryWrapper.cs (1)
Task
(675-678)Streetcode/Streetcode.DAL/Repositories/Realizations/Event/EventRepository.cs (2)
EventRepository
(12-18)EventRepository
(14-17)Streetcode/Streetcode.BLL/DTO/Event/HistoricalEventDTO.cs (1)
HistoricalEventDto
(9-12)Streetcode/Streetcode.BLL/DTO/Event/CustomEventDTO.cs (1)
CustomEventDto
(9-14)Streetcode/Streetcode.XUnitTest/MediatRTests/Event/GetAllEventsTests.cs (2)
List
(142-151)List
(153-190)
Streetcode/Streetcode.BLL/Validators/Event/BaseEventValidator.cs (1)
Streetcode/Streetcode.BLL/DTO/Event/CreateUpdate/CreateUpdateEventDTO.cs (1)
CreateUpdateEventDto
(5-16)
Streetcode/Streetcode.XIntegrationTest/ControllerTests/Event/EventControllerTests.cs (4)
Streetcode/Streetcode.XIntegrationTest/ControllerTests/Utils/Client/Event/EventClient.cs (6)
EventClient
(7-26)EventClient
(9-12)Task
(14-14)Task
(16-16)Task
(18-19)Task
(21-25)Streetcode/Streetcode.BLL/DTO/Event/EventDTO.cs (1)
EventDto
(6-14)Streetcode/Streetcode.BLL/DTO/Event/GetAllEventsResponseDTO.cs (1)
GetAllEventsResponseDto
(3-7)Streetcode/Streetcode.BLL/DTO/Event/CreateUpdate/CreateUpdateEventDTO.cs (1)
CreateUpdateEventDto
(5-16)
Streetcode/Streetcode.XUnitTest/MediatRTests/Event/GetEventByIdTests.cs (2)
Streetcode/Streetcode.BLL/MediatR/Event/GetById/GetEventByIdHandler.cs (3)
GetEventByIdHandler
(14-81)GetEventByIdHandler
(21-31)Task
(33-80)Streetcode/Streetcode.BLL/DTO/Event/HistoricalEventDTO.cs (1)
HistoricalEventDto
(9-12)
Streetcode/Streetcode.XIntegrationTest/ControllerTests/Utils/Client/Event/EventClient.cs (4)
Streetcode/Streetcode.BLL/MediatR/Event/GetAllShort/GetAllEventsShortHandler.cs (1)
Task
(31-43)Streetcode/Streetcode.BLL/MediatR/Event/GetAll/GetAllEventsHandler.cs (1)
Task
(35-94)Streetcode/Streetcode.BLL/MediatR/Event/GetById/GetEventByIdHandler.cs (1)
Task
(33-80)Streetcode/Streetcode.BLL/DTO/Event/CreateUpdate/CreateUpdateEventDTO.cs (1)
CreateUpdateEventDto
(5-16)
Streetcode/Streetcode.WebApi/Controllers/Event/EventsController.cs (8)
Streetcode/Streetcode.BLL/DTO/Event/GetAllEventsResponseDTO.cs (1)
GetAllEventsResponseDto
(3-7)Streetcode/Streetcode.BLL/MediatR/Event/GetAll/GetAllEventsHandler.cs (1)
Task
(35-94)Streetcode/Streetcode.BLL/MediatR/Event/Create/CreateEventHandler.cs (2)
Task
(36-71)Task
(89-102)Streetcode/Streetcode.BLL/MediatR/Event/Update/UpdateEventHandler.cs (2)
Task
(41-93)Task
(134-164)Streetcode/Streetcode.BLL/MediatR/Event/Delete/DeleteEventHandler.cs (1)
Task
(28-52)Streetcode/Streetcode.BLL/DTO/Event/EventDTO.cs (1)
EventDto
(6-14)Streetcode/Streetcode.BLL/DTO/Event/CreateUpdate/CreateUpdateEventDTO.cs (1)
CreateUpdateEventDto
(5-16)Streetcode/Streetcode.BLL/DTO/Event/UpdateEventDTO.cs (1)
UpdateEventDto
(5-8)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: Jenkins
🔇 Additional comments (27)
Streetcode/Streetcode.BLL/MediatR/Event/GetAllShort/GetAllEventsShortHandler.cs (2)
35-40
: Clarify the null check on repository results
It's unusual for a repository'sGetAllAsync()
method to returnnull
instead of an empty collection. Confirm if it can actually returnnull
, or consider adjusting the repository so it never returnsnull
. This ensures consistent error handling and reduces confusion.
42-42
: Mapping to DTO looks correct
Returning a mapped result is a clean approach that maintains separation of concerns and ensures well-structured data transfer.Streetcode/Streetcode.BLL/Validators/Event/BaseEventValidator.cs (2)
8-15
: Well-structured constants for validation constraints.The class defines clear, reasonable length constraints for various fields. This approach promotes maintainability by centralizing these values as constants rather than embedding them directly in validation rules.
18-20
: Missing regex pattern for title validation.The title validation should include a regex pattern to validate the format of the input. This was previously mentioned in a review comment and has not been implemented.
RuleFor(e => e.Title) .NotEmpty().WithMessage(localizer["CannotBeEmpty", fieldLocalizer["Title"]]) .Length(TitleMinLength, TitleMaxLength).WithMessage(localizer["LengthBetween", TitleMinLength, TitleMaxLength]) + .Matches(@"^[A-Za-zА-Яа-яІіЇїЄєҐґ0-9\p{L}\d\s\-'-]+$").WithMessage(localizer["TitleFormat"]);
Streetcode/Streetcode.XIntegrationTest/ControllerTests/Utils/Client/Event/EventClient.cs (7)
1-4
: Imports look good.No issues found with the namespaces or references here.
5-8
: Namespace and class declaration are consistent.The structure aligns well with the folder hierarchy and naming conventions.
9-12
: Constructor is clear and straightforward.Passing
secondPartUrl
to the base class is a clean approach; no concerns found.
14-15
: GetAllAsync method is suitably aligned with the intended endpoint.No issues with the route or usage of
SendQuery
.
16-17
: GetByIdAsync method is correctly referencing the query path.Matches the API route conventions for fetching by ID.
18-19
: CreateAsync method aligns with the route and uses the correct HTTP verb.The DTO usage is consistent with the existing create operation pattern.
21-25
: Eliminate redundant ID passing in DeleteAsync.This was flagged before, so marking it as a repeated comment. Currently, the method includes the ID in both the path (
/Delete/{id}
) and the request body. Remove the redundant body parameter to avoid confusion and ensure consistency with typical REST conventions.- var dto = new { Id = id }; - return await this.SendCommand($"/Delete/{id}", Method.Delete, dto, authToken); + return await this.SendCommand($"/Delete/{id}", Method.Delete, null, authToken);Streetcode/Streetcode.BLL/DTO/Event/EventShortDTO.cs (1)
1-6
: All imports look appropriate.
No issues spotted; the namespaces and using directives are minimal and relevant.Streetcode/Streetcode.XIntegrationTest/ControllerTests/Event/EventControllerTests.cs (1)
88-95
: TheCreate_ReturnsSuccess_WithAdminToken
test is effective.
This straightforward test covers the primary scenario. The coverage looks good; no further issues identified.Streetcode/Streetcode.WebApi/Controllers/Event/EventsController.cs (3)
1-12
: No immediate issues in the controller imports.
All namespaces appear consistent and relevant to the controller logic.
58-66
:❓ Verification inconclusive
Confirm behavior when deleting non-existent resources.
Currently, a missing event likely triggers a failure in the Mediator handler, but consider verifying that the controller translates it to a 404 status.
🏁 Script executed:
#!/bin/bash # Check if a non-existent ID returns 404 in the DeleteEventCommand handler or is handled differently rg -A 5 'DeleteEventCommand'Length of output: 4200
Action Required: Verify HTTP 404 Response for Non-existent Events
The DeleteEventCommand tests correctly capture the error scenario—returning an error (with the key
"CannotFindEventWithCorrespondingId"
) when an event isn’t found. However, it’s not clear from the controller code if theHandleResult
method translates this error into a proper 404 HTTP response for the client. Please verify (or add an integration test) that when a DELETE request is made for a non-existent event, the controller responds with a 404 status instead of, for example, a 200 or 500 status.
- Confirm that
HandleResult
maps the mediator’s error result to a 404 Not Found.- If this mapping is not already implemented, consider updating the logic and adding tests to enforce the correct HTTP response for missing resources.
31-36
:❓ Verification inconclusive
Verify the not-found case in
GetById
.
Ensure the mediator returns an appropriate error status (like 404) if the event is nonexistent.
🏁 Script executed:
#!/bin/bash # Check where not-found logic is handled in the GetEventByIdQuery handler or controller pipeline rg -A 5 'return.*Result\.Fail'Length of output: 106680
Clarify Not-Found Handling in GetById Endpoint
Please verify that the mediator’s GetEventByIdQuery handler properly checks for a missing event and returns a failure (for example, via Result.Fail) that the controller’s HandleResult method then maps to a 404 response. While the codebase consistently uses Result.Fail in various handlers, the shell output did not reveal evidence for this specific event scenario. It would be helpful to ensure that:
- The GetEventByIdQuery handler performs a null check and returns a failure result when the event does not exist.
- The controller’s HandleResult method correctly interprets such a failure as a 404 Not Found response.
- Appropriate test cases are in place to validate this behavior.
Streetcode/Streetcode.BLL/MediatR/Event/GetById/GetEventByIdHandler.cs (6)
1-5
: Imports appear correct and comprehensive.The imported namespaces correctly reflect the dependencies needed for MediatR, AutoMapper, localization, logging, and repository wrapping. No issues spotted here.
12-31
: Constructor injection is clear and follows best practices.The constructor neatly injects required services (
IMapper
,IRepositoryWrapper
,ILoggerService
,IStringLocalizer
), promoting testability and maintainability.
33-39
: Good repository usage withInclude
chaining for related data.Fetching
EventStreetcodes
andStreetcodeContent
viaInclude
is efficient and ensures related data is readily available.
41-46
: Effective error handling for missing entities.Returning a failure result with both localized error messaging and logger integration offers clarity for debugging. This adheres to good exception-handling practices.
63-77
: Streetcodes mapping logic is straightforward and efficient.Your filter and projection of
StreetcodeContent
toStreetcodeShortDTO
is appropriate. The fallback to an empty list prevents null references. Nicely handled.
79-80
: Returning a success result is appropriate.The successful result containing the mapped DTO concludes the handler properly. No issues found.
Streetcode/Streetcode.XUnitTest/MediatRTests/Event/GetEventByIdTests.cs (4)
1-13
: Good organization of importsThe imports are well-structured and properly organized, making it clear what dependencies this test class requires.
16-22
: Test class setup looks goodThe class declaration and field setup follows best practices for unit testing. Fields are clearly named and properly scoped as private.
24-37
: Constructor initialization is well-structuredGood job initializing all the required dependencies in the constructor. The handler is properly created with all the necessary mock objects.
89-95
: SetupRepositoryMock method is well-implementedThe helper method effectively configures the mock repository for both test methods, reducing code duplication.
Streetcode/Streetcode.XUnitTest/MediatRTests/Event/CreateEventTests.cs (1)
109-125
: Well-structured repository mock setupThe helper method effectively handles different test scenarios, including exception cases, with a clean conditional structure.
public BaseEventValidator(IStringLocalizer<FailedToValidateSharedResource> localizer, IStringLocalizer<FieldNamesSharedResource> fieldLocalizer) | ||
{ | ||
RuleFor(e => e.Title) | ||
.NotEmpty().WithMessage(localizer["CannotBeEmpty", fieldLocalizer["Title"]]) | ||
.Length(TitleMinLength, TitleMaxLength).WithMessage(localizer["LengthBetween", TitleMinLength, TitleMaxLength]); | ||
|
||
RuleFor(e => e.Date) | ||
.NotEmpty().WithMessage(localizer["CannotBeEmpty", fieldLocalizer["Date"]]); | ||
|
||
RuleFor(e => e.Description) | ||
.MaximumLength(DescriptionMaxLength).WithMessage(localizer["MaxLength", fieldLocalizer["Description"], DescriptionMaxLength]); | ||
|
||
RuleFor(e => e.Location) | ||
.MaximumLength(LocationMaxLength).WithMessage(localizer["MaxLength", fieldLocalizer["Location"], LocationMaxLength]); | ||
|
||
RuleFor(e => e.Organizer) | ||
.MaximumLength(OrganizerMaxLength).WithMessage(localizer["MaxLength", fieldLocalizer["Organizer"], OrganizerMaxLength]); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Missing validation for EventType field.
According to the DTO, the EventType
is a required field but is not validated in this class. Consider adding validation for this field to ensure it contains valid values.
RuleFor(e => e.Organizer)
.MaximumLength(OrganizerMaxLength).WithMessage(localizer["MaxLength", fieldLocalizer["Organizer"], OrganizerMaxLength]);
+RuleFor(e => e.EventType)
+ .NotEmpty().WithMessage(localizer["CannotBeEmpty", fieldLocalizer["EventType"]])
+ .Must(type => new[] { "Historical", "Custom" }.Contains(type))
+ .WithMessage(localizer["InvalidEventType"]);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
public BaseEventValidator(IStringLocalizer<FailedToValidateSharedResource> localizer, IStringLocalizer<FieldNamesSharedResource> fieldLocalizer) | |
{ | |
RuleFor(e => e.Title) | |
.NotEmpty().WithMessage(localizer["CannotBeEmpty", fieldLocalizer["Title"]]) | |
.Length(TitleMinLength, TitleMaxLength).WithMessage(localizer["LengthBetween", TitleMinLength, TitleMaxLength]); | |
RuleFor(e => e.Date) | |
.NotEmpty().WithMessage(localizer["CannotBeEmpty", fieldLocalizer["Date"]]); | |
RuleFor(e => e.Description) | |
.MaximumLength(DescriptionMaxLength).WithMessage(localizer["MaxLength", fieldLocalizer["Description"], DescriptionMaxLength]); | |
RuleFor(e => e.Location) | |
.MaximumLength(LocationMaxLength).WithMessage(localizer["MaxLength", fieldLocalizer["Location"], LocationMaxLength]); | |
RuleFor(e => e.Organizer) | |
.MaximumLength(OrganizerMaxLength).WithMessage(localizer["MaxLength", fieldLocalizer["Organizer"], OrganizerMaxLength]); | |
} | |
public BaseEventValidator(IStringLocalizer<FailedToValidateSharedResource> localizer, IStringLocalizer<FieldNamesSharedResource> fieldLocalizer) | |
{ | |
RuleFor(e => e.Title) | |
.NotEmpty().WithMessage(localizer["CannotBeEmpty", fieldLocalizer["Title"]]) | |
.Length(TitleMinLength, TitleMaxLength).WithMessage(localizer["LengthBetween", TitleMinLength, TitleMaxLength]); | |
RuleFor(e => e.Date) | |
.NotEmpty().WithMessage(localizer["CannotBeEmpty", fieldLocalizer["Date"]]); | |
RuleFor(e => e.Description) | |
.MaximumLength(DescriptionMaxLength).WithMessage(localizer["MaxLength", fieldLocalizer["Description"], DescriptionMaxLength]); | |
RuleFor(e => e.Location) | |
.MaximumLength(LocationMaxLength).WithMessage(localizer["MaxLength", fieldLocalizer["Location"], LocationMaxLength]); | |
RuleFor(e => e.Organizer) | |
.MaximumLength(OrganizerMaxLength).WithMessage(localizer["MaxLength", fieldLocalizer["Organizer"], OrganizerMaxLength]); | |
RuleFor(e => e.EventType) | |
.NotEmpty().WithMessage(localizer["CannotBeEmpty", fieldLocalizer["EventType"]]) | |
.Must(type => new[] { "Historical", "Custom" }.Contains(type)) | |
.WithMessage(localizer["InvalidEventType"]); | |
} |
switch (eventEntity.EventType) | ||
{ | ||
case "Historical": | ||
mappedEvent = _mapper.Map<HistoricalEventDto>(eventEntity); | ||
break; | ||
case "Custom": | ||
mappedEvent = _mapper.Map<CustomEventDto>(eventEntity); | ||
break; | ||
default: | ||
mappedEvent = _mapper.Map<EventDto>(eventEntity); | ||
break; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential event-type mismatch.
The code checks for "Historical"
and "Custom"
, but the test data and other references may use "HistoricalEvent"
and "CustomEvent"
. This mismatch could prevent correct DTO mapping.
Here is a suggested fix to align the switch cases with the event types:
-case "Historical":
+case "HistoricalEvent":
mappedEvent = _mapper.Map<HistoricalEventDto>(eventEntity);
break;
-case "Custom":
+case "CustomEvent":
mappedEvent = _mapper.Map<CustomEventDto>(eventEntity);
break;
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
switch (eventEntity.EventType) | |
{ | |
case "Historical": | |
mappedEvent = _mapper.Map<HistoricalEventDto>(eventEntity); | |
break; | |
case "Custom": | |
mappedEvent = _mapper.Map<CustomEventDto>(eventEntity); | |
break; | |
default: | |
mappedEvent = _mapper.Map<EventDto>(eventEntity); | |
break; | |
} | |
switch (eventEntity.EventType) | |
{ | |
case "HistoricalEvent": | |
mappedEvent = _mapper.Map<HistoricalEventDto>(eventEntity); | |
break; | |
case "CustomEvent": | |
mappedEvent = _mapper.Map<CustomEventDto>(eventEntity); | |
break; | |
default: | |
mappedEvent = _mapper.Map<EventDto>(eventEntity); | |
break; | |
} |
_mockFailedToUpdateLocalizer, | ||
_mockAnErrorOccurredLocalizer, | ||
_mockCanFindLocalizer); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handler initialization needs to be updated
Update the handler initialization to use the corrected field name.
_handler = new UpdateEventHandler(
_mockMapper.Object,
_mockRepository.Object,
_mockLogger.Object,
_mockFailedToUpdateLocalizer,
_mockAnErrorOccurredLocalizer,
- _mockCanFindLocalizer);
+ _mockCannotFindLocalizer);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
_mockFailedToUpdateLocalizer, | |
_mockAnErrorOccurredLocalizer, | |
_mockCanFindLocalizer); | |
_mockFailedToUpdateLocalizer, | |
_mockAnErrorOccurredLocalizer, | |
_mockCannotFindLocalizer); |
_mockCanFindLocalizer = new MockCannotFindLocalizer(); | ||
_mockFailedToUpdateLocalizer = new MockFailedToUpdateLocalizer(); | ||
_mockAnErrorOccurredLocalizer = new MockAnErrorOccurredLocalizer(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix inconsistent variable naming in constructor
The constructor initializations don't match the field declarations.
- _mockCanFindLocalizer = new MockCannotFindLocalizer();
+ _mockCannotFindLocalizer = new MockCannotFindLocalizer();
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
_mockCanFindLocalizer = new MockCannotFindLocalizer(); | |
_mockFailedToUpdateLocalizer = new MockFailedToUpdateLocalizer(); | |
_mockAnErrorOccurredLocalizer = new MockAnErrorOccurredLocalizer(); | |
_mockCannotFindLocalizer = new MockCannotFindLocalizer(); | |
_mockFailedToUpdateLocalizer = new MockFailedToUpdateLocalizer(); | |
_mockAnErrorOccurredLocalizer = new MockAnErrorOccurredLocalizer(); |
string expectedErrorValue = _mockCanFindLocalizer[expectedErrorKey, eventId]; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Variable name mismatch with field name
The variable references the incorrectly named field.
- string expectedErrorValue = _mockCanFindLocalizer[expectedErrorKey, eventId];
+ string expectedErrorValue = _mockCannotFindLocalizer[expectedErrorKey, eventId];
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
string expectedErrorValue = _mockCanFindLocalizer[expectedErrorKey, eventId]; | |
string expectedErrorValue = _mockCannotFindLocalizer[expectedErrorKey, eventId]; |
public class UpdateEventTests | ||
{ | ||
private readonly Mock<IMapper> _mockMapper; | ||
private readonly Mock<IRepositoryWrapper> _mockRepository; | ||
private readonly Mock<ILoggerService> _mockLogger; | ||
private readonly MockCannotFindLocalizer _mockCanFindLocalizer; | ||
private readonly MockFailedToUpdateLocalizer _mockFailedToUpdateLocalizer; | ||
private readonly MockAnErrorOccurredLocalizer _mockAnErrorOccurredLocalizer; | ||
private readonly UpdateEventHandler _handler; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix naming inconsistency in mock localizer field
There's a naming inconsistency between the field declaration and its usage in the code.
- private readonly MockCannotFindLocalizer _mockCanFindLocalizer;
+ private readonly MockCannotFindLocalizer _mockCannotFindLocalizer;
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
public class UpdateEventTests | |
{ | |
private readonly Mock<IMapper> _mockMapper; | |
private readonly Mock<IRepositoryWrapper> _mockRepository; | |
private readonly Mock<ILoggerService> _mockLogger; | |
private readonly MockCannotFindLocalizer _mockCanFindLocalizer; | |
private readonly MockFailedToUpdateLocalizer _mockFailedToUpdateLocalizer; | |
private readonly MockAnErrorOccurredLocalizer _mockAnErrorOccurredLocalizer; | |
private readonly UpdateEventHandler _handler; | |
public class UpdateEventTests | |
{ | |
private readonly Mock<IMapper> _mockMapper; | |
private readonly Mock<IRepositoryWrapper> _mockRepository; | |
private readonly Mock<ILoggerService> _mockLogger; | |
private readonly MockCannotFindLocalizer _mockCannotFindLocalizer; | |
private readonly MockFailedToUpdateLocalizer _mockFailedToUpdateLocalizer; | |
private readonly MockAnErrorOccurredLocalizer _mockAnErrorOccurredLocalizer; | |
private readonly UpdateEventHandler _handler; |
SetupRepositoryMock(saveSuccess: true); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add mapper configuration for entity creation
The test doesn't configure the mock mapper to map the DTO to an entity. This is important to test that the handler correctly maps the input data.
SetupRepositoryMock(saveSuccess: true);
+_mockMapper.Setup(m => m.Map<HistoricalEvent>(It.IsAny<CreateUpdateEventDto>()))
+ .Returns(new HistoricalEvent { Id = 1, EventType = "Historical", TimelineItemId = 1 });
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
SetupRepositoryMock(saveSuccess: true); | |
SetupRepositoryMock(saveSuccess: true); | |
_mockMapper.Setup(m => m.Map<HistoricalEvent>(It.IsAny<CreateUpdateEventDto>())) | |
.Returns(new HistoricalEvent { Id = 1, EventType = "Historical", TimelineItemId = 1 }); |
public Task<Result<GetAllEventsResponseDto>> Handle(GetAllEventsQuery request, CancellationToken cancellationToken) | ||
{ | ||
PaginationResponse<DAL.Entities.Event.Event> paginationResponse = _repositoryWrapper | ||
.EventRepository | ||
.GetAllPaginated( | ||
request.page, | ||
request.pageSize, | ||
predicate: !string.IsNullOrEmpty(request.EventType) | ||
? e => e.EventType == request.EventType | ||
: null, | ||
include: query => query | ||
.Include(e => e.EventStreetcodes !) | ||
.ThenInclude(es => es.StreetcodeContent !)); | ||
|
||
if (paginationResponse is null) | ||
{ | ||
string errorMsg = _stringLocalizeCannotFind["CannotFindAnyEvents"].Value; | ||
_logger.LogError(request, errorMsg); | ||
return Task.FromResult(Result.Fail<GetAllEventsResponseDto>(new Error(errorMsg))); | ||
} | ||
|
||
IEnumerable<DAL.Entities.Event.Event> filteredEvents = paginationResponse.Entities; | ||
|
||
IEnumerable<object> mappedEvents = filteredEvents | ||
.Select(e => | ||
{ | ||
var eventDto = e switch | ||
{ | ||
HistoricalEvent historicalEvent => _mapper.Map<HistoricalEventDto>(historicalEvent), | ||
CustomEvent customEvent => _mapper.Map<CustomEventDto>(customEvent), | ||
_ => _mapper.Map<EventDto>(e) | ||
}; | ||
|
||
if(e.EventStreetcodes != null) | ||
{ | ||
eventDto.Streetcodes = e.EventStreetcodes | ||
.Where(es => es.StreetcodeContent != null) | ||
.Select(es => new StreetcodeShortDTO | ||
{ | ||
Id = es.StreetcodeContent.Id, | ||
Title = es.StreetcodeContent.Title | ||
}) | ||
.ToList(); | ||
} | ||
else | ||
{ | ||
eventDto.Streetcodes = new List<StreetcodeShortDTO>(); | ||
} | ||
|
||
return eventDto; | ||
}); | ||
|
||
GetAllEventsResponseDto getAllEventsResponseDTO = new GetAllEventsResponseDto() | ||
{ | ||
TotalAmount = paginationResponse.TotalItems, | ||
Events = mappedEvents, | ||
}; | ||
|
||
return Task.FromResult(Result.Ok(getAllEventsResponseDTO)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be better to divide this Handle method into smaller ones, because now it violates SRP
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here, SRP
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove all unused namespaces
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the same remark for the code across whole file
Summary of issue
Need to create an "Events" entity for the new "Calendar" module
Summary of change
Summary by CodeRabbit
This update delivers an improved, seamless interaction with event data, ensuring smoother and more reliable event management for users.