using BBWY.Common.Extensions;
using BBWY.Common.Http;
using BBWY.Common.Models;
using BBWY.Server.Business.Extensions;
using BBWY.Server.Model;
using BBWY.Server.Model.Db;
using BBWY.Server.Model.Db.Mds;
using BBWY.Server.Model.Dto;
using FreeSql;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Net.Http;
using Yitter.IdGenerator;

namespace BBWY.Server.Business
{
    public class OrderBusiness : BasePlatformRelayBusiness, IDenpendency
    {
        private IFreeSql fsql;

        private IIdGenerator idGenerator;

        private Lazy<ProductBusiness> productBusinessLazy;
        private ProductBusiness productBusiness => productBusinessLazy.Value;

        private Lazy<FreeSqlMultiDBManager> freeSqlMultiDBManagerLazy;
        private FreeSqlMultiDBManager freeSqlMultiDBManager => freeSqlMultiDBManagerLazy.Value;

        private IMemoryCache memoryCache;
        private static TimeSpan sdGroupExpirationTimeSpan = TimeSpan.FromMinutes(20);

        public OrderBusiness(RestApiService restApiService,
                             IFreeSql fsql,
                             IIdGenerator idGenerator,
                             IOptions<GlobalConfig> options,
                             IServiceProvider serviceProvider,
                             IMemoryCache memoryCache) : base(restApiService, options)
        {
            this.fsql = fsql;
            this.idGenerator = idGenerator;
            this.memoryCache = memoryCache;
            freeSqlMultiDBManagerLazy = new Lazy<FreeSqlMultiDBManager>(() => serviceProvider.GetService<FreeSqlMultiDBManager>());
            productBusinessLazy = new Lazy<ProductBusiness>(() => serviceProvider.GetService<ProductBusiness>());
        }

        private ISelect<Order, OrderConsignee, OrderCost> GetOrderListQueryConditions(SearchOrderRequest searchOrderRequest)
        {
            var select = fsql.Select<Order, OrderConsignee, OrderCost>().LeftJoin((o, ocs, oct) => o.Id == ocs.OrderId)
                                                                        .LeftJoin((o, ocs, oct) => o.Id == oct.OrderId);
            if (!string.IsNullOrEmpty(searchOrderRequest.OrderId))
            {
                select = select.Where((o, ocs, oct) => o.Id == searchOrderRequest.OrderId);
            }
            else
            {
                if (!string.IsNullOrEmpty(searchOrderRequest.Sku) || !string.IsNullOrEmpty(searchOrderRequest.ProductNo) || !string.IsNullOrEmpty(searchOrderRequest.ProductId))
                {
                    var childSelect = fsql.Select<OrderSku>().As("osku")
                                          .WhereIf(!string.IsNullOrEmpty(searchOrderRequest.Sku), osku => osku.SkuId == searchOrderRequest.Sku)
                                          .WhereIf(!string.IsNullOrEmpty(searchOrderRequest.ProductId), osku => osku.ProductId == searchOrderRequest.ProductId)
                                          .WhereIf(!string.IsNullOrEmpty(searchOrderRequest.ProductNo), osku => osku.ProductNo == searchOrderRequest.ProductNo);
                    select = select.Where((o, ocs, oct) => childSelect.Where(osku => osku.OrderId == o.Id).Any());
                }

                select = select.WhereIf(searchOrderRequest.OrderState != null, (o, ocs, oct) => o.OrderState == searchOrderRequest.OrderState)
                               .WhereIf(searchOrderRequest.StartDate != null, (o, ocs, oct) => o.StartTime >= searchOrderRequest.StartDate)
                               .WhereIf(searchOrderRequest.EndDate != null, (o, ocs, oct) => o.StartTime <= searchOrderRequest.EndDate)
                               .WhereIf(searchOrderRequest.IncludeExceptionOrder,
                                        (o, ocs, oct) => o.OrderState != Enums.OrderState.已取消 &&
                                                         ((o.StorageType != Enums.StorageType.SD && o.StorageType != null && oct.PurchaseAmount == 0M) ||
                                                         (o.StorageType != Enums.StorageType.SD && oct.PurchaseAmount + oct.DeliveryExpressFreight > o.OrderSellerPrice + o.FreightPrice) ||
                                                         (o.StorageType == null && o.OrderState != Enums.OrderState.等待采购)))
                               .WhereIf(searchOrderRequest.OnlyDF, (o, ocs, oct) => o.StorageType == Enums.StorageType.代发)
                               .WhereIf(searchOrderRequest.ExcludeCanceled, (o, ocs, oct) => o.OrderState != Enums.OrderState.已取消)
                               .WhereIf(searchOrderRequest.ExcludeSD && !searchOrderRequest.OnlyDF, (o, ocs, oct) => o.StorageType == null || o.StorageType != Enums.StorageType.SD)
                               .WhereIf(string.IsNullOrEmpty(searchOrderRequest.ContactName) == false, (o, ocs, oct) => ocs.ContactName == searchOrderRequest.ContactName)
                               .WhereIf(string.IsNullOrEmpty(searchOrderRequest.Waybill) == false, (o, ocs, oct) => o.WaybillNo == searchOrderRequest.Waybill);
            }

            select = select.WhereIf(searchOrderRequest.ShopId != null, (o, ocs, oct) => o.ShopId == searchOrderRequest.ShopId)
                           .WhereIf(!string.IsNullOrEmpty(searchOrderRequest.SDOperator), (o, ocs, oct) => o.SDOperator == searchOrderRequest.SDOperator);

            //select = select.Where((o, ocs, oct) => o.ShopId == searchOrderRequest.ShopId);

            return select;
        }

        private Expression<Func<Order, OrderConsignee, OrderCost, Order>> GetOrderListField()
        {
            return (o, ocs, oct) => new Order()
            {
                Id = o.Id,
                BuyerRemark = o.BuyerRemark,
                EndTime = o.EndTime,
                FreightPrice = o.FreightPrice,
                ModifyTime = o.ModifyTime,
                OrderPayment = o.OrderPayment,
                OrderSellerPrice = o.OrderSellerPrice,
                OrderState = o.OrderState,
                OrderTotalPrice = o.OrderTotalPrice,
                OrderType = o.OrderType,
                PayType = o.PayType,
                Platform = o.Platform,
                ShopId = o.ShopId,
                StartTime = o.StartTime,
                StorageType = o.StorageType,
                StoreId = o.StoreId,
                StoreOrder = o.StoreOrder,
                VenderRemark = o.VenderRemark,
                PurchaseRemark = o.PurchaseRemark,
                WaybillNo = o.WaybillNo,
                Flag = o.Flag,
                SDType = o.SDType,
                SDKey = o.SDKey,
                SDOperator = o.SDOperator,
                SDPayBillNo = o.SDPayBillNo,
                SDPayChannel = o.SDPayChannel,
                IsAfterSaleOrder = o.IsAfterSaleOrder,
                SellerPreferentialAmount = o.SellerPreferentialAmount,
                PreferentialAmount = o.PreferentialAmount,

                ContactName = ocs.ContactName,
                Address = ocs.Address,
                Province = ocs.Province,
                County = ocs.County,
                Town = ocs.Town,
                City = ocs.City,
                IsDecode = ocs.IsDecode,
                Mobile = ocs.Mobile,
                TelePhone = ocs.TelePhone,

                DeliveryExpressFreight = oct.DeliveryExpressFreight,
                PlatformCommissionAmount = oct.PlatformCommissionAmount,
                PlatformCommissionRatio = oct.PlatformCommissionRatio,
                //PreferentialAmount = oct.PreferentialAmount,
                Profit = oct.Profit,
                PurchaseAmount = oct.PurchaseAmount,
                IsManualEdited = oct.IsManualEdited,
                SDCommissionAmount = oct.SDCommissionAmount,
                SDOrderAmount = oct.SDOrderAmount,
                RefundAmount = oct.RefundAmount,
                RefundPurchaseAmount = oct.RefundPurchaseAmount,
                AfterTotalCost = oct.AfterTotalCost
            };
        }

