package implments

import (
	"LAPP_ACURA_MOM_BACKEND/common"
	baseDal "LAPP_ACURA_MOM_BACKEND/dao/base"
	meDal "LAPP_ACURA_MOM_BACKEND/dao/me"
	omDal "LAPP_ACURA_MOM_BACKEND/dao/om"
	dal "LAPP_ACURA_MOM_BACKEND/dao/pln"
	"LAPP_ACURA_MOM_BACKEND/db"
	"LAPP_ACURA_MOM_BACKEND/global"
	"LAPP_ACURA_MOM_BACKEND/grmi"
	"LAPP_ACURA_MOM_BACKEND/infra/logger"
	meMeta "LAPP_ACURA_MOM_BACKEND/meta/me"
	omMeta "LAPP_ACURA_MOM_BACKEND/meta/om"
	meta "LAPP_ACURA_MOM_BACKEND/meta/pln"
	baseModel "LAPP_ACURA_MOM_BACKEND/models/base"
	channelModel "LAPP_ACURA_MOM_BACKEND/models/channel"
	meModel "LAPP_ACURA_MOM_BACKEND/models/me"
	omModel "LAPP_ACURA_MOM_BACKEND/models/om"
	model "LAPP_ACURA_MOM_BACKEND/models/pln"
	omSvr "LAPP_ACURA_MOM_BACKEND/services/om"
	"LAPP_ACURA_MOM_BACKEND/utils"
	"fmt"
	"github.com/360EntSecGroup-Skylar/excelize/v2"
	uuid "github.com/iris-contrib/go.uuid"
	"sort"
	"strconv"
	"time"
)

func (impl *CustOrderServiceImplement) LockCustOrder(user *global.User, custOrderIdLi []string) error {
	grmi.Log(user, "/services/pln/implments/CustOrder.service.impl.go", "LockCustOrder", "锁定客户订单")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	// 数据表dao层
	custOrderDao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
	custOrderStatusDao := dal.NewCustOrderStatusDAO(session, user.PlantNr, user.UserId)
	custOrderStatusRecDao := dal.NewCustOrderStatusHistoryDAO(session, user.PlantNr, user.UserId)
	custOrderStatusRecLi := make([]model.CustOrderStatusHistory, 0, len(custOrderIdLi))
	custOrderStatusLi := make([]model.CustOrderStatus, 0, len(custOrderIdLi))
	custOrderLi := make([]model.CustOrder, 0, len(custOrderIdLi))
	for _, custOrderId := range custOrderIdLi {
		// 校验客户订单是否存在及状态
		orderData, err := custOrderDao.SelectOne(custOrderId)
		if err != nil {
			return grmi.NewBusinessError("查询客户订单失败, error:" + err.Error())
		}
		if orderData == nil {
			return grmi.NewBusinessError("客户订单不存在, 订单ID:" + custOrderId)
		}
		if orderData.OrderStatus.Status != baseModel.WO_STATUS_PLANNED {
			return grmi.NewBusinessError("客户订单当前状态不是已计划, 订单ID:" + custOrderId)
		}
		custOrderLi = append(custOrderLi, *orderData)
		custOrderStatusRec := model.CustOrderStatusHistory{
			CustOrderId: custOrderId,
			FromStatus:  orderData.OrderStatus.Status,
			ToStatus:    baseModel.WO_STATUS_LOCKED,
			ChangeTime:  grmi.DateTime(time.Now()),
		}
		custOrderStatusRecLi = append(custOrderStatusRecLi, custOrderStatusRec)
		orderData.OrderStatus.Status = baseModel.WO_STATUS_LOCKED
		custOrderStatusLi = append(custOrderStatusLi, orderData.OrderStatus)
	}
	if err := session.Begin(); err != nil {
		return grmi.NewBusinessError("开启事务失败, 错误:" + err.Error())
	}
	err := custOrderStatusDao.Update(&custOrderStatusLi)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新客户订单状态失败，错误:" + err.Error())
	}
	err = custOrderStatusRecDao.Insert(&custOrderStatusRecLi)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("保存客户订单状态变更历史失败，错误:" + err.Error())
	}
	_ = session.Commit()
	sort.Slice(custOrderLi, func(i, j int) bool {
		itemI := custOrderLi[i]
		itemJ := custOrderLi[j]
		return itemJ.PlanStartTime.Restore().Before(itemI.PlanStartTime.Restore())
	})
	plantNr := user.PlantNr
	channel, exist := common.ReleaseTaskChannel[plantNr]
	if !exist {
		return nil
	}
	for _, custOrder := range custOrderLi {
		err = channel.SendData(custOrder)
		if err != nil {
			return nil
		}
	}
	return nil
}

