package orderman

import (
	"crypto/md5"
	"errors"
	"fmt"
	"git.rosy.net.cn/baseapi/platformapi/tao_vegetable"
	"git.rosy.net.cn/baseapi/platformapi/tiktok_shop/tiktok_api"
	"git.rosy.net.cn/jx-callback/business/jxstore/cms"
	"math"
	"strings"
	"time"

	"git.rosy.net.cn/jx-callback/business/authz/autils"
	"git.rosy.net.cn/jx-callback/business/jxutils/excel"
	"git.rosy.net.cn/jx-callback/business/jxutils/netprinter"
	"git.rosy.net.cn/jx-callback/business/jxutils/weixinmsg"
	tao "git.rosy.net.cn/jx-callback/business/partner/purchase/tao_vegetable"
	"git.rosy.net.cn/jx-callback/business/partner/purchase/tiktok_store"
	"git.rosy.net.cn/jx-callback/globals/api2"
	beego "github.com/astaxie/beego/server/web"

	"git.rosy.net.cn/baseapi/platformapi/dingdingapi"
	"git.rosy.net.cn/baseapi/platformapi/jdeclpapi"

	"git.rosy.net.cn/jx-callback/business/jxutils/ddmsg"
	"git.rosy.net.cn/jx-callback/business/jxutils/tasksch"
	"git.rosy.net.cn/jx-callback/business/partner/purchase/jdshop"
	"git.rosy.net.cn/jx-callback/globals/api"

	"git.rosy.net.cn/baseapi"
	"git.rosy.net.cn/baseapi/platformapi/jdshopapi"
	"git.rosy.net.cn/baseapi/utils"
	"git.rosy.net.cn/jx-callback/business/jxcallback/scheduler"
	"git.rosy.net.cn/jx-callback/business/jxutils"
	"git.rosy.net.cn/jx-callback/business/jxutils/jxcontext"
	"git.rosy.net.cn/jx-callback/business/model"
	"git.rosy.net.cn/jx-callback/business/model/dao"
	"git.rosy.net.cn/jx-callback/business/partner"
	"git.rosy.net.cn/jx-callback/globals"
	"github.com/astaxie/beego/client/orm"
)

var (
	orderNoBeginTimestamp int64
)

func init() {
	orderNoBeginTimestamp = utils.Str2Time("2010-01-01 00:00:00").Unix()
}

type tSkuCountPrice struct {
	Count     int   `json:"count"`
	SalePrice int64 `json:"salePrice"`
}

// msgVendorStatus的意思是事件本身的类型，类似有时收到NewOrder事件去取，订单状态不一定就是New的
// OnOrderAdjust也类似，而OrderStatus要记录的是消息，所以添加这个
func (c *OrderManager) OnOrderNew(order *model.GoodsOrder, orderStatus *model.OrderStatus) (err error) {
	if order.ConsigneeMobile2 == "" && jxutils.IsStringLikeMobile(order.ConsigneeMobile) {
		order.ConsigneeMobile2 = order.ConsigneeMobile
	}

	db := dao.GetDB()
	txDB, _ := dao.Begin(db)
	defer func() {
		if r := recover(); r != nil {
			dao.Rollback(db, txDB)
			panic(r)
		}
	}()
	if order.Status == model.OrderStatusUnknown {
		order.Status = model.OrderStatusNew
	}

	var isDuplicated bool
	if order.Status == model.OrderStatusNew && order.VendorID == model.VendorIDJX && !model.IsOrderJXTemp(order) {
		isDuplicated, _, err = c.addOrderStatus(orderStatus, db)
	} else {
		isDuplicated, err = addOrderOrWaybillStatus(orderStatus, db)
		if err == nil && !isDuplicated {
			isDuplicated, err = c.SaveOrder(order, false, db)
		}
	}

	if err == nil {
		dao.Commit(db, txDB)
		if !isDuplicated {
			err = scheduler.CurrentScheduler.OnOrderNew(order, false, false)
		}
	} else {
		dao.Rollback(db, txDB)
	}
	return err
}

// todo 调整单的处理可能还需要再细化一点，当前只是简单的删除重建
func (c *OrderManager) OnOrderAdjust(order *model.GoodsOrder, orderStatus *model.OrderStatus) (err error) {
	if order.ConsigneeMobile2 == "" && jxutils.IsStringLikeMobile(order.ConsigneeMobile) {
		order.ConsigneeMobile2 = order.ConsigneeMobile
	}

	db := dao.GetDB()
	txDB, _ := dao.Begin(db)
	defer func() {
		if r := recover(); r != nil {
			dao.Rollback(db, txDB)
			panic(r)
		}
	}()
	// 出现过调整单后，状态回到新订单状态，比如：911350836000622
	// 不完全确定，加一个处理
	if order.Status < model.OrderStatusAccepted {
		order.Status = model.OrderStatusAccepted
	}
	isDuplicated, err := addOrderOrWaybillStatus(orderStatus, db)
	if err == nil && !isDuplicated {
		err = utils.CallFuncLogError(func() error {
			_, err = db.Db.Raw("DELETE FROM order_sku WHERE vendor_order_id = ? AND vendor_id = ?", order.VendorOrderID, order.VendorID).Exec()
			return err
		}, "OnAdjustOrder delete order, orderID:%s", order.VendorOrderID)
		if err != nil {
			return err
		}
		adjustCount := int8(0)
		previousOrder := &model.GoodsOrder{
			VendorOrderID: order.VendorOrderID,
			VendorID:      order.VendorID,
		}
		if err = dao.GetEntity(db, previousOrder, model.FieldVendorOrderID, model.FieldVendorID); err != nil && !dao.IsNoRowsError(err) {
			return err
		}
		if err == nil {
			adjustCount = previousOrder.AdjustCount
			if _, err = dao.DeleteEntity(db, previousOrder); err != nil {
				return err
			}
			order.VendorWaybillID = previousOrder.VendorWaybillID
			order.WaybillVendorID = previousOrder.WaybillVendorID
		} else {
			globals.SugarLogger.Warnf("OnOrderAdjust, but previous order:%s doesn't exist", order.VendorOrderID)
		}
		// err = utils.CallFuncLogError(func() error {
		// 	_, err = db.Db.Raw("DELETE FROM goods_order WHERE vendor_order_id = ? AND vendor_id = ?", order.VendorOrderID, order.VendorID).Exec()
		// 	return err
		// }, "OnAdjustOrder delete order_sku, orderID:%s", order.VendorOrderID)
		order.AdjustCount = adjustCount + 1
		//扣点的订单需要修改订单的totalshopmoney
		if err == nil && order.OrderPayPercentage < 50 && order.OrderPayPercentage > 0 {
			order2, _ := partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).GetOrder(order.VendorOrgCode, order.VendorOrderID, order.VendorStoreID)
			order.TotalShopMoney = order2.TotalShopMoney
		}
		isDuplicated, err = c.SaveOrder(order, true, db)
	}
	if err == nil {
		dao.Commit(db, txDB)
		if !isDuplicated {
			// 因为订单调度器需要的是真实状态，所以用order的状态
			_ = scheduler.CurrentScheduler.OnOrderNew(order, false, false)
			_ = scheduler.CurrentScheduler.OnOrderStatusChanged(order, orderStatus, false)
		}
	} else {
		dao.Rollback(db, txDB)
	}
	return err
}

func (c *OrderManager) OnOrderStatusChanged(vendorOrgCode string, orderStatus *model.OrderStatus) (err error) {
	db := dao.GetDB()
	txDB, _ := dao.Begin(db)
	defer func() {
		if r := recover(); r != nil {
			dao.Rollback(db, txDB)
			panic(r)
		}
	}()
	// 有些平台（比如美团外卖），在新订单事件没有成功返回，但在重发订单消息前，订单状态转换，则不会再重发新订单事件，特殊处理一下
	if orderStatus != nil && orderStatus.Status == model.OrderStatusAccepted {
		loadOrder, err2 := c.LoadOrder(orderStatus.VendorOrderID, orderStatus.VendorID)
		if err2 == ErrCanNotFindOrder {
			if handler := partner.GetPurchaseOrderHandlerFromVendorID(orderStatus.VendorID); handler != nil {
				if order, err2 := handler.GetOrder(vendorOrgCode, orderStatus.VendorOrderID, ""); err2 == nil && order != nil {
					c.OnOrderNew(order, orderStatus)
				}
			}
		} else if loadOrder.Status < model.OrderStatusAccepted && loadOrder.VendorID == model.VendorIDTaoVegetable {
			loadOrder.Status = model.OrderStatusAccepted
			loadOrder.VendorStatus = tao_vegetable.OrderStatusNew
			c.UpdateOrderFields(loadOrder, []string{"Status", "VendorStatus"})
		} else if loadOrder.Status < model.OrderStatusAccepted && loadOrder.VendorID == model.VendorIDMTWM {
			loadOrder.Status = model.OrderStatusAccepted
			c.UpdateOrderFields(loadOrder, []string{"Status", "VendorStatus"})
		}
	}

	isDuplicated, order, err := c.addOrderStatus(orderStatus, db)
	if err == nil {
		dao.Commit(db, txDB)
		if orderStatus.Status == model.OrderStatusWaybillTipChanged {
			if order, err2 := c.LoadOrder(orderStatus.VendorOrderID, orderStatus.VendorID); err2 == nil {
				if handler := partner.GetWaybillTipUpdater(orderStatus.RefVendorID); handler != nil {
					tipFee, err2 := handler.GetWaybillTip(jxcontext.AdminCtx, vendorOrgCode, order.VendorStoreID, orderStatus.RefVendorOrderID, orderStatus.VendorOrderID, "")
					if err2 == nil {
						order.WaybillTipMoney = tipFee
						c.UpdateOrderFields(order, []string{"WaybillTipMoney"})
					}
				}
			}
		} else if orderStatus.Status == model.OrderStatusFinished {
			if order, err2 := c.LoadOrder(orderStatus.VendorOrderID, orderStatus.VendorID); err2 == nil {
				// 当前只针对三方运单更新配送费信息
				if order.WaybillVendorID >= 0 && order.VendorWaybillID != "" && order.WaybillVendorID != order.VendorID {
					if waybill, err2 := c.LoadWaybill(order.VendorWaybillID, order.WaybillVendorID); err2 == nil {
						if handler := partner.GetWaybillTipUpdater(waybill.WaybillVendorID); handler != nil {
							tipFee, err2 := handler.GetWaybillTip(jxcontext.AdminCtx, waybill.VendorOrgCode, "", order.VendorOrderID, waybill.VendorWaybillID, waybill.VendorWaybillID2)
							if err2 == nil && waybill.TipFee != tipFee {
								waybill.ActualFee += tipFee - waybill.TipFee
								waybill.TipFee = tipFee
								dao.UpdateEntity(db, waybill, "TipFee", "ActualFee")
							}
						}
					}
				}

				// 目前存在当订单为平台自配送时,本地储存新订单的结算信息是包含了配送费的!所以结算信息不对!
				// 修改为订单完成时更新订单的结算信息
				settlementAmount, err3 := partner.GetPurchaseOrderHandlerFromVendorID(order.VendorID).GetOrderSettleAccounts(order)
				if err3 == nil && settlementAmount != model.NO {
					order.TotalShopMoney = settlementAmount
					dao.UpdateEntity(db, order, "TotalShopMoney")
				}

				//更新订单new_earning_price
				if order.EarningType == model.EarningTypePoints {
					waybill, _ := c.LoadWaybill(order.VendorWaybillID, order.WaybillVendorID)
					// store, _ := c.LoadStoreDetail(jxutils.GetSaleStoreIDFromOrder(order), order.VendorID)
					if waybill == nil {
						if (order.NewEarningPrice == 0 || order.NewEarningPrice != order.TotalShopMoney*int64(100-order.OrderPayPercentage/2)/int64(100)) && order.OrderPayPercentage <= 50 {
							order.NewEarningPrice = order.TotalShopMoney * int64(100-order.OrderPayPercentage/2) / int64(100)
						}
					} else {
						if (order.NewEarningPrice == 0 || order.NewEarningPrice != (order.TotalShopMoney-waybill.DesiredFee)*int64(100-order.OrderPayPercentage/2)/int64(100)) && order.OrderPayPercentage <= 50 {
							order.NewEarningPrice = order.TotalShopMoney*int64(100-order.OrderPayPercentage/2)/int64(100) - waybill.DesiredFee
						}
					}
					dao.UpdateEntity(db, order, "NewEarningPrice")
				}

				if order.VendorID == model.VendorIDMTWM {
					if afsOrders, _ := dao.GetAfsOrders(db, order.VendorID, order.VendorOrderID, ""); len(afsOrders) > 0 {
						for _, v := range afsOrders {
							if handler := partner.GetPurchaseOrderHandlerFromVendorID(v.VendorID); handler != nil {
								if orderAfsInfo, err := handler.GetOrderAfsInfo(nil, v.VendorOrderID, v.AfsOrderID); err == nil && orderAfsInfo.AfsTotalShopMoney != 0 {
									v.AfsTotalShopMoney = orderAfsInfo.AfsTotalShopMoney
								}
								dao.UpdateEntity(db, v, "AfsTotalShopMoney")
							}
							break
						}
					}
				}
			}
			// 刷新订单结束时间
			order.OrderFinishedAt = time.Now()
			dao.UpdateEntity(db, order, "OrderFinishedAt", "TotalShopMoney")
		} else if orderStatus.Status == model.OrderStatusCanceled {
			order2, _ := c.LoadOrder(orderStatus.VendorOrderID, orderStatus.VendorID) // 订单被取消,则取消三方运单
			if orderStatus.OrderType == model.OrderTypeOrder {
				waybill, _ := dao.GetWaybills(db, order2.VendorOrderID, []int64{model.VendorIDMTPS, model.VendorIDDada, model.VendorIDFengNiao, model.VendorIDUUPT, model.VendorIDSFPS})
				for _, v := range waybill {
					if err := partner.GetDeliveryPlatformFromVendorID(v.WaybillVendorID).Handler.CancelWaybill(v, 0, "订单被取消了1"); err != nil {
						partner.CurOrderManager.OnOrderMsg(order2, fmt.Sprintf("订单[%s]被取消了,运单[%s]取消失败Err: %s", order.VendorOrderID, v.VendorWaybillID, err.Error()), "")
					} else {
						partner.CurOrderManager.OnOrderMsg(order2, fmt.Sprintf("订单[%s]被取消了,运单[%s]取消成功", order.VendorOrderID, v.VendorWaybillID), "")
					}
				}
				// 刷新订单结束时间
				order2.OrderFinishedAt = time.Now()
				dao.UpdateEntity(db, order2, "OrderFinishedAt")
			}

			if handler := partner.GetPurchaseOrderHandlerFromVendorID(orderStatus.VendorID); handler != nil && (orderStatus.VendorID == model.VendorIDMTWM || orderStatus.VendorID == model.VendorIDEBAI) {
				compensation, applyErr := handler.ApplyCompensationOrder(order2)
				if applyErr != nil {
					partner.CurOrderManager.OnOrderMsg(order2, utils.Int2Str(order2.Status), fmt.Sprintf("取消订单申请赔付失败:%s", applyErr.Error()))
				} else {
					if compensation == "" {
						compensation = "成功"
					}
					partner.CurOrderManager.OnOrderMsg(order2, utils.Int2Str(order2.Status), fmt.Sprintf("取消订单申请赔付:%s", compensation))
				}

				if order2.Status != model.OrderStatusCanceled {
					order2.Status = model.OrderStatusCanceled
					order2.VendorStatus = orderStatus.VendorStatus
					dao.UpdateEntity(db, order2, "Status")
				}
			}

			// 判断是否需要打印取消订单
			storeDetail, errDetail := c.LoadStoreDetail(order2.JxStoreID, order2.VendorID)
			if errDetail == nil && storeDetail.IsPrintCancelOrder == model.YES { // 取消申请
				_, err = netprinter.PrintRefundOrCancelOrder(jxcontext.AdminCtx, model.YES, order2, order2.JxStoreID)
			}
			if err != nil {
				globals.SugarLogger.Debug("Get store Detail Err: ", err)
			}

			// 商品库存修改
			switch beego.BConfig.RunMode {
			case model.ServerTypeFruits, model.ServerTypeVegetable:
				ModifyOrderSkusStock(db, order2, true)
			case model.ServerTypePet:
				// 宠物会出现美团多门店对应京西一个门店的库存数,即同一老板开多家店,单只有一个库存门店,
				// 所以不同门店同一品牌,最终商品库存只扣除门店ID最小的商品库存(最早创建门店,主店)
				// 最好商品由主店创建,复制到分店,分店本地同步状态不在打开
				ModifyPetOrderSkusStock(db, order2, true)
			}
		}

		if !isDuplicated {
			if order != nil {
				order.Skus = c.loadOrderSku(db, order.VendorOrderID, order.VendorID)
				_ = scheduler.CurrentScheduler.OnOrderStatusChanged(order, orderStatus, false)
			}
		}
	} else {
		dao.Rollback(db, txDB)
	}
	return err
}

func (c *OrderManager) ChangeOrderInfo(order *model.GoodsOrder) (err error) {
	db := dao.GetDB()
	_, err = dao.UpdateEntity(db, order, "ConsigneeAddress", "ConsigneeName", "ConsigneeMobile", "ConsigneeLat", "ConsigneeLng", "BuyerComment")
	return err
}

func (c *OrderManager) OnOrderMsg(order *model.GoodsOrder, vendorStatus, remark string) (err error) {
	_, _, err = c.addOrderStatus(&model.OrderStatus{
		VendorOrderID:    order.VendorOrderID,
		VendorID:         order.VendorID,
		OrderType:        model.OrderTypeOrder,
		RefVendorOrderID: order.VendorOrderID,
		RefVendorID:      order.VendorID,

		VendorStatus: vendorStatus,
		Status:       model.OrderStatusMsg,
		StatusTime:   time.Now(),
		Remark:       utils.LimitUTF8StringLen(remark, 255),
	}, nil)
	return err
}