        public OrderListResponse GetOrderList(SearchOrderRequest searchOrderRequest)
        {
            if (searchOrderRequest.OrderState == Enums.OrderState.已取消)
                searchOrderRequest.ExcludeCanceled = false;
            if (searchOrderRequest.EndDate != null)
                searchOrderRequest.EndDate = searchOrderRequest.EndDate.Value.Date.AddDays(1).AddSeconds(-1);


            //var noCancelSelect = GetOrderListQueryConditions(searchOrderRequest);
            //var currentConditionsTotalProfit = noCancelSelect.Where((o, ocs, oct) => o.OrderState != Enums.OrderState.已取消).ToAggregate((o, ocs, oct) => oct.Sum(oct.Key.Profit));

            var select = GetOrderListQueryConditions(searchOrderRequest).OrderByDescending((o, ocs, oct) => o.StartTime)
                                                                        .Count(out var total)
                                                                        .Page(searchOrderRequest.PageIndex, searchOrderRequest.PageSize);

            var orderSourceList = select.ToList(GetOrderListField());
            var orderList = orderSourceList.Map<IList<OrderResponse>>();

            if (orderList.Count > 0)
            {
                var orderIdList = orderList.Select(o => o.Id).ToList();

                #region 处理代发信息
                var orderDropShippingList = fsql.Select<OrderDropShipping>().Where(ods => orderIdList.Contains(ods.OrderId))
                                                                            .ToList()
                                                                            .Map<IList<OrderDropShippingResponse>>();
                foreach (var order in orderList)
                {
                    order.OrderDropShippingList = orderDropShippingList.Where(ods => ods.OrderId == order.Id && ods.IsHistory == false).ToList();
                    order.HistoryOrderDropShippingList = orderDropShippingList.Where(ods => ods.OrderId == order.Id && ods.IsHistory).ToList();
                }
                  
                #endregion

                #region 处理Sku
                var orderSkuList = fsql.Select<OrderSku>().Where(osku => orderIdList.Contains(osku.OrderId)).ToList().Map<IList<OrderSkuResponse>>();
                foreach (var order in orderList)
                {
                    order.ItemList = orderSkuList.Where(osku => osku.OrderId == order.Id).ToList();
                    if (order.StorageType == Enums.StorageType.代发)
                    {
                        foreach (var orderSku in order.ItemList)
                        {
                            if (orderSku.OrderDropShippingId == null && (order.OrderDropShippingList?.Count() ?? 0) > 0)
                                orderSku.OrderDropShippingId = order.OrderDropShippingList[0].Id;
                        }
                    }
                }

                #endregion

                #region 处理优惠券
                var orderCouponList = fsql.Select<OrderCoupon>().Where(oc => orderIdList.Contains(oc.OrderId)).ToList().Map<IList<OrderCouponResponse>>();
                foreach (var order in orderList)
                    order.OrderCouponList = orderCouponList.Where(oc => oc.OrderId == order.Id).ToList();
                #endregion

                #region 处理订单成本明细
                var orderCostDetailList = fsql.Select<OrderCostDetail>().Where(ocd => orderIdList.Contains(ocd.OrderId) && ocd.IsEnabled == true).ToList().Map<IList<OrderCostDetailResponse>>();
                foreach (var order in orderList)
                    order.OrderCostDetailList = orderCostDetailList.Where(ocd => ocd.OrderId == order.Id).ToList();
                #endregion

                #region 处理售后信息
                var afterSaleOrderList = fsql.Select<AfterSaleOrder>().Where(aso => orderIdList.Contains(aso.OrderId)).ToList<AfterSaleOrderResponse>();
                foreach (var order in orderList)
                    order.AfterSaleOrderList = afterSaleOrderList.Where(aso => aso.OrderId == order.Id).ToList();
                #endregion

                #region 翻译仓库Id
                foreach (var order in orderList)
                    order.StoreName = globalConfig.Stores.FirstOrDefault(s => s.StoreId == order.StoreId)?.StoreName ?? order.StoreId;
                #endregion
            }

            var response = new OrderListResponse()
            {
                Count = total,
                Items = orderList,
                //CurrentConditionsTotalProfit = currentConditionsTotalProfit
            };
            return response;
        }