// AnalysisPlanFromExcel 解析Excel
func (impl *CustOrderServiceImplement) AnalysisPlanFromExcel(user *global.User, filepath string) error {
	grmi.Log(user, "/services/pln/implments/CustOrder.service.impl.go", "AnalysisPlanFromExcel", "从Excel解析需求")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	var startDate, endDate time.Time
	productFamilyDao := meDal.NewProductFamilyDAO(session, user.PlantNr, user.UserId)
	productFamilyWorkLineDao := meDal.NewProductFamilyWorkLineLstDAO(session, user.PlantNr, user.UserId)
	projectDao := meDal.NewProjectDAO(session, user.PlantNr, user.UserId)
	snrDao := baseDal.NewSnrDAO(session, user.PlantNr, user.UserId)
	file, err := excelize.OpenFile(filepath)
	if err != nil {
		return grmi.NewBusinessError("读取文件失败, error:" + err.Error())
	}
	rowsIterator, err := file.Rows("Sheet1")
	if err != nil {
		return grmi.NewBusinessError("读取Sheet1页失败, error:" + err.Error())
	}
	today, _ := time.ParseInLocation(grmi.DateTimeOutFormat, time.Now().Format(grmi.DateOutFormat)+" 00:00:00", utils.TimezoneLocation)
	rowIndex := 0
	projectMap := make(map[string]*meModel.Project)
	productFamilyMap := make(map[string]*meModel.ProductFamily)
	custOrderWorkLineMap := make(map[string][]model.CustOrder, 0)
	for rowsIterator.Next() {
		rowIndex++
		// 第一行标题行
		if rowIndex == 1 {
			_, err = rowsIterator.Columns()
			if err != nil {
				return grmi.NewBusinessError("去读excel行数据失败, error:" + err.Error())
			}
			continue
		}

		row, err := rowsIterator.Columns()
		if err != nil {
			return grmi.NewBusinessError("去读excel行数据失败, error:" + err.Error())
		}
		if len(row) != 5 {
			return grmi.NewBusinessError("excel数据列数不合规, 行数:" + strconv.Itoa(rowIndex))
		}
		productFamilyId := row[0]
		projectId := row[1]
		qty, err := strconv.Atoi(row[2])
		if err != nil {
			return grmi.NewBusinessError("解析数量失败， 行数:" + strconv.Itoa(rowIndex))
		}
		if qty == 0 {
			return grmi.NewBusinessError("需求数量为0, 行数:" + strconv.Itoa(rowIndex))
		}
		planDateStr := row[3]
		planDate, err := time.ParseInLocation(grmi.DateOutFormat, planDateStr, utils.TimezoneLocation)
		if err != nil {
			return grmi.NewBusinessError("解析计划日期失败, 行数:" + strconv.Itoa(rowIndex))
		}
		if planDate.Before(today) {
			return grmi.NewBusinessError("计划日期不能早于今天")
		}
		if rowIndex == 2 {
			startDate = planDate
			endDate = planDate
		}
		if planDate.Before(startDate) {
			startDate = planDate
		}
		if endDate.Before(planDate) {
			endDate = planDate
		}
		workLineId := row[4]
		productFamily, exist := productFamilyMap[productFamilyId]
		if !exist {
			productFamily, err = productFamilyDao.SelectOne(productFamilyId)
			if err != nil {
				return grmi.NewBusinessError("查询派生数据失败, 错误:" + err.Error())
			}
			if productFamily == nil {
				return grmi.NewBusinessError("派生不存在, 派生ID:" + productFamilyId + ", 行数:" + strconv.Itoa(rowIndex))
			}
			productFamilyMap[productFamilyId] = productFamily
		}
		if !productFamily.MultiWorkLineToggle {
			if productFamily.WorkLineId != workLineId {
				return grmi.NewBusinessError("派生指定的产线不可生产, 派生ID:" + productFamilyId + ", 产线ID:" + workLineId)
			}

		} else {
			workLineLi, err := productFamilyWorkLineDao.Select([]grmi.Predicate{
				meMeta.ProductFamilyWorkLineLst_ProductFamilyId.NewPredicate(grmi.Equal, productFamilyId),
			}, nil)
			if err != nil {
				return grmi.NewBusinessError("查询派生可生产产线失败, 错误:" + err.Error())
			}
			var match bool
			for _, workLine := range workLineLi {
				if workLine.WorkLineId == workLineId {
					match = true
					break
				}
			}
			if !match {
				return grmi.NewBusinessError("派生指定的产线不可生产, 派生ID:" + productFamilyId + ", 产线ID:" + workLineId)
			}
		}
		project, exist := projectMap[projectId]
		if !exist {
			project, err = projectDao.SelectOne(projectId)
			if err != nil {
				return grmi.NewBusinessError("查询项目数据失败, 错误:" + err.Error())
			}
			if project == nil {
				return grmi.NewBusinessError("项目不存在, 项目ID:" + projectId + ", 行数:" + strconv.Itoa(rowIndex))
			}
			projectMap[projectId] = project
		}
		custOrder := model.CustOrder{
			ProductFamilyId: productFamilyId,
			PartId:          productFamilyId,
			OrderType:       baseModel.ODER_TYPE_INTERVAL,
			OrderInfo:       productFamily.Descr,
			OrderTime:       grmi.DateTime(time.Now()),
			ProjectId:       projectId,
			ConfigValue:     productFamily.ConfigValue,
			ModelValue:      productFamily.ModelValue,
			ColorValue:      productFamily.ColorValue,
			PlanQty:         qty,
			WorkLineId:      workLineId,
			QuantityPerHour: int(productFamily.Jph),
			PlanStartDate:   grmi.Date(planDate),
			SourceId:        "EXCEL",
		}
		custOrder.OrderStatus = model.CustOrderStatus{
			Status: baseModel.ORDER_STATUS_UNPLANED,
		}
		custOrder.OrderQty = model.CustOrderQty{
			PlanQty: custOrder.PlanQty,
		}
		custOrderWorkLineMap[workLineId] = append(custOrderWorkLineMap[workLineId], custOrder)
	}
	releaseCustOrderLi := make([]model.CustOrder, 0)
	for workLineId, custOrderLi := range custOrderWorkLineMap {
		for index, custOrder := range custOrderLi {
			project := projectMap[custOrder.ProjectId]
			custOrderId, err := snrDao.GetNextSnr(project.CustOrderSnr)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("获取客户订单流水号失败, 错误:" + err.Error())
			}
			custOrder.CustOrderId = custOrderId
			custOrder.OrderQty.CustOrderId = custOrderId
			custOrder.OrderStatus.CustOrderId = custOrderId
			custOrderLi[index] = custOrder
		}
		custOrderWorkLineMap[workLineId] = custOrderLi
	}
	endDate = endDate.AddDate(0, 0, 2)
	for workLineId, custOrderLi := range custOrderWorkLineMap {
		sortCustOrderLi, err := impl.AutoScheduler(user, session, workLineId, startDate, endDate, custOrderLi)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("自动排程失败，错误:" + err.Error())
		}
		releaseCustOrderLi = append(releaseCustOrderLi, sortCustOrderLi...)
	}
	_ = session.Commit()
	sort.Slice(releaseCustOrderLi, func(i, j int) bool {
		itemI := releaseCustOrderLi[i]
		itemJ := releaseCustOrderLi[j]
		return itemI.PlanStartTime.Restore().Before(itemJ.PlanStartTime.Restore())
	})
	plantNr := user.PlantNr
	channel, exist := common.ReleaseTaskChannel[plantNr]
	if !exist {
		fmt.Println("通道不存在")
		return nil
	}
	for _, custOrder := range releaseCustOrderLi {
		err = channel.SendData(custOrder)
		if err != nil {
			fmt.Println("发送数据出错:" + err.Error())
			return nil
		}
	}
	return nil
}

