package models

import (
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	orm "go-admin/common/global"
	"go-admin/logger"
	"go-admin/tools"
	"gorm.io/gorm"
	"math/rand"
	"time"
)

const (
	ErpInventoryAllotOrderUnAudit     = 1 // 库存调拨-待审核
	ErpInventoryAllotOrderWaitSend    = 2 // 库存调拨-待发货
	ErpInventoryAllotOrderWaitReceive = 3 // 库存调拨-待收货
	ErpInventoryAllotOrderFinished    = 4 // 库存调拨-已完成
)

// ErpInventoryAllotOrder 库存调拨订单表
type ErpInventoryAllotOrder struct {
	Model
	SerialNumber     string                       `json:"serial_number" gorm:"index"`    // 单据编号
	DeliverStoreId   uint32                       `json:"deliver_store_id" gorm:"index"` // 调出门店id
	DeliverStoreName string                       `json:"deliver_store_name"`            // 调出门店名称
	ReceiveStoreId   uint32                       `json:"receive_store_id" gorm:"index"` // 调入门店id
	ReceiveStoreName string                       `json:"receive_store_name"`            // 调入门店名称
	HandlerId        uint32                       `json:"handler_id" gorm:"index"`       // 经手人id
	HandlerName      string                       `json:"handler_name"`                  // 经手人名称
	MakerTime        *time.Time                   `json:"maker_time"`                    // 制单时间
	MakerId          uint32                       `json:"maker_id" gorm:"index"`         // 制单人id
	MakerName        string                       `json:"maker_name"`                    // 制单人名称
	AuditTime        *time.Time                   `json:"audit_time"`                    // 审核时间
	AuditorId        uint32                       `json:"auditor_id" gorm:"index"`       // 审核人id
	AuditorName      string                       `json:"auditor_name"`                  // 审核人名称
	DeliverTime      *time.Time                   `json:"deliver_time"`                  // 发货时间
	ReceiveTime      *time.Time                   `json:"receive_time"`                  // 收货时间/调入时间
	LogisticsNumber  string                       `json:"logistics_number"`              // 物流单号
	State            uint32                       `json:"state"`                         // 1-待审核 2-待发货 3-待收货 4-已完成
	TotalCount       uint32                       `json:"total_count"`                   // 商品总数量
	Remark           string                       `json:"remark"`                        // 备注
	Commodities      []ErpInventoryAllotCommodity `json:"commodities" gorm:"-"`          // 库存调拨商品信息
}

// ErpInventoryAllotCommodity 库存调拨商品信息表
type ErpInventoryAllotCommodity struct {
	Model
	AllotOrderId  uint32  `json:"allot_order_id" gorm:"index"` // 库存调拨订单表id
	CommodityId   uint32  `json:"commodity_id" gorm:"index"`   // 商品id
	CommodityName string  `json:"commodity_name"`              // 商品名称
	CategoryId    uint32  `json:"category_id" gorm:"index"`    // 分类id
	CategoryName  string  `json:"category_name"`               // 分类名称
	IMEIType      uint32  `json:"imei_type"`                   // 1-无串码 2-串码
	IMEI          string  `json:"imei"`                        // 商品串码
	Count         uint32  `json:"count"`                       // 数量
	Amount        float64 `json:"amount"`                      // 金额（采购价）
	Remark        string  `json:"remark"`                      // 备注
	StockCount    uint32  `json:"stock_count" gorm:"-"`        // 库存数量
}

// InventoryAllotAddReq 新增库存调拨入参
type InventoryAllotAddReq struct {
	DeliverStoreId   uint32                       `json:"deliver_store_id" binding:"required"`   // 调出门店id
	DeliverStoreName string                       `json:"deliver_store_name" binding:"required"` // 调出门店名称
	ReceiveStoreId   uint32                       `json:"receive_store_id" binding:"required"`   // 调入门店id
	ReceiveStoreName string                       `json:"receive_store_name" binding:"required"` // 调入门店名称
	HandlerId        uint32                       `json:"handler_id" binding:"required"`         // 经手人id
	HandlerName      string                       `json:"handler_name" binding:"required"`       // 经手人名称
	Commodities      []ErpInventoryAllotCommodity `json:"commodities"  binding:"required"`       // 库存调拨商品信息
}

// InventoryAllotEditReq 编辑库存调拨入参
type InventoryAllotEditReq struct {
	SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
	InventoryAllotAddReq
}

// InventoryAllotAuditReq 审核入参
type InventoryAllotAuditReq struct {
	SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
	State        int    `json:"state"  binding:"required"`        // 审核操作: 1-审核 2-取消审核
}

// InventoryAllotDeleteReq 删除入参
type InventoryAllotDeleteReq struct {
	SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
}

// InventoryAllotListReq 查询库存调拨列表入参
type InventoryAllotListReq struct {
	SerialNumber   string `json:"serial_number"`    // 单据编号
	DeliverStoreId uint32 `json:"deliver_store_id"` // 调出门店id
	ReceiveStoreId uint32 `json:"receive_store_id"` // 调入门店id
	HandlerId      uint32 `json:"handler_id"`       // 经手人id
	State          int    `json:"state"`            // 1-待审核 2-待发货 3-待收货 4-已完成
	AuditTimeStart string `json:"audit_time_start"` // 审核开始时间
	AuditTimeEnd   string `json:"audit_time_end"`   // 审核结束时间
	PageIndex      int    `json:"pageIndex"`        // 页码
	PageSize       int    `json:"pageSize"`         // 页面条数
}

// InventoryAllotListResp 查询库存调拨列表出参
type InventoryAllotListResp struct {
	List      []ErpInventoryAllotOrder `json:"list"`
	Total     int                      `json:"total"`     // 总条数
	PageIndex int                      `json:"pageIndex"` // 页码
	PageSize  int                      `json:"pageSize"`  // 页面条数
}

// InventoryAllotDetailReq  查询库存调拨详情入参
type InventoryAllotDetailReq struct {
	SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
}

// InventoryAllotDeliverReq 调拨发货入参
type InventoryAllotDeliverReq struct {
	SerialNumber    string `json:"serial_number" binding:"required"` // 单据编号
	LogisticsNumber string `json:"logistics_number"`                 // 物流单号
	Remark          string `json:"remark"`                           // 备注
}

// InventoryAllotReceiveReq 调拨收货入参
type InventoryAllotReceiveReq struct {
	SerialNumber string `json:"serial_number" binding:"required"` // 单据编号
}