        public IList<ExportOrderResponse> ExportOrderList(SearchOrderRequest searchOrderRequest)
        {
            if (searchOrderRequest.OrderState == Enums.OrderState.已取消)
                searchOrderRequest.ExcludeCanceled = false;
            if (searchOrderRequest.EndDate != null)
                searchOrderRequest.EndDate = searchOrderRequest.EndDate.Value.Date.AddDays(1).AddSeconds(-1);

            var select = fsql.Select<Order, OrderConsignee, OrderCost>().LeftJoin((o, ocs, oct) => o.Id == ocs.OrderId)
                                                                        .LeftJoin((o, ocs, oct) => o.Id == oct.OrderId);

            if (!string.IsNullOrEmpty(searchOrderRequest.OrderId))
            {
                select = select.Where((o, ocs, oct) => o.Id == searchOrderRequest.OrderId);
            }
            else
            {
                if (!string.IsNullOrEmpty(searchOrderRequest.Sku) || !string.IsNullOrEmpty(searchOrderRequest.ProductNo))
                {
                    var childSelect = fsql.Select<OrderSku>().As("osku")
                                          .WhereIf(string.IsNullOrEmpty(searchOrderRequest.Sku) == false, osku => osku.SkuId == searchOrderRequest.Sku)
                                          .WhereIf(string.IsNullOrEmpty(searchOrderRequest.ProductNo) == false, osku => osku.ProductNo == searchOrderRequest.ProductNo);
                    select = select.Where((o, ocs, oct) => childSelect.Where(osku => osku.OrderId == o.Id).Any());
                }

                select = select.WhereIf(searchOrderRequest.OrderState != null, (o, ocs, oct) => o.OrderState == searchOrderRequest.OrderState)
                               .WhereIf(searchOrderRequest.StartDate != null, (o, ocs, oct) => o.StartTime >= searchOrderRequest.StartDate)
                               .WhereIf(searchOrderRequest.EndDate != null, (o, ocs, oct) => o.StartTime <= searchOrderRequest.EndDate)
                               .WhereIf(searchOrderRequest.OnlyDF, (o, ocs, oct) => o.StorageType == Enums.StorageType.代发)
                               .WhereIf(searchOrderRequest.ExcludeCanceled, (o, ocs, oct) => o.OrderState != Enums.OrderState.已取消)
                               .WhereIf(searchOrderRequest.ExcludeSD && !searchOrderRequest.OnlyDF, (o, ocs, oct) => o.StorageType == null || o.StorageType != Enums.StorageType.SD)
                               .WhereIf(string.IsNullOrEmpty(searchOrderRequest.ContactName) == false, (o, ocs, oct) => ocs.ContactName == searchOrderRequest.ContactName)
                               .WhereIf(string.IsNullOrEmpty(searchOrderRequest.Waybill) == false, (o, ocs, oct) => o.WaybillNo == searchOrderRequest.Waybill);
            }

            select = select.Where((o, ocs, oct) => o.ShopId == searchOrderRequest.ShopId)
                           .OrderByDescending((o, ocs, oct) => o.StartTime);

            var orderSourceList = select.ToList((o, ocs, oct) => new ExportOrderResponse()
            {
                OrderId = o.Id,
                FreightPrice = o.FreightPrice,
                OrderTotalPrice = o.OrderTotalPrice,
                OrderStartTime = o.StartTime.Value,
                StorageType = o.StorageType,
                ConsigneeStr = ocs.ContactName + "|" + ocs.Mobile + "|" + ocs.Province + ocs.City + ocs.County + ocs.Address,
                DeliveryExpressFreight = oct.DeliveryExpressFreight,
                PlatformCommissionAmount = oct.PlatformCommissionAmount,
                Profit = oct.Profit,
                TotalCost = oct.SDCommissionAmount + oct.SDOrderAmount + oct.PlatformCommissionAmount + oct.PurchaseAmount + oct.DeliveryExpressFreight,
                //PurchaseOrderIds = ods.PurchaseOrderId,
                OrderState = o.OrderState.Value,
                VenderRemark = o.VenderRemark,
                OrderPayment = o.OrderPayment,
                OrderSellerPrice = o.OrderSellerPrice
            });

            var orderIdList = orderSourceList.Select(o => o.OrderId).ToList();
            var orderSkuList = fsql.Select<OrderSku>().Where(osku => orderIdList.Contains(osku.OrderId)).ToList();
            var orderCostDetailGroup = fsql.Select<OrderCostDetail>().Where(ocd => orderIdList.Contains(ocd.OrderId) && ocd.IsEnabled == true)
                                                                    .GroupBy(ocd => ocd.OrderId).ToList(g => new
                                                                    {
                                                                        OrderId = g.Key,
                                                                        SkuAmount = g.Sum(g.Value.SkuAmount),
                                                                        FirstFreight = g.Sum(g.Value.FirstFreight),
                                                                        StorageAmount = g.Sum(g.Value.StorageAmount),
                                                                        PurchaseFreight = g.Sum(g.Value.PurchaseFreight)
                                                                    });
            var orderDropShippingList = fsql.Select<OrderDropShipping>().Where(ods => orderIdList.Contains(ods.OrderId) && ods.IsHistory == false).ToList();

            foreach (var order in orderSourceList)
            {
                var statistics = orderCostDetailGroup.FirstOrDefault(g => g.OrderId == order.OrderId);
                order.FirstFreight = statistics?.FirstFreight ?? 0M;
                order.PurchaseSkuAmount = statistics?.SkuAmount ?? 0M;
                order.PurchaseFreight = statistics?.PurchaseFreight ?? 0M;
                order.StorageAmount = statistics?.StorageAmount ?? 0M;
                order.SkuIds = string.Join("|", orderSkuList.Where(osku => osku.OrderId == order.OrderId).Select(osku => osku.SkuId));
                order.ProfitRatio = order.TotalCost == 0 ? 0 : Math.Round(order.Profit / order.TotalCost * 100, 2);
                if (order.StorageType == Enums.StorageType.代发)
                    order.PurchaseOrderIds = string.Join("|", orderDropShippingList.Where(ods => ods.OrderId == order.OrderId).Select(ods => ods.PurchaseOrderId));
            }
            return orderSourceList;

        }

        public OrderResponse GetOrderById(string orderId)
        {
            var order = fsql.Select<Order, OrderConsignee, OrderCost>().LeftJoin((o, ocs, oct) => o.Id == ocs.OrderId)
                                                                       .LeftJoin((o, ocs, oct) => o.Id == oct.OrderId)
                                                                       .Where((o, ocs, oct) => o.Id == orderId)
                                                                       .ToOne(GetOrderListField());
            if (order == null)
                throw new BusinessException("订单不存在");

            var orderResponse = order.Map<OrderResponse>();
            var orderSkuList = fsql.Select<OrderSku>().Where(osku => osku.OrderId == orderId).ToList().Map<IList<OrderSkuResponse>>();
            var orderCouponList = fsql.Select<OrderCoupon>().Where(oc => oc.OrderId == orderId).ToList().Map<IList<OrderCouponResponse>>();
            var orderCostDetailList = fsql.Select<OrderCostDetail>().Where(ocd => ocd.OrderId == orderId && ocd.IsEnabled == true).ToList().Map<IList<OrderCostDetailResponse>>();
            var orderDropShippingList = fsql.Select<OrderDropShipping>().Where(ods => ods.OrderId == orderId).ToList().Map<IList<OrderDropShippingResponse>>();

            if (order.IsAfterSaleOrder)
                orderResponse.AfterSaleOrderList = fsql.Select<AfterSaleOrder>().Where(aso => aso.OrderId == orderId).ToList<AfterSaleOrderResponse>();

            //orderResponse.OrderDropShippingList = orderDropShippingList;
            orderResponse.OrderDropShippingList = orderDropShippingList.Where(ods => ods.IsHistory == false).ToList();
            orderResponse.HistoryOrderDropShippingList = orderDropShippingList.Where(ods => ods.IsHistory).ToList();
            orderResponse.ItemList = orderSkuList;
            if (order.StorageType == Enums.StorageType.代发)
            {
                foreach (var orderSku in orderResponse.ItemList)
                {
                    if (orderSku.OrderDropShippingId == null && (orderResponse.OrderDropShippingList?.Count() ?? 0) > 0)
                        orderSku.OrderDropShippingId = orderResponse.OrderDropShippingList[0].Id;
                }
            }

            orderResponse.OrderCouponList = orderCouponList;
            orderResponse.OrderCostDetailList = orderCostDetailList;
            orderResponse.StoreName = globalConfig.Stores.FirstOrDefault(s => s.StoreId == orderResponse.StoreId)?.StoreName ?? order.StoreId;
            return orderResponse;
        }

        public IList<OrderBelongShopResponse> GetOrderBelongShop(IList<string> orderIdList)
        {
            var orderGroups = fsql.Select<Order>().Where(o => orderIdList.Contains(o.Id)).ToList(o => new { o.ShopId, OrderId = o.Id }).GroupBy(o => o.ShopId);
            var shopIdList = orderGroups.Select(o => o.Key.ToString()).ToList();
            var shops = freeSqlMultiDBManager.MDSfsql.Select<Shops>().Where(s => shopIdList.Contains(s.ShopId)).ToList(s => new { s.ShopId, s.ShopName });
            var list = new List<OrderBelongShopResponse>();
            foreach (var orderGroup in orderGroups)
            {
                var shop = shops.FirstOrDefault(s => s.ShopId == orderGroup.Key.ToString());
                if (shop == null)
                    continue;
                var orderBelongShop = new OrderBelongShopResponse()
                {
                    ShopId = orderGroup.Key,
                    ShopName = shop.ShopName,
                    OrderIdList = orderGroup.Select(x => x.OrderId).ToList()
                };
                list.Add(orderBelongShop);
            }
            return list;
        }

