Skip to content

Commit c7d5209

Browse files
committed
feat: implement GetAllProductsWithoutSellerListing query and handler; enhance product filtering with SubjectFilter and SellerId
1 parent 1cdb11b commit c7d5209

File tree

16 files changed

+298
-165
lines changed

16 files changed

+298
-165
lines changed

Source/Ecommerce.Application/Common/Interfaces/Persistence/IProductRepository.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Ecommerce.Application.UseCases.Products.Common;
33
using Ecommerce.Application.UseCases.Products.Queries.GetFilteredProducts;
44
using Ecommerce.Domain.Common.Entities;
5+
using Ecommerce.Domain.OrderAggregate.ValueObjects;
56
using Ecommerce.Domain.ProductAggregate;
67
using Ecommerce.Domain.ProductAggregate.Entities;
78
using Ecommerce.Domain.ProductAggregate.ValueObjects;
@@ -100,4 +101,8 @@ Task<GetProductsResult> GetAllProductsSellerNotListedAsync(
100101
/// </summary>
101102
/// <returns></returns>
102103
Task<int> CountProducts();
104+
105+
IDictionary<OrderId, IEnumerable<Product>> GetMappedOrderIdWithProducts(
106+
IDictionary<OrderId, IEnumerable<ProductId>> dict
107+
);
103108
}

