From 326a87e1a9a3f1bf8a362675117518f079d08d3f Mon Sep 17 00:00:00 2001 From: Nguyen Xuan Nhan Date: Sun, 2 Jun 2024 21:18:12 +0700 Subject: [PATCH] fix: best seller query issue --- .../Reports/BestSellerProducts.Request.cs | 2 +- .../Endpoints/Reports/BestSellerProducts.cs | 4 +-- .../Reports/DTOs/BestSellerProductsDto.cs | 18 +++++----- .../BestSellerProductsHandler.cs | 33 +++++++++++-------- .../BestSellerProductsQuery.cs | 3 +- .../BestSellerProductsValidator.cs | 13 +------- 6 files changed, 33 insertions(+), 40 deletions(-) diff --git a/src/RookieShop.ApiService/Endpoints/Reports/BestSellerProducts.Request.cs b/src/RookieShop.ApiService/Endpoints/Reports/BestSellerProducts.Request.cs index 4b82b6e..35d79e5 100644 --- a/src/RookieShop.ApiService/Endpoints/Reports/BestSellerProducts.Request.cs +++ b/src/RookieShop.ApiService/Endpoints/Reports/BestSellerProducts.Request.cs @@ -1,3 +1,3 @@ namespace RookieShop.ApiService.Endpoints.Reports; -public sealed record BestSellerProductsRequest(int Top, DateTime? From, DateTime? To); \ No newline at end of file +public sealed record BestSellerProductsRequest(int Top); \ No newline at end of file diff --git a/src/RookieShop.ApiService/Endpoints/Reports/BestSellerProducts.cs b/src/RookieShop.ApiService/Endpoints/Reports/BestSellerProducts.cs index 25d4de3..86f450a 100644 --- a/src/RookieShop.ApiService/Endpoints/Reports/BestSellerProducts.cs +++ b/src/RookieShop.ApiService/Endpoints/Reports/BestSellerProducts.cs @@ -12,7 +12,7 @@ public sealed class BestSellerProducts(ISender sender) { public void MapEndpoint(IEndpointRouteBuilder app) => app.MapGet("/reports/best-seller-products", - async (int top, DateTime? from, DateTime? to) => await HandleAsync(new(top, from, to))) + async (int top) => await HandleAsync(new(top))) .Produces>>() .WithTags(nameof(Reports)) .WithName("Best Seller Products") @@ -22,7 +22,7 @@ public sealed class BestSellerProducts(ISender sender) public async Task>> HandleAsync(BestSellerProductsRequest request, CancellationToken cancellationToken = default) { - BestSellerProductsQuery query = new(request.Top, request.From, request.To); + BestSellerProductsQuery query = new(request.Top); var result = await sender.Send(query, cancellationToken); diff --git a/src/RookieShop.Application/Reports/DTOs/BestSellerProductsDto.cs b/src/RookieShop.Application/Reports/DTOs/BestSellerProductsDto.cs index 0fcfea2..9dd9132 100644 --- a/src/RookieShop.Application/Reports/DTOs/BestSellerProductsDto.cs +++ b/src/RookieShop.Application/Reports/DTOs/BestSellerProductsDto.cs @@ -1,10 +1,10 @@ -using RookieShop.Domain.Entities.ProductAggregator.ValueObjects; +namespace RookieShop.Application.Reports.DTOs; -namespace RookieShop.Application.Reports.DTOs; - -public sealed record BestSellerProductsDto( - Guid ProductId, - string ProductName, - int TotalSoldQuantity, - ProductPrice Price, - string? ImageUrl); \ No newline at end of file +public sealed class BestSellerProductsDto +{ + public Guid ProductId { get; set; } + public string? ProductName { get; set; } + public int TotalSoldQuantity { get; set; } + public string Price { get; set; } = string.Empty; + public string? ImageUrl { get; set; } +} \ No newline at end of file diff --git a/src/RookieShop.Application/Reports/Queries/BestSellerProducts/BestSellerProductsHandler.cs b/src/RookieShop.Application/Reports/Queries/BestSellerProducts/BestSellerProductsHandler.cs index 94f4e46..fa678ef 100644 --- a/src/RookieShop.Application/Reports/Queries/BestSellerProducts/BestSellerProductsHandler.cs +++ b/src/RookieShop.Application/Reports/Queries/BestSellerProducts/BestSellerProductsHandler.cs @@ -2,11 +2,12 @@ using Dapper; using RookieShop.Application.Reports.DTOs; using RookieShop.Domain.SharedKernel; +using RookieShop.Infrastructure.Storage.Azurite; using RookieShop.Persistence; namespace RookieShop.Application.Reports.Queries.BestSellerProducts; -public sealed class BestSellerProductsHandler(IDatabaseFactory factory) +public sealed class BestSellerProductsHandler(IDatabaseFactory factory, IAzuriteService azuriteService) : IQueryHandler>> { public async Task>> Handle(BestSellerProductsQuery request, @@ -14,25 +15,29 @@ public sealed class BestSellerProductsHandler(IDatabaseFactory factory) { const string sql = $""" SELECT - p.id AS {nameof(BestSellerProductsDto.ProductId)}, - p.name AS {nameof(BestSellerProductsDto.ProductName)}, - p.image_name AS {nameof(BestSellerProductsDto.ImageUrl)}, - SUM(od.quantity) AS {nameof(BestSellerProductsDto.TotalSoldQuantity)}, - p.price AS {nameof(BestSellerProductsDto.Price)} + p.id AS {nameof(BestSellerProductsDto.ProductId)}, + p.name AS {nameof(BestSellerProductsDto.ProductName)}, + p.image_name AS {nameof(BestSellerProductsDto.ImageUrl)}, + p.price AS {nameof(BestSellerProductsDto.Price)}, + COUNT(od.quantity) AS {nameof(BestSellerProductsDto.TotalSoldQuantity)} FROM products p - JOIN order_details od ON p.id = od.product_id - JOIN orders o ON od.order_id = o.id - WHERE (@From IS NULL OR o.update_date >= @From) - AND (@To IS NULL OR o.update_date <= @To) - AND o.order_status = 1 - GROUP BY p.id, p.name, p.image_name, p.price + JOIN order_details od ON p.id = od.product_id + JOIN orders o ON od.order_id = o.id + WHERE o.order_status = 1 + GROUP BY p.id, p.name, p.image_name, p.price ORDER BY {nameof(BestSellerProductsDto.TotalSoldQuantity)} DESC - LIMIT @Top; + LIMIT 5 """; using var conn = factory.GetOpenConnection(); - var result = await conn.QueryAsync(sql, new { request.From, request.To, request.Top }); + var data = await conn.QueryAsync(sql, new { request.Top }); + + var result = data.Select(item => + { + item.ImageUrl = azuriteService.GetFileUrl(item.ImageUrl); + return item; + }).ToList(); return result.ToList(); } diff --git a/src/RookieShop.Application/Reports/Queries/BestSellerProducts/BestSellerProductsQuery.cs b/src/RookieShop.Application/Reports/Queries/BestSellerProducts/BestSellerProductsQuery.cs index c476ce1..8808eba 100644 --- a/src/RookieShop.Application/Reports/Queries/BestSellerProducts/BestSellerProductsQuery.cs +++ b/src/RookieShop.Application/Reports/Queries/BestSellerProducts/BestSellerProductsQuery.cs @@ -4,5 +4,4 @@ namespace RookieShop.Application.Reports.Queries.BestSellerProducts; -public sealed record BestSellerProductsQuery(int Top, DateTime? From, DateTime? To) - : IQuery>>; \ No newline at end of file +public sealed record BestSellerProductsQuery(int Top) : IQuery>>; \ No newline at end of file diff --git a/src/RookieShop.Application/Reports/Queries/BestSellerProducts/BestSellerProductsValidator.cs b/src/RookieShop.Application/Reports/Queries/BestSellerProducts/BestSellerProductsValidator.cs index 94133b2..3db7b42 100644 --- a/src/RookieShop.Application/Reports/Queries/BestSellerProducts/BestSellerProductsValidator.cs +++ b/src/RookieShop.Application/Reports/Queries/BestSellerProducts/BestSellerProductsValidator.cs @@ -4,16 +4,5 @@ namespace RookieShop.Application.Reports.Queries.BestSellerProducts; public sealed class BestSellerProductsValidator : AbstractValidator { - public BestSellerProductsValidator() - { - RuleFor(x => x.Top) - .NotEmpty() - .GreaterThan(0); - - RuleFor(x => x.From) - .LessThan(x => x.To); - - RuleFor(x => x.To) - .GreaterThan(x => x.From); - } + public BestSellerProductsValidator() => RuleFor(x => x.Top).NotEmpty().GreaterThan(0); } \ No newline at end of file