func (impl *CustOrderServiceImplement) ReleaseSingleOrder(user *global.User, custOrderData model.CustOrder) error {
	releaseId, err := uuid.NewV4()
	if err != nil {
		return grmi.NewBusinessError("生成任务id失败,错误:" + err.Error())
	}
	log, _ := logger.NewLogger("客户订单派工,id:"+releaseId.String(), "PLN")
	err = impl.ReleaseCustOrder(user, custOrderData, log)
	if err != nil {
		engine := db.Eloquent.Master()
		session := engine.NewSession()
		defer session.Close()
		statusHistoryDao := dal.NewCustOrderStatusHistoryDAO(session, user.PlantNr, user.UserId)
		statusDao := dal.NewCustOrderStatusDAO(session, user.PlantNr, user.UserId)
		statusHistory := model.CustOrderStatusHistory{
			CustOrderId: custOrderData.CustOrderId,
			StatusChangeType: model.STATUS_CHANGE_TYPE_RELEASE,
			FromStatus: custOrderData.OrderStatus.Status,
			ToStatus: baseModel.WO_STATUS_RELEASE_FAILED,
			ChangeTime: grmi.DateTime(time.Now()),
			TriggerPara1: err.Error(),
		}
		innerErr := statusHistoryDao.InsertOne(&statusHistory)
		if innerErr != nil {
			log.Error("派工失败, 保存客户订单状态变更记录失败, 错误:" + err.Error())
			return err
		}
		custOrderData.OrderStatus.Status = baseModel.WO_STATUS_RELEASE_FAILED
		innerErr = statusDao.UpdateOne(&custOrderData.OrderStatus)
		if err != nil {
			log.Error("派工失败, 更新客户订单状态变更记录失败, 错误:" + err.Error())
			return err
		}
		return err
	}
	return nil
}

