diff --git a/BBWYB.Common/Extensions/ConverterExtensions.cs b/BBWYB.Common/Extensions/ConverterExtensions.cs new file mode 100644 index 0000000..2bc884e --- /dev/null +++ b/BBWYB.Common/Extensions/ConverterExtensions.cs @@ -0,0 +1,17 @@ +namespace BBWYB.Common.Extensions +{ + public static class ConverterExtensions + { + public static long? ToInt64(this object? o) + { + try + { + return Convert.ToInt64(o); + } + catch + { + return null; + } + } + } +} diff --git a/BBWYB.Server.Business/PurchaseScheme/PurchaseSchemeBusiness.cs b/BBWYB.Server.Business/PurchaseScheme/PurchaseSchemeBusiness.cs index a51173d..c83d183 100644 --- a/BBWYB.Server.Business/PurchaseScheme/PurchaseSchemeBusiness.cs +++ b/BBWYB.Server.Business/PurchaseScheme/PurchaseSchemeBusiness.cs @@ -16,6 +16,8 @@ namespace BBWYB.Server.Business private PurchaseProductAPIService purchaseProductAPIService; private RestApiService restApiService; + private IList invalidOrderStateList; + public PurchaseSchemeBusiness(IFreeSql fsql, NLogManager nLogManager, IIdGenerator idGenerator, @@ -24,6 +26,7 @@ namespace BBWYB.Server.Business { this.purchaseProductAPIService = purchaseProductAPIService; this.restApiService = restApiService; + this.invalidOrderStateList = new List() { Enums.OrderState.待付款, Enums.OrderState.已取消 }; } private void ExtractNewPurchaser(IList purchaserSchemeList, IList addPurchaserList) where T : InputPurchaseSchemeRequest @@ -392,6 +395,7 @@ namespace BBWYB.Server.Business psReq.SchemeGroupId = newPurchaseGroupId; var defaultCost = 0M; decimal? bargainingCost = null; + var isContainsActualPrice = psReq.PurchaseSchemeProductList.Any(pspReq => pspReq.PurchaseSchemeProductSkuList.Any(pssReq => pssReq.ActualPrice != null)); var ps = new PurchaseScheme() { CreateTime = DateTime.Now, @@ -423,11 +427,13 @@ namespace BBWYB.Server.Business //ps.DefaultCost += ((pssReq.ActualPrice ?? pssReq.DefaultPrice) ?? 0) * (pssReq.PurchaseRatio ?? 1); defaultCost += pssReq.DefaultPrice ?? 0; - if (pssReq.ActualPrice != null && pssReq.ActualPrice > 0M) + if (isContainsActualPrice) { if (bargainingCost == null) bargainingCost = 0M; bargainingCost += ((pssReq.ActualPrice ?? pssReq.DefaultPrice) ?? 0) * (pssReq.PurchaseRatio ?? 1); + if (pssReq.ActualPrice != null && pssReq.ActualPrice > 0) + pss.LastBargainingTime = DateTime.Now; } #region 处理历史版本 @@ -450,6 +456,8 @@ namespace BBWYB.Server.Business ps.DefaultCost = defaultCost; ps.BargainingCost = bargainingCost; + if (bargainingCost != null) + ps.LastBargainingTime = DateTime.Now; var historyPs = ps.Map(); historyPs.HistoryId = idGenerator.NewLong(); insertHistoryPSList.Add(historyPs); @@ -462,7 +470,15 @@ namespace BBWYB.Server.Business { ExtractNewPurchaser(batchCURDSchemeRequest.EditPurchaseSchemeList, newPurchaserList); var editSchemeIdList = batchCURDSchemeRequest.EditPurchaseSchemeList.Select(ps => ps.Id).ToList(); - List dbPurchaseSchemes = fsql.Select().Where(ps => editSchemeIdList.Contains(ps.Id)).ToList(); + var dbPurchaseSchemes = GetPurchaseSchemeList(new QuerySchemeRequest() + { + SchemeIdList = editSchemeIdList, + IncludePurchaseSkuBasicInfo = 0, + IncludeSkuStatisticsInfo = 0 + }); + var dbPssList = dbPurchaseSchemes.SelectMany(ps => ps.PurchaseSchemeProductList.SelectMany(psp => psp.PurchaseSchemeProductSkuList)); + + //List dbPurchaseSchemes = fsql.Select().Where(ps => editSchemeIdList.Contains(ps.Id)).ToList(); deletePartsSchemeIdList.AddRange(batchCURDSchemeRequest.EditPurchaseSchemeList.Select(ps => ps.Id)); foreach (var psReq in batchCURDSchemeRequest.EditPurchaseSchemeList) @@ -474,6 +490,7 @@ namespace BBWYB.Server.Business var newVersion = dbps.Version + 1; //采购方案版本 var defaultCost = 0M; decimal? bargainingCost = null; //只有当任意配件包含议价成本时才具备此值 + var isContainsActualPrice = psReq.PurchaseSchemeProductList.Any(pspReq => pspReq.PurchaseSchemeProductSkuList.Any(pssReq => pssReq.ActualPrice != null)); foreach (var pspReq in psReq.PurchaseSchemeProductList) { var psp = pspReq.Map(); @@ -488,14 +505,19 @@ namespace BBWYB.Server.Business pss.Id = idGenerator.NewLong(); pss.CreateTime = DateTime.Now; pss.SkuPurchaseSchemeId = schemeId; + var dbPss = dbPssList.FirstOrDefault(x => x.SkuId == pssReq.SkuId && x.PurchaseSkuId == pssReq.PurchaseSkuId && x.SkuPurchaseSchemeId == schemeId); + pss.LastBargainingTime = dbPss?.LastBargainingTime; addPurchaseSchemeProductSkuList.Add(pss); - //defaultCost += ((pssReq.ActualPrice ?? pssReq.DefaultPrice) ?? 0) * (pssReq.PurchaseRatio ?? 1); + defaultCost += pssReq.DefaultPrice ?? 0; - if (pssReq.ActualPrice != null && pssReq.ActualPrice > 0M) + if (isContainsActualPrice) { if (bargainingCost == null) bargainingCost = 0M; bargainingCost += ((pssReq.ActualPrice ?? pssReq.DefaultPrice) ?? 0) * (pssReq.PurchaseRatio ?? 1); + + if (pssReq.ActualPrice != null && pssReq.ActualPrice > 0M && dbPss != null && dbPss.ActualPrice != pssReq.ActualPrice) + pss.LastBargainingTime = DateTime.Now; } #region 处理历史版本 @@ -520,6 +542,7 @@ namespace BBWYB.Server.Business var psupdate = fsql.Update(schemeId) .Set(ps => ps.DefaultCost, defaultCost) .Set(ps => ps.BargainingCost, bargainingCost) + .SetIf(bargainingCost != null && bargainingCost != dbps.BargainingCost, ps => ps.LastBargainingTime, DateTime.Now) .Set(ps => ps.HYSchemeId, psReq.HYSchemeId) .Set(ps => ps.HYBDId, psReq.HYBDId) .Set(ps => ps.Version, newVersion); @@ -645,6 +668,9 @@ namespace BBWYB.Server.Business if (purchaseSchemeList.Count > 0) { var purchaseSchemeIdList = purchaseSchemeList.Select(p => p.Id).ToList(); + var spuIdList = purchaseSchemeList.Select(ps => ps.ProductId).Distinct().ToList(); + var skuIdList = purchaseSchemeList.Select(ps => ps.SkuId).Distinct().ToList(); + var recentDate = DateTime.Now.Date.AddDays(-30); var purchaseSchemeProductList = fsql.Select() .InnerJoin((psp, p) => psp.PurchaserId == p.Id) @@ -671,6 +697,62 @@ namespace BBWYB.Server.Business var purchaseSchemeProductSkuList = fsql.Select().Where(p => purchaseSchemeIdList.Contains(p.SkuPurchaseSchemeId)) .ToList().Map>(); + if (request.IncludeSkuStatisticsInfo == 1) + { + var recent30daySpuItemCountGroups = fsql.Select() + .LeftJoin((osku, o) => osku.OrderId == o.Id) + .Where((osku, o) => spuIdList.Contains(osku.ProductId) && + !invalidOrderStateList.Contains(o.OrderState) && + o.StartTime >= recentDate) + .GroupBy((osku, o) => osku.ProductId) + .ToList(g => new + { + ProductId = g.Key, + ItemTotal = g.Sum(g.Value.Item1.ItemTotal) + }); + + var recent30daySkuItemCountGroups = fsql.Select() + .LeftJoin((osku, o) => osku.OrderId == o.Id) + .Where((osku, o) => skuIdList.Contains(osku.SkuId) && + !invalidOrderStateList.Contains(o.OrderState) && + o.StartTime >= recentDate) + .GroupBy((osku, o) => osku.SkuId) + .ToList(g => new + { + SkuId = g.Key, + ItemTotal = g.Sum(g.Value.Item1.ItemTotal) + }); + + //sku最近使用的采购方案 + var skuRecentPurchaseList = fsql.Select() + .Where(ps => skuIdList.Contains(ps.SkuId)) + .GroupBy(ps => ps.SkuId) + .WithTempQuery(g => new { SkuId = g.Key, MaxTime = g.Max(g.Value.LastPurchaseTime) }) + .From() + .InnerJoin((ps1, ps2) => ps1.SkuId == ps2.SkuId && ps1.MaxTime == ps2.LastPurchaseTime) + .ToList((ps1, ps2) => new + { + SkuId = ps2.SkuId, + LastPurchaseTime = ps2.LastPurchaseTime, + LastPurchasePriceCost = ps2.LastPurchasePriceCost + }); + + foreach (var scheme in purchaseSchemeList) + { + #region 近30天spu/sku销量 + scheme.Recent30DaySpuItemCount = Convert.ToInt64(recent30daySpuItemCountGroups.FirstOrDefault(x => x.ProductId == scheme.ProductId)?.ItemTotal ?? 0); + scheme.Recent30DaySkuItemCount = Convert.ToInt64(recent30daySkuItemCountGroups.FirstOrDefault(x => x.SkuId == scheme.SkuId)?.ItemTotal ?? 0); + #endregion + + #region sku最近采购价和最近采购时间 + var recentScheme = skuRecentPurchaseList.FirstOrDefault(x => x.SkuId == scheme.SkuId); + scheme.SkuLastPurchasePriceCost = recentScheme?.LastPurchasePriceCost; + scheme.SkuLastPurchaseTime = recentScheme?.LastPurchaseTime; + #endregion + } + } + + foreach (var scheme in purchaseSchemeList) { var schemeProductList = purchaseSchemeProductList.Where(ps => ps.SkuPurchaseSchemeId == scheme.Id); @@ -1092,7 +1174,9 @@ namespace BBWYB.Server.Business if (schemeList.Count() == 0) throw new BusinessException("采购方案不存在"); var scheme = schemeList[0]; + var isContainsActualPrice = scheme.PurchaseSchemeProductList.Any(pspReq => pspReq.PurchaseSchemeProductSkuList.Any(pssReq => pssReq.ActualPrice != null)); var defaultCost = 0M; + decimal? bargainingCost = null; long? pssId = null; foreach (var schemeProduct in scheme.PurchaseSchemeProductList) { @@ -1104,14 +1188,23 @@ namespace BBWYB.Server.Business tartegtPurchaseProductSku.PurchaseRatio = request.Ratio; pssId = tartegtPurchaseProductSku.Id; } + if (pssId == null) + throw new BusinessException("未找到需要更新的采购配件"); - defaultCost += schemeProduct.PurchaseSchemeProductSkuList.Sum(pss => ((pss.ActualPrice ?? pss.PurchaseSkuPrice) ?? 0) * (pss.PurchaseRatio ?? 1)); + defaultCost += schemeProduct.PurchaseSchemeProductSkuList.Sum(pss => (pss.PurchaseSkuPrice ?? 0) * (pss.PurchaseRatio ?? 1)); + if (isContainsActualPrice) + { + if (bargainingCost == null) + bargainingCost = 0M; + bargainingCost += schemeProduct.PurchaseSchemeProductSkuList.Sum(pss => ((pss.ActualPrice ?? pss.PurchaseSkuPrice) ?? 0) * (pss.PurchaseRatio ?? 1)); + } } - if (pssId == null) - throw new BusinessException("未找到需要更新的采购配件"); + fsql.Transaction(() => { - fsql.Update(request.SchemeId).Set(ps => ps.DefaultCost, defaultCost).ExecuteAffrows(); + fsql.Update(request.SchemeId).Set(ps => ps.DefaultCost, defaultCost) + .SetIf(bargainingCost != null, ps => ps.BargainingCost, bargainingCost) + .ExecuteAffrows(); fsql.Update(pssId.Value).Set(pss => pss.PurchaseRatio, request.Ratio).ExecuteAffrows(); }); return defaultCost; @@ -1294,6 +1387,7 @@ namespace BBWYB.Server.Business var purchaseSchemeList = GetPurchaseSchemeList(new QuerySchemeRequest() { IncludePurchaseSkuBasicInfo = 1, + IncludeSkuStatisticsInfo = 0, SchemeIdList = schemeIdList }); diff --git a/BBWYB.Server.Model/Dto/Request/PurchaseScheme/QuerySchemeRequest.cs b/BBWYB.Server.Model/Dto/Request/PurchaseScheme/QuerySchemeRequest.cs index 419c3cb..94e748f 100644 --- a/BBWYB.Server.Model/Dto/Request/PurchaseScheme/QuerySchemeRequest.cs +++ b/BBWYB.Server.Model/Dto/Request/PurchaseScheme/QuerySchemeRequest.cs @@ -47,5 +47,10 @@ namespace BBWYB.Server.Model.Dto /// public int? IncludePurchaseSkuBasicInfo { get; set; } + /// + /// 是否包含店铺Sku统计信息 (最近采购时间/最近采购价/最近30天销量) 是=1 否=0或null + /// + public int? IncludeSkuStatisticsInfo { get; set; } + } } diff --git a/BBWYB.Server.Model/Dto/Response/PurchaseScheme/PurchaseSchemeResponse.cs b/BBWYB.Server.Model/Dto/Response/PurchaseScheme/PurchaseSchemeResponse.cs index 562a1ad..d7dc078 100644 --- a/BBWYB.Server.Model/Dto/Response/PurchaseScheme/PurchaseSchemeResponse.cs +++ b/BBWYB.Server.Model/Dto/Response/PurchaseScheme/PurchaseSchemeResponse.cs @@ -17,6 +17,11 @@ namespace BBWYB.Server.Model.Dto /// public decimal? SkuLastPurchasePriceCost { get; set; } + /// + /// 店铺SKU的最近采购时间 + /// + public DateTime? SkuLastPurchaseTime { get; set; } + /// /// 近30天Spu销量 ///