You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1435 lines
68 KiB
C#

9 months ago
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();
/// <summary>
/// 获取可打折金额,排除指定优惠
/// </summary>
/// <param name="orderObject"></param>
/// <param name="withOutProm"></param>
/// <returns></returns>
public static List<OrderItem> 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));
}
/// <summary>
/// 获取可打折参与优惠的商品总金额,排除指定优惠
/// </summary>
/// <param name="orderObject"></param>
/// <param name="withOutProm"></param>
/// <returns></returns>
public static decimal GetValidPromItemsAmount(OrderObject orderObject, string planNo)
{
var validItems = GetValidPromItems(orderObject, planNo);
return validItems.Sum(x => x.Amount);
}
/// <summary>
/// 获取可打折参与优惠的商品
/// </summary>
/// <param name="orderObject"></param>
/// <returns></returns>
public static List<OrderItem> 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;
}
/// <summary>
/// 获取可打折参与优惠的商品总金额
/// </summary>
/// <param name="orderObject"></param>
/// <returns></returns>
public static decimal GetValidPromItemsAmount(OrderObject orderObject)
{
var validItems = GetValidPromItems(orderObject);
return validItems.Sum(x => x.Amount);
}
/// <summary>
/// 更新套餐主信息
/// </summary>
/// <param name="item"></param>
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<PromotionItem> newItems = new List<PromotionItem>();
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<OrderItem> 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<OrderItem> 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);
}
/// <summary>
/// 整单促销,参与集合,排除集合
/// </summary>
/// <param name="orderObject"></param>
/// <param name="promotionItem"></param>
/// <param name="joinList"></param>
/// <param name="outList"></param>
public static void Calculate(OrderObject orderObject, PromotionOrder promotionItem, List<string> joinList, List<string> outList)
{
switch (promotionItem.PromotionType)
{
case PromotionType.:
{
//整单满减需要分摊给单品
//单品分摊计算规则:单品的金额 / 整单金额小计 * 立减金额 = 单品分摊的金额;
//折后单价计算规则:单品分摊后单价 = 单品分摊的金额 / 单品数量
//单品折扣率 = 单品分摊金额 / 单品金额小计
//已经分摊金额的合计,用于处理最后一个单品相减的问题
List<OrderItem> 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);
}
/// <summary>
/// 套餐分摊
/// </summary>
/// <param name="orderObject"></param>
/// <param name="orderItem"></param>
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());
}
}
/// <summary>
/// 套餐分摊
/// </summary>
/// <param name="rows"></param>
public static void CalculateSuitShare(OrderObject orderObject, List<OrderItem> 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<OrderItem> 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<PromotionItem> items , PromotionType type)
{
return items.Exists(x => x.PromotionType == type);
}
public static void Replace(List<PromotionItem> 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<PromotionItem> items, List<PromotionItem> 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<PromotionOrder> items , PromotionType type)
{
return items.Exists(x => x.PromotionType == type);
}
public static void Replace(List<PromotionOrder> 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 );
}
}
}
}