// 检查新增库存调拨信息
func checkAllotInventoryParam(req *InventoryAllotAddReq, editFlag bool) error {
	if len(req.Commodities) == 0 {
		return errors.New("商品信息为空")
	}

	noIMEICommodityMap := make(map[uint32]bool, 0)
	for _, item := range req.Commodities {
		// 校验数量
		if item.Count <= 0 {
			return fmt.Errorf("商品[%s]数量[%d]错误，需大于0", item.CommodityName, item.Count)
		} else {
			if item.Count != 1 && item.IMEIType != NoIMEICommodity { // 串码商品数量不为1，则报错
				return fmt.Errorf("串码商品[%s]数量[%d]错误，需为1", item.CommodityName, item.Count)
			}
		}

		//// 校验编辑订单时是否有传商品ID
		//if editFlag {
		//	if item.ID == 0 {
		//		return fmt.Errorf("商品[%s]ID为空", item.CommodityName)
		//	}
		//}

		// 校验串码类型
		switch item.IMEIType {
		case 1, 2, 3:
			// 串码商品校验串码是否为空
			if item.IMEIType != NoIMEICommodity && item.IMEI == "" {
				return fmt.Errorf("[%s]是串码商品，其串码不能为空", item.CommodityName)
			}
		default:
			return fmt.Errorf("商品[%s]串码类型[%d]错误", item.CommodityName, item.IMEIType)
		}

		// 校验非串码商品是否重复
		if item.IMEIType == NoIMEICommodity {
			_, ok := noIMEICommodityMap[item.CommodityId]
			if !ok {
				noIMEICommodityMap[item.CommodityId] = true
			} else {
				return fmt.Errorf("商品[%s]重复，相同的非串码商品只能有1条数据", item.CommodityName)
			}
		}

		// 检查调出门店是否有对应商品，调拨数量是否 < 商品库存数量
		var stockCount int64
		var err error
		if item.IMEIType == NoIMEICommodity { // 非串码商品
			err = orm.Eloquent.Table("erp_stock_commodity").
				Where("erp_commodity_id = ? AND store_id = ? AND state = 1", item.CommodityId, req.DeliverStoreId).
				Count(&stockCount).Error
		} else { // 串码商品
			err = orm.Eloquent.Table("erp_stock_commodity").
				Where("erp_commodity_id = ? AND store_id = ? AND state = 1 AND imei = ?", item.CommodityId,
					req.DeliverStoreId, item.IMEI).Count(&stockCount).Error
		}
		if err != nil {
			return errors.New("查询商品库存失败，" + err.Error())
		}
		if stockCount == 0 {
			return fmt.Errorf("商品[%s]库存数量为0", item.CommodityName)
		}
		if stockCount < int64(item.Count) {
			return fmt.Errorf("商品[%s]库存数量[%d]少于调拨数量[%d]", item.CommodityName, stockCount, item.Count)
		}
	}

	return nil
}

// newAllotInventorySn 生成库存调拨订单号
func newAllotInventorySn() string {
	nowTime := time.Now()
	rand.Seed(nowTime.UnixNano())
	max := 1
	for {
		if max > 5 {
			logger.Error("create NewProductInventorySn err")
			return ""
		}
		random := rand.Intn(9000) + 1000
		sn := fmt.Sprintf("%s%d", nowTime.Format("060102"), random)
		exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_inventory_allot_order "+
			"WHERE serial_number='%s'", "db"+sn))
		if err != nil {
			logger.Error("exist sn err")
		}
		if !exist {
			return "db" + sn
		}

		max++
	}
}

// AddInventoryAllot 新增库存调拨
func AddInventoryAllot(req *InventoryAllotAddReq, sysUser *SysUser) (*ErpInventoryAllotOrder, error) {
	// 检查库存调拨信息
	if err := checkAllotInventoryParam(req, false); err != nil {
		return nil, err
	}

	var err error
	nowTime := time.Now()

	// 计算库存调拨的总数量
	var nTotalCount uint32
	for i, _ := range req.Commodities {
		nTotalCount += req.Commodities[i].Count // 数量
	}

	// 组合库存调拨订单数据
	inventoryAllotOrder := &ErpInventoryAllotOrder{
		SerialNumber:     newAllotInventorySn(),
		DeliverStoreId:   req.DeliverStoreId,
		DeliverStoreName: req.DeliverStoreName,
		ReceiveStoreId:   req.ReceiveStoreId,
		ReceiveStoreName: req.ReceiveStoreName,
		HandlerId:        req.HandlerId,
		HandlerName:      req.HandlerName,
		MakerTime:        &nowTime,
		MakerId:          uint32(sysUser.UserId),
		MakerName:        sysUser.NickName,
		State:            ErpInventoryAllotOrderUnAudit,
		TotalCount:       nTotalCount,
	}

	// 创建库存调拨订单
	begin := orm.Eloquent.Begin()
	err = begin.Create(inventoryAllotOrder).Error
	if err != nil {
		begin.Rollback()
		logger.Error("create allot order err:", logger.Field("err", err))
		return nil, err
	}

	// 创建库存调拨商品信息，添加库存调拨订单id
	for i, _ := range req.Commodities {
		req.Commodities[i].AllotOrderId = inventoryAllotOrder.ID

		// 查询商品信息
		commodityInfo, err := GetCommodity(req.Commodities[i].CommodityId)
		if err != nil {
			logger.Error("SetCategory err:", logger.Field("err", err))
			return nil, err
		}

		req.Commodities[i].CategoryId = commodityInfo.ErpCategoryId
		req.Commodities[i].CategoryName = commodityInfo.ErpCategoryName

		// 如果是非串码，且数量大于1，则进行拆分
		if req.Commodities[i].IMEIType == 1 && req.Commodities[i].Count > 1 {
			nCount := req.Commodities[i].Count
			for j := 0; j < int(nCount); j++ {
				req.Commodities[i].ID = 0
				req.Commodities[i].Count = 1
				err = begin.Create(&req.Commodities[i]).Error
				if err != nil {
					begin.Rollback()
					logger.Error("create allot commodity err:", logger.Field("err", err))
					return nil, err
				}
			}
		} else { // 普通串码商品则只有1条数据
			err = begin.Create(&req.Commodities[i]).Error
			if err != nil {
				begin.Rollback()
				logger.Error("create allot commodity err:", logger.Field("err", err))
				return nil, err
			}
		}
	}

	err = begin.Commit().Error
	if err != nil {
		begin.Rollback()
		logger.Error("commit allot commodity err:", logger.Field("err", err))
		return nil, err
	}

	return inventoryAllotOrder, nil
}