func setFakeOrderFlag(db *dao.DaoDB, order *model.GoodsOrder) {
	if order.DeliveryType == model.OrderDeliveryTypeSelfTake {
		if realMobile := jxutils.GetRealMobile4Order(order); realMobile != "" {
			if configList, err := dao.QueryConfigs(db, model.ConfigSysFakeOrderMobiles, model.ConfigTypeSys, ""); err == nil && len(configList) > 0 {
				isMatch := false
				mobileList := strings.Split(configList[0].Value, ",")
				for _, v := range mobileList {
					if jxutils.TrimDecorationChar(v) == realMobile {
						isMatch = true
						break
					}
				}
				if isMatch {
					order.Flag |= model.OrderFlagMaskFake
				}
			}
		}
	}
}

func (c *OrderManager) SaveOrder(order *model.GoodsOrder, isAdjust bool, db *dao.DaoDB) (isDuplicated bool, err error) {
	// 忽略查找JX信息错误
	c.updateOrderOtherInfo(order, db)
	order.ID = 0
	order.WaybillVendorID = model.VendorIDUnknown
	order.OrderFinishedAt = utils.DefaultTimeValue

	setFakeOrderFlag(db, order)
	// cms.HandleOrder4Consignee(order)

	txDB, _ := dao.Begin(db)
	defer func() {
		if r := recover(); r != nil || err != nil {
			dao.Rollback(db, txDB)
			if r != nil {
				panic(r)
			}
		}
	}()
	// todo hardcode 兼容京东消息错序问题
	orderStatus := &model.OrderStatus{}
	if dao.GetRow(db, orderStatus, `
		SELECT *
		FROM order_status
		WHERE order_type = ? AND vendor_order_id = ? AND vendor_id = ? AND status > 0
		ORDER BY status_time DESC
		LIMIT 1
		`, model.OrderTypeOrder, order.VendorOrderID, order.VendorID) == nil {
		if orderStatus.Status > order.Status {
			order.Status = orderStatus.Status
			order.VendorStatus = orderStatus.VendorStatus
			order.StatusTime = orderStatus.StatusTime

			// jxutils.RefreshOrderSkuRelated(order)
		}
	}

	filterOrderInfo(order)
	created, _, err2 := db.Db.ReadOrCreate(order, "VendorOrderID", "VendorID")
	if err = err2; err == nil {
		originalOrder := &model.GoodsOrderOriginal{
			VendorOrderID:  order.VendorOrderID,
			VendorID:       order.VendorID,
			OrderCreatedAt: order.OrderCreatedAt,
			OriginalData:   order.OriginalData,
		}
		_, _, err = db.Db.ReadOrCreate(originalOrder, "VendorOrderID", "VendorID")
		if created {
			if err = dao.CreateMultiEntities(db, order.Skus); err != nil {
				baseapi.SugarLogger.Warnf("saveOrder orderID:%s, save order_sku failed with error:%v", order.VendorOrderID, err)
			}
		} else {
			isDuplicated = true
			order.DuplicatedCount++
			db.Db.Update(order, "DuplicatedCount")
			baseapi.SugarLogger.Infof("saveOrder duplicated orderid:%s msg received", order.VendorOrderID)
		}
		//} else {
		//	baseapi.SugarLogger.Warnf("saveOrder orderID:%s, save order OriginalData failed2 with error:%v", order.VendorOrderID, err)
		//}
	} else {
		//globals.SugarLogger.Warnf("saveOrder create order:%v, error:%v", order, err)
	}
	//修改商品库存
	if err == nil {
		switch beego.BConfig.RunMode {
		case model.ServerTypeFruits, model.ServerTypeVegetable:
			err = ModifyOrderSkusStock(db, order, false)
		case model.ServerTypePet:
			// 宠物会出现美团多门店对应京西一个门店的库存数,即同一老板开多家店,单只有一个库存门店,
			// 所以不同门店同一品牌,最终商品库存只扣除门店ID最小的商品库存(最早创建门店,主店)
			// 最好商品由主店创建,复制到分店,分店本地同步状态不在打开
			err = ModifyPetOrderSkusStock(db, order, false)
		}
	}
	if err == nil {
		dao.Commit(db, txDB)
	}
	return isDuplicated, err
}

// ModifyOrderSkusStock 果园和菜市同步库存
func ModifyOrderSkusStock(db *dao.DaoDB, order *model.GoodsOrder, isAdd bool) (err error) {
	store, err := dao.GetStoreDetail(db, order.JxStoreID, order.VendorID, order.VendorOrgCode)
	if err != nil || store.IsSync != model.YES {
		return nil // 门店未打开同步不修改库存
	}
	skus := order.Skus
	for _, sku := range skus {
		storeSkus, _ := dao.GetStoresSkusInfo(db, []int{jxutils.GetSaleStoreIDFromOrder(order)}, []int{sku.SkuID})
		if len(storeSkus) == 0 {
			continue
		}
		storeSku, stock := storeSkus[0], 0
		if storeSku.Stock == 0 {
			continue
		}
		if isAdd {
			stock = storeSku.Stock + sku.Count
		} else {
			stock = storeSku.Stock - sku.Count
			//如果是进货的订单，进货方门店对应商品要加上这么多库存
			if order.OrderType == model.OrderTypeSupplyGoods {
				storeSkus2, _ := dao.GetStoresSkusInfo(db, []int{order.FromStoreID}, []int{sku.SkuID})
				if len(storeSkus2) > 0 {
					storeSku3 := storeSkus2[0]
					storeSku3.Stock = storeSku3.Stock + sku.Count
					db.Db.Update(storeSku3, "Stock")
				}
			}
			realStock := checkPriceDefendOrderByStock(db, jxutils.GetSaleStoreIDFromOrder(order), sku.SkuID, stock, storeSku.JxPrice)
			if realStock != -1 {
				stock = realStock
			}
		}
		storeSku.Stock = stock
		db.Db.Update(storeSku, "Stock")
	}
	return err
}

// ModifyPetOrderSkusStock 宠物同步库存
func ModifyPetOrderSkusStock(db *dao.DaoDB, order *model.GoodsOrder, isAdd bool) (err error) {
	store, err := dao.GetStoreDetail(db, order.JxStoreID, order.VendorID, order.VendorOrgCode)
	if err != nil {
		return err // 门店未打开同步不修改库存
	}

	storeList, err := dao.GetStoreList(db, nil, nil, nil, []int{store.BrandID}, nil, "")
	if err != nil {
		return err
	}
	if len(storeList) == 0 {
		globals.SugarLogger.Errorf("根据品牌获取门店信息异常,未获取到门店列表[storeID:%d,brandID:%d]", store.ID, store.BrandID)
		return nil
	}
	storeIdList := make([]int, 0, len(storeList))
	for _, v := range storeList {
		storeIdList = append(storeIdList, v.ID)
	}

	skus := order.Skus
	skuIDList := make([]int, 0, len(skus))
	for _, sku := range skus {
		storeSkus, _ := dao.GetStoresSkusInfo(db, storeIdList, []int{sku.SkuID})
		if len(storeSkus) == 0 {
			continue
		}
		storeSku, stock := storeSkus[0], 0
		for _, ss := range storeSkus {
			if ss.StoreID == storeList[0].ID {
				storeSku = ss
				stock = ss.Stock
				globals.SugarLogger.Debugf("---------本地当前库存----skuid :%d,count :%d", ss.SkuID, stock)
				break
			}
		}
		if isAdd {
			stock = storeSku.Stock + sku.Count
		} else {
			stock = storeSku.Stock - sku.Count
		}
		//if isAdd {
		//	stock = storeSku.Stock + sku.Count
		//} else {
		//	stock = storeSku.Stock - sku.Count
		//	//如果是进货的订单，进货方门店对应商品要加上这么多库存
		//	//if order.OrderType == model.OrderTypeSupplyGoods {
		//	//	storeSkus2, _ := dao.GetStoresSkusInfo(db, []int{order.FromStoreID}, []int{sku.SkuID})
		//	//	if len(storeSkus2) > 0 {
		//	//		storeSku3 := storeSkus2[0]
		//	//		storeSku3.Stock = storeSku3.Stock + sku.Count
		//	//		db.Db.Update(storeSku3, "Stock")
		//	//	}
		//	//}
		//	//realStock := checkPriceDefendOrderByStock(db, jxutils.GetSaleStoreIDFromOrder(order), sku.SkuID, stock, storeSku.JxPrice)
		//	//if realStock != -1 {
		//	//	stock = realStock
		//	//}
		//}
		if stock <= model.NO {
			stock = 0
		}
		skuIDList = append(skuIDList, sku.SkuID)
		dao.ExecuteSQL(db, `UPDATE thing_map SET sync_status = 1 WHERE thing_id = ? AND vendor_id = ?`, sku.SkuID, 0)
		for _, ss := range storeSkus {
			ss.Stock = stock
			ss.UpdatedAt = time.Now()
			if beego.BConfig.RunMode == model.ServerTypePet {
				globals.SugarLogger.Debugf("----本地修改后库存----jxpt stock :=%d, %d,%d", sku.SkuID, ss.Stock, sku.Count)
			}
			dao.UpdateEntity(db, ss, "Stock", "UpdatedAt")
		}
	}
	if hit, err := cms.CurVendorSync.SyncStoresSkus2(jxcontext.AdminCtx, nil, 0, db, nil, storeIdList, false, skuIDList, nil, model.SyncFlagStockMask, true, true); err != nil {
		globals.SugarLogger.Debugf("----ModifyPetOrderSkusStock Update err opther: %v , %s", err, hit)
	}
	if hit, err := cms.SyncSkus(jxcontext.AdminCtx, nil, nil, []string{"309558"}, nil, skuIDList, true); err != nil {
		globals.SugarLogger.Debugf("----ModifyPetOrderSkusStock Update err jd: %v,%s", err, hit)
	}
	return err
}

func filterOrderInfo(order *model.GoodsOrder) {
	order.ConsigneeName = utils.LimitUTF8StringLen2(order.ConsigneeName, 32)
	order.ConsigneeAddress = utils.LimitUTF8StringLen2(order.ConsigneeAddress, 255)
	order.ConsigneeAddress = strings.ReplaceAll(order.ConsigneeAddress, "·", "")
}

// FinisOrderWaybillFee 订单完成时,计算结算信息
func FinisOrderWaybillFee(db *dao.DaoDB, order *model.GoodsOrder, bill *model.Waybill) (err error) {
	if db == nil {
		db = dao.GetDB()
	}
	if bill.WaybillVendorID != model.VendorIDMTPS && bill.WaybillVendorID != model.VendorIDDada && bill.WaybillVendorID != model.VendorIDFengNiao && bill.WaybillVendorID != model.VendorIDUUPT {
		return nil
	}
	// 查询所有运单
	bills, err := dao.GetWaybills(db, order.VendorOrderID, []int64{model.VendorIDDada, model.VendorIDFengNiao, model.VendorIDMTPS, model.VendorIDUUPT, model.VendorIDSFPS})
	if err != nil {
		return err
	}

	store, _ := dao.GetStoreDetail(db, order.JxStoreID, order.VendorID, order.VendorOrgCode)
	// 正常来说只会出现一个完成运单,之前有bug会出现多个完成订单,这不做考虑.默认一个运单完成,其他运单取消状态
	// 1.完成当前运单的金额核算,正常完成的订单金额不需要核算
	// 2.取消运单的金额核算
	cancelWaybill := make(map[string]*model.Waybill, 0)
	for _, v := range bills {
		if v.Status != model.WaybillStatusCanceled {
			continue
		}
		if v.VendorWaybillID == bill.VendorWaybillID {
			continue
		}
		cancelWaybill[v.VendorWaybillID] = v
	}
	// 已经全部运单取消,退款结算
	for _, v := range bills {
		if v.VendorWaybillID == bill.VendorWaybillID {
			continue
		}
		// 已经取消订单的违约金计算
		if err = countWaybillSettleInfo(db, order, v, store); err != nil {
			return err
		}
	}

	// 3.总的收支核算
	if err = orderFeeSettle(db, order, bill, bills, store); err != nil {
		return err
	}
	return nil
}

// ResetCreateWaybillFee 取消所有运单时计算结算信息
func ResetCreateWaybillFee(db *dao.DaoDB, order *model.GoodsOrder, bill *model.Waybill) (err error) {
	if db == nil {
		db = dao.GetDB()
	}

	if bill.WaybillVendorID != model.VendorIDMTPS && bill.WaybillVendorID != model.VendorIDDada && bill.WaybillVendorID != model.VendorIDFengNiao && bill.WaybillVendorID != model.VendorIDUUPT {
		return nil
	}

	// 获取订单运单详情列表
	store, _ := dao.GetStoreDetail(db, jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, order.VendorOrgCode)

	// 订单被取消了,所有运单应该也被取消了,检查是否退还配送费
	// 1.查询订单创建的所有运单,三方配送运单(达达,蜂鸟,uu,美团配送),平台自配送订单不参与
	if err := countWaybillSettleInfo(db, order, bill, store); err != nil {
		return err
	}
	// 所有运单停止调度之后才开始退还余额(三方运单)
	bills, err := dao.GetWaybills(db, order.VendorOrderID, []int64{model.VendorIDDada, model.VendorIDFengNiao, model.VendorIDMTPS, model.VendorIDUUPT, model.VendorIDSFPS})
	if err != nil {
		return err
	}

	// 所有取消的运单
	cancelWaybill := make(map[string]*model.Waybill, 0)
	for _, v := range bills {
		if v.Status == model.WaybillStatusCanceled && v.VendorWaybillID != bill.VendorWaybillID {
			cancelWaybill[v.VendorWaybillID] = v
		}
	}
	cancelWaybill[bill.VendorWaybillID] = bill
	// 已经全部运单取消,退款结算
	if len(bills) == len(cancelWaybill) {
		// 最终的金额核算,多退少补
		if err = orderFeeSettle(db, order, bill, bills, store); err != nil {
			return err
		}
	}

	return err
}

// countWaybillSettleInfo 计算订单的结算信息
func countWaybillSettleInfo(db *dao.DaoDB, order *model.GoodsOrder, bill *model.Waybill, store *dao.StoreDetail) error {
	if handlerInfo := partner.GetDeliveryPlatformFromVendorID(bill.WaybillVendorID); handlerInfo != nil {
		// 这一步必须要做,可能不是最后取消订单,需要更新违约金和取消状态
		deductFee, err := handlerInfo.Handler.GetDeliverLiquidatedDamages(bill.VendorOrderID, bill.VendorWaybillID)
		if err != nil {
			partner.CurOrderManager.OnOrderMsg(order, fmt.Sprintf("订单[%s],运单平台[%d],运单[%s]取消,获取违约金异常:%v", order.VendorOrderID, bill.WaybillVendorID, bill.VendorWaybillID, err), "")
			return err
		}

		if err = dao.UpdateWaybillActualFee(db, bill.VendorWaybillID, bill.VendorOrderID, deductFee, deductFee); err != nil {
			return err
		}
		// 门店发单,支付运单违约金
		if store != nil && store.CreateDeliveryType == model.YES && deductFee != model.NO {
			err = partner.CurStoreAcctManager.InsertStoreAcctExpendAndUpdateStoreAcctBalance(jxcontext.AdminCtx, store.ID, int(deductFee), partner.StoreAcctTypeExpendCreateWaybillDeductFee, bill.VendorOrderID, bill.VendorWaybillID, 0)
			if err != nil {
				partner.CurOrderManager.OnOrderMsg(order, fmt.Sprintf("订单[%s],运单平台[%d],运单[%s]取消,获取违约金门店扣除失败:%v,金额[%d]", order.VendorOrderID, bill.WaybillVendorID, bill.VendorWaybillID, err, deductFee), "")
				return err
			}
		}

		if store != nil && store.CreateDeliveryType == model.NO && deductFee != model.NO {
			err = partner.CurStoreAcctManager.InsertBrandBill(jxcontext.AdminCtx, store.BrandID, int(deductFee), model.BrandBillTypeExpend, model.BrandBillFeeTypeDeductFee, order.VendorOrderID, order.VendorWaybillID)
			if err != nil {
				partner.CurOrderManager.OnOrderMsg(order, fmt.Sprintf("订单[%s],运单平台[%d],运单[%s]取消,获取违约金品牌扣除失败:%v,金额[%d]", order.VendorOrderID, bill.WaybillVendorID, bill.VendorWaybillID, err, deductFee), "")
				return err
			}
		}
		if err == nil {
			partner.CurOrderManager.OnOrderMsg(order, fmt.Sprintf("订单[%s],运单平台[%d],运单[%s]取消,违约金扣除成功:%d", order.VendorOrderID, bill.WaybillVendorID, bill.VendorWaybillID, deductFee), "")
			return err
		}
	}
	return nil
}

