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#

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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 );
}
}
}
}