// EditAllotInventory  编辑库存调拨
func EditAllotInventory(req *InventoryAllotEditReq) (*ErpInventoryAllotOrder, error) {
	// 查询订单信息
	var inventoryAllotOrder ErpInventoryAllotOrder
	err := orm.Eloquent.Table("erp_inventory_allot_order").Where("serial_number = ?", req.SerialNumber).
		Find(&inventoryAllotOrder).Error
	if err != nil {
		logger.Error("allot order err:", logger.Field("err", err))
		return nil, err
	}

	// 未找到订单
	if inventoryAllotOrder.ID == 0 {
		return nil, fmt.Errorf("未找到该订单，请检查单据编号[%s]", req.SerialNumber)
	}

	if inventoryAllotOrder.State != ErpInventoryAllotOrderUnAudit { // 只有待审核的订单才能编辑
		return nil, errors.New("订单不是待审核状态")
	}

	// 检查库存调拨信息
	if err = checkAllotInventoryParam(&req.InventoryAllotAddReq, true); err != nil {
		return nil, err
	}

	// 计算库存调拨的总数量
	var nTotalCount uint32
	for i, _ := range req.Commodities {
		nTotalCount += req.Commodities[i].Count // 数量
	}

	begin := orm.Eloquent.Begin()
	// 1-更新库存调拨信息
	inventoryAllotOrder.DeliverStoreId = req.DeliverStoreId
	inventoryAllotOrder.DeliverStoreName = req.DeliverStoreName
	inventoryAllotOrder.ReceiveStoreId = req.ReceiveStoreId
	inventoryAllotOrder.ReceiveStoreName = req.ReceiveStoreName
	inventoryAllotOrder.HandlerId = req.HandlerId
	inventoryAllotOrder.HandlerName = req.HandlerName
	inventoryAllotOrder.TotalCount = nTotalCount

	err = begin.Model(&ErpInventoryAllotOrder{}).Where("id = ?", inventoryAllotOrder.ID).
		Omit("created_at").Save(inventoryAllotOrder).Error
	if err != nil {
		begin.Rollback()
		logger.Error("update allot order err:", logger.Field("err", err))
		return nil, err
	}

	// 2-更新库存调拨商品表
	err = updateAllotCommodityData(begin, inventoryAllotOrder.ID, req)
	if err != nil {
		begin.Rollback()
		logger.Error("update erp_inventory_allot_commodity err:", logger.Field("err", err))
		return nil, err
	}

	err = begin.Commit().Error
	if err != nil {
		begin.Rollback()
		logger.Error("commit err:", logger.Field("err", err))
		return nil, err
	}

	return &inventoryAllotOrder, nil
}

// updateAllotCommodityData 更新库存调拨商品信息
func updateAllotCommodityData(gdb *gorm.DB, orderId uint32, req *InventoryAllotEditReq) error {
	// 查询现有的零售订单信息
	var commodities []ErpInventoryAllotCommodity
	err := orm.Eloquent.Table("erp_inventory_allot_commodity").Where("allot_order_id = ?", orderId).Find(&commodities).Error
	if err != nil {
		logger.Error("query erp_inventory_allot_commodity err:", logger.Field("err", err))
		return err
	}

	// 删除所有的商品信息
	if len(commodities) != 0 {
		err = gdb.Delete(&commodities).Error
		if err != nil {
			logger.Error("更新商品订单信息-删除 error")
			return errors.New("操作失败:" + err.Error())
		}
	}

	// 新建所有的商品信息
	for i, _ := range req.Commodities {
		req.Commodities[i].AllotOrderId = orderId

		// 查询商品信息
		commodityInfo, err := GetCommodity(req.Commodities[i].CommodityId)
		if err != nil {
			logger.Error("SetCategory err:", logger.Field("err", err))
			return err
		}

		req.Commodities[i].CategoryId = commodityInfo.ErpCategoryId
		req.Commodities[i].CategoryName = commodityInfo.ErpCategoryName
		req.Commodities[i].CommodityName = commodityInfo.Name

		// 如果是非串码，且数量大于1，则进行拆分
		if req.Commodities[i].IMEIType == 1 && req.Commodities[i].Count > 1 {
			nCount := req.Commodities[i].Count
			for j := 0; j < int(nCount); j++ {
				req.Commodities[i].ID = 0
				req.Commodities[i].Count = 1
				err = gdb.Create(&req.Commodities[i]).Error
				if err != nil {
					logger.Error("create allot commodity err:", logger.Field("err", err))
					return err
				}
			}
		} else { // 普通串码商品则只有1条数据
			err = gdb.Create(&req.Commodities[i]).Error
			if err != nil {
				logger.Error("create allot commodity err:", logger.Field("err", err))
				return err
			}
		}
	}

	return nil
}