        /// <summary>
        /// 解密
        /// </summary>
        /// <param name="decryptConsigneeRequest"></param>
        /// <returns></returns>
        /// <exception cref="BusinessException"></exception>
        public ConsigneeSimpleResponse DecryptConsignee(DecryptConsigneeRequest decryptConsigneeRequest)
        {
            var relayAPIHost = GetPlatformRelayAPIHost(decryptConsigneeRequest.Platform);
            var sendResult = restApiService.SendRequest(relayAPIHost, "api/PlatformSDK/DecryptConsignee", decryptConsigneeRequest, null, HttpMethod.Post);
            if (sendResult.StatusCode != System.Net.HttpStatusCode.OK)
                throw new BusinessException(sendResult.Content) { Code = (int)sendResult.StatusCode };
            var response = JsonConvert.DeserializeObject<ApiResponse<ConsigneeSimpleResponse>>(sendResult.Content);
            if (!response.Success)
                throw new BusinessException(response.Msg) { Code = response.Code };

            if (!string.IsNullOrEmpty(decryptConsigneeRequest.PlaintextMobile))
                response.Data.Mobile = decryptConsigneeRequest.PlaintextMobile;

            //将解密后的收货人信息存至数据库
            if (decryptConsigneeRequest.SaveDb)
            {
                fsql.Update<OrderConsignee>(decryptConsigneeRequest.OrderId).Set(oc => oc.ContactName, response.Data.ContactName)
                                                                            .Set(oc => oc.Address, response.Data.Address)
                                                                            .SetIf(!string.IsNullOrEmpty(response.Data.Mobile), oc => oc.Mobile, response.Data.Mobile)
                                                                            .SetIf(!string.IsNullOrEmpty(response.Data.TelePhone), oc => oc.TelePhone, response.Data.TelePhone)
                                                                            .Set(oc => oc.IsDecode, true)
                                                                            .ExecuteAffrows();
            }
            return response.Data;
        }

        /// <summary>
        /// 自动计算成本
        /// </summary>
        /// <param name="autoCalculationCostRequest"></param>
        public void AutoCalculationCost(AutoCalculationCostRequest autoCalculationCostRequest)
        {
            var dbOrder = fsql.Select<Order>(autoCalculationCostRequest.OrderId).ToOne();
            if (dbOrder == null)
                throw new BusinessException($"订单号{autoCalculationCostRequest.OrderId}不存在");

            var orderSkus = fsql.Select<OrderSku>().Where(osku => osku.OrderId == autoCalculationCostRequest.OrderId).ToList();
            var orderSkuIds = orderSkus.Select(osku => osku.SkuId).ToList();
            var purchaserOrders = fsql.Select<PurchaseOrder>().Where(po => po.StorageType == autoCalculationCostRequest.StorageType &&
                                                                           po.RemainingQuantity != 0 &&
                                                                           orderSkuIds.Contains(po.SkuId)).ToList();
            if (purchaserOrders.Count() == 0)
                throw new BusinessException("库存为零不能自动计算成本");
            var dbAfterSaleOrderList = fsql.Select<AfterSaleOrder>().Where(aso => aso.OrderId == autoCalculationCostRequest.OrderId).ToList();

            var orderCost = fsql.Select<OrderCost>(autoCalculationCostRequest.OrderId).ToOne();
            var orderCostDetails = fsql.Select<OrderCostDetail>().Where(ocd => ocd.OrderId == autoCalculationCostRequest.OrderId && ocd.IsEnabled == true).ToList();

            IUpdate<Order> orderUpdate = null;
            IUpdate<OrderCost> updateOrderCost = null;
            IInsert<OrderCost> insertOrderCost = null;
            IList<IUpdate<PurchaseOrder>> updatePurchaseOrderList = new List<IUpdate<PurchaseOrder>>();
            List<OrderCostDetail> insertOrderCostDetailList = new List<OrderCostDetail>();

            if (autoCalculationCostRequest.IsSetStorageType)
                orderUpdate = fsql.Update<Order>(autoCalculationCostRequest.OrderId).Set(o => o.StorageType, autoCalculationCostRequest.StorageType);

            var orderCostPurchaseAmount = 0M;
            var orderDeliveryExpressFreight = 0M; //发货总运费,sku购买数量第二个开始半价
            foreach (var orderSku in orderSkus)
            {
                //查询该sku的扣减明细
                var currentOrderSkuCostDetails = orderCostDetails.Where(ocd => ocd.SkuId == orderSku.SkuId);
                //已扣减数量
                var deductedQuantity = currentOrderSkuCostDetails.Count() == 0 ? 0 : currentOrderSkuCostDetails.Sum(ocd => ocd.DeductionQuantity);
                //剩余扣减数量
                var noDeductionQuantity = orderSku.ItemTotal.Value - deductedQuantity;
                if (noDeductionQuantity <= 0)
                    continue;

                //是否多次扣减库存
                var isReduceMultiTimes = false;
                if (currentOrderSkuCostDetails.Count() > 0)
                    isReduceMultiTimes = true;  //之前有过扣减记录,发货运费按半价计算

                while (noDeductionQuantity != 0)
                {
                    var purchaseOrder = purchaserOrders.FirstOrDefault(po => po.StorageType == autoCalculationCostRequest.StorageType &&
                                                                                               po.RemainingQuantity != 0 &&
                                                                                               po.SkuId == orderSku.SkuId);
                    if (purchaseOrder == null)
                        break; //没有库存了


                    //本次扣减数量
                    var deductionQuantity = purchaseOrder.RemainingQuantity >= noDeductionQuantity ? noDeductionQuantity : purchaseOrder.RemainingQuantity;
                    //本次扣减量的采购成本
                    var currentPurchaseAmount = purchaseOrder.UnitCost * deductionQuantity;
                    //本次扣减量的发货运费
                    var currentSkuDeliveryFreight = isReduceMultiTimes ?
                                                    (purchaseOrder.SingleDeliveryFreight / 2 * deductionQuantity) :
                                                    (purchaseOrder.SingleDeliveryFreight + purchaseOrder.SingleDeliveryFreight / 2 * (deductionQuantity - 1));
                    isReduceMultiTimes = true;

                    noDeductionQuantity -= deductionQuantity;
                    purchaseOrder.RemainingQuantity -= deductionQuantity;

                    //累计采购成本
                    orderCostPurchaseAmount += currentPurchaseAmount;
                    //累计发货运费(销售运费)
                    orderDeliveryExpressFreight += currentSkuDeliveryFreight;

                    var updateSql = fsql.Update<PurchaseOrder>(purchaseOrder.Id).Set(po => po.RemainingQuantity - deductionQuantity);
                    updatePurchaseOrderList.Add(updateSql);

                    var orderCostDetail = new OrderCostDetail()
                    {
                        Id = idGenerator.NewLong(),
                        OrderId = autoCalculationCostRequest.OrderId,
                        ProductId = orderSku.ProductId,
                        SkuId = orderSku.SkuId,
                        CreateTime = DateTime.Now,
                        PurchaseOrderPKId = purchaseOrder.Id,
                        //UnitCost = purchaseOrder.UnitCost,
                        DeductionQuantity = deductionQuantity,
                        DeliveryExpressFreight = currentSkuDeliveryFreight,
                        //TotalCost = currentPurchaseAmount,
                        ConsumableAmount = purchaseOrder.SingleConsumableAmount * deductionQuantity,
                        FirstFreight = purchaseOrder.SingleFirstFreight * deductionQuantity,
                        InStorageAmount = purchaseOrder.SingleInStorageAmount * deductionQuantity,
                        OutStorageAmount = purchaseOrder.SingleOutStorageAmount * deductionQuantity,
                        //OperationAmount = purchaseOrder.SingleOperationAmount * deductionQuantity,
                        PurchaseFreight = purchaseOrder.SingleFreight * deductionQuantity,
                        SkuAmount = purchaseOrder.SingleSkuAmount * deductionQuantity,
                        StorageAmount = purchaseOrder.SingleStorageAmount * deductionQuantity
                    };
                    insertOrderCostDetailList.Add(orderCostDetail);
                }
            }

            if (orderCost == null)
            {
                if (autoCalculationCostRequest.PlatformCommissionRatio == 0M)
                    autoCalculationCostRequest.PlatformCommissionRatio = 0.05M;
                #region 计算成本
                orderCost = new OrderCost()
                {
                    OrderId = autoCalculationCostRequest.OrderId,
                    PlatformCommissionRatio = autoCalculationCostRequest.PlatformCommissionRatio,
                    PreferentialAmount = dbOrder.PreferentialAmount,
                    Profit = 0,
                    PurchaseAmount = orderCostPurchaseAmount,
                    DeliveryExpressFreight = orderDeliveryExpressFreight,
                    CreateTime = DateTime.Now
                };
                //orderCost.PlatformCommissionAmount = dbOrder.OrderSellerPrice * orderCost.PlatformCommissionRatio;
                //orderCost.Profit = dbOrder.OrderSellerPrice +
                //                   dbOrder.FreightPrice -
                //                   orderCost.PurchaseAmount -
                //                   orderCost.DeliveryExpressFreight -
                //                   orderCost.PlatformCommissionAmount;
                orderCost.CalculationOrderProfitAndCost(dbOrder, dbAfterSaleOrderList);
                insertOrderCost = fsql.Insert(orderCost);
                #endregion
            }
            else
            {
                orderCost.PurchaseAmount += orderCostPurchaseAmount;
                orderCost.DeliveryExpressFreight += orderDeliveryExpressFreight;
                //orderCost.Profit = dbOrder.OrderSellerPrice +
                //                   dbOrder.FreightPrice -
                //                   orderCost.PurchaseAmount -
                //                   orderCost.DeliveryExpressFreight -
                //                   orderCost.PlatformCommissionAmount;
                orderCost.CalculationOrderProfitAndCost(dbOrder, dbAfterSaleOrderList);
                updateOrderCost = fsql.Update<OrderCost>().SetSource(orderCost);
            }

            fsql.Transaction(() =>
            {
                orderUpdate?.ExecuteAffrows();
                updateOrderCost?.ExecuteAffrows();
                insertOrderCost?.ExecuteAffrows();
                if (updatePurchaseOrderList.Count > 0)
                {
                    foreach (var update in updatePurchaseOrderList)
                        update.ExecuteAffrows();
                }
                if (insertOrderCostDetailList.Count > 0)
                    fsql.Insert(insertOrderCostDetailList).ExecuteAffrows();
            });
        }