// 订单金额核算
func orderFeeSettle(db *dao.DaoDB, order *model.GoodsOrder, bill *model.Waybill, bills []*model.Waybill, store *dao.StoreDetail) (err error) {
	billExpend := 0
	billIncome := 0
	allFee := 0
	// 门店结算,全部支出
	if store.CreateDeliveryType == model.YES {
		// 此订单支出的费用
		expendType := []int{partner.StoreAcctTypeExpendCreateWaybillEx, partner.StoreAcctTypeExpendCreateWaybillTip, partner.StoreAcctTypeExpendCreateWaybill2ndMore, partner.StoreAcctTypeExpendCreateWaybillDeductFee, partner.StoreAcctTypeRealFeeExpend}
		billExpend, err = dao.GetStoreAcctExpendTotal(db, store.ID, expendType, bill.VendorOrderID, utils.ZeroTimeValue, utils.ZeroTimeValue)
		if err != nil {
			globals.SugarLogger.Errorf("GetStoreAcctExpendTotal 545 err :%v", err)
			return err
		}
		// 此订单退还的费用
		incomeType := []int{partner.StoreAcctTypeRealFeeIncome, partner.StoreAcctTypeIncomeCancelTemp, partner.StoreAcctTypeIncomeCancelReal}
		billIncome, err = dao.GetStoreAcctIncomeTotal(db, store.ID, incomeType, bill.VendorOrderID, utils.ZeroTimeValue, utils.ZeroTimeValue)
		if err != nil {
			globals.SugarLogger.Errorf("GetStoreAcctIncomeTotal 551 err :%v", err)
			return err
		}

	} else {
		billExpend, err = dao.GetBrandBillOrderExpend(db, store.BrandID, bill.VendorOrderID)
		if err != nil {
			return err
		}
		billIncome, err = dao.GetBrandBillOrderIncome(db, store.BrandID, bill.VendorOrderID)
		if err != nil {
			return err
		}
	}

	for _, v := range bills {
		allFee += int(v.DesiredFee)
		//allFee += int(v.TipFee)
	}
	// 运单支出费用统计,应该等于 支出费用- 退还费用
	globals.SugarLogger.Errorf("计算错误:订单支出费用应该=退还费用+运单支出费用,支出费用:%d,已经退还费用:%d,运单计算费用:%d", billExpend, billIncome, allFee)
	if allFee != billExpend-billIncome {
		globals.SugarLogger.Errorf("计算错误:订单支出费用应该=退还费用+运单支出费用,支出费用:%d,已经退还费用:%d,剩余退还费用:%d", billExpend, billIncome, billExpend-billIncome)
	}

	if billExpend-billIncome == allFee {
		globals.SugarLogger.Debugf("计算正确,运单消耗[%d],账户支出[%d],账户退回[%d]", allFee, billExpend, billIncome)
		partner.CurOrderManager.OnOrderMsg(order, fmt.Sprintf("计算正确,运单消耗[%d],账户支出[%d],账户退回[%d]", allFee, billExpend, billIncome), "")
		return nil
	}

	abnormalAmount := billExpend - billIncome - allFee
	switch store.CreateDeliveryType {
	case model.NO: // 品牌结算
		if abnormalAmount > 0 { // 多退
			err = partner.CurStoreAcctManager.InsertBrandBill(jxcontext.AdminCtx, store.BrandID, abnormalAmount, model.BrandBillTypeIncome, model.BrandBillFeeTypeDelivery, order.VendorOrderID, order.VendorWaybillID)
			if err != nil {
				partner.CurOrderManager.OnOrderMsg(order, fmt.Sprintf("订单[%s],运单平台[%d],运单[%s]取消,品牌支出大于消耗,多退:%v,金额[%d]", order.VendorOrderID, bill.WaybillVendorID, bill.VendorWaybillID, err, abnormalAmount), "")
				globals.SugarLogger.Errorf("InsertBrandBill 489 : %v", err)
				return err
			}
		}
		if abnormalAmount < 0 {
			err = partner.CurStoreAcctManager.InsertBrandBill(jxcontext.AdminCtx, store.BrandID, abnormalAmount*-1, model.BrandBillTypeExpend, model.BrandBillFeeTypeDelivery, order.VendorOrderID, order.VendorWaybillID)
			if err != nil {
				partner.CurOrderManager.OnOrderMsg(order, fmt.Sprintf("订单[%s],运单平台[%d],运单[%s]取消,品牌支出小于消耗,少补:%v,金额[%d]", order.VendorOrderID, bill.WaybillVendorID, bill.VendorWaybillID, err, abnormalAmount), "")
				globals.SugarLogger.Errorf("InsertBrandBill 489 : %v", err)
				return err
			}
		}
	case model.YES: // 门店结算
		if abnormalAmount > 0 { // 多退
			err = partner.CurStoreAcctManager.InsertStoreAcctIncomeAndUpdateStoreAcctBalance(jxcontext.AdminCtx, store.ID, int(billExpend-billIncome-allFee), partner.StoreAcctTypeIncomeCancelReal, bill.VendorOrderID, bill.VendorWaybillID, 0)
			if err != nil {
				partner.CurOrderManager.OnOrderMsg(order, fmt.Sprintf("订单[%s],运单平台[%d],运单[%s]取消,支出大于消耗,多退:%v,金额[%d]", order.VendorOrderID, bill.WaybillVendorID, bill.VendorWaybillID, err, abnormalAmount), "")
				globals.SugarLogger.Errorf("InsertStoreAcctIncomeAndUpdateStoreAcctBalance 483 : %v", err)
			}
		}
		if abnormalAmount < 0 {
			err = partner.CurStoreAcctManager.InsertStoreAcctExpendAndUpdateStoreAcctBalance(jxcontext.AdminCtx, store.ID, int(abnormalAmount)*-1, partner.StoreAcctTypeExpendCreateWaybill2ndMore, bill.VendorOrderID, bill.VendorWaybillID, 0)
			if err != nil {
				partner.CurOrderManager.OnOrderMsg(order, fmt.Sprintf("订单[%s],运单平台[%d],运单[%s]取消,支出小于消耗,少补:%v,金额[%d]", order.VendorOrderID, bill.WaybillVendorID, bill.VendorWaybillID, err, abnormalAmount), "")
				globals.SugarLogger.Errorf("InsertStoreAcctIncomeAndUpdateStoreAcctBalance 483 : %v", err)
			}
		}
	}
	return err
}

func checkPriceDefendOrderByStock(db *dao.DaoDB, storeID, skuID, stock, jxPrice int) (realStock int) {
	var (
		sumStock = 0
	)
	priceDefends, _ := dao.GetPriceDefendOrder(db, "", []int{storeID}, []int{skuID}, []int{jxutils.GetDefendPriceIssue()}, 0, 1, 0, 1, "", utils.ZeroTimeValue, utils.ZeroTimeValue, false)
	if len(priceDefends) == 0 {
		return -1
	}
	for _, v := range priceDefends {
		sumStock += v.Count
	}
	//如果现库存小于等于用户守价的库存，就要开始了
	//如果小于，要按照守价时间的先后来决定
	//如果等于，就刚好全部成功，然后库存清0
	if stock < sumStock {
		tStock := stock
		for _, v := range priceDefends {
			if tStock <= v.Count {
				tStock -= v.Count
				v.IsSuccess = model.YES
				v.RealPrice = int64(jxPrice)
				dao.UpdateEntity(db, v, "IsSuccess", "RealPrice")
			} else {
				continue
			}
		}
		realStock = tStock
	} else if stock == sumStock {
		for _, v := range priceDefends {
			v.IsSuccess = model.YES
			v.RealPrice = int64(jxPrice)
			dao.UpdateEntity(db, v, "IsSuccess", "RealPrice")
		}
		realStock = 0 //库存清0
	} else {
		realStock = -1
	}
	return realStock
}

func (c *OrderManager) updateOrderSkuOtherInfo(order *model.GoodsOrder, db *dao.DaoDB, storePayPercentage, changePriceType int) (err error) {
	jxStoreID := jxutils.GetShowStoreIDFromOrder(order)
	var opNumStr string
	if time.Now().Sub(order.OrderCreatedAt) < 1*time.Hour && order.VendorID != model.VendorIDJD {
		opNumStr = "2"
	} else {
		opNumStr = "2"
	}

	if jxStoreID == 0 {
		return nil
	}
	storeDetail, err1 := dao.GetStoreDetail(db, jxStoreID, order.VendorID, order.VendorOrgCode)
	if err1 != nil || storeDetail.IsSync != model.YES {
		return nil
	}
	orderSkus := order.Skus

	var vendorSkuIDs []string
	for _, v := range orderSkus {
		if v.VendorSkuID == "" {
			vendorSkuIDs = append(vendorSkuIDs, "vendorSkuIdIsNil")
		} else {
			vendorSkuIDs = append(vendorSkuIDs, v.VendorSkuID)
		}
	}
	if len(vendorSkuIDs) > 0 {
		var vendorStoreID string
		if order.VendorID == model.VendorIDJDShop && order.VendorOrgCode == "1" {
			vendorStoreID = model.JdShopMainVendorStoreID
		} else {
			vendorStoreID = order.VendorStoreID
		}
		l, err := dao.GetStoreSkuPriceAndWeight(db, vendorStoreID, order.VendorID, vendorSkuIDs)
		if err != nil {
			return err
		}
		skumapper := storeSkuPriceAndWeight2Map(l)
		for _, v := range orderSkus {
			v.VendorOrderID = order.VendorOrderID
			v.VendorID = order.VendorID

			intVendorSkuID := utils.Str2Int64WithDefault(v.VendorSkuID, 0)
			if intVendorSkuID != 0 && v.VendorSkuID != "-70000" { // todo hard code
				skuBindInfo := skumapper[v.VendorSkuID]
				if v.SkuID == 0 {
					v.SkuID = v.JxSkuID
				}
				if skuBindInfo == nil {
					skuList, _ := dao.GetStoresSkusInfo(db, []int{jxStoreID}, []int{v.SkuID})
					if len(skuList) == model.YES {
						//结算类型
						jxOrderEarningType := 0
						if storeDetail.PayPercentage < 50 {
							jxOrderEarningType = model.EarningTypePoints
						} else {
							jxOrderEarningType = model.EarningTypeQuote
						}
						switch jxOrderEarningType {
						case model.EarningTypeQuote:
							v.ShopPrice = int64(skuList[0].Price)
						case model.EarningTypePoints:
							if order.VendorID == model.VendorIDJD {
								v.ShopPrice = int64(skuList[0].JdPrice)
							} else if order.VendorID == model.VendorIDMTWM {
								v.ShopPrice = int64(skuList[0].MtwmPrice)
							} else if order.VendorID == model.VendorIDEBAI {
								v.ShopPrice = int64(skuList[0].EbaiPrice)
							} else if order.VendorID == model.VendorIDDD {
								v.ShopPrice = int64(skuList[0].DdPrice)
							} else if order.VendorID == model.VendorIDTaoVegetable {
								v.ShopPrice = int64(skuList[0].TaoPrice)
							}
						}

						switch order.VendorID {
						case model.VendorIDMTWM:
							skuList[0].MtwmID = utils.Str2Int64(v.VendorSkuID)
							dao.UpdateEntity(db, skuList[0], "MtwmID")
						case model.VendorIDEBAI:
							skuList[0].EbaiID = utils.Str2Int64(v.VendorSkuID)
							dao.UpdateEntity(db, skuList[0], "EbaiID")
						case model.VendorIDDD:
							skuList[0].DdID = utils.Str2Int64(v.VendorSkuID)
							dao.UpdateEntity(db, skuList[0], "DdID")
						case model.VendorIDTaoVegetable:
							skuList[0].TaoID = utils.Str2Int64(v.VendorSkuID)
							dao.UpdateEntity(db, skuList[0], "TaoID")
						}
					}

					if v.ShopPrice == 0 {
						v.ShopPrice = v.SalePrice * 60 / 100
					}
				} else {
					// TODO 客户端当前逻辑认为SkuID为0为赠品
					v.JxSkuID = skuBindInfo.SkuID
					//京东商城的话，门店里可能取不到对应商品
					if order.VendorID == model.VendorIDJDShop /*|| order.VendorID == model.VendorIDDD*/ {
						if v.SkuID == 0 && v.JxSkuID != 0 {
							v.SkuID = v.JxSkuID
						}
						// v.JxSkuID = v.SkuID
						storeSkus, _ := dao.GetStoresSkusInfo(db, []int{order.StoreID}, []int{v.SkuID})
						if len(storeSkus) > 0 {
							v.ShopPrice = int64(storeSkus[0].Price)
						} else {
							v.ShopPrice = v.SalePrice * 60 / 100
						}
					} else {
						v.ShopPrice = int64(skuBindInfo.Price)
						if v.ShopPrice == 0 {
							v.ShopPrice = v.SalePrice * 60 / 100
						}
					}
					if v.SkuName == "" {
						v.SkuName = jxutils.ComposeSkuNameOriginal(skuBindInfo.Prefix, skuBindInfo.Name, skuBindInfo.Comment, skuBindInfo.Unit, skuBindInfo.SpecQuality, skuBindInfo.SpecUnit, 0)
					}
					v.Weight = skuBindInfo.Weight // 以本地信息中的WEIGHT为准
					if v.Upc == "" {
						v.Upc = skuBindInfo.Upc
					}
					//饿鲜达的订单做一下处理
					if strings.Contains(order.StoreName, model.ExdStoreName) {
						if v.SkuID == 0 && !strings.Contains(v.SkuName, "免费") {
							v.SkuID = v.JxSkuID
						}
					}
					if skuBindInfo.Price == 0 {
						globals.SugarLogger.Infof("updateOrderSkuOtherInfo [运营%s]%s订单sku门店价格为零（一般原因为没有门店价格信息），orderID:%s, StoreID:%d, SkuID:%d, sku:%v", opNumStr, model.VendorChineseNames[order.VendorID], order.VendorOrderID, jxStoreID, v.JxSkuID, v)
					}
				}
			}
			// 直营店始终按比例结算，不考虑活动与结算表
			salePrice := v.SalePrice
			if changePriceType == model.StoreChangePriceTypeManagedStore && v.ShopPrice != 0 {
				salePrice = 0
			}
			v.EarningPrice = jxutils.CaculateSkuEarningPrice(v.ShopPrice, salePrice, storePayPercentage)
		}
		// 直营店始终按比例结算，不考虑活动与结算表
		if changePriceType != model.StoreChangePriceTypeManagedStore {
			updateSingleOrderEarningPrice(order, db)
		}
		//TODO 重复购买有活动且结算价大于0的商品需要拆分，第一个商品按结算价，后面的商品按shopprice 或者 saleprice, 2020-05-06
		//TODO 京东美团的订单，做活动的商品之前就会拆分出来，所以只做更新，饿百暂时不管， 2020-05-07
		//TODO 不根据商品是否拆分，直接根据该商品做了活动，并且他的vendorPrice 和 salePrice 相等，就按新规则结算， 2020-05-11
		//TODO 现在不判断商品做没做活动，只要vendorPrice和salePrice不等，就默认为做了活动，不做活动的商品就按新规则结算，2020-05-18
		// if order.VendorID == model.VendorIDJD || order.VendorID == model.VendorIDMTWM {
		// 	for _, v := range orderSkus {
		// 		if v.EarningPrice > 0 {
		// 			if v.VendorPrice == v.SalePrice {
		// 				var earningPrice = 0
		// 				if v.ShopPrice < v.SalePrice {
		// 					if v.ShopPrice == 0 {
		// 						earningPrice = int(utils.Float64TwoInt64(math.Round(utils.Int2Float64(int(v.SalePrice)) * utils.Int2Float64(storePayPercentage) / 100)))
		// 					} else {
		// 						earningPrice = int(utils.Float64TwoInt64(math.Round(utils.Int2Float64(int(v.ShopPrice)) * utils.Int2Float64(storePayPercentage) / 100)))
		// 					}
		// 				} else {
		// 					earningPrice = int(utils.Float64TwoInt64(math.Round(utils.Int2Float64(int(v.SalePrice)) * utils.Int2Float64(storePayPercentage) / 100)))
		// 				}
		// 				v.EarningPrice = int64(earningPrice)
		// 			}
		// 		}
		// 	}
		// }
	}
	return nil
}

func storeSkuPriceAndWeight2Map(l []*dao.StoreSkuPriceAndWeight) (skuMapper map[string]*dao.StoreSkuPriceAndWeight) {
	skuMapper = make(map[string]*dao.StoreSkuPriceAndWeight)
	for _, v := range l {
		skuMapper[v.VendorSkuID] = v
	}
	return skuMapper
}

func updateSingleOrderEarningPrice(order *model.GoodsOrder, db *dao.DaoDB) {
	jxStoreID := jxutils.GetShowStoreIDFromOrder(order)
	skuIDMap := make(map[int]int)
	for _, v := range order.Skus {
		if skuID := jxutils.GetSkuIDFromOrderSku(v); skuID > 0 {
			skuIDMap[skuID] = 1
		}
	}
	if len(skuIDMap) > 0 {
		actStoreSkuList, err := dao.GetEffectiveActStoreSkuInfo(db, 0, []int{order.VendorID}, model.ActTypeAll, []int{jxStoreID}, jxutils.IntMap2List(skuIDMap), order.OrderCreatedAt, order.OrderCreatedAt)
		if err != nil {
			globals.SugarLogger.Errorf("updateOrderSkuOtherInfo can not get sku promotion info for error:%v", err)
		}
		if actStoreSkuMap := jxutils.NewActStoreSkuMap(actStoreSkuList, false); actStoreSkuMap != nil {
			for _, v := range order.Skus {
				if skuID := jxutils.GetSkuIDFromOrderSku(v); skuID > 0 {
					if actStoreSku := actStoreSkuMap.GetActStoreSku(jxStoreID, skuID, order.VendorID); actStoreSku != nil {
						v.EarningPrice = actStoreSku.EarningPrice
						if true { //v.StoreSubName != "" { // 之前这里为什么要加判断？
							v.StoreSubID = int64(actStoreSku.ActID)
						}
					}
				}
			}
		}
	}
}

