193 lines
7.0 KiB
C#
193 lines
7.0 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 && 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();
|
|
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();
|
|
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,
|
|
MinimumUnit = product.MinimumUnit,
|
|
Name = product.Name,
|
|
UnitPrice = product.UnitPrice,
|
|
SoldAmount = product.SoldAmount,
|
|
LogoUrl = _fileService.GetFileUrl(Models.UploadScences.Product, product.Logo)
|
|
};
|
|
if (result is ProductInfo)
|
|
{
|
|
(result as ProductInfo)!.CategoryId = product.CategoryId;
|
|
(result as ProductInfo)!.Detail = product.Detail;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private string BuildCategoryPath(int categoryId)
|
|
{
|
|
return $"/{categoryId}/";
|
|
}
|
|
|
|
#endregion
|
|
} |