// List 查询采购订单列表
func (m *InventoryAllotListReq) List(c *gin.Context) (*InventoryAllotListResp, error) {
	resp := &InventoryAllotListResp{
		PageIndex: m.PageIndex,
		PageSize:  m.PageSize,
	}
	page := m.PageIndex - 1
	if page < 0 {
		page = 0
	}
	if m.PageSize == 0 {
		m.PageSize = 10
	}
	qs := orm.Eloquent.Table("erp_inventory_allot_order")

	// 非管理员才判断所属门店
	if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
		sysUser, err := GetSysUserByCtx(c)
		if err != nil {
			return nil, err
		}

		// 返回sysUser未过期的门店id列表
		storeList := GetValidStoreIDs(sysUser.StoreData)
		if m.DeliverStoreId != 0 || m.ReceiveStoreId != 0 {
			if m.DeliverStoreId != 0 {
				if !Contains(storeList, m.DeliverStoreId) {
					return nil, errors.New("您没有该门店权限")
				}
			}

			if m.ReceiveStoreId != 0 {
				if !Contains(storeList, m.ReceiveStoreId) {
					return nil, errors.New("您没有该门店权限")
				}
			}
		} else {
			if len(storeList) > 0 {
				if len(storeList) == 1 {
					qs = qs.Where("deliver_store_id = ? or receive_store_id=?", storeList[0], storeList[0])
				} else {
					qs = qs.Where("deliver_store_id IN (?) or receive_store_id IN (?)", storeList, storeList)
				}
			} else {
				return nil, errors.New("用户未绑定门店")
			}
		}
	}

	if m.SerialNumber != "" {
		qs = qs.Where("serial_number=?", m.SerialNumber)
	} else {
		if m.DeliverStoreId != 0 {
			qs = qs.Where("deliver_store_id=?", m.DeliverStoreId)
		}
		if m.ReceiveStoreId != 0 {
			qs = qs.Where("receive_store_id=?", m.ReceiveStoreId)
		}
		if m.HandlerId != 0 {
			qs = qs.Where("handler_id=?", m.HandlerId)
		}
		if m.State != 0 {
			qs = qs.Where("state=?", m.State)
		}
		if m.AuditTimeStart != "" {
			parse, err := time.Parse(QueryTimeFormat, m.AuditTimeStart)
			if err != nil {
				logger.Errorf("AllotInventoryList err:", err)
				return nil, err
			}
			qs = qs.Where("audit_time > ?", parse)
		}
		if m.AuditTimeEnd != "" {
			parse, err := time.Parse(QueryTimeFormat, m.AuditTimeEnd)
			if err != nil {
				logger.Errorf("AllotInventoryList err:", err)
				return nil, err
			}
			qs = qs.Where("audit_time < ?", parse)
		}
	}

	var count int64
	err := qs.Count(&count).Error
	if err != nil {
		logger.Error("count err:", logger.Field("err", err))
		return resp, err
	}
	resp.Total = int(count)
	var orders []ErpInventoryAllotOrder
	err = qs.Order("id DESC").Offset(page * m.PageSize).Limit(m.PageSize).Find(&orders).Error
	if err != nil && err != RecordNotFound {
		logger.Error("allot list err:", logger.Field("err", err))
		return resp, err
	}

	// 校验时间，如果为01-01-01 08:05，则赋值为空
	for i, v := range orders {
		if v.MakerTime != nil && v.MakerTime.IsZero() {
			orders[i].MakerTime = nil
		}

		if v.AuditTime != nil && v.AuditTime.IsZero() {
			orders[i].AuditTime = nil
		}
	}

	resp.List = orders
	return resp, nil
}

// AuditAllotInventory 审核库存调拨入库 state：1-审核，2-取消审核
func AuditAllotInventory(req *InventoryAllotAuditReq, c *gin.Context) error {
	// 查询订单信息
	var inventoryAllotOrder ErpInventoryAllotOrder
	err := orm.Eloquent.Table("erp_inventory_allot_order").Where("serial_number = ?", req.SerialNumber).
		Find(&inventoryAllotOrder).Error
	if err != nil {
		logger.Error("order err:", logger.Field("err", err))
		return err
	}

	sysUser, err := GetSysUserByCtx(c)
	if err != nil {
		logger.Error("sys user err:", logger.Field("err", err))
		return err
	}

	// 校验入参门店是否包含在用户所有门店中，是否过期
	if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
		if !CheckUserStore(inventoryAllotOrder.DeliverStoreId, sysUser) {
			return errors.New("操作失败：您没有该门店权限")
		}
	}

	if inventoryAllotOrder.ID == 0 {
		return errors.New("未查询到订单信息")
	}

	begin := orm.Eloquent.Begin()

	// 判断入参state：1-审核，2-取消审核
	orderState := 0
	switch req.State {
	case 1: // 1-审核：待审核状态可以审核
		if inventoryAllotOrder.State != ErpInventoryAllotOrderUnAudit { // 订单不是未审核状态
			return errors.New("订单已审核，无需再次审核")
		}
		orderState = ErpInventoryAllotOrderWaitSend
		// 更新商品的库存状态
		err = allotAuditAndUpdateStock(begin, inventoryAllotOrder)
		if err != nil {
			begin.Rollback()
			logger.Error("ProductAuditAndUpdateStock err:", logger.Field("err", err))
			return fmt.Errorf("审核失败，%s", err.Error())
		}
	case 2: // 2-取消审核
		orderState = ErpInventoryAllotOrderUnAudit
		if inventoryAllotOrder.State == ErpInventoryAllotOrderUnAudit { // 订单未审核
			return errors.New("订单是未审核状态，无需取消审核")
		}
		if IsMonthEndClosed(*inventoryAllotOrder.AuditTime) {
			return errors.New("财务已月结")
		}
		// 更新商品的库存状态
		err = cancelAllotAuditAndUpdateStock(begin, inventoryAllotOrder)
		if err != nil {
			begin.Rollback()
			return fmt.Errorf("取消审核失败，%s", err.Error())
		}
	default:
		logger.Error("order err, req.State is:", logger.Field("req.State", req.State))
		return errors.New("参数有误")
	}

	// 更新库存调拨订单表
	err = begin.Table("erp_inventory_allot_order").Where("id = ?", inventoryAllotOrder.ID).
		Updates(map[string]interface{}{
			"state":        orderState,
			"auditor_id":   sysUser.UserId,
			"audit_time":   time.Now(),
			"auditor_name": sysUser.NickName,
		}).Error
	if err != nil {
		begin.Rollback()
		logger.Error("update erp_inventory_allot_order err:", logger.Field("err", err))
		return err
	}

	err = begin.Commit().Error
	if err != nil {
		begin.Rollback()
		logger.Errorf("commit err:", err)
		return err
	}

	return nil
}