func (c *OrderManager) updateOrderOtherInfo(order *model.GoodsOrder, db *dao.DaoDB) (err error) {
	payPercentage := 0
	changePriceType := model.StoreChangePriceTypeDirect
	var storeDetail *dao.StoreDetail
	if order.VendorID == model.VendorIDJDShop {
		storeDetail, err = dao.GetStoreDetailByVendorStoreID(db, order.VendorStoreID, order.VendorID, order.VendorOrgCode)
	} else {
		storeDetail, err = dao.GetStoreDetailByVendorStoreID(db, order.VendorStoreID, order.VendorID, "")
	}
	if err != nil {
		if !dao.IsNoRowsError(err) {
			return err
		}
		if time.Now().Sub(order.OrderCreatedAt) < 1*time.Hour {
			globals.SugarLogger.Infof("updateOrderOtherInfo [运营]订单在京西与平台都找不到京西门店信息,订单:%s,平台门店ID:%s,平台:%s", order.VendorOrderID, order.VendorStoreID, model.VendorChineseNames[order.VendorID])
		}
		err = nil
	} else {
		order.JxStoreID = storeDetail.Store.ID
		changePriceType = int(storeDetail.ChangePriceType)
		//判断订单结算比例
		if storeDetail.VendorPayPercentage != 0 {
			payPercentage = storeDetail.VendorPayPercentage
		} else {
			payPercentage = storeDetail.PayPercentage
		}
		if payPercentage < 50 {
			order.EarningType = model.EarningTypePoints
		} else {
			order.EarningType = model.EarningTypeQuote
		}
		order.OrderPayPercentage = payPercentage
		order.CreateDeliveryType = storeDetail.CreateDeliveryType
	}
	if err = c.updateOrderSkuOtherInfo(order, db, payPercentage, changePriceType); err == nil {
		jxutils.RefreshOrderSkuRelated(order)
		//EarningPrice2, 新规则，门店结算比例在50以下的做新规则计算
		jxutils.RefreshOrderEarningPrice2(order, payPercentage)
		// caculateOrderEarningPrice(order, payPercentage)
	}
	return err
}

// 计算结算给门店的金额
// func caculateOrderEarningPrice(order *model.GoodsOrder, storePayPercentage int) {
// 	order.EarningPrice = 0
// 	for _, v := range order.Skus {
// 		skuEarningPrice := v.EarningPrice
// 		if skuEarningPrice == 0 {
// 			skuEarningPrice = jxutils.CaculateSkuEarningPrice(v.ShopPrice, v.SalePrice, storePayPercentage)
// 		}
// 		order.EarningPrice += skuEarningPrice * int64(v.Count)
// 	}
// }

func (c *OrderManager) addOrderStatus(orderStatus *model.OrderStatus, db *dao.DaoDB) (isDuplicated bool, order *model.GoodsOrder, err error) {
	if db == nil {
		db = dao.GetDB()
	}

	isDuplicated, err = addOrderOrWaybillStatus(orderStatus, db)
	if err == nil && !isDuplicated && (orderStatus.Status != model.OrderStatusUnknown && orderStatus.Status != model.OrderStatusMsg) {
		// todo 加这个代码的原因是,抖店运单取消会去将本地的订单状态设置为取消,跳过,不修改本地订单状态
		if orderStatus.RefVendorID == model.VendorIDDD && orderStatus.OrderType == model.OrderTypeWaybill && orderStatus.VendorStatus == utils.Int64ToStr(tiktok_api.ShipmentStatusCanceled) {
			return isDuplicated, order, err
		}

		order = &model.GoodsOrder{
			VendorOrderID: orderStatus.VendorOrderID,
			VendorID:      orderStatus.VendorID,
		}
		if err = db.Db.ReadForUpdate(order, "VendorOrderID", "VendorID"); err == nil {
			// todo 美团在订单完成后，还可能收到订单取消（应该当成售后单处理才合适），强制忽略这种情况，比如订单：80662201436073600
			// 后来又发现有订单（81710104014426376）在完成后，直接再被取消的情况，不能生成售后单，还是再允许完成后取消。。。
			// if orderStatus.VendorID == model.VendorIDMTWM && model.IsOrderFinalStatus(order.Status) {
			// 	return false, order, nil
			// }
			if (model.IsOrderLockStatus(orderStatus.Status) || model.IsOrderUnlockStatus(orderStatus.Status)) ||
				(model.IsOrderMainStatus(orderStatus.Status) && orderStatus.Status >= order.Status) { // todo 要求status不能回绕
				order.VendorStatus = orderStatus.VendorStatus
				updateFields := []string{
					"VendorStatus",
					"UpdatedAt",
				}
				if model.IsOrderMainStatus(orderStatus.Status) {
					order.Status = orderStatus.Status
					order.StatusTime = orderStatus.StatusTime
					updateFields = append(updateFields, "Status", "StatusTime")
					if model.IsOrderFinalStatus(orderStatus.Status) {
						order.OrderFinishedAt = orderStatus.StatusTime
						updateFields = append(updateFields, "OrderFinishedAt")
						if order.LockStatus != model.OrderStatusUnknown {
							order.LockStatus = model.OrderStatusUnknown
							updateFields = append(updateFields, "LockStatus")
						}
					}
				} else {
					if model.IsOrderUnlockStatus(orderStatus.Status) {
						order.LockStatus = model.OrderStatusUnknown
						updateFields = append(updateFields, "LockStatus")
					} else if model.IsOrderLockStatus(orderStatus.Status) {
						if order.LockStatus != model.OrderStatusUnknown {
							globals.SugarLogger.Warnf("addOrderStatus refOrderID:%s, orderID:%s, order.LockStatus:%d, status.LockStatus:%d", orderStatus.RefVendorOrderID, orderStatus.VendorOrderID, order.LockStatus, orderStatus.Status)
						}
						order.Flag &= ^model.OrderFlagMaskUserApplyCancel
						order.LockStatus = orderStatus.Status
						order.LockStatusTime = orderStatus.StatusTime
						updateFields = append(updateFields, "LockStatus", "LockStatusTime", "Flag")
					}
				}

				utils.CallFuncLogError(func() error {
					_, err = db.Db.Update(order, updateFields...)
					return err
				}, "addOrderStatus update orderID:%s, status:%v", order.VendorOrderID, orderStatus)
			} else {
				isDuplicated = true
			}
		} else {
			order = nil
			if dao.IsNoRowsError(err) { // todo 消息错序
				err = nil
			} else {
				globals.SugarLogger.Warnf("addOrderStatus orderID:%s read failed with error:%v", order.VendorOrderID, err)
			}
		}
	}

	return isDuplicated, order, err
}

func (c *OrderManager) loadOrderSku(db *dao.DaoDB, vendorOrderID string, vendorID int) (orderSkus []*model.OrderSku) {
	utils.CallFuncLogError(func() (err error) {
		_, err = db.Db.QueryTable("order_sku").Filter("vendor_order_id", vendorOrderID).Filter("vendor_id", vendorID).All(&orderSkus)
		return err
	}, "loadOrderSku orderID:%s", vendorOrderID)
	return orderSkus
}

func (c *OrderManager) LoadStoreDetail(storeID, vendorID int) (storeDetail *dao.StoreDetail, err error) {
	var (
		db = dao.GetDB()
	)
	storeDetail, err = dao.GetStoreDetail(db, storeID, vendorID, "")
	return storeDetail, err
}

func (c *OrderManager) loadOrder(vendorOrderID, vendorOrderID2 string, vendorID int) (order *model.GoodsOrder, err error) {
	db1 := dao.GetDB()
	db := db1.Db
	order = &model.GoodsOrder{
		VendorOrderID:  vendorOrderID,
		VendorOrderID2: vendorOrderID2,
		VendorID:       vendorID,
	}
	keyFields := []string{
		model.FieldVendorID,
	}
	if vendorOrderID != "" {
		keyFields = append(keyFields, model.FieldVendorOrderID)
	}
	if vendorOrderID2 != "" {
		keyFields = append(keyFields, model.FieldVendorOrderID2)
	}
	if err = db.Read(order, keyFields...); err == nil {
		vendorOrderID = order.VendorOrderID
		order.Skus = c.loadOrderSku(db1, vendorOrderID, vendorID)
	}
	if err != nil {
		order = nil
		if err == orm.ErrNoRows {
			err = ErrCanNotFindOrder
		}
	}
	return order, err
}

func (c *OrderManager) LoadOrder(vendorOrderID string, vendorID int) (order *model.GoodsOrder, err error) {
	return c.loadOrder(vendorOrderID, "", vendorID)
}

func (c *OrderManager) LoadOrder2(vendorOrderID2 string, vendorID int) (order *model.GoodsOrder, err error) {
	return c.loadOrder("", vendorOrderID2, vendorID)
}

func (c *OrderManager) LoadOrderFinancial(vendorOrderID string, vendorID int) (order *model.OrderFinancial, err error) {
	return c.loadOrderFinancial(vendorOrderID, "", vendorID)
}

func (c *OrderManager) LoadOrderFinancial2(vendorOrderID2 string, vendorID int) (order *model.OrderFinancial, err error) {
	return c.loadOrderFinancial("", vendorOrderID2, vendorID)
}

func (c *OrderManager) loadOrderFinancial(vendorOrderID, vendorOrderID2 string, vendorID int) (order *model.OrderFinancial, err error) {
	db := orm.NewOrm()
	order = &model.OrderFinancial{
		VendorOrderID:  vendorOrderID,
		VendorOrderID2: vendorOrderID2,
		VendorID:       vendorID,
	}
	keyFields := []string{
		model.FieldVendorID,
	}
	if vendorOrderID != "" {
		keyFields = append(keyFields, model.FieldVendorOrderID)
	}
	if vendorOrderID2 != "" {
		keyFields = append(keyFields, model.FieldVendorOrderID2)
	}

	// 这块不知道怎么写了、、、标注一下
	if err = db.Read(order, keyFields...); err == nil {
		vendorOrderID = order.VendorOrderID
		err = utils.CallFuncLogError(func() error {
			_, err = db.QueryTable("order_sku_financial").Filter("vendor_order_id", vendorOrderID).Filter("vendor_id", vendorID).Filter("is_afs_order", 0).All(&order.Skus)
			return err
		}, "LoadOrder orderID:%s", vendorOrderID)
	}
	if err != nil {
		order = nil
		if err == orm.ErrNoRows {
			err = ErrCanNotFindOrder
		}
	}
	return order, err
}

func (c *OrderManager) UpdateOrderStatusAndDeliveryFlag(order *model.GoodsOrder) (err error) {
	return c.UpdateOrderFields(order, []string{"Status", "DeliveryFlag"})
}

func (c *OrderManager) UpdateOrderFields(order *model.GoodsOrder, fieldList []string) (err error) {
	db := dao.GetDB()
	utils.CallFuncLogError(func() error {
		if order.ID == 0 {
			order2 := *order
			if err = dao.GetEntity(db, &order2, model.FieldVendorOrderID, model.FieldVendorID); err == nil {
				order.ID = order2.ID
			} else if dao.IsNoRowsError(err) {
				err = nil // 强制忽略订单不存在错误
			}
		}
		if err == nil && order.ID != 0 {
			_, err = db.Db.Update(order, fieldList...)
		}
		return err
	}, "UpdateOrderFields orderID:%s failed with error:%v", order.VendorOrderID, err)
	return err
}

func (c *OrderManager) RefreshHistoryOrdersEarningPrice(ctx *jxcontext.Context, vendorOrderID string, actID int, vendorIDs []int, storeID int, fromDate, toDate string, isAsync, isContinueWhenError bool) (hint string, errCode string, err error) {
	var (
		orderList     []*model.GoodsOrder
		fromDateParam time.Time
		toDateParam   time.Time
		beginAt       time.Time
		endAt         time.Time
	)
	db := dao.GetDB()
	if actID > 0 {
		if fromDate != "" && toDate != "" {
			fromDateParam = utils.Str2Time(fromDate)
			toDateParam = utils.Str2Time(toDate)
			actList, _ := dao.QueryActs(db, actID, 0, math.MaxInt32, 0, "", -1, nil, nil, nil, 0, nil, 0, utils.DefaultTimeValue, utils.DefaultTimeValue, utils.DefaultTimeValue, utils.DefaultTimeValue)
			if len(actList.Data) > 0 {
				actBeginAt := actList.Data[0].BeginAt
				actEndAt := actList.Data[0].EndAt
				if fromDateParam.Sub(actBeginAt) > 0 && fromDateParam.Sub(actEndAt) > 0 {
					return "", model.ErrCodeGeneralFailed, errors.New(fmt.Sprintf("结算活动有效时间范围与订单创建时间范围不一致！，活动时间范围：[%v] 至 [%v] ，订单创建时间范围 ：[%v] 至 [%v]", actBeginAt, actEndAt, fromDateParam, toDateParam))
				}
				if actBeginAt.Sub(toDateParam) > 0 && actEndAt.Sub(toDateParam) > 0 {
					return "", model.ErrCodeGeneralFailed, errors.New(fmt.Sprintf("结算活动有效时间范围与订单创建时间范围不一致！，活动时间范围：[%v] 至 [%v] ，订单创建时间范围 ：[%v] 至 [%v]", actBeginAt, actEndAt, fromDateParam, toDateParam))
				}
				if fromDateParam.Sub(actBeginAt) > 0 {
					beginAt = fromDateParam
					if toDateParam.Sub(actEndAt) > 0 {
						endAt = actEndAt
					} else {
						endAt = toDateParam
					}
				} else {
					beginAt = actBeginAt
					if toDateParam.Sub(actEndAt) > 0 {
						endAt = actEndAt
					} else {
						endAt = toDateParam
					}
				}
				orderList, _ = dao.QueryOrders(db, vendorOrderID, actID, vendorIDs, storeID, beginAt, endAt)
			} else {
				return "", model.ErrCodeGeneralFailed, errors.New(fmt.Sprintf("未查询到相关结算活动，活动ID：[%d]", actID))
			}
		} else if fromDate == "" && toDate == "" {
			actList, _ := dao.QueryActs(db, actID, 0, math.MaxInt32, 0, "", -1, nil, nil, nil, 0, nil, 0, utils.DefaultTimeValue, utils.DefaultTimeValue, utils.DefaultTimeValue, utils.DefaultTimeValue)
			if len(actList.Data) > 0 {
				orderList, _ = dao.QueryOrders(db, vendorOrderID, actID, vendorIDs, storeID, actList.Data[0].BeginAt, actList.Data[0].EndAt)
				if len(orderList) == 0 {
					return "", model.ErrCodeGeneralFailed, errors.New(fmt.Sprintf("未查询到相关订单！开始时间：[%v]，结束时间：[%v]", actList.Data[0].BeginAt, actList.Data[0].EndAt))
				}
			} else {
				return "", model.ErrCodeGeneralFailed, errors.New(fmt.Sprintf("未查询到相关结算活动，活动ID：[%d]", actID))
			}
		} else {
			return "", model.ErrCodeGeneralFailed, errors.New(fmt.Sprintf("间隔时间必须完整！时间范围：[%v]  至  [%v]", fromDate, toDate))
		}
	} else {
		if fromDate != "" && toDate != "" {
			fromDateParam = utils.Str2Time(fromDate)
			toDateParam = utils.Str2Time(toDate)
			//若未传入活动ID,且时间间隔大于10天则不允许查询
			if math.Ceil(toDateParam.Sub(fromDateParam).Hours()/24) > 10 {
				return "", model.ErrCodeGeneralFailed, errors.New(fmt.Sprintf("查询间隔时间不允许大于10天！时间范围：[%v]  至  [%v]", fromDate, toDate))
			}
			orderList, _ = dao.QueryOrders(db, vendorOrderID, actID, vendorIDs, storeID, fromDateParam, toDateParam)
		} else {
			return "", model.ErrCodeGeneralFailed, errors.New(fmt.Sprintf("若不按活动查询则间隔时间必须完整！时间范围：[%v]  至  [%v]", fromDate, toDate))
		}
	}
	if len(orderList) <= 0 {
		return "", model.ErrCodePoint, errors.New(fmt.Sprintf("所选活动没有要更新结算价的订单！,vendorOrderID : %s, actID : %d, 时间范围：[%v]  至  [%v]", vendorOrderID, actID, fromDate, toDate))
	}
	task := tasksch.NewParallelTask("刷新历史订单结算价", tasksch.NewParallelConfig().SetIsContinueWhenError(isContinueWhenError), ctx,
		func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
			order := batchItemList[0].(*model.GoodsOrder)
			db := dao.GetDB()
			updateSingleOrderEarningPrice(order, db)
			txDB, _ := dao.Begin(db)
			defer func() {
				if r := recover(); r != nil || err != nil {
					dao.Rollback(db, txDB)
					if r != nil {
						panic(r)
					}
				}
			}()
			for _, value := range order.Skus {
				// storeID := 0
				// if order.StoreID == 0 {
				// 	storeID = order.JxStoreID
				// } else {
				// 	storeID = order.StoreID
				// }
				// result, _ := dao.GetEffectiveActStoreSkuInfo(db, 0, nil, 0, []int{storeID}, []int{value.SkuID}, order.OrderCreatedAt, order.OrderCreatedAt)
				// if len(result) > 0 {
				// 	if result[0].EarningPrice != 0 {
				// 		var (
				// 			storePayPercentage int
				// 		)
				// 		stores, _ := dao.GetStoreList(db, []int{order.StoreID}, nil, nil, nil, "")
				// 		if len(stores) > 0 {
				// 			storePayPercentage = stores[0].PayPercentage
				// 		} else {
				// 			storePayPercentage = 70
				// 		}
				// 		sku := value
				// 		sku.Count = value.Count - 1
				// 		value.Count = 1
				// 		if value.ShopPrice < value.SalePrice {
				// 			sku.EarningPrice = value.ShopPrice * int64(storePayPercentage)
				// 		} else {
				// 			sku.EarningPrice = value.SalePrice * int64(storePayPercentage)
				// 		}
				// 		order.Skus = append(order.Skus, sku)
				// 	}
				// }
				if _, err = dao.UpdateEntity(db, value, "EarningPrice", "StoreSubID"); err != nil {
					return nil, err
				}
			}
			jxutils.RefreshOrderSkuRelated(order)
			storeID := 0
			if order.StoreID == 0 {
				storeID = order.JxStoreID
			} else {
				storeID = order.StoreID
			}
			store, _ := dao.GetStoreDetail(db, storeID, order.VendorID, "")
			payPercentage := store.PayPercentage
			if payPercentage <= 50 {
				order.NewEarningPrice = order.TotalShopMoney * utils.Float64TwoInt64(utils.Int2Float64(100)-utils.Int2Float64(payPercentage)/2) / 100
			} else {
				order.NewEarningPrice = order.EarningPrice
			}
			num, err := dao.UpdateEntity(db, order, "EarningPrice", "NewEarningPrice")
			if err != nil {
				return nil, err
			}
			dao.Commit(db, txDB)
			retVal = []string{utils.Int64ToStr(num)}
			return retVal, err
		}, orderList)
	tasksch.HandleTask(task, nil, true).Run()
	if !isAsync {
		resultNum, err2 := task.GetResult(0)
		if err = err2; err == nil {
			hint = resultNum[0].(string)
		}
	} else {
		hint = task.GetID()
	}
	return hint, model.ErrCodeSuccess, err
}

