/// <summary> /// 子订单发票计算 /// </summary> /// <param name="masterSOInfo"></param> /// <param name="subSOInfo"></param> private void AssignSubSOInvoice(SOInfo subSOInfo) { //如果子单金额小于等于1,并且开具了增值税发票,则将增票改为普票并记录修改日志 if (subSOInfo.InvoiceInfo.IsVAT.HasValue && subSOInfo.InvoiceInfo.IsVAT.Value) { decimal invoiceAmt = SOCommon.CalculateInvoiceAmount( subSOInfo.BaseInfo.CashPay, subSOInfo.BaseInfo.PremiumAmount.Value, subSOInfo.BaseInfo.ShipPrice.Value, subSOInfo.BaseInfo.PayPrice.Value, subSOInfo.BaseInfo.PromotionAmount.Value, subSOInfo.BaseInfo.GiftCardPay.Value, subSOInfo.BaseInfo.PayWhenReceived.Value); if (invoiceAmt <= 1M) { subSOInfo.InvoiceInfo.IsVAT = false; } } }
/// <summary> /// 分摊子订单 /// </summary> /// <param name="subSOList"></param> private void CalculateSubSO(List <SOInfo> subSOList) { // 按金额升序排列,保证分摊的最后订单的金额最大,减少分摊误差。 subSOList.Sort((o1, o2) => { return(o1.BaseInfo.SOAmount.Value.CompareTo(o2.BaseInfo.SOAmount.Value)); }); decimal masterSOTotalPrice = CurrentSO.BaseInfo.PromotionAmount.Value; //计算金额基数 decimal masterSOTotalWeight = 0; //计算重量基数 CurrentSO.Items.ForEach(item => { masterSOTotalPrice += item.Quantity.Value * item.OriginalPrice.Value; masterSOTotalWeight += item.Quantity.Value * item.Weight.Value; }); #region 分摊主的费用到子订单 int t_PointPay = CurrentSO.BaseInfo.PointPay.Value; decimal t_ShipPrice = CurrentSO.BaseInfo.ShipPrice.Value; decimal t_PayPrice = CurrentSO.BaseInfo.PayPrice.Value; decimal t_PremiumAmt = CurrentSO.BaseInfo.PremiumAmount.Value; decimal t_PrepayAmt = CurrentSO.BaseInfo.PrepayAmount.Value; decimal t_PromotionValue = CurrentSO.BaseInfo.CouponAmount.Value; decimal t_GiftCardPay = CurrentSO.BaseInfo.GiftCardPay.Value; decimal?t_OriginShipPrice = CurrentSO.ShippingInfo.OriginShipPrice ?? 0; decimal?t_PackageFee = CurrentSO.ShippingInfo.PackageFee ?? 0; decimal?t_RegisteredFee = CurrentSO.ShippingInfo.RegisteredFee ?? 0; decimal?t_ShippingFee = CurrentSO.ShippingInfo.ShippingFee ?? 0; decimal?t_Weight3PL = CurrentSO.ShippingInfo.Weight3PL ?? 0; decimal?t_WeightSO = CurrentSO.ShippingInfo.Weight ?? 0; int subSOIndex = 0; foreach (SOInfo soInfo in subSOList) { bool isLastSubSO = ++subSOIndex == subSOList.Count; decimal subSOWeight = 0; //订单总重量 decimal subSOTotalPrice = 0; //订单去优惠券折扣后的总价 soInfo.BaseInfo.PromotionAmount = 0; soInfo.BaseInfo.GainPoint = 0; soInfo.BaseInfo.CouponAmount = 0; soInfo.Items.ForEach(item => { item.SOSysNo = soInfo.SysNo; soInfo.BaseInfo.PromotionAmount += item.PromotionAmount.Value; //计算销售规则拆扣 soInfo.BaseInfo.GainPoint += item.GainPoint; //计算获得的积分 soInfo.BaseInfo.CouponAmount += item.CouponAmount; //计算优惠券折扣 subSOWeight += item.Weight.Value * item.Quantity.Value; //价格引用Price,而不是OriginalPrice,因为总价中不包含优惠券折扣。 subSOTotalPrice += item.Quantity.Value * item.Price.Value + item.PromotionAmount.Value; }); soInfo.ShippingInfo.Weight = subSOWeight; #region 分摊订单费用 decimal weightRate = subSOWeight / (masterSOTotalWeight <= 0 ? 1 : masterSOTotalWeight); //重量分摊比例 decimal priceRate = subSOTotalPrice / (masterSOTotalPrice <= 0 ? 1 : masterSOTotalPrice); //金额分摊比例 if (!isLastSubSO) // 不是最后一个子订单 { //根据重量来分摊运费 soInfo.BaseInfo.ShipPrice = UtilityHelper.ToMoney(CurrentSO.BaseInfo.ShipPrice.Value * weightRate); t_ShipPrice -= soInfo.BaseInfo.ShipPrice.Value; //根据价格来分摊积分支付 soInfo.BaseInfo.PointPay = (int)(Math.Round(CurrentSO.BaseInfo.PointPay.Value * priceRate)); t_PointPay -= soInfo.BaseInfo.PointPay.Value; soInfo.BaseInfo.PointPayAmount = Convert.ToDecimal(soInfo.BaseInfo.PointPay) / ExternalDomainBroker.GetPointToMoneyRatio(); //计算积分支付 //根据价格来分摊手续费 soInfo.BaseInfo.PayPrice = UtilityHelper.ToMoney(CurrentSO.BaseInfo.PayPrice.Value * priceRate); t_PayPrice -= soInfo.BaseInfo.PayPrice.Value; //根据价格来分摊积保价费 soInfo.BaseInfo.PremiumAmount = UtilityHelper.ToMoney(CurrentSO.BaseInfo.PremiumAmount.Value * priceRate); t_PremiumAmt -= soInfo.BaseInfo.PremiumAmount.Value; //余额支付的分摊比例 decimal priceRate_Prepay = soInfo.BaseInfo.SOTotalAmount / (CurrentSO.BaseInfo.SOTotalAmount <= 0 ? 1 : CurrentSO.BaseInfo.SOTotalAmount); //根据商品总价分摊余额支付 soInfo.BaseInfo.PrepayAmount = UtilityHelper.ToMoney(CurrentSO.BaseInfo.PrepayAmount.Value * priceRate_Prepay);//分摊余额支付 t_PrepayAmt -= soInfo.BaseInfo.PrepayAmount.Value; //根据商品总价分摊礼品卡支付 soInfo.BaseInfo.GiftCardPay = UtilityHelper.ToMoney(CurrentSO.BaseInfo.GiftCardPay.Value * priceRate_Prepay);//分摊礼品支付 t_GiftCardPay -= soInfo.BaseInfo.GiftCardPay.Value; } else // 最后一个子订单 { soInfo.BaseInfo.ShipPrice = UtilityHelper.ToMoney(t_ShipPrice); soInfo.BaseInfo.PointPay = t_PointPay; soInfo.BaseInfo.PointPayAmount = Convert.ToDecimal(soInfo.BaseInfo.PointPay) / ExternalDomainBroker.GetPointToMoneyRatio(); //计算积分支付 soInfo.BaseInfo.PayPrice = UtilityHelper.ToMoney(t_PayPrice); soInfo.BaseInfo.PremiumAmount = UtilityHelper.ToMoney(t_PremiumAmt); //余额支付的分摊比例 decimal priceRate_Prepay = soInfo.BaseInfo.SOTotalAmount / (CurrentSO.BaseInfo.SOTotalAmount <= 0 ? 1 : CurrentSO.BaseInfo.SOTotalAmount); soInfo.BaseInfo.PrepayAmount = UtilityHelper.ToMoney(t_PrepayAmt); soInfo.BaseInfo.GiftCardPay = UtilityHelper.ToMoney(t_GiftCardPay); } if (CurrentSO.SOGiftCardList.Count > 0) { decimal itemGiftCardPay = soInfo.BaseInfo.GiftCardPay.Value; foreach (ECCentral.BizEntity.IM.GiftCardRedeemLog giftCard in CurrentSO.SOGiftCardList) { if (itemGiftCardPay <= 0) { break; } if (giftCard.Amount <= 0) { continue; } if (giftCard.Amount >= itemGiftCardPay) { giftCard.Amount -= itemGiftCardPay; soInfo.SOGiftCardList.Add(new ECCentral.BizEntity.IM.GiftCardRedeemLog { Code = giftCard.Code, Amount = itemGiftCardPay }); itemGiftCardPay = 0; break; } else { itemGiftCardPay -= giftCard.Amount.Value; soInfo.SOGiftCardList.Add(new ECCentral.BizEntity.IM.GiftCardRedeemLog { Code = giftCard.Code, Amount = giftCard.Amount }); giftCard.Amount = 0; } if (itemGiftCardPay == 0M) { break; } } } if (IsAutoSplit) { soInfo.BaseInfo.Status = SOStatus.WaitingOutStock;//拆分后子单为待出库状态 } else { soInfo.BaseInfo.Status = SOStatus.Origin;//拆分后子单为待审核状态 } //拆单后需要重新计算每个子单是否是大件 soInfo.BaseInfo.IsLarge = SOCommon.ValidateIsLarge(soInfo.ShippingInfo.Weight.Value); // 是否大件商品 if (!isLastSubSO) { soInfo.ShippingInfo.OriginShipPrice = UtilityHelper.ToMoney((CurrentSO.ShippingInfo.OriginShipPrice ?? 0) * weightRate); t_OriginShipPrice -= soInfo.ShippingInfo.OriginShipPrice; soInfo.ShippingInfo.PackageFee = UtilityHelper.ToMoney((CurrentSO.ShippingInfo.PackageFee ?? 0) * weightRate); t_PackageFee -= soInfo.ShippingInfo.PackageFee; soInfo.ShippingInfo.RegisteredFee = UtilityHelper.ToMoney((CurrentSO.ShippingInfo.RegisteredFee ?? 0) * weightRate); t_RegisteredFee -= soInfo.ShippingInfo.RegisteredFee; soInfo.ShippingInfo.ShippingFee = UtilityHelper.ToMoney((CurrentSO.ShippingInfo.ShippingFee ?? 0) * weightRate); t_ShippingFee -= soInfo.ShippingInfo.ShippingFee; soInfo.ShippingInfo.Weight3PL = (int)((CurrentSO.ShippingInfo.Weight3PL ?? 0) * weightRate); t_Weight3PL -= soInfo.ShippingInfo.Weight3PL; soInfo.ShippingInfo.Weight = (int)((CurrentSO.ShippingInfo.Weight ?? 0) * weightRate); t_WeightSO -= soInfo.ShippingInfo.Weight; } else { soInfo.ShippingInfo.OriginShipPrice = t_OriginShipPrice; soInfo.ShippingInfo.PackageFee = t_PackageFee; soInfo.ShippingInfo.RegisteredFee = t_RegisteredFee; soInfo.ShippingInfo.ShippingFee = t_ShippingFee; soInfo.ShippingInfo.Weight3PL = t_Weight3PL; soInfo.ShippingInfo.Weight = t_WeightSO; } #endregion AssignSubSOPromotion(soInfo); AssignSubSOInvoice(soInfo); if (SubSOAssign != null) { SubSOAssign(soInfo); } List <ItemGrossProfitInfo> gorsses = new List <ItemGrossProfitInfo>(); foreach (ItemGrossProfitInfo gross in CurrentSO.ItemGrossProfitList) { foreach (SOItemInfo item in soInfo.Items) { if (gross.ProductSysNo == item.ProductSysNo) { ItemGrossProfitInfo subgross = SerializationUtility.DeepClone(gross); subgross.SOSysNo = soInfo.SysNo.Value; soInfo.ItemGrossProfitList.Add(subgross); } } } } #endregion }
public List <SOPriceMasterInfo> SplitSO() { bool isCombine = CurrentSO.ShippingInfo.IsCombine.HasValue ? CurrentSO.ShippingInfo.IsCombine.Value : false; decimal currenSOInvocieAmount = SOCommon.CalculateInvoiceAmount(CurrentSO.BaseInfo.CashPay, CurrentSO.BaseInfo.PremiumAmount.Value, CurrentSO.BaseInfo.ShipPrice.Value, CurrentSO.BaseInfo.PayPrice.Value, CurrentSO.BaseInfo.PromotionAmount.Value, CurrentSO.BaseInfo.GiftCardPay.Value, CurrentSO.BaseInfo.PayWhenReceived.Value); decimal currenSOReceivableAmount = CurrentSO.BaseInfo.ReceivableAmount; List <SOPriceMasterInfo> soPriceList = new List <SOPriceMasterInfo>(); if (CurrentSO.Items == null || CurrentSO.Items.Count == 0) { return(soPriceList);//BackOrder订单存在0 item的情况 } //排序的目的是为了最后一个商品的价格是最大的,不会因为减去折扣失败,导致重新计算 List <SOItemInfo> soItemList = CurrentSO.Items.OrderBy(item => item.Price) .Select(item => item) .ToList(); SOItemInfo soLastSOItem = soItemList.Last(); SOItemInfo soLastSOItemNoExtend = soItemList.Where(item => (item.ProductType != SOProductType.ExtendWarranty && item.ProductType != SOProductType.Coupon)).Last(); //拆分逻辑 decimal itemSumValue = CurrentSO.Items.Sum(x => x.Price.Value * x.Quantity.Value) + CurrentSO.BaseInfo.PromotionAmount.Value; //计算Item总重量,因为延保和优惠券Weight为0,这里不用排除 decimal totalWeight = CurrentSO.Items.Sum(x => x.Weight.Value * x.Quantity.Value); decimal residual_CashPay = CurrentSO.BaseInfo.CashPay; decimal residual_PayPrice = CurrentSO.BaseInfo.PayPrice.Value; decimal residual_PointPay = CurrentSO.BaseInfo.PointPayAmount.Value; decimal residual_PremiumAmt = CurrentSO.BaseInfo.PremiumAmount.Value; decimal residual_PrepayAmt = CurrentSO.BaseInfo.PrepayAmount.Value; decimal residual_ShippingCharge = CurrentSO.BaseInfo.ShipPrice.Value; decimal residual_GiftCardPay = CurrentSO.BaseInfo.GiftCardPay.Value; //找到所有优惠券 List <SOPriceItemInfo> couponProductPriceInfoList = new List <SOPriceItemInfo>(); //找到所有延保 List <SOPriceItemInfo> extendWarrentyProductPriceInfoList = new List <SOPriceItemInfo>(); soItemList.ForEach(item => { SOPriceItemInfo priceItem = new SOPriceItemInfo(); decimal itemRate = (item.Price.Value * item.Quantity.Value + item.PromotionAmount.Value) / (itemSumValue <= 0 ? 1 : itemSumValue); decimal itemRateForShippingCharge = item.Weight.Value * item.Quantity.Value / (totalWeight <= 0 ? 1 : totalWeight); priceItem.MasterProductSysNo = item.MasterProductSysNo; priceItem.PromotionAmount = item.PromotionAmount; priceItem.Price = item.Price; priceItem.OriginalPrice = item.OriginalPrice; priceItem.ProductSysNo = item.ProductSysNo; priceItem.ProductType = item.ProductType; priceItem.Quantity = item.Quantity; priceItem.CouponAmount = item.CouponAmount; priceItem.GainPoint = item.GainPoint; priceItem.MasterSysNo = 0;//暂时放仓库编号,作为分仓的中间变量 //对非优惠券项进行分摊 if (item.ProductType != SOProductType.Coupon) { if (item != soLastSOItem) { priceItem.PayPrice = UtilityHelper.ToMoney(CurrentSO.BaseInfo.PayPrice.Value * itemRate); residual_PayPrice -= priceItem.PayPrice.Value; priceItem.PointPayAmount = UtilityHelper.ToMoney(CurrentSO.BaseInfo.PointPayAmount.Value * itemRate); residual_PointPay -= priceItem.PointPayAmount.Value; priceItem.PremiumAmount = UtilityHelper.ToMoney(CurrentSO.BaseInfo.PremiumAmount.Value * itemRate); residual_PremiumAmt -= priceItem.PremiumAmount.Value; } else { priceItem.PayPrice = UtilityHelper.ToMoney(residual_PayPrice); priceItem.PointPayAmount = UtilityHelper.ToMoney(residual_PointPay); priceItem.PremiumAmount = UtilityHelper.ToMoney(residual_PremiumAmt); } if (item != soLastSOItemNoExtend) { priceItem.ShipPrice = UtilityHelper.ToMoney(CurrentSO.BaseInfo.ShipPrice.Value * itemRateForShippingCharge); residual_ShippingCharge -= priceItem.ShipPrice.Value; } else { priceItem.ShipPrice = UtilityHelper.ToMoney(residual_ShippingCharge); } //计算现金支付 priceItem.CashPay = UtilityHelper.ToMoney(CalculateSOPriceItemCashPay(priceItem)); decimal priceRate_Prepay = (priceItem.CashPay.Value + priceItem.PayPrice.Value + priceItem.ShipPrice.Value + priceItem.PromotionAmount.Value + priceItem.PremiumAmount.Value) / (CurrentSO.BaseInfo.SOTotalAmount <= 0 ? 1 : CurrentSO.BaseInfo.SOTotalAmount); if (item != soLastSOItem) { priceItem.PrepayAmount = UtilityHelper.ToMoney(CurrentSO.BaseInfo.PrepayAmount.Value * priceRate_Prepay); residual_PrepayAmt -= priceItem.PrepayAmount.Value; priceItem.GiftCardPay = UtilityHelper.ToMoney(CurrentSO.BaseInfo.GiftCardPay.Value * priceRate_Prepay); residual_GiftCardPay -= priceItem.GiftCardPay.Value; } else { priceItem.PrepayAmount = UtilityHelper.ToMoney(residual_PrepayAmt); priceItem.GiftCardPay = UtilityHelper.ToMoney(residual_GiftCardPay); } priceItem.ExtendPrice = priceItem.OriginalPrice * priceItem.Quantity; priceItem.InvoiceAmount = item.OriginalPrice * item.Quantity; } // 根据仓库编号将订单商品价格信息分组 switch (item.ProductType.Value) { case SOProductType.Product: case SOProductType.Gift: case SOProductType.Award: case SOProductType.Accessory: case SOProductType.SelfGift: { SOPriceMasterInfo soPriceInfo = soPriceList.Find((p) => { return(p.StockSysNo == item.StockSysNo); }); if (soPriceInfo == null) { soPriceInfo = new SOPriceMasterInfo(); soPriceInfo.StockSysNo = item.StockSysNo; soPriceList.Add(soPriceInfo); } soPriceInfo.Items.Add(priceItem); break; } case SOProductType.Coupon: couponProductPriceInfoList.Add(priceItem); break; case SOProductType.ExtendWarranty: extendWarrentyProductPriceInfoList.Add(priceItem); break; } }); int i = 0; foreach (SOPriceMasterInfo soPriceInfo in soPriceList) { i++; //添加优惠券到每个分仓 soPriceInfo.Items.AddRange(couponProductPriceInfoList); //延保跟随主商品 extendWarrentyProductPriceInfoList.ForEach(item => { if (soPriceInfo.Items.Exists(o => o.ProductSysNo == int.Parse(item.MasterProductSysNo))) { soPriceInfo.Items.Add(item); } }); soPriceInfo.CashPay = soPriceInfo.Items.Sum(item => item.CashPay); soPriceInfo.PromotionAmount = soPriceInfo.Items.Sum(item => item.PromotionAmount); soPriceInfo.PayPrice = soPriceInfo.Items.Sum(item => item.PayPrice); soPriceInfo.PointPayAmount = soPriceInfo.Items.Sum(item => item.PointPayAmount); soPriceInfo.PremiumAmount = soPriceInfo.Items.Sum(item => item.PremiumAmount); soPriceInfo.PrepayAmount = soPriceInfo.Items.Sum(item => item.PrepayAmount); soPriceInfo.CouponAmount = soPriceInfo.Items.Sum(item => item.CouponAmount); soPriceInfo.ShipPrice = soPriceInfo.Items.Sum(item => item.ShipPrice); soPriceInfo.GainPoint = soPriceInfo.Items.Sum(item => item.GainPoint); soPriceInfo.GiftCardPay = soPriceInfo.Items.Sum(item => item.GiftCardPay); soPriceInfo.SOAmount = UtilityHelper.ToMoney(soPriceInfo.Items .Where(item => item.ProductType == SOProductType.Product || item.ProductType == SOProductType.ExtendWarranty) .Sum(item => item.OriginalPrice.Value * item.Quantity.Value)); decimal substactAmt = 0; //模式4,发票金额为0 if (CurrentSO.InvoiceInfo.InvoiceType == InvoiceType.MET && CurrentSO.ShippingInfo.StockType == StockType.SELF && CurrentSO.ShippingInfo.ShippingType == ECCentral.BizEntity.Invoice.DeliveryType.SELF) { foreach (SOPriceItemInfo subItem in soPriceInfo.Items) { substactAmt += subItem.Price.Value * subItem.Quantity.Value; subItem.InvoiceAmount = 0; } } //商家仓储,商家开票 if (CurrentSO.ShippingInfo.StockType == StockType.MET && CurrentSO.InvoiceInfo.InvoiceType == InvoiceType.MET) { foreach (SOPriceItemInfo subItem in soPriceInfo.Items) { substactAmt += subItem.Price.Value * subItem.Quantity.Value; subItem.InvoiceAmount = 0; } } //代收代付的商品需减去InvocieAmt currenSOInvocieAmount -= substactAmt; if (i == soPriceList.Count) { soPriceInfo.InvoiceAmount = CalculateInvoiceAmount(soPriceInfo, CurrentSO.BaseInfo.PayWhenReceived.Value, isCombine) - substactAmt; currenSOInvocieAmount -= soPriceInfo.InvoiceAmount.Value; soPriceInfo.ReceivableAmount = CalculateReceivableAmount(soPriceInfo, CurrentSO.BaseInfo.PayWhenReceived.Value, isCombine); currenSOReceivableAmount -= soPriceInfo.ReceivableAmount.Value; } else { soPriceInfo.InvoiceAmount = currenSOInvocieAmount; soPriceInfo.ReceivableAmount = currenSOReceivableAmount; } soPriceInfo.InvoiceAmount = soPriceInfo.InvoiceAmount < 0 ? 0 : soPriceInfo.InvoiceAmount; soPriceInfo.SOSysNo = SOSysNo; soPriceInfo.Status = SOPriceStatus.Original; } TransactionOptions options = new TransactionOptions(); options.IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted; using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, options)) { //初始化数据,如果存在则删除 SOPriceDA.DeleteSOPriceBySOSysNo(SOSysNo); foreach (SOPriceMasterInfo priceInfo in soPriceList) { SOPriceDA.InsertSOPrice(priceInfo, CurrentSO.CompanyCode); foreach (SOPriceItemInfo priceItem in priceInfo.Items) { priceItem.MasterSysNo = priceInfo.SysNo; SOPriceDA.InsertSOPriceItem(priceItem, SOSysNo, CurrentSO.CompanyCode); } } scope.Complete(); } return(soPriceList); }