        /// <summary>
        /// 手动计算成本
        /// </summary>
        /// <param name="manualCalculationCostRequest"></param>
        /// <exception cref="BusinessException"></exception>
        public void ManualCalculationCost(ManualCalculationCostRequest manualCalculationCostRequest)
        {
            var dbOrder = fsql.Select<Order>(manualCalculationCostRequest.OrderId).ToOne();
            if (dbOrder == null)
                throw new BusinessException($"订单号{manualCalculationCostRequest.OrderId}不存在");
            if (manualCalculationCostRequest.OrderCostDetailList == null || manualCalculationCostRequest.OrderCostDetailList.Count() == 0)
                throw new BusinessException($"缺少明细信息");

            IUpdate<Order> orderUpdate = null;
            IUpdate<OrderCost> updateOrderCost = null;
            IInsert<OrderCost> insertOrderCost = null;
            List<OrderCostDetail> insertOrderCostDetailList = new List<OrderCostDetail>();
            var dbAfterSaleOrderList = fsql.Select<AfterSaleOrder>().Where(aso => aso.OrderId == manualCalculationCostRequest.OrderId).ToList();

            if (manualCalculationCostRequest.IsSetStorageType)
                orderUpdate = fsql.Update<Order>(manualCalculationCostRequest.OrderId).Set(o => o.StorageType, manualCalculationCostRequest.StorageType);

            insertOrderCostDetailList.AddRange(manualCalculationCostRequest.OrderCostDetailList.Map<IList<OrderCostDetail>>());
            foreach (var orderCostDetail in insertOrderCostDetailList)
            {
                orderCostDetail.Id = idGenerator.NewLong();
                orderCostDetail.CreateTime = DateTime.Now;
                orderCostDetail.OrderId = manualCalculationCostRequest.OrderId;
                orderCostDetail.PurchaseOrderPKId = 0;
            }

            var totalPurchaseCost = insertOrderCostDetailList.Sum(ocd => ocd.TotalCost);
            var totalDeliveryExpressFreight = insertOrderCostDetailList.Sum(ocd => ocd.DeliveryExpressFreight);

            var orderCost = fsql.Select<OrderCost>(manualCalculationCostRequest.OrderId).ToOne();
            if (orderCost == null)
            {
                if (manualCalculationCostRequest.PlatformCommissionRatio == 0M)
                    manualCalculationCostRequest.PlatformCommissionRatio = 0.05M;
                orderCost = new OrderCost()
                {
                    OrderId = manualCalculationCostRequest.OrderId,
                    PlatformCommissionRatio = manualCalculationCostRequest.PlatformCommissionRatio,
                    PreferentialAmount = dbOrder.PreferentialAmount,
                    Profit = 0,
                    PurchaseAmount = totalPurchaseCost,
                    DeliveryExpressFreight = totalDeliveryExpressFreight,
                    CreateTime = DateTime.Now,
                    IsManualEdited = true
                };
                //orderCost.PlatformCommissionAmount = dbOrder.OrderSellerPrice * orderCost.PlatformCommissionRatio;
                //orderCost.Profit = dbOrder.OrderSellerPrice +
                //                   dbOrder.FreightPrice -
                //                   orderCost.PurchaseAmount -
                //                   orderCost.DeliveryExpressFreight -
                //                   orderCost.PlatformCommissionAmount;
                orderCost.CalculationOrderProfitAndCost(dbOrder, dbAfterSaleOrderList);
                insertOrderCost = fsql.Insert(orderCost);
            }
            else
            {
                orderCost.PurchaseAmount = totalPurchaseCost;
                orderCost.DeliveryExpressFreight = totalDeliveryExpressFreight;
                //orderCost.Profit = dbOrder.OrderSellerPrice +
                //                   dbOrder.FreightPrice -
                //                   orderCost.PurchaseAmount -
                //                   orderCost.DeliveryExpressFreight -
                //                   orderCost.PlatformCommissionAmount;
                orderCost.CalculationOrderProfitAndCost(dbOrder, dbAfterSaleOrderList);
                orderCost.IsManualEdited = true;
                updateOrderCost = fsql.Update<OrderCost>().SetSource(orderCost);
            }

            fsql.Transaction(() =>
            {
                fsql.Update<OrderCostDetail>().Set(ocd => ocd.IsEnabled, false).Where(ocd => ocd.OrderId == manualCalculationCostRequest.OrderId).ExecuteAffrows();
                orderUpdate?.ExecuteAffrows();
                insertOrderCost?.ExecuteAffrows();
                updateOrderCost?.ExecuteAffrows();
                fsql.Insert(insertOrderCostDetailList).ExecuteAffrows();
            });
        }