func RefreshOrdersWithoutJxStoreID(ctx *jxcontext.Context, fromDate, toDate string, isAsync, isContinueWhenError bool) (hint string, err error) {
	var (
		fromDateParam time.Time
		toDateParam   time.Time
	)
	if fromDate != "" {
		fromDateParam = utils.Str2Time(fromDate)
	}
	if toDate != "" {
		toDateParam = utils.Str2Time(toDate)
	}
	db := dao.GetDB()
	task := tasksch.NewParallelTask("订单门店归属补漏", tasksch.NewParallelConfig().SetParallelCount(1), ctx,
		func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
			_, err = dao.UpdateOrdersWithoutJxStoreID(db, fromDateParam, toDateParam)
			return retVal, err
		}, []int{0})
	tasksch.HandleTask(task, nil, true).Run()
	if !isAsync {
		_, err = task.GetResult(0)
		hint = "1"
	} else {
		hint = task.GetID()
	}
	return hint, err
}

func GetOrdersSupplement(ctx *jxcontext.Context, storIDs, vendorIDs, statuss []int, vendorOrderID, fromTime, toTime string, stype, IsReverse, offset, pageSize int) (pageInfo *model.PagedInfo, err error) {
	var (
		db        = dao.GetDB()
		fromTimeP time.Time
		toTimeP   time.Time
	)
	if fromTime != "" {
		fromTimeP = utils.Str2Time(fromTime)
	}
	if toTime != "" {
		toTimeP = utils.Str2Time(toTime)
	}
	if fromTimeP.After(toTimeP) {
		return nil, fmt.Errorf("时间范围不合法！开始时间：[%v]，结束时间：[%v]", fromTimeP, toTimeP)
	}
	result, totalCount, err := dao.GetOrdersSupplement(db, storIDs, vendorIDs, statuss, vendorOrderID, fromTimeP, toTimeP, stype, IsReverse, offset, pageSize)
	pageInfo = &model.PagedInfo{
		Data:       result,
		TotalCount: totalCount,
	}
	return pageInfo, err
}

func AddUpdateOrdersSupplement(ctx *jxcontext.Context, ordersSupplement *model.OrderSupplementFee) (num int64, err error) {
	var (
		db = dao.GetDB()
		id = ordersSupplement.ID
	)
	now := time.Now()
	ordersSupplement.SupplementTime = &now
	txDB, _ := dao.Begin(db)
	defer func() {
		if r := recover(); r != nil || err != nil {
			dao.Rollback(db, txDB)
			if r != nil {
				panic(r)
			}
		}
	}()
	if id > 0 {
		orderSupplementFee, _ := dao.GetOrdersSupplementNoPage(db, id, nil, nil, nil, "", utils.ZeroTimeValue, utils.ZeroTimeValue, 0, 0)
		if len(orderSupplementFee) > 2 || len(orderSupplementFee) == 0 {
			return 0, fmt.Errorf("查询扣款记录有误，请联系技术部！")
		}
		if orderSupplementFee[0].Status == 1 {
			return 0, fmt.Errorf("已结账的扣款信息不允许修改！门店ID:[%v]，订单号:[%v]", ordersSupplement.StoreID, ordersSupplement.VendorOrderID)
		}
		ordersSupplement.UpdatedAt = time.Now()
		ordersSupplement.LastOperator = ctx.GetUserName()
		ordersSupplement.CreatedAt = orderSupplementFee[0].CreatedAt
		if ordersSupplement.Status == -1 {
			ordersSupplement.DeletedAt = time.Now()
		} else {
			ordersSupplement.DeletedAt = utils.DefaultTimeValue
		}
		num, err = dao.UpdateEntity(db, ordersSupplement)
	} else {
		dao.WrapAddIDCULDEntity(ordersSupplement, ctx.GetUserName())
		err = dao.CreateEntity(db, ordersSupplement)
	}
	dao.Commit(db, txDB)
	return num, err
}

func RefreshOrdersPriceInfo(ctx *jxcontext.Context, fromTime, toTime time.Time, isAsync, isContinueWhenError bool) (hint string, err error) {
	if utils.IsTimeZero(fromTime) {
		return "", fmt.Errorf("必须指定起始时间")
	}
	if utils.IsTimeZero(toTime) {
		toTime = fromTime
	}

	db := dao.GetDB()
	orderList, err := dao.QueryOrders(db, "", 0, nil, 0, fromTime, toTime)
	if err == nil && len(orderList) > 0 {
		task := tasksch.NewParallelTask("RefreshOrdersPriceInfo", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(isContinueWhenError), ctx,
			func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
				curOrder := batchItemList[0].(*model.GoodsOrder)
				newOrder, err := FixedOrderManager.LoadOrder(curOrder.VendorOrderID, curOrder.VendorID)
				if err == nil {
					db := dao.GetDB()
					if err = FixedOrderManager.updateOrderOtherInfo(newOrder, db); err == nil {
						txDB, _ := dao.Begin(db)
						defer func() {
							if r := recover(); r != nil {
								dao.Rollback(db, txDB)
								panic(r)
							}
						}()
						if _, err = dao.UpdateEntity(db, newOrder); err != nil {
							dao.Rollback(db, txDB)
							return nil, err
						}

						for _, sku := range newOrder.Skus {
							if _, err = dao.UpdateEntity(db, sku); err != nil {
								dao.Rollback(db, txDB)
								return nil, err
							}
						}
						dao.Commit(db, txDB)
					}
				}
				return retVal, err
			}, orderList)
		tasksch.HandleTask(task, nil, true).Run()
		if isAsync {
			hint = task.GetID()
		} else {
			_, err = task.GetResult(0)
			hint = "1"
		}
	}
	return hint, err
}

type GetOrderSimpleInfoResult struct {
	VendorOrderID   string `orm:"column(vendor_order_id)" json:"vendorOrderID"`
	Status          int    `json:"status"`
	WaybillVendorID int    `orm:"column(waybill_vendor_id)" json:"waybillVendorID"`
	CourierName     string `json:"courierName"`
	CourierMobile   string `json:"courierMobile"`
	Tel1            string `json:"tel1"`
	MarketManPhone  string `json:"marketManPhone"`
}

func GetOrderSimpleInfo(ctx *jxcontext.Context, vendorOrderID string) (getOrderSimpleInfoResult *GetOrderSimpleInfoResult, err error) {
	db := dao.GetDB()
	sql := `
		SELECT a.vendor_order_id, a.status, a.waybill_vendor_id, c.courier_name, c.courier_mobile, b.tel1, b.market_man_phone
		FROM goods_order a
		JOIN store b ON IF(a.store_id <> '', a.store_id, a.jx_store_id) = b.id 
		LEFT JOIN waybill c ON c.vendor_order_id = a.vendor_order_id 
		WHERE (a.vendor_order_id LIKE ? OR a.consignee_mobile LIKE ?)
		ORDER BY a.order_created_at DESC
		LIMIT 1 
	`
	sqlParams := []interface{}{
		"%" + vendorOrderID + "%",
		"%" + vendorOrderID + "%",
	}
	err = dao.GetRow(db, &getOrderSimpleInfoResult, sql, sqlParams)
	if getOrderSimpleInfoResult == nil {
		return getOrderSimpleInfoResult, fmt.Errorf("未查询到该订单的信息！")
	}

	return getOrderSimpleInfoResult, err
}

func setJdsOrderSeq(order *model.GoodsOrder) (err error) {
	type tCount struct {
		Count int `json:"count"`
	}
	var counts []*tCount
	sql := `
		SELECT count(*) count FROM goods_order WHERE store_id = ? AND order_created_at >= ? AND order_created_at <= ? AND vendor_id = ?
	`
	sqlParams := []interface{}{
		order.StoreID, utils.Time2Date(time.Now()), utils.Time2Date(time.Now().AddDate(0, 0, 1)), order.VendorID,
	}
	err = dao.GetRows(dao.GetDB(), &counts, sql, sqlParams)
	order.OrderSeq = counts[0].Count + 1
	return err
}

