Skip to content

Commit

Permalink
clean architecture implemetation done
Browse files Browse the repository at this point in the history
  • Loading branch information
rahul-atharva committed Apr 28, 2023
1 parent 59194a9 commit 5b117d1
Show file tree
Hide file tree
Showing 125 changed files with 1,671 additions and 8,438 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,7 @@
</ItemGroup>

<ItemGroup>
<Folder Include="Features\Cart\" />
<Folder Include="Features\ProductType\" />
<Folder Include="Features\Product\" />
<Folder Include="Features\Payment\" />
<Folder Include="Features\Order\" />
</ItemGroup>

</Project>
2 changes: 1 addition & 1 deletion src/BlazorEcommerce.Application/ConfigureServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public static IServiceCollection AddApplicationServices(this IServiceCollection

services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly());

services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly())); ;
services.AddMediatR(cfg => cfg.RegisterServicesFromAssembly(Assembly.GetExecutingAssembly()));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(UnhandledExceptionBehaviour<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ public interface ICurrentUser
string? UserId { get; }

string? UserEmail { get; }

bool UserIsInRole(string roleName);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using BlazorEcommerce.Shared.Cart;
using Microsoft.AspNetCore.Http;

namespace BlazorEcommerce.Application.Contracts.Payment
{
public interface IPaymentService
{
Task<IResponse> CreateCheckoutSession(List<CartProductResponse> products);
Task<IResponse> FulfillOrder(HttpRequest request);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using BlazorEcommerce.Application.Contracts.Identity;
using BlazorEcommerce.Shared.Cart;

namespace BlazorEcommerce.Application.Features.Cart.Commands.AddToCart;

public record AddToCartCommandRequest(CartItemDto cartItem) : IRequest<IResponse>;

public class AddToCartCommandHandler : IRequestHandler<AddToCartCommandRequest, IResponse>
{
private readonly ICommandUnitOfWork<int> _command;
private readonly IQueryUnitOfWork _query;
private readonly ICurrentUser _currentUser;
private readonly IMapper _mapper;

public AddToCartCommandHandler(ICommandUnitOfWork<int> command, IQueryUnitOfWork query, ICurrentUser currentUser, IMapper mapper)
{
_command = command;
_query = query;
_currentUser = currentUser;
_mapper = mapper;
}

public async Task<IResponse> Handle(AddToCartCommandRequest request, CancellationToken cancellationToken)
{
request.cartItem.UserId = _currentUser.UserId;

var sameItem = await _query.CartItemQuery.GetByIdAsync(ci => ci.ProductId == request.cartItem.ProductId &&
ci.ProductTypeId == request.cartItem.ProductTypeId && ci.UserId == request.cartItem.UserId);

if (sameItem == null)
{
await _command.CartItemCommand.AddAsync(_mapper.Map<CartItem>(request.cartItem));
}
else
{
sameItem.Quantity += request.cartItem.Quantity;
}

await _command.SaveAsync();

return new SuccessResponse();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using BlazorEcommerce.Application.Contracts.Identity;

namespace BlazorEcommerce.Application.Features.Cart.Commands.RemoveItemFromCart;

public record RemoveItemFromCartCommandRequest(int productId, int productTypeId) : IRequest<IResponse>;

public class RemoveItemFromCartCommandHandler : IRequestHandler<RemoveItemFromCartCommandRequest, IResponse>
{
private readonly ICommandUnitOfWork<int> _command;
private readonly IQueryUnitOfWork _query;
private readonly ICurrentUser _currentUser;

public RemoveItemFromCartCommandHandler(ICommandUnitOfWork<int> command, IQueryUnitOfWork query, ICurrentUser currentUser)
{
_command = command;
_query = query;
_currentUser = currentUser;
}

public async Task<IResponse> Handle(RemoveItemFromCartCommandRequest request, CancellationToken cancellationToken)
{
var dbCartItem = await _query.CartItemQuery.GetByIdAsync(ci => ci.ProductId == request.productId &&
ci.ProductTypeId == request.productTypeId && ci.UserId == _currentUser.UserId);

if (dbCartItem == null)
{
return new ErrorResponse(HttpStatusCodes.NotFound, String.Format(Messages.NotExist, "Cart item"));
}

_command.CartItemCommand.Remove(dbCartItem);
await _command.SaveAsync();

return new SuccessResponse();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using BlazorEcommerce.Application.Contracts.Identity;
using BlazorEcommerce.Shared.Cart;

namespace BlazorEcommerce.Application.Features.Cart.Commands.StoreCartItems;

public record StoreCartItemsCommandRequest(List<CartItemDto> cartItems) : IRequest<IResponse>;

public class StoreCartItemsCommandHandler : IRequestHandler<StoreCartItemsCommandRequest, IResponse>
{
private readonly ICommandUnitOfWork<int> _command;
private readonly ICurrentUser _currentUser;
private readonly IMapper _mapper;

public StoreCartItemsCommandHandler(ICommandUnitOfWork<int> command, ICurrentUser currentUser, IMapper mapper)
{
_command = command;
_currentUser = currentUser;
_mapper = mapper;
}

public async Task<IResponse> Handle(StoreCartItemsCommandRequest request, CancellationToken cancellationToken)
{
request.cartItems.ForEach(cartItem => cartItem.UserId = _currentUser.UserId);

await _command.CartItemCommand.AddRangeAsync(_mapper.Map<List<CartItem>>(request.cartItems));
await _command.SaveAsync();

return new SuccessResponse();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using BlazorEcommerce.Application.Contracts.Identity;
using BlazorEcommerce.Shared.Cart;

namespace BlazorEcommerce.Application.Features.Cart.Commands.UpdateQuantity;

public record UpdateQuantityCommandRequest(CartItemDto cartItem) : IRequest<IResponse>;

public class UpdateQuantityCommandHandler : IRequestHandler<UpdateQuantityCommandRequest, IResponse>
{
private readonly ICommandUnitOfWork<int> _command;
private readonly IQueryUnitOfWork _query;
private readonly ICurrentUser _currentUser;
private readonly IMapper _mapper;

public UpdateQuantityCommandHandler(ICommandUnitOfWork<int> command, IQueryUnitOfWork query, ICurrentUser currentUser, IMapper mapper)
{
_command = command;
_query = query;
_currentUser = currentUser;
_mapper = mapper;
}

public async Task<IResponse> Handle(UpdateQuantityCommandRequest request, CancellationToken cancellationToken)
{
var dbCartItem = await _query.CartItemQuery.GetByIdAsync(ci => ci.ProductId == request.cartItem.ProductId &&
ci.ProductTypeId == request.cartItem.ProductTypeId && ci.UserId == _currentUser.UserId);

if (dbCartItem == null)
{
return new ErrorResponse(HttpStatusCodes.NotFound,String.Format(Messages.NotExist, "Cart item"));
}

dbCartItem.Quantity = request.cartItem.Quantity;
await _command.SaveAsync();

return new SuccessResponse();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using BlazorEcommerce.Application.Contracts.Identity;

namespace BlazorEcommerce.Application.Features.Cart.Query.GetCartItemsCount;

public record GetCartItemsCountQueryRequest : IRequest<IResponse>;

public class GetCartItemsCountQueryHandler : IRequestHandler<GetCartItemsCountQueryRequest, IResponse>
{
private readonly IQueryUnitOfWork _query;
private readonly ICurrentUser _currentUser;

public GetCartItemsCountQueryHandler(IQueryUnitOfWork query, ICurrentUser currentUser)
{
_query = query;
_currentUser = currentUser;
}

public async Task<IResponse> Handle(GetCartItemsCountQueryRequest request, CancellationToken cancellationToken)
{
var resords = await _query.CartItemQuery.GetAllWithIncludeAsync(false, ci => ci.UserId == _currentUser.UserId);

return new DataResponse<int>(resords.Count(), HttpStatusCodes.Accepted);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using BlazorEcommerce.Shared.Cart;

namespace BlazorEcommerce.Application.Features.Cart.Query.GetCartProducts;

public record GetCartProductsQueryRequest(List<CartItemDto> cartItems) : IRequest<IResponse>;

public class GetCartProductsQueryHandler : IRequestHandler<GetCartProductsQueryRequest, IResponse>
{
private readonly IQueryUnitOfWork _query;
private readonly IMapper _mapper;

public GetCartProductsQueryHandler(IQueryUnitOfWork query, IMapper mapper)
{
_query = query;
_mapper = mapper;
}

public async Task<IResponse> Handle(GetCartProductsQueryRequest request, CancellationToken cancellationToken)
{
var result = new List<CartProductResponse>();

foreach (var item in request.cartItems)
{
var product = await _query.ProductQuery.GetByIdAsync(p => p.Id == item.ProductId);

if (product == null)
{
continue;
}

var productVariant = await _query.ProductVariantQuery.GetWithIncludeAsync(false,
v => v.ProductId == item.ProductId
&& v.ProductTypeId == item.ProductTypeId,
false,
v => v.ProductType);;

if (productVariant == null)
{
continue;
}

var cartProduct = new CartProductResponse
{
ProductId = product.Id,
Title = product.Title,
ImageUrl = product.ImageUrl,
Price = productVariant.Price,
ProductType = productVariant.ProductType.Name,
ProductTypeId = productVariant.ProductTypeId,
Quantity = item.Quantity
};

result.Add(cartProduct);
}

return new DataResponse<List<CartProductResponse>>(result,HttpStatusCodes.Accepted);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using BlazorEcommerce.Application.Contracts.Identity;
using BlazorEcommerce.Shared.Cart;

namespace BlazorEcommerce.Application.Features.Cart.Query.GetDbCartProducts;

public record GetDbCartProductsQueryRequest : IRequest<IResponse>;

public class GetDbCartProductsQueryHandler : IRequestHandler<GetDbCartProductsQueryRequest, IResponse>
{
private readonly IQueryUnitOfWork _query;
private readonly ICurrentUser _currentUser;

public GetDbCartProductsQueryHandler(IQueryUnitOfWork query, ICurrentUser currentUser)
{
_query = query;
_currentUser = currentUser;
}

public async Task<IResponse> Handle(GetDbCartProductsQueryRequest request, CancellationToken cancellationToken)
{
var cartItems = await _query.CartItemQuery.GetAllWithIncludeAsync(false,ci => ci.UserId == _currentUser.UserId);

var result = new List<CartProductResponse>();

foreach (var item in cartItems)
{
var product = await _query.ProductQuery.GetByIdAsync(p => p.Id == item.ProductId);

if (product == null)
{
continue;
}

var productVariant = await _query.ProductVariantQuery.GetWithIncludeAsync(false,
v => v.ProductId == item.ProductId
&& v.ProductTypeId == item.ProductTypeId,
false,
v => v.ProductType); ;

if (productVariant == null)
{
continue;
}

var cartProduct = new CartProductResponse
{
ProductId = product.Id,
Title = product.Title,
ImageUrl = product.ImageUrl,
Price = productVariant.Price,
ProductType = productVariant.ProductType.Name,
ProductTypeId = productVariant.ProductTypeId,
Quantity = item.Quantity
};

result.Add(cartProduct);
}

return new DataResponse<List<CartProductResponse>>(result, HttpStatusCodes.Accepted);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
using BlazorEcommerce.Application.Contracts.Identity;
using BlazorEcommerce.Shared.Cart;
using BlazorEcommerce.Shared.Order;

namespace BlazorEcommerce.Application.Features.Order.Command.PlaceOrder;

public record PlaceOrderCommandRequest(List<CartProductResponse> products) : IRequest<IResponse>;

public class PlaceOrderCommandHandler : IRequestHandler<PlaceOrderCommandRequest, IResponse>
{
private readonly ICommandUnitOfWork<int> _command;
private readonly IMapper _mapper;
private readonly ICurrentUser _currentUser;
private readonly IQueryUnitOfWork _query;

public PlaceOrderCommandHandler(ICommandUnitOfWork<int> command, IMapper mapper, ICurrentUser currentUser, IQueryUnitOfWork query)
{
_command = command;
_mapper = mapper;
_currentUser = currentUser;
_query = query;
}

public async Task<IResponse> Handle(PlaceOrderCommandRequest request, CancellationToken cancellationToken)
{
string userId = _currentUser.UserId;

decimal totalPrice = 0;
request.products.ForEach(product => totalPrice += product.Price * product.Quantity);

var orderItems = new List<OrderItemDto>();
request.products.ForEach(product => orderItems.Add(new OrderItemDto
{
ProductId = product.ProductId,
ProductTypeId = product.ProductTypeId,
Quantity = product.Quantity,
TotalPrice = product.Price * product.Quantity
}));

var order = new OrderDto
{
UserId = userId,
OrderDate = DateTime.Now,
TotalPrice = totalPrice,
OrderItems = orderItems
};

await _command.OrderCommand.AddAsync(_mapper.Map<Domain.Entities.Order>(order));

var cartItems = await _query.CartItemQuery.GetAllWithIncludeAsync(false, ci => ci.UserId == userId);

_command.CartItemCommand.RemoveRange(cartItems);

await _command.SaveAsync();

return new SuccessResponse();
}
}
Loading

0 comments on commit 5b117d1

Please sign in to comment.