// Copyright (c) Shenyang Leading Edge Intelligent Technology Co., Ltd. All rights reserved.

package implments

import (
	baseDal "LAPP_ACURA_MOM_BACKEND/dao/base"
	meDal "LAPP_ACURA_MOM_BACKEND/dao/me"
	dal "LAPP_ACURA_MOM_BACKEND/dao/om"
	"LAPP_ACURA_MOM_BACKEND/db"
	"LAPP_ACURA_MOM_BACKEND/global"
	"LAPP_ACURA_MOM_BACKEND/grmi"
	meMeta "LAPP_ACURA_MOM_BACKEND/meta/me"
	meta "LAPP_ACURA_MOM_BACKEND/meta/om"
	baseModel "LAPP_ACURA_MOM_BACKEND/models/base"
	meModel "LAPP_ACURA_MOM_BACKEND/models/me"
	model "LAPP_ACURA_MOM_BACKEND/models/om"
	"strconv"
	"strings"
	"time"
)

/******************************************************************************
 *
 * @Description              : SerialOrder的默认查询条件
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-10-22 14:06:37
 *
 ******************************************************************************/
var DefaultConditionOfSerialOrder = grmi.NewCondition(
	map[string]grmi.ConditionItem{
		meta.SerialOrder_SerialOrderId.UrlParameterName:      grmi.NewConditionItem(meta.SerialOrder_SerialOrderId, grmi.Equal, true),
		meta.SerialOrder_ArtId.UrlParameterName:              grmi.NewConditionItem(meta.SerialOrder_ArtId, grmi.Equal, false),
		meta.SerialOrder_ProjectId.UrlParameterName:          grmi.NewConditionItem(meta.SerialOrder_ProjectId, grmi.Equal, false),
		meta.SerialOrder_Descr.UrlParameterName:              grmi.NewConditionItem(meta.SerialOrder_Descr, grmi.Equal, false),
		meta.SerialOrder_WorkOrderId.UrlParameterName:        grmi.NewConditionItem(meta.SerialOrder_WorkOrderId, grmi.Equal, false),
		meta.SerialOrder_CustOrderId.UrlParameterName:        grmi.NewConditionItem(meta.SerialOrder_CustOrderId, grmi.Equal, false),
		meta.SerialOrder_FirstPieceInBatch.UrlParameterName:  grmi.NewConditionItem(meta.SerialOrder_FirstPieceInBatch, grmi.Equal, false),
		meta.SerialOrder_LastPieceInBatch.UrlParameterName:   grmi.NewConditionItem(meta.SerialOrder_LastPieceInBatch, grmi.Equal, false),
		meta.SerialOrder_PreSchedKey.UrlParameterName:        grmi.NewConditionItem(meta.SerialOrder_PreSchedKey, grmi.Equal, false),
		meta.SerialOrder_SchedKey.UrlParameterName:           grmi.NewConditionItem(meta.SerialOrder_SchedKey, grmi.Equal, false),
		meta.SerialOrder_Priority.UrlParameterName:           grmi.NewConditionItem(meta.SerialOrder_Priority, grmi.Equal, false),
		meta.SerialOrder_OrderType.UrlParameterName:          grmi.NewConditionItem(meta.SerialOrder_OrderType, grmi.Equal, false),
		meta.SerialOrder_OrderType1.UrlParameterName:         grmi.NewConditionItem(meta.SerialOrder_OrderType1, grmi.Equal, false),
		meta.SerialOrder_OrderType2.UrlParameterName:         grmi.NewConditionItem(meta.SerialOrder_OrderType2, grmi.Equal, false),
		meta.SerialOrder_PlanResourceId.UrlParameterName:     grmi.NewConditionItem(meta.SerialOrder_PlanResourceId, grmi.Equal, false),
		meta.SerialOrder_UsedResourceId.UrlParameterName:     grmi.NewConditionItem(meta.SerialOrder_UsedResourceId, grmi.Equal, false),
		meta.SerialOrder_PlanQty.UrlParameterName:            grmi.NewConditionItem(meta.SerialOrder_PlanQty, grmi.Equal, false),
		meta.SerialOrder_QtyUomId.UrlParameterName:           grmi.NewConditionItem(meta.SerialOrder_QtyUomId, grmi.Equal, false),
		meta.SerialOrder_OpTimePerItem.UrlParameterName:      grmi.NewConditionItem(meta.SerialOrder_OpTimePerItem, grmi.Equal, false),
		meta.SerialOrder_TimeUomId.UrlParameterName:          grmi.NewConditionItem(meta.SerialOrder_TimeUomId, grmi.Equal, false),
		meta.SerialOrder_PlanStartDate.UrlParameterName:      grmi.NewConditionItem(meta.SerialOrder_PlanStartDate, grmi.Approximate, false),
		meta.SerialOrder_PlanEndDate.UrlParameterName:        grmi.NewConditionItem(meta.SerialOrder_PlanEndDate, grmi.Approximate, false),
		meta.SerialOrder_SetupStartTime.UrlParameterName:     grmi.NewConditionItem(meta.SerialOrder_SetupStartTime, grmi.Approximate, false),
		meta.SerialOrder_SetupEndTime.UrlParameterName:       grmi.NewConditionItem(meta.SerialOrder_SetupEndTime, grmi.Approximate, false),
		meta.SerialOrder_PlanStartTime.UrlParameterName:      grmi.NewConditionItem(meta.SerialOrder_PlanStartTime, grmi.Approximate, false),
		meta.SerialOrder_PlanEndTime.UrlParameterName:        grmi.NewConditionItem(meta.SerialOrder_PlanEndTime, grmi.Approximate, false),
		meta.SerialOrder_ActStartTime.UrlParameterName:       grmi.NewConditionItem(meta.SerialOrder_ActStartTime, grmi.Approximate, false),
		meta.SerialOrder_ActEndTime.UrlParameterName:         grmi.NewConditionItem(meta.SerialOrder_ActEndTime, grmi.Approximate, false),
		meta.SerialOrder_PickingFlag.UrlParameterName:        grmi.NewConditionItem(meta.SerialOrder_PickingFlag, grmi.Equal, false),
		meta.SerialOrder_IsFirstPieceToggle.UrlParameterName: grmi.NewConditionItem(meta.SerialOrder_IsFirstPieceToggle, grmi.Equal, false),
		meta.SerialOrder_SyncKey.UrlParameterName:            grmi.NewConditionItem(meta.SerialOrder_SyncKey, grmi.Equal, false),
		meta.SerialOrder_BackFlushFlag.UrlParameterName:      grmi.NewConditionItem(meta.SerialOrder_BackFlushFlag, grmi.Equal, false),
		meta.SerialOrder_RepairFlag.UrlParameterName:         grmi.NewConditionItem(meta.SerialOrder_RepairFlag, grmi.Equal, false),
		meta.SerialOrder_CtrlPara1.UrlParameterName:          grmi.NewConditionItem(meta.SerialOrder_CtrlPara1, grmi.Equal, false),
		meta.SerialOrder_CtrlPara2.UrlParameterName:          grmi.NewConditionItem(meta.SerialOrder_CtrlPara2, grmi.Equal, false),
		meta.SerialOrder_CtrlStr1.UrlParameterName:           grmi.NewConditionItem(meta.SerialOrder_CtrlStr1, grmi.Equal, false),
		meta.SerialOrder_CtrlStr2.UrlParameterName:           grmi.NewConditionItem(meta.SerialOrder_CtrlStr2, grmi.Equal, false),
		meta.SerialOrder_QualityCheck.UrlParameterName:       grmi.NewConditionItem(meta.SerialOrder_QualityCheck, grmi.Equal, false),
		meta.SerialOrder_QualityCheckTime.UrlParameterName:   grmi.NewConditionItem(meta.SerialOrder_QualityCheckTime, grmi.Equal, false),
		meta.SerialOrder_MainOrderId.UrlParameterName:        grmi.NewConditionItem(meta.SerialOrder_MainOrderId, grmi.Equal, false),
		meta.SerialOrder_EOLCheck.UrlParameterName:           grmi.NewConditionItem(meta.SerialOrder_EOLCheck, grmi.Equal, false),
		meta.SerialOrder_CtrlTime1.UrlParameterName:          grmi.NewConditionItem(meta.SerialOrder_CtrlTime1, grmi.Approximate, false),
		meta.SerialOrder_CtrlTime2.UrlParameterName:          grmi.NewConditionItem(meta.SerialOrder_CtrlTime2, grmi.Approximate, false),
		meta.SerialOrder_LastModify.UrlParameterName:         grmi.NewConditionItem(meta.SerialOrder_LastModify, grmi.Approximate, false),
		meta.SerialOrder_LastUser.UrlParameterName:           grmi.NewConditionItem(meta.SerialOrder_LastUser, grmi.Equal, false),
		meta.SerialOrder_CreateTime.UrlParameterName:         grmi.NewConditionItem(meta.SerialOrder_CreateTime, grmi.Approximate, false),
	},
	nil,
)