func MergeJdsOrders(ctx *jxcontext.Context, vendorOrderIDs []string) (vendorOrderIDJds string, err error) {
	var (
		db             = dao.GetDB()
		orders         []*model.GoodsOrder
		orderSkus      []*model.OrderSku
		orderIDs       []string
		storeDuplicate = make(map[int]int)
		storeID        int
	)
	for _, vendorOrderID := range vendorOrderIDs {
		order, _ := dao.GetSimpleOrder(db, vendorOrderID)
		if err != nil || order == nil {
			return "", fmt.Errorf("未查询到该订单！订单号：[%v]", vendorOrderID)
		}
		if order.Status >= model.OrderStatusDelivering && order.Status != model.OrderStatusCanceled {
			return "", fmt.Errorf("暂不支持此状态的订单进行转移！订单号:[%v]", vendorOrderID)
		}
		if order.VendorID != model.VendorIDJDShop {
			return "", fmt.Errorf("暂不支持非京狗的订单进行转移！订单号:[%v]", vendorOrderID)
		}
		storeDuplicate[jxutils.GetSaleStoreIDFromOrder(order)] = jxutils.GetSaleStoreIDFromOrder(order)
		orders = append(orders, order)

		//订单商品
		skus, _ := dao.GetSimpleOrderSkus(db, order.VendorOrderID, nil)
		orderSkus = append(orderSkus, skus...)

		orderIDs = append(orderIDs, vendorOrderID)
	}
	if len(storeDuplicate) > 1 {
		return "", fmt.Errorf("只能选择相同门店的订单进行合并！")
	} else {
		storeID = jxutils.GetSaleStoreIDFromOrder(orders[0])
	}
	for _, order := range orders {
		var waybill *model.Waybill
		//将订单和运单取消
		waybills, err := dao.GetWaybills(db, order.VendorOrderID, nil)
		if err != nil {
			return "", err
		}
		if len(waybills) > 0 {
			for _, v := range waybills {
				if v.Status != model.WaybillStatusCanceled {
					waybill = v
				}
			}
			if waybill != nil {
				if waybill.WaybillVendorID != model.VendorIDJDWL {
					if handler := partner.GetDeliveryPlatformFromVendorID(waybill.WaybillVendorID); handler != nil {
						err = handler.Handler.CancelWaybill(waybill, 0, "订单合并被取消2")
					}
				}
			}
		}
		if err = jdshop.ChangeOrderStatus(order.VendorOrderID, model.OrderStatusCanceled, "订单合并被取消"); err != nil {
			return "", err
		}
	}
	//重新构建order的数据
	storeMaps, err := dao.GetStoresMapList(db, []int{model.VendorIDJDShop}, []int{storeID}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", "")
	if err != nil || len(storeMaps) == 0 {
		return "", fmt.Errorf("该门店未绑定京狗平台，请先绑定后再转移！门店：[%v]", storeID)
	}
	stores, _ := dao.GetStoreList(db, []int{storeID}, nil, nil, nil, nil, "")
	var (
		newEarningPrice int64
		actualPrice     int64
		shopPrice       int64
		salePrice       int64
		totalShop       int64
	)
	for _, v := range orders {
		newEarningPrice += v.NewEarningPrice
		actualPrice += v.ActualPayPrice
		shopPrice += v.ShopPrice
		salePrice += v.SalePrice
		totalShop += v.TotalShopMoney
	}
	store := stores[0]
	order := orders[0]
	order.ID = 0
	order.NewEarningPrice = newEarningPrice
	order.ActualPayPrice = actualPrice
	order.SalePrice = salePrice
	order.ShopPrice = shopPrice
	order.TotalShopMoney = totalShop
	order.VendorOrderID = utils.Int64ToStr(utils.Str2Int64(orders[0].VendorOrderID2)*10000000) + utils.Int2Str(time.Now().Second())
	if len(order.VendorOrderID) < 18 {
		order.VendorOrderID = order.VendorOrderID + "0"
	}
	order.VendorOrderID2 = strings.Join(orderIDs, ",")
	order.Status = model.OrderStatusNew
	setJdsOrderSeq(order)
	if order.BusinessType == model.BusinessTypeImmediate {
		var (
			opentime1      = jxutils.JxOperationTime2TimeByDate(store.OpenTime1, order.CreatedAt)
			opentime2      = jxutils.JxOperationTime2TimeByDate(store.OpenTime2, order.CreatedAt)
			closetime1     = jxutils.JxOperationTime2TimeByDate(store.CloseTime1, order.CreatedAt)
			closetime2     = jxutils.JxOperationTime2TimeByDate(store.CloseTime2, order.CreatedAt)
			orderCreatedAt = order.CreatedAt
		)
		if store.OpenTime1 == 0 || store.CloseTime1 == 0 {
			return "", fmt.Errorf("该门店没有营业时间，不能接单！门店：[%v]", storeID)
		}
		if !(orderCreatedAt.Sub(opentime1) >= 0 && orderCreatedAt.Sub(closetime1) <= 0) {
			if store.OpenTime2 != 0 && store.CloseTime2 != 0 {
				if !(orderCreatedAt.Sub(opentime2) >= 0 && orderCreatedAt.Sub(closetime2) <= 0) {
					if orderCreatedAt.Sub(opentime1) < 0 {
						order.ExpectedDeliveredTime = opentime1
						order.BusinessType = model.BusinessTypeDingshida
					} else {
						if orderCreatedAt.Sub(opentime2) < 0 {
							order.ExpectedDeliveredTime = opentime2
						} else {
							order.ExpectedDeliveredTime = opentime1.AddDate(0, 0, 1)
						}
						order.BusinessType = model.BusinessTypeDingshida
					}
				}
			} else {
				if orderCreatedAt.Sub(opentime1) < 0 {
					order.ExpectedDeliveredTime = opentime1
				} else {
					order.ExpectedDeliveredTime = opentime1.AddDate(0, 0, 1)
				}
				order.BusinessType = model.BusinessTypeDingshida
			}
		}
	}
	//结算类型
	if store.PayPercentage < 50 {
		order.EarningType = model.EarningTypePoints
	} else {
		order.EarningType = model.EarningTypeQuote
	}
	if storeID != model.JdShopMainStoreID {
		order.DeliveryFlag = model.NO
	}
	//skus
	for _, sku := range orderSkus {
		sku.VendorOrderID = order.VendorOrderID
		sku.ID = 0
	}
	order.Skus = orderSkus
	err = partner.CurOrderManager.OnOrderNew(order, model.Order2Status(order))
	vendorOrderIDJds = order.VendorOrderID
	return vendorOrderIDJds, err
}

func TransferJdsOrder(ctx *jxcontext.Context, vendorOrderID string, storeID int) (vendorOrderIDJds string, err error) {
	var (
		db      = dao.GetDB()
		waybill *model.Waybill
	)
	order, err := dao.GetSimpleOrder(db, vendorOrderID)
	if err != nil || order == nil {
		return "", fmt.Errorf("未查询到该订单！订单号：[%v]", vendorOrderID)
	}
	if order.Status >= model.OrderStatusDelivering && order.Status != model.OrderStatusCanceled {
		return "", fmt.Errorf("暂不支持此状态的订单进行转移！")
	}
	if order.VendorID != model.VendorIDJDShop && order.VendorID != model.VendorIDJX {
		return "", fmt.Errorf("暂不支持该平台的订单进行转移！")
	}
	skus, err := dao.GetSimpleOrderSkus(db, vendorOrderID, nil)
	if err != nil || order == nil {
		return "", fmt.Errorf("未查询到该订单商品！订单号：[%v]", vendorOrderID)
	}
	//将订单和运单取消
	waybills, err := dao.GetWaybills(db, vendorOrderID, nil)
	if err != nil {
		return "", err
	}
	if len(waybills) > 0 {
		for _, v := range waybills {
			if v.Status != model.WaybillStatusCanceled {
				waybill = v
			}
		}
		if waybill != nil {
			if handler := partner.GetDeliveryPlatformFromVendorID(waybill.WaybillVendorID); handler != nil {
				err = handler.Handler.CancelWaybill(waybill, 0, "订单转移被取消3")
			}
		}
	}
	//重新构建order的数据
	storeMaps, err := dao.GetStoresMapList(db, []int{order.VendorID}, []int{storeID}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", order.VendorOrgCode)
	if err != nil || len(storeMaps) == 0 {
		return "", fmt.Errorf("该门店未绑定平台，请先绑定后再转移！门店：[%v]", storeID)
	}
	stores, err := dao.GetStoreList(db, []int{storeID}, nil, nil, nil, nil, "")
	if len(storeMaps) > 0 && len(stores) > 0 {
		if storeMaps[0].VendorStoreID == "" {
			return "", fmt.Errorf("该门店未绑定平台，或绑定有误，请联系技术部！门店：[%v]", storeID)
		}
		order.StoreID = storeID
		order.StoreName = stores[0].Name
		order.VendorStoreID = storeMaps[0].VendorStoreID
		//如果是立即达的订单，要判断一下下单时间是否在门店营业时间范围内
		//若没有，则要把这个订单变成定时达，预计送达时间改为门店的营业时间
		//如果门店没有营业时间，则直接报错
		if order.BusinessType == model.BusinessTypeImmediate {
			store := stores[0]
			var (
				opentime1      = jxutils.JxOperationTime2TimeByDate(store.OpenTime1, order.OrderCreatedAt)
				opentime2      = jxutils.JxOperationTime2TimeByDate(store.OpenTime2, order.OrderCreatedAt)
				closetime1     = jxutils.JxOperationTime2TimeByDate(store.CloseTime1, order.OrderCreatedAt)
				closetime2     = jxutils.JxOperationTime2TimeByDate(store.CloseTime2, order.OrderCreatedAt)
				orderCreatedAt = order.OrderCreatedAt
			)
			if store.OpenTime1 == 0 || store.CloseTime1 == 0 {
				return "", fmt.Errorf("该门店没有营业时间，不能接单！门店：[%v]", storeID)
			}
			if closetime1.Sub(opentime1) <= time.Hour {
				return "", fmt.Errorf("该门店营业时间间隔过小，请确认！门店：[%v]", storeID)
			}
			if !(orderCreatedAt.Sub(opentime1) >= 0 && orderCreatedAt.Sub(closetime1) <= 0) {
				if store.OpenTime2 != 0 && store.CloseTime2 != 0 {
					if !(orderCreatedAt.Sub(opentime2) >= 0 && orderCreatedAt.Sub(closetime2) <= 0) {
						if orderCreatedAt.Sub(opentime1) < 0 {
							order.ExpectedDeliveredTime = opentime1
							order.BusinessType = model.BusinessTypeDingshida
						} else {
							if orderCreatedAt.Sub(opentime2) < 0 {
								order.ExpectedDeliveredTime = opentime2
							} else {
								order.ExpectedDeliveredTime = opentime1.AddDate(0, 0, 1)
							}
							order.BusinessType = model.BusinessTypeDingshida
						}
					}
				} else {
					if orderCreatedAt.Sub(opentime1) < 0 {
						order.ExpectedDeliveredTime = opentime1
					} else {
						order.ExpectedDeliveredTime = opentime1.AddDate(0, 0, 1)
					}
					order.BusinessType = model.BusinessTypeDingshida
				}
			}
		}
		//结算类型
		if stores[0].PayPercentage < 50 {
			order.EarningType = model.EarningTypePoints
		} else {
			order.EarningType = model.EarningTypeQuote
		}
	} else {
		return "", fmt.Errorf("未查询到该门店对应的平台信息！门店：[%v]", order.StoreID)
	}
	if order.VendorID == model.VendorIDJDShop {
		if len(order.VendorOrderID) > 12 {
			var goodsOrders []*model.GoodsOrder
			sql := `
				SELECT * FROM goods_order WHERE vendor_order_id2 = ? ORDER BY vendor_order_id DESC
			`
			sqlParams := []interface{}{order.VendorOrderID2}
			err = dao.GetRows(db, &goodsOrders, sql, sqlParams)
			for _, order := range goodsOrders {
				if order.Status != model.OrderStatusCanceled {
					err = jdshop.ChangeOrderStatus(order.VendorOrderID, model.OrderStatusCanceled, "订单转移被取消")
				}
			}
			// suffix := utils.Str2Int(goodsOrders[0].VendorOrderID[12:len(goodsOrders[0].VendorOrderID)])
			// suffix++
			if len(order.VendorOrderID2) > 18 {
				order.VendorOrderID2 = order.VendorOrderID2[0:12]
			}
			order.VendorOrderID = utils.Int64ToStr(utils.Str2Int64(order.VendorOrderID2)*10000000) + utils.Int2Str(time.Now().Second())
			if len(order.VendorOrderID) < 18 {
				order.VendorOrderID = order.VendorOrderID + "0"
			}
		}
		if storeID != model.JdShopMainStoreID {
			order.DeliveryFlag = model.NO
		}
		err = jdshop.ChangeOrderStatus(vendorOrderID, model.OrderStatusCanceled, "订单转移被取消")
		if err != nil {
			return "", err
		}
		order.Status = model.OrderStatusNew
		if order.ActualPayPrice == 0 {
			msg, err := jdshop.GetJdsOrder(order.VendorOrderID2, order.VendorOrgCode)
			if err == nil {
				if jxutils.StandardPrice2Int(utils.Str2Float64(msg.OrderPayment)) == 0 {
					order.ActualPayPrice = jxutils.StandardPrice2Int(utils.Str2Float64(msg.OrderTotalPrice) + utils.Str2Float64(msg.FreightPrice) - utils.Str2Float64(msg.SellerDiscount))
				} else {
					order.ActualPayPrice = jxutils.StandardPrice2Int(utils.Str2Float64(msg.OrderPayment))
				}
				order.TotalShopMoney = utils.Float64TwoInt64(float64(order.ActualPayPrice) * jdshopapi.JdsPayPercentage)
			}
		}
	} else {
		order.VendorOrderID2 = order.VendorOrderID
		order.VendorOrderID = utils.Int64ToStr(jxutils.GenOrderNo())
		order.DeliveryFlag = model.NO
		orderStatus := &model.OrderStatus{
			VendorOrderID:    vendorOrderID,
			VendorID:         model.VendorIDJX,
			OrderType:        model.OrderTypeOrder,
			RefVendorOrderID: vendorOrderID,
			RefVendorID:      model.VendorIDJX,
			VendorStatus:     utils.Int2Str(model.OrderStatusCanceled),
			Status:           model.OrderStatusCanceled,
			StatusTime:       time.Now(),
			Remark:           "订单转移被取消",
		}
		jxutils.CallMsgHandlerAsync(func() {
			err = partner.CurOrderManager.OnOrderStatusChanged(order.VendorOrgCode, orderStatus)
		}, jxutils.ComposeUniversalOrderID(vendorOrderID, model.VendorIDJX))
		if err != nil {
			return "", err
		}
		if order.VendorOrgCode == "1" {
			order.Status = model.OrderStatusAccepted
		} else {
			order.Status = model.OrderStatusNew
		}
	}
	for _, sku := range skus {
		sku.VendorOrderID = order.VendorOrderID
		sku.ID = 0
		var storesSku *model.StoreSkuBind
		sql := `
			SELECT * FROM store_sku_bind WHERE deleted_at = ? AND store_id = ? AND jds_id = ?
		`
		sqlParams := []interface{}{utils.DefaultTimeValue, model.JdShopMainStoreID, sku.VendorSkuID}
		if err = dao.GetRow(db, &storesSku, sql, sqlParams); err == nil && storesSku != nil {
			if realStoresSkus, err := dao.GetStoresSkusInfo(db, []int{storeID}, []int{storesSku.SkuID}); err == nil && len(realStoresSkus) > 0 {
				sku.ShopPrice = int64(realStoresSkus[0].Price)
			}
		}
		order.Skus = append(order.Skus, sku)
	}
	setJdsOrderSeq(order)
	err = partner.CurOrderManager.OnOrderNew(order, model.Order2Status(order))
	vendorOrderIDJds = order.VendorOrderID
	return vendorOrderIDJds, err
}

func SendJdwlForJdsOrder(ctx *jxcontext.Context, vendorOrderID string) (err error) {
	db := dao.GetDB()
	order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, model.VendorIDJDShop)
	if order == nil || err != nil {
		return fmt.Errorf("目前只支持京狗订单创建！")
	}
	if order.Status >= model.OrderStatusDelivering {
		return fmt.Errorf("订单当前状态不支持创建！")
	}
	waybill := &model.Waybill{}
	waybills, err := dao.GetWaybills(db, vendorOrderID, nil)
	if err != nil {
		return err
	}
	if len(waybills) > 0 {
		for _, v := range waybills {
			if v.Status != model.WaybillStatusCanceled {
				waybill = v
			}
		}
		if handler := partner.GetDeliveryPlatformFromVendorID(model.VendorIDJDWL); handler != nil {
			err = handler.Handler.CancelWaybill(waybill, 0, "订单已发送其他物流4")
		}
		if err != nil {
			return err
		}
	}
	var vendorWaybillID string
	if order.StoreID == model.JdShopMainStoreID {
		var (
			goodsNos   []string
			prices     []string
			quantities []string
		)
		for _, v := range order.Skus {
			skus, err := dao.GetSkus(db, []int{v.SkuID}, nil, nil, nil, nil)
			if err != nil || len(skus) == 0 {
				continue
			}
			goodsNos = append(goodsNos, skus[0].EclpID)
			prices = append(prices, "0")
			quantities = append(quantities, utils.Int2Str(v.Count))
		}
		eclpSoNo, err := api.JdEclpAPI.AddOrder(&jdeclpapi.AddOrderParam{
			IsvUUID:              order.VendorOrderID,
			IsvSource:            jdeclpapi.IsvSource,
			ShopNo:               jdeclpapi.ShopNo,
			DepartmentNo:         jdeclpapi.DepartmentNo,
			WarehouseNo:          jdeclpapi.WarehouseNo,
			ShipperNo:            jdeclpapi.ShipperNo,
			SalesPlatformOrderNo: order.VendorOrderID,
			SalePlatformSource:   jdeclpapi.SalePlatformSource,
			ConsigneeName:        order.ConsigneeName,
			ConsigneeMobile:      order.ConsigneeMobile,
			ConsigneeAddress:     order.ConsigneeAddress,
			OrderMark:            jdeclpapi.OrderMark,
			GoodsNo:              strings.Join(goodsNos, ","),
			Price:                strings.Join(prices, ","),
			Quantity:             strings.Join(quantities, ","),
		})
		waybill := &model.Waybill{
			VendorOrderID:     order.VendorOrderID,
			OrderVendorID:     model.VendorIDJX,
			VendorWaybillID:   eclpSoNo,
			WaybillVendorID:   model.VendorIDJDWL,
			Status:            model.WaybillStatusDelivering,
			WaybillCreatedAt:  time.Now(),
			StatusTime:        time.Now(),
			WaybillFinishedAt: utils.DefaultTimeValue,
			DeliveryFlag:      model.OrderDeliveryFlagMaskScheduleDisabled,
		}
		dao.CreateEntity(db, waybill)
		if err != nil {
			return err
		}
		order.EclpOutID = eclpSoNo
		dao.UpdateEntity(db, order, "EclpOutID")
		vendorWaybillID = eclpSoNo
	} else {
		// if handler := partner.GetDeliveryPlatformFromVendorID(model.VendorIDJDWL); handler != nil {
		// 	waybill2, err := handler.Handler.CreateWaybill(order, 0)
		// 	if err != nil {
		// 		return err
		// 	}
		// 	vendorWaybillID = waybill2.VendorWaybillID
		// }
	}
	jdshop.CurPurchaseHandler.OrderExport(ctx, vendorOrderID, vendorWaybillID, false)
	return err
}

func AdjustJdsOrderSimple(ctx *jxcontext.Context, vendorOrderID string, skuID int) (err error) {
	var (
		db = dao.GetDB()
	)
	orderSkus, err := dao.GetSimpleOrderSkus(db, vendorOrderID, []int{skuID})
	order, err := dao.GetSimpleOrder(db, vendorOrderID)
	//如果不是商城模板店
	if jxutils.GetSaleStoreIDFromOrder(order) != model.JdShopMainStoreID {
		return fmt.Errorf("目前只支持商城模板店的简单售前删除！")
	}
	orderSkus2, err := dao.GetSimpleOrderSkus(db, vendorOrderID, nil)
	if len(orderSkus2) == 1 {
		return fmt.Errorf("这一单只剩这最后一个商品了，不允许删除！")
	}
	if len(orderSkus) == 0 {
		return fmt.Errorf("未查询到该订单商品！")
	}
	if order.Status > model.OrderStatusAccepted {
		return fmt.Errorf("目前只支持待拣货状态前的订单售前调整！")
	}
	orderSku := orderSkus[0]
	if orderSku.Count > 1 {
		orderSku.Count--
		_, err = dao.UpdateEntity(db, orderSku, "Count")
	} else {
		_, err = dao.DeleteEntity(db, orderSku)
	}
	order.AdjustCount++
	order.ActualPayPrice = order.ActualPayPrice - orderSku.SalePrice
	order.TotalShopMoney = int64(float64(order.ActualPayPrice) * jdshopapi.JdsPayPercentage)
	dao.UpdateEntity(db, order, "AdjustCount", "TotalShopMoney")
	return err
}

func UpdateWaybillDesiredFee(ctx *jxcontext.Context, vendorOrderID string, desiredFee int) (err error) {
	var (
		db = dao.GetDB()
	)
	order, _ := dao.GetSimpleOrder(db, vendorOrderID)
	if order == nil {
		return fmt.Errorf("未找到该订单！orderID: %v", vendorOrderID)
	}
	bill, _ := partner.CurOrderManager.LoadWaybill(order.VendorWaybillID, order.WaybillVendorID)
	if bill == nil {
		waybill := &model.Waybill{
			VendorOrderID:     order.VendorOrderID,
			OrderVendorID:     order.VendorID,
			VendorWaybillID:   utils.Int64ToStr(GenOrderNo(ctx)),
			WaybillVendorID:   -1,
			Status:            model.WaybillStatusDelivered,
			WaybillCreatedAt:  time.Now(),
			StatusTime:        time.Now(),
			WaybillFinishedAt: utils.DefaultTimeValue,
			DeliveryFlag:      model.OrderDeliveryFlagMaskScheduleDisabled,
			DesiredFee:        int64(desiredFee),
		}
		dao.CreateEntity(db, waybill)
		order.VendorWaybillID = waybill.VendorWaybillID
		dao.UpdateEntity(db, order, "VendorWaybillID")
	} else {
		bill.DesiredFee = int64(desiredFee)
		_, err = dao.UpdateEntity(db, bill, "DesiredFee")
		if order.EarningType == model.EarningTypePoints {
			order.NewEarningPrice = order.NewEarningPrice - int64(desiredFee)
			_, err = dao.UpdateEntity(db, order, "NewEarningPrice")
		}
	}
	return err
}

func AcceptOrRefuseOrder(ctx *jxcontext.Context, vendorOrderID string, vendorID int, isAccept bool) (err error) {
	order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, vendorID)
	handler := partner.GetPurchaseOrderHandlerFromVendorID(vendorID)
	err = handler.AcceptOrRefuseOrder(order, isAccept, ctx.GetUserName())
	if err == nil && isAccept && vendorID == model.VendorIDEBAI {
		// netprinter.PrintOrderByOrder(jxcontext.AdminCtx, order)
		// smsmsg.NotifyNewOrder(order)
		// smsmsg.NotifyNewUserOrder(order)
		// weixinmsg.NotifyNewOrder(order)
		// msghub.OnNewOrder(order)
	}
	return err
}

func GenOrderNo(ctx *jxcontext.Context) (orderNo int64) {
	const prefix = 88
	const randPartNum = 1000
	orderNo = time.Now().Unix() - orderNoBeginTimestamp
	// fmt.Println(orderNo)
	orderNo = orderNo * randPartNum
	md5Bytes := md5.Sum([]byte(utils.GetUUID()))
	randPart := 0
	for k, v := range md5Bytes {
		randPart += int(v) << ((k % 3) * 8)
	}
	orderNo += int64(randPart % randPartNum)
	orderNo += int64(math.Pow10(int(math.Log10(float64(orderNo)))+1)) * prefix
	return orderNo
}

func RefreshJdsOrderConsigneeInfo(ctx *jxcontext.Context, vendorOrderID string) (err error) {
	order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, model.VendorIDJDShop)
	if order == nil {
		return fmt.Errorf("未查询到此京东商城订单！")
	}
	waybill, err := partner.CurOrderManager.LoadWaybill(order.VendorWaybillID, order.WaybillVendorID)
	if waybill != nil {
		return fmt.Errorf("已经创建了三方运单不允许修改联系人信息！")
	}
	jdsOrder, err := jdshop.GetJdsOrder(order.VendorOrderID2, order.VendorOrgCode)
	if err != nil {
		return err
	}
	if jdsOrder == nil {
		return fmt.Errorf("未查询到对应的京东商城订单！")
	}
	order.ConsigneeAddress = jdshop.Decrypt(jdsOrder.ConsigneeInfo.FullAddress, order.VendorOrgCode)
	order.ConsigneeName = jdshop.Decrypt(jdsOrder.ConsigneeInfo.Fullname, order.VendorOrgCode)
	order.ConsigneeMobile = jdshop.Decrypt(jdsOrder.ConsigneeInfo.Mobile, order.VendorOrgCode)
	order.ConsigneeMobile2 = jdshop.Decrypt(jdsOrder.ConsigneeInfo.Telephone, order.VendorOrgCode)
	order.BuyerComment = jdsOrder.OrderRemark
	if order.ConsigneeAddress != "" {
		lng, lat, _, _, _ := api.TencentMapAPI.GetCoordinateFromAddress(order.ConsigneeAddress, "")
		order.ConsigneeLng = jxutils.StandardCoordinate2Int(lng)
		order.ConsigneeLat = jxutils.StandardCoordinate2Int(lat)
	}
	partner.CurOrderManager.UpdateOrderFields(order, []string{"ConsigneeAddress", "ConsigneeName", "ConsigneeMobile", "ConsigneeMobile2", "BuyerComment", "ConsigneeLng", "ConsigneeLat"})
	return err
}

