using Infrastructure.Attribute; using SqlSugar; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using ARW.Model; using ARW.Repository; using ARW.Repository.Business.GoodsManager.Goodss; using ARW.Service.Api.IBusinessService.GoodsManager.Goodss; using ARW.Model.Dto.Api.GoodsManager.Goodss; using ARW.Model.Models.Business.GoodsManager.Goodss; using ARW.Model.Vo.Api.GoodsManager.Goodss; using ARW.Model.Models.Business.ShopManager.Shops; using ARW.Repository.Business.GoodsManager.GoodsSpecs.GoodsSpecRels; using ARW.Repository.Business.GoodsManager.GoodsSpecs.Specs; using ARW.Repository.Business.GoodsManager.GoodsSpecs.SpecValues; using Newtonsoft.Json; using Senparc.CO2NET.Extensions; using ARW.Model.Models.Business.GoodsManager.GoodsSpecs.GoodsSkus; using ARW.Repository.Business.GoodsManager.GoodsSpecs.GoodsSkus; using ARW.Model.Models.Business.GoodsManager.GoodsCategorys; using ARW.Repository.Business.GoodsManager.GoodsCategorys; using System; using ARW.Common; using Microsoft.AspNetCore.Components.Forms; using ARW.Repository.Business.LogisticsManage.Deliverys; using ARW.Repository.Business.Custom.CustomerAddresses; using ARW.Repository.Business.LogisticsManage.DeliveryRules; using Infrastructure; using ARW.Model.Models.Business.LogisticsManage.DeliveryRules; using ARW.Model.Vo.Business.GoodsManager.Goodss; namespace ARW.Service.Api.BusinessService.GoodsManager.Goodss { /// /// 商品接口实现类Api /// /// @author lwh /// @date 2023-07-09 /// [AppService(ServiceType = typeof(IGoodsServiceApi), ServiceLifetime = LifeTime.Transient)] public class GoodsServiceImplApi : BaseService, IGoodsServiceApi { private readonly GoodsRepository _GoodsRepository; private readonly GoodsSpecRelRepository _GoodsSpecRelRepository; private readonly SpecRepository _SpecRepository; private readonly SpecValueRepository _SpecValueRepository; private readonly GoodsSkuRepository _GoodsSkuRepository; private readonly GoodsCategoryRepository _GoodsCategoryRepository; private readonly DeliveryRepository _DeliveryRepository; private readonly DeliveryRuleRepository _DeliveryRuleRepository; private readonly CustomerAddressRepository _CustomerAddressRepository; public GoodsServiceImplApi(GoodsRepository GoodsRepository, GoodsSpecRelRepository goodsSpecRelRepository, SpecRepository specRepository, SpecValueRepository specValueRepository, GoodsSkuRepository goodsSkuRepository, GoodsCategoryRepository goodsCategoryRepository, DeliveryRepository deliveryRepository, CustomerAddressRepository customerAddressRepository, DeliveryRuleRepository deliveryRuleRepository) { this._GoodsRepository = GoodsRepository; _GoodsSpecRelRepository = goodsSpecRelRepository; _SpecRepository = specRepository; _SpecValueRepository = specValueRepository; _GoodsSkuRepository = goodsSkuRepository; _GoodsCategoryRepository = goodsCategoryRepository; _DeliveryRepository = deliveryRepository; _CustomerAddressRepository = customerAddressRepository; _DeliveryRuleRepository = deliveryRuleRepository; } #region Api接口代码 /// /// 查询商品列表(Api) /// /// /// public async Task> GetGoodsListApi(GoodsQueryDtoApi parm) { //开始拼装查询条件 var predicate = Expressionable.Create(); string[] goodsCategoryArr = null; // 检索经营类目 //if (parm.GoodsCategoryGuid != null) //{ // var data = await _GoodsCategoryRepository.GetListAsync(); // var SewGoodsCategorys = data.FindAll(delegate (GoodsCategory goodsCategory) // { // string[] parentGoodsCategoryId = goodsCategory.GoodsCategoryAncestralGuid.Split(",", StringSplitOptions.RemoveEmptyEntries); // return parentGoodsCategoryId.Contains(parm.GoodsCategoryGuid.ToString()); // }); // goodsCategoryArr = SewGoodsCategorys.Select(s => s.GoodsCategoryGuid.ToString()).ToArray(); //} predicate = predicate.AndIF(parm.ShopGuid != null, s => s.ShopGuid == parm.ShopGuid); predicate = predicate.AndIF(parm.ShopGoodsCategoryGuid != 0, s => s.ShopGoodsCategoryGuid == parm.ShopGoodsCategoryGuid); predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.GoodsName), s => s.GoodsName.Contains(parm.GoodsName)); predicate = predicate.AndIF(!string.IsNullOrEmpty(parm.GoodsCoding), s => s.GoodsCoding.Contains(parm.GoodsCoding)); predicate = predicate.AndIF(parm.MinPrice != 0, s => s.GoodsPriceLowest >= parm.MinPrice); predicate = predicate.AndIF(parm.MaxPrice != 0, s => s.GoodsPriceLowest <= parm.MaxPrice); var sortType = OrderByType.Asc; if (parm.GoodsSortType == 1) sortType = OrderByType.Desc; var query = _GoodsRepository .Queryable() .LeftJoin((s, c) => s.ShopGuid == c.ShopGuid) .Where(predicate.ToExpression()) .WhereIF(parm.GoodsCategoryGuid != 0, (s, c) => c.ShopBusinessCategoryGuid == parm.GoodsCategoryGuid) //.WhereIF(parm.GoodsCategoryGuid != null, (s, c) => c.ShopBusinessCategoryGuid == parm.GoodsCategoryGuid || goodsCategoryArr.Contains(c.ShopBusinessCategoryGuid.ToString())) .Where(s => s.GoodsShelfStatus == 1) .OrderByIF(parm.GoodsSort == 0, s => s.GoodsSort, OrderByType.Asc) .OrderByIF(parm.GoodsSort == 1, s => s.GoodsPriceLowest, sortType) .OrderByIF(parm.GoodsSort == 2, s => s.GoodsSalesInitial + s.GoodsSalesActual, sortType) //.OrderBy(s => s.GoodsSort, OrderByType.Desc) .Select((s, c) => new GoodsVoApi { SpuId = s.GoodsGuid, ShopGuid = s.ShopGuid, ShopName = c.ShopName, CategoryIds = s.ShopGoodsCategoryGuid, Title = s.GoodsName, GoodsCoding = s.GoodsCoding, Video = s.GoodsMainImageVideo, PrimaryImage = s.GoodsVideoCover, Images = s.GoodsPicture, Price = s.GoodsPriceLowest, OriginPrice = s.GoodsDashedPriceLowest, SpuStockQuantity = s.GoodsTotalInventory, SoldNum = s.GoodsSalesInitial + s.GoodsSalesActual, IsPutOnSale = s.GoodsShelfStatus, }); return await query.ToPageAsync(parm); } /// /// 查询商品列表(Api) /// /// /// public async Task> GetGoodsApi(GoodsQueryDtoApi parm) { //开始拼装查询条件 var predicate = Expressionable.Create(); predicate = predicate.AndIF(parm.ShopGoodsCategoryGuid != 0, s => s.ShopGoodsCategoryGuid == parm.ShopGoodsCategoryGuid); var query = _GoodsRepository .Queryable() .LeftJoin((s, c) => s.ShopGuid == c.ShopGuid) .Where(predicate.ToExpression()) .Where(s => s.GoodsShelfStatus == 1) .OrderBy(s => s.GoodsSort, OrderByType.Asc) .Select((s, c) => new GoodsVoApi { SpuId = s.GoodsGuid, ShopGuid = s.ShopGuid, ShopName = c.ShopName, CategoryIds = s.ShopGoodsCategoryGuid, Title = s.GoodsName, GoodsCoding = s.GoodsCoding, Video = s.GoodsMainImageVideo, PrimaryImage = s.GoodsVideoCover, Images = s.GoodsPicture, Price = s.GoodsPriceLowest, OriginPrice = s.GoodsDashedPriceLowest, SpuStockQuantity = s.GoodsTotalInventory, SoldNum = s.GoodsSalesInitial + s.GoodsSalesActual, IsPutOnSale = s.GoodsShelfStatus, }); var list = await query.ToListAsync(); foreach (var item in list) { item.Thumb = item.Images.Split(',').First(); } return list; } /// /// 获取商品运费(Api) /// /// /// public async Task GetGoodsFreight(GoodsFreightDto parm) { decimal freight = 0; foreach (var item in parm.GoodsRequestList) { var goods = await _GoodsRepository.GetFirstAsync(s => s.GoodsGuid == item.SpuId); var delivery = await _DeliveryRepository.GetFirstAsync(s => s.DeliveryGuid == goods.DeliveryGuid); var deliveRule = await _DeliveryRuleRepository.GetFirstAsync(s => s.DeliveryGuid == delivery.DeliveryGuid); var adress = await _CustomerAddressRepository.GetFirstAsync(s => s.CustomerAddressGuid == parm.CustomerAddressGuid); // 判断是否在配送范围 var regionIdList = Tools.SpitIntArrary(deliveRule.DeliveryRuleRegion).ToList(); if (regionIdList.Contains(adress.CustomerAddressCityId)) { // 判断是否免运费 if (deliveRule.DeliveryRuleFirstFee == 0) return freight; // 按件计费 if (delivery.DeliveryBillingMethod == 1) { freight += CalculateFreight(item.Quantity, deliveRule); } // 按重量计费 if (delivery.DeliveryBillingMethod == 2) { // 是否有sku if (item.SkuId != 0) { var sku = await _GoodsSkuRepository.GetFirstAsync(s => s.GoodsSkuId == item.SkuId); if (sku == null) return freight; var skuWeight = sku.GoodsSkuWeight * item.Quantity; freight += CalculateFreight(skuWeight, deliveRule); } else { var allWeight = goods.GoodsWeight * item.Quantity; freight += CalculateFreight(allWeight, deliveRule); } } } else { throw new CustomException($"{goods.GoodsName} 不在配送范围内"); } } return Math.Round(freight, 2); ; } /// /// 查询商品详情(Api) /// /// /// public async Task GetGoodsDetails(GoodsDtoApi parm) { var query = _GoodsRepository .Queryable() .LeftJoin((s, c) => s.ShopGuid == c.ShopGuid) .Where(s => s.GoodsGuid == parm.SpuId) .Select((s, c) => new GoodsApiDetailsVo { SpuId = s.GoodsGuid, ShopGuid = s.ShopGuid, ShopLogo = c.ShopLogo, ShopName = c.ShopName, ShopSalesOrderCount = c.ShopSalesOrderCount, ShopIntro = c.ShopIntro, CategoryIds = s.ShopGoodsCategoryGuid, Title = s.GoodsName, GoodsCoding = s.GoodsCoding, Video = s.GoodsMainImageVideo, PrimaryImage = s.GoodsVideoCover, Images = s.GoodsPicture, MinSalePrice = s.GoodsPriceLowest, MaxSalePrice = s.GoodsPriceHighest, MaxLinePrice = s.GoodsDashedPriceHighest, SpuStockQuantity = s.GoodsTotalInventory, SoldNum = s.GoodsSalesInitial + s.GoodsSalesActual, Desc = s.GoodsDetails, IsPutOnSale = s.GoodsShelfStatus, GoodsSellingPoint = s.GoodsSellingPoint }).Take(1); var json = await query.ToJsonAsync(); var data = await GetSpecList(json); return data; } /// /// 获取商品的规格组列表 /// /// /// public async Task GetSpecList(string json) { if (json != "[]") { json = json.Remove(0, 1); json = json.Substring(0, json.Length - 1); var data = JsonConvert.DeserializeObject(json); var goodsSpecListVo = new List(); var specIds = (await _GoodsSpecRelRepository.GetListAsync(s => s.GoodsGuid == data.SpuId)) .Select(item => item.SpecId) .Distinct() .ToList(); var specs = await _SpecRepository.GetListAsync(s => specIds.Contains(s.SpecId)); var specValueIds = (await _GoodsSpecRelRepository.GetListAsync(s => s.GoodsGuid == data.SpuId)) .Where(item => item.SpecValueId != 0) .Select(item => item.SpecValueId) .Distinct() .ToList(); var specValues = await GetSpecValuesAsync(specValueIds); foreach (var spec in specs) { var goodsSpecVo = new GoodsSpecApiVo { SpecId = spec.SpecId, Title = spec.SpecName, SpecValueList = new List() }; goodsSpecVo.SpecValueList.AddRange(specValues.Where(sv => sv.SpecId == spec.SpecId)); goodsSpecListVo.Add(goodsSpecVo); } // 获取Sku列表 var skuList = await _GoodsSkuRepository.GetListAsync(s => s.GoodsGuid == data.SpuId); data.SkuList = await GetSkuListWithSpecValuesAsync(skuList); data.SpecList = goodsSpecListVo; json = data.ToJson(); } return json; } /// /// 获取商品规格值列表 /// /// /// private async Task> GetSpecValuesAsync(List specValueIds) { var specValues = await _SpecValueRepository.GetListAsync(sv => specValueIds.Contains(sv.SpecValueId)); return specValues.Select(sv => new SpecValueApiVo { SpecValueId = sv.SpecValueId, SpecId = sv.SpecId, SpecValue = sv.SpecValueName, }).ToList(); } /// /// 获取商品sku列表 /// /// /// private async Task> GetSkuListWithSpecValuesAsync(List skuList) { var resList = new List(); var specValueIds = skuList.SelectMany(sku => new[] { sku.SpecValueId, sku.SpecSecondValueId, sku.SpecThirdValueId }) .Distinct() .Where(id => id != 0) .ToList(); // sku所属商品规格 var specValues = await GetSpecValuesAsync(specValueIds); var addedSpecValueIds = new HashSet(); foreach (var item in skuList) { var list = new List(); await AddSkuSpecInfo(item.SpecValueId); await AddSkuSpecInfo(item.SpecSecondValueId); await AddSkuSpecInfo(item.SpecThirdValueId); async Task AddSkuSpecInfo(int specValueId) { if (specValueId != 0) { //addedSpecValueIds.Add(specValueId); var sku = specValues.FirstOrDefault(sv => sv.SpecValueId == specValueId); var spec = await _SpecRepository.GetFirstAsync(s => s.SpecId == sku.SpecId); var skuSpecInfo = new SkuSpecInfo { SpecId = sku.SpecId, SpecTitle = spec.SpecName, SpecValueId = sku.SpecValueId, SpecValue = sku.SpecValue }; list.Add(skuSpecInfo); } } // sku价格 var skuPriceInfoList = new List(); var skuPriceInfo1 = new PriceInfo { PriceType = 1, Price = item.GoodsSkuPrice, PriceTypeName = "销售价格" }; skuPriceInfoList.Add(skuPriceInfo1); if (item.GoodsSkuLinePrice != 0) { var skuPriceInfo2 = new PriceInfo { PriceType = 2, Price = item.GoodsSkuLinePrice, PriceTypeName = "划线价格" }; skuPriceInfoList.Add(skuPriceInfo2); } var skuVo = new GoosSkuApiVo { SkuId = item.GoodsSkuId, SkuImage = item.GoodsSkuImg, SpecInfo = list, PriceInfo = skuPriceInfoList, Quantity = item.GoodsSkuStockNum, Weight = item.GoodsSkuWeight }; resList.Add(skuVo); } return resList; } /// /// 计算运费 /// /// /// /// public decimal CalculateFreight(decimal parm, DeliveryRule deliveRule) { decimal freight = 0; // 是否超过首件/首重 if (parm >= deliveRule.DeliveryRuleFirst) { freight += deliveRule.DeliveryRuleFirstFee; if (parm > deliveRule.DeliveryRuleFirst) { var additionalCount = parm - deliveRule.DeliveryRuleFirst; var additionalFee = additionalCount / deliveRule.DeliveryRuleAdditional * deliveRule.DeliveryRuleAdditionalFee; freight += additionalFee; } } return freight; } #endregion } }