// allotAuditAndUpdateStock 库存调拨审核后更新库存信息
func allotAuditAndUpdateStock(gdb *gorm.DB, allotOrder ErpInventoryAllotOrder) error {
	// 查询库存调拨商品信息
	var commodities []ErpInventoryAllotCommodity
	err := orm.Eloquent.Table("erp_inventory_allot_commodity").Where("allot_order_id = ?",
		allotOrder.ID).Find(&commodities).Error
	if err != nil {
		logger.Error("query erp_inventory_allot_commodity err:", logger.Field("err", err))
		return err
	}

	if len(commodities) == 0 {
		return errors.New("未查询到商品信息")
	}

	// 遍历库存调拨商品信息，将商品id相同的非串码商品进行合并，数量累加即可
	trimCommodities := MergeCommodities(commodities)

	// 遍历库存调拨商品信息
	for _, v := range trimCommodities {
		var stockCommodity []ErpStockCommodity
		err = orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? AND store_id = ? "+
			"AND state = ? AND imei = ?", v.CommodityId, allotOrder.DeliverStoreId, InStock, v.IMEI).
			Order("first_stock_time ASC").Find(&stockCommodity).Error
		if err != nil {
			return fmt.Errorf("审核失败，查询商品库存失败：[%s]", err.Error())
		}

		if len(stockCommodity) == 0 {
			return fmt.Errorf("审核失败，未找到商品库存信息")
		}

		if v.Count > uint32(len(stockCommodity)) {
			return fmt.Errorf("审核失败，商品[%s]库存数量[%d]少于调拨数量[%d]", v.CommodityName,
				len(stockCommodity), v.Count)
		}

		// 更新库存商品表商品状态为：调拨中；调拨中归属门店不更新，只有完成调拨后才更新到调入门店
		var nAmount float64
		for i := 0; i < int(v.Count); i++ {
			//stockCommodity[i].StoreId = allotOrder.ReceiveStoreId
			//stockCommodity[i].StoreName = allotOrder.ReceiveStoreName
			stockCommodity[i].State = InAllot
			if err := gdb.Model(&ErpStockCommodity{}).Where("id = ?", stockCommodity[i].ID).
				Updates(stockCommodity[i]).Error; err != nil {
				return fmt.Errorf("审核失败，更新商品库存失败：%s", err.Error())
			}
			nAmount += stockCommodity[i].WholesalePrice
		}
		if v.Count != 0 {
			nAmount = nAmount / float64(v.Count) // todo 目前只能计算平均采购价
		}

		// 更新库存调拨商品信息表的调拨金额
		err = gdb.Table("erp_inventory_allot_commodity").Where("allot_order_id = ? and commodity_id = ? and "+
			"imei = ?", v.AllotOrderId, v.CommodityId, v.IMEI).
			Updates(map[string]interface{}{
				"amount": nAmount,
			}).Error
		if err != nil {
			logger.Errorf("update erp_inventory_allot_commodity amount err:", err)
			return err
		}

		// 更新库存商品数量
		err = gdb.Exec(fmt.Sprintf(
			"UPDATE erp_stock SET count=count-%d WHERE  store_id=%d AND erp_commodity_id=%d",
			v.Count, allotOrder.DeliverStoreId, v.CommodityId)).Error
		if err != nil {
			logger.Errorf("update stock err:", err)
			return err
		}

		// 更新调出门店的库存调拨数量
		err = gdb.Exec(fmt.Sprintf(
			"UPDATE erp_stock SET dispatch_count = dispatch_count+%d WHERE store_id=%d AND erp_commodity_id=%d",
			v.Count, allotOrder.DeliverStoreId, v.CommodityId)).Error
		if err != nil {
			logger.Errorf("update stock err:", err)
			return err
		}

		//// 更新调入门店的库存调拨数量
		//exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_stock WHERE store_id=%d AND erp_commodity_id=%d",
		//	allotOrder.ReceiveStoreId, v.CommodityId))
		//if err != nil {
		//	logger.Errorf("exist err:", err)
		//	return err
		//}
		//if exist {
		//	err = gdb.Exec(fmt.Sprintf(
		//		"UPDATE erp_stock SET dispatch_count = dispatch_count+%d WHERE store_id=%d AND erp_commodity_id=%d",
		//		v.Count, allotOrder.ReceiveStoreId, v.CommodityId)).Error
		//	if err != nil {
		//		logger.Errorf("update stock err:", err)
		//		return err
		//	}
		//} else {
		//	stock := &ErpStock{
		//		StoreId:               allotOrder.ReceiveStoreId,
		//		StoreName:             allotOrder.ReceiveStoreName,
		//		ErpCommodityId:        v.CommodityId,
		//		ErpCommodityName:      v.CommodityName,
		//		ErpCategoryId:         stockCommodity[0].ErpCategoryId,
		//		ErpCategoryName:       stockCommodity[0].ErpCategoryName,
		//		CommoditySerialNumber: stockCommodity[0].CommoditySerialNumber,
		//		IMEIType:              v.IMEIType,
		//		RetailPrice:           stockCommodity[0].RetailPrice,
		//		MinRetailPrice:        stockCommodity[0].MinRetailPrice,
		//		Count:                 0,
		//		DispatchCount:         v.Count,
		//	}
		//	err = gdb.Create(stock).Error
		//	if err != nil {
		//		logger.Errorf("create stock err:", err)
		//		return err
		//	}
		//}
	}

	return nil
}

// MergeCommodities 遍历库存调拨商品信息，将商品id相同的非串码商品进行合并，数量累加即可
func MergeCommodities(commodities []ErpInventoryAllotCommodity) []ErpInventoryAllotCommodity {
	// 用于存储合并后的商品信息
	mergedCommodities := make([]ErpInventoryAllotCommodity, 0)
	// 用于记录无串码商品的合并信息
	commodityMap := make(map[uint32]*ErpInventoryAllotCommodity)

	for _, commodity := range commodities {
		// 只处理无串码商品
		if commodity.IMEIType == 1 {
			if existing, found := commodityMap[commodity.CommodityId]; found {
				// 如果相同商品 ID 的无串码商品已存在，则数量累加
				existing.Count += commodity.Count
				commodityMap[commodity.CommodityId] = existing
			} else {
				// 否则，加入到 commodityMap 中
				newCommodity := commodity
				commodityMap[commodity.CommodityId] = &newCommodity
			}
		} else {
			// 对于有串码的商品，直接加入到合并后的列表中
			mergedCommodities = append(mergedCommodities, commodity)
		}
	}

	// 将合并后的无串码商品加入到合并后的列表中
	for _, commodity := range commodityMap {
		mergedCommodities = append(mergedCommodities, *commodity)
	}

	return mergedCommodities
}