        /// <summary>
        /// 刷单计算成本
        /// </summary>
        /// <param name="sdCalculationCostRequest"></param>
        /// <exception cref="BusinessException"></exception>
        public void SDCalculationCost(SDCalculationCostRequest sdCalculationCostRequest)
        {
            var dbOrder = fsql.Select<Order>(sdCalculationCostRequest.OrderId).ToOne();
            if (dbOrder == null)
            {
                //待付款订单SD埋点
                //memoryCache.Remove(sdCalculationCostRequest.OrderId);
                memoryCache.Set(sdCalculationCostRequest.OrderId, sdCalculationCostRequest, sdGroupExpirationTimeSpan);
                return;
            }

            //修改平台订单备注
            var relayAPIHost = GetPlatformRelayAPIHost(sdCalculationCostRequest.Platform);
            var editApiResult = restApiService.SendRequest(relayAPIHost, "/Api/PlatformSDK/EditVenderRemark", new EditVenderRemarkRequest()
            {
                AppKey = sdCalculationCostRequest.AppKey,
                AppSecret = sdCalculationCostRequest.AppSecret,
                AppToken = sdCalculationCostRequest.AppToken,
                Flag = sdCalculationCostRequest.Flag,
                OrderId = sdCalculationCostRequest.OrderId,
                Platform = sdCalculationCostRequest.Platform,
                VenderRemark = sdCalculationCostRequest.VenderRemark
            }, null, HttpMethod.Post);
            if (editApiResult.StatusCode != System.Net.HttpStatusCode.OK)
                throw new BusinessException($"修改商家备注失败 {editApiResult.Content}") { Code = (int)editApiResult.StatusCode };
            var editResponse = JsonConvert.DeserializeObject<ApiResponse>(editApiResult.Content);
            if (!editResponse.Success)
                throw new BusinessException(editResponse.Msg);

            IUpdate<Order> orderUpdate = null;
            IUpdate<OrderCost> updateOrderCost = null;
            IInsert<OrderCost> insertOrderCost = null;

            var dbAfterSaleOrderList = fsql.Select<AfterSaleOrder>().Where(aso => aso.OrderId == sdCalculationCostRequest.OrderId).ToList();

            orderUpdate = fsql.Update<Order>(sdCalculationCostRequest.OrderId).Set(o => o.SDType, sdCalculationCostRequest.SDType)
                                                                              .Set(o => o.Flag, sdCalculationCostRequest.Flag)
                                                                              .Set(o => o.VenderRemark, sdCalculationCostRequest.VenderRemark)
                                                                              .Set(o => o.SDKey, sdCalculationCostRequest.SDKey)
                                                                              .Set(o => o.SDPayBillNo, sdCalculationCostRequest.SDPayBillNo)
                                                                              .Set(o => o.SDOperator, sdCalculationCostRequest.SDOperator)
                                                                              .SetIf(sdCalculationCostRequest.SDPayChannel != null, o => o.SDPayChannel, sdCalculationCostRequest.SDPayChannel);
            if (sdCalculationCostRequest.IsSetStorageType)
                orderUpdate = orderUpdate.Set(o => o.StorageType, Enums.StorageType.SD);

            var orderCost = fsql.Select<OrderCost>(sdCalculationCostRequest.OrderId).ToOne();
            if (orderCost == null)
            {
                if (sdCalculationCostRequest.PlatformCommissionRatio == 0M)
                    sdCalculationCostRequest.PlatformCommissionRatio = 0.05M;
                orderCost = new OrderCost()
                {
                    OrderId = sdCalculationCostRequest.OrderId,
                    PlatformCommissionRatio = sdCalculationCostRequest.PlatformCommissionRatio,
                    PreferentialAmount = dbOrder.PreferentialAmount,
                    Profit = 0,
                    DeliveryExpressFreight = sdCalculationCostRequest.DeliveryExpressFreight,
                    CreateTime = DateTime.Now,
                    IsManualEdited = true,
                    SDCommissionAmount = sdCalculationCostRequest.SDCommissionAmount,
                    SDOrderAmount = sdCalculationCostRequest.SDOrderAmount
                };
                //orderCost.PlatformCommissionAmount = dbOrder.OrderSellerPrice * orderCost.PlatformCommissionRatio;
                //orderCost.Profit = (orderCost.SDCommissionAmount + orderCost.DeliveryExpressFreight + orderCost.PlatformCommissionAmount) * -1;
                orderCost.CalculationSDOrderProfitAndCost(dbOrder, dbAfterSaleOrderList);
                insertOrderCost = fsql.Insert(orderCost);
            }
            else
            {
                orderCost.SDCommissionAmount = sdCalculationCostRequest.SDCommissionAmount;
                orderCost.SDOrderAmount = sdCalculationCostRequest.SDOrderAmount;
                orderCost.DeliveryExpressFreight = sdCalculationCostRequest.DeliveryExpressFreight;
                //orderCost.Profit = (orderCost.SDCommissionAmount + orderCost.DeliveryExpressFreight + orderCost.PlatformCommissionAmount) * -1;
                orderCost.CalculationSDOrderProfitAndCost(dbOrder, dbAfterSaleOrderList);
                orderCost.IsManualEdited = true;
                updateOrderCost = fsql.Update<OrderCost>().SetSource(orderCost);
            }

            fsql.Transaction(() =>
            {
                orderUpdate?.ExecuteAffrows();
                updateOrderCost?.ExecuteAffrows();
                insertOrderCost?.ExecuteAffrows();
            });
        }