Source/Ecommerce.Application/Common/Mapping/OrderMappingProfile.cs

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -16,30 +16,30 @@ public class OrderMappingProfile : Profile
1616
{
1717
public OrderMappingProfile()
1818
{
19-
CreateMap<GetOrdersResult, OrdersResult>();
20-
21-
CreateMap<Order, OrderResult>()
22-
.ForMember(dest => dest.OrderId, opt => opt.MapFrom(src => src.Id.Value.ToString()))
23-
.ForMember(dest => dest.UserId, opt => opt.MapFrom(src => src.UserId.Value.ToString()))
24-
.ForMember(dest => dest.Total, opt => opt.MapFrom(src => src.Total))
25-
.ForMember(dest => dest.ShippingAddress, opt => opt.MapFrom(src => src.ShippingAddress))
26-
.ForMember(dest => dest.Status, opt => opt.MapFrom(src => src.Status.ToString()))
27-
.ForMember(dest => dest.OrderItems, opt => opt.MapFrom(src => src.OrderItems.ToList()))
28-
.ForMember(dest => dest.OrderDate, opt => opt.MapFrom(src => src.OrderDate));
29-
30-
CreateMap<ShippingAddressCommand, ShippingAddress>();
31-
32-
CreateMap<OrderItem, OrderItemResult>()
33-
.ForMember(dest => dest.ProductId, opt => opt.MapFrom(src => src.ProductId.Value.ToString()))
34-
.ForMember(dest => dest.Quantity, opt => opt.MapFrom(src => src.Quantity))
35-
.ForMember(dest => dest.PriceValueInCents, opt => opt.MapFrom(src => src.Price.ValueInCents));
36-
37-
// CreateMap<IReadOnlyList<OrderItem>, List<OrderItemResult>>(); // AutoMapper will use the OrderItem -> OrderItemResult mapping
38-
39-
// Mapping for OrderTotal to OrderTotalResult
40-
CreateMap<OrderTotal, OrderTotalResult>()
41-
.ForMember(dest => dest.ValueTotalInCents, opt => opt.MapFrom(src => src.ValueTotalInCents))
42-
.ForMember(dest => dest.Currency, opt => opt.MapFrom(src => src.Currency.ToString()));
19+
// CreateMap<GetOrdersResult, OrdersResult>();
20+
21+
// CreateMap<Order, OrderResult>()
22+
// .ForMember(dest => dest.OrderId, opt => opt.MapFrom(src => src.Id.Value.ToString()))
23+
// .ForMember(dest => dest.UserId, opt => opt.MapFrom(src => src.UserId.Value.ToString()))
24+
// .ForMember(dest => dest.Total, opt => opt.MapFrom(src => src.Total))
25+
// .ForMember(dest => dest.ShippingAddress, opt => opt.MapFrom(src => src.ShippingAddress))
26+
// .ForMember(dest => dest.Status, opt => opt.MapFrom(src => src.Status.ToString()))
27+
// .ForMember(dest => dest.OrderItems, opt => opt.MapFrom(src => src.OrderItems.ToList()))
28+
// .ForMember(dest => dest.OrderDate, opt => opt.MapFrom(src => src.OrderDate));
29+
30+
// CreateMap<ShippingAddressCommand, ShippingAddress>();
31+
32+
// CreateMap<OrderItem, OrderItemResult>()
33+
// .ForMember(dest => dest.ProductId, opt => opt.MapFrom(src => src.ProductId.Value.ToString()))
34+
// .ForMember(dest => dest.Quantity, opt => opt.MapFrom(src => src.Quantity))
35+
// .ForMember(dest => dest.PriceValueInCents, opt => opt.MapFrom(src => src.Price.ValueInCents));
36+
37+
// // CreateMap<IReadOnlyList<OrderItem>, List<OrderItemResult>>(); // AutoMapper will use the OrderItem -> OrderItemResult mapping
38+
39+
// // Mapping for OrderTotal to OrderTotalResult
40+
// CreateMap<OrderTotal, OrderTotalResult>()
41+
// .ForMember(dest => dest.ValueTotalInCents, opt => opt.MapFrom(src => src.ValueTotalInCents))
42+
// .ForMember(dest => dest.Currency, opt => opt.MapFrom(src => src.Currency.ToString()));
4343

4444
// Mapping for Order to OrderResult
4545
}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using Ecommerce.Application.Common.Models;
2+
using Ecommerce.Application.UseCases.Orders.Common;
23
using Ecommerce.Domain.OrderAggregate;
4+
using Ecommerce.Domain.ProductAggregate;
35

46
namespace Ecommerce.Application.Common.Models;
57

6-
public class GetOrdersResult : GetResult<Order> { }
8+
public class GetOrdersResult : GetResult<(Order order, IEnumerable<Product> products)> { }

Source/Ecommerce.Application/Common/Models/Search/Elastic/ElasticSearchFilterParams.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using Ecommerce.Application.Common.Models.Enums;
2+
using Ecommerce.Application.UseCases.Products.Queries.GetFilteredProducts;
3+
using Ecommerce.Domain.UserAggregate.ValueObjects;
24

35
namespace Ecommerce.Application.Common.Models.Search.Elastic;
46

@@ -7,6 +9,9 @@ public record ElasticSearchFilterParams
79
// Required: The index or indices to search
810
public required string Index { get; init; }
911

12+
public UserId? SellerId { get; init; }
13+
public SubjectFilter SubjectFilter { get; init; } = SubjectFilter.AllProducts; // Fetch all products by default
14+
1015
// Optional: Full-text search term
1116
public string? SearchTerm { get; init; }
1217

@@ -19,8 +24,6 @@ public record ElasticSearchFilterParams
1924
public decimal? MinRating { get; init; }
2025
public decimal? MaxRating { get; init; } // Less common, usually just minRating
2126

22-
public string? SellerId { get; init; } // Filter by seller ID
23-
2427
public PaginationParameters Pagination { get; init; } = default!;
2528

2629
// Optional: Sorting

Source/Ecommerce.Application/UseCases/Orders/Common/OrdersResult.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using Ecommerce.Application.UseCases.Products.Common;
12
using Ecommerce.Domain.OrderAggregate.ValueObjects;
23

34
namespace Ecommerce.Application.UseCases.Orders.Common;
@@ -6,7 +7,7 @@ public class OrdersResult
67
{
78
public int TotalItems { get; set; } = 0;
89
public int TotalItemsFetched { get; set; } = 0;
9-
public List<OrderResult> Items { get; set; } = new List<OrderResult>();
10+
public required List<OrderResult> Items { get; set; }
1011
}
1112

1213
public class OrderResult
@@ -17,7 +18,7 @@ public class OrderResult
1718
public required ShippingAddress ShippingAddress { get; set; }
1819
public required string Status { get; set; }
1920

20-
public List<OrderItemResult> OrderItems = [];
21+
public required List<OrderItemResult> OrderItems;
2122
public required DateTime OrderDate { get; set; }
2223
}
2324