// UpdateStockCounts 根据商品类型（串码或非串码）以及 storeId 更新每个商品的库存数量。
func UpdateStockCounts(commodities []ErpInventoryAllotCommodity, storeId uint32) ([]ErpInventoryAllotCommodity, error) {
	// 创建映射表，分开存储串码商品和非串码商品
	imeiMap := make(map[string]*ErpInventoryAllotCommodity)    // 串码商品
	nonImeiMap := make(map[uint32]*ErpInventoryAllotCommodity) // 非串码商品

	// 将商品按串码和非串码分开
	for i, commodity := range commodities {
		if commodity.IMEIType == 2 {
			imeiMap[commodity.IMEI] = &commodities[i]
		} else if commodity.IMEIType == 1 {
			nonImeiMap[commodity.CommodityId] = &commodities[i]
		}
	}

	// 查询串码商品的库存数量
	if len(imeiMap) > 0 {
		var imeiKeys []string
		for imei := range imeiMap {
			imeiKeys = append(imeiKeys, imei)
		}

		var stockCounts []struct {
			IMEI       string `gorm:"column:imei"`
			StockCount int64  `gorm:"column:stock_count"`
		}
		err := orm.Eloquent.Table("erp_stock_commodity").
			Where("imei IN (?) AND state = ?", imeiKeys, InStock).
			Select("imei, COUNT(*) as stock_count").
			Group("imei").
			Scan(&stockCounts).Error
		if err != nil {
			return nil, err
		}

		for _, stock := range stockCounts {
			if commodity, exists := imeiMap[stock.IMEI]; exists {
				commodity.StockCount = uint32(stock.StockCount)
			}
		}
	}

	// 查询非串码商品的库存数量
	if len(nonImeiMap) > 0 {
		var commodityIDs []uint32
		for id := range nonImeiMap {
			commodityIDs = append(commodityIDs, id)
		}

		var stockCounts []struct {
			ErpCommodityID uint32 `gorm:"column:erp_commodity_id"`
			StockCount     int64  `gorm:"column:stock_count"`
		}
		err := orm.Eloquent.Table("erp_stock_commodity").
			Where("erp_commodity_id IN (?) AND store_id = ? AND state = ?", commodityIDs, storeId, InStock).
			Select("erp_commodity_id, COUNT(*) as stock_count").
			Group("erp_commodity_id").
			Scan(&stockCounts).Error
		if err != nil {
			return nil, err
		}

		for _, stock := range stockCounts {
			if commodity, exists := nonImeiMap[stock.ErpCommodityID]; exists {
				commodity.StockCount = uint32(stock.StockCount)
			}
		}
	}

	return commodities, nil
}

// MergeAllCommodities 遍历库存调拨商品信息，将商品id相同的所有商品进行合并，数量累加即可
func MergeAllCommodities(commodities []ErpInventoryAllotCommodity) []ErpInventoryAllotCommodity {
	// 用于存储合并后的商品信息
	mergedCommodities := make([]ErpInventoryAllotCommodity, 0)
	// 用于记录无串码商品的合并信息
	commodityMap := make(map[uint32]*ErpInventoryAllotCommodity)

	for _, commodity := range commodities {
		if existing, found := commodityMap[commodity.CommodityId]; found {
			// 如果相同商品 ID 的无串码商品已存在，则数量累加
			existing.Count += commodity.Count
			commodityMap[commodity.CommodityId] = existing
		} else {
			// 否则，加入到 commodityMap 中
			newCommodity := commodity
			commodityMap[commodity.CommodityId] = &newCommodity
		}
	}

	// 将合并后的无串码商品加入到合并后的列表中
	for _, commodity := range commodityMap {
		mergedCommodities = append(mergedCommodities, *commodity)
	}

	return mergedCommodities
}

// MergeChangeCommodities 遍历库存变动商品信息，将商品id相同的非串码商品进行合并，数量累加即可
func MergeChangeCommodities(commodities []ErpInventoryChangeCommodity) []ErpInventoryChangeCommodity {
	// 用于存储合并后的商品信息
	mergedCommodities := make([]ErpInventoryChangeCommodity, 0)
	// 用于记录无串码商品的合并信息
	commodityMap := make(map[uint32]*ErpInventoryChangeCommodity)

	for _, commodity := range commodities {
		// 只处理无串码商品
		if commodity.IMEIType == 1 {
			if existing, found := commodityMap[commodity.CommodityId]; found {
				// 如果相同商品 ID 的无串码商品已存在，则数量累加
				existing.Count += commodity.Count
				commodityMap[commodity.CommodityId] = existing
			} else {
				// 否则，加入到 commodityMap 中
				newCommodity := commodity
				commodityMap[commodity.CommodityId] = &newCommodity
			}
		} else {
			// 对于有串码的商品，直接加入到合并后的列表中
			mergedCommodities = append(mergedCommodities, commodity)
		}
	}

	// 将合并后的无串码商品加入到合并后的列表中
	for _, commodity := range commodityMap {
		mergedCommodities = append(mergedCommodities, *commodity)
	}

	return mergedCommodities
}