// ReleaseCustOrder 对客户订单进行派工
func (impl *CustOrderServiceImplement) ReleaseCustOrder(user *global.User, custOrderData model.CustOrder, log logger.Log) error {

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	var productCraftMap = make(map[string]omModel.SerialOrder)
	// 数据表dao层
	projectDao := meDal.NewProjectDAO(session, user.PlantNr, user.UserId)
	custOrderQtyDao := dal.NewCustOrderQtyDAO(session, user.PlantNr, user.UserId)
	custOrderStatusDao := dal.NewCustOrderStatusDAO(session, user.PlantNr, user.UserId)
	custOrderStatusRecDao := dal.NewCustOrderStatusHistoryDAO(session, user.PlantNr, user.UserId)
	snrDao := baseDal.NewSnrDAO(session, user.PlantNr, user.UserId)
	workLineDao := baseDal.NewWorkLineDAO(session, user.PlantNr, user.UserId)
	productFamilyRelateDao := meDal.NewProductFamilyRelateDAO(session, user.PlantNr, user.UserId)
	productWorkLineDao := meDal.NewProductWorkLineLstDAO(session, user.PlantNr, user.UserId)
	labelHeadDao := baseDal.NewLabelHeadDAO(session, user.PlantNr, user.UserId)
	labelDetailDao := baseDal.NewLabelDetailDAO(session, user.PlantNr, user.UserId)
	serialOrderDao := omDal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	serialOrderStatusDao := omDal.NewSerialOrderStatusDAO(session, user.PlantNr, user.UserId)
	serialOrderPoDao := omDal.NewSerialOrderPOLstDAO(session, user.PlantNr, user.UserId)
	serialOrderStepDao := omDal.NewSerialOrderStepLstDAO(session, user.PlantNr, user.UserId)
	serialOrderOPDetailDao := omDal.NewSerialOrderOPDetailDAO(session, user.PlantNr, user.UserId)
	serialOrderStatusRecDao := omDal.NewSerialOrderStatusRecLstDAO(session, user.PlantNr, user.UserId)
	// 创建serialOrder service接口
	serialOrderSvr := omSvr.NewSerialOrderService()
	// 查询当前是否有需要派工的custOrder
	needReleaseQty := custOrderData.OrderQty.PlanQty - custOrderData.OrderQty.ReleasedQty - custOrderData.OrderQty.CancelQty
	log.Info("开始派工, 当前派工客户订单ID:" + custOrderData.CustOrderId + ", 需要派工数量:" + strconv.Itoa(needReleaseQty))
	// 获取客户订单的车型配置下的所有座椅
	productLi, err := productFamilyRelateDao.SelectProductByFamilyIdForCreateSerialOrder(custOrderData.ProjectId, custOrderData.ProductFamilyId)
	if err != nil {
		return grmi.NewBusinessError("通过车型配置查询关联座椅产品失败, error:" + err.Error())
	}
	if len(productLi) == 0 {
		return grmi.NewBusinessError("该客户订单的车型配置未关联座椅产品")
	}
	project, err := projectDao.SelectOne(custOrderData.ProjectId)
	if err != nil {
		return grmi.NewBusinessError("获取车型项目失败, error:" + err.Error())
	}
	if project == nil {
		return grmi.NewBusinessError("车型项目不存在, 车型项目ID:" + custOrderData.ProjectId)
	}
	// 每个总成生产的时间
	duration := custOrderData.PlanEndTime.Restore().Sub(custOrderData.PlanStartTime.Restore())
	totalQty := custOrderData.PlanQty * len(productLi)
	perDuration := duration.Seconds() / float64(totalQty)

	if custOrderData.CtrlPara1 == 1 {
		var current int
		// 如果客户订单是拆分出来的客户订单 则只是重置所归属的工单及工艺状态
		serialOrderDataLi, err := serialOrderDao.Select([]grmi.Predicate{
			omMeta.SerialOrder_CustOrderId.NewPredicate(grmi.Equal, custOrderData.CustOrderId),
			omMeta.SerialOrder_OrderType.NewPredicate(grmi.Equal, baseModel.ODER_TYPE_SEQ),
		}, []grmi.Field{omMeta.SerialOrder_PlanStartTime})
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("查询客户订单下的工单失败， error:" + err.Error())
		}
		for _, serialOrder := range serialOrderDataLi {
			planStartTime := custOrderData.PlanStartTime.Restore().Add(time.Duration(int(perDuration)*current) * time.Second)
			planEndTime := custOrderData.PlanStartTime.Restore().Add(time.Duration(int(perDuration)*(current+1)) * time.Second)
			current++
			planStartDate := grmi.Date(planStartTime)
			planEndDate := grmi.Date(planEndTime)
			timeInt, err := strconv.Atoi(planStartTime.Format("060102150405"))
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("通过时间获取工单调度Key失败, error:" + err.Error())
			}
			//dealedSchedKey := int64(todayInt*1000000 + schedKey*100)
			var dealedSchedKey = int64(timeInt * 100)
			serialOrder.PlanStartTime = grmi.DateTime(planStartTime)
			serialOrder.PlanEndTime = grmi.DateTime(planEndTime)
			serialOrder.PlanStartDate = planStartDate
			serialOrder.PlanEndDate = planEndDate
			serialOrder.SchedKey = dealedSchedKey
			err = serialOrderDao.UpdateOne(&serialOrder)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("更新工单数据失败， error:" + err.Error())
			}
			serialOrderStatusRec := omModel.SerialOrderStatusRecLst{
				SerialOrderId: serialOrder.SerialOrderId,
				PrevStatus:    serialOrder.SerialOrderStatus.Status,
				Status:        baseModel.WO_STATUS_RELEASED,
			}
			err = serialOrderStatusRecDao.InsertOne(&serialOrderStatusRec)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("写入工单状态变更历史失败, error:" + err.Error())
			}
			serialOrder.SerialOrderStatus.Status = baseModel.WO_STATUS_RELEASED
			err = serialOrderStatusDao.UpdateOne(&serialOrder.SerialOrderStatus)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("更新工单状态失败, error:" + err.Error())
			}
			poUpdateData := omModel.SerialOrderPOLst{
				Status: baseModel.WO_STATUS_RELEASED,
			}
			err = serialOrderPoDao.UpdateWhere([]grmi.Predicate{omMeta.SerialOrderPOLst_SerialOrderId.NewPredicate(grmi.Equal, serialOrder.SerialOrderId)}, &poUpdateData, []string{omMeta.SerialOrderPOLst_Status.Name}...)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("更新工单工序状态失败, error:" + err.Error())
			}
			stepUpdateData := omModel.SerialOrderStepLst{
				Status: baseModel.WO_STATUS_RELEASED,
			}
			err = serialOrderStepDao.UpdateWhere([]grmi.Predicate{omMeta.SerialOrderStepLst_SerialOrderId.NewPredicate(grmi.Equal, serialOrder.SerialOrderId)}, &stepUpdateData, []string{omMeta.SerialOrderStepLst_Status.Name}...)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("更新工单工步状态失败, error:" + err.Error())
			}
			opDetailUpdateData := omModel.SerialOrderOPDetail{
				Status: baseModel.WO_STATUS_RELEASED,
			}
			err = serialOrderOPDetailDao.UpdateWhere([]grmi.Predicate{omMeta.SerialOrderOPDetail_SerialOrderId.NewPredicate(grmi.Equal, serialOrder.SerialOrderId)}, &opDetailUpdateData, []string{omMeta.SerialOrderOPDetail_Status.Name}...)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("更新工单详细操作状态失败, error:" + err.Error())
			}
			//	对预装工单的处理
			preSerialOrderLi, err := serialOrderDao.Select([]grmi.Predicate{
				omMeta.SerialOrder_OrderType.NewPredicate(grmi.Equal, baseModel.ORDER_TYPE_PRE),
				omMeta.SerialOrder_GenerateFlag.NewPredicate(grmi.Equal, 0),
				omMeta.SerialOrder_MainOrderId.NewPredicate(grmi.Equal, serialOrder.SerialOrderId),
			}, nil)
			if err != nil {
				return grmi.NewBusinessError("查询工单下的预装工单失败, 错误：" + err.Error())
			}
			for _, preOrder := range preSerialOrderLi {
				preOrder.PlanStartTime = grmi.DateTime(planStartTime)
				preOrder.PlanEndTime = grmi.DateTime(planEndTime)
				preOrder.PlanStartDate = grmi.Date(planStartTime)
				preOrder.PlanEndDate = grmi.Date(planEndTime)
				preOrder.SchedKey = dealedSchedKey
				err = serialOrderDao.UpdateOne(&preOrder)
				if err != nil {
					return grmi.NewBusinessError("更新预装工单数据失败, 错误：" + err.Error())
				}
				statusRec := omModel.SerialOrderStatusRecLst{
					SerialOrderId: preOrder.SerialOrderId,
					Status:        baseModel.WO_STATUS_RELEASED,
					PrevStatus:    preOrder.SerialOrderStatus.Status,
				}
				preOrder.SerialOrderStatus.Status = baseModel.WO_STATUS_RELEASED
				err = serialOrderStatusRecDao.InsertOne(&statusRec)
				if err != nil {
					_ = session.Rollback()
					return grmi.NewBusinessError("插入预装工单状态变更记录失败, error:" + err.Error())
				}
				err = serialOrderStatusDao.UpdateOneWithStatus(&preOrder.SerialOrderStatus, baseModel.WO_STATUS_UNPLANNED)
				if err != nil {
					_ = session.Rollback()
					return grmi.NewBusinessError("更新预装工单状态失败， error:" + err.Error())
				}
				poUpdateData := &omModel.SerialOrderPOLst{
					Status: baseModel.WO_STATUS_RELEASED,
				}
				err = serialOrderPoDao.UpdateWhere([]grmi.Predicate{omMeta.SerialOrderPOLst_SerialOrderId.NewPredicate(grmi.Equal, preOrder.SerialOrderId)}, poUpdateData, omMeta.SerialOrderPOLst_Status.Name)
				if err != nil {
					_ = session.Rollback()
					return grmi.NewBusinessError("更新预装工单工序状态失败, error:" + err.Error())
				}
				stepUpdateData := &omModel.SerialOrderStepLst{
					Status: baseModel.WO_STATUS_RELEASED,
				}
				err = serialOrderStepDao.UpdateWhere([]grmi.Predicate{omMeta.SerialOrderStepLst_SerialOrderId.NewPredicate(grmi.Equal, preOrder.SerialOrderId)}, stepUpdateData, omMeta.SerialOrderStepLst_Status.Name)
				if err != nil {
					_ = session.Rollback()
					return grmi.NewBusinessError("更新预装工单工步状态失败, error:" + err.Error())
				}
				opDetailUpdateData := &omModel.SerialOrderOPDetail{
					Status: baseModel.WO_STATUS_RELEASED,
				}
				err = serialOrderOPDetailDao.UpdateWhere([]grmi.Predicate{omMeta.SerialOrderOPDetail_SerialOrderId.NewPredicate(grmi.Equal, preOrder.SerialOrderId)}, opDetailUpdateData, omMeta.SerialOrderOPDetail_Status.Name)
				if err != nil {
					_ = session.Rollback()
					return grmi.NewBusinessError("更新预装工单详细操作状态失败, error:" + err.Error())
				}
			}
		}
		custOrderStatusRec := model.CustOrderStatusHistory{
			CustOrderId: custOrderData.CustOrderId,
			FromStatus:  custOrderData.OrderStatus.Status,
			ToStatus:    baseModel.WO_STATUS_RELEASED,
			ChangeTime:  grmi.DateTime(time.Now()),
		}
		err = custOrderStatusRecDao.InsertOne(&custOrderStatusRec)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("插入客户订单状态变更历史失败, error:" + err.Error())
		}
		custOrderData.OrderStatus.Status = baseModel.WO_STATUS_RELEASED
		err = custOrderStatusDao.UpdateOne(&custOrderData.OrderStatus)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新客户订单状态失败, error:" + err.Error())
		}
		_ = session.Commit()
		return nil
	}

	// 产线组与所属产线的MAP数据结构
	workLineGroupMap := make(map[string]map[string]interface{})
	workLineMap := make(map[string]baseModel.WorkLine)
	allWorkLineLi, err := workLineDao.Select(nil, nil)
	if err != nil {
		return grmi.NewBusinessError("查询工厂产线数据失败, 错误:" + err.Error())
	}
	for _, workLine := range allWorkLineLi {
		workLineMap[workLine.WorkLineid] = workLine
		if workLine.GroupType == baseModel.WORK_LINE_TYPE_GROUP {
			workLineGroupMap[workLine.WorkLineid] = make(map[string]interface{})
		}
	}
	for _, workLine := range allWorkLineLi {
		if workLine.GroupType == baseModel.WORK_LINE_TYPE_REAL {
			_, exist := workLineGroupMap[workLine.GroupLineId]
			if exist {
				workLineGroupMap[workLine.GroupLineId][workLine.WorkLineid] = nil
			}
		}
	}

	for i := 0; i < needReleaseQty; i++ {
		writeSerialOrderLi := make([]omModel.SerialOrder, 0)
		writeSerialOrderStatusLi := make([]omModel.SerialOrderStatus, 0)
		writeSerialOrderStepLi := make([]omModel.SerialOrderStepLst, 0)
		writeSerialOrderPoLi := make([]omModel.SerialOrderPOLst, 0)
		writeSerialOrderOpLi := make([]omModel.SerialOrderOPDetail, 0)
		writeLabelHeadLi := make([]baseModel.LabelHead, 0)
		writeLabelDetailLi := make([]baseModel.LabelDetail, 0)
		syncKey := custOrderData.CustOrderId + "-" + strconv.Itoa(custOrderData.OrderQty.ReleasedQty)
		waitReleaseSerialOrderLi := make([]omModel.SerialOrder, 0, len(productLi))
		for index, product := range productLi {
			var serialOrder omModel.SerialOrder
			orderCraft, exist := productCraftMap[product.ProductId]
			if !exist {
				// 获取生产使用的产线
				var resourceId string
				if product.MultiWorkLineToggle {
					relateWorkLineLi, err := productWorkLineDao.Select([]grmi.Predicate{
						meMeta.ProductWorkLineLst_ProductId.NewPredicate(grmi.Equal, product.ProductId),
						meMeta.ProductWorkLineLst_ProjectId.NewPredicate(grmi.Equal, product.ProjectId),
					}, nil)
					if err != nil {
						return grmi.NewBusinessError("查询总成关联产线失败, 错误:" + err.Error())
					}
					canUsedWorkLineMap, exist := workLineGroupMap[custOrderData.WorkLineId]
					if !exist {
						return grmi.NewBusinessError("未获取到该派生产线组下的实体产线")
					}
					for _, workLine := range relateWorkLineLi {
						_, exist = canUsedWorkLineMap[workLine.WorkLineId]
						if exist {
							if resourceId == "" {
								resourceId = workLine.WorkLineId
							} else {
								return grmi.NewBusinessError("总成在关联了可生产产线，总成ID:" + product.ProductId)
							}
						}
					}
					if resourceId == "" {
						return grmi.NewBusinessError("未获取到可生产的产线")
					}
				} else {
					resourceId = product.DefaultWorkLineId
				}
				currentIndex := custOrderData.OrderQty.ReleasedQty*len(productLi) + index
				planStartTime := custOrderData.PlanStartTime.Restore().Add(time.Duration(int(perDuration)*currentIndex) * time.Second)
				planEndTime := custOrderData.PlanStartTime.Restore().Add(time.Duration(int(perDuration)*(currentIndex+1)) * time.Second)
				planStartDate := grmi.Date(planStartTime)
				planEndDate := grmi.Date(planEndTime)
				serialOrderId := product.MachineCode + "$serialNumber$" + product.ProductType + product.ColorValue
				timeInt, err := strconv.Atoi(planStartTime.Format("060102150405"))
				if err != nil {
					return grmi.NewBusinessError("通过时间获取工单调度Key失败, error:" + err.Error())
				}
				var dealedSchedKey = int64(timeInt * 100)
				serialOrder = omModel.SerialOrder{
					SerialOrderId:  serialOrderId,
					ArtId:          product.ProductId,
					ProjectId:      custOrderData.ProjectId,
					Descr:          product.Descr,
					CustOrderId:    custOrderData.CustOrderId,
					OrderType:      baseModel.ODER_TYPE_SEQ,
					PlanResourceId: resourceId,
					UsedResourceId: resourceId,
					SchedKey:       dealedSchedKey,
					PlanQty:        1,
					PlanStartDate:  planStartDate,
					PlanEndDate:    planEndDate,
					PlanStartTime:  grmi.DateTime(planStartTime),
					PlanEndTime:    grmi.DateTime(planEndTime),
					PickingFlag:    product.PickingFlag,
					SyncKey:        syncKey,
				}
				if custOrderData.OrderQty.ReleasedQty == 0 {
					serialOrder.IsFirstPieceToggle = true
				}
				serialOrderStatus := omModel.SerialOrderStatus{
					SerialOrderId: serialOrderId,
					Status:        baseModel.WO_STATUS_RELEASED,
				}
				serialOrder.SerialOrderStatus = serialOrderStatus

				err = serialOrderSvr.GenerateProductCraft(user, session, &serialOrder)
				if err != nil {
					return err
				}
				orderCraft = serialOrder
				orderCraft.PreOrderLi = make([]omModel.SerialOrder, 0, len(serialOrder.PreOrderLi))
				orderCraft.SerialOrderPOLstLi = make([]omModel.SerialOrderPOLst, len(serialOrder.SerialOrderPOLstLi), len(serialOrder.SerialOrderPOLstLi))
				orderCraft.SerialOrderStepLstLi = make([]omModel.SerialOrderStepLst, len(serialOrder.SerialOrderStepLstLi), len(serialOrder.SerialOrderStepLstLi))
				orderCraft.SerialOrderOPDetailLi = make([]omModel.SerialOrderOPDetail, len(serialOrder.SerialOrderOPDetailLi), len(serialOrder.SerialOrderOPDetailLi))
				orderCraft.LabelHeadLi = make([]baseModel.LabelHead, len(serialOrder.LabelHeadLi), len(serialOrder.LabelHeadLi))
				orderCraft.LabelDetailLi = make([]baseModel.LabelDetail, len(serialOrder.LabelDetailLi), len(serialOrder.LabelDetailLi))
				copy(orderCraft.SerialOrderPOLstLi, serialOrder.SerialOrderPOLstLi)
				copy(orderCraft.SerialOrderStepLstLi, serialOrder.SerialOrderStepLstLi)
				copy(orderCraft.SerialOrderOPDetailLi, serialOrder.SerialOrderOPDetailLi)
				copy(orderCraft.LabelHeadLi, serialOrder.LabelHeadLi)
				copy(orderCraft.LabelDetailLi, serialOrder.LabelDetailLi)
				for _, preOrder := range serialOrder.PreOrderLi {
					newPreOrder := preOrder
					newPreOrder.SerialOrderPOLstLi = make([]omModel.SerialOrderPOLst, len(preOrder.SerialOrderPOLstLi), len(preOrder.SerialOrderPOLstLi))
					newPreOrder.SerialOrderStepLstLi = make([]omModel.SerialOrderStepLst, len(preOrder.SerialOrderStepLstLi), len(preOrder.SerialOrderStepLstLi))
					newPreOrder.SerialOrderOPDetailLi = make([]omModel.SerialOrderOPDetail, len(preOrder.SerialOrderOPDetailLi), len(preOrder.SerialOrderOPDetailLi))
					newPreOrder.LabelHeadLi = make([]baseModel.LabelHead, len(preOrder.LabelHeadLi), len(preOrder.LabelHeadLi))
					newPreOrder.LabelDetailLi = make([]baseModel.LabelDetail, len(preOrder.LabelDetailLi), len(preOrder.LabelDetailLi))
					copy(newPreOrder.SerialOrderPOLstLi, preOrder.SerialOrderPOLstLi)
					copy(newPreOrder.SerialOrderStepLstLi, preOrder.SerialOrderStepLstLi)
					copy(newPreOrder.SerialOrderOPDetailLi, preOrder.SerialOrderOPDetailLi)
					copy(newPreOrder.LabelHeadLi, preOrder.LabelHeadLi)
					copy(newPreOrder.LabelDetailLi, preOrder.LabelDetailLi)
					orderCraft.PreOrderLi = append(orderCraft.PreOrderLi, newPreOrder)
				}
				productCraftMap[serialOrder.ArtId] = orderCraft
			} else {
				serialOrder = orderCraft
				currentIndex := custOrderData.OrderQty.ReleasedQty*len(productLi) + index
				planStartTime := custOrderData.PlanStartTime.Restore().Add(time.Duration(int(perDuration)*currentIndex) * time.Second)
				planEndTime := custOrderData.PlanStartTime.Restore().Add(time.Duration(int(perDuration)*(currentIndex+1)) * time.Second)
				planStartDate := grmi.Date(planStartTime)
				planEndDate := grmi.Date(planEndTime)
				timeInt, err := strconv.Atoi(planStartTime.Format("060102150405"))
				if err != nil {
					return grmi.NewBusinessError("通过时间获取工单调度Key失败, error:" + err.Error())
				}
				var dealedSchedKey = int64(timeInt * 100)
				serialOrder.SyncKey = syncKey
				serialOrder.PlanStartTime = grmi.DateTime(planStartTime)
				serialOrder.PlanEndTime = grmi.DateTime(planEndTime)
				serialOrder.PlanStartDate = planStartDate
				serialOrder.PlanEndDate = planEndDate
				serialOrder.SchedKey = dealedSchedKey
				serialOrder.ArtId = product.ProductId
				if custOrderData.OrderQty.ReleasedQty != 0 {
					serialOrder.IsFirstPieceToggle = false
				}
				serialOrder.PreOrderLi = make([]omModel.SerialOrder, 0, len(orderCraft.PreOrderLi))
				serialOrder.SerialOrderPOLstLi = make([]omModel.SerialOrderPOLst, len(orderCraft.SerialOrderPOLstLi), len(orderCraft.SerialOrderPOLstLi))
				serialOrder.SerialOrderStepLstLi = make([]omModel.SerialOrderStepLst, len(orderCraft.SerialOrderStepLstLi), len(orderCraft.SerialOrderStepLstLi))
				serialOrder.SerialOrderOPDetailLi = make([]omModel.SerialOrderOPDetail, len(orderCraft.SerialOrderOPDetailLi), len(orderCraft.SerialOrderOPDetailLi))
				serialOrder.LabelHeadLi = make([]baseModel.LabelHead, len(orderCraft.LabelHeadLi), len(orderCraft.LabelHeadLi))
				serialOrder.LabelDetailLi = make([]baseModel.LabelDetail, len(orderCraft.LabelDetailLi), len(orderCraft.LabelDetailLi))
				copy(serialOrder.SerialOrderPOLstLi, orderCraft.SerialOrderPOLstLi)
				copy(serialOrder.SerialOrderStepLstLi, orderCraft.SerialOrderStepLstLi)
				copy(serialOrder.SerialOrderOPDetailLi, orderCraft.SerialOrderOPDetailLi)
				copy(serialOrder.LabelHeadLi, orderCraft.LabelHeadLi)
				copy(serialOrder.LabelDetailLi, orderCraft.LabelDetailLi)
				for _, preOrder := range orderCraft.PreOrderLi {
					newPreOrder := preOrder
					newPreOrder.MainOrderId = serialOrder.SerialOrderId
					newPreOrder.SyncKey = serialOrder.SyncKey
					newPreOrder.SchedKey = serialOrder.SchedKey
					newPreOrder.PreSchedKey = serialOrder.SchedKey
					newPreOrder.PlanStartTime = serialOrder.PlanStartTime
					newPreOrder.PlanEndTime = serialOrder.PlanEndTime
					newPreOrder.PlanStartDate = serialOrder.PlanStartDate
					newPreOrder.PlanEndDate = serialOrder.PlanEndDate
					newPreOrder.SerialOrderPOLstLi = make([]omModel.SerialOrderPOLst, len(preOrder.SerialOrderPOLstLi), len(preOrder.SerialOrderPOLstLi))
					newPreOrder.SerialOrderStepLstLi = make([]omModel.SerialOrderStepLst, len(preOrder.SerialOrderStepLstLi), len(preOrder.SerialOrderStepLstLi))
					newPreOrder.SerialOrderOPDetailLi = make([]omModel.SerialOrderOPDetail, len(preOrder.SerialOrderOPDetailLi), len(preOrder.SerialOrderOPDetailLi))
					newPreOrder.LabelHeadLi = make([]baseModel.LabelHead, len(preOrder.LabelHeadLi), len(preOrder.LabelHeadLi))
					newPreOrder.LabelDetailLi = make([]baseModel.LabelDetail, len(preOrder.LabelDetailLi), len(preOrder.LabelDetailLi))
					copy(newPreOrder.SerialOrderPOLstLi, preOrder.SerialOrderPOLstLi)
					copy(newPreOrder.SerialOrderStepLstLi, preOrder.SerialOrderStepLstLi)
					copy(newPreOrder.SerialOrderOPDetailLi, preOrder.SerialOrderOPDetailLi)
					copy(newPreOrder.LabelHeadLi, preOrder.LabelHeadLi)
					copy(newPreOrder.LabelDetailLi, preOrder.LabelDetailLi)
					serialOrder.PreOrderLi = append(serialOrder.PreOrderLi, newPreOrder)
				}

			}
			waitReleaseSerialOrderLi = append(waitReleaseSerialOrderLi, serialOrder)
		}
		if err = session.Begin(); err != nil {
			return grmi.NewBusinessError("开启事务失败, 错误:" + err.Error())
		}
		serialNumber, err := snrDao.GetNextSnrWithTime(project.SerialOrderSnr, waitReleaseSerialOrderLi[0].PlanStartTime.Restore())
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("生成工单流水号失败, error:" + err.Error())
		}
		preSerialNumber, err := snrDao.GetNextSnr(project.PreOrderSnr)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("获取流水号失败，错误:" + err.Error())
		}
		for _, serialOrder := range waitReleaseSerialOrderLi {
			serialOrderSvr.ReplaceData(&serialOrder, serialNumber, false)
			for index, preOrder := range serialOrder.PreOrderLi {
				preOrder.MainOrderId = serialOrder.SerialOrderId
				serialOrderSvr.ReplaceData(&preOrder, preSerialNumber, true)
				serialOrder.PreOrderLi[index] = preOrder
			}
			writeSerialOrderLi = append(writeSerialOrderLi, serialOrder)
			writeSerialOrderStatusLi = append(writeSerialOrderStatusLi, serialOrder.SerialOrderStatus)
			writeSerialOrderPoLi = append(writeSerialOrderPoLi, serialOrder.SerialOrderPOLstLi...)
			writeSerialOrderStepLi = append(writeSerialOrderStepLi, serialOrder.SerialOrderStepLstLi...)
			writeSerialOrderOpLi = append(writeSerialOrderOpLi, serialOrder.SerialOrderOPDetailLi...)
			writeLabelHeadLi = append(writeLabelHeadLi, serialOrder.LabelHeadLi...)
			writeLabelDetailLi = append(writeLabelDetailLi, serialOrder.LabelDetailLi...)
			for _, preOrder := range serialOrder.PreOrderLi {
				writeSerialOrderLi = append(writeSerialOrderLi, preOrder)
				writeSerialOrderStatusLi = append(writeSerialOrderStatusLi, preOrder.SerialOrderStatus)
				writeSerialOrderPoLi = append(writeSerialOrderPoLi, preOrder.SerialOrderPOLstLi...)
				writeSerialOrderStepLi = append(writeSerialOrderStepLi, preOrder.SerialOrderStepLstLi...)
				writeSerialOrderOpLi = append(writeSerialOrderOpLi, preOrder.SerialOrderOPDetailLi...)
				writeLabelHeadLi = append(writeLabelHeadLi, preOrder.LabelHeadLi...)
				writeLabelDetailLi = append(writeLabelDetailLi, preOrder.LabelDetailLi...)
			}

		}
		// 插入工单
		num := len(writeSerialOrderLi) / 50
		remainder := len(writeSerialOrderLi) % 50
		for i := 0; i < num; i++ {
			insertLi := writeSerialOrderLi[50*i : (i+1)*50]
			err = serialOrderDao.Insert(&insertLi)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("保存工单失败, 错误:" + err.Error())
			}
		}
		if remainder != 0 {
			insertLi := writeSerialOrderLi[num*50:]
			err = serialOrderDao.Insert(&insertLi)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("保存工单失败, 错误:" + err.Error())
			}
		}
		// 插入工单状态
		num = len(writeSerialOrderStatusLi) / 50
		remainder = len(writeSerialOrderStatusLi) % 50
		for i := 0; i < num; i++ {
			insertLi := writeSerialOrderStatusLi[50*i : (i+1)*50]
			err = serialOrderStatusDao.Insert(&insertLi)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("保存工单状态失败, 错误:" + err.Error())
			}
		}
		if remainder != 0 {
			insertLi := writeSerialOrderStatusLi[num*50:]
			err = serialOrderStatusDao.Insert(&insertLi)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("保存工单状态失败, 错误:" + err.Error())
			}
		}
		// 插入工单工序数据
		num = len(writeSerialOrderPoLi) / 50
		remainder = len(writeSerialOrderPoLi) % 50
		for i := 0; i < num; i++ {
			insertLi := writeSerialOrderPoLi[50*i : (i+1)*50]
			err = serialOrderPoDao.Insert(&insertLi)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("保存工单工序失败, 错误:" + err.Error())
			}
		}
		if remainder != 0 {
			insertLi := writeSerialOrderPoLi[num*50:]
			err = serialOrderPoDao.Insert(&insertLi)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("保存工单工序失败, 错误:" + err.Error())
			}
		}
		// 插入工单工步数据
		num = len(writeSerialOrderStepLi) / 50
		remainder = len(writeSerialOrderStepLi) % 50
		for i := 0; i < num; i++ {
			insertLi := writeSerialOrderStepLi[50*i : (i+1)*50]
			err = serialOrderStepDao.Insert(&insertLi)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("保存工单工步失败, 错误:" + err.Error())
			}
		}
		if remainder != 0 {
			insertLi := writeSerialOrderStepLi[num*50:]
			err = serialOrderStepDao.Insert(&insertLi)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("保存工单工步失败, 错误:" + err.Error())
			}
		}
		// 插入工单工艺数据
		num = len(writeSerialOrderOpLi) / 50
		remainder = len(writeSerialOrderOpLi) % 50
		for i := 0; i < num; i++ {
			insertLi := writeSerialOrderOpLi[50*i : (i+1)*50]
			err = serialOrderOPDetailDao.Insert(&insertLi)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("保存工单工艺失败, 错误:" + err.Error())
			}
		}
		if remainder != 0 {
			insertLi := writeSerialOrderOpLi[num*50:]
			err = serialOrderOPDetailDao.Insert(&insertLi)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("保存工单工艺失败, 错误:" + err.Error())
			}
		}
		// 写入打印标签数据
		num = len(writeLabelHeadLi) / 50
		remainder = len(writeLabelHeadLi) % 50
		for i := 0; i < num; i++ {
			insertLi := writeLabelHeadLi[50*i : (i+1)*50]
			err = labelHeadDao.Insert(&insertLi)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("保存标签头部失败, 错误:" + err.Error())
			}
		}
		if remainder != 0 {
			insertLi := writeLabelHeadLi[num*50:]
			err = labelHeadDao.Insert(&insertLi)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("保存标签头部失败, 错误:" + err.Error())
			}
		}
		num = len(writeLabelDetailLi) / 50
		remainder = len(writeLabelDetailLi) % 50
		for i := 0; i < num; i++ {
			insertLi := writeLabelDetailLi[50*i : (i+1)*50]
			err = labelDetailDao.Insert(&insertLi)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("保存标签详情失败, 错误:" + err.Error())
			}
		}
		if remainder != 0 {
			insertLi := writeLabelDetailLi[num*50:]
			err = labelDetailDao.Insert(&insertLi)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("保存标签详情失败, 错误:" + err.Error())
			}
		}
		log.Info("客户订单派工完成一次, 客户订单当前派工数量:" + strconv.Itoa(custOrderData.OrderQty.ReleasedQty))
		custOrderData.OrderQty.ReleasedQty += 1
		err = custOrderQtyDao.UpdateOne(&custOrderData.OrderQty)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新客户订单派工数量失败，错误:" + err.Error())
		}
		_ = session.Commit()
	}
	if custOrderData.OrderQty.PlanQty == custOrderData.OrderQty.ReleasedQty+custOrderData.OrderQty.CancelQty {
		if err = session.Begin(); err != nil {
			return grmi.NewBusinessError("开启事务失败, 错误：" + err.Error())
		}
		custOrderStatusRec := model.CustOrderStatusHistory{
			CustOrderId: custOrderData.CustOrderId,
			FromStatus:  custOrderData.OrderStatus.Status,
			ToStatus:    baseModel.WO_STATUS_RELEASED,
			ChangeTime:  grmi.DateTime(time.Now()),
		}
		err = custOrderStatusRecDao.InsertOne(&custOrderStatusRec)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("插入客户订单状态变更历史失败, error:" + err.Error())
		}
		custOrderData.OrderStatus.Status = baseModel.WO_STATUS_RELEASED
		err = custOrderStatusDao.UpdateOne(&custOrderData.OrderStatus)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新客户订单状态失败, error:" + err.Error())
		}
		_ = session.Commit()
	} else {
		log.Error("客户订单已经派工完成，但是并没有改变客户订单状态, 当前派工客户订单ID:" + custOrderData.CustOrderId)
	}
	log.Info("客户订单已经派工完成, 当前派工客户订单ID:" + custOrderData.CustOrderId)
	return nil
}