/******************************************************************************
 *
 * @Description              : SerialOrder的默认分页查询条件
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-10-22 14:06:37
 *
 ******************************************************************************/
var DefaultConditionOfSerialOrderAndPaging = grmi.NewCondition(
	DefaultConditionOfSerialOrder.Items,
	grmi.NewPaging(),
)

/******************************************************************************
 *
 * @Struct Name              : SerialOrderServiceImplement
 *-----------------------------------------------------------------------------
 *
 * @Description              : SerialOrder的服务实现
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-10-22 14:06:37
 *
 ******************************************************************************/
type SerialOrderServiceImplement struct {
}

/******************************************************************************
 *
 * @Function Name            : NewSerialOrderDAOImplement
 *-----------------------------------------------------------------------------
 *
 * @Description              : 创建一个SerialOrderDAOImplement实例
 *
 * @Return Value             : SerialOrderDAOImplement实例
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-10-22 14:06:37
 *
 ******************************************************************************/
func NewSerialOrderServiceImplement() *SerialOrderServiceImplement {
	return &SerialOrderServiceImplement{}
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/om/SerialOrderService.InsertOne
 *
 ******************************************************************************/
func (impl *SerialOrderServiceImplement) InsertOne(user *global.User, entity *model.SerialOrder) error {

	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "InsertOneSerialOrder", "插入一个SerialOrder")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	if entity.OrderType != baseModel.ODER_TYPE_INTERVAL {
		return grmi.NewBusinessError("只允许创建内部订单")
	}
	entity.PlanQty = 1
	if err := session.Begin(); err != nil {
		return err
	}
	productDao := meDal.NewProductDAO(session, user.PlantNr, user.UserId)
	product, err := productDao.SelectOne(entity.ArtId, entity.ProjectId)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("查询产品数据失败, error:" + err.Error())
	}
	if product == nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("生产的产品不存在, 产品ID:" + entity.ArtId)
	}
	projectDao := meDal.NewProjectDAO(session, user.PlantNr, user.UserId)
	project, err := projectDao.SelectOne(entity.ProjectId)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("查询车型项目数据失败, error:" + err.Error())
	}
	if project == nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("车型项目数据不存在, 项目ID:" + entity.ProjectId)
	}
	if product.MultiWorkLineToggle {
		productWorkLineDao := meDal.NewProductWorkLineLstDAO(session, user.PlantNr, user.UserId)
		workLineLi, err := productWorkLineDao.Select([]grmi.Predicate{
			meMeta.ProductWorkLineLst_ProductId.NewPredicate(grmi.Equal, entity.ArtId),
			meMeta.ProductWorkLineLst_ProjectId.NewPredicate(grmi.Equal, entity.ProjectId),
		}, nil)
		if err != nil {
			return grmi.NewBusinessError("查询总成可生产产线失败, 错误:" + err.Error())
		}
		var canProduct bool
		for _, workLine := range workLineLi {
			if workLine.WorkLineId == entity.UsedResourceId {
				canProduct = true
				break
			}
		}
		if !canProduct {
			return grmi.NewBusinessError("该总成不能在指定的产线上生产！")
		}
	} else {
		if product.DefaultWorkLineId != entity.UsedResourceId {
			return grmi.NewBusinessError("该总成不能在指定的产线上生产！")
		}
	}
	dao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	statusDao := dal.NewSerialOrderStatusDAO(session, user.PlantNr, user.UserId)
	snrDao := baseDal.NewSnrDAO(session, user.PlantNr, user.UserId)
	//serialNumberStr, err := snrDao.GetNextSnr(project.SerialOrderSnr)
	//if err != nil {
	//	_ = session.Rollback()
	//	return grmi.NewBusinessError("生成工单流水号失败, error:" + err.Error())
	//}
	//serialNumber, err := strconv.Atoi(serialNumberStr)
	//if err != nil {
	//	_ = session.Rollback()
	//	return grmi.NewBusinessError("流水号规则错误, error:" + err.Error())
	//}
	//first := serialNumber / 34
	//if first > 34 {
	//	_ = session.Rollback()
	//	return grmi.NewBusinessError("超过流水号支持的范围")
	//}
	//second := serialNumber % 34
	//firstStr := baseModel.NUMBER_MAP[first]
	//secondStr := baseModel.NUMBER_MAP[second]
	//machineCode := product.MachineCode
	//now := time.Now()
	//year := now.Year()
	//month := int(now.Month())
	//day := now.Day()
	//yearStr := baseModel.YEAR_MAP[year]
	//monthStr := baseModel.MONTH_MAP[month]
	//dayStr := baseModel.DAY_MAP[day]
	//serialOrderId := machineCode + yearStr + monthStr + dayStr + firstStr + secondStr + "0" + product.ColorValue
	serialNumber, err := snrDao.GetNextSnr(project.INTSerialOrderSnr)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("生成工单流水号失败, error:" + err.Error())
	}
	serialOrderId := product.MachineCode + serialNumber + product.ProductType + product.ColorValue
	entity.SerialOrderId = serialOrderId
	err = dao.InsertOne(entity)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("写入工单数据失败, error:" + err.Error())
	}
	status := model.SerialOrderStatus{
		SerialOrderId: serialOrderId,
		Status:        baseModel.WO_STATUS_UNPLANNED,
	}
	err = statusDao.InsertOne(&status)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("插入工单状态失败, error:" + err.Error())
	}
	_ = session.Commit()
	return nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/om/SerialOrderService.DeleteOne
 *
 ******************************************************************************/
func (impl *SerialOrderServiceImplement) DeleteOne(user *global.User, serialOrderId string) error {

	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "DeleteOneSerialOrder", "删除一个SerialOrder")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	record, err := dao.SelectOne(serialOrderId)
	if err != nil {
		return err
	}
	if record == nil {
		return grmi.NewBusinessError("不存在指定记录!")
	}
	err = dao.DeleteOne(serialOrderId)
	if err != nil {
		return err
	}
	return nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/om/SerialOrderService.SelectOne
 *
 ******************************************************************************/
func (impl *SerialOrderServiceImplement) SelectOne(user *global.User, serialOrderId string) (*model.SerialOrder, error) {

	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "SelectOneSerialOrder", "查询一个SerialOrder")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	result, err := dao.SelectOne(serialOrderId)
	if err != nil {
		return nil, err
	}
	return result, nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/om/SerialOrderService.UpdateOne
 *
 ******************************************************************************/
func (impl *SerialOrderServiceImplement) UpdateOne(user *global.User, entity *model.SerialOrder) error {

	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "UpdateOneSerialOrder", "修改一个SerialOrder")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	if entity.OrderType != baseModel.ODER_TYPE_INTERVAL {
		return grmi.NewBusinessError("工单类型不允许修改")
	}
	dao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	record, err := dao.SelectOne(entity.SerialOrderId)
	if err != nil {
		return err
	}
	if record == nil {
		return grmi.NewBusinessError("不存在指定记录!")
	}
	if record.OrderType != baseModel.ODER_TYPE_INTERVAL {
		return grmi.NewBusinessError("当前工单不是内部工单，不允许修改, 工单ID:" + entity.SerialOrderId)
	}
	statusDao := dal.NewSerialOrderStatusDAO(session, user.PlantNr, user.UserId)
	serialOrderStatus, err := statusDao.SelectOne(entity.SerialOrderId)
	if err != nil {
		return grmi.NewBusinessError("查询工单状态失败, error:" + err.Error())
	}
	if serialOrderStatus == nil {
		return grmi.NewBusinessError("工单状态不存在, 工单ID:" + entity.SerialOrderId)
	}
	if serialOrderStatus.Status != baseModel.WO_STATUS_UNPLANNED {
		return grmi.NewBusinessError("工单状态不为未计划, 工单ID:" + entity.SerialOrderId)
	}
	err = dao.UpdateOne(entity)
	if err != nil {
		return err
	}

	return nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/om/SerialOrderService.Insert
 *
 ******************************************************************************/
func (impl *SerialOrderServiceImplement) Insert(user *global.User, entities *[]model.SerialOrder) error {

	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "InsertSerialOrder", "插入多个SerialOrder")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)

	for _, entity := range *entities {
		record, err := dao.SelectOne(entity.SerialOrderId)
		if err != nil {
			return err
		}
		if record != nil {
			return grmi.NewBusinessError("已经存在相同主键的记录!")
		}
	}

	err := dao.Insert(entities)
	if err != nil {
		return err
	}
	return nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/om/SerialOrderService.Delete
 *
 ******************************************************************************/
func (impl *SerialOrderServiceImplement) Delete(user *global.User, entities *[]model.SerialOrder) error {

	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "DeleteSerialOrder", "删除多个SerialOrder")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)

	for _, entity := range *entities {
		record, err := dao.SelectOne(entity.SerialOrderId)
		if err != nil {
			return err
		}
		if record == nil {
			return grmi.NewBusinessError("不存在指定记录!")
		}
	}

	err := dao.Delete(entities)
	if err != nil {
		return err
	}
	return nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/om/SerialOrderService.Select
 *
 ******************************************************************************/
func (impl *SerialOrderServiceImplement) Select(user *global.User, urlParameters map[string]string) ([]model.SerialOrder, error) {

	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "SelectSerialOrder", "查询SerialOrder")

	condition := DefaultConditionOfSerialOrderAndPaging
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	predicates, err := condition.BuildPredicates(urlParameters)
	if err != nil {
		return nil, err
	}
	dao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	result, err := dao.Select(predicates, condition.OrderByFields)
	if err != nil {
		return nil, err
	}
	return result, nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/om/SerialOrderService.SelectAndPaging
 *
 ******************************************************************************/
func (impl *SerialOrderServiceImplement) SelectAndPaging(user *global.User, urlParameters map[string]string) (grmi.PagingResult, error) {

	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "SelectSerialOrder", "查询SerialOrder")

	condition := DefaultConditionOfSerialOrderAndPaging
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	predicates, err := condition.BuildPredicates(urlParameters)
	if err != nil {
		return grmi.EmptyPagingResult, err
	}
	dao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	condition.Fill(urlParameters)
	result, err := dao.SelectAndPaging(condition.Paging, predicates, condition.OrderByFields)
	if err != nil {
		return grmi.EmptyPagingResult, err
	}
	return result, nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/om/SerialOrderService.Update
 *
 ******************************************************************************/
func (impl *SerialOrderServiceImplement) Update(user *global.User, entities *[]model.SerialOrder) error {

	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "UpdateSerialOrder", "修改多个SerialOrder")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)

	for _, entity := range *entities {
		record, err := dao.SelectOne(entity.SerialOrderId)
		if err != nil {
			return err
		}
		if record == nil {
			return grmi.NewBusinessError("不存在指定记录!")
		}
	}

	err := dao.Update(entities)
	if err != nil {
		return err
	}
	return nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/om/SerialOrderService.CancelSerialOrder
 *
 ******************************************************************************/
func (impl *SerialOrderServiceImplement) CancelSerialOrder(user *global.User, serialOrderId string) error {

	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "CancelSerialOrder", "取消一个SerialOrder")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	record, err := dao.SelectOne(serialOrderId)
	if err != nil {
		return err
	}
	if record == nil {
		return grmi.NewBusinessError("不存在指定记录!")
	}
	if record.OrderType != baseModel.ODER_TYPE_INTERVAL {
		return grmi.NewBusinessError("工单不是内部工单，不允许取消, 工单ID:" + serialOrderId)
	}
	statusDao := dal.NewSerialOrderStatusDAO(session, user.PlantNr, user.UserId)
	status, err := statusDao.SelectOne(serialOrderId)
	if err != nil {
		return grmi.NewBusinessError("查询工单状态数据失败, error:" + err.Error())
	}
	if status == nil {
		return grmi.NewBusinessError("工单状态数据不存在, 工单ID:" + serialOrderId)
	}
	originStatus := status.Status
	if status.Status != baseModel.WO_STATUS_UNPLANNED && status.Status != baseModel.WO_STATUS_RELEASED {
		return grmi.NewBusinessError("工单状态不是未计划, 不允许取消, 工单ID：" + serialOrderId)
	}
	preSerialOrderLi, err := dao.Select([]grmi.Predicate{
		meta.SerialOrder_OrderType.NewPredicate(grmi.Equal, baseModel.ORDER_TYPE_PRE),
		meta.SerialOrder_GenerateFlag.NewPredicate(grmi.Equal, 0),
		meta.SerialOrder_MainOrderId.NewPredicate(grmi.Equal, serialOrderId),
	}, nil)
	if err != nil {
		return grmi.NewBusinessError("查询工单下的预装工单失败, 错误：" + err.Error())
	}
	for _, preOrder := range preSerialOrderLi {
		if preOrder.SerialOrderStatus.Status > baseModel.WO_STATUS_RELEASED {
			return grmi.NewBusinessError("预装工单已经不允许取消, 工单ID:" + preOrder.SerialOrderId)
		}
	}
	if err := session.Begin(); err != nil {
		return err
	}
	statusRecDao := dal.NewSerialOrderStatusRecLstDAO(session, user.PlantNr, user.UserId)
	serialOrderPOLstDao := dal.NewSerialOrderPOLstDAO(session, user.PlantNr, user.UserId)
	serialOrderStepDao := dal.NewSerialOrderStepLstDAO(session, user.PlantNr, user.UserId)
	serialOrderOPDetailDao := dal.NewSerialOrderOPDetailDAO(session, user.PlantNr, user.UserId)
	statusRec := model.SerialOrderStatusRecLst{
		SerialOrderId: serialOrderId,
		Status:        baseModel.WO_STATUS_CANCELED,
		PrevStatus:    status.Status,
	}
	status.Status = baseModel.WO_STATUS_CANCELED
	err = statusRecDao.InsertOne(&statusRec)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("插入工单状态变更记录失败, error:" + err.Error())
	}
	err = statusDao.UpdateOne(status)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新工单状态失败， error:" + err.Error())
	}
	if originStatus == baseModel.WO_STATUS_RELEASED {
		poUpdateData := &model.SerialOrderPOLst{
			Status: baseModel.WO_STATUS_CANCELED,
		}
		err = serialOrderPOLstDao.UpdateWhere([]grmi.Predicate{meta.SerialOrderPOLst_SerialOrderId.NewPredicate(grmi.Equal, serialOrderId)}, poUpdateData, meta.SerialOrderPOLst_Status.Name)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新工单工序状态失败, error:" + err.Error())
		}
		stepUpdateData := &model.SerialOrderStepLst{
			Status: baseModel.WO_STATUS_CANCELED,
		}
		err = serialOrderStepDao.UpdateWhere([]grmi.Predicate{meta.SerialOrderStepLst_SerialOrderId.NewPredicate(grmi.Equal, serialOrderId)}, stepUpdateData, meta.SerialOrderStepLst_Status.Name)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新工单工步状态失败, error:" + err.Error())
		}
		opDetailUpdateData := &model.SerialOrderOPDetail{
			Status: baseModel.WO_STATUS_CANCELED,
		}
		err = serialOrderOPDetailDao.UpdateWhere([]grmi.Predicate{meta.SerialOrderOPDetail_SerialOrderId.NewPredicate(grmi.Equal, serialOrderId)}, opDetailUpdateData, meta.SerialOrderOPDetail_Status.Name)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新工单详细操作状态失败, error:" + err.Error())
		}
	}
	// 取消预装工单
	for _, preOrder := range preSerialOrderLi {
		originStatus = preOrder.SerialOrderStatus.Status
		statusRec = model.SerialOrderStatusRecLst{
			SerialOrderId: preOrder.SerialOrderId,
			Status:        baseModel.WO_STATUS_CANCELED,
			PrevStatus:    preOrder.SerialOrderStatus.Status,
		}
		preOrder.SerialOrderStatus.Status = baseModel.WO_STATUS_CANCELED
		err = statusRecDao.InsertOne(&statusRec)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("插入预装工单状态变更记录失败, error:" + err.Error())
		}
		err = statusDao.UpdateOne(&preOrder.SerialOrderStatus)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新预装工单状态失败， error:" + err.Error())
		}
		if originStatus == baseModel.WO_STATUS_RELEASED {
			poUpdateData := &model.SerialOrderPOLst{
				Status: baseModel.WO_STATUS_CANCELED,
			}
			err = serialOrderPOLstDao.UpdateWhere([]grmi.Predicate{meta.SerialOrderPOLst_SerialOrderId.NewPredicate(grmi.Equal, preOrder.SerialOrderId)}, poUpdateData, meta.SerialOrderPOLst_Status.Name)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("更新预装工单工序状态失败, error:" + err.Error())
			}
			stepUpdateData := &model.SerialOrderStepLst{
				Status: baseModel.WO_STATUS_CANCELED,
			}
			err = serialOrderStepDao.UpdateWhere([]grmi.Predicate{meta.SerialOrderStepLst_SerialOrderId.NewPredicate(grmi.Equal, preOrder.SerialOrderId)}, stepUpdateData, meta.SerialOrderStepLst_Status.Name)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("更新预装工单工步状态失败, error:" + err.Error())
			}
			opDetailUpdateData := &model.SerialOrderOPDetail{
				Status: baseModel.WO_STATUS_CANCELED,
			}
			err = serialOrderOPDetailDao.UpdateWhere([]grmi.Predicate{meta.SerialOrderOPDetail_SerialOrderId.NewPredicate(grmi.Equal, preOrder.SerialOrderId)}, opDetailUpdateData, meta.SerialOrderOPDetail_Status.Name)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("更新预装工单详细操作状态失败, error:" + err.Error())
			}
		}
	}
	_ = session.Commit()
	return nil
}

// ExtractArtId 从Bom数据结构中提取需要的每种物料数量
func (impl *SerialOrderServiceImplement) ExtractArtId(bomHead *meModel.BomHead) map[string]int {
	artMap := make(map[string]int)
	bomLstLi := bomHead.BomLstLi
	for _, bomLst := range bomLstLi {
		_, exist := artMap[bomLst.CmatNr]
		if exist {
			artMap[bomLst.CmatNr] += int(bomLst.CmatQty / bomLst.FmatQty)
		} else {
			artMap[bomLst.CmatNr] = int(bomLst.CmatQty / bomLst.FmatQty)
		}
	}
	return artMap
}


// SelectSortOrder 查询排序工单页的已排序的工单
func (impl *SerialOrderServiceImplement) SelectSortOrder(user *global.User, urlParameters map[string]string) (grmi.PagingResult, error) {
	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "SelectSortOrder", "查询已排序订单")
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	var err error
	resourceId, exist := urlParameters["resourceId"]
	if !exist {
		return grmi.EmptyPagingResult, grmi.NewBusinessError("未选择查询的产线")
	}
	planDate := urlParameters["planDate"]
	statusStr := urlParameters["status"]
	seqStartStr := urlParameters["seqStart"]
	seqEndStr := urlParameters["seqEnd"]
	custOrderId := urlParameters["custOrderId"]
	serialOrderId := urlParameters["serialOrderId"]
	status, err := strconv.Atoi(statusStr)
	if err != nil {
		status = 0
	}
	var seqStart, seqEnd int
	seqStart, err = strconv.Atoi(seqStartStr)
	if err != nil {
		seqStart = 0
	}
	seqEnd, err = strconv.Atoi(seqEndStr)
	if err != nil {
		seqEnd = 0
	}
	var pageNumber, pageSize int64
	pageNumberStr, exist := urlParameters["pageNumber"]
	if !exist {
		pageNumber = 1
	} else {
		pageNumber, err = strconv.ParseInt(pageNumberStr, 0, 10)
		if err != nil {
			pageNumber = 1
		}
	}
	pageSizeStr, exist := urlParameters["pageSize"]
	if !exist {
		pageSize = 10
	} else {
		pageSize, err = strconv.ParseInt(pageSizeStr, 0, 10)
		if err != nil {
			pageSize = 10
		}
	}
	dao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	result, err := dao.SelectOrderByResource(resourceId, status, planDate, seqStart, seqEnd, custOrderId, serialOrderId, true, false, pageNumber, pageSize)
	return result, err
}

// SelectUnSortOrder 查询排序工单页的未排序的工单
func (impl *SerialOrderServiceImplement) SelectUnSortOrder(user *global.User, urlParameters map[string]string) (grmi.PagingResult, error) {
	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "SelectUnSortOrder", "查询未排序订单")
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	var err error
	resourceId, exist := urlParameters["resourceId"]
	if !exist {
		return grmi.EmptyPagingResult, grmi.NewBusinessError("未选择查询的产线")
	}
	serialOrderId := urlParameters["serialOrderId"]
	var pageNumber, pageSize int64
	pageNumberStr, exist := urlParameters["pageNumber"]
	if !exist {
		pageNumber = 1
	} else {
		pageNumber, err = strconv.ParseInt(pageNumberStr, 0, 10)
		if err != nil {
			pageNumber = 1
		}
	}
	pageSizeStr, exist := urlParameters["pageSize"]
	if !exist {
		pageSize = 10
	} else {
		pageSize, err = strconv.ParseInt(pageSizeStr, 0, 10)
		if err != nil {
			pageSize = 10
		}
	}
	dao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	result, err := dao.SelectOrderByResource(resourceId, 0, "", 0, 0, "", serialOrderId, false, false, pageNumber, pageSize)
	return result, err
}

// SelectUrgencyOrder 查询排序工单页的紧急工单
func (impl *SerialOrderServiceImplement) SelectUrgencyOrder(user *global.User, urlParameters map[string]string) (grmi.PagingResult, error) {
	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "SelectUrgencyOrder", "查询紧急订单")
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	var err error
	resourceId, exist := urlParameters["resourceId"]
	if !exist {
		return grmi.EmptyPagingResult, grmi.NewBusinessError("未选择查询的产线")
	}
	var pageNumber, pageSize int64
	pageNumberStr, exist := urlParameters["pageNumber"]
	if !exist {
		pageNumber = 1
	} else {
		pageNumber, err = strconv.ParseInt(pageNumberStr, 0, 10)
		if err != nil {
			pageNumber = 1
		}
	}
	pageSizeStr, exist := urlParameters["pageSize"]
	if !exist {
		pageSize = 10
	} else {
		pageSize, err = strconv.ParseInt(pageSizeStr, 0, 10)
		if err != nil {
			pageSize = 10
		}
	}
	dao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	result, err := dao.SelectOrderByResource(resourceId, 0, "", 0, 0, "", "", false, true, pageNumber, pageSize)
	return result, err
}

// ChangeOrderToUrgency 将工单放到紧急工单队列中
func (impl *SerialOrderServiceImplement) ChangeOrderToUrgency(user *global.User, serialOrderId string, priority int) (err error) {
	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "ChangeOrderToUrgency", "将未计划的工单放到紧急工单队列中")
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	if priority == 0 {
		return grmi.NewBusinessError("未设置优先级")
	}
	dao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	statusDao := dal.NewSerialOrderStatusDAO(session, user.PlantNr, user.UserId)
	statusRecDao := dal.NewSerialOrderStatusRecLstDAO(session, user.PlantNr, user.UserId)
	serialOrder, err := dao.SelectOne(serialOrderId)
	if err != nil {
		return grmi.NewBusinessError("查询工单数据失败, error:" + err.Error())
	}
	if serialOrder == nil {
		return grmi.NewBusinessError("不存在对应的工单， 工单ID:" + serialOrderId)
	}
	serialOrderStatus, err := statusDao.SelectOne(serialOrderId)
	if err != nil {
		return grmi.NewBusinessError("查询工单的状态失败, error:" + err.Error())
	}
	if serialOrderStatus == nil {
		return grmi.NewBusinessError("工单状态数据不存在, 工单ID:" + serialOrderId)
	}
	if serialOrderStatus.Status != baseModel.WO_STATUS_UNPLANNED {
		return grmi.NewBusinessError("工单的状态不是未计划, 工单ID:" + serialOrderId)
	}
	if err := session.Begin(); err != nil {
		return err
	}
	serialOrder.Priority = priority
	serialOrder.PlanStartDate = grmi.Date(time.Now())
	serialOrder.PlanEndDate = grmi.Date(time.Now())
	serialOrder.PlanStartTime = grmi.DateTime(time.Now())
	serialOrder.PlanEndTime = grmi.DateTime(time.Now())
	err = dao.UpdateOne(serialOrder)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新工单数据失败, error:" + err.Error())
	}

	serialOrderStatus.Status = baseModel.WO_STATUS_LOCKED
	err = statusDao.UpdateOne(serialOrderStatus)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新工单状态失败, error:")
	}
	statusRec := model.SerialOrderStatusRecLst{
		SerialOrderId: serialOrderId,
		Status:        baseModel.WO_STATUS_LOCKED,
		PrevStatus:    baseModel.WO_STATUS_UNPLANNED,
	}
	err = statusRecDao.InsertOne(&statusRec)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("插入工单状态变更记录失败, error:" + err.Error())
	}
	_ = session.Commit()
	return nil
}

// WithdrawSerialOrder 撤回已计划的内部订单
func (impl *SerialOrderServiceImplement) WithdrawSerialOrder(user *global.User, serialOrderId string, source string) (err error) {
	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "WithdrawSerialOrder", "撤回已计划的内部订单")
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	if err := session.Begin(); err != nil {
		return err
	}
	serialOrderDao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	serialOrder, err := serialOrderDao.SelectOne(serialOrderId)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("查询工单失败, error:" + err.Error())
	}
	if serialOrder == nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("工单不存在， 工单ID:" + serialOrderId)
	}
	if source == "urgency" {
		if serialOrder.Priority == 0 {
			_ = session.Rollback()
			return grmi.NewBusinessError("该工单不是紧急队列中的工单")
		}
	}
	serialOrder.Priority = 0
	serialOrder.PlanStartDate = grmi.Date{}
	serialOrder.PlanEndDate = grmi.Date{}
	serialOrder.PlanStartTime = grmi.DateTime{}
	serialOrder.PlanEndTime = grmi.DateTime{}
	serialOrder.SchedKey = 0
	err = serialOrderDao.UpdateOne(serialOrder)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新工单数据失败， error:" + err.Error())
	}
	statusDao := dal.NewSerialOrderStatusDAO(session, user.PlantNr, user.UserId)
	statusRecDao := dal.NewSerialOrderStatusRecLstDAO(session, user.PlantNr, user.UserId)
	serialOrderStatus, err := statusDao.SelectOne(serialOrderId)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("查询工单的状态失败, error:" + err.Error())
	}
	if serialOrderStatus == nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("工单状态数据不存在, 工单ID:" + serialOrderId)
	}

	if serialOrderStatus.Status != baseModel.WO_STATUS_LOCKED {
		_ = session.Rollback()
		return grmi.NewBusinessError("工单的状态不是已锁定, 工单ID:" + serialOrderId)
	}

	serialOrderStatus.Status = baseModel.WO_STATUS_UNPLANNED
	err = statusDao.UpdateOne(serialOrderStatus)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新工单状态失败, error:")
	}
	statusRec := model.SerialOrderStatusRecLst{
		SerialOrderId: serialOrderId,
		Status:        baseModel.WO_STATUS_UNPLANNED,
		PrevStatus:    baseModel.WO_STATUS_LOCKED,
	}
	err = statusRecDao.InsertOne(&statusRec)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("插入工单状态变更记录失败, error:" + err.Error())
	}
	_ = session.Commit()
	return nil
}

// PutIntSerialOrderToSeq 将未排序的内部订单放入放排序队列
func (impl *SerialOrderServiceImplement) PutIntSerialOrderToSeq(user *global.User, serialOrderId string, preSchedKey int64) error {
	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "PutIntSerialOrderToSeq", "将内部订单放入到排序队列中")
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	if err := session.Begin(); err != nil {
		return err
	}
	dao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	serialOrder, err := dao.SelectOne(serialOrderId)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("查询工单数据失败, error:" + err.Error())
	}
	if serialOrder == nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("工单数据不存在, 工单ID:" + err.Error())
	}
	if serialOrder.OrderType != baseModel.ODER_TYPE_INTERVAL {
		_ = session.Rollback()
		return grmi.NewBusinessError("工单不是内部订单,不支持该操作")
	}
	serialOrder.PlanStartDate = grmi.Date(time.Now())
	serialOrder.PlanEndDate = grmi.Date(time.Now())
	serialOrder.PlanStartTime = grmi.DateTime(time.Now())
	serialOrder.PlanEndTime = grmi.DateTime(time.Now())
	err = dao.UpdateOne(serialOrder)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新工单数据失败, error:" + err.Error())
	}
	statusDao := dal.NewSerialOrderStatusDAO(session, user.PlantNr, user.UserId)
	statusRecDao := dal.NewSerialOrderStatusRecLstDAO(session, user.PlantNr, user.UserId)
	serialOrderStatus, err := statusDao.SelectOne(serialOrderId)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("查询工单的状态失败, error:" + err.Error())
	}
	if serialOrderStatus == nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("工单状态数据不存在, 工单ID:" + serialOrderId)
	}
	if serialOrderStatus.Status != baseModel.WO_STATUS_UNPLANNED {
		_ = session.Rollback()
		return grmi.NewBusinessError("工单的状态不是未计划, 工单ID:" + serialOrderId)
	}
	schedKey := preSchedKey + 1
	serialOrderLi, err := dao.Select([]grmi.Predicate{meta.SerialOrder_PlanResourceId.NewPredicate(grmi.Equal, serialOrder.PlanResourceId), meta.SerialOrder_SchedKey.NewPredicate(grmi.Equal, schedKey)}, nil)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("查询工单数据失败， error:" + err.Error())
	}
	if len(serialOrderLi) != 0 {
		_ = session.Rollback()
		return grmi.NewBusinessError("该PreSchedKey之后已存在紧连接的工单, 请调整")
	}
	serialOrder.SchedKey = schedKey
	err = dao.UpdateOne(serialOrder)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新工单数据失败, error:" + err.Error())
	}
	serialOrderStatus.Status = baseModel.WO_STATUS_LOCKED
	err = statusDao.UpdateOne(serialOrderStatus)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新工单状态数据失败， error:" + err.Error())
	}
	statusRec := model.SerialOrderStatusRecLst{
		SerialOrderId: serialOrderId,
		PrevStatus:    baseModel.WO_STATUS_UNPLANNED,
		Status:        baseModel.WO_STATUS_LOCKED,
	}
	err = statusRecDao.InsertOne(&statusRec)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("插入工单状态变更记录失败, error:" + err.Error())
	}
	_ = session.Commit()
	return nil
}

// ChangeOrderSchedKey 已排序的内部订单调整schedKey
func (impl *SerialOrderServiceImplement) ChangeOrderSchedKey(user *global.User, serialOrderId string, schedKey int64) error {
	grmi.Log(user, "/services/om/implments/SerialOrder.service.impl.go", "ChangeOrderSchedKey", "已排序的内部订单调整schedKey")
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	serialOrder, err := dao.SelectOne(serialOrderId)
	if err != nil {
		return grmi.NewBusinessError("查询工单数据失败, error:" + err.Error())
	}
	if serialOrder == nil {
		return grmi.NewBusinessError("工单数据不存在, 工单ID:" + err.Error())
	}
	if serialOrder.OrderType != baseModel.ODER_TYPE_INTERVAL {
		return grmi.NewBusinessError("工单不是内部订单,不支持该操作")
	}
	statusDao := dal.NewSerialOrderStatusDAO(session, user.PlantNr, user.UserId)
	serialOrderStatus, err := statusDao.SelectOne(serialOrderId)
	if err != nil {
		return grmi.NewBusinessError("查询工单的状态失败, error:" + err.Error())
	}
	if serialOrderStatus == nil {
		return grmi.NewBusinessError("工单状态数据不存在, 工单ID:" + serialOrderId)
	}
	if serialOrderStatus.Status != baseModel.WO_STATUS_LOCKED {
		return grmi.NewBusinessError("工单的状态不是已锁定, 工单ID:" + serialOrderId)
	}
	serialOrderLi, err := dao.Select([]grmi.Predicate{meta.SerialOrder_ProjectId.NewPredicate(grmi.Equal, serialOrder.ProjectId), meta.SerialOrder_SchedKey.NewPredicate(grmi.Equal, schedKey)}, nil)
	if err != nil {
		return grmi.NewBusinessError("查询工单数据失败， error:" + err.Error())
	}
	if len(serialOrderLi) != 0 {
		return grmi.NewBusinessError("已存在该SchedKey的工单, 请调整")
	}
	serialOrder.SchedKey = schedKey
	err = dao.UpdateOne(serialOrder)
	if err != nil {
		return grmi.NewBusinessError("更新工单数据失败, error:" + err.Error())
	}
	_ = session.Commit()
	return nil
}

// GetOrderPOLi 获取工序所有的前序
func (impl *SerialOrderServiceImplement) GetOrderPOLi(poData baseModel.Process, allPoMap map[string]baseModel.Process) []baseModel.Process {
	prePoLi := strings.Split(poData.PrePO, ",")
	prePoDataLi := make([]baseModel.Process, 0, len(prePoLi))
	for _, poId := range prePoLi {
		prePoData, exist := allPoMap[poId]
		if exist {
			prePoDataLi = append(prePoDataLi, prePoData)
			if prePoData.PrePO != "" {
				innerPrePoDataLi := impl.GetOrderPOLi(prePoData, allPoMap)
				prePoDataLi = append(prePoDataLi, innerPrePoDataLi...)
			}
		}
	}
	return prePoDataLi
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/om/SerialOrderService.GetSerialOrderOperationData
 *
 ******************************************************************************/
func (impl *SerialOrderServiceImplement) GetSerialOrderOperationData(user *global.User, serialOrderId string) (interface{}, error) {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	// 1. 查询工单
	// 2. 通过工单查询生产的产线
	// 3. 通过产线查询末序之外的工序列表
	// 4. 通过工序查询当前工序生成工步结果
	serialOrderDao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	serialOrderPoDao := dal.NewSerialOrderPOLstDAO(session, user.PlantNr, user.UserId)
	serialOrder, err := serialOrderDao.SelectOne(serialOrderId)
	if err != nil {
		return nil, grmi.NewBusinessError("查询工单失败, error:" + err.Error())
	}
	if serialOrder == nil {
		return nil, grmi.NewBusinessError("工单不存在, 工单ID:" + serialOrderId)
	}
	var traceOrderId string
	if serialOrder.OriginSerialOrderId != "" {
		traceOrderId = serialOrder.OriginSerialOrderId
	} else {
		traceOrderId = serialOrder.SerialOrderId
	}
	articleDao := baseDal.NewArticleDAO(session, user.PlantNr, user.UserId)
	article, err := articleDao.SelectOne(serialOrder.ArtId, serialOrder.ProjectId)
	if err != nil {
		return nil, grmi.NewBusinessError("查询工单总成数据失败, error:" + err.Error())
	}
	if article == nil {
		return nil, grmi.NewBusinessError("工单绑定总成不存在, 总成ID:" + serialOrder.ArtId)
	}
	poDataLi, err := serialOrderPoDao.SelectWithPO(traceOrderId, serialOrder.UsedResourceId)
	if err != nil {
		return nil, grmi.NewBusinessError("查询工单工序操作数据失败, error:" + err.Error())
	}
	var result model.TraceData
	result.Status = true
	result.BarCode = serialOrderId
	result.IsFirstPiece = serialOrder.IsFirstPieceToggle
	result.Desc = article.Descr1
	displayPoLi := make([]string, 0)
	poStatusMap := make(map[string]string)
	for _, poData := range poDataLi {
		displayPoLi = append(displayPoLi, poData.Process.PO)
		if poData.Status == baseModel.WO_STATUS_FINISHED {
			poStatusMap[poData.Process.PO] = "成功"
		} else {
			poStatusMap[poData.Process.PO] = "失败"
			result.Status = false
		}
	}

	// 查询工序关联的所有工位
	processWorkPlaceDao := baseDal.NewProcessWorkPlaceLstDAO(session, user.PlantNr, user.UserId)
	relateWorkPlaceLi, err := processWorkPlaceDao.SelectByProcess(displayPoLi)
	if err != nil {
		return nil, grmi.NewBusinessError("查询工序关联的工位失败, error:" + err.Error())
	}
	workPlaceMap := make(map[int]string)
	ignorePOMap := make(map[string]interface{})
	for _, relateDate := range relateWorkPlaceLi {
		if relateDate.WorkPlace.TriggerFrom == baseModel.TRIGGER_FROM_PICKING {
			ignorePOMap[relateDate.ProcessWorkPlaceLst.PO] = nil
		}
		workPlaceMap[relateDate.WorkPlace.WorkPlaceNr] = relateDate.WorkPlace.WorkPlaceId
	}
	//stepDao := dal.NewSerialOrderStepLstDAO(session, user.PlantNr, user.UserId)
	//poIdLiInterface := make([]interface{}, 0, len(displayPoLi))
	selectPoIdLi := make([]string, 0, len(displayPoLi))
	for _, poId := range displayPoLi {
		_, exist := ignorePOMap[poId]
		if exist {
			continue
		}
		//poIdLiInterface = append(poIdLiInterface, poId)
		selectPoIdLi = append(selectPoIdLi, poId)
	}

	//stepLi, err := stepDao.Select([]grmi.Predicate{meta.SerialOrderStepLst_SerialOrderId.NewPredicate(grmi.Equal, serialOrderId), meta.SerialOrderStepLst_PO.NewPredicate(grmi.Include, poIdLiInterface...)}, nil)
	//if err != nil {
	//	return nil, grmi.NewBusinessError("查询工单工步数据失败, error:" + err.Error())
	//}

	//for _, step := range stepLi {
	//	if step.Status != baseModel.WO_STATUS_FINISHED {
	//		result.Status = false
	//	}
	//}
	//poDataLi, err := serialOrderPoDao.Select([]grmi.Predicate{meta.SerialOrderPOLst_SerialOrderId.NewPredicate(grmi.Equal, serialOrderId), meta.SerialOrderPOLst_PO.NewPredicate(grmi.Include, poIdLiInterface...)}, nil)
	//if err != nil {
	//	return nil, grmi.NewBusinessError("查询工单工序操作数据失败, error:" + err.Error())
	//}

	articleAtocdDao := baseDal.NewArticleAtcodLstDAO(session, user.PlantNr, user.UserId)
	var needEOL bool
	var needSBR bool
	attributeLi, err := articleAtocdDao.SelectByArtId(serialOrder.ArtId)
	if err != nil {
		return nil, grmi.NewBusinessError("查询总成关联属性失败, error:" + err.Error())
	}
	for _, attributeItem := range attributeLi {
		if attributeItem.Attribute.Descr == "EOL" {
			needEOL = true
		} else if attributeItem.Attribute.Descr == "SBR检测" {
			needSBR = true
		}
	}
	// 通过工序和工单ID查询工步操作结果
	opDao := dal.NewSerialOrderOPDetailRecvDataLstDAO(session, user.PlantNr, user.UserId)
	result.IsFirstPiece = serialOrder.IsFirstPieceToggle
	result.TraceDataTraceData = make([]model.POOperationData, 0)
	for _, poId := range selectPoIdLi {
		opLi, err := opDao.GetOpRecvDataByPO(traceOrderId, poId)
		if err != nil {
			return nil, grmi.NewBusinessError("查询工艺操作数据失败, error:" + err.Error())
		}
		var poOperationData model.POOperationData
		poOperationData.PO = poId
		poOperationData.Status = poStatusMap[poId]
		poOperationData.RecvDataLi = make([]model.RecvDataItem, 0)
		var preOperationId int
		var preOriginPos int
		for index, opData := range opLi {
			if index == 0 {
				preOperationId = opData.Operation.OperationId
				preOriginPos = opData.SerialOrderOPDetailRecvDataLst.OriginPos
			} else {
				if preOperationId == opData.Operation.OperationId && preOriginPos == opData.SerialOrderOPDetailRecvDataLst.OriginPos {
					poOperationData.RecvDataLi = poOperationData.RecvDataLi[:len(poOperationData.RecvDataLi)-1]
				}
			}
			preOperationId = opData.Operation.OperationId
			preOriginPos = opData.SerialOrderOPDetailRecvDataLst.OriginPos
			var operationDesc string
			if opData.SerialOrderOPDetail.StepType == baseModel.STEP_OPC_RULE {
				operationDesc = opData.OPCComRule.DBlockDesc
			} else if opData.SerialOrderOPDetail.StepType == baseModel.STEP_TW_RULE {
				operationDesc = opData.TightenWrenchRuleInfo.StepDesc
			} else {
				operationDesc = opData.Operation.StepDesc
			}
			var status string
			if opData.SerialOrderOPDetailRecvDataLst.Status == 1 {
				status = "成功"
			} else {
				status = "失败"
			}
			recvData := model.RecvDataItem{
				SerialOrderId: opData.SerialOrderOPDetailRecvDataLst.SerialOrderId,
				ArtId:         opData.SerialOrderOPDetailRecvDataLst.SubArtId,
				PO:            opData.SerialOrderOPDetailRecvDataLst.PO,
				OperationDesc: operationDesc,
				RecvData:      opData.SerialOrderOPDetailRecvDataLst.RecvData,
				Status:        status,
				Remark1:       opData.SerialOrderOPDetailRecvDataLst.Remark1,
				ExecuteTime:   opData.SerialOrderOPDetailRecvDataLst.CreateTime.ToString(),
			}
			poOperationData.RecvDataLi = append(poOperationData.RecvDataLi, recvData)
		}
		result.TraceDataTraceData = append(result.TraceDataTraceData, poOperationData)
	}
	if needEOL {
		// 电检 主驾和副驾需要查询EOLDR 和 EOLPA 两张表 后排 查询EOLBR
		eolStatus, remark, recordTime, err := impl.ExtractEOL(session, user, serialOrder)
		if err != nil {
			return nil, err
		}
		var poOperationData model.POOperationData
		poOperationData.PO = "电检"
		if eolStatus {
			poOperationData.Status = "成功"
		} else {
			poOperationData.Status = "失败"
		}
		recvData := model.RecvDataItem{
			SerialOrderId: serialOrderId,
			ArtId:         "",
			PO:            "EOL",
			OperationDesc: "电检",
			Status:        poOperationData.Status,
			RecvData:      "",
			Remark1:       remark,
			ExecuteTime:   recordTime.Format(grmi.DateTimeOutFormat),
		}

		poOperationData.RecvDataLi = append(poOperationData.RecvDataLi, recvData)
		result.TraceDataTraceData = append(result.TraceDataTraceData, poOperationData)
		if eolStatus {
			serialOrder.EOLCheck = model.EOL_STATUS_OK
		} else {
			serialOrder.EOLCheck = model.EOL_STATUS_NG
		}
		err = serialOrderDao.UpdateOne(serialOrder)
		if err != nil {
			return nil, grmi.NewBusinessError("将电检结果保存到工单上失败, 错误:" + err.Error())
		}
	}
	if needSBR {

	}
	return result, nil
}

// CancelMultiSerialOrder 批量取消工单
func (impl *SerialOrderServiceImplement) CancelMultiSerialOrder(user *global.User, serialOrderIdLi []string) error {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	statusRecDao := dal.NewSerialOrderStatusRecLstDAO(session, user.PlantNr, user.UserId)
	serialOrderPOLstDao := dal.NewSerialOrderPOLstDAO(session, user.PlantNr, user.UserId)
	serialOrderStepDao := dal.NewSerialOrderStepLstDAO(session, user.PlantNr, user.UserId)
	serialOrderOPDetailDao := dal.NewSerialOrderOPDetailDAO(session, user.PlantNr, user.UserId)
	for _, serialOrderId := range serialOrderIdLi {
		record, err := dao.SelectOne(serialOrderId)
		if err != nil {
			return err
		}
		if record == nil {
			return grmi.NewBusinessError("不存在指定记录!")
		}
		if record.OrderType != baseModel.ODER_TYPE_INTERVAL {
			return grmi.NewBusinessError("工单不是内部工单，不允许取消, 工单ID:" + serialOrderId)
		}
		statusDao := dal.NewSerialOrderStatusDAO(session, user.PlantNr, user.UserId)
		status, err := statusDao.SelectOne(serialOrderId)
		if err != nil {
			return grmi.NewBusinessError("查询工单状态数据失败, error:" + err.Error())
		}
		if status == nil {
			return grmi.NewBusinessError("工单状态数据不存在, 工单ID:" + serialOrderId)
		}
		originStatus := status.Status
		if status.Status > baseModel.WO_STATUS_RELEASED {
			return grmi.NewBusinessError("工单已经进行不允许取消, 工单ID：" + serialOrderId)
		}
		preSerialOrderLi, err := dao.Select([]grmi.Predicate{
			meta.SerialOrder_OrderType.NewPredicate(grmi.Equal, baseModel.ORDER_TYPE_PRE),
			meta.SerialOrder_GenerateFlag.NewPredicate(grmi.Equal, 0),
			meta.SerialOrder_MainOrderId.NewPredicate(grmi.Equal, serialOrderId),
		}, nil)
		if err != nil {
			return grmi.NewBusinessError("查询工单下的预装工单失败, 错误：" + err.Error())
		}
		for _, preOrder := range preSerialOrderLi {
			if preOrder.SerialOrderStatus.Status > baseModel.WO_STATUS_RELEASED {
				return grmi.NewBusinessError("预装工单已经不允许取消, 工单ID:" + preOrder.SerialOrderId)
			}
		}
		if err := session.Begin(); err != nil {
			return grmi.NewBusinessError("开启事务失败, 错误：" + err.Error())
		}

		statusRec := model.SerialOrderStatusRecLst{
			SerialOrderId: serialOrderId,
			Status:        baseModel.WO_STATUS_CANCELED,
			PrevStatus:    status.Status,
		}
		status.Status = baseModel.WO_STATUS_CANCELED
		err = statusRecDao.InsertOne(&statusRec)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("插入工单状态变更记录失败, error:" + err.Error())
		}
		err = statusDao.UpdateOne(status)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新工单状态失败， error:" + err.Error())
		}
		if originStatus == baseModel.WO_STATUS_RELEASED {
			poUpdateData := &model.SerialOrderPOLst{
				Status: baseModel.WO_STATUS_CANCELED,
			}
			err = serialOrderPOLstDao.UpdateWhere([]grmi.Predicate{meta.SerialOrderPOLst_SerialOrderId.NewPredicate(grmi.Equal, serialOrderId)}, poUpdateData, meta.SerialOrderPOLst_Status.Name)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("更新工单工序状态失败, error:" + err.Error())
			}
			stepUpdateData := &model.SerialOrderStepLst{
				Status: baseModel.WO_STATUS_CANCELED,
			}
			err = serialOrderStepDao.UpdateWhere([]grmi.Predicate{meta.SerialOrderStepLst_SerialOrderId.NewPredicate(grmi.Equal, serialOrderId)}, stepUpdateData, meta.SerialOrderStepLst_Status.Name)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("更新工单工步状态失败, error:" + err.Error())
			}
			opDetailUpdateData := &model.SerialOrderOPDetail{
				Status: baseModel.WO_STATUS_CANCELED,
			}
			err = serialOrderOPDetailDao.UpdateWhere([]grmi.Predicate{meta.SerialOrderOPDetail_SerialOrderId.NewPredicate(grmi.Equal, serialOrderId)}, opDetailUpdateData, meta.SerialOrderOPDetail_Status.Name)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("更新工单详细操作状态失败, error:" + err.Error())
			}
		}
		// 取消预装工单
		for _, preOrder := range preSerialOrderLi {
			originStatus = preOrder.SerialOrderStatus.Status
			statusRec = model.SerialOrderStatusRecLst{
				SerialOrderId: preOrder.SerialOrderId,
				Status:        baseModel.WO_STATUS_CANCELED,
				PrevStatus:    preOrder.SerialOrderStatus.Status,
			}
			preOrder.SerialOrderStatus.Status = baseModel.WO_STATUS_CANCELED
			err = statusRecDao.InsertOne(&statusRec)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("插入预装工单状态变更记录失败, error:" + err.Error())
			}
			err = statusDao.UpdateOne(&preOrder.SerialOrderStatus)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("更新预装工单状态失败， error:" + err.Error())
			}
			if originStatus == baseModel.WO_STATUS_RELEASED {
				poUpdateData := &model.SerialOrderPOLst{
					Status: baseModel.WO_STATUS_CANCELED,
				}
				err = serialOrderPOLstDao.UpdateWhere([]grmi.Predicate{meta.SerialOrderPOLst_SerialOrderId.NewPredicate(grmi.Equal, preOrder.SerialOrderId)}, poUpdateData, meta.SerialOrderPOLst_Status.Name)
				if err != nil {
					_ = session.Rollback()
					return grmi.NewBusinessError("更新预装工单工序状态失败, error:" + err.Error())
				}
				stepUpdateData := &model.SerialOrderStepLst{
					Status: baseModel.WO_STATUS_CANCELED,
				}
				err = serialOrderStepDao.UpdateWhere([]grmi.Predicate{meta.SerialOrderStepLst_SerialOrderId.NewPredicate(grmi.Equal, preOrder.SerialOrderId)}, stepUpdateData, meta.SerialOrderStepLst_Status.Name)
				if err != nil {
					_ = session.Rollback()
					return grmi.NewBusinessError("更新预装工单工步状态失败, error:" + err.Error())
				}
				opDetailUpdateData := &model.SerialOrderOPDetail{
					Status: baseModel.WO_STATUS_CANCELED,
				}
				err = serialOrderOPDetailDao.UpdateWhere([]grmi.Predicate{meta.SerialOrderOPDetail_SerialOrderId.NewPredicate(grmi.Equal, preOrder.SerialOrderId)}, opDetailUpdateData, meta.SerialOrderOPDetail_Status.Name)
				if err != nil {
					_ = session.Rollback()
					return grmi.NewBusinessError("更新预装工单详细操作状态失败, error:" + err.Error())
				}
			}
		}
	}
	_ = session.Commit()
	return nil
}