// cancelAllotAuditAndUpdateStock 库存调拨反审核后更新库存信息
func cancelAllotAuditAndUpdateStock(gdb *gorm.DB, allotOrder ErpInventoryAllotOrder) error {
	// 查询库存调拨商品信息
	var commodities []ErpInventoryAllotCommodity
	if err := orm.Eloquent.Table("erp_inventory_allot_commodity").Where("allot_order_id = ?",
		allotOrder.ID).Find(&commodities).Error; err != nil {
		logger.Error("query erp_inventory_allot_commodity err:", logger.Field("err", err))
		return err
	}
	if len(commodities) == 0 {
		return errors.New("取消审核失败，未查询到库存调拨商品信息")
	}

	// 遍历库存调拨商品信息，将商品id相同的非串码商品进行合并，数量累加即可
	trimCommodities := MergeCommodities(commodities)

	switch allotOrder.State {
	// 2 待发货：状态改为待审核，调拨中库存恢复为在库
	// 3 待收货：状态改为待审核，调拨中库存恢复为在库
	case ErpInventoryAllotOrderWaitSend, ErpInventoryAllotOrderWaitReceive:
		// 遍历库存调拨商品信息
		for _, v := range trimCommodities {
			var stockCommodity []ErpStockCommodity
			err := orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? AND store_id = ? "+
				"AND state = ? AND imei = ?", v.CommodityId, allotOrder.DeliverStoreId, InAllot, v.IMEI).
				Find(&stockCommodity).Error
			if err != nil {
				return fmt.Errorf("查询商品库存失败：[%s]", err.Error())
			}
			if len(stockCommodity) == 0 {
				return fmt.Errorf("未找到商品库存信息")
			}

			// 更新库存商品表商品状态为：在库
			for i := 0; i < int(v.Count); i++ {
				//stockCommodity[i].StoreId = allotOrder.DeliverStoreId
				//stockCommodity[i].StoreName = allotOrder.DeliverStoreName
				stockCommodity[i].State = InStock
				err = gdb.Model(&ErpStockCommodity{}).Where("id = ?", stockCommodity[i].ID).
					Updates(stockCommodity[i]).Error
				if err != nil {
					return fmt.Errorf("更新商品库存失败：%s", err.Error())
				}
			}

			// 更新库存商品数量
			err = gdb.Exec(fmt.Sprintf(
				"UPDATE erp_stock SET count=count+%d WHERE  store_id=%d AND erp_commodity_id=%d",
				v.Count, allotOrder.DeliverStoreId, v.CommodityId)).Error
			if err != nil {
				logger.Errorf("update stock err:", err)
				return fmt.Errorf("更新库存商品数量失败：%s", err.Error())
			}

			// 更新库存商品调拨数量
			err = gdb.Exec(fmt.Sprintf(
				"UPDATE erp_stock SET dispatch_count = dispatch_count-%d WHERE store_id=%d AND erp_commodity_id=%d",
				v.Count, allotOrder.DeliverStoreId, v.CommodityId)).Error
			if err != nil {
				logger.Errorf("update stock err:", err)
				return err
			}
		}
	case ErpInventoryAllotOrderFinished: // 已完成：状态改为待审核，调入门店对应商品的库存更新到调出门店，如果库存不足则报错
		// 遍历库存调拨商品信息
		for _, v := range trimCommodities {
			var stockCommodity []ErpStockCommodity
			err := orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? AND store_id = ? "+
				"AND state = ? AND imei = ?", v.CommodityId, allotOrder.ReceiveStoreId, InStock, v.IMEI).
				Find(&stockCommodity).Error
			if err != nil {
				return fmt.Errorf("查询商品库存失败：[%s]", err.Error())
			}
			if len(stockCommodity) == 0 {
				return fmt.Errorf("未找到商品库存信息")
			}

			if v.Count > uint32(len(stockCommodity)) {
				return fmt.Errorf("商品[%s]库存数量[%d]不足", v.CommodityName, len(stockCommodity))
			}

			// 更新库存商品表商品状态为：在库
			for i := 0; i < int(v.Count); i++ {
				stockCommodity[i].StoreId = allotOrder.DeliverStoreId
				stockCommodity[i].StoreName = allotOrder.DeliverStoreName
				stockCommodity[i].State = InStock
				err = gdb.Model(&ErpStockCommodity{}).Where("id = ?", stockCommodity[i].ID).
					Updates(stockCommodity[i]).Error
				if err != nil {
					return fmt.Errorf("更新商品库存失败：%s", err.Error())
				}
			}

			// 更新库存商品数量
			// 调入门店减去对应调入的数量
			err = gdb.Exec(fmt.Sprintf(
				"UPDATE erp_stock SET count=count-%d WHERE  store_id=%d AND erp_commodity_id=%d",
				v.Count, allotOrder.ReceiveStoreId, v.CommodityId)).Error
			if err != nil {
				logger.Errorf("update stock err:", err)
				return err
			}

			// 调出门店加上对应调出的数量
			err = gdb.Exec(fmt.Sprintf(
				"UPDATE erp_stock SET count=count+%d WHERE  store_id=%d AND erp_commodity_id=%d",
				v.Count, allotOrder.DeliverStoreId, v.CommodityId)).Error
			if err != nil {
				logger.Errorf("update stock err:", err)
				return err
			}

		}
	default:
		return fmt.Errorf("订单当前状态未知[%d]", allotOrder.State)
	}

	// 更新库存调拨订单信息
	allotOrder.State = ErpInventoryAllotOrderUnAudit
	err := gdb.Model(&ErpInventoryAllotOrder{}).Where("id = ?", allotOrder.ID).
		Updates(allotOrder).Error
	if err != nil {
		return fmt.Errorf("更新库存调拨订单失败：%s", err.Error())
	}

	return nil
}

// DeliverAllotInventory 调拨发货
func DeliverAllotInventory(req *InventoryAllotDeliverReq, c *gin.Context) error {
	// 查询订单信息
	var inventoryAllotOrder ErpInventoryAllotOrder
	err := orm.Eloquent.Table("erp_inventory_allot_order").Where("serial_number = ?", req.SerialNumber).
		Find(&inventoryAllotOrder).Error
	if err != nil {
		logger.Error("order err:", logger.Field("err", err))
		return err
	}

	sysUser, err := GetSysUserByCtx(c)
	if err != nil {
		logger.Error("sys user err:", logger.Field("err", err))
		return err
	}

	// 校验入参门店是否包含在用户所有门店中，是否过期
	if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
		if !CheckUserStore(inventoryAllotOrder.DeliverStoreId, sysUser) {
			return errors.New("操作失败：您没有该门店权限")
		}
	}

	if inventoryAllotOrder.ID == 0 {
		return errors.New("未查询到订单信息")
	}

	if inventoryAllotOrder.State != ErpInventoryAllotOrderWaitSend {
		return errors.New("订单不是待发货状态")
	}

	nowTime := time.Now()
	inventoryAllotOrder.LogisticsNumber = req.LogisticsNumber
	inventoryAllotOrder.Remark = req.Remark
	inventoryAllotOrder.State = ErpInventoryAllotOrderWaitReceive
	inventoryAllotOrder.DeliverTime = &nowTime

	err = orm.Eloquent.Model(&ErpInventoryAllotOrder{}).Where("id = ?", inventoryAllotOrder.ID).
		Updates(inventoryAllotOrder).Error
	if err != nil {
		return err
	}

	// 触发消息通知
	TriggerBizEvent(BizTypeOnAllot, EventOnAllot, map[string]interface{}{
		"serial_number":      inventoryAllotOrder.SerialNumber,
		"deliver_store_name": inventoryAllotOrder.DeliverStoreName,
		"audit_time":         inventoryAllotOrder.AuditTime,
	}, inventoryAllotOrder.ReceiveStoreId)

	return nil
}

