Files
StopShopping/StopShopping.Services/Implementions/ProductService.cs
2026-03-30 11:07:30 +08:00

191 lines
6.9 KiB
C#

using Microsoft.EntityFrameworkCore;
using StopShopping.EF;
using StopShopping.Services.Models.Req;
using StopShopping.Services.Models.Resp;
namespace StopShopping.Services.Implementions;
public class ProductService : IProductService
{
public ProductService(
StopShoppingContext dbContext,
IClaimsService claimsService,
IFileService fileService,
ISerialNoGenerator serialNoGenerator)
{
_dbContext = dbContext;
_claimsService = claimsService;
_fileService = fileService;
_serilNoGenerator = serialNoGenerator;
}
private readonly StopShoppingContext _dbContext;
private readonly IClaimsService _claimsService;
private readonly IFileService _fileService;
private readonly ISerialNoGenerator _serilNoGenerator;
public ApiResponse<ProductInfo> Detail(ProductIdParams model)
{
var detail = _dbContext.Products
.AsNoTracking()
.Where(p => p.Id == model.ProductId && !p.Deleted)
.Include(p => p.Category)
.Select(Cast<ProductInfo>)
.FirstOrDefault();
if (null == detail)
return new ApiResponse<ProductInfo>().Failed("商品已不存在,请刷新重试");
return new ApiResponse<ProductInfo>(detail);
}
public async Task<ApiResponse<PagedResult<Product>>> SearchAsync(ProductSearchParms model)
{
var userId = _claimsService.GetCurrentUserId();
var qry = _dbContext.Products
.AsNoTracking()
.Include(p => p.Category)
.Where(p => !p.Deleted);
if (userId.HasValue)
qry = qry.Where(p => p.UserId == userId);
if (model.CategoryId > 0)
{
var categoryPath = (await _dbContext.Categories
.FirstOrDefaultAsync(c1 => c1.Id == model.CategoryId))
?.Path ?? "";
qry = qry.Where(p =>
_dbContext.Categories
.Where(c => c.Path.StartsWith(categoryPath))
.Select(c => c.Id)
.Contains(p.CategoryId));
}
if (!string.IsNullOrWhiteSpace(model.Keyword))
qry = qry.Where(p =>
p.Name.Contains(model.Keyword)
|| (p.Description != null && p.Description.Contains(model.Keyword)));
var orderedQry = WithOrderBys(qry, model.OrderBys);
var result = await orderedQry!
.Select(Cast<Product>)
.ToAsyncEnumerable()
.ToPagedAsync(model.PageIndex, model.PageSize);
return new ApiResponse<PagedResult<Product>>(result);
}
public async Task<ApiResponse> EditAsync(EditProductParams model)
{
var userId = _claimsService.GetCurrentUserId()!.Value;
EF.Models.Product? product = null;
if (model.Id > 0)
{
product = await _dbContext.Products
.FirstOrDefaultAsync(p =>
p.Id == model.Id.Value
&& p.UserId == userId
&& !p.Deleted);
if (null == product)
return ApiResponse.Failed("商品已不存在,请刷新重试");
}
else
{
product = new()
{
SerialNo = _serilNoGenerator.GenerateProductNo(),
UserId = userId,
Logo = string.IsNullOrWhiteSpace(model.LogoName)
? Consts.DEFAULT_PRODUCT
: model.LogoName
};
await _dbContext.Products.AddAsync(product);
}
product.CategoryId = model.CategoryId;
product.Description = model.Description;
product.Detail = model.Detail;
product.MinimumUnit = model.MinimumUnit ?? "";
product.Name = model.Name ?? "";
product.UnitPrice = model.UnitPrice;
await _dbContext.SaveChangesAsync();
return ApiResponse.Succed();
}
public async Task<ApiResponse> DeleteAsync(ProductIdParams model)
{
var userId = _claimsService.GetCurrentUserId()!.Value;
var product = await _dbContext.Products
.FirstOrDefaultAsync(p =>
p.Id == model.ProductId
&& p.UserId == userId
&& !p.Deleted);
if (null == product)
return ApiResponse.Failed("此商品已不存在,请刷新重试");
product.Deleted = true;
await _dbContext.SaveChangesAsync();
return ApiResponse.Succed();
}
#region private methods
private IOrderedQueryable<EF.Models.Product>? WithOrderBys(IQueryable<EF.Models.Product> qry, IEnumerable<ProductOrderBys> orderBys)
{
IOrderedQueryable<EF.Models.Product>? orderedQry = null;
foreach (var orderby in orderBys)
{
if (null == orderedQry)
orderedQry = orderby switch
{
ProductOrderBys.CreateTime => qry.OrderBy(p => p.CreateTime),
ProductOrderBys.CreateTimeDesc => qry.OrderByDescending(p => p.CreateTime),
ProductOrderBys.Category => qry.OrderBy(p => p.Category),
ProductOrderBys.CategoryDesc => qry.OrderByDescending(p => p.Category),
ProductOrderBys.SoldAmount => qry.OrderBy(p => p.SoldAmount),
ProductOrderBys.SoldAmountDesc => qry.OrderByDescending(p => p.SoldAmount),
_ => qry.OrderBy(p => p.CreateTime),
};
else
orderedQry = orderby switch
{
ProductOrderBys.CreateTime => orderedQry.ThenBy(p => p.CreateTime),
ProductOrderBys.CreateTimeDesc => orderedQry.ThenByDescending(p => p.CreateTime),
ProductOrderBys.Category => orderedQry.ThenBy(p => p.Category),
ProductOrderBys.CategoryDesc => orderedQry.ThenByDescending(p => p.Category),
ProductOrderBys.SoldAmount => orderedQry.ThenBy(p => p.SoldAmount),
ProductOrderBys.SoldAmountDesc => orderedQry.ThenByDescending(p => p.SoldAmount),
_ => orderedQry.ThenBy(p => p.CreateTime),
};
}
return orderedQry;
}
private T Cast<T>(EF.Models.Product product)
where T : Product, new()
{
var result = new T
{
CategoryName = product.Category.Name,
CreateTime = product.CreateTime.ToFormatted(),
Description = product.Description,
Id = product.Id,
LogoUrl = _fileService.GetFileUrl(Models.UploadScences.Product, product.Logo),
MinimumUnit = product.MinimumUnit,
Name = product.Name,
UnitPrice = product.UnitPrice,
SoldAmount = product.SoldAmount,
};
if (result is ProductInfo)
{
(result as ProductInfo)!.CategoryId = product.CategoryId;
(result as ProductInfo)!.Detail = product.Detail;
}
return result;
}
#endregion
}