diff --git a/server/nt.microservice/infrastructure/nt.orchestrator.AppHost/Program.cs b/server/nt.microservice/infrastructure/nt.orchestrator.AppHost/Program.cs index 77fdea4f..a52f8329 100644 --- a/server/nt.microservice/infrastructure/nt.orchestrator.AppHost/Program.cs +++ b/server/nt.microservice/infrastructure/nt.orchestrator.AppHost/Program.cs @@ -70,6 +70,12 @@ .WithEnvironment("MSSQL_SA_PASSWORD", infrastructureSettings.SqlServer.Password) .WithHttpEndpoint(port: infrastructureSettings.SqlServer.HostPort, targetPort: infrastructureSettings.SqlServer.TargetPort, isProxied: true); +var couchbase = builder.AddContainer("nt-reviewservice-db", "couchbase:community") + .WithEnvironment("CB_USERNAME", "Administrator") + .WithEnvironment("CB_PASSWORD", "password") + .WithEndpoint(port: 8091, targetPort:8091, scheme:"http") + .WithEndpoint(port: 8093, targetPort:8093); + var authServiceInstances = new List>(); foreach(var port in serviceSettings.AuthService.InstancePorts) @@ -171,7 +177,8 @@ var reviewService = builder.AddProject("nt-reviewservice-service") .WithEnvironment(Constants.Global.EnvironmentVariables.RunningWithVariable, Constants.Global.EnvironmentVariables.RunningWithValue) - .WithUrls(c => c.Urls.ForEach(u => u.DisplayText = $"Open API ({u.Endpoint?.EndpointName})")); + .WithUrls(c => c.Urls.ForEach(u => u.DisplayText = $"Open API ({u.Endpoint?.EndpointName})")) + .WaitFor(couchbase); var gateway = builder.AddProject(Constants.Gateway.ServiceName, launchProfileName: Constants.Gateway.LaunchProfile) diff --git a/server/nt.microservice/infrastructure/nt.orchestrator.AppHost/nt.orchestrator.AppHost.csproj b/server/nt.microservice/infrastructure/nt.orchestrator.AppHost/nt.orchestrator.AppHost.csproj index 1b43f6a8..5e65dca2 100644 --- a/server/nt.microservice/infrastructure/nt.orchestrator.AppHost/nt.orchestrator.AppHost.csproj +++ b/server/nt.microservice/infrastructure/nt.orchestrator.AppHost/nt.orchestrator.AppHost.csproj @@ -13,6 +13,7 @@ + diff --git a/server/nt.microservice/services/ReviewService/ReviewService.Application.DTO/Reviews/Review.cs b/server/nt.microservice/services/ReviewService/ReviewService.Application.DTO/Reviews/Review.cs deleted file mode 100644 index 0aff9e2d..00000000 --- a/server/nt.microservice/services/ReviewService/ReviewService.Application.DTO/Reviews/Review.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace ReviewService.Application.DTO.Reviews; - -public class Review -{ - public Guid ReviewId { get; set; } - public string MovieTitle { get; set; } = null!; -} diff --git a/server/nt.microservice/services/ReviewService/ReviewService.Application.DTO/Reviews/ReviewDto.cs b/server/nt.microservice/services/ReviewService/ReviewService.Application.DTO/Reviews/ReviewDto.cs new file mode 100644 index 00000000..3a3b36bd --- /dev/null +++ b/server/nt.microservice/services/ReviewService/ReviewService.Application.DTO/Reviews/ReviewDto.cs @@ -0,0 +1,12 @@ +namespace ReviewService.Application.DTO.Reviews; + +public class ReviewDto +{ + public Guid ReviewId { get; set; } + public Guid MovieId { get; set; } + + public string Content { get; set; } = string.Empty; + public int Rating { get; set; } + public string UserName { get; set; } = string.Empty; + +} diff --git a/server/nt.microservice/services/ReviewService/ReviewService.Application.Interfaces/Operations/IReviewService.cs b/server/nt.microservice/services/ReviewService/ReviewService.Application.Interfaces/Operations/IReviewService.cs index 01e6b174..7ff857d6 100644 --- a/server/nt.microservice/services/ReviewService/ReviewService.Application.Interfaces/Operations/IReviewService.cs +++ b/server/nt.microservice/services/ReviewService/ReviewService.Application.Interfaces/Operations/IReviewService.cs @@ -4,5 +4,6 @@ namespace ReviewService.Application.Interfaces.Operations; public interface IReviewService { - public Task> GetReviewsByMovieIdAsync(Guid movieId); + Task> GetReviewsByMovieIdAsync(Guid movieId); + Task CreateReviewAsync(ReviewDto reviewDto); } diff --git a/server/nt.microservice/services/ReviewService/ReviewService.Application.Interfaces/Repository/GenericRepository.cs b/server/nt.microservice/services/ReviewService/ReviewService.Application.Interfaces/Repository/GenericRepository.cs deleted file mode 100644 index ae479858..00000000 --- a/server/nt.microservice/services/ReviewService/ReviewService.Application.Interfaces/Repository/GenericRepository.cs +++ /dev/null @@ -1,20 +0,0 @@ -using ReviewService.Domain.Entities; - -namespace ReviewService.Application.Interfaces.Repository; - -public interface IGenericRepository where TEntity : class, IEntity, new() -{ - Task> GetAll(); - Task GetByIdAsync(long id); - Task AddAsync(TEntity entity); - Task UpdateAsync(TEntity entity); - Task DeleteAsync(TEntity entity); -} - -public interface ReviewRepository : IGenericRepository -{ - Task> GetReviewsByMovieIdAsync(Guid movieId); - Task> GetReviewsByUserIdAsync(Guid userId); - Task> GetReviewsByRatingAsync(int rating); - Task> GetReviewsByDateRangeAsync(DateTime startDate, DateTime endDate); -} \ No newline at end of file diff --git a/server/nt.microservice/services/ReviewService/ReviewService.Application.Orchestration/Commands/CreateReviewCommand.cs b/server/nt.microservice/services/ReviewService/ReviewService.Application.Orchestration/Commands/CreateReviewCommand.cs new file mode 100644 index 00000000..77b10be3 --- /dev/null +++ b/server/nt.microservice/services/ReviewService/ReviewService.Application.Orchestration/Commands/CreateReviewCommand.cs @@ -0,0 +1,9 @@ +using MediatR; +using ReviewService.Application.DTO.Reviews; + +namespace ReviewService.Application.Orchestration.Commands; + +public class CreateReviewCommand : IRequest +{ + public required ReviewDto Review { get; init; } +} diff --git a/server/nt.microservice/services/ReviewService/ReviewService.Application.Orchestration/Commands/CreateReviewCommandHandler.cs b/server/nt.microservice/services/ReviewService/ReviewService.Application.Orchestration/Commands/CreateReviewCommandHandler.cs new file mode 100644 index 00000000..c2f00757 --- /dev/null +++ b/server/nt.microservice/services/ReviewService/ReviewService.Application.Orchestration/Commands/CreateReviewCommandHandler.cs @@ -0,0 +1,18 @@ +using MediatR; +using ReviewService.Application.Interfaces.Operations; + +namespace ReviewService.Application.Orchestration.Commands; + +public class CreateReviewCommandHandler : IRequestHandler +{ + private readonly IReviewService _reviewService; + public CreateReviewCommandHandler(IReviewService reviewService) + { + _reviewService = reviewService ?? throw new ArgumentNullException(nameof(reviewService)); + } + + public async Task Handle(CreateReviewCommand request, CancellationToken cancellationToken) + { + return await _reviewService.CreateReviewAsync(request.Review).ConfigureAwait(false); + } +} diff --git a/server/nt.microservice/services/ReviewService/ReviewService.Application.Orchestration/Queries/GetReviewsByMovieIdQuery.cs b/server/nt.microservice/services/ReviewService/ReviewService.Application.Orchestration/Queries/GetReviewsByMovieIdQuery.cs index 9f078e72..a21e7b33 100644 --- a/server/nt.microservice/services/ReviewService/ReviewService.Application.Orchestration/Queries/GetReviewsByMovieIdQuery.cs +++ b/server/nt.microservice/services/ReviewService/ReviewService.Application.Orchestration/Queries/GetReviewsByMovieIdQuery.cs @@ -3,7 +3,7 @@ namespace ReviewService.Application.Orchestration.Queries; -public class GetReviewsByMovieIdQuery : IRequest> +public class GetReviewsByMovieIdQuery : IRequest> { public Guid MovieId { get; set; } public GetReviewsByMovieIdQuery(Guid movieId) diff --git a/server/nt.microservice/services/ReviewService/ReviewService.Application.Orchestration/Queries/GetReviewsByMovieIdQueryHandler.cs b/server/nt.microservice/services/ReviewService/ReviewService.Application.Orchestration/Queries/GetReviewsByMovieIdQueryHandler.cs index 1dab701a..8f55eecd 100644 --- a/server/nt.microservice/services/ReviewService/ReviewService.Application.Orchestration/Queries/GetReviewsByMovieIdQueryHandler.cs +++ b/server/nt.microservice/services/ReviewService/ReviewService.Application.Orchestration/Queries/GetReviewsByMovieIdQueryHandler.cs @@ -4,7 +4,7 @@ namespace ReviewService.Application.Orchestration.Queries; -public class GetReviewsByMovieIdQueryHandler : IRequestHandler> +public class GetReviewsByMovieIdQueryHandler : IRequestHandler> { private readonly IReviewService _reviewService; public GetReviewsByMovieIdQueryHandler(IReviewService reviewService) @@ -12,7 +12,7 @@ public GetReviewsByMovieIdQueryHandler(IReviewService reviewService) _reviewService = reviewService; } - public Task> Handle(GetReviewsByMovieIdQuery request, CancellationToken cancellationToken) + public Task> Handle(GetReviewsByMovieIdQuery request, CancellationToken cancellationToken) { return _reviewService.GetReviewsByMovieIdAsync(request.MovieId); } diff --git a/server/nt.microservice/services/ReviewService/ReviewService.Application.Orchestration/ReviewService.Application.Orchestration.csproj b/server/nt.microservice/services/ReviewService/ReviewService.Application.Orchestration/ReviewService.Application.Orchestration.csproj index be99fe48..d0d1e240 100644 --- a/server/nt.microservice/services/ReviewService/ReviewService.Application.Orchestration/ReviewService.Application.Orchestration.csproj +++ b/server/nt.microservice/services/ReviewService/ReviewService.Application.Orchestration/ReviewService.Application.Orchestration.csproj @@ -6,10 +6,6 @@ enable - - - - diff --git a/server/nt.microservice/services/ReviewService/ReviewService.Application.Services/Interfaces/IReviewService.cs b/server/nt.microservice/services/ReviewService/ReviewService.Application.Services/Interfaces/IReviewService.cs deleted file mode 100644 index 7824d97a..00000000 --- a/server/nt.microservice/services/ReviewService/ReviewService.Application.Services/Interfaces/IReviewService.cs +++ /dev/null @@ -1,8 +0,0 @@ -using ReviewService.Application.DTO.Reviews; - -namespace ReviewService.Application.Services.Interfaces; - -public interface IReviewService -{ - Task> GetReviewsByMovieIdAsync(Guid movieId); -} diff --git a/server/nt.microservice/services/ReviewService/ReviewService.Application.Services/Operations/ReviewService.cs b/server/nt.microservice/services/ReviewService/ReviewService.Application.Services/Operations/ReviewService.cs index 665d7793..49c51e9d 100644 --- a/server/nt.microservice/services/ReviewService/ReviewService.Application.Services/Operations/ReviewService.cs +++ b/server/nt.microservice/services/ReviewService/ReviewService.Application.Services/Operations/ReviewService.cs @@ -1,12 +1,39 @@ -using ReviewService.Application.DTO.Reviews; -using ReviewService.Application.Services.Interfaces; +using AutoMapper; +using Microsoft.Extensions.Logging; +using ReviewService.Application.DTO.Reviews; +using ReviewService.Application.Interfaces.Operations; +using ReviewService.Domain.Entities; +using ReviewService.Domain.Repositories; namespace ReviewService.Application.Services.Operations; public class ReviewService : IReviewService { - public Task> GetReviewsByMovieIdAsync(Guid movieId) + private readonly IReviewRepository _reviewRepository; + private readonly IMapper _mapper; + private readonly ILogger _logger; + public ReviewService(IReviewRepository reviewRepository,IMapper mapper, ILogger logger) + { + _reviewRepository = reviewRepository ?? throw new ArgumentNullException(nameof(reviewRepository)); + _mapper = mapper ?? throw new ArgumentNullException(nameof(mapper)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } + public Task> GetReviewsByMovieIdAsync(Guid movieId) { throw new NotImplementedException(); } + + public async Task CreateReviewAsync(ReviewDto reviewDto) + { + try + { + var review = await _reviewRepository.AddAsync(_mapper.Map(reviewDto)).ConfigureAwait(false); + return review.Id; + } + catch (Exception ex) + { + _logger.LogError(ex, "An error occurred while creating a review."); + throw; + } + } } diff --git a/server/nt.microservice/services/ReviewService/ReviewService.Application.Services/ReviewService.Application.Services.csproj b/server/nt.microservice/services/ReviewService/ReviewService.Application.Services/ReviewService.Application.Services.csproj index 3c6a2248..57630032 100644 --- a/server/nt.microservice/services/ReviewService/ReviewService.Application.Services/ReviewService.Application.Services.csproj +++ b/server/nt.microservice/services/ReviewService/ReviewService.Application.Services/ReviewService.Application.Services.csproj @@ -6,8 +6,14 @@ enable + + + + + + diff --git a/server/nt.microservice/services/ReviewService/ReviewService.Domain/Repositories/IGenericRepository.cs b/server/nt.microservice/services/ReviewService/ReviewService.Domain/Repositories/IGenericRepository.cs new file mode 100644 index 00000000..57d022e1 --- /dev/null +++ b/server/nt.microservice/services/ReviewService/ReviewService.Domain/Repositories/IGenericRepository.cs @@ -0,0 +1,12 @@ +using ReviewService.Domain.Entities; + +namespace ReviewService.Domain.Repositories; + +public interface IGenericRepository where TEntity : class, IEntity, new() +{ + Task> GetAll(); + Task GetByIdAsync(long id); + Task AddAsync(TEntity entity); + Task UpdateAsync(TEntity entity); + Task DeleteAsync(TEntity entity); +} diff --git a/server/nt.microservice/services/ReviewService/ReviewService.Domain/Repositories/IReviewRepository.cs b/server/nt.microservice/services/ReviewService/ReviewService.Domain/Repositories/IReviewRepository.cs new file mode 100644 index 00000000..0aac5f82 --- /dev/null +++ b/server/nt.microservice/services/ReviewService/ReviewService.Domain/Repositories/IReviewRepository.cs @@ -0,0 +1,11 @@ +using ReviewService.Domain.Entities; + +namespace ReviewService.Domain.Repositories; + +public interface IReviewRepository : IGenericRepository +{ + Task> GetReviewsByMovieIdAsync(Guid movieId); + Task> GetReviewsByUserIdAsync(Guid userId); + Task> GetReviewsByRatingAsync(int rating); + Task> GetReviewsByDateRangeAsync(DateTime startDate, DateTime endDate); +} \ No newline at end of file diff --git a/server/nt.microservice/services/ReviewService/ReviewService.Infrastructure.Repository/Repositories/GenericRepository.cs b/server/nt.microservice/services/ReviewService/ReviewService.Infrastructure.Repository/Repositories/GenericRepository.cs new file mode 100644 index 00000000..0dab4f8b --- /dev/null +++ b/server/nt.microservice/services/ReviewService/ReviewService.Infrastructure.Repository/Repositories/GenericRepository.cs @@ -0,0 +1,32 @@ +using ReviewService.Domain.Entities; +using ReviewService.Domain.Repositories; + +namespace ReviewService.Infrastructure.Repository.Repositories; + +public class GenericRepository : IGenericRepository where TEntity : class, IEntity, new() +{ + public Task AddAsync(TEntity entity) + { + throw new NotImplementedException(); + } + + public Task DeleteAsync(TEntity entity) + { + throw new NotImplementedException(); + } + + public Task> GetAll() + { + throw new NotImplementedException(); + } + + public Task GetByIdAsync(long id) + { + throw new NotImplementedException(); + } + + public Task UpdateAsync(TEntity entity) + { + throw new NotImplementedException(); + } +} diff --git a/server/nt.microservice/services/ReviewService/ReviewService.Infrastructure.Repository/ReviewService.Infrastructure.Repository.csproj b/server/nt.microservice/services/ReviewService/ReviewService.Infrastructure.Repository/ReviewService.Infrastructure.Repository.csproj index 125f4c93..04125aee 100644 --- a/server/nt.microservice/services/ReviewService/ReviewService.Infrastructure.Repository/ReviewService.Infrastructure.Repository.csproj +++ b/server/nt.microservice/services/ReviewService/ReviewService.Infrastructure.Repository/ReviewService.Infrastructure.Repository.csproj @@ -6,4 +6,8 @@ enable + + + + diff --git a/server/nt.microservice/services/ReviewService/ReviewService.Presentation.Api/Controllers/UserReviewsController.cs b/server/nt.microservice/services/ReviewService/ReviewService.Presentation.Api/Controllers/UserReviewsController.cs index 6f37de51..bf8bd4bc 100644 --- a/server/nt.microservice/services/ReviewService/ReviewService.Presentation.Api/Controllers/UserReviewsController.cs +++ b/server/nt.microservice/services/ReviewService/ReviewService.Presentation.Api/Controllers/UserReviewsController.cs @@ -1,5 +1,8 @@ +using AutoMapper; +using MediatR; using Microsoft.AspNetCore.Mvc; -using ReviewService.Presenation.Api.ViewModels; +using ReviewService.Application.Orchestration.Commands; +using ReviewService.Presenation.Api.Models; namespace ReviewService.Api.Controllers; @@ -8,15 +11,53 @@ namespace ReviewService.Api.Controllers; public class UserReviewsController : ControllerBase { private readonly ILogger _logger; + private readonly IMapper _mapper; + private readonly IMediator _mediator; - public UserReviewsController(ILogger logger) + public UserReviewsController(IMediator mediator, IMapper mapper, ILogger logger) { _logger = logger; + _mapper = mapper; + _mediator = mediator; } - [HttpGet(Name = "GetReviewsForMovie")] - public ActionResult GetReviewsForMovie(GetReviewsForMovieRequest request) + [HttpGet] + [Route("GetReviewsForMovie/{movieId}")] + public ActionResult GetReviewsForMovie(Guid movieId) { return default!; } + + [HttpPost] + [Route("CreateReview")] + public async Task> CreateReview(CreateReviewRequest request) + { + try + { + if (!ModelState.IsValid) + { + return BadRequest(ModelState); + } + + var reviewId = await _mediator.Send(new CreateReviewCommand + { + Review = _mapper.Map(request) + }).ConfigureAwait(false); + + if (reviewId == Guid.Empty) + { + _logger.LogError("Failed to create review. Review ID is empty."); + return BadRequest("Failed to create review."); + } + return Ok(new CreateReviewResponse + { + Id = reviewId + }); + } + catch (Exception e) + { + _logger.LogError(@"An error occurred while creating the review.", e); + return BadRequest(e); + } + } } diff --git a/server/nt.microservice/services/ReviewService/ReviewService.Presentation.Api/Models/CreateReviewRequest.cs b/server/nt.microservice/services/ReviewService/ReviewService.Presentation.Api/Models/CreateReviewRequest.cs new file mode 100644 index 00000000..f08df856 --- /dev/null +++ b/server/nt.microservice/services/ReviewService/ReviewService.Presentation.Api/Models/CreateReviewRequest.cs @@ -0,0 +1,9 @@ +namespace ReviewService.Presenation.Api.Models; + +public class CreateReviewRequest +{ + public Guid MovieId { get; set; } + public string Content { get; set; } = string.Empty; + public int Rating { get; set; } + public string UserName { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/server/nt.microservice/services/ReviewService/ReviewService.Presentation.Api/Models/CreateReviewResponse.cs b/server/nt.microservice/services/ReviewService/ReviewService.Presentation.Api/Models/CreateReviewResponse.cs new file mode 100644 index 00000000..efa95156 --- /dev/null +++ b/server/nt.microservice/services/ReviewService/ReviewService.Presentation.Api/Models/CreateReviewResponse.cs @@ -0,0 +1,6 @@ +namespace ReviewService.Presenation.Api.Models; + +public class CreateReviewResponse +{ + public Guid Id { get; set; } +} \ No newline at end of file diff --git a/server/nt.microservice/services/ReviewService/ReviewService.Presentation.Api/ViewModels/GetReviewsForMovieRequest.cs b/server/nt.microservice/services/ReviewService/ReviewService.Presentation.Api/Models/GetReviewsForMovieResponse.cs similarity index 78% rename from server/nt.microservice/services/ReviewService/ReviewService.Presentation.Api/ViewModels/GetReviewsForMovieRequest.cs rename to server/nt.microservice/services/ReviewService/ReviewService.Presentation.Api/Models/GetReviewsForMovieResponse.cs index 5365cf08..881310e3 100644 --- a/server/nt.microservice/services/ReviewService/ReviewService.Presentation.Api/ViewModels/GetReviewsForMovieRequest.cs +++ b/server/nt.microservice/services/ReviewService/ReviewService.Presentation.Api/Models/GetReviewsForMovieResponse.cs @@ -1,9 +1,5 @@ -namespace ReviewService.Presenation.Api.ViewModels; +namespace ReviewService.Presenation.Api.Models; -public record GetReviewsForMovieRequest -{ - public Guid MovieId { get; set; } -} public record GetReviewsForMovieResponse { diff --git a/server/nt.microservice/services/ReviewService/ReviewService.Presentation.Api/ReviewService.Presenation.Api.csproj b/server/nt.microservice/services/ReviewService/ReviewService.Presentation.Api/ReviewService.Presenation.Api.csproj index e2dec2a8..74a7fa93 100644 --- a/server/nt.microservice/services/ReviewService/ReviewService.Presentation.Api/ReviewService.Presenation.Api.csproj +++ b/server/nt.microservice/services/ReviewService/ReviewService.Presentation.Api/ReviewService.Presenation.Api.csproj @@ -10,12 +10,17 @@ + + + + +