func UpdateOrderInfo(ctx *jxcontext.Context, vendorOrderID string, vendorID int, payload map[string]interface{}) (num int64, err error) {
	var (
		db             = dao.GetDB()
		jxSubsidyMoney int64
	)
	order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, vendorID)
	if payload["consigneeLng"] != nil || payload["consigneeLat"] != nil {
		payload["consigneeLng"] = jxutils.StandardCoordinate2Int(utils.Interface2Float64WithDefault(payload["consigneeLng"], 0.0))
		payload["consigneeLat"] = jxutils.StandardCoordinate2Int(utils.Interface2Float64WithDefault(payload["consigneeLat"], 0.0))
	}
	if payload["expectedDeliveredTime"] != nil {
		payload["expectedDeliveredTime"] = utils.Str2Time(payload["expectedDeliveredTime"].(string))
	}
	if payload["jxSubsidyMoney"] != nil {
		jxSubsidyMoney = utils.Interface2Int64WithDefault(payload["jxSubsidyMoney"], 0)
		//if order.EarningType == model.EarningTypeQuote {
		//	payload["earningPrice"] = order.EarningPrice - order.JxSubsidyMoney + jxSubsidyMoney
		//}
	}
	valid := dao.StrictMakeMapByStructObject(payload, order, ctx.GetUserName())
	if len(valid) > 0 {
		txDB, _ := dao.Begin(db)
		defer func() {
			if r := recover(); r != nil {
				dao.Rollback(db, txDB)
				panic(r)
			}
		}()
		if num, err = dao.UpdateEntityByKV(db, order, valid, nil); err != nil {
			dao.Rollback(db, txDB)
			return 0, err
		}
		dao.Commit(db, txDB)
	}
	if payload["jxSubsidyMoney"] != nil {
		var (
			userIDs []string
		)
		storeDetail, _ := dao.GetStoreDetail(db, jxutils.GetSaleStoreIDFromOrder(order), order.VendorID, order.VendorOrgCode)
		if storeDetail != nil && storeDetail.Tel1 != "" {
			user, _ := dao.GetUserByID(db, "mobile", storeDetail.Tel1)
			if user != nil {
				userIDs = append(userIDs, user.UserID)
			}
			if storeDetail.Tel2 != "" {
				user2, _ := dao.GetUserByID(db, "mobile", storeDetail.Tel2)
				if user2 != nil {
					userIDs = append(userIDs, user2.UserID)
				}
			}
		}
		weixinmsg.SendUserMessage(jxcontext.AdminCtx, "订单补偿", fmt.Sprintf("您收到了%v元的订单补偿，订单号：[%v]", jxutils.IntPrice2Standard(jxSubsidyMoney), order.VendorOrderID), userIDs, true, true)
	}
	return num, err
}

func RefreshOrderSkuInfo(ctx *jxcontext.Context, vendorOrderID string, vendorID, skuID int) (num int64, err error) {
	var (
		db                      = dao.GetDB()
		shopPrice, earningPrice int64
	)
	order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, vendorID)
	if order.EarningType != model.EarningTypeQuote {
		return 0, fmt.Errorf("目前只支持报价订单有此操作！")
	}
	updateOrderSku := func(v *model.OrderSku, skuID2 int) (err error) {
		storeSkus, _ := dao.GetStoresSkusInfo(db, []int{jxutils.GetSaleStoreIDFromOrder(order)}, []int{skuID2})
		if len(storeSkus) == 0 {
			return fmt.Errorf("未找到此门店商品！")
		}
		storeSku := storeSkus[0]
		if beego.BConfig.RunMode == model.ServerTypeFruits || beego.BConfig.RunMode == model.ServerTypePet {
			if v.SalePrice > v.ShopPrice {
				v.EarningPrice = int64(math.Round(float64(storeSku.Price) * float64(order.OrderPayPercentage) / 100))
			} else {
				v.EarningPrice = int64(math.Round(float64(v.SalePrice) * float64(order.OrderPayPercentage) / 100))
			}
		} else {
			v.EarningPrice = int64(math.Round(float64(storeSku.Price) * float64(order.OrderPayPercentage) / 100))
		}
		v.ShopPrice = int64(storeSku.Price)
		dao.UpdateEntity(db, v, "ShopPrice", "EarningPrice")
		return err
	}
	for _, v := range order.Skus {
		if v.SkuID == 0 {
			if v.JxSkuID == skuID {
				err = updateOrderSku(v, skuID)
			}
		} else {
			if v.SkuID == skuID {
				err = updateOrderSku(v, skuID)
			}
		}
	}
	if err != nil {
		return 0, err
	}
	for _, v := range order.Skus {
		shopPrice += v.ShopPrice * int64(v.Count)
		earningPrice += v.EarningPrice * int64(v.Count)
	}
	order.ShopPrice = shopPrice
	order.EarningPrice = earningPrice
	num, err = dao.UpdateEntity(db, order, "ShopPrice", "EarningPrice")
	return num, err
}

func UpdateJdsOrdersStatus(ctx *jxcontext.Context, orderCreatedStart, orderCreatedEnd time.Time) (err error) {
	var (
		pageSize = 20
		orderIDs []int64
	)
	orderResult, err := jdshop.CurPurchaseHandler.GetJdsOrders(ctx, utils.Time2Str(orderCreatedStart), utils.Time2Str(orderCreatedEnd), 1, pageSize)
	if orderResult.TotalCount > pageSize {
		for pageNO := 1; pageNO < orderResult.TotalCount/pageSize+1; pageNO++ {
			orderResult2, _ := jdshop.CurPurchaseHandler.GetJdsOrders(ctx, utils.Time2Str(orderCreatedStart), utils.Time2Str(orderCreatedEnd), pageNO, pageSize)
			for _, order := range orderResult2.OrderList {
				if order.OrderStatus == jdshopapi.OrderStatusCancelm2 {
					orderIDs = append(orderIDs, order.OrderID)
				}
			}
		}
	}
	for _, orderID := range orderIDs {
		var goodsOrder *model.GoodsOrder
		sql := `
			SELECT * FROM goods_order WHERE vendor_order_id2 = ?
		`
		sqlParams := []interface{}{orderID}
		if dao.GetRow(dao.GetDB(), &goodsOrder, sql, sqlParams); goodsOrder != nil {
			if goodsOrder.Status != model.OrderStatusCanceled {
				goodsOrder.Status = model.OrderStatusCanceled
				dao.UpdateEntity(dao.GetDB(), goodsOrder, "Status")
			}
		}
	}
	return err
}

func SaveJdsOrders(ctx *jxcontext.Context, orderCreatedStart, orderCreatedEnd time.Time) (err error) {
	var (
		pageSize = 10
	)
	orderResult, err := jdshop.CurPurchaseHandler.GetJdsOrders(ctx, utils.Time2Str(orderCreatedStart), utils.Time2Str(orderCreatedEnd), 1, pageSize)
	if err != nil {
		noticeMsg := fmt.Sprintf("京东商城保存订单出错！（多半是cookie过期了）,err :[%v]", err)
		ddmsg.SendUserMessage(dingdingapi.MsgTyeText, "BF09DB25350611EB89AC525400E86DC0", "cookie", noticeMsg)
		return err
	}
	orders, err := result2Orders(ctx, orderResult)
	if orderResult.TotalCount > pageSize {
		for pageNO := 2; pageNO <= orderResult.TotalCount/pageSize+1; pageNO++ {
			orderResult, _ := jdshop.CurPurchaseHandler.GetJdsOrders(ctx, utils.Time2Str(orderCreatedStart), utils.Time2Str(orderCreatedEnd), pageNO, pageSize)
			orders2, _ := result2Orders(ctx, orderResult)
			orders = append(orders, orders2...)
		}
	}
	for _, order := range orders {
		partner.CurOrderManager.OnOrderNew(order, model.Order2Status(order))
		noticeMsg := fmt.Sprintf("京东商城新订单，订单号：[%v] ,将要发到的门店id：[%v] , 门店名：[%v]", order.VendorOrderID, order.StoreID, order.StoreName)
		if order.OrderType == model.OrderTypeAddressErr {
			noticeMsg += " 此订单地址有问题，需要矫正坐标！"
		}
		var role = autils.NewRole("jdshop", 0)
		userIDList, _ := api2.RoleMan.GetRoleUserList(role)
		for _, v := range userIDList {
			ddmsg.SendUserMessage(dingdingapi.MsgTyeText, v, "京东商城来新订单了！", noticeMsg)
		}
	}
	return err
}

func result2Orders(ctx *jxcontext.Context, result *jdshopapi.AllOrdersResult) (orders []*model.GoodsOrder, err error) {
	var (
		db = dao.GetDB()
	)
	for _, jdsOrder := range result.OrderList {
		//等待付款的排除
		//完成	19
		//配送中 52
		//待配送 51
		//待接单 50
		if jdsOrder.OrderStatus == jdshopapi.JdsOrderStatusWaittingPay || jdsOrder.OrderStatus == jdshopapi.JdsOrderStatusWaittingPayDel {
			continue
		}
		//有可能是库里已经有这个订单了
		orderE, err := partner.CurOrderManager.LoadOrder(utils.Int64ToStr(jdsOrder.OrderID)+"00000001", model.VendorIDJDShop)
		if orderE != nil {
			continue
		}

		orderDetail, err := jdshop.GetAPI("2").OrderDetail(utils.Int64ToStr(jdsOrder.OrderID))
		if err != nil {
			continue
		}
		order := &model.GoodsOrder{
			VendorOrderID2:   utils.Int64ToStr(jdsOrder.OrderID),
			VendorOrderID:    utils.Int64ToStr(jdsOrder.OrderID) + "00000001",
			VendorID:         model.VendorIDJDShop,
			BaseFreightMoney: jxutils.StandardPrice2Int(jdsOrder.Freight),
			VendorStatus:     utils.Int2Str(jdsOrder.OrderStatus),
			VendorUserID:     jdsOrder.UserPin,
			BuyerComment:     jdsOrder.UserRemark,
			PickDeadline:     utils.DefaultTimeValue,
			OriginalData:     string(utils.MustMarshal(jdsOrder)),
			StoreName:        jdsOrder.StoreName,
			OrderCreatedAt:   utils.Str2Time(jdsOrder.OrderCreateTime + ":00"),
			ConsigneeAddress: orderDetail.ConsigneeAddress,
			ConsigneeName:    orderDetail.ConsigneeName,
			ActualPayPrice:   orderDetail.ActualPayPrice,
			Status:           model.OrderStatusNew,
			TotalShopMoney:   utils.Float64TwoInt64(math.Round(utils.Int64ToFloat64(orderDetail.ActualPayPrice) * jdshopapi.JdsPayPercentage)),
			DeliveryType:     model.OrderDeliveryTypeStoreSelf,
			StatusTime:       utils.Str2Time(jdsOrder.OrderCreateTime + ":00"),
			OrderSeq:         0,
			VendorOrgCode:    "2",
		}
		//获取真实手机号
		fakeMobile, err := jdshop.GetAPI("2").PhoneSensltiveInfo(order.VendorOrderID2, orderDetail.MobileKey)
		if err != nil {
			continue
		} else {
			order.ConsigneeMobile = jxutils.DecryptDESECB([]byte(fakeMobile), []byte(jdshopapi.JdsMobileKey))
		}
		if order.TotalShopMoney < 100 {
			order.TotalShopMoney = 100
		}
		//如果是暂停，表示是预订单
		if jdsOrder.OrderStatus == jdshopapi.JdsOrderStatusPause {
			order.BusinessType = model.BusinessTypeDingshida
			order.ExpectedDeliveredTime = utils.Str2Time(orderDetail.ExpectedDeliveredTime)
			order.PickDeadline = order.ExpectedDeliveredTime.Add(-time.Hour)
		} else if jdsOrder.OrderStatus != jdshopapi.JdsOrderStatusWaittingPayDel {
			order.ExpectedDeliveredTime = order.OrderCreatedAt.Add(time.Hour)
			order.BusinessType = model.BusinessTypeImmediate
		}
		//表示可能是定时达的
		if orderDetail.ExpectedDeliveredTime != "" {
			order.BusinessType = model.BusinessTypeDingshida
			order.ExpectedDeliveredTime = utils.Str2Time(orderDetail.ExpectedDeliveredTime)
			order.PickDeadline = order.ExpectedDeliveredTime.Add(-time.Hour)
		}
		setJdsOrderSeq(order)
		for _, v := range jdsOrder.OrderItems {
			sku := &model.OrderSku{
				VendorID:      model.VendorIDJDShop,
				VendorOrderID: order.VendorOrderID,
				Count:         v.SkuNum,
				VendorSkuID:   utils.Int64ToStr(v.SkuID),
				SkuName:       v.SkuName,
				VendorPrice:   jxutils.StandardPrice2Int(v.JdPrice),
				SalePrice:     jxutils.StandardPrice2Int(v.JdPrice),
			}
			var storeSku *model.StoreSkuBind
			sql := `
				SELECT * FROM store_sku_bind WHERE store_id = ? AND jds_id = ? AND deleted_at = ?
			`
			sqlParams := []interface{}{model.JdShopMainStoreID, v.SkuID, utils.DefaultTimeValue}
			err = dao.GetRow(dao.GetDB(), &storeSku, sql, sqlParams)
			if storeSku != nil {
				sku.SkuID = storeSku.SkuID
			}
			_, _, _, specUnit, _, specQuality := jxutils.SplitSkuName(v.SkuName)
			sku.Weight = jxutils.FormatSkuWeight(specQuality, specUnit)
			order.Skus = append(order.Skus, sku)
		}
		var store *dao.StoreDetail
		if jdsOrder.MdbStoreID != 0 {
			if store, err = dao.GetStoreDetailByVendorStoreID(db, utils.Int64ToStr(jdsOrder.MdbStoreID), model.VendorIDJDShop, "2"); store != nil && err == nil {
				order.StoreID = store.ID
				order.JxStoreID = store.ID
				order.StoreName = store.Name
				order.VendorStoreID = utils.Int64ToStr(jdsOrder.MdbStoreID)
				//结算类型
				if store.PayPercentage < 50 {
					order.EarningType = model.EarningTypePoints
				} else {
					order.EarningType = model.EarningTypeQuote
				}
				var (
					shopPriceSum int
				)
				for _, sku := range order.Skus {
					storeSkuList, _ := dao.GetStoresSkusInfo(db, []int{order.StoreID}, []int{sku.SkuID})
					if len(storeSkuList) > 0 {
						shopPriceSum += storeSkuList[0].Price * sku.Count
						sku.ShopPrice = int64(storeSkuList[0].Price)
					} else {
						shopPriceSum += int(sku.SalePrice) * 60 / 100
					}
				}
				if order.EarningType == model.EarningTypeQuote && shopPriceSum+700 > int(order.TotalShopMoney) {
					buildOrderTo102919(order)
				}
				if order.ConsigneeAddress != "" {
					var (
						cityCode             = 0
						lng, lat, lng2, lat2 float64
					)
					if shopDetail, _ := api.JdShopAPI.ShopDetail(int(jdsOrder.MdbStoreID)); shopDetail != nil {
						if shopDetail.AddCode2 != 0 {
							var place = &model.Place{}
							sql1 := "SELECT * FROM place WHERE jds_code = ?"
							sqlParams1 := []interface{}{shopDetail.AddCode2}
							if err2 := dao.GetRow(db, &place, sql1, sqlParams1); err2 == nil && place != nil {
								cityCode = place.Code
							} else {
								sql2 := "SELECT * FROM place WHERE jd_code = ?"
								sqlParams2 := []interface{}{shopDetail.AddCode2}
								if err3 := dao.GetRow(db, &place, sql2, sqlParams2); err3 == nil && place != nil {
									cityCode = place.Code
								}
							}
						}
					}
					//if cityCode != 0 {
					//lng, lat, _ = api.AutonaviAPI.GetCoordinateFromAddressByPage(order.ConsigneeAddress, cityCode)
					//} else {
					lng2, lat2, _, _, err = api.TencentMapAPI.GetCoordinateFromAddress(order.ConsigneeAddress, utils.Int2Str(cityCode))
					if err == nil && lng2 != 0 && lat2 != 0 {
						order.ConsigneeLng = jxutils.StandardCoordinate2Int(lng2)
						order.ConsigneeLat = jxutils.StandardCoordinate2Int(lat2)
					} /* else {
						order.ConsigneeLng = jxutils.StandardCoordinate2Int(lng2)
						order.ConsigneeLat = jxutils.StandardCoordinate2Int(lat2)
					}*/
					//}
					distance := jxutils.EarthDistance(lng, lat, lng2, lat2)
					if distance > 1 {
						order.OrderType = model.OrderTypeAddressErr
						order.DeliveryFlag = model.OrderDeliveryFlagMaskScheduleDisabled
					}
				}
			} else {
				continue
			}
		} else {
			buildOrderTo102919(order)
		}
		//TODO 2021-10-11 取消限额
		//if order.ActualPayPrice > 300000 {
		//	buildOrderTo102919(order)
		//	globals.SugarLogger.Debugf("resultjdsOrders  return 8")
		//}
		if store != nil {
			distance := jxutils.EarthDistance(jxutils.IntCoordinate2Standard(order.ConsigneeLng), jxutils.IntCoordinate2Standard(order.ConsigneeLat), jxutils.IntCoordinate2Standard(store.Lng), jxutils.IntCoordinate2Standard(store.Lat))
			if distance > 4 {
				buildOrderTo102919(order)
			}
			if store.Status != model.StoreStatusOpened && store.Status != model.StoreStatusHaveRest {
				buildOrderTo102919(order)
			}
		}
		orders = append(orders, order)
	}
	return orders, err
}

func buildOrderTo102919(order *model.GoodsOrder) {
	// if order.VendorOrgCode == "1" {
	// 	order.StoreID = 102919
	// 	order.JxStoreID = 102919
	// 	order.StoreName = "商城模板(成都发货)"
	// 	order.VendorStoreID = model.JdShopMainVendorStoreID
	// } else {
	order.StoreID = model.JdShopMainStoreID
	order.JxStoreID = model.JdShopMainStoreID
	order.StoreName = "商城模板店2"
	order.VendorStoreID = model.JdShopMainVendorStoreID
	// }
	order.DeliveryFlag = model.OrderDeliveryFlagMaskScheduleDisabled
}