func (impl *CustOrderServiceImplement) ReleasePlantTask(user *global.User) {
	log, _ := logger.NewLogger("派工任务", "PLN")
	plantNr := user.PlantNr
	channel, exist := common.ReleaseTaskChannel[plantNr]
	if !exist {
		return
	}
	for {
		custOrder, ok, err := channel.Read()
		if err != nil {
			return
		}
		if !ok {
			continue
		}
		err = impl.ReleaseSingleOrder(user, custOrder)
		if err != nil {
			log.Error("派工异常, 错误:" + err.Error())
			channel.Close()
			return
		}
	}
}

func (impl *CustOrderServiceImplement) ReleaseTask() error {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	userId := "scheduler"
	plantDao := baseDal.NewPlantDAO(session, userId)
	plantLi, err := plantDao.Select(nil, nil)
	if err != nil {
		return err
	}
	for _, plant := range plantLi {
		user := &global.User{
			PlantNr: plant.PlantNr,
			UserId:  userId,
		}
		custOrderDao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
		custOrderLi, err := custOrderDao.SelectNeedReleaseCustOrder()
		if err != nil {
			return err
		}
		channel, exist := common.ReleaseTaskChannel[user.PlantNr]
		if !exist {
			channel = channelModel.NewReleaseChannel()
			common.ReleaseTaskChannel[user.PlantNr] = channel
		}
		for _, custOrder := range custOrderLi {
			err = channel.SendData(custOrder)
			if err != nil {
				return err
			}
		}
		go func(user *global.User) {
			impl.ReleasePlantTask(user)
		}(user)
	}
	return nil
}