@@ -29,7 +30,7 @@ public class OrderTotalResult
2930

3031
public class OrderItemResult
3132
{
32-
public required string ProductId { get; set; }
33+
public required ProductResult Product { get; set; }
3334
public required int Quantity { get; set; }
34-
public required long PriceValueInCents { get; set; }
35+
public required long OrderItemTotalInCents { get; set; }
3536
}

Source/Ecommerce.Application/UseCases/Orders/Queries/GetOrders/GetOrdersCommandHandler.cs

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
1+
using System.Collections.Immutable;
12
using AutoMapper;
23
using Ecommerce.Application.Common.Errors;
34
using Ecommerce.Application.Common.Interfaces.Persistence;
45
using Ecommerce.Application.Common.Interfaces.Providers.Context;
56
using Ecommerce.Application.Common.Models;
67
using Ecommerce.Application.Common.Utilities;
78
using Ecommerce.Application.UseCases.Orders.Common;
9+
using Ecommerce.Application.UseCases.Products.Common;
10+
using Ecommerce.Domain.Common.Enums;
11+
using Ecommerce.Domain.OrderAggregate;
12+
using Ecommerce.Domain.OrderAggregate.Entities;
13+
using Ecommerce.Domain.ProductAggregate;
814
using FluentResults;
915
using MediatR;
1016

@@ -34,6 +40,55 @@ CancellationToken cancellationToken
3440
if (orders is null)
3541
return NotFoundError.GetResult("user", "user is not found");
3642

37-
return mapper.Map<OrdersResult>(orders);
43+
// LogPretty.Log(orders);
44+
45+
var res = new OrdersResult
46+
{
47+
Items = orders
48+
.Items.Select(tup => new OrderResult
49+
{
50+
OrderId = tup.order.Id.Value.ToString(),
51+
OrderDate = tup.order.OrderDate,
52+
ShippingAddress = tup.order.ShippingAddress,
53+
Status = tup.order.Status.ToString(),
54+
Total = new OrderTotalResult()
55+
{
56+
Currency = Currency.USD.ToString(),
57+
ValueTotalInCents = tup.products.Sum(p =>
58+
{
59+
var oi = tup.order.OrderItems.Where(oi => oi.ProductId == p.Id).First();
60+
long sum = p.Price.ValueInCents * (oi is null ? 0 : oi.Quantity);
61+
62+
return sum;
63+
}),
64+
},
65+
UserId = tup.order.UserId,
66+
OrderItems = tup
67+
.products.Select(p =>
68+
{
69+
var oi = tup.order.OrderItems.FirstOrDefault(oi => oi.ProductId == p.Id);
70+
var res = new OrderItemResult
71+
{
72+
OrderItemTotalInCents = p.Price.ValueInCents * (oi is null ? 0 : oi.Quantity),
73+
Product = mapper.Map<ProductResult>(p),
74+
Quantity = oi is null ? 0 : oi.Quantity,
75+
};
76+
// Console.WriteLine("Order Item Result\n:");
77+
// LogPretty.Log(res); // Order Item is printing okay!!!
78+
return res;
79+
})
80+
.ToList(),
81+
})
82+
.ToList(),
83+
TotalItems = orders.TotalItems,
84+
TotalItemsFetched = orders.TotalItemsFetched,
85+
};
86+
87+
// WHAT IN THE BLOODY HELL IS HAPPENING, Order Items are not being included in the 'res'??? Even though they're printed
88+
// and are present when constructing the dto above
89+
90+
// LogPretty.Log(res.Items.Select(x => x.OrderItems)); // Order Item is not Present Here! In the result object
91+
92+
return res;
3893
}
3994
}