// ReceiveAllotInventory 调拨收货
func ReceiveAllotInventory(req *InventoryAllotReceiveReq, c *gin.Context) error {
	// 查询订单信息
	var inventoryAllotOrder ErpInventoryAllotOrder
	if err := orm.Eloquent.Table("erp_inventory_allot_order").Where("serial_number = ?", req.SerialNumber).
		Find(&inventoryAllotOrder).Error; err != nil {
		logger.Error("order err:", logger.Field("err", err))
		return err
	}

	sysUser, err := GetSysUserByCtx(c)
	if err != nil {
		logger.Error("sys user err:", logger.Field("err", err))
		return err
	}

	// 校验入参门店是否包含在用户所有门店中，是否过期
	if !(tools.GetRoleName(c) == "admin" || tools.GetRoleName(c) == "系统管理员") {
		if !CheckUserStore(inventoryAllotOrder.ReceiveStoreId, sysUser) {
			return errors.New("操作失败：您没有该门店权限")
		}
	}

	if inventoryAllotOrder.ID == 0 {
		return errors.New("未查询到订单信息")
	}

	if inventoryAllotOrder.State != ErpInventoryAllotOrderWaitReceive {
		return errors.New("订单不是待收货状态")
	}

	// 查询库存调拨商品信息
	var commodities []ErpInventoryAllotCommodity
	if err := orm.Eloquent.Table("erp_inventory_allot_commodity").Where("allot_order_id = ?",
		inventoryAllotOrder.ID).Find(&commodities).Error; err != nil {
		logger.Error("query erp_inventory_allot_commodity err:", logger.Field("err", err))
		return err
	}
	if len(commodities) == 0 {
		return errors.New("未查询到库存调拨商品信息")
	}

	// 遍历库存调拨商品信息，将商品id相同的非串码商品进行合并，数量累加即可
	trimCommodities := MergeCommodities(commodities)

	begin := orm.Eloquent.Begin()
	// 遍历库存调拨商品信息
	for _, v := range trimCommodities {
		var stockCommodity []ErpStockCommodity
		err = orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? AND store_id = ? "+
			"AND state = ? AND imei = ?", v.CommodityId, inventoryAllotOrder.DeliverStoreId, InAllot, v.IMEI).
			Find(&stockCommodity).Error
		if err != nil {
			begin.Rollback()
			return fmt.Errorf("查询商品库存失败：[%s]", err.Error())
		}
		if len(stockCommodity) == 0 {
			begin.Rollback()
			return fmt.Errorf("未找到商品库存信息")
		}

		// 更新库存商品表商品状态为：在库，同时更新所属门店为调入门店
		for i := 0; i < int(v.Count); i++ {
			stockCommodity[i].StoreId = inventoryAllotOrder.ReceiveStoreId
			stockCommodity[i].StoreName = inventoryAllotOrder.ReceiveStoreName
			stockCommodity[i].State = InStock
			stockCommodity[i].StockTime = time.Now()
			err = begin.Where("id", stockCommodity[i].ID).Omit("created_at").Save(&stockCommodity[i]).Error
			//err = begin.Model(&ErpStockCommodity{}).Where("id = ?", stockCommodity[i].ID).
			//	Updates(stockCommodity[i]).Error
			if err != nil {
				begin.Rollback()
				return fmt.Errorf("更新商品库存失败：%s", err.Error())
			}
		}
	}

	// 遍历库存调拨商品信息，将商品id相同的非串码商品进行合并，数量累加即可
	trimAllCommodities := MergeAllCommodities(trimCommodities)
	for _, v := range trimAllCommodities {
		var stockCommodity []ErpStockCommodity
		err = orm.Eloquent.Table("erp_stock_commodity").Where("erp_commodity_id = ? AND store_id = ? "+
			"AND state = ? AND imei = ?", v.CommodityId, inventoryAllotOrder.DeliverStoreId, InAllot, v.IMEI).
			Find(&stockCommodity).Error
		if err != nil {
			begin.Rollback()
			return fmt.Errorf("查询商品库存失败：[%s]", err.Error())
		}
		if len(stockCommodity) == 0 {
			begin.Rollback()
			return fmt.Errorf("未找到商品库存信息")
		}

		// 更新调入门店的库存数量
		exist, err := QueryRecordExist(fmt.Sprintf("SELECT * FROM erp_stock WHERE store_id=%d AND erp_commodity_id=%d",
			inventoryAllotOrder.ReceiveStoreId, v.CommodityId))
		if err != nil {
			begin.Rollback()
			logger.Errorf("exist err:", err)
			return err
		}
		if exist {
			// 更新调入门店库存商品数量
			err = begin.Exec(fmt.Sprintf(
				"UPDATE erp_stock SET count=count+%d WHERE  store_id=%d AND erp_commodity_id=%d",
				v.Count, inventoryAllotOrder.ReceiveStoreId, v.CommodityId)).Error
			if err != nil {
				begin.Rollback()
				logger.Errorf("update stock err:", err)
				return err
			}
		} else {
			stock := &ErpStock{
				StoreId:               inventoryAllotOrder.ReceiveStoreId,
				StoreName:             inventoryAllotOrder.ReceiveStoreName,
				ErpCommodityId:        v.CommodityId,
				ErpCommodityName:      v.CommodityName,
				ErpCategoryId:         stockCommodity[0].ErpCategoryId,
				ErpCategoryName:       stockCommodity[0].ErpCategoryName,
				CommoditySerialNumber: stockCommodity[0].CommoditySerialNumber,
				IMEIType:              v.IMEIType,
				RetailPrice:           stockCommodity[0].RetailPrice,
				MinRetailPrice:        stockCommodity[0].MinRetailPrice,
				Count:                 v.Count,
				DispatchCount:         0,
			}
			err = begin.Create(stock).Error
			if err != nil {
				begin.Rollback()
				logger.Errorf("create stock err:", err)
				return err
			}
		}

		//// 更新库存商品数量
		//err = begin.Exec(fmt.Sprintf(
		//	"UPDATE erp_stock SET count=count+%d WHERE  store_id=%d AND erp_commodity_id=%d",
		//	v.Count, inventoryAllotOrder.ReceiveStoreId, v.CommodityId)).Error
		//if err != nil {
		//	begin.Rollback()
		//	logger.Errorf("update stock err:", err)
		//	return err
		//}

		// 更新调出门店库存商品调拨数量
		err = begin.Exec(fmt.Sprintf(
			"UPDATE erp_stock SET dispatch_count = dispatch_count-%d WHERE store_id=%d AND erp_commodity_id=%d",
			v.Count, inventoryAllotOrder.DeliverStoreId, v.CommodityId)).Error
		if err != nil {
			begin.Rollback()
			logger.Errorf("update stock err:", err)
			return err
		}
	}

	// 更新调拨订单的状态为：已完成
	nowTime := time.Now()
	inventoryAllotOrder.State = ErpInventoryAllotOrderFinished
	inventoryAllotOrder.ReceiveTime = &nowTime
	err = begin.Model(&ErpInventoryAllotOrder{}).Where("id = ?", inventoryAllotOrder.ID).
		Updates(inventoryAllotOrder).Error
	if err != nil {
		begin.Rollback()
		return err
	}

	err = begin.Commit().Error
	if err != nil {
		begin.Rollback()
		logger.Errorf("commit err:", err)
		return err
	}
	return nil
}