func RefreshJdAfsOrderTotalShopMoney() {
	var (
		db        = dao.GetDB()
		afsOrders []*model.AfsOrder
	)
	sql := `
		SELECT * FROM afs_order WHERE afs_created_at > ? AND vendor_id = ? AND status = ? AND afs_total_shop_money = 0
	`
	sqlParams := []interface{}{time.Now().AddDate(0, 0, -3), model.VendorIDJD, model.AfsOrderStatusFinished}
	dao.GetRows(db, &afsOrders, sql, sqlParams)
	for _, v := range afsOrders {
		//排除物竞天择的
		if order, _ := partner.CurOrderManager.LoadOrder(v.VendorOrderID, v.VendorID); !strings.Contains(order.BuyerComment, "JD") {
			if handler := partner.GetPurchaseOrderHandlerFromVendorID(v.VendorID); handler != nil {
				if orderAfsInfo, err := handler.GetOrderAfsInfo(nil, v.VendorOrderID, v.AfsOrderID); err == nil && orderAfsInfo.AfsTotalShopMoney != 0 {
					v.AfsTotalShopMoney = orderAfsInfo.AfsTotalShopMoney
				}
			}
			dao.UpdateEntity(db, v, "AfsTotalShopMoney")
		}
	}
}

func DelOrderSkuInfo(ctx *jxcontext.Context, vendorOrderID string, vendorID, id int) (num int64, err error) {
	var (
		db                      = dao.GetDB()
		shopPrice, earningPrice int64
		orderSkus               []*model.OrderSku
	)
	order, err := partner.CurOrderManager.LoadOrder(vendorOrderID, vendorID)
	if order.EarningType != model.EarningTypeQuote {
		return 0, fmt.Errorf("目前只支持报价订单有此操作！")
	}
	sql := `
		SELECT * FROM order_sku WHERE vendor_order_id = ? ORDER BY id
	`
	sqlParams := []interface{}{vendorOrderID}
	dao.GetRows(db, &orderSkus, sql, sqlParams)
	if len(orderSkus) < 3 {
		return 0, fmt.Errorf("商品数小于3，不允许删除！")
	}
	if orderSkus[0].ID == int64(id) {
		return 0, fmt.Errorf("不允许删第一个商品！")
	}
	for _, v := range order.Skus {
		if v.ID == int64(id) {
			if v.Count == model.YES {
				sql := `
					DELETE FROM order_sku WHERE id = ?
				`
				sqlParams := []interface{}{v.ID}
				dao.ExecuteSQL(db, sql, sqlParams)
			} else {
				sql := `
					UPDATE order_sku SET count = ? WHERE id = ?
				`
				sqlParams := []interface{}{v.Count - 1, v.ID}
				dao.ExecuteSQL(db, sql, sqlParams)
			}

			shopPrice = v.ShopPrice * int64(1)
			earningPrice = v.EarningPrice * int64(1)
			//shopPrice = v.ShopPrice * int64(v.Count)
			//earningPrice = v.EarningPrice * int64(v.Count)
		}
	}
	order.ShopPrice -= shopPrice
	order.EarningPrice -= earningPrice
	num, err = dao.UpdateEntity(db, order, "ShopPrice", "EarningPrice")
	return num, err
}

func BuildFakeMatterOrder() {
	var (
		db = dao.GetDB()
	)
	storeMaps, _ := dao.GetStoresMapList(db, []int{model.VendorIDJX}, []int{668202}, nil, model.StoreStatusAll, model.StoreIsSyncAll, "", "", "")
	task := tasksch.NewParallelTask("BuildFakeMatterOrder", tasksch.NewParallelConfig().SetParallelCount(1).SetIsContinueWhenError(true), jxcontext.AdminCtx,
		func(task *tasksch.ParallelTask, batchItemList []interface{}, params ...interface{}) (retVal interface{}, err error) {
			storeMap := batchItemList[0].(*model.StoreMap)
			storeDetail, _ := dao.GetStoreDetail(db, storeMap.StoreID, storeMap.VendorID, "")
			vendorOrderID := utils.Int64ToStr(jxutils.GenOrderNo())
			order := &model.GoodsOrder{
				VendorOrderID:         vendorOrderID,
				VendorID:              model.VendorIDJX,
				VendorStoreID:         utils.Int2Str(model.MatterStoreID),
				StoreID:               model.MatterStoreID,
				JxStoreID:             model.MatterStoreID,
				StoreName:             "物料申请",
				ShopPrice:             2000,
				SalePrice:             2000,
				Weight:                1460,
				ConsigneeName:         storeDetail.Name,
				ConsigneeMobile:       storeDetail.Tel1,
				ConsigneeAddress:      storeDetail.Address,
				ConsigneeLng:          storeDetail.Lng,
				ConsigneeLat:          storeDetail.Lat,
				SkuCount:              1,
				GoodsCount:            1,
				Status:                model.OrderStatusFinished,
				VendorStatus:          utils.Int2Str(model.OrderStatusFinished),
				ExpectedDeliveredTime: time.Now().Add(time.Hour),
				WaybillVendorID:       401,
				OrderCreatedAt:        time.Now(),
				OrderFinishedAt:       time.Now().Add(time.Hour * 2),
				ActualPayPrice:        501,
				StatusTime:            time.Now().Add(time.Hour),
				BusinessType:          1,
				VendorPrice:           3100,
				DeliveryType:          "store",
				TotalShopMoney:        471,
				EarningPrice:          2000,
				DeliveryFlag:          1,
				FromStoreID:           storeDetail.ID,
				EarningType:           1,
				OrderType:             1,
				OrderPayPercentage:    100,
			}
			order.CreatedAt = time.Now()
			order.UpdatedAt = time.Now()
			orderSku := &model.OrderSku{
				VendorOrderID:  vendorOrderID,
				VendorID:       model.VendorIDJX,
				Count:          1,
				VendorSkuID:    "6039382",
				SkuID:          6039382,
				JxSkuID:        6039382,
				SkuName:        "背心袋(京西菜市)1.46kg/件(100个)",
				ShopPrice:      2000,
				SalePrice:      1,
				Weight:         1460,
				OrderCreatedAt: time.Now(),
				EarningPrice:   2000,
				VendorPrice:    3100,
			}
			dao.CreateEntity(db, order)
			dao.CreateEntity(db, orderSku)
			statusList := []int{2, 5, 15, 20, 110}
			for _, v := range statusList {
				orderStatus := &model.OrderStatus{
					VendorOrderID:    vendorOrderID,
					VendorID:         model.VendorIDJX,
					OrderType:        1,
					RefVendorOrderID: vendorOrderID,
					RefVendorID:      model.VendorIDJX,
					Status:           v,
					VendorStatus:     utils.Int2Str(v),
					StatusTime:       time.Now().Add(time.Minute * time.Duration(v)),
				}
				orderStatus.CreatedAt = time.Now()
				orderStatus.UpdatedAt = time.Now()
				dao.CreateEntity(db, orderStatus)
			}
			return retVal, err
		}, storeMaps)
	tasksch.HandleTask(task, nil, true).Run()
	task.GetResult(0)
}

func ExportOrderWithSku(ctx *jxcontext.Context, orders []*model.GoodsOrderExt) (downloadURL string, err error) {
	type ExportOrderWithSkuExt struct {
		StoreName       string  `json:"门店名"`
		VendorName      string  `json:"平台名"`
		OrderCreatedAt  string  `json:"下单时间"`
		VendorOrderID   string  `orm:"column(vendor_order_id)" json:"订单号"`
		EarningPrice    float64 `json:"订单结算"`
		SkuName         string  `json:"商品名"`
		CategoryNameFst string  `json:"一级分类名"`
		CategoryNameSnd string  `json:"二级分类名"`
		ShopPrice       float64 `json:"商品报价"`
		Count           int     `json:"数量"`
		EarningPriceSku float64 `json:"商品结算"`
		Upc             string  `json:"条形码"`
		IsAfs           int     `json:"是否已售后"`
		AfsCount        int     `json:"售后数量"`
	}
	var (
		db         = dao.GetDB()
		excelTitle = []string{
			"门店名",
			"平台名",
			"下单时间",
			"订单号",
			"订单结算",
			"商品名",
			"一级分类名",
			"二级分类名",
			"商品报价",
			"数量",
			"商品结算",
			"条形码",
			"是否已售后",
			"售后数量",
		}
		vendorOrderIDs []string
		results        []*ExportOrderWithSkuExt
	)
	for _, v := range orders {
		vendorOrderIDs = append(vendorOrderIDs, v.VendorOrderID)
	}
	sql := `
		SELECT IF(a.vendor_id = 0, '京东',IF(a.vendor_id = 1, '美团',IF(a.vendor_id = 3, '饿百','不明'))) vendor_name, 
			DATE_FORMAT(a.order_created_at,'%Y-%m-%d %h:%i:%s') order_created_at,
			a.vendor_order_id, IF(b.earning_type = 1, b.earning_price, b.total_shop_money * (100-b.order_pay_percentage/2)/100) /100 earning_price, 
			a.shop_price /100 shop_price, a.count, IF(b.earning_type = 1, a.earning_price, 0) /100 earning_price_sku, a.sku_name, d.upc,
			e.name store_name, f.name category_name_snd, g.name category_name_fst, IF(h.id IS NULL, 0, 1) is_afs, h.count afs_count
	     FROM order_sku a
	LEFT JOIN goods_order b ON a.vendor_order_id = b.vendor_order_id
	LEFT JOIN sku c ON c.id = a.sku_id 
	LEFT JOIN sku_name d ON d.id = c.name_id
	LEFT JOIN store e ON IF(b.jx_store_id = 0, b.store_id, b.jx_store_id) = e.id
	LEFT JOIN sku_category f ON f.id = d.category_id
	LEFT JOIN sku_category g ON g.id = f.parent_id
	LEFT JOIN order_sku_financial h ON h.vendor_order_id = a.vendor_order_id AND h.sku_id = a.sku_id AND is_afs_order = ?
		WHERE a.vendor_order_id IN (` + dao.GenQuestionMarks(len(vendorOrderIDs)) + `)
     ORDER BY store_name, order_created_at DESC
	`
	sqlParams := []interface{}{model.YES, vendorOrderIDs}
	err = dao.GetRows(db, &results, sql, sqlParams)
	if err != nil {
		return "", err
	}
	var sheetList []*excel.Obj2ExcelSheetConfig
	excelConf := &excel.Obj2ExcelSheetConfig{
		Title:       "sheet1",
		Data:        results,
		CaptionList: excelTitle,
	}
	sheetList = append(sheetList, excelConf)
	downloadURL, _, err = jxutils.UploadExeclAndPushMsg(sheetList, "订单导出")
	baseapi.SugarLogger.Debug("WriteToExcel: dataSuccess downloadURL: [%v]", downloadURL)
	return downloadURL, err
}

// UpdateTiktokShopTotalMoney 定时任务更新抖店订单的平台结算
func UpdateTiktokShopTotalMoney(storeId int64, startTime, endTime time.Time) error {
	var (
		db             = dao.GetDB()
		goodsOrders    = make([]*model.GoodsOrder, 0, 0)
		nextStartIndex = ""
		errList        = make([]string, 0, 0)
	)

	sql := `SELECT g.* FROM goods_order g WHERE 1=1 `
	param := []interface{}{}
	if storeId != 0 {
		sql += `AND g.store_id = ?`
		param = append(param, storeId)
	}
	if !utils.IsTimeZero(startTime) {
		sql += ` AND g.order_created_at >= ? `
		param = append(param, startTime)
	}
	if !utils.IsTimeZero(endTime) {
		sql += ` AND g.order_created_at <= ? `
		param = append(param, endTime)
	}
	if utils.IsTimeZero(startTime) && utils.IsTimeZero(endTime) {
		orderCreateTime := time.Now().AddDate(0, 0, -50)
		sql += ` AND g.order_created_at >= ? `
		param = append(param, orderCreateTime)
	}

	sql += ` AND g.status = ? AND g.vendor_id = ? AND total_shop_money = ?  ORDER BY g.order_created_at desc`
	param = append(param, []interface{}{model.OrderStatusFinished, model.VendorIDDD, model.NO}...)
	if err := dao.GetRows(db, &goodsOrders, sql, param...); err != nil {
		return err
	}

	for _, v := range goodsOrders {
		orderDetail, err := tiktok_store.GetOrderDetail(v.VendorOrgCode, v.VendorOrderID)
		if err != nil {
			errList = append(errList, fmt.Sprintf("详情错误orderID[%s],%v", v.VendorOrderID, err))
			continue
		}

		childrenOrderList := make([]string, 0, 0)
		for _, skuList := range orderDetail.SkuOrderList {
			childrenOrderList = append(childrenOrderList, skuList.OrderId)
		}

		totalShopMoney, next, err := tiktok_store.GetOrderTotalShopMoney(v.VendorOrgCode, strings.Join(childrenOrderList, ","), nextStartIndex)
		if err != nil {
			errList = append(errList, fmt.Sprintf("结算错误orderID[%s],%v", v.VendorOrderID, err))
			continue
		}
		nextStartIndex = next
		v.TotalShopMoney = totalShopMoney
		if v.EarningType == model.EarningTypePoints {
			waybill, _ := partner.CurOrderManager.LoadWaybill(v.VendorWaybillID, v.WaybillVendorID)
			// store, _ := c.LoadStoreDetail(jxutils.GetSaleStoreIDFromOrder(order), order.VendorID)
			if waybill == nil {
				if (v.NewEarningPrice == 0 || v.NewEarningPrice != v.TotalShopMoney*int64(100-v.OrderPayPercentage/2)/int64(100)) && v.OrderPayPercentage <= 50 {
					v.NewEarningPrice = v.TotalShopMoney * int64(100-v.OrderPayPercentage/2) / int64(100)
				}
			} else {
				if (v.NewEarningPrice == 0 || v.NewEarningPrice != (v.TotalShopMoney-waybill.DesiredFee)*int64(100-v.OrderPayPercentage/2)/int64(100)) && v.OrderPayPercentage <= 50 {
					v.NewEarningPrice = v.TotalShopMoney*int64(100-v.OrderPayPercentage/2)/int64(100) - waybill.DesiredFee
				}
			}
		}
		if _, err = dao.UpdateEntity(db, v, "TotalShopMoney", "NewEarningPrice"); err != nil {
			errList = append(errList, fmt.Sprintf("修改本地结算错误orderID[%s],%v", v.VendorOrderID, err))
			continue
		}
	}
	if len(errList) == model.NO {
		return nil
	}
	return fmt.Errorf(strings.Join(errList, "|"))
}

// UpdateTaoSettleInfo 定时任务更新淘鲜达结算信息
func UpdateTaoSettleInfo() {
	db := dao.GetDB()
	var count = 0

	timeStart := time.Now().Add(-24 * 4 * time.Hour)
	startTime := time.Date(timeStart.Year(), timeStart.Month(), timeStart.Day(), 0, 0, 0, 0, timeStart.Location())

	timeEnd := time.Now().Add(-24 * 1 * time.Hour)
	endTime := time.Date(timeEnd.Year(), timeEnd.Month(), timeEnd.Day()-1, 23, 59, 59, 0, timeStart.Location())

	storeMaps, err := dao.GetTaoOrderVendor(db, startTime, endTime)
	if err != nil {
		return
	}

	for k, v := range storeMaps {
		globals.SugarLogger.Debugf("门店id : %s", k)
		count++
		settleInfo, err := tao.GetOrderTotalShopMoney(v, k, startTime, endTime)
		if err != nil {
			globals.SugarLogger.Errorf("获取淘鲜达结算信息异常 := %v", err)
			continue
		}
		if len(settleInfo) == model.NO {
			continue
		}

		for orderId2, settle := range settleInfo {
			goodsOrder, err := partner.CurOrderManager.LoadOrder2(orderId2, model.VendorIDTaoVegetable)
			if err != nil || goodsOrder == nil {
				globals.SugarLogger.Debugf("门店[%d:%s],订单查询异常[%s:%v]", v, k, orderId2, err)
				continue
			}

			goodsOrder.TotalShopMoney = utils.Float64TwoInt64(utils.Str2Float64(settle) * 100)
			if goodsOrder.EarningType == model.EarningTypePoints {
				waybill, _ := partner.CurOrderManager.LoadWaybill(goodsOrder.VendorWaybillID, goodsOrder.WaybillVendorID)
				if waybill == nil {
					if (goodsOrder.NewEarningPrice == 0 || goodsOrder.NewEarningPrice != goodsOrder.TotalShopMoney*int64(100-goodsOrder.OrderPayPercentage/2)/int64(100)) && goodsOrder.OrderPayPercentage <= 50 {
						goodsOrder.NewEarningPrice = goodsOrder.TotalShopMoney * int64(100-goodsOrder.OrderPayPercentage/2) / int64(100)
					}
				} else {
					if (goodsOrder.NewEarningPrice == 0 || goodsOrder.NewEarningPrice != (goodsOrder.TotalShopMoney-waybill.DesiredFee)*int64(100-goodsOrder.OrderPayPercentage/2)/int64(100)) && goodsOrder.OrderPayPercentage <= 50 {
						goodsOrder.NewEarningPrice = goodsOrder.TotalShopMoney*int64(100-goodsOrder.OrderPayPercentage/2)/int64(100) - waybill.DesiredFee
					}
				}
			}
			globals.SugarLogger.Debugf("更新本地订单结算信息 := %s,%d", goodsOrder.VendorOrderID, goodsOrder.TotalShopMoney)
			if _, err := dao.UpdateEntity(db, goodsOrder, "TotalShopMoney", "NewEarningPrice"); err != nil {
				globals.SugarLogger.Errorf("更新本地订单结算信息错误 : %s", err)
				continue
			}
		}
	}
}