Source/Ecommerce.Application/UseCases/Products/Queries/GetAllProducts/GetAllProductsQuery.cs

Lines changed: 0 additions & 19 deletions
This file was deleted.

Source/Ecommerce.Application/UseCases/Products/Queries/GetAllProducts/GetAllProductsQueryHandler.cs

Lines changed: 0 additions & 69 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using Ecommerce.Application.UseCases.Common.Interfaces;
2+
using Ecommerce.Application.UseCases.Products.Common;
3+
using Ecommerce.Application.UseCases.Products.Queries.GetFilteredProducts;
4+
using FluentResults;
5+
using MediatR;
6+
7+
namespace Ecommerce.Application.UseCases.Products.Queries.GetAllProductsWithoutSellerListing;
8+
9+
public class GetAllProductsWithoutSellerListingQuery : IRequest<Result<ProductsResult>>
10+
{
11+
public FilterProductsQuery? FilterQuery { get; set; }
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using AutoMapper;
2+
using Ecommerce.Application.Common.Interfaces.Persistence;
3+
using Ecommerce.Application.Common.Interfaces.Providers.Context;
4+
using Ecommerce.Application.Common.Models;
5+
using Ecommerce.Application.Common.Utilities;
6+
using Ecommerce.Application.UseCases.Products.Common;
7+
using Ecommerce.Application.UseCases.Products.Queries.GetFilteredProducts;
8+
using Ecommerce.Domain.UserAggregate.ValueObjects;
9+
using FluentResults;
10+
using MediatR;
11+
12+
namespace Ecommerce.Application.UseCases.Products.Queries.GetAllProductsWithoutSellerListing;
13+
14+
public class GetAllProductsWithoutSellerListingQueryHandler
15+
: IRequestHandler<GetAllProductsWithoutSellerListingQuery, Result<ProductsResult>>
16+
{
17+
private readonly IProductRepository _productRepository;
18+
private readonly IUserContextService _userContextService;
19+
private readonly ISender _sender;
20+
private readonly IMapper _mapper;
21+
22+
public GetAllProductsWithoutSellerListingQueryHandler(
23+
IProductRepository productRepository,
24+
IMapper mapper,
25+
IUserContextService contextService,
26+
ISender sender
27+
)
28+
{
29+
_productRepository = productRepository;
30+
_userContextService = contextService;
31+
_mapper = mapper;
32+
_sender = sender;
33+
}
34+
35+
public async Task<Result<ProductsResult>> Handle(
36+
GetAllProductsWithoutSellerListingQuery request,
37+
CancellationToken cancellationToken
38+
)
39+
{
40+
var userId = _userContextService.GetValidUserId();
41+
if (userId.IsFailed)
42+
return userId.ToResult();
43+
44+
var result = await _sender.Send(
45+
new FilterProductsQuery()
46+
{
47+
SearchTerm = request.FilterQuery?.SearchTerm,
48+
CategoryIds = request.FilterQuery?.CategoryIds,
49+
MaxPriceValueInCents = request.FilterQuery?.MaxPriceValueInCents,
50+
MinPriceValueInCents = request.FilterQuery?.MinPriceValueInCents,
51+
SortBy = request.FilterQuery?.SortBy,
52+
SellerId = userId.Value,
53+
SubjectFilter = SubjectFilter.AllProductsWithoutSeller,
54+
PaginationParameters = request.FilterQuery is null
55+
? new PaginationParameters()
56+
: request.FilterQuery.PaginationParameters,
57+
}
58+
);
59+
60+
return result;
61+
}
62+
}

0 commit comments

Comments
 (0)