// SelectReleaseTask 查询派工任务
func (impl *CustOrderServiceImplement) SelectReleaseTask(user *global.User) ([]model.CustOrder, error) {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	custOrderDao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
	custOrderLi, err := custOrderDao.SelectReleasingOrder()
	return custOrderLi, err
}

// RepairReleaseFailedTask 修复派工失败
func (impl *CustOrderServiceImplement) RepairReleaseFailedTask(user *global.User) (err error)  {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	custOrderStatusDao := dal.NewCustOrderStatusDAO(session, user.PlantNr, user.UserId)
	statusHistoryDao := dal.NewCustOrderStatusHistoryDAO(session, user.PlantNr, user.UserId)
	custOrderDao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
	statusLi, err := custOrderStatusDao.Select([]grmi.Predicate{
		meta.CustOrderStatus_Status.NewPredicate(grmi.Equal, baseModel.WO_STATUS_RELEASE_FAILED),
	}, nil)
	if err != nil {
		return grmi.NewBusinessError("查询客户订单数据失败, 错误:" + err.Error())
	}
	if len(statusLi) == 0 {
		return grmi.NewBusinessError("不存在派工失败的客户订单")
	}
	channel, exist := common.ReleaseTaskChannel[user.PlantNr]
	if !exist {
		return grmi.NewBusinessError("该工厂任务队列不存在, 请联系软件供应商")
	}
	if err = session.Begin(); err != nil {
		return grmi.NewBusinessError("开启事务失败, 错误:" + err.Error())
	}
	for _, status := range statusLi {
		statusHistory := model.CustOrderStatusHistory{
			CustOrderId: status.CustOrderId,
			StatusChangeType: model.STATUS_CHANGE_TYPE_RELEASE,
			FromStatus: status.Status,
			ToStatus: baseModel.WO_STATUS_LOCKED,
			ChangeTime: grmi.DateTime(time.Now()),
			TriggerPara1: "修复派工任务",
		}
		err = statusHistoryDao.InsertOne(&statusHistory)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("保存客户订单状态变更历史失败， 错误:" + err.Error())
		}
		status.Status = baseModel.WO_STATUS_LOCKED
		 err = custOrderStatusDao.UpdateOne(&status)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新客户订单状态失败， 错误:" + err.Error())
		}
	}
	err = channel.ResetChannel()
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("刷新任务队列失败")
	}
	custOrderLi, err := custOrderDao.SelectNeedReleaseCustOrder()
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("查询需要派工的客户订单失败, 错误:" + err.Error())
	}
	for _, custOrder := range custOrderLi {
		err = channel.SendData(custOrder)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("向队列发送数据失败, 错误:" + err.Error())
		}
	}
	_ = session.Commit()
	go impl.ReleasePlantTask(user)
	return nil

}