Add Get queries for variants and categories
This commit is contained in:
@@ -0,0 +1,40 @@
|
|||||||
|
using MediatR;
|
||||||
|
using Printbase.Application.Products.Dtos;
|
||||||
|
using Printbase.Application.Products.Queries;
|
||||||
|
|
||||||
|
namespace Printbase.Application.Products.Handlers;
|
||||||
|
|
||||||
|
public class GetCategoriesHandler(IUnitOfWork unitOfWork)
|
||||||
|
: IRequestHandler<GetCategoriesQuery, IEnumerable<CategoryDto>>
|
||||||
|
{
|
||||||
|
public async Task<IEnumerable<CategoryDto>> Handle(GetCategoriesQuery request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
IEnumerable<Domain.Entities.Product.Category> categories;
|
||||||
|
|
||||||
|
if (request.RootCategoriesOnly)
|
||||||
|
{
|
||||||
|
categories = await unitOfWork.CategoryRepository.GetRootCategoriesAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
else if (request.IsActive.HasValue && request.IsActive.Value)
|
||||||
|
{
|
||||||
|
categories = await unitOfWork.CategoryRepository.GetActiveAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
categories = await unitOfWork.CategoryRepository.GetAllAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
return categories.Select(c => new CategoryDto
|
||||||
|
{
|
||||||
|
Id = c.Id,
|
||||||
|
Name = c.Name,
|
||||||
|
Description = c.Description,
|
||||||
|
ImageUrl = c.ImageUrl,
|
||||||
|
SortOrder = c.SortOrder,
|
||||||
|
IsActive = c.IsActive,
|
||||||
|
ParentCategoryId = c.ParentCategoryId,
|
||||||
|
CreatedAt = c.CreatedAt,
|
||||||
|
ModifiedAt = c.ModifiedAt
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
using MediatR;
|
||||||
|
using Printbase.Application.Products.Dtos;
|
||||||
|
using Printbase.Application.Products.Queries;
|
||||||
|
|
||||||
|
namespace Printbase.Application.Products.Handlers;
|
||||||
|
|
||||||
|
public class GetProductVariantsHandler(IUnitOfWork unitOfWork)
|
||||||
|
: IRequestHandler<GetProductVariantsQuery, IEnumerable<ProductVariantDto>>
|
||||||
|
{
|
||||||
|
public async Task<IEnumerable<ProductVariantDto>> Handle(GetProductVariantsQuery request, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
IEnumerable<Domain.Entities.Product.ProductVariant> variants;
|
||||||
|
|
||||||
|
if (request.ProductId.HasValue)
|
||||||
|
{
|
||||||
|
if (request.InStockOnly)
|
||||||
|
{
|
||||||
|
variants = await unitOfWork.ProductVariantRepository.GetInStockByProductIdAsync(request.ProductId.Value, cancellationToken);
|
||||||
|
}
|
||||||
|
else if (request.IsActive.HasValue && request.IsActive.Value)
|
||||||
|
{
|
||||||
|
variants = await unitOfWork.ProductVariantRepository.GetActiveByProductIdAsync(request.ProductId.Value, cancellationToken);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
variants = await unitOfWork.ProductVariantRepository.GetByProductIdAsync(request.ProductId.Value, cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
variants = new List<Domain.Entities.Product.ProductVariant>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return variants.Select(pv => new ProductVariantDto
|
||||||
|
{
|
||||||
|
Id = pv.Id,
|
||||||
|
ProductId = pv.ProductId,
|
||||||
|
Size = pv.Size,
|
||||||
|
Color = pv.Color,
|
||||||
|
Price = pv.Price,
|
||||||
|
ImageUrl = pv.ImageUrl,
|
||||||
|
Sku = pv.Sku,
|
||||||
|
StockQuantity = pv.StockQuantity,
|
||||||
|
IsActive = pv.IsActive,
|
||||||
|
Product = new ProductDto
|
||||||
|
{
|
||||||
|
Id = pv.Product.Id,
|
||||||
|
Name = pv.Product.Name,
|
||||||
|
Description = pv.Product.Description,
|
||||||
|
BasePrice = pv.Product.BasePrice,
|
||||||
|
IsCustomizable = pv.Product.IsCustomizable,
|
||||||
|
IsActive = pv.Product.IsActive,
|
||||||
|
ImageUrl = pv.Product.ImageUrl,
|
||||||
|
CategoryId = pv.Product.CategoryId,
|
||||||
|
CreatedAt = pv.Product.CreatedAt,
|
||||||
|
ModifiedAt = pv.Product.ModifiedAt
|
||||||
|
},
|
||||||
|
CreatedAt = pv.CreatedAt,
|
||||||
|
ModifiedAt = pv.ModifiedAt
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
using MediatR;
|
||||||
|
using Printbase.Application.Products.Dtos;
|
||||||
|
|
||||||
|
namespace Printbase.Application.Products.Queries;
|
||||||
|
|
||||||
|
public class GetCategoriesQuery : IRequest<IEnumerable<CategoryDto>>
|
||||||
|
{
|
||||||
|
public bool? IsActive { get; set; }
|
||||||
|
public bool RootCategoriesOnly { get; set; } = false;
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using MediatR;
|
||||||
|
using Printbase.Application.Products.Dtos;
|
||||||
|
|
||||||
|
namespace Printbase.Application.Products.Queries;
|
||||||
|
|
||||||
|
public class GetProductVariantsQuery : IRequest<IEnumerable<ProductVariantDto>>
|
||||||
|
{
|
||||||
|
public Guid? ProductId { get; set; }
|
||||||
|
public bool? IsActive { get; set; }
|
||||||
|
public bool InStockOnly { get; set; } = false;
|
||||||
|
}
|
||||||
30
src/Printbase.WebApi/Controllers/CategoriesController.cs
Normal file
30
src/Printbase.WebApi/Controllers/CategoriesController.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using MediatR;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Printbase.Application.Products.Commands;
|
||||||
|
using Printbase.Application.Products.Dtos;
|
||||||
|
|
||||||
|
namespace Printbase.WebApi.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class CategoriesController(IMediator mediator) : ControllerBase
|
||||||
|
{
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<ActionResult<CategoryDto>> CreateCategory([FromBody] CreateCategoryCommand command)
|
||||||
|
{
|
||||||
|
var result = await mediator.Send(command);
|
||||||
|
return CreatedAtAction(nameof(CreateCategory), new { id = result.Id }, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete("{id:guid}")]
|
||||||
|
public async Task<ActionResult> DeleteCategory(Guid id)
|
||||||
|
{
|
||||||
|
var command = new DeleteCategoryCommand { Id = id };
|
||||||
|
var result = await mediator.Send(command);
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
return NotFound();
|
||||||
|
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using MediatR;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Printbase.Application.Products.Commands;
|
||||||
|
using Printbase.Application.Products.Dtos;
|
||||||
|
|
||||||
|
namespace Printbase.WebApi.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class ProductVariantsController(IMediator mediator) : ControllerBase
|
||||||
|
{
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<ActionResult<ProductVariantDto>> CreateProductVariant([FromBody] CreateProductVariantCommand command)
|
||||||
|
{
|
||||||
|
var result = await mediator.Send(command);
|
||||||
|
return CreatedAtAction(nameof(CreateProductVariant), new { id = result.Id }, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete("{id}")]
|
||||||
|
public async Task<ActionResult> DeleteProductVariant(Guid id)
|
||||||
|
{
|
||||||
|
var command = new DeleteProductVariantCommand { Id = id };
|
||||||
|
var result = await mediator.Send(command);
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
return NotFound();
|
||||||
|
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
65
src/Printbase.WebApi/Controllers/ProductsController.cs
Normal file
65
src/Printbase.WebApi/Controllers/ProductsController.cs
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
using MediatR;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Printbase.Application.Products.Commands;
|
||||||
|
using Printbase.Application.Products.Dtos;
|
||||||
|
using Printbase.Application.Products.Queries;
|
||||||
|
using Printbase.Domain.Common.Models;
|
||||||
|
|
||||||
|
namespace Printbase.WebApi.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class ProductsController(IMediator mediator) : ControllerBase
|
||||||
|
{
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<ActionResult<PagedResultDto<ProductDto>>> GetProducts(
|
||||||
|
[FromQuery] int pageNumber = 1,
|
||||||
|
[FromQuery] int pageSize = 10,
|
||||||
|
[FromQuery] string? searchTerm = null,
|
||||||
|
[FromQuery] Guid? categoryId = null,
|
||||||
|
[FromQuery] decimal? minPrice = null,
|
||||||
|
[FromQuery] decimal? maxPrice = null,
|
||||||
|
[FromQuery] bool? isActive = true,
|
||||||
|
[FromQuery] bool? isCustomizable = null,
|
||||||
|
[FromQuery] string sortBy = "Name",
|
||||||
|
[FromQuery] string sortDirection = "ASC")
|
||||||
|
{
|
||||||
|
var filterParameters = new ProductFilterParameters
|
||||||
|
{
|
||||||
|
PageNumber = pageNumber,
|
||||||
|
PageSize = pageSize,
|
||||||
|
SearchTerm = searchTerm,
|
||||||
|
CategoryId = categoryId,
|
||||||
|
MinPrice = minPrice,
|
||||||
|
MaxPrice = maxPrice,
|
||||||
|
IsActive = isActive,
|
||||||
|
IsCustomizable = isCustomizable,
|
||||||
|
SortBy = sortBy,
|
||||||
|
SortDirection = sortDirection
|
||||||
|
};
|
||||||
|
|
||||||
|
var query = new GetProductsQuery { FilterParameters = filterParameters };
|
||||||
|
var result = await mediator.Send(query);
|
||||||
|
|
||||||
|
return Ok(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<ActionResult<ProductDto>> CreateProduct([FromBody] CreateProductCommand command)
|
||||||
|
{
|
||||||
|
var result = await mediator.Send(command);
|
||||||
|
return CreatedAtAction(nameof(CreateProduct), new { id = result.Id }, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete("{id:guid}")]
|
||||||
|
public async Task<ActionResult> DeleteProduct(Guid id)
|
||||||
|
{
|
||||||
|
var command = new DeleteProductCommand { Id = id };
|
||||||
|
var result = await mediator.Send(command);
|
||||||
|
|
||||||
|
if (!result)
|
||||||
|
return NotFound();
|
||||||
|
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,12 @@
|
|||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Printbase.Application;
|
||||||
using Printbase.Application.Products.Handlers;
|
using Printbase.Application.Products.Handlers;
|
||||||
using Printbase.Domain.Entities.Users;
|
using Printbase.Domain.Entities.Users;
|
||||||
|
using Printbase.Domain.Repositories;
|
||||||
|
using Printbase.Infrastructure;
|
||||||
using Printbase.Infrastructure.Database;
|
using Printbase.Infrastructure.Database;
|
||||||
|
using Printbase.Infrastructure.Repositories;
|
||||||
|
|
||||||
namespace Printbase.WebApi;
|
namespace Printbase.WebApi;
|
||||||
|
|
||||||
@@ -12,6 +16,11 @@ public static class Startup
|
|||||||
{
|
{
|
||||||
var services = builder.Services;
|
var services = builder.Services;
|
||||||
|
|
||||||
|
services.AddScoped<IProductRepository, ProductRepository>();
|
||||||
|
services.AddScoped<IProductVariantRepository, ProductVariantRepository>();
|
||||||
|
services.AddScoped<ICategoryRepository, CategoryRepository>();
|
||||||
|
services.AddScoped<IUnitOfWork, UnitOfWork>();
|
||||||
|
|
||||||
services.AddDbContext<ApplicationDbContext>(options =>
|
services.AddDbContext<ApplicationDbContext>(options =>
|
||||||
options.UseSqlServer(
|
options.UseSqlServer(
|
||||||
builder.Configuration.GetConnectionString("DefaultConnection"),
|
builder.Configuration.GetConnectionString("DefaultConnection"),
|
||||||
@@ -67,6 +76,9 @@ public static class Startup
|
|||||||
policy.RequireRole("Administrator", "ProductManager"))
|
policy.RequireRole("Administrator", "ProductManager"))
|
||||||
.AddPolicy("CustomerPolicy", policy =>
|
.AddPolicy("CustomerPolicy", policy =>
|
||||||
policy.RequireRole("Customer", "Administrator", "OrderManager", "ProductManager"));
|
policy.RequireRole("Customer", "Administrator", "OrderManager", "ProductManager"));
|
||||||
|
|
||||||
|
services.AddControllers();
|
||||||
|
services.AddSwaggerGen();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
public static void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||||
@@ -86,18 +98,22 @@ public static class Startup
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (env.IsDevelopment())
|
// if (env.IsDevelopment())
|
||||||
{
|
// {
|
||||||
app.UseSwagger();
|
// app.UseSwagger();
|
||||||
app.UseSwaggerUI();
|
// app.UseSwaggerUI();
|
||||||
app.UseDeveloperExceptionPage();
|
// app.UseDeveloperExceptionPage();
|
||||||
}
|
// }
|
||||||
else
|
// else
|
||||||
{
|
// {
|
||||||
app.UseExceptionHandler("/Error");
|
// app.UseExceptionHandler("/Error");
|
||||||
app.UseHsts();
|
// app.UseHsts();
|
||||||
app.UseHttpsRedirection();
|
// app.UseHttpsRedirection();
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
app.UseSwagger();
|
||||||
|
app.UseSwaggerUI();
|
||||||
|
app.UseDeveloperExceptionPage();
|
||||||
|
|
||||||
app.UseRouting();
|
app.UseRouting();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user