using System; using System.Collections.Generic; using System.Linq; using System.Text; using POSV.Entity.Pormotion; using POSV.Utils; namespace POSV.ShoppingCart { public class PromotionUtils { private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger(); /// /// 获取可打折金额,排除指定优惠 /// /// /// /// public static List GetValidPromItems(OrderObject orderObject, string planNo) { return orderObject.Items.FindAll(x => x.RowState != OrderRowState.套餐明 && (x.Promotions.Count == 0 || (x.Promotions.Count == 1 && x.Promotions[0].PlanNo == planNo)) && x.DiscountFlag == 1 && !orderObject.Items.Exists(y => y.RowState != OrderRowState.套餐明 && y.ParentId == x.Id)); } /// /// 获取可打折参与优惠的商品总金额,排除指定优惠 /// /// /// /// public static decimal GetValidPromItemsAmount(OrderObject orderObject, string planNo) { var validItems = GetValidPromItems(orderObject, planNo); return validItems.Sum(x => x.Amount); } /// /// 获取可打折参与优惠的商品 /// /// /// public static List GetValidPromItems(OrderObject orderObject) { return orderObject.Items.FindAll(x => x.RowState != OrderRowState.套餐明 && x.Promotions.Count == 0 && x.DiscountFlag == 1 ); //return orderObject.Items.FindAll(x => x.RowState != OrderRowState.套餐明 && x.Promotions.Count == 0 && x.DiscountFlag == 1 && !orderObject.Items.Exists(y => y.ParentId == x.Id)); } public static decimal GetValidPromItemsByCoupon(OrderObject orderObject, MemberCouponType type) { var validAmount = 0.00M; if (type == MemberCouponType.CASH) { //代金券启用金额 //排除已经参与优惠的商品,计算有效的订单金额 var validItems = orderObject.Items.FindAll(x => x.RowState != OrderRowState.套餐明 && !orderObject.Items.Exists(y => y.RowState != OrderRowState.套餐明 && y.ParentId == x.Id)); validAmount = validItems.Sum(x => x.Amount); } else if (type == MemberCouponType.DISCOUNT) { //启用金额 //排除已经参与优惠的商品,计算有效的订单金额 var validItems = orderObject.Items.FindAll(x => x.RowState != OrderRowState.套餐明 && x.Promotions.Count == 0 && x.DiscountFlag == 0 && !orderObject.Items.Exists(y => y.RowState != OrderRowState.套餐明 && y.ParentId == x.Id)); validAmount = validItems.Sum(x => x.Amount); } else if (type == MemberCouponType.GIFT) { //启用金额 //排除已经参与优惠的商品,计算有效的订单金额 var validItems = orderObject.Items.FindAll(x => x.RowState != OrderRowState.套餐明 && (x.Promotions.Count == 0 || (x.Promotions.Count > 0 && x.Promotions.FindAll(y => y.PromotionType != PromotionType.会员价 && y.PromotionType != PromotionType.会员等级优惠).Count <= 0) ) && !orderObject.Items.Exists(y => y.RowState != OrderRowState.套餐明 && y.ParentId == x.Id)); validAmount = validItems.Sum(x => x.Amount); } else if (type == MemberCouponType.PRODUCT) { //启用金额 //排除已经参与优惠的商品,计算有效的订单金额 var validItems = orderObject.Items.FindAll(x => x.RowState != OrderRowState.套餐明 && (x.Promotions.Count == 0 || (x.Promotions.Count > 0 && x.Promotions.FindAll(y => y.PromotionType != PromotionType.会员价 && y.PromotionType != PromotionType.会员等级优惠).Count <= 0) ) && !orderObject.Items.Exists(y => y.RowState != OrderRowState.套餐明 && y.ParentId == x.Id)); validAmount = validItems.Sum(x => x.Amount); } return validAmount; } /// /// 获取可打折参与优惠的商品总金额 /// /// /// public static decimal GetValidPromItemsAmount(OrderObject orderObject) { var validItems = GetValidPromItems(orderObject); return validItems.Sum(x => x.Amount); } /// /// 更新套餐主信息 /// /// public static void UpdateSuitMain(OrderObject orderObject,OrderItem item) { if (item.RowState == OrderRowState.套餐主 || item.RowState == OrderRowState.套餐明) { var mainItem = orderObject.Items.Find(x => x.Group == item.Group && x.RowState == OrderRowState.套餐主); var subItems = orderObject.Items.FindAll(x => x.Group == item.Group && x.RowState == OrderRowState.套餐明); if (mainItem != null && subItems != null) { mainItem.FlavorCount = subItems.Sum(x => x.FlavorCount); mainItem.FlavorAmount = subItems.Sum(x => x.FlavorAmount); mainItem.FlavorDiscountAmount = subItems.Sum(x => x.FlavorDiscountAmount); mainItem.FlavorReceivableAmount = subItems.Sum(x => x.FlavorReceivableAmount); } } } public static void PromotionMake(OrderItem orderItem, PromotionItem promotionItem) { List newItems = new List(); switch (promotionItem.PromotionType) { case PromotionType.折扣: case PromotionType.整单折扣: case PromotionType.电子折扣券: { if (orderItem.RowState == OrderRowState.套餐明) { promotionItem.DiscountRate =( 1 - promotionItem.MainProductRate); } else { newItems.Add(promotionItem); } } break; case PromotionType.免单: case PromotionType.赠送: { if (orderItem.RowState == OrderRowState.套餐明) { promotionItem.DiscountRate = 0; } else { promotionItem.DiscountRate = 0; newItems.Add(promotionItem); } } break; } if (orderItem.Flavors != null && orderItem.Flavors.Count > 0) { foreach (FlavorItem flavorItem in orderItem.Flavors) { flavorItem.DiscountPrice = OrderUtils.ToRound(flavorItem.Price * promotionItem.DiscountRate); flavorItem.DiscountAmount = OrderUtils.ToRound(flavorItem.Amount * (1 - promotionItem.DiscountRate)); } PromotionItem promotionItemMake = new PromotionItem(); promotionItemMake.Id = IdWorkerUtils.Instance.NextId(); promotionItemMake.TenantId = orderItem.TenantId; promotionItemMake.OrderId = orderItem.OrderId; promotionItemMake.TradeNo = orderItem.TradeNo; promotionItemMake.ItemId = orderItem.Id; promotionItemMake.PromotionType = PromotionType.做法折扣; promotionItemMake.Amount = orderItem.FlavorAmount; promotionItemMake.DiscountAmount = orderItem.FlavorDiscountAmount; promotionItemMake.ReceivableAmount = orderItem.FlavorReceivableAmount; promotionItemMake.DiscountRate = promotionItem.DiscountRate; promotionItemMake.Enabled = false; promotionItemMake.FinishDate = orderItem.FinishDate; newItems.Add(promotionItemMake); } ReplaceItems(orderItem.Promotions, newItems); } public static void Calculate(OrderObject orderObject , PromotionOrder promotionItem) { switch (promotionItem.PromotionType) { case PromotionType.整单折扣: { foreach(var orderItem in orderObject.Items) { //服务端禁止单品折扣 if(orderItem.DiscountFlag == 0) { orderItem.Action = "云端不允许折扣"; continue; } //忽略套餐明细,套餐明细依赖套餐主分摊折扣 if (orderItem.RowState == OrderRowState.套餐明) { continue; } //折扣优惠,相对固定值是输入的 折扣率 var discount = new PromotionItem(); //折扣标识 discount.Id = IdWorkerUtils.Instance.NextId(); //租户ID discount.TenantId = orderItem.TenantId; //订单ID discount.OrderId = orderItem.OrderId; //订单编号 discount.TradeNo = orderItem.TradeNo; //单品编号 discount.ItemId = orderItem.Id; //折扣类型 discount.PromotionType = PromotionType.整单折扣; //方案 discount.PlanName = promotionItem.PlanName; //输入80代表8折,折扣率为0.8 discount.DiscountRate = promotionItem.DiscountRate; //分摊数据对应整单优惠的行数据ID discount.RelationId = promotionItem.Id; //优惠前金额 discount.Amount = orderItem.Amount; //优惠金额 discount.DiscountAmount = OrderUtils.ToRound(discount.Amount * (1 - discount.DiscountRate)); //优惠后金额 discount.ReceivableAmount = discount.Amount - discount.DiscountAmount; //优惠生效 discount.Enabled = true; //折扣,影响折扣后的单价 = 折扣的总金额 / 购买的数量 orderItem.DiscountPrice = OrderUtils.ToDiscountPrice(discount.ReceivableAmount / orderItem.Quantity); orderItem.Action = "整单折扣操作"; //做法是否参与折扣 if (!Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_ALLOW_MAKEDISCOUNT, false)) { Replace(orderItem.Promotions, discount); } else { if (orderItem.RowState == OrderRowState.普通) { PromotionMake(orderItem, discount); } else if (orderItem.RowState == OrderRowState.套餐主) { PromotionMake(orderItem, discount); List orderItemDetailList = orderObject.Items.FindAll(x => x.RowState == OrderRowState.套餐明 && orderItem.Id.Equals(x.ParentId)); foreach (OrderItem orderItemDetail in orderItemDetailList) { discount.MainProductRate = orderItem.DiscountRate; PromotionMake(orderItemDetail, discount); } } } UpdateSuitMain(orderObject, orderItem); //套餐道菜分摊 CalculateSuitShare(orderObject, orderItem); } //优惠前金额 promotionItem.Amount = orderObject.Amount; //优惠金额 promotionItem.DiscountAmount = OrderUtils.ToRound(promotionItem.Amount * (1 - promotionItem.DiscountRate)); //优惠后金额 promotionItem.ReceivableAmount = promotionItem.Amount - promotionItem.DiscountAmount; //优惠生效 promotionItem.Enabled = true; } break; case PromotionType.整单议价: { //整单议价需要分摊给单品 //单品分摊计算规则:单品的金额 / 整单金额小计 * 议价后金额 = 单品分摊的金额; //折后单价计算规则:单品分摊后单价 = 单品分摊的金额 / 单品数量 //单品折扣率 = 单品分摊金额 / 单品金额小计 //已经分摊金额的合计,用于处理最后一个单品相减的问题 decimal sum = 0; var lists = orderObject.Items.OrderBy(x => x.OrderNo).ToList(); for (int i = 0;i< lists.Count; i++) { var orderItem = lists[i]; //服务端禁止单品折扣 if (orderItem.DiscountFlag == 0) { orderItem.Action = "云端不允许议价"; continue; } //忽略套餐明细,套餐明细依赖套餐主分摊折扣 if (orderItem.RowState == OrderRowState.套餐明) { continue; } //折扣优惠,相对固定值是输入的 折扣率 var discount = new PromotionItem(); //折扣标识 discount.Id = IdWorkerUtils.Instance.NextId(); //折扣类型 discount.PromotionType = PromotionType.整单议价; //租户ID discount.TenantId = orderItem.TenantId; //订单ID discount.OrderId = orderItem.OrderId; //订单编号 discount.TradeNo = orderItem.TradeNo; //单品编号 discount.ItemId = orderItem.Id; //分摊数据对应整单优惠的行数据ID discount.RelationId = promotionItem.Id; //分摊的金额 var _amount = OrderUtils.ToRound(orderItem.Amount / orderObject.Amount * promotionItem.ReceivableAmount); //如果是最后一条记录,分摊金额采用减法 if(i+1 == orderObject.Items.Count) { _amount = promotionItem.ReceivableAmount - sum; } else { sum += _amount; } //折扣率 discount.DiscountRate = OrderUtils.ToRound(_amount / orderItem.Amount); //优惠前金额 discount.Amount = orderItem.Amount; //优惠金额 discount.DiscountAmount = orderItem.Amount - _amount; //优惠后金额 discount.ReceivableAmount = _amount; //优惠生效 discount.Enabled = true; //折扣,影响折扣后的单价 = 折扣的总金额 / 购买的数量 orderItem.DiscountPrice = OrderUtils.ToDiscountPrice(discount.ReceivableAmount / orderItem.Quantity); Replace(orderItem.Promotions , discount); UpdateSuitMain(orderObject, orderItem); //套餐道菜分摊 CalculateSuitShare(orderObject, orderItem); } //优惠生效 promotionItem.Enabled = true; } break; case PromotionType.整单立减: { //整单立减需要分摊给单品 //单品分摊计算规则:单品的金额 / 整单金额小计 * 立减金额 = 单品分摊的金额; //折后单价计算规则:单品分摊后单价 = 单品分摊的金额 / 单品数量 //单品折扣率 = 单品分摊金额 / 单品金额小计 //已经分摊金额的合计,用于处理最后一个单品相减的问题 decimal sum = 0; var lists = orderObject.Items.OrderBy(x => x.OrderNo).ToList(); var validItems = GetValidPromItems(orderObject); //有效商品金额 decimal validAmount = validItems.Sum(x => x.Amount); for (int i = 0; i < lists.Count; i++) { var orderItem = lists[i]; //服务端禁止单品折扣 if (orderItem.DiscountFlag == 0) { orderItem.Action = "云端不允许优惠"; continue; } //忽略套餐明细,套餐明细依赖套餐主分摊折扣 if (orderItem.RowState == OrderRowState.套餐明) { continue; } //折扣优惠,相对固定值是输入的 折扣率 var discount = new PromotionItem(); //折扣标识 discount.Id = IdWorkerUtils.Instance.NextId(); //折扣类型 discount.PromotionType = PromotionType.整单立减; //折扣方案 discount.PlanName = promotionItem.PlanName; //租户ID discount.TenantId = orderItem.TenantId; //订单ID discount.OrderId = orderItem.OrderId; //订单编号 discount.TradeNo = orderItem.TradeNo; //单品编号 discount.ItemId = orderItem.Id; //分摊数据对应整单优惠的行数据ID discount.RelationId = promotionItem.Id; //分摊的金额 //var _amount = OrderUtils.ToRound( promotionItem.DiscountAmount / orderObject.Items.Where(f=>f.RowState != OrderRowState.套餐明).Count()); var _amount = OrderUtils.ToRound(orderItem.Amount / validAmount * promotionItem.DiscountAmount); //如果是最后一条记录,分摊金额采用减法 if (i + 1 == orderObject.Items.Count) { _amount = promotionItem.DiscountAmount - sum; } else { sum += _amount; } //优惠前金额 discount.Amount = orderItem.Amount; //优惠金额 discount.DiscountAmount = _amount; //优惠后金额 discount.ReceivableAmount = orderItem.Amount - _amount; //折扣率 discount.DiscountRate = OrderUtils.ToRound(discount.ReceivableAmount / orderItem.Amount); //优惠生效 discount.Enabled = true; //折扣,影响折扣后的单价 = 折扣的总金额 / 购买的数量 orderItem.DiscountPrice = OrderUtils.ToDiscountPrice(discount.ReceivableAmount / orderItem.Quantity); Replace(orderItem.Promotions, discount); UpdateSuitMain(orderObject, orderItem); //套餐道菜分摊 CalculateSuitShare(orderObject, orderItem); } //优惠生效 promotionItem.Enabled = true; } break; case PromotionType.卡友日: { //整单立减需要分摊给单品 //单品分摊计算规则:单品的金额 / 整单金额小计 * 立减金额 = 单品分摊的金额; //折后单价计算规则:单品分摊后单价 = 单品分摊的金额 / 单品数量 //单品折扣率 = 单品分摊金额 / 单品金额小计 //已经分摊金额的合计,用于处理最后一个单品相减的问题 decimal sum = 0; var validItems = GetValidPromItems(orderObject); //有效商品金额 decimal validAmount = validItems.Sum(x => x.Amount); for (int i = 0; i < validItems.Count; i++) { var orderItem = validItems[i]; //服务端禁止单品折扣 if (orderItem.DiscountFlag == 0) { orderItem.Action = "云端不允许优惠"; continue; } //忽略套餐明细,套餐明细依赖套餐主分摊折扣 if (orderItem.RowState == OrderRowState.套餐明) { continue; } //折扣优惠,相对固定值是输入的 折扣率 var discount = new PromotionItem(); //折扣标识 discount.Id = IdWorkerUtils.Instance.NextId(); //折扣类型 discount.PromotionType = PromotionType.卡友日; //租户ID discount.TenantId = orderItem.TenantId; //订单ID discount.OrderId = orderItem.OrderId; //订单编号 discount.TradeNo = orderItem.TradeNo; //单品编号 discount.ItemId = orderItem.Id; //分摊数据对应整单优惠的行数据ID discount.RelationId = promotionItem.Id; discount.PlanNo = promotionItem.PlanNo; discount.PlanName = promotionItem.PlanName; //分摊的金额 var _amount = OrderUtils.ToRound(orderItem.Amount / validAmount * promotionItem.DiscountAmount); //如果是最后一条记录,分摊金额采用减法 if (i + 1 == orderObject.Items.Count) { _amount = promotionItem.DiscountAmount - sum; } else { sum += _amount; } //优惠前金额 discount.Amount = orderItem.Amount; //优惠金额 discount.DiscountAmount = _amount; //优惠后金额 discount.ReceivableAmount = orderItem.Amount - _amount; //折扣率 if(orderItem.Amount == 0) { discount.DiscountRate = 0; } else { discount.DiscountRate = OrderUtils.ToRound(discount.ReceivableAmount / orderItem.Amount); } //优惠生效 discount.Enabled = true; //折扣,影响折扣后的单价 = 折扣的总金额 / 购买的数量 orderItem.DiscountPrice = OrderUtils.ToDiscountPrice(discount.ReceivableAmount / orderItem.Quantity); Replace(orderItem.Promotions, discount); UpdateSuitMain(orderObject, orderItem); //套餐道菜分摊 CalculateSuitShare(orderObject, orderItem); } //优惠生效 promotionItem.Enabled = true; } break; case PromotionType.实体优惠券: { //整单立减需要分摊给单品 //单品分摊计算规则:单品的金额 / 整单金额小计 * 立减金额 = 单品分摊的金额; //折后单价计算规则:单品分摊后单价 = 单品分摊的金额 / 单品数量 //单品折扣率 = 单品分摊金额 / 单品金额小计 //已经分摊金额的合计,用于处理最后一个单品相减的问题 decimal sum = 0; var validItems = GetValidPromItems(orderObject); //有效商品金额 decimal validAmount = validItems.Sum(x => x.Amount); for (int i = 0; i < validItems.Count; i++) { var orderItem = validItems[i]; //服务端禁止单品折扣 if (orderItem.DiscountFlag == 0) { orderItem.Action = "云端不允许优惠"; continue; } //忽略套餐明细,套餐明细依赖套餐主分摊折扣 if (orderItem.RowState == OrderRowState.套餐明) { continue; } //折扣优惠,相对固定值是输入的 折扣率 var discount = new PromotionItem(); //折扣标识 discount.Id = IdWorkerUtils.Instance.NextId(); //折扣类型 discount.PromotionType = PromotionType.实体优惠券; //租户ID discount.TenantId = orderItem.TenantId; //订单ID discount.OrderId = orderItem.OrderId; //订单编号 discount.TradeNo = orderItem.TradeNo; //单品编号 discount.ItemId = orderItem.Id; //分摊数据对应整单优惠的行数据ID discount.RelationId = promotionItem.Id; discount.PlanNo = promotionItem.PlanNo; discount.PlanName = promotionItem.PlanName; //分摊的金额 var _amount = OrderUtils.ToRound(orderItem.Amount / validAmount * promotionItem.DiscountAmount); //如果是最后一条记录,分摊金额采用减法 if (i + 1 == orderObject.Items.Count) { _amount = promotionItem.DiscountAmount - sum; } else { sum += _amount; } //优惠前金额 discount.Amount = orderItem.Amount; //优惠金额 discount.DiscountAmount = _amount; //优惠后金额 discount.ReceivableAmount = orderItem.Amount - _amount; //折扣率 if (orderItem.Amount == 0) { discount.DiscountRate = 0; } else { discount.DiscountRate = OrderUtils.ToRound(discount.ReceivableAmount / orderItem.Amount); } //优惠生效 discount.Enabled = true; //折扣,影响折扣后的单价 = 折扣的总金额 / 购买的数量 orderItem.DiscountPrice = OrderUtils.ToDiscountPrice(discount.ReceivableAmount / orderItem.Quantity); //优惠券信息 discount.Ext1 = promotionItem.Ext1; Replace(orderItem.Promotions, discount); UpdateSuitMain(orderObject, orderItem); //套餐道菜分摊 CalculateSuitShare(orderObject, orderItem); } //优惠生效 promotionItem.Enabled = true; } break; case PromotionType.免单: { //整单立减需要分摊给单品 //单品分摊计算规则:单品的金额 / 整单金额小计 * 立减金额 = 单品分摊的金额; //折后单价计算规则:单品分摊后单价 = 单品分摊的金额 / 单品数量 //单品折扣率 = 单品分摊金额 / 单品金额小计 //已经分摊金额的合计,用于处理最后一个单品相减的问题 decimal sum = 0; var validItems = GetValidPromItems(orderObject); //有效商品金额 decimal validAmount = validItems.Sum(x => x.Amount); for (int i = 0; i < validItems.Count; i++) { var orderItem = validItems[i]; //服务端禁止单品折扣 if (orderItem.DiscountFlag == 0) { orderItem.Action = "云端不允许优惠"; continue; } //忽略套餐明细,套餐明细依赖套餐主分摊折扣 if (orderItem.RowState == OrderRowState.套餐明) { continue; } //折扣优惠,相对固定值是输入的 折扣率 var discount = new PromotionItem(); //折扣标识 discount.Id = IdWorkerUtils.Instance.NextId(); //折扣类型 discount.PromotionType = PromotionType.免单; //租户ID discount.TenantId = orderItem.TenantId; //订单ID discount.OrderId = orderItem.OrderId; //订单编号 discount.TradeNo = orderItem.TradeNo; //单品编号 discount.ItemId = orderItem.Id; //分摊数据对应整单优惠的行数据ID discount.RelationId = promotionItem.Id; discount.PlanNo = promotionItem.PlanNo; discount.PlanName = promotionItem.PlanName; //分摊的金额 var _amount = OrderUtils.ToRound(orderItem.Amount / validAmount * promotionItem.DiscountAmount); //如果是最后一条记录,分摊金额采用减法 if (i + 1 == orderObject.Items.Count) { _amount = promotionItem.DiscountAmount - sum; } else { sum += _amount; } //优惠前金额 discount.Amount = orderItem.Amount; //优惠金额 discount.DiscountAmount = _amount; //优惠后金额 discount.ReceivableAmount = orderItem.Amount - _amount; //折扣率 if (orderItem.Amount == 0) { discount.DiscountRate = 0; } else { discount.DiscountRate = OrderUtils.ToRound(discount.ReceivableAmount / orderItem.Amount); } //优惠生效 discount.Enabled = true; //折扣,影响折扣后的单价 = 折扣的总金额 / 购买的数量 orderItem.DiscountPrice = OrderUtils.ToDiscountPrice(discount.ReceivableAmount / orderItem.Quantity); //做法是否参与折扣 if (!Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_ALLOW_MAKEDISCOUNT, false)) { Replace(orderItem.Promotions, discount); } else { if (orderItem.RowState == OrderRowState.普通) { PromotionMake(orderItem, discount); } else if (orderItem.RowState == OrderRowState.套餐主) { PromotionMake(orderItem, discount); List orderItemDetailList = orderObject.Items.FindAll(x => x.RowState == OrderRowState.套餐明 && orderItem.Id.Equals(x.ParentId)); foreach (OrderItem orderItemDetail in orderItemDetailList) { discount.MainProductRate = orderItem.DiscountRate; PromotionMake(orderItemDetail, discount); } } } UpdateSuitMain(orderObject, orderItem); //套餐道菜分摊 CalculateSuitShare(orderObject, orderItem); } //优惠生效 promotionItem.Enabled = true; } break; case PromotionType.电子代金券: case PromotionType.电子折扣券: { //整单立减需要分摊给单品 //单品分摊计算规则:单品的金额 / 整单金额小计 * 立减金额 = 单品分摊的金额; //折后单价计算规则:单品分摊后单价 = 单品分摊的金额 / 单品数量 //单品折扣率 = 单品分摊金额 / 单品金额小计 //已经分摊金额的合计,用于处理最后一个单品相减的问题 decimal sum = 0; var validItems = GetValidPromItems(orderObject); //有效商品金额 decimal validAmount = validItems.Sum(x => x.Amount); for (int i = 0; i < validItems.Count; i++) { var orderItem = validItems[i]; //服务端禁止单品折扣 if (orderItem.DiscountFlag == 0) { orderItem.Action = "云端不允许优惠"; continue; } //忽略套餐明细,套餐明细依赖套餐主分摊折扣 if (orderItem.RowState == OrderRowState.套餐明) { continue; } //折扣优惠,相对固定值是输入的 折扣率 var discount = new PromotionItem(); //折扣标识 discount.Id = IdWorkerUtils.Instance.NextId(); //折扣类型 discount.PromotionType = promotionItem.PromotionType; //租户ID discount.TenantId = orderItem.TenantId; //订单ID discount.OrderId = orderItem.OrderId; //订单编号 discount.TradeNo = orderItem.TradeNo; //单品编号 discount.ItemId = orderItem.Id; //分摊数据对应整单优惠的行数据ID discount.RelationId = promotionItem.Id; discount.PlanNo = promotionItem.PlanNo; discount.PlanName = promotionItem.PlanName; //兑换券ID discount.CouponId = promotionItem.CouponId; //分摊的金额 var _amount = OrderUtils.ToRound(orderItem.Amount / validAmount * promotionItem.DiscountAmount); //如果是最后一条记录,分摊金额采用减法 if (i + 1 == orderObject.Items.Count) { _amount = promotionItem.DiscountAmount - sum; } else { sum += _amount; } //优惠前金额 discount.Amount = orderItem.Amount; //优惠金额 discount.DiscountAmount = _amount; //优惠后金额 discount.ReceivableAmount = orderItem.Amount - _amount; //折扣率 if (orderItem.Amount == 0) { discount.DiscountRate = 0; } else { discount.DiscountRate = OrderUtils.ToRound(discount.ReceivableAmount / orderItem.Amount); } //优惠生效 discount.Enabled = true; //折扣,影响折扣后的单价 = 折扣的总金额 / 购买的数量 orderItem.DiscountPrice = OrderUtils.ToDiscountPrice(discount.ReceivableAmount / orderItem.Quantity); if (promotionItem.PromotionType == PromotionType.电子折扣券) { //做法是否参与折扣 if (!Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_ALLOW_MAKEDISCOUNT, false)) { Replace(orderItem.Promotions, discount); } else { if (orderItem.RowState == OrderRowState.套餐明) { OrderItem orderItemMain = orderObject.Items.Find(x => x.RowState == OrderRowState.套餐主 && x.Id.Equals(orderItem.ParentId)); discount.MainProductRate = orderItemMain.DiscountRate; } PromotionMake(orderItem, discount); } } else { Replace(orderItem.Promotions, discount); } UpdateSuitMain(orderObject, orderItem); //套餐道菜分摊 CalculateSuitShare(orderObject, orderItem); } //优惠生效 promotionItem.Enabled = true; } break; } Replace(orderObject.Promotions , promotionItem); } /// /// 整单促销,参与集合,排除集合 /// /// /// /// /// public static void Calculate(OrderObject orderObject, PromotionOrder promotionItem, List joinList, List outList) { switch (promotionItem.PromotionType) { case PromotionType.满减促销: { //整单满减需要分摊给单品 //单品分摊计算规则:单品的金额 / 整单金额小计 * 立减金额 = 单品分摊的金额; //折后单价计算规则:单品分摊后单价 = 单品分摊的金额 / 单品数量 //单品折扣率 = 单品分摊金额 / 单品金额小计 //已经分摊金额的合计,用于处理最后一个单品相减的问题 List joinItemList = GetValidPromItems(orderObject).OrderBy(x => x.OrderNo).ToList(); if (joinList != null && joinList.Count > 0) { //获取计算范围内的订单项 joinItemList = joinItemList.FindAll(x => joinList.Exists(y => y == x.SpecId)); } if (outList != null && outList.Count > 0) { //排除不在计算范围内的订单项 joinItemList = joinItemList.FindAll(x => !outList.Exists(y => y == x.SpecId)); } decimal totalJoinAmount = joinItemList.Sum(x => x.Amount); decimal sum = 0; for (int i = 0; i < joinItemList.Count; i++) { var orderItem = joinItemList[i]; //折扣优惠,相对固定值是输入的 折扣率 var discount = new PromotionItem(); //折扣标识 discount.Id = IdWorkerUtils.Instance.NextId(); //折扣类型 discount.PromotionType = PromotionType.满减促销; //租户ID discount.TenantId = orderItem.TenantId; //订单ID discount.OrderId = orderItem.OrderId; //订单编号 discount.TradeNo = orderItem.TradeNo; //单品编号 discount.ItemId = orderItem.Id; //分摊数据对应整单优惠的行数据ID discount.RelationId = promotionItem.Id; discount.PlanNo = promotionItem.PlanNo; discount.PlanName = promotionItem.PlanName; //分摊的金额 var _amount = OrderUtils.ToRound(orderItem.Amount / totalJoinAmount * promotionItem.DiscountAmount); //如果是最后一条记录,分摊金额采用减法 if (i + 1 == joinItemList.Count) { _amount = promotionItem.DiscountAmount - sum; } else { sum += _amount; } //优惠前金额 discount.Amount = orderItem.Amount; //优惠金额 discount.DiscountAmount = _amount; //优惠后金额 discount.ReceivableAmount = orderItem.Amount - _amount; //折扣率 if(orderItem.Amount == 0) { discount.DiscountRate = 0; } else { discount.DiscountRate = OrderUtils.ToRound(discount.ReceivableAmount / orderItem.Amount); } //优惠生效 discount.Enabled = true; //折扣,影响折扣后的单价 = 折扣的总金额 / 购买的数量 orderItem.DiscountPrice = OrderUtils.ToDiscountPrice(discount.ReceivableAmount / orderItem.Quantity); Replace(orderItem.Promotions, discount); UpdateSuitMain(orderObject, orderItem); //套餐道菜分摊 CalculateSuitShare(orderObject, orderItem); } //优惠生效 promotionItem.Enabled = true; } break; } Replace(orderObject.Promotions, promotionItem); } /// /// 套餐分摊 /// /// /// public static void CalculateSuitShare(OrderObject orderObject, OrderItem orderItem) { //判断是否是套餐主 if (orderItem.RowState == OrderRowState.套餐主) { //分摊道菜优惠 var _rows = orderObject.Items.FindAll(x => (x.Id == orderItem.Id || x.ParentId == orderItem.Id) && x.Group == orderItem.Group).OrderBy(x => x.OrderNo); //分摊道菜优惠 PromotionUtils.CalculateSuitShare(orderObject,_rows.ToList()); } } /// /// 套餐分摊 /// /// public static void CalculateSuitShare(OrderObject orderObject, List rows) { //套餐主菜售价 var _master = rows.Find(x => x.RowState == OrderRowState.套餐主); //套餐明细列表 var _details = rows.FindAll(x => x.RowState == OrderRowState.套餐明).OrderByDescending(x => x.Amount).ToList(); if (_master == null || _details == null) { return; } //套餐主的金额,不包含加价 var _masterAmount = _master.SalePrice * _master.Quantity * (1 - _master.DiscountRate); //套菜金额合计 = Sum(道菜售价*道菜数量) var _detailAmount = _details.Sum(x => x.Amount); //已经分摊金额的合计,用于处理最后一个单品相减的问题 decimal sum = 0; var lists = _details.OrderByDescending(x => x.Amount).ToList(); for (int i = 0; i < lists.Count; i++) { var item = lists[i]; //道菜优惠 var discount = new PromotionItem(); //标识 discount.Id = IdWorkerUtils.Instance.NextId(); //租户ID discount.TenantId = item.TenantId; //订单ID discount.OrderId = item.OrderId; //订单编号 discount.TradeNo = item.TradeNo; //单品编号 discount.ItemId = item.Id; //类型 discount.PromotionType = PromotionType.道菜分摊; //道菜明细分摊的金额,相对应套餐主菜售价分摊,主菜的金额 / 道菜明细总金额 * 道菜金额 = 道菜分摊的金额 * 主菜折扣 var itemAmount = OrderUtils.ToRound((item.Amount / _detailAmount) * _masterAmount + item.SuitAmount * (1 - _master.DiscountRate)); //如果是最后一条记录,分摊金额采用减法 if (i + 1 == lists.Count) { itemAmount = _masterAmount - sum; } else { sum += itemAmount; } //优惠后金额 discount.ReceivableAmount = itemAmount; //优惠金额 discount.DiscountAmount = item.Amount - itemAmount; //是否启用 discount.Enabled = false; //记录主菜的优惠率 discount.MainProductRate = _master.DiscountRate; PromotionUtils.Calculate(orderObject,item, discount); } } public static void Calculate(OrderObject orderObject, OrderItem orderItem , PromotionItem promotionItem) { switch (promotionItem.PromotionType) { case PromotionType.折扣: { //服务端禁止单品折扣 if (orderItem.DiscountFlag == 0) { orderItem.Action = "云端不允许折扣"; return; } //优惠前金额 promotionItem.Amount = orderItem.Amount; //优惠金额 promotionItem.DiscountAmount = OrderUtils.ToRound(promotionItem.Amount * (1 - promotionItem.DiscountRate)); //优惠后金额 promotionItem.ReceivableAmount = OrderUtils.ToRound(promotionItem.Amount - promotionItem.DiscountAmount); //优惠生效 promotionItem.Enabled = true; //折扣,影响折扣后的单价 = 折扣的总金额 / 购买的数量 orderItem.DiscountPrice = OrderUtils.ToRound(promotionItem.ReceivableAmount / orderItem.Quantity); orderItem.Action = "单品折扣操作"; } break; case PromotionType.议价: { //优惠前金额 promotionItem.Amount = orderItem.Amount; //优惠金额 promotionItem.DiscountAmount = OrderUtils.ToRound(orderItem.Amount-(orderItem.Quantity * promotionItem.DiscountPrice)); //优惠后金额 promotionItem.ReceivableAmount = OrderUtils.ToRound(orderItem.Quantity * promotionItem.DiscountPrice); //优惠生效 promotionItem.Enabled = true; //折扣,影响折扣后的单价 = 折扣的总金额 / 购买的数量 orderItem.DiscountPrice = promotionItem.DiscountPrice; } break; case PromotionType.赠送: { //优惠生效 promotionItem.Enabled = true; //折扣,影响折扣后的单价 = 折扣的总金额 / 购买的数量 orderItem.DiscountPrice = OrderUtils.ToRound(promotionItem.ReceivableAmount / orderItem.Quantity); orderItem.Action = "单品赠送操作"; } break; case PromotionType.道菜分摊: { //优惠前金额 promotionItem.Amount = orderItem.Amount; //优惠率 if(promotionItem.Amount == 0) { promotionItem.DiscountRate = 0; } else { promotionItem.DiscountRate = OrderUtils.ToRound(promotionItem.DiscountAmount / promotionItem.Amount); } //优惠生效 promotionItem.Enabled = true; //折扣,影响折扣后的单价 = 折扣的总金额 / 购买的数量 orderItem.DiscountPrice = OrderUtils.ToRound(promotionItem.ReceivableAmount / orderItem.Quantity); orderItem.Action = "道菜分摊操作"; } break; case PromotionType.会员价: { //优惠前金额 promotionItem.Amount = orderItem.Amount; //优惠金额 promotionItem.DiscountAmount = OrderUtils.ToRound((orderItem.Price - orderItem.MemberPrice) * orderItem.Quantity); //优惠后的金额 promotionItem.ReceivableAmount = OrderUtils.ToRound(promotionItem.Amount - promotionItem.DiscountAmount); //优惠生效 promotionItem.Enabled = true; //折扣,影响折扣后的单价 = 折扣的总金额 / 购买的数量 orderItem.DiscountPrice = OrderUtils.ToRound(promotionItem.ReceivableAmount / orderItem.Quantity); orderItem.Action = "会员价优惠操作"; } break; case PromotionType.商品优惠券: { //优惠前金额 promotionItem.Amount = orderItem.ReceivableAmount; //优惠后的金额 promotionItem.ReceivableAmount = OrderUtils.ToRound(promotionItem.Amount - promotionItem.DiscountAmount); //折扣率 promotionItem.DiscountRate = OrderUtils.ToRound(promotionItem.ReceivableAmount / promotionItem.Amount); //优惠生效 promotionItem.Enabled = true; //折扣,影响折扣后的单价 = 折扣的总金额 / 购买的数量 orderItem.DiscountPrice = OrderUtils.ToRound(promotionItem.ReceivableAmount / orderItem.Quantity); orderItem.Action = "商品优惠券操作"; } break; case PromotionType.会员等级优惠: { //优惠前金额 promotionItem.Amount = orderItem.Amount; //优惠金额 promotionItem.DiscountAmount = promotionItem.DiscountAmount; //优惠后的金额 promotionItem.ReceivableAmount = OrderUtils.ToRound(promotionItem.Amount - promotionItem.DiscountAmount); //优惠生效 promotionItem.Enabled = true; //折扣,影响折扣后的单价 = 折扣的总金额 / 购买的数量 orderItem.DiscountPrice = OrderUtils.ToRound(promotionItem.ReceivableAmount / orderItem.Quantity); orderItem.Action = "会员等级优惠操作"; } break; case PromotionType.立减: { //优惠前金额 promotionItem.Amount = orderItem.Amount; //优惠后的金额 promotionItem.ReceivableAmount = OrderUtils.ToRound(promotionItem.Amount - promotionItem.DiscountAmount); //折扣率 promotionItem.DiscountRate = OrderUtils.ToRound(promotionItem.ReceivableAmount / promotionItem.Amount); //优惠生效 promotionItem.Enabled = true; //折扣,影响折扣后的单价 = 折扣的总金额 / 购买的数量 orderItem.DiscountPrice = OrderUtils.ToRound(promotionItem.ReceivableAmount / orderItem.Quantity); orderItem.Action = "立减优惠操作"; } break; case PromotionType.卡友日: { //优惠前金额 promotionItem.Amount = orderItem.Amount; //优惠后的金额 promotionItem.ReceivableAmount = OrderUtils.ToRound(promotionItem.Amount - promotionItem.DiscountAmount); //优惠生效 promotionItem.Enabled = true; //折扣,影响折扣后的单价 = 折扣的总金额 / 购买的数量 orderItem.DiscountPrice = OrderUtils.ToRound(promotionItem.ReceivableAmount / orderItem.Quantity); orderItem.Action = "会员日优惠操作"; } break; case PromotionType.商品促销: { //优惠前金额 promotionItem.Amount = orderItem.Amount; //优惠后的金额 promotionItem.ReceivableAmount = OrderUtils.ToRound(promotionItem.Amount - promotionItem.DiscountAmount); //优惠生效 promotionItem.Enabled = true; //折扣,影响折扣后的单价 = 折扣的总金额 / 购买的数量 orderItem.DiscountPrice = OrderUtils.ToRound(promotionItem.ReceivableAmount / orderItem.Quantity); orderItem.Action = "商品促销优惠操作"; } break; case PromotionType.双数特价赠送: case PromotionType.双数特价优惠: { //优惠前金额 promotionItem.Amount = orderItem.Amount; //优惠后的金额 promotionItem.ReceivableAmount = OrderUtils.ToRound(promotionItem.Amount - promotionItem.DiscountAmount); //优惠生效 promotionItem.Enabled = true; //折扣,影响折扣后的单价 = 折扣的总金额 / 购买的数量 orderItem.DiscountPrice = OrderUtils.ToRound(promotionItem.ReceivableAmount / orderItem.Quantity); orderItem.Action = "双数特价促销优惠操作"; } break; case PromotionType.电子兑换券: { //优惠生效 promotionItem.Enabled = true; //折扣,影响折扣后的单价 = 折扣的总金额 / 购买的数量 orderItem.DiscountPrice = OrderUtils.ToRound(promotionItem.ReceivableAmount / orderItem.Quantity); orderItem.Action = "电子兑换券操作"; } break; case PromotionType.电子商品券: { //优惠生效 promotionItem.Enabled = true; //折扣,影响折扣后的单价 = 折扣的总金额 / 购买的数量 orderItem.DiscountPrice = OrderUtils.ToRound(promotionItem.ReceivableAmount / orderItem.Quantity); orderItem.Action = "电子商品券操作"; } break; } //做法是否参与折扣 if (!Global.Instance.GlobalConfigBoolValue(ConfigConstant.CASHIER_ALLOW_MAKEDISCOUNT, false)) { Replace(orderItem.Promotions, promotionItem); UpdateSuitMain(orderObject, orderItem); } else { switch (promotionItem.PromotionType) { case PromotionType.折扣: case PromotionType.赠送: { if (orderItem.RowState == OrderRowState.普通) { PromotionMake(orderItem, promotionItem); } else if (orderItem.RowState == OrderRowState.套餐主) { PromotionMake(orderItem, promotionItem); List orderItemDetailList = orderObject.Items.FindAll(x => x.RowState == OrderRowState.套餐明 && orderItem.Id.Equals(x.ParentId)); foreach (OrderItem orderItemDetail in orderItemDetailList) { promotionItem.MainProductRate = orderItem.DiscountRate; PromotionMake(orderItemDetail, promotionItem); } } UpdateSuitMain(orderObject, orderItem); } break; default: Replace(orderItem.Promotions, promotionItem); UpdateSuitMain(orderObject, orderItem); break; } } } public static bool Exists(List items , PromotionType type) { return items.Exists(x => x.PromotionType == type); } public static void Replace(List items , PromotionItem newItem) { //是否存在 var exists = Exists(items , newItem.PromotionType); if (exists) { items.RemoveAll(x => x.PromotionType == newItem.PromotionType); } items.Add(newItem); } public static void ReplaceItems(List items, List newItems) { foreach (PromotionItem newItem in newItems) { //是否存在 var exists = Exists(items, newItem.PromotionType); if (exists) { items.RemoveAll(x => x.PromotionType == newItem.PromotionType); } items.Add(newItem); } } public static bool Exists(List items , PromotionType type) { return items.Exists(x => x.PromotionType == type); } public static void Replace(List items , PromotionOrder newItem) { //是否存在 var exists = Exists(items , newItem.PromotionType); if (exists) { items.RemoveAll(x => x.PromotionType == newItem.PromotionType); } items.Add(newItem); } public static void Remove(OrderObject order, string promotionNo) { //是否存在 order.Promotions.RemoveAll(x => x.PlanNo == promotionNo); //删除单品 foreach(var item in order.Items) { item.Promotions.RemoveAll(x => x.PlanNo == promotionNo); //重新算折扣价 item.DiscountPrice = OrderUtils.ToRound((item.Amount - item.DiscountAmount) / item.Quantity); UpdateSuitMain(order, item); //套餐道菜分摊 CalculateSuitShare(order, item); //套餐道菜分摊 //PromotionUtils.CalculateSuitShare(order,item ); } } } }