        /// <summary>
        /// 关联外部订单
        /// </summary>
        /// <param name="relationPurchaseOrderRequestV2"></param>
        public void RelationPurchaseOrderV2(RelationPurchaseOrderRequestV2 relationPurchaseOrderRequestV2)
        {
            var dbOrder = fsql.Select<Order>(relationPurchaseOrderRequestV2.OrderDropShippingList[0].OrderId).ToOne();
            if (dbOrder == null)
                throw new BusinessException($"订单号{relationPurchaseOrderRequestV2.OrderDropShippingList[0].OrderId}不存在");

            if (relationPurchaseOrderRequestV2.PlatformCommissionRatio == 0M)
                relationPurchaseOrderRequestV2.PlatformCommissionRatio = 0.05M;

            List<OrderDropShipping> insertOrderDropShippingList = new List<OrderDropShipping>();
            List<IUpdate<OrderDropShipping>> updateOrderDropShippingList = new List<IUpdate<OrderDropShipping>>();
            IInsert<OrderCost> insertOrderCost = null;
            IUpdate<OrderCost> updateOrderCost = null;
            IDelete<PurchaseOrder> deletePurchaseOrder = null;
            IDelete<OrderCostDetail> deleteOrderCostDetail = null;
            List<IUpdate<OrderSku>> updateOrderSkuList = new List<IUpdate<OrderSku>>();
            List<PurchaseOrder> insertPurchaseOrderList = new List<PurchaseOrder>();
            List<OrderCostDetail> insertOrderCostDetailList = new List<OrderCostDetail>();

            var oldPourchaseIdList = fsql.Select<OrderCostDetail>().Where(ocd => ocd.OrderId == dbOrder.Id)
                                                                   .ToList(ocd => ocd.PurchaseOrderPKId);

            deletePurchaseOrder = fsql.Delete<PurchaseOrder>().Where(po => oldPourchaseIdList.Contains(po.Id));
            deleteOrderCostDetail = fsql.Delete<OrderCostDetail>().Where(ocd => ocd.OrderId == dbOrder.Id);

            foreach (var odsRequest in relationPurchaseOrderRequestV2.OrderDropShippingList)
            {
                #region 代发信息表
                var orderDropShipping = odsRequest.Map<OrderDropShipping>();
                if (orderDropShipping.Id == 0)
                {
                    orderDropShipping.Id = idGenerator.NewLong();
                    orderDropShipping.CreateTime = DateTime.Now;
                    orderDropShipping.ShopId = dbOrder.ShopId;
                    insertOrderDropShippingList.Add(orderDropShipping);
                }
                else
                {
                    updateOrderDropShippingList.Add(fsql.Update<OrderDropShipping>().SetSource(orderDropShipping).IgnoreColumns(ods => new { ods.CreateTime, ods.ShopId, ods.IsHistory }));
                }
                #endregion

                foreach (var relationOrderSku in odsRequest.RelationPurchaseOrderSkuList)
                {
                    #region OrderSku
                    var updateOrderSku = fsql.Update<OrderSku>().Set(osku => osku.OrderDropShippingId, orderDropShipping.Id)
                                                                .Where(osku => osku.SkuId == relationOrderSku.SkuId && osku.OrderId == dbOrder.Id);
                    updateOrderSkuList.Add(updateOrderSku);
                    #endregion

                    #region 采购单
                    var purchaseOrder = new PurchaseOrder()
                    {
                        Id = idGenerator.NewLong(),
                        CreateTime = DateTime.Now,
                        ProductId = relationOrderSku.ProductId,
                        PurchaseMethod = Enums.PurchaseMethod.线下采购,
                        StorageType = Enums.StorageType.代发,
                        PurchaseOrderId = odsRequest.PurchaseOrderId,
                        PurchasePlatform = odsRequest.PurchasePlatform,
                        PurchaseQuantity = relationOrderSku.Quantity,
                        RemainingQuantity = 0,
                        ShopId = dbOrder.ShopId,
                        SkuId = relationOrderSku.SkuId,
                        SingleConsumableAmount = 0,
                        SingleFirstFreight = 0,
                        SingleFreight = odsRequest.PurchaseFreight / odsRequest.RelationPurchaseOrderSkuList.Count() / relationOrderSku.Quantity,
                        //SingleOperationAmount = 0,
                        SingleInStorageAmount = 0,
                        SingleOutStorageAmount = 0,
                        SingleStorageAmount = 0,
                        SingleSkuAmount = relationOrderSku.SingleSkuAmount,
                        SingleDeliveryFreight = 0
                    };
                    insertPurchaseOrderList.Add(purchaseOrder);
                    #endregion

                    #region 明细
                    insertOrderCostDetailList.Add(new OrderCostDetail()
                    {
                        Id = idGenerator.NewLong(),
                        ConsumableAmount = 0,
                        CreateTime = DateTime.Now,
                        DeductionQuantity = relationOrderSku.Quantity,
                        DeliveryExpressFreight = 0,
                        FirstFreight = 0,
                        //OperationAmount = 0,
                        InStorageAmount = 0,
                        OutStorageAmount = 0,
                        OrderId = dbOrder.Id,
                        ProductId = relationOrderSku.ProductId,
                        PurchaseFreight = odsRequest.PurchaseFreight / odsRequest.RelationPurchaseOrderSkuList.Count(),
                        SkuAmount = relationOrderSku.SingleSkuAmount * relationOrderSku.Quantity,
                        SkuId = relationOrderSku.SkuId,
                        StorageAmount = 0,
                        //TotalCost = relationOrderSku.SingleSkuAmount * relationOrderSku.Quantity + odsRequest.PurchaseFreight / odsRequest.RelationPurchaseOrderSkuList.Count(),
                        //UnitCost = purchaseOrder.UnitCost,
                        PurchaseOrderPKId = purchaseOrder.Id
                    });
                    #endregion
                }

                #region 订单成本
                var totalDeliveryFreight = relationPurchaseOrderRequestV2.OrderDropShippingList.Sum(ods => ods.DeliveryFreight);
                var totalPurchaseAmount = relationPurchaseOrderRequestV2.OrderDropShippingList.Sum(ods => ods.PurchaseAmount);
                var orderCost = fsql.Select<OrderCost>(dbOrder.Id).ToOne();
                if (orderCost != null)
                {
                    orderCost.PlatformCommissionRatio = relationPurchaseOrderRequestV2.PlatformCommissionRatio;
                    orderCost.PlatformCommissionAmount = dbOrder.OrderSellerPrice * relationPurchaseOrderRequestV2.PlatformCommissionRatio;
                    orderCost.DeliveryExpressFreight = totalDeliveryFreight;
                    orderCost.PurchaseAmount = totalPurchaseAmount;
                    orderCost.Profit = dbOrder.OrderSellerPrice +
                                       dbOrder.FreightPrice -
                                       orderCost.PurchaseAmount -
                                       orderCost.DeliveryExpressFreight -
                                       orderCost.PlatformCommissionAmount;
                    updateOrderCost = fsql.Update<OrderCost>().SetSource(orderCost).IgnoreColumns(oc => new
                    {
                        oc.CreateTime,
                        oc.SDCommissionAmount,
                        oc.SDOrderAmount,
                        oc.PlatformCommissionAmount,
                        oc.PlatformCommissionRatio
                    });
                }
                else
                {
                    var preferentialAmount = fsql.Select<OrderCoupon>().Where(oc => oc.OrderId == dbOrder.Id)
                                                                       .ToAggregate(g => g.Sum(g.Key.CouponPrice));
                    orderCost = new OrderCost()
                    {
                        OrderId = dbOrder.Id,
                        CreateTime = DateTime.Now,
                        DeliveryExpressFreight = totalDeliveryFreight,
                        PlatformCommissionRatio = relationPurchaseOrderRequestV2.PlatformCommissionRatio,
                        SDCommissionAmount = 0,
                        SDOrderAmount = 0,
                        PurchaseAmount = totalPurchaseAmount,
                        PlatformCommissionAmount = dbOrder.OrderSellerPrice * relationPurchaseOrderRequestV2.PlatformCommissionRatio,
                        PreferentialAmount = preferentialAmount,
                        IsManualEdited = true
                    };

                    orderCost.Profit = dbOrder.OrderSellerPrice +
                                       dbOrder.FreightPrice -
                                       orderCost.PurchaseAmount -
                                       orderCost.DeliveryExpressFreight -
                                       orderCost.PlatformCommissionAmount;
                    insertOrderCost = fsql.Insert(orderCost);
                }
                #endregion
            }

            fsql.Transaction(() =>
                {
                    deletePurchaseOrder.ExecuteAffrows();
                    deleteOrderCostDetail.ExecuteAffrows();
                    foreach (var update in updateOrderSkuList)
                        update.ExecuteAffrows();
                    fsql.Insert(insertPurchaseOrderList).ExecuteAffrows();
                    fsql.Insert(insertOrderCostDetailList).ExecuteAffrows();
                    insertOrderCost?.ExecuteAffrows();
                    updateOrderCost?.ExecuteAffrows();
                    if (insertOrderDropShippingList.Count() > 0)
                        fsql.Insert(insertOrderDropShippingList).ExecuteAffrows();
                    if (updateOrderDropShippingList.Count() > 0)
                    {
                        foreach (var update in updateOrderDropShippingList)
                            update.ExecuteAffrows();
                    }
                    if (dbOrder.StorageType != Enums.StorageType.代发)
                    {
                        fsql.Update<Order>(dbOrder.Id)
                            .Set(o => o.StorageType, Enums.StorageType.代发)
                            .SetIf(dbOrder.OrderState == Enums.OrderState.等待采购, o => o.OrderState, Enums.OrderState.待出库)
                            .ExecuteAffrows();
                    }
                });
        }

        /// <summary>
        /// 出库
        /// </summary>
        /// <param name="outStockRequest"></param>
        /// <exception cref="BusinessException"></exception>
        public void OutStock(OutStockRequest outStockRequest)
        {
            var dbOrder = fsql.Select<Order>(outStockRequest.OrderId).ToOne();
            if (dbOrder == null)
                throw new BusinessException($"订单{outStockRequest.OrderId}不存在");
            if (dbOrder.OrderState != Enums.OrderState.待出库)
                throw new BusinessException($"订单{outStockRequest.OrderId} 只有在待出库时才允许出库");

            var relayAPIHost = GetPlatformRelayAPIHost(outStockRequest.Platform);
            var sendResult = restApiService.SendRequest(relayAPIHost, "api/PlatformSDK/OutStock", outStockRequest, null, HttpMethod.Post);
            if (sendResult.StatusCode != System.Net.HttpStatusCode.OK)
                throw new BusinessException(sendResult.Content) { Code = (int)sendResult.StatusCode };
            var response = JsonConvert.DeserializeObject<ApiResponse<ConsigneeSimpleResponse>>(sendResult.Content);
            if (!response.Success)
                throw new BusinessException(response.Msg) { Code = response.Code };

            fsql.Update<Order>(outStockRequest.OrderId).Set(o => o.OrderState, Enums.OrderState.待收货)
                                                       .Set(o => o.WaybillNo, outStockRequest.WayBillNo)
                                                       .ExecuteAffrows();
        }

        /// <summary>
        /// 修改商家备注
        /// </summary>
        /// <param name="editVenderRemarkRequest"></param>
        public void EditVenderRemark(EditVenderRemarkRequest editVenderRemarkRequest)
        {
            //修改平台订单备注
            var relayAPIHost = GetPlatformRelayAPIHost(editVenderRemarkRequest.Platform);

            if (editVenderRemarkRequest.Platform == Enums.Platform.京东)
            {
                var editApiResult = restApiService.SendRequest(relayAPIHost, "/Api/PlatformSDK/EditVenderRemark", editVenderRemarkRequest, null, HttpMethod.Post);
                if (editApiResult.StatusCode != System.Net.HttpStatusCode.OK)
                    throw new BusinessException($"修改商家备注失败 {editApiResult.Content}") { Code = (int)editApiResult.StatusCode };
                var editResponse = JsonConvert.DeserializeObject<ApiResponse>(editApiResult.Content);
                if (!editResponse.Success)
                    throw new BusinessException(editResponse.Msg);
            }
            else
            {
                throw new NotImplementedException();
            }

            fsql.Update<Order>(editVenderRemarkRequest.OrderId).Set(o => o.Flag, editVenderRemarkRequest.Flag)
                                                               .Set(o => o.VenderRemark, editVenderRemarkRequest.VenderRemark)
                                                               .ExecuteAffrows();
        }

        public OrderResponse SDGroupPullOrder(SDGroupPullOrderRequest request)
        {
            OrderResponse orderResponse = null;
            try
            {
                orderResponse = GetOrderById(request.OrderId);
            }
            catch
            {

            }

            if (orderResponse == null)
            {
                var relayAPIHost = GetPlatformRelayAPIHost(request.Platform);
                var orderApiResult = restApiService.SendRequest(relayAPIHost, "api/PlatformSDK/GetNoPayOrder", new SearchPlatformOrderRequest()
                {
                    OrderId = request.OrderId,
                    AppKey = request.AppKey,
                    AppSecret = request.AppSecret,
                    AppToken = request.AppToken,
                    Platform = request.Platform
                }, null, HttpMethod.Post);
                if (orderApiResult.StatusCode != System.Net.HttpStatusCode.OK)
                    throw new BusinessException($"获取未付款订单失败 {orderApiResult.Content}");

                var orderJToken = JToken.Parse(orderApiResult.Content);
                var orderInfoJToken = orderJToken["Data"]["jingdong_pop_order_notPayOrderById_responce"]["orderDataNotPayInfo"];
                if (orderInfoJToken == null || !orderInfoJToken.HasValues)
                    throw new BusinessException("未查询到待付款订单");

                orderResponse = new OrderResponse()
                {
                    Id = orderInfoJToken["orderId"].ToString(),
                    ShopId = request.ShopId.ToString(),
                    OrderStartTime = DateTime.Parse(orderInfoJToken["orderCreated"].ToString()),
                    ItemList = new List<OrderSkuResponse>(),
                    Platform = request.Platform,
                    OrderCost = new OrderCostResponse()
                    {
                        OrderId = orderInfoJToken["orderId"].ToString(),
                        IsManualEdited = false
                    }
                };

                var orderSkuIds = string.Join(",", orderInfoJToken["itemList"].Children().Select(j => j.Value<string>("skuId")));
                var skuList = productBusiness.GetProductSkuList(new SearchProductSkuRequest()
                {
                    AppKey = request.AppKey,
                    AppSecret = request.AppSecret,
                    AppToken = request.AppToken,
                    Platform = request.Platform,
                    Sku = orderSkuIds
                });

                foreach (var sku in skuList)
                {
                    if (sku.Price != 0)
                    {
                        var num = orderInfoJToken["itemList"].Children().FirstOrDefault(j => j.Value<string>("skuId") == sku.Id)?.Value<int>("num") ?? 1;
                        orderResponse.ItemList.Add(new OrderSkuResponse()
                        {
                            Logo = sku.Logo,
                            OrderId = request.OrderId,
                            Price = sku.Price,
                            Title = sku.Title,
                            ProductId = sku.ProductId,
                            Id = sku.Id,
                            ItemTotal = num
                        });
                    }
                }
            }
            return orderResponse;
        }
    }
}