// 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"
	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"
	omModel "LAPP_ACURA_MOM_BACKEND/models/om"
	model "LAPP_ACURA_MOM_BACKEND/models/pln"
	"LAPP_ACURA_MOM_BACKEND/services/schedule"
	"github.com/go-xorm/xorm"
	uuid "github.com/iris-contrib/go.uuid"
	"strconv"
	"strings"
	"time"
)

/******************************************************************************
 *
 * @Description              : CustOrder的默认查询条件
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-10-22 13:50:40
 *
 ******************************************************************************/
var DefaultConditionOfCustOrder = grmi.NewCondition(
	map[string]grmi.ConditionItem{
		meta.CustOrder_CustOrderId.UrlParameterName:        grmi.NewConditionItem(meta.CustOrder_CustOrderId, grmi.Equal, true),
		meta.CustOrder_ProductFamilyId.UrlParameterName:    grmi.NewConditionItem(meta.CustOrder_ProductFamilyId, grmi.Equal, false),
		meta.CustOrder_PartId.UrlParameterName:             grmi.NewConditionItem(meta.CustOrder_PartId, grmi.Equal, false),
		meta.CustOrder_OemOrderId.UrlParameterName:         grmi.NewConditionItem(meta.CustOrder_OemOrderId, grmi.Equal, false),
		meta.CustOrder_OrderType.UrlParameterName:          grmi.NewConditionItem(meta.CustOrder_OrderType, grmi.Equal, false),
		meta.CustOrder_OrderInfo.UrlParameterName:          grmi.NewConditionItem(meta.CustOrder_OrderInfo, grmi.Equal, false),
		meta.CustOrder_OrderTime.UrlParameterName:          grmi.NewConditionItem(meta.CustOrder_OrderTime, grmi.Approximate, false),
		meta.CustOrder_DeliveryTime.UrlParameterName:       grmi.NewConditionItem(meta.CustOrder_DeliveryTime, grmi.Approximate, false),
		meta.CustOrder_ProjectId.UrlParameterName:          grmi.NewConditionItem(meta.CustOrder_ProjectId, grmi.Equal, false),
		meta.CustOrder_ConfigValue.UrlParameterName:        grmi.NewConditionItem(meta.CustOrder_ConfigValue, grmi.Equal, false),
		meta.CustOrder_ModelValue.UrlParameterName:         grmi.NewConditionItem(meta.CustOrder_ModelValue, grmi.Equal, false),
		meta.CustOrder_ColorValue.UrlParameterName:         grmi.NewConditionItem(meta.CustOrder_ColorValue, grmi.Equal, false),
		meta.CustOrder_HandleStatus.UrlParameterName:       grmi.NewConditionItem(meta.CustOrder_HandleStatus, grmi.Equal, false),
		meta.CustOrder_VinPrefix.UrlParameterName:          grmi.NewConditionItem(meta.CustOrder_VinPrefix, grmi.Equal, false),
		meta.CustOrder_VinNrFrom.UrlParameterName:          grmi.NewConditionItem(meta.CustOrder_VinNrFrom, grmi.Equal, false),
		meta.CustOrder_VinNrTo.UrlParameterName:            grmi.NewConditionItem(meta.CustOrder_VinNrTo, grmi.Equal, false),
		meta.CustOrder_Vin.UrlParameterName:                grmi.NewConditionItem(meta.CustOrder_Vin, grmi.Equal, false),
		meta.CustOrder_PlanQty.UrlParameterName:            grmi.NewConditionItem(meta.CustOrder_PlanQty, grmi.Equal, false),
		meta.CustOrder_DeliveryDate.UrlParameterName:       grmi.NewConditionItem(meta.CustOrder_DeliveryDate, grmi.Approximate, false),
		meta.CustOrder_DeliveryDateTime.UrlParameterName:   grmi.NewConditionItem(meta.CustOrder_DeliveryDateTime, grmi.Approximate, false),
		meta.CustOrder_OemSeq.UrlParameterName:             grmi.NewConditionItem(meta.CustOrder_OemSeq, grmi.Equal, false),
		meta.CustOrder_AssemblyLine.UrlParameterName:       grmi.NewConditionItem(meta.CustOrder_AssemblyLine, grmi.Equal, false),
		meta.CustOrder_UnloadingPoint.UrlParameterName:     grmi.NewConditionItem(meta.CustOrder_UnloadingPoint, grmi.Equal, false),
		meta.CustOrder_CalloffId.UrlParameterName:          grmi.NewConditionItem(meta.CustOrder_CalloffId, grmi.Equal, false),
		meta.CustOrder_CalloffDateTime.UrlParameterName:    grmi.NewConditionItem(meta.CustOrder_CalloffDateTime, grmi.Approximate, false),
		meta.CustOrder_ConsigneePlant.UrlParameterName:     grmi.NewConditionItem(meta.CustOrder_ConsigneePlant, grmi.Equal, false),
		meta.CustOrder_ConsigneeCompany.UrlParameterName:   grmi.NewConditionItem(meta.CustOrder_ConsigneeCompany, grmi.Equal, false),
		meta.CustOrder_ConsumeCompany.UrlParameterName:     grmi.NewConditionItem(meta.CustOrder_ConsumeCompany, grmi.Equal, false),
		meta.CustOrder_ConsumePlant.UrlParameterName:       grmi.NewConditionItem(meta.CustOrder_ConsumePlant, grmi.Equal, false),
		meta.CustOrder_UnloadingPlace.UrlParameterName:     grmi.NewConditionItem(meta.CustOrder_UnloadingPlace, grmi.Equal, false),
		meta.CustOrder_VehicleIdSet.UrlParameterName:       grmi.NewConditionItem(meta.CustOrder_VehicleIdSet, grmi.Equal, false),
		meta.CustOrder_VehicleId.UrlParameterName:          grmi.NewConditionItem(meta.CustOrder_VehicleId, grmi.Equal, false),
		meta.CustOrder_WorkLineId.UrlParameterName:         grmi.NewConditionItem(meta.CustOrder_WorkLineId, grmi.Equal, false),
		meta.CustOrder_PlanStartTime.UrlParameterName:      grmi.NewConditionItem(meta.CustOrder_PlanStartTime, grmi.Equal, false),
		meta.CustOrder_PlanEndTime.UrlParameterName:        grmi.NewConditionItem(meta.CustOrder_PlanEndTime, grmi.Equal, false),
		meta.CustOrder_PlanStartDate.UrlParameterName:      grmi.NewConditionItem(meta.CustOrder_PlanStartDate, grmi.Equal, false),
		meta.CustOrder_PlanEndDate.UrlParameterName:        grmi.NewConditionItem(meta.CustOrder_PlanEndDate, grmi.Equal, false),
		meta.CustOrder_ActStartTime.UrlParameterName:       grmi.NewConditionItem(meta.CustOrder_ActStartTime, grmi.Equal, false),
		meta.CustOrder_ActEndTime.UrlParameterName:         grmi.NewConditionItem(meta.CustOrder_ActEndTime, grmi.Equal, false),
		meta.CustOrder_SetupStartTime.UrlParameterName:     grmi.NewConditionItem(meta.CustOrder_SetupStartTime, grmi.Equal, false),
		meta.CustOrder_SetupEndTime.UrlParameterName:       grmi.NewConditionItem(meta.CustOrder_SetupEndTime, grmi.Equal, false),
		meta.CustOrder_FixStartTimeToggle.UrlParameterName: grmi.NewConditionItem(meta.CustOrder_FixStartTimeToggle, grmi.Equal, false),
		meta.CustOrder_QuantityPerHour.UrlParameterName:    grmi.NewConditionItem(meta.CustOrder_QuantityPerHour, grmi.Equal, false),
		meta.CustOrder_CtrlPara1.UrlParameterName:          grmi.NewConditionItem(meta.CustOrder_CtrlPara1, grmi.Equal, false),
		meta.CustOrder_CtrlPara2.UrlParameterName:          grmi.NewConditionItem(meta.CustOrder_CtrlPara2, grmi.Equal, false),
		meta.CustOrder_CtrlStr1.UrlParameterName:           grmi.NewConditionItem(meta.CustOrder_CtrlStr1, grmi.Equal, false),
		meta.CustOrder_CtrlStr2.UrlParameterName:           grmi.NewConditionItem(meta.CustOrder_CtrlStr2, grmi.Equal, false),
		meta.CustOrder_LastModify.UrlParameterName:         grmi.NewConditionItem(meta.CustOrder_LastModify, grmi.Approximate, false),
		meta.CustOrder_LastUser.UrlParameterName:           grmi.NewConditionItem(meta.CustOrder_LastUser, grmi.Equal, false),
		meta.CustOrder_CreateTime.UrlParameterName:         grmi.NewConditionItem(meta.CustOrder_CreateTime, grmi.Approximate, false),
		meta.CustOrder_SourceId.UrlParameterName:           grmi.NewConditionItem(meta.CustOrder_SourceId, grmi.Equal, false),
	},
	nil,
)

/******************************************************************************
 *
 * @Description              : CustOrder的默认分页查询条件
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-10-22 13:50:40
 *
 ******************************************************************************/
var DefaultConditionOfCustOrderAndPaging = grmi.NewCondition(
	DefaultConditionOfCustOrder.Items,
	grmi.NewPaging(),
)

/******************************************************************************
 *
 * @Struct Name              : CustOrderServiceImplement
 *-----------------------------------------------------------------------------
 *
 * @Description              : CustOrder的服务实现
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-10-22 13:50:40
 *
 ******************************************************************************/
type CustOrderServiceImplement struct {
}

/******************************************************************************
 *
 * @Function Name            : NewCustOrderDAOImplement
 *-----------------------------------------------------------------------------
 *
 * @Description              : 创建一个CustOrderDAOImplement实例
 *
 * @Return Value             : CustOrderDAOImplement实例
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-10-22 13:50:40
 *
 ******************************************************************************/
func NewCustOrderServiceImplement() *CustOrderServiceImplement {
	return &CustOrderServiceImplement{}
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/pln/CustOrderService.InsertOne
 *
 ******************************************************************************/
func (impl *CustOrderServiceImplement) InsertOne(user *global.User, entity *model.CustOrder) error {

	grmi.Log(user, "/services/pln/implments/CustOrder.service.impl.go", "InsertOneCustOrder", "插入一个CustOrder")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
	snrDao := baseDal.NewSnrDAO(session, user.PlantNr, user.UserId)
	projectDao := meDal.NewProjectDAO(session, user.PlantNr, user.UserId)
	qtyDao := dal.NewCustOrderQtyDAO(session, user.PlantNr, user.UserId)
	statusDao := dal.NewCustOrderStatusDAO(session, user.PlantNr, user.UserId)
	if entity.PlanQty == 0 {
		return grmi.NewBusinessError("创建客户订单计划生产数量为0")
	}
	if entity.ProductFamilyId == "" {
		return grmi.NewBusinessError("工单数据缺失")
	}
	productFamilyDao := meDal.NewProductFamilyDAO(session, user.PlantNr, user.UserId)
	productFamily, err := productFamilyDao.SelectOne(entity.ProductFamilyId)
	if err != nil {
		return grmi.NewBusinessError("查询车型配置失败, error:" + err.Error())
	}
	if productFamily == nil {
		return grmi.NewBusinessError("不存在订单指定的车型配置,车型配置ID:" + entity.ProductFamilyId)
	}
	if !productFamily.Enable {
		return grmi.NewBusinessError("当前派生未启用， 不允许创建客户订单")
	}
	project, err := projectDao.SelectOne(productFamily.ProjectId)
	if err != nil {
		return grmi.NewBusinessError("查询车型项目失败, error:" + err.Error())
	}
	if project == nil {
		return grmi.NewBusinessError("不存在对应的车型项目, 车型项目ID:" + productFamily.ProjectId)
	}
	// 校验指定的生产产线 派生是否已经关联
	if entity.WorkLineId == "" {
		return grmi.NewBusinessError("未指定生产产线")
	}
	usedWorkLineId := entity.WorkLineId
	if !productFamily.MultiWorkLineToggle {
		if usedWorkLineId != productFamily.WorkLineId {
			return grmi.NewBusinessError("该派生不能在指定的产线上生产")
		}
	} else {
		productFamilyWorkLineDao := meDal.NewProductFamilyWorkLineLstDAO(session, user.PlantNr, user.UserId)
		workLineLi, err := productFamilyWorkLineDao.Select([]grmi.Predicate{
			meMeta.ProductFamilyWorkLineLst_ProductFamilyId.NewPredicate(grmi.Equal, entity.ProductFamilyId),
		}, nil)
		if err != nil {
			return grmi.NewBusinessError("查询派生产线关联数据失败, 错误:" + err.Error())
		}
		var canProduct bool
		for _, workLine := range workLineLi {
			if workLine.WorkLineId == entity.WorkLineId {
				canProduct = true
				break
			}
		}
		if !canProduct {
			return grmi.NewBusinessError("该派生不能在指定的产线上生产")
		}
	}
	entity.SourceId = baseModel.ODER_TYPE_INTERVAL
	entity.OrderType = baseModel.ODER_TYPE_INTERVAL
	entity.QuantityPerHour = int(productFamily.Jph)
	entity.OrderInfo = productFamily.Descr
	entity.ConfigValue = productFamily.ConfigValue
	entity.ColorValue = productFamily.ColorValue
	entity.ModelValue = productFamily.ModelValue
	entity.ProjectId = productFamily.ProjectId
	if err = session.Begin(); err != nil {
		return err
	}
	custOrderId, err := snrDao.GetNextSnr(project.CustOrderSnr)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("生成客户订单流水号失败, error:" + custOrderId)
	}
	entity.CustOrderId = custOrderId
	custOrderQty := model.CustOrderQty{
		CustOrderId: custOrderId,
		PlanQty:     entity.PlanQty,
	}
	err = qtyDao.InsertOne(&custOrderQty)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("写入客户订单数量失败, error:" + err.Error())
	}
	custOrderStatus := model.CustOrderStatus{
		CustOrderId: custOrderId,
		Status:      baseModel.WO_STATUS_UNPLANNED,
	}
	err = statusDao.InsertOne(&custOrderStatus)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("写入客户订单状态数据失败, error:" + err.Error())
	}
	err = dao.InsertOne(entity)
	if err != nil {
		_ = session.Rollback()
		return err
	}
	_ = session.Commit()
	return nil
}

func (impl *CustOrderServiceImplement) Cancel(user *global.User, custOrderId string) error {
	grmi.Log(user, "/services/pln/implments/CustOrder.service.impl.go", "Cancel", "取消一个CustOrder")
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
	record, err := dao.SelectOne(custOrderId)
	if err != nil {
		return err
	}
	if record == nil {
		return grmi.NewBusinessError("不存在指定记录!")
	}
	//查询订单状态
	statusDao := dal.NewCustOrderStatusDAO(session, user.PlantNr, user.UserId)
	historyDao := dal.NewCustOrderStatusHistoryDAO(session, user.PlantNr, user.UserId)
	status, err := statusDao.SelectOne(record.CustOrderId)
	if err != nil {
		return err
	}
	if status.Status != baseModel.ORDER_STATUS_UNPLANED {
		return grmi.NewBusinessError("订单状态不在未计划中无法取消")
	}
	//修改订单状态
	session.Begin()
	status.Status = baseModel.ORDER_STATUS_CANCELED
	err = statusDao.UpdateOne(status)
	if err != nil {
		session.Rollback()
		return grmi.NewBusinessError(err.Error())
	}
	statusLog := model.CustOrderStatusHistory{
		CustOrderId: record.CustOrderId,
		FromStatus:  baseModel.ORDER_STATUS_UNPLANED,
		ToStatus:    baseModel.ORDER_STATUS_CANCELED,
		ChangeTime:  grmi.DateTime{},
	}
	err = historyDao.InsertOne(&statusLog)
	if err != nil {
		session.Rollback()
		return grmi.NewBusinessError(err.Error())
	}
	_ = session.Commit()
	return nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/pln/CustOrderService.DeleteOne
 *
 ******************************************************************************/
func (impl *CustOrderServiceImplement) DeleteOne(user *global.User, custOrderId string) error {

	grmi.Log(user, "/services/pln/implments/CustOrder.service.impl.go", "DeleteOneCustOrder", "删除一个CustOrder")

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

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/pln/CustOrderService.SelectOne
 *
 ******************************************************************************/
func (impl *CustOrderServiceImplement) SelectOne(user *global.User, custOrderId string) (*model.CustOrder, error) {

	grmi.Log(user, "/services/pln/implments/CustOrder.service.impl.go", "SelectOneCustOrder", "查询一个CustOrder")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
	result, err := dao.SelectOne(custOrderId)

	if err != nil {
		return nil, err
	}
	return result, nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/pln/CustOrderService.UpdateOne
 *
 ******************************************************************************/
func (impl *CustOrderServiceImplement) UpdateOne(user *global.User, entity *model.CustOrder) error {

	grmi.Log(user, "/services/pln/implments/CustOrder.service.impl.go", "UpdateOneCustOrder", "修改一个CustOrder")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
	custOrderQtyDao := dal.NewCustOrderQtyDAO(session, user.PlantNr, user.UserId)
	record, err := dao.SelectOne(entity.CustOrderId)
	if err != nil {
		return err
	}
	if record == nil {
		return grmi.NewBusinessError("不存在指定记录!")
	}
	if record.OrderStatus.Status != baseModel.WO_STATUS_UNPLANNED {
		return grmi.NewBusinessError("该客户订单状态不是未计划，不允许修改")
	}
	if err := session.Begin(); err != nil {
		return grmi.NewBusinessError("开启事务失败, error:" + err.Error())
	}
	if record.PlanQty != entity.PlanQty {
		record.OrderQty.PlanQty = entity.PlanQty
		err = custOrderQtyDao.UpdateOne(&record.OrderQty)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新客户订单数量失败, error:" + err.Error())
		}
	}
	err = dao.UpdateOne(entity)
	if err != nil {
		_ = session.Rollback()
		return err
	}
	_ = session.Commit()
	return nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/pln/CustOrderService.Insert
 *
 ******************************************************************************/
func (impl *CustOrderServiceImplement) Insert(user *global.User, entities *[]model.CustOrder) error {

	grmi.Log(user, "/services/pln/implments/CustOrder.service.impl.go", "InsertCustOrder", "插入多个CustOrder")

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

	for _, entity := range *entities {
		record, err := dao.SelectOne(entity.CustOrderId)
		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/pln/CustOrderService.Delete
 *
 ******************************************************************************/
func (impl *CustOrderServiceImplement) Delete(user *global.User, entities *[]model.CustOrder) error {

	grmi.Log(user, "/services/pln/implments/CustOrder.service.impl.go", "DeleteCustOrder", "删除多个CustOrder")

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

	for _, entity := range *entities {
		record, err := dao.SelectOne(entity.CustOrderId)
		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/pln/CustOrderService.Select
 *
 ******************************************************************************/
func (impl *CustOrderServiceImplement) Select(user *global.User, urlParameters map[string]string) ([]model.CustOrder, error) {

	grmi.Log(user, "/services/pln/implments/CustOrder.service.impl.go", "SelectCustOrder", "查询CustOrder")

	condition := DefaultConditionOfCustOrderAndPaging
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	predicates, err := condition.BuildPredicates(urlParameters)
	if err != nil {
		return nil, err
	}
	dao := dal.NewCustOrderDAO(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/pln/CustOrderService.SelectAndPaging
 *
 ******************************************************************************/
func (impl *CustOrderServiceImplement) SelectAndPaging(user *global.User, urlParameters map[string]string) (grmi.PagingResult, error) {

	grmi.Log(user, "/services/pln/implments/CustOrder.service.impl.go", "SelectCustOrder", "查询CustOrder")

	condition := DefaultConditionOfCustOrderAndPaging
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	predicates, err := condition.BuildPredicates(urlParameters)
	if err != nil {
		return grmi.EmptyPagingResult, err
	}
	dao := dal.NewCustOrderDAO(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/pln/CustOrderService.Update
 *
 ******************************************************************************/
func (impl *CustOrderServiceImplement) Update(user *global.User, entities *[]model.CustOrder) error {

	grmi.Log(user, "/services/pln/implments/CustOrder.service.impl.go", "UpdateCustOrder", "修改多个CustOrder")

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

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

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

// PlanCustOrder 将客户订单状态置为已计划 并设置计划开始时间
func (impl *CustOrderServiceImplement) PlanCustOrder(user *global.User, entity *model.CustOrder) error {
	grmi.Log(user, "/services/pln/implments/CustOrder.service.impl.go", "PlanCustOrder", "计划客户订单")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	if err := session.Begin(); err != nil {
		return err
	}
	entity.PlanStartDate = grmi.Date(time.Now())
	entity.PlanEndDate = grmi.Date(time.Now())
	entity.PlanStartTime = grmi.DateTime(time.Now())
	entity.PlanEndTime = grmi.DateTime(time.Now())
	dao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
	record, err := dao.SelectOne(entity.CustOrderId)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("查询客户订单数据失败, error:" + err.Error())
	}
	if record == nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("客户订单不存在, 订单ID:" + entity.CustOrderId)
	}
	statusDao := dal.NewCustOrderStatusDAO(session, user.PlantNr, user.UserId)
	status, err := statusDao.SelectOne(entity.CustOrderId)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("查询客户订单状态失败, error:" + err.Error())
	}
	if status == nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("客户订单状态不存在, 订单ID:" + entity.CustOrderId)
	}
	if status.Status != baseModel.WO_STATUS_UNPLANNED {
		_ = session.Rollback()
		return grmi.NewBusinessError("客户订单状态不是未计划, 订单ID:" + entity.CustOrderId)
	}
	err = dao.UpdateOne(entity)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新客户订单数据失败, error:" + err.Error())
	}
	status.Status = baseModel.WO_STATUS_PLANNED
	err = statusDao.UpdateOne(status)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新客户订单状态失败， error:" + err.Error())
	}
	statusRecDao := dal.NewCustOrderStatusHistoryDAO(session, user.PlantNr, user.UserId)
	statusRec := model.CustOrderStatusHistory{
		CustOrderId: entity.CustOrderId,
		FromStatus:  baseModel.WO_STATUS_UNPLANNED,
		ToStatus:    baseModel.WO_STATUS_PLANNED,
		ChangeTime:  grmi.DateTime(time.Now()),
	}
	err = statusRecDao.InsertOne(&statusRec)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("插入客户订单状态变更记录失败, error:" + err.Error())
	}
	_ = session.Commit()
	return nil
}


// ReportWort 处理MES的报工数据
func (impl *CustOrderServiceImplement) ReportWort(user *global.User) {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	log, _ := logger.NewLogger("Schuler", "ReportWork")
	uid, err := uuid.NewV1()
	if err != nil {
		return
	}
	reportId := uid.String()
	log.Info("报工同步开始, 报工任务ID:" + reportId)
	// 从serialOrder状态变更表中获取MES操作完成的serialOrder
	serialOrderStatusRecDao := omDal.NewSerialOrderStatusRecLstDAO(session, user.PlantNr, user.UserId)
	serialOrderDao := omDal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	event, err := serialOrderStatusRecDao.SelectClosedEvent()
	if err != nil {
		log.Error("报工同步阶段, 查询报工事件失败, 错误:" + err.Error() + ", 报工任务ID:" + reportId)
		return
	}
	if event == nil {
		log.Info("报工完成, 未获取到新的报工事件, 报工任务ID:" + reportId)
		return
	}
	log.Info("报工同步阶段, 处理工单ID:" + event.SerialOrder.SerialOrderId + ", 报工任务ID:" + reportId)
	// 查询serialOrder关联的客户订单
	custOrderDao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
	custOrderStatusDao := dal.NewCustOrderStatusDAO(session, user.PlantNr, user.UserId)
	custOrderStatusHistoryDao := dal.NewCustOrderStatusHistoryDAO(session, user.PlantNr, user.UserId)
	custOrder, err := custOrderDao.SelectOne(event.SerialOrder.CustOrderId)
	if err != nil {
		log.Error("报工同步阶段, 查询关联的客户订单失败, 错误:" + err.Error() + ", 报工任务ID:" + reportId)
		return
	}
	if custOrder == nil {
		log.Error("报工同步阶段, 查询关联的客户订单不存在, 客户订单ID:" + event.SerialOrder.CustOrderId + ", 报工任务ID:" + reportId)
		return
	}
	if custOrder.OrderStatus.Status >= baseModel.WO_STATUS_FINISHED {
		log.Error("报工同步阶段, 关联的客户订单已完成, 客户订单ID:" + event.SerialOrder.CustOrderId + ", 报工任务ID:" + reportId)
		return
	}
	// 开启事务 开始处理客户订单数量
	if err = session.Begin(); err != nil {
		log.Error("报工同步阶段, 开启事务失败, 错误:" + err.Error() + ", 报工任务ID:" + reportId)
		return
	}
	event.SerialOrderStatusRecLst.OutputStatus = omModel.ORDER_DEALED
	err = serialOrderStatusRecDao.UpdateOne(&event.SerialOrderStatusRecLst)
	if err != nil {
		_ = session.Rollback()
		log.Error("报工同步阶段, 更新工单状态变更记录处理状态失败, 错误:" + err.Error() + ", 报工任务ID:" + reportId)
		return
	}
	//serialOrder := event.SerialOrder
	serialOrderLi, err := serialOrderDao.Select([]grmi.Predicate{omMeta.SerialOrder_SyncKey.NewPredicate(grmi.Equal, event.SerialOrder.SyncKey)}, nil)
	var carComplete = true
	var completeQty int
	for _, serialOrder := range serialOrderLi {
		if serialOrder.SerialOrderStatus.Status < baseModel.WO_STATUS_FINISHED {
			carComplete = false
		} else if serialOrder.SerialOrderStatus.Status == baseModel.WO_STATUS_FINISHED {
			completeQty += 1
		}
	}
	// 客户订单下的工单数量+1
	custOrder.OrderQty.SerialOrderActQty += 1
	// 如果客户订单下的同一台套工单都完成 ActQty +1
	if carComplete {
		custOrder.OrderQty.ActQty += 1
	}
	// 如果客户订单下的同一台套只完成一个 说明该工单是这个台套的第一个完成的工单 RunningQty+1
	if completeQty == 1 {
		custOrder.OrderQty.RunningQty += 1
	}
	// 关单
	if custOrder.OrderQty.ActQty == custOrder.OrderQty.PlanQty {
		custOrderStatsusHistory := model.CustOrderStatusHistory{
			CustOrderId:      custOrder.CustOrderId,
			StatusChangeType: model.STATUS_CHANGE_TYPE_REPORT,
			FromStatus:       custOrder.OrderStatus.Status,
			ToStatus:         baseModel.WO_STATUS_FINISHED,
			ChangeTime:       grmi.DateTime(time.Now()),
		}
		err = custOrderStatusHistoryDao.InsertOne(&custOrderStatsusHistory)
		if err != nil {
			_ = session.Rollback()
			log.Error("报工同步阶段, 插入客户订单状态变更记录失败, 错误:" + err.Error() + ", 报工任务ID:" + reportId)
			return
		}
		custOrder.OrderStatus.Status = baseModel.WO_STATUS_FINISHED
		err = custOrderStatusDao.UpdateOne(&custOrder.OrderStatus)
		if err != nil {
			_ = session.Rollback()
			log.Error("报工同步阶段, 更新客户订单状态失败, 错误:" + err.Error() + ", 报工任务ID:" + reportId)
			return
		}
		custOrder.ActEndTime = event.SerialOrderStatusRecLst.CreateTime
		err = custOrderDao.UpdateOne(custOrder)
		if err != nil {
			_ = session.Rollback()
			log.Error("报工同步阶段, 更新客户订单关闭时间失败, 错误:" + err.Error() + ", 报工任务ID:" + reportId)
		}
		log.Info("报工同步阶段, 客户订单关闭， 处理客户订单ID:" + custOrder.CustOrderId + ", 处理工单ID:" + event.SerialOrder.SerialOrderId + ", 报工任务ID:" + reportId)
		_ = session.Commit()
		return
	}
	if custOrder.OrderStatus.Status == baseModel.WO_STATUS_RELEASED {
		custOrderStatsusHistory := model.CustOrderStatusHistory{
			CustOrderId:      custOrder.CustOrderId,
			StatusChangeType: model.STATUS_CHANGE_TYPE_REPORT,
			FromStatus:       custOrder.OrderStatus.Status,
			ToStatus:         baseModel.WO_STATUS_RUNNING,
			ChangeTime:       grmi.DateTime(time.Now()),
		}
		err = custOrderStatusHistoryDao.InsertOne(&custOrderStatsusHistory)
		if err != nil {
			_ = session.Rollback()
			log.Error("报工同步阶段, 插入客户订单状态变更记录失败, 错误:" + err.Error() + ", 报工任务ID:" + reportId)
			return
		}
		custOrder.OrderStatus.Status = baseModel.WO_STATUS_RUNNING
		err = custOrderStatusDao.UpdateOne(&custOrder.OrderStatus)
		if err != nil {
			_ = session.Rollback()
			log.Error("报工同步阶段, 更新客户订单状态失败, 错误:" + err.Error() + ", 报工任务ID:" + reportId)
			return
		}
		custOrder.ActStartTime = event.SerialOrderStatusRecLst.CreateTime
		err = custOrderDao.UpdateOne(custOrder)
		if err != nil {
			_ = session.Rollback()
			log.Error("报工同步阶段, 更新客户订单开始时间失败, 错误:" + err.Error() + ", 报工任务ID:" + reportId)
		}
		log.Info("报工同步阶段, 客户订单已置为运行中， 处理客户订单ID:" + custOrder.CustOrderId + ", 处理工单ID:" + event.SerialOrder.SerialOrderId + ", 报工任务ID:" + reportId)
		_ = session.Commit()
		return
	}
	log.Info("报工同步阶段, 客户订单已经在运行中， 处理客户订单ID:" + custOrder.CustOrderId + ", 处理工单ID:" + event.SerialOrder.SerialOrderId + ", 报工任务ID:" + reportId)
	_ = session.Commit()
	return
}

// CancelCustOrderQty 取消客户订单数量
func (impl *CustOrderServiceImplement) CancelCustOrderQty(user *global.User, custOrderId string, cancelQty int) error {
	grmi.Log(user, "/services/pln/implments/CustOrder.service.impl.go", "CancelCustOrderQty", "取消客户订单数量")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	custOrderDao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
	custOrderQtyDao := dal.NewCustOrderQtyDAO(session, user.PlantNr, user.UserId)
	custOrderStatusDao := dal.NewCustOrderStatusDAO(session, user.PlantNr, user.UserId)
	custOrderStatusHistoryDao := dal.NewCustOrderStatusHistoryDAO(session, user.PlantNr, user.UserId)
	serialOrderDao := omDal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	serialOrderStatusDao := omDal.NewSerialOrderStatusDAO(session, user.PlantNr, user.UserId)
	serialOrderStatusRecDao := omDal.NewSerialOrderStatusRecLstDAO(session, user.PlantNr, user.UserId)
	productFamilyRelateDao := meDal.NewProductFamilyRelateDAO(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)
	// 校验客户订单数据及状态
	custOrder, err := custOrderDao.SelectOne(custOrderId)
	if err != nil {
		return grmi.NewBusinessError("查询客户订单失败, error:" + err.Error())
	}
	if custOrder == nil {
		return grmi.NewBusinessError("客户订单不存在, 客户订单ID:" + custOrderId)
	}
	if custOrder.OrderStatus.Status <= baseModel.WO_STATUS_PLANNED || custOrder.OrderStatus.Status >= baseModel.WO_STATUS_FINISHED {
		return grmi.NewBusinessError("当前客户订单的状态不允许取消数量")
	}
	if custOrder.OrderQty.PlanQty-custOrder.OrderQty.RunningQty-custOrder.OrderQty.CancelQty < cancelQty {
		return grmi.NewBusinessError("取消数量已经大于客户订单允许取消的数量")
	}
	//originCancelQty := custOrder.OrderQty.CancelQty
	productLi, err := productFamilyRelateDao.SelectProductByFamilyIdForCreateSerialOrder(custOrder.ProjectId, custOrder.ProductFamilyId)
	if err != nil {
		return grmi.NewBusinessError("查询派生下的总成失败, error:" + err.Error())
	}
	productNum := len(productLi)
	serialOrderDataLi, err := serialOrderDao.SelectUnOnGoingSerialOrder(custOrderId)
	if err != nil {
		return grmi.NewBusinessError("查询工单数据失败, error:" + err.Error())
	}
	syncKeyMap := make(map[string][]omModel.VOmSerialorder)
	syncKeyLi := make([]string, 0)
	for _, serialOrderData := range serialOrderDataLi {
		_, exist := syncKeyMap[serialOrderData.SerialOrder.SyncKey]
		if !exist {
			syncKeyLi = append(syncKeyLi, serialOrderData.SerialOrder.SyncKey)
			syncKeyMap[serialOrderData.SerialOrder.SyncKey] = make([]omModel.VOmSerialorder, 0)
		}
		syncKeyMap[serialOrderData.SerialOrder.SyncKey] = append(syncKeyMap[serialOrderData.SerialOrder.SyncKey], serialOrderData)
	}
	var count int
	splitSyncKeyLi := make([]string, 0)
	for _, syncKey := range syncKeyLi {
		if len(syncKeyMap[syncKey]) == productNum {
			splitSyncKeyLi = append(splitSyncKeyLi, syncKey)
			count++
		}
	}
	if count < cancelQty {
		return grmi.NewBusinessError("当前客户订单可取消数量小于需要取消数量")
	}


	impl.QuickSort(splitSyncKeyLi)
	statusRecLi := make([]omModel.SerialOrderStatusRecLst, 0)
	cancelSerialOrderIdLi := make([]interface{}, 0)
	orderDataLi := make([]omModel.SerialOrder, 0)
	for i := 0; i < cancelQty; i++ {
		cancelSyncKey := splitSyncKeyLi[i]
		innerOrderLi, err := serialOrderDao.Select([]grmi.Predicate{omMeta.SerialOrder_SyncKey.NewPredicate(grmi.Equal, cancelSyncKey)}, nil)
		if err != nil {
			return grmi.NewBusinessError("查询工单数据失败, error:" + err.Error())
		}
		orderDataLi = append(orderDataLi, innerOrderLi...)
	}
	if err = session.Begin(); err != nil {
		return grmi.NewBusinessError("开启事务失败, error:" + err.Error())
	}
	for _, serialOrderData := range orderDataLi {
		cancelSerialOrderIdLi = append(cancelSerialOrderIdLi, serialOrderData.SerialOrderId)
		serialOrderStatus := serialOrderData.SerialOrderStatus
		statusRec := omModel.SerialOrderStatusRecLst{
			SerialOrderId: serialOrderData.SerialOrderId,
			PrevStatus:    serialOrderStatus.Status,
			Status:        baseModel.WO_STATUS_CANCELED,
			Remark1:       "SPLIT",
		}
		statusRecLi = append(statusRecLi, statusRec)
		serialOrderStatus.Status = baseModel.WO_STATUS_CANCELED
		err = serialOrderStatusDao.UpdateOneWithStatus(&serialOrderStatus, baseModel.WO_STATUS_RELEASED)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新工单状态失败, error:" + err.Error())
		}
		//poUpdateData := omModel.SerialOrderPOLst{
		//	Status: baseModel.WO_STATUS_CANCELED,
		//}
		//err = serialOrderPoDao.UpdateWhere([]grmi.Predicate{omMeta.SerialOrderPOLst_SerialOrderId.NewPredicate(grmi.Equal, serialOrderData.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_CANCELED,
		//}
		//err = serialOrderStepDao.UpdateWhere([]grmi.Predicate{omMeta.SerialOrderStepLst_SerialOrderId.NewPredicate(grmi.Equal, serialOrderData.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_CANCELED,
		//}
		//err = serialOrderOPDetailDao.UpdateWhere([]grmi.Predicate{omMeta.SerialOrderOPDetail_SerialOrderId.NewPredicate(grmi.Equal, serialOrderData.SerialOrderId)}, &opDetailUpdateData, []string{omMeta.SerialOrderOPDetail_Status.Name}...)
		//if err != nil {
		//	_ = session.Rollback()
		//	return grmi.NewBusinessError("更新工单详细操作状态失败, error:" + err.Error())
		//}
	}
	// 保存工单状态变更记录
	num := len(statusRecLi) / 50
	remainder := len(statusRecLi) % 50
	for i := 0; i < num; i++ {
		insertLi := statusRecLi[50*i : (i+1)*50]
		err = serialOrderStatusRecDao.Insert(&insertLi)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("保存工单状态变更记录失败, 错误:" + err.Error())
		}
	}
	if remainder != 0 {
		insertLi := statusRecLi[num*50:]
		err = serialOrderStatusRecDao.Insert(&insertLi)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("保存工单状态变更记录失败, 错误:" + err.Error())
		}
	}
	// 更新工单工序状态
	poUpdateData := omModel.SerialOrderPOLst{
		Status: baseModel.WO_STATUS_CANCELED,
	}
	num = len(cancelSerialOrderIdLi) / 50
	remainder = len(cancelSerialOrderIdLi) % 50
	for i := 0; i < num; i++ {
		updateLi := cancelSerialOrderIdLi[50*i : (i+1)*50]
		err = serialOrderPoDao.UpdateWhere([]grmi.Predicate{
			omMeta.SerialOrderPOLst_SerialOrderId.NewPredicate(grmi.Include, updateLi...),
		}, &poUpdateData, omMeta.SerialOrderPOLst_Status.Name)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新工单工序状态变更记录失败, 错误:" + err.Error())
		}
	}
	if remainder != 0 {
		updateLi := cancelSerialOrderIdLi[num*50:]
		err = serialOrderPoDao.UpdateWhere([]grmi.Predicate{
			omMeta.SerialOrderPOLst_SerialOrderId.NewPredicate(grmi.Include, updateLi...),
		}, &poUpdateData, omMeta.SerialOrderPOLst_Status.Name)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新工单工序状态变更记录失败, 错误:" + err.Error())
		}
	}
	// 处理客户订单数量数据
	custOrder.OrderQty.CancelQty += cancelQty
	err = custOrderQtyDao.UpdateOne(&custOrder.OrderQty)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新客户订单数量数据失败, error:" + err.Error())
	}
	// 通过数量判断是否需要处理客户订单状态
	if custOrder.OrderQty.CancelQty+custOrder.OrderQty.ActQty == custOrder.OrderQty.PlanQty {
		if custOrder.OrderQty.CancelQty == custOrder.OrderQty.PlanQty {
			custOrderHistory := model.CustOrderStatusHistory{
				CustOrderId:      custOrderId,
				StatusChangeType: model.STATUS_CHANGE_TYPE_OPERATION,
				FromStatus:       custOrder.OrderStatus.Status,
				ToStatus:         baseModel.ORDER_STATUS_CANCELED,
				ChangeTime:       grmi.DateTime(time.Now()),
			}
			err = custOrderStatusHistoryDao.InsertOne(&custOrderHistory)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("插入客户订单状态变更历史失败, error:" + err.Error())
			}
			custOrder.OrderStatus.Status = baseModel.ORDER_STATUS_CANCELED
			err = custOrderStatusDao.UpdateOne(&custOrder.OrderStatus)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("更新客户订单状态失败, error:" + err.Error())
			}
		} else {
			custOrderHistory := model.CustOrderStatusHistory{
				CustOrderId:      custOrderId,
				StatusChangeType: model.STATUS_CHANGE_TYPE_OPERATION,
				FromStatus:       custOrder.OrderStatus.Status,
				ToStatus:         baseModel.ORDER_STATUS_CLOSED,
				ChangeTime:       grmi.DateTime(time.Now()),
			}
			err = custOrderStatusHistoryDao.InsertOne(&custOrderHistory)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("插入客户订单状态变更历史失败, error:" + err.Error())
			}
			custOrder.OrderStatus.Status = baseModel.ORDER_STATUS_CLOSED
			err = custOrderStatusDao.UpdateOne(&custOrder.OrderStatus)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("更新客户订单状态失败, error:" + err.Error())
			}
		}
	}
	//// 生成需要取消的台套Key
	//cancelSyncKeyLi := make([]string, 0, cancelQty)
	//for i := 0; i < cancelQty; i++ {
	//	cancelKey := custOrder.OrderQty.PlanQty - originCancelQty - i - 1
	//	syncKey := custOrder.CustOrderId + "-" + strconv.Itoa(cancelKey)
	//	cancelSyncKeyLi = append(cancelSyncKeyLi, syncKey)
	//}
	//// 查询台套Key下的序列工单
	//serialOrderIdLi, err := serialOrderDao.SelectSerialOrderIdBySyncKey(cancelSyncKeyLi)
	//if err != nil {
	//	_ = session.Rollback()
	//	return grmi.NewBusinessError("通过台套Key查询序列工单数据失败, error:" + err.Error())
	//}
	//// 校验序列工单的状态是否都是40一下
	//statusLi, err := serialOrderStatusDao.SelectSerialOrderStatusBySerialOrderId(serialOrderIdLi)
	//if err != nil {
	//	_ = session.Rollback()
	//	return grmi.NewBusinessError("查询工单状态失败, error:" + err.Error())
	//}
	//for _, status := range statusLi {
	//	if status > 40 {
	//		_ = session.Rollback()
	//		return grmi.NewBusinessError("待取消的序列工单状态存在40及以上")
	//	}
	//}
	//// 更新序列工单状态 同时写入状态变更记录
	//serialOrderStatusRecLi := make([]omModel.SerialOrderStatusRecLst, 0, 20)
	//for _, serialOrderId := range serialOrderIdLi {
	//	serialOrderStatusRec := omModel.SerialOrderStatusRecLst{
	//		SerialOrderId: serialOrderId,
	//		PrevStatus:    baseModel.WO_STATUS_RELEASED,
	//		Status:        baseModel.WO_STATUS_CANCELED,
	//	}
	//	serialOrderStatusRecLi = append(serialOrderStatusRecLi, serialOrderStatusRec)
	//	if len(serialOrderStatusRecLi) == 20 {
	//		err = serialOrderStatusRecDao.Insert(&serialOrderStatusRecLi)
	//		if err != nil {
	//			_ = session.Rollback()
	//			return grmi.NewBusinessError("插入工单状态变更记录失败, error:" + err.Error())
	//		}
	//		serialOrderStatusRecLi = make([]omModel.SerialOrderStatusRecLst, 0, 20)
	//	}
	//}
	//if len(serialOrderStatusRecLi) > 0 {
	//	err = serialOrderStatusRecDao.Insert(&serialOrderStatusRecLi)
	//	if err != nil {
	//		_ = session.Rollback()
	//		return grmi.NewBusinessError("插入工单状态变更记录失败, error:" + err.Error())
	//	}
	//}
	//statusUpdateData := omModel.SerialOrderStatus{
	//	Status: baseModel.WO_STATUS_CANCELED,
	//}
	//idLi := make([]interface{}, 0, len(serialOrderIdLi))
	//for _, serialOrderId := range serialOrderIdLi {
	//	idLi = append(idLi, serialOrderId)
	//}
	//err = serialOrderStatusDao.UpdateWhere([]grmi.Predicate{omMeta.SerialOrderStatus_SerialOrderId.NewPredicate(grmi.Include, idLi...)}, &statusUpdateData, []string{omMeta.SerialOrderStatus_Status.Name}...)
	//if err != nil {
	//	_ = session.Rollback()
	//	return grmi.NewBusinessError("更新工单状态失败, error:" + err.Error())
	//}
	//poUpdateData := omModel.SerialOrderPOLst{
	//	Status: baseModel.WO_STATUS_CANCELED,
	//}
	//serialOrderPoDao := omDal.NewSerialOrderPOLstDAO(session, user.PlantNr, user.UserId)
	//err = serialOrderPoDao.UpdateWhere([]grmi.Predicate{omMeta.SerialOrderPOLst_SerialOrderId.NewPredicate(grmi.Include, idLi...)}, &poUpdateData, []string{omMeta.SerialOrderPOLst_Status.Name}...)
	//if err != nil {
	//	_ = session.Rollback()
	//	return grmi.NewBusinessError("更新工单工序状态失败, error:" + err.Error())
	//}
	//serialOrderStepDao := omDal.NewSerialOrderStepLstDAO(session, user.PlantNr, user.UserId)
	//stepUpdateData := omModel.SerialOrderStepLst{
	//	Status: baseModel.WO_STATUS_CANCELED,
	//}
	//err = serialOrderStepDao.UpdateWhere([]grmi.Predicate{omMeta.SerialOrderStepLst_SerialOrderId.NewPredicate(grmi.Include, idLi...)}, &stepUpdateData, []string{omMeta.SerialOrderStepLst_Status.Name}...)
	//if err != nil {
	//	_ = session.Rollback()
	//	return grmi.NewBusinessError("更新工单工步状态失败, error:" + err.Error())
	//}
	//serialOrderOPDetailDao := omDal.NewSerialOrderOPDetailDAO(session, user.PlantNr, user.UserId)
	//opDetailUpdateData := omModel.SerialOrderOPDetail{
	//	Status: baseModel.WO_STATUS_CANCELED,
	//}
	//err = serialOrderOPDetailDao.UpdateWhere([]grmi.Predicate{omMeta.SerialOrderOPDetail_SerialOrderId.NewPredicate(grmi.Include, idLi...)}, &opDetailUpdateData, []string{omMeta.SerialOrderOPDetail_Status.Name}...)
	//if err != nil {
	//	_ = session.Rollback()
	//	return grmi.NewBusinessError("更新工单详细操作状态失败, error:" + err.Error())
	//}
	_ = session.Commit()
	return nil
}

// CancelCustOrder 取消客户订单
func (impl *CustOrderServiceImplement) CancelCustOrder(user *global.User, custOrderId string) error {
	grmi.Log(user, "/services/pln/implments/CustOrder.service.impl.go", "CancelCustOrder", "取消客户订单")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	custOrderDao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
	custOrderStatusDao := dal.NewCustOrderStatusDAO(session, user.PlantNr, user.UserId)
	custOrderStatusHistoryDao := dal.NewCustOrderStatusHistoryDAO(session, user.PlantNr, user.UserId)
	// 校验客户订单数据及状态
	custOrder, err := custOrderDao.SelectOne(custOrderId)
	if err != nil {
		return grmi.NewBusinessError("查询客户订单失败, error:" + err.Error())
	}
	if custOrder == nil {
		return grmi.NewBusinessError("客户订单不存在, 客户订单ID:" + custOrderId)
	}
	if custOrder.OrderStatus.Status != baseModel.WO_STATUS_UNPLANNED {
		return grmi.NewBusinessError("当前客户订单状态不是未计划, 不允许取消")
	}
	if err = session.Begin(); err != nil {
		return grmi.NewBusinessError("开启事务失败, error:" + err.Error())
	}
	custOrder.OrderStatus.Status = baseModel.WO_STATUS_CANCELED
	err = custOrderStatusDao.UpdateOne(&custOrder.OrderStatus)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新客户订单状态失败, error:" + err.Error())
	}
	custOrderStatusHistory := model.CustOrderStatusHistory{
		CustOrderId:      custOrderId,
		StatusChangeType: model.STATUS_CHANGE_TYPE_OPERATION,
		FromStatus:       baseModel.WO_STATUS_UNPLANNED,
		ToStatus:         baseModel.WO_STATUS_CANCELED,
		ChangeTime:       grmi.DateTime(time.Now()),
	}
	err = custOrderStatusHistoryDao.InsertOne(&custOrderStatusHistory)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("插入客户订单状态变更历史失败, error:" + err.Error())
	}
	_ = session.Commit()
	return nil
}

// WithdrawCustOrder 回撤已计划的客户订单
func (impl *CustOrderServiceImplement) WithdrawCustOrder(user *global.User, custOrderId string) error {
	grmi.Log(user, "/services/pln/implments/CustOrder.service.impl.go", "WithdrawCustOrder", "回撤已计划的客户订单")
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	custOrderDao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
	custOrderStatusDao := dal.NewCustOrderStatusDAO(session, user.PlantNr, user.UserId)
	custOrderStatusHistoryDao := dal.NewCustOrderStatusHistoryDAO(session, user.PlantNr, user.UserId)
	// 校验客户订单数据及状态
	custOrder, err := custOrderDao.SelectOne(custOrderId)
	if err != nil {
		return grmi.NewBusinessError("查询客户订单失败, error:" + err.Error())
	}
	if custOrder == nil {
		return grmi.NewBusinessError("客户订单不存在, 客户订单ID:" + custOrderId)
	}
	if custOrder.OrderStatus.Status != baseModel.WO_STATUS_PLANNED {
		return grmi.NewBusinessError("当前客户订单状态不是已计划, 不允许回撤")
	}
	if err = session.Begin(); err != nil {
		return grmi.NewBusinessError("开启事务失败, error:" + err.Error())
	}
	custOrder.OrderStatus.Status = baseModel.WO_STATUS_UNPLANNED
	err = custOrderStatusDao.UpdateOne(&custOrder.OrderStatus)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新客户订单状态失败, error:" + err.Error())
	}
	custOrderStatusHistory := model.CustOrderStatusHistory{
		CustOrderId:      custOrderId,
		StatusChangeType: model.STATUS_CHANGE_TYPE_OPERATION,
		FromStatus:       baseModel.WO_STATUS_PLANNED,
		ToStatus:         baseModel.WO_STATUS_UNPLANNED,
		ChangeTime:       grmi.DateTime(time.Now()),
	}
	err = custOrderStatusHistoryDao.InsertOne(&custOrderStatusHistory)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("插入客户订单状态变更历史失败, error:" + err.Error())
	}
	_ = session.Commit()
	return nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/pln/CustOrderService.Select
 *
 ******************************************************************************/
func (impl *CustOrderServiceImplement) PageSelect(user *global.User, urlParameters map[string]string) (grmi.PagingResult, error) {

	grmi.Log(user, "/services/pln/implments/CustOrder.service.impl.go", "SelectCustOrder", "查询CustOrder")

	condition := DefaultConditionOfCustOrderAndPaging
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	custOrderId := urlParameters["custOrderId"]
	statusStr := urlParameters["status"]
	startTimeStr := urlParameters["start"]
	endTimeStr := urlParameters["end"]
	workLineId := urlParameters["workLineId"]
	pageNumberStr := urlParameters["pageNumber"]
	pageSizeStr := urlParameters["pageSize"]
	projectId := urlParameters["projectId"]
	productFamilyId := urlParameters["productFamilyId"]
	pageNumber, err := strconv.Atoi(pageNumberStr)
	if err != nil {
		pageNumber = 1
	}
	pageSize, err := strconv.Atoi(pageSizeStr)
	if err != nil {
		pageSize = 10
	}
	status, _ := strconv.Atoi(statusStr)

	dao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
	condition.Fill(urlParameters)
	result, err := dao.PageSelect(custOrderId, workLineId, status, projectId, productFamilyId, startTimeStr, endTimeStr, int64(pageSize), int64(pageNumber))
	if err != nil {
		return grmi.EmptyPagingResult, err
	}
	return result, nil
}

func (impl *CustOrderServiceImplement) SelectCanCancelQty(user *global.User, custOrderId string) (int, error) {
	grmi.Log(user, "/services/pln/implments/CustOrder.service.impl.go", "SelectCanCancelQty", "查询可以取消的数量")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	custOrderDao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
	serialOrderDao := omDal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	productFamilyRelateDao := meDal.NewProductFamilyRelateDAO(session, user.PlantNr, user.UserId)
	custOrder, err := custOrderDao.SelectOne(custOrderId)
	if err != nil {
		return 0, grmi.NewBusinessError("查询客户订单失败, error:" + err.Error())
	}
	if custOrder == nil {
		return 0, grmi.NewBusinessError("客户订单不存在")
	}
	productLi, err := productFamilyRelateDao.SelectProductByFamilyIdForCreateSerialOrder(custOrder.ProjectId, custOrder.ProductFamilyId)
	if err != nil {
		return 0, grmi.NewBusinessError("查询派生下的总成失败, error:" + err.Error())
	}
	productNum := len(productLi)
	serialOrderDataLi, err := serialOrderDao.SelectUnOnGoingSerialOrder(custOrderId)
	if err != nil {
		return 0, grmi.NewBusinessError("查询工单数据失败, error:" + err.Error())
	}
	syncKeyMap := make(map[string][]omModel.VOmSerialorder)
	syncKeyLi := make([]string, 0)
	for _, serialOrderData := range serialOrderDataLi {
		_, exist := syncKeyMap[serialOrderData.SerialOrder.SyncKey]
		if !exist {
			syncKeyLi = append(syncKeyLi, serialOrderData.SerialOrder.SyncKey)
			syncKeyMap[serialOrderData.SerialOrder.SyncKey] = make([]omModel.VOmSerialorder, 0)
		}
		syncKeyMap[serialOrderData.SerialOrder.SyncKey] = append(syncKeyMap[serialOrderData.SerialOrder.SyncKey], serialOrderData)
	}
	var count int
	for _, syncKey := range syncKeyLi {
		if len(syncKeyMap[syncKey]) == productNum {
			count++
		}
	}
	return count, nil
}

func (impl *CustOrderServiceImplement) SplitOrderQty(user *global.User, custOrderId string, qty int) error {
	grmi.Log(user, "/services/pln/implments/CustOrder.service.impl.go", "SelectCanCancelQty", "查询可以取消的数量")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	custOrderDao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
	custOrderStatusDao := dal.NewCustOrderStatusDAO(session, user.PlantNr, user.UserId)
	custOrderQtyDao := dal.NewCustOrderQtyDAO(session, user.PlantNr, user.UserId)
	custOrderStatusHistoryDao := dal.NewCustOrderStatusHistoryDAO(session, user.PlantNr, user.UserId)
	serialOrderDao := omDal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	serialOrderStatusDao := omDal.NewSerialOrderStatusDAO(session, user.PlantNr, user.UserId)
	serialOrderStatusRecDao := omDal.NewSerialOrderStatusRecLstDAO(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)
	productFamilyRelateDao := meDal.NewProductFamilyRelateDAO(session, user.PlantNr, user.UserId)
	snrDao := baseDal.NewSnrDAO(session, user.PlantNr, user.UserId)
	projectDao := meDal.NewProjectDAO(session, user.PlantNr, user.UserId)
	custOrder, err := custOrderDao.SelectOne(custOrderId)
	if err != nil {
		return grmi.NewBusinessError("查询客户订单失败, error:" + err.Error())
	}
	if custOrder == nil {
		return grmi.NewBusinessError("客户订单不存在")
	}
	if custOrder.OrderStatus.Status >= baseModel.WO_STATUS_FINISHED {
		return grmi.NewBusinessError("该客户订单不允许拆单")
	}
	if custOrder.OrderQty.PlanQty-custOrder.OrderQty.CancelQty < qty {
		return grmi.NewBusinessError("客户订单允许拆分的数量不足")
	}
	project, err := projectDao.SelectOne(custOrder.ProjectId)
	if err != nil {
		return grmi.NewBusinessError("查询项目数据失败, error:" + err.Error())
	}
	if project == nil {
		return grmi.NewBusinessError("客户订单绑定的项目不存在")
	}
	if custOrder.OrderStatus.Status < baseModel.WO_STATUS_LOCKED {
		if err = session.Begin(); err != nil {
			return grmi.NewBusinessError("开启事务失败, error:" + err.Error())
		}
		newCustOrderId, err := snrDao.GetNextSnr(project.CustOrderSnr)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("生成新的客户订单流水号失败, error:" + err.Error())
		}
		newCustOrder := model.CustOrder{
			SourceId:           custOrderId,
			CustOrderId:        newCustOrderId,
			ProductFamilyId:    custOrder.ProductFamilyId,
			PartId:             custOrder.PartId,
			OemOrderId:         custOrder.OemOrderId,
			OrderType:          custOrder.OrderType,
			OrderInfo:          custOrder.OrderInfo,
			OrderTime:          custOrder.OrderTime,
			DeliveryTime:       custOrder.DeliveryTime,
			ProjectId:          custOrder.ProjectId,
			ConfigValue:        custOrder.ConfigValue,
			ModelValue:         custOrder.ModelValue,
			ColorValue:         custOrder.ColorValue,
			HandleStatus:       custOrder.HandleStatus,
			VinPrefix:          custOrder.VinPrefix,
			VinNrFrom:          custOrder.VinNrFrom,
			VinNrTo:            custOrder.VinNrTo,
			Vin:                custOrder.Vin,
			PlanQty:            qty,
			DeliveryDate:       custOrder.DeliveryDate,
			DeliveryDateTime:   custOrder.DeliveryDateTime,
			OemSeq:             custOrder.OemSeq,
			AssemblyLine:       custOrder.AssemblyLine,
			UnloadingPoint:     custOrder.UnloadingPoint,
			CalloffId:          custOrder.CalloffId,
			CalloffDateTime:    custOrder.CalloffDateTime,
			ConsigneePlant:     custOrder.ConsigneePlant,
			ConsigneeCompany:   custOrder.ConsigneeCompany,
			ConsumeCompany:     custOrder.ConsumeCompany,
			ConsumePlant:       custOrder.ConsumePlant,
			UnloadingPlace:     custOrder.UnloadingPlace,
			VehicleIdSet:       custOrder.VehicleIdSet,
			VehicleId:          custOrder.VehicleId,
			FixStartTimeToggle: custOrder.FixStartTimeToggle,
			WorkLineId:         custOrder.WorkLineId,
			QuantityPerHour:    custOrder.QuantityPerHour,
			CtrlPara1:          1,
		}
		err = custOrderDao.InsertOne(&newCustOrder)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("写入拆分出新的客户订单失败, error:" + err.Error())
		}
		newCustOrderStatus := model.CustOrderStatus{
			CustOrderId: newCustOrderId,
			Status:      baseModel.WO_STATUS_UNPLANNED,
		}
		err = custOrderStatusDao.InsertOne(&newCustOrderStatus)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("写入拆分出新的客户订单状态数据失败, error:" + err.Error())
		}
		newCustOrderQty := model.CustOrderQty{
			CustOrderId: newCustOrderId,
			PlanQty:     qty,
		}
		err = custOrderQtyDao.InsertOne(&newCustOrderQty)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("写入拆分出新的客户订单数量数据失败, error:" + err.Error())
		}
		custOrder.PlanQty = custOrder.PlanQty - qty
		err = custOrderDao.UpdateOne(custOrder)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新客户订单数据失败, error:" + err.Error())
		}
		custOrder.OrderQty.PlanQty = custOrder.OrderQty.PlanQty - qty
		custOrder.OrderQty.ReleasedQty = custOrder.OrderQty.ReleasedQty - qty
		err = custOrderQtyDao.UpdateOne(&custOrder.OrderQty)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新客户订单数量数据失败, error:" + err.Error())
		}
		if custOrder.OrderQty.PlanQty == custOrder.OrderQty.CancelQty {
			custOrderStatusRec := model.CustOrderStatusHistory{
				CustOrderId:      custOrderId,
				StatusChangeType: model.STATUS_CHANGE_TYPE_SPLIT,
				FromStatus:       custOrder.OrderStatus.Status,
				ToStatus:         baseModel.WO_STATUS_CANCELED,
				ChangeTime:       grmi.DateTime(time.Now()),
			}
			err = custOrderStatusHistoryDao.InsertOne(&custOrderStatusRec)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("写入客户订单状态变更历史失败, error:" + err.Error())
			}
			custOrder.OrderStatus.Status = baseModel.WO_STATUS_CANCELED
			err = custOrderStatusDao.UpdateOne(&custOrder.OrderStatus)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("更新客户订单状态失败, error:" + err.Error())
			}
		} else if custOrder.OrderQty.PlanQty == custOrder.OrderQty.ActQty+custOrder.OrderQty.CancelQty {
			custOrderStatusRec := model.CustOrderStatusHistory{
				CustOrderId:      custOrderId,
				StatusChangeType: model.STATUS_CHANGE_TYPE_SPLIT,
				FromStatus:       custOrder.OrderStatus.Status,
				ToStatus:         baseModel.WO_STATUS_FINISHED,
				ChangeTime:       grmi.DateTime(time.Now()),
			}
			err = custOrderStatusHistoryDao.InsertOne(&custOrderStatusRec)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("写入客户订单状态变更历史失败, error:" + err.Error())
			}
			custOrder.OrderStatus.Status = baseModel.WO_STATUS_FINISHED
			err = custOrderStatusDao.UpdateOne(&custOrder.OrderStatus)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("更新客户订单状态失败, error:" + err.Error())
			}
		}
	}

	productLi, err := productFamilyRelateDao.SelectProductByFamilyIdForCreateSerialOrder(custOrder.ProjectId, custOrder.ProductFamilyId)
	if err != nil {
		return grmi.NewBusinessError("查询派生下的总成失败, error:" + err.Error())
	}
	productNum := len(productLi)
	serialOrderDataLi, err := serialOrderDao.SelectUnOnGoingSerialOrder(custOrderId)
	if err != nil {
		return grmi.NewBusinessError("查询工单数据失败, error:" + err.Error())
	}
	syncKeyMap := make(map[string][]omModel.VOmSerialorder)
	syncKeyLi := make([]string, 0)
	for _, serialOrderData := range serialOrderDataLi {
		_, exist := syncKeyMap[serialOrderData.SerialOrder.SyncKey]
		if !exist {
			syncKeyLi = append(syncKeyLi, serialOrderData.SerialOrder.SyncKey)
			syncKeyMap[serialOrderData.SerialOrder.SyncKey] = make([]omModel.VOmSerialorder, 0)
		}
		syncKeyMap[serialOrderData.SerialOrder.SyncKey] = append(syncKeyMap[serialOrderData.SerialOrder.SyncKey], serialOrderData)
	}
	var count int
	splitSyncKeyLi := make([]string, 0)
	for _, syncKey := range syncKeyLi {
		if len(syncKeyMap[syncKey]) == productNum {
			splitSyncKeyLi = append(splitSyncKeyLi, syncKey)
			count++
		}
	}
	impl.QuickSort(splitSyncKeyLi)
	if count < qty {
		return grmi.NewBusinessError("当前客户订单可取消数量小于需要取消数量")
	}
	if err = session.Begin(); err != nil {
		return grmi.NewBusinessError("开启事务失败, error:" + err.Error())
	}
	newCustOrderId, err := snrDao.GetNextSnr(project.CustOrderSnr)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("生成新的客户订单流水号失败, error:" + err.Error())
	}
	newCustOrder := model.CustOrder{
		SourceId:           custOrderId,
		CustOrderId:        newCustOrderId,
		ProductFamilyId:    custOrder.ProductFamilyId,
		PartId:             custOrder.PartId,
		OemOrderId:         custOrder.OemOrderId,
		OrderType:          custOrder.OrderType,
		OrderInfo:          custOrder.OrderInfo,
		OrderTime:          custOrder.OrderTime,
		DeliveryTime:       custOrder.DeliveryTime,
		ProjectId:          custOrder.ProjectId,
		ConfigValue:        custOrder.ConfigValue,
		ModelValue:         custOrder.ModelValue,
		ColorValue:         custOrder.ColorValue,
		HandleStatus:       custOrder.HandleStatus,
		VinPrefix:          custOrder.VinPrefix,
		VinNrFrom:          custOrder.VinNrFrom,
		VinNrTo:            custOrder.VinNrTo,
		Vin:                custOrder.Vin,
		PlanQty:            qty,
		DeliveryDate:       custOrder.DeliveryDate,
		DeliveryDateTime:   custOrder.DeliveryDateTime,
		OemSeq:             custOrder.OemSeq,
		AssemblyLine:       custOrder.AssemblyLine,
		UnloadingPoint:     custOrder.UnloadingPoint,
		CalloffId:          custOrder.CalloffId,
		CalloffDateTime:    custOrder.CalloffDateTime,
		ConsigneePlant:     custOrder.ConsigneePlant,
		ConsigneeCompany:   custOrder.ConsigneeCompany,
		ConsumeCompany:     custOrder.ConsumeCompany,
		ConsumePlant:       custOrder.ConsumePlant,
		UnloadingPlace:     custOrder.UnloadingPlace,
		VehicleIdSet:       custOrder.VehicleIdSet,
		VehicleId:          custOrder.VehicleId,
		FixStartTimeToggle: custOrder.FixStartTimeToggle,
		WorkLineId:         custOrder.WorkLineId,
		QuantityPerHour:    custOrder.QuantityPerHour,
		CtrlPara1:          1,
	}
	err = custOrderDao.InsertOne(&newCustOrder)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("写入拆分出新的客户订单失败, error:" + err.Error())
	}
	newCustOrderStatus := model.CustOrderStatus{
		CustOrderId: newCustOrderId,
		Status:      baseModel.WO_STATUS_UNPLANNED,
	}
	err = custOrderStatusDao.InsertOne(&newCustOrderStatus)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("写入拆分出新的客户订单状态数据失败, error:" + err.Error())
	}
	newCustOrderQty := model.CustOrderQty{
		CustOrderId: newCustOrderId,
		PlanQty:     qty,
	}
	err = custOrderQtyDao.InsertOne(&newCustOrderQty)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("写入拆分出新的客户订单数量数据失败, error:" + err.Error())
	}
	custOrder.PlanQty = custOrder.PlanQty - qty
	err = custOrderDao.UpdateOne(custOrder)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新客户订单数据失败, error:" + err.Error())
	}
	custOrder.OrderQty.PlanQty = custOrder.OrderQty.PlanQty - qty
	custOrder.OrderQty.ReleasedQty = custOrder.OrderQty.ReleasedQty - qty
	err = custOrderQtyDao.UpdateOne(&custOrder.OrderQty)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新客户订单数量数据失败, error:" + err.Error())
	}
	if custOrder.OrderQty.PlanQty == custOrder.OrderQty.CancelQty {
		custOrderStatusRec := model.CustOrderStatusHistory{
			CustOrderId:      custOrderId,
			StatusChangeType: model.STATUS_CHANGE_TYPE_SPLIT,
			FromStatus:       custOrder.OrderStatus.Status,
			ToStatus:         baseModel.WO_STATUS_CANCELED,
			ChangeTime:       grmi.DateTime(time.Now()),
		}
		err = custOrderStatusHistoryDao.InsertOne(&custOrderStatusRec)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("写入客户订单状态变更历史失败, error:" + err.Error())
		}
		custOrder.OrderStatus.Status = baseModel.WO_STATUS_CANCELED
		err = custOrderStatusDao.UpdateOne(&custOrder.OrderStatus)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新客户订单状态失败, error:" + err.Error())
		}
	} else if custOrder.OrderQty.PlanQty == custOrder.OrderQty.ActQty+custOrder.OrderQty.CancelQty {
		custOrderStatusRec := model.CustOrderStatusHistory{
			CustOrderId:      custOrderId,
			StatusChangeType: model.STATUS_CHANGE_TYPE_SPLIT,
			FromStatus:       custOrder.OrderStatus.Status,
			ToStatus:         baseModel.WO_STATUS_FINISHED,
			ChangeTime:       grmi.DateTime(time.Now()),
		}
		err = custOrderStatusHistoryDao.InsertOne(&custOrderStatusRec)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("写入客户订单状态变更历史失败, error:" + err.Error())
		}
		custOrder.OrderStatus.Status = baseModel.WO_STATUS_FINISHED
		err = custOrderStatusDao.UpdateOne(&custOrder.OrderStatus)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新客户订单状态失败, error:" + err.Error())
		}
	}
	for i := 0; i < qty; i++ {
		cancelSyncKey := splitSyncKeyLi[i]
		orderDataLi, err := serialOrderDao.Select([]grmi.Predicate{omMeta.SerialOrder_SyncKey.NewPredicate(grmi.Equal, cancelSyncKey)}, nil)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("查询工单数据失败, error:" + err.Error())
		}
		for _, serialOrderData := range orderDataLi {
			serialOrderData.CustOrderId = newCustOrderId
			resultLi := strings.Split(serialOrderData.SyncKey, "-")
			if len(resultLi) < 2 {
				_ = session.Rollback()
				return grmi.NewBusinessError("工单SyncKey格式错误，工单ID:" + serialOrderData.SerialOrderId)
			}
			serialOrderData.SyncKey = newCustOrderId + "-" + resultLi[len(resultLi)-1]
			err = serialOrderDao.UpdateOne(&serialOrderData)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("更新工单数据失败, error:" + err.Error())
			}
			serialOrderStatus := serialOrderData.SerialOrderStatus
			statusRec := omModel.SerialOrderStatusRecLst{
				SerialOrderId: serialOrderData.SerialOrderId,
				PrevStatus:    serialOrderStatus.Status,
				Status:        baseModel.WO_STATUS_UNPLANNED,
				Remark1:       "SPLIT",
			}
			err = serialOrderStatusRecDao.InsertOne(&statusRec)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("写入工单状态变更记录失败, error:" + err.Error())
			}
			serialOrderStatus.Status = baseModel.WO_STATUS_UNPLANNED
			err = serialOrderStatusDao.UpdateOneWithStatus(&serialOrderStatus, baseModel.WO_STATUS_RELEASED)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("更新工单状态失败, error:" + err.Error())
			}
			poUpdateData := omModel.SerialOrderPOLst{
				Status: baseModel.WO_STATUS_UNPLANNED,
			}
			err = serialOrderPoDao.UpdateWhere([]grmi.Predicate{omMeta.SerialOrderPOLst_SerialOrderId.NewPredicate(grmi.Equal, serialOrderData.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_UNPLANNED,
			}
			err = serialOrderStepDao.UpdateWhere([]grmi.Predicate{omMeta.SerialOrderStepLst_SerialOrderId.NewPredicate(grmi.Equal, serialOrderData.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_UNPLANNED,
			}
			err = serialOrderOPDetailDao.UpdateWhere([]grmi.Predicate{omMeta.SerialOrderOPDetail_SerialOrderId.NewPredicate(grmi.Equal, serialOrderData.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, serialOrderData.SerialOrderId),
			}, nil)
			if err != nil {
				return grmi.NewBusinessError("查询工单下的预装工单失败, 错误：" + err.Error())
			}
			for _, preOrder := range preSerialOrderLi {
				preOrder.CustOrderId = newCustOrderId
				err = serialOrderDao.UpdateOne(&preOrder)
				if err != nil {
					return grmi.NewBusinessError("更新预装工单数据失败, 错误:" + err.Error())
				}
				if preOrder.SerialOrderStatus.Status > baseModel.WO_STATUS_RELEASED {
					return grmi.NewBusinessError("预装工单已经不允许取消, 工单ID:" + preOrder.SerialOrderId)
				}
				originStatus := preOrder.SerialOrderStatus.Status
				statusRec = omModel.SerialOrderStatusRecLst{
					SerialOrderId: preOrder.SerialOrderId,
					Status:        baseModel.WO_STATUS_UNPLANNED,
					PrevStatus:    preOrder.SerialOrderStatus.Status,
				}
				preOrder.SerialOrderStatus.Status = baseModel.WO_STATUS_UNPLANNED
				err = serialOrderStatusRecDao.InsertOne(&statusRec)
				if err != nil {
					_ = session.Rollback()
					return grmi.NewBusinessError("插入预装工单状态变更记录失败, error:" + err.Error())
				}
				err = serialOrderStatusDao.UpdateOneWithStatus(&preOrder.SerialOrderStatus, baseModel.WO_STATUS_RELEASED)
				if err != nil {
					_ = session.Rollback()
					return grmi.NewBusinessError("更新预装工单状态失败， error:" + err.Error())
				}
				if originStatus == baseModel.WO_STATUS_RELEASED {
					poUpdateData := &omModel.SerialOrderPOLst{
						Status: baseModel.WO_STATUS_UNPLANNED,
					}
					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_UNPLANNED,
					}
					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_UNPLANNED,
					}
					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())
					}
				}
			}
		}
	}
	_ = session.Commit()
	return nil
}



func (impl *CustOrderServiceImplement) QuickSort(values []string) {
	if len(values) <= 1 {
		return
	}
	mid, i := values[0], 1
	tempLi := strings.Split(mid, "-")
	midNum, _ := strconv.Atoi(tempLi[len(tempLi)-1])
	head, tail := 0, len(values)-1
	for head < tail {
		tempLi = strings.Split(values[i], "-")
		iNum, _ := strconv.Atoi(tempLi[len(tempLi)-1])
		if iNum < midNum {
			values[i], values[tail] = values[tail], values[i]
			tail--
		} else {
			values[i], values[head] = values[head], values[i]
			head++
			i++
		}
	}
	values[head] = mid
	impl.QuickSort(values[:head])
	impl.QuickSort(values[head+1:])
}

func (impl *CustOrderServiceImplement) QuickSortProductData(values []model.HourProductData) {
	if len(values) <= 1 {
		return
	}
	mid, i := values[0], 1
	midTime := mid.LastDoneTime
	head, tail := 0, len(values)-1
	for head < tail {
		iTime := values[i].LastDoneTime
		if iTime.After(midTime) {
			values[i], values[tail] = values[tail], values[i]
			tail--
		} else {
			values[i], values[head] = values[head], values[i]
			head++
			i++
		}
	}
	values[head] = mid
	impl.QuickSortProductData(values[:head])
	impl.QuickSortProductData(values[head+1:])
}

// AutoScheduler 自动排程 同时对客户订单进行落库
func (impl *CustOrderServiceImplement) AutoScheduler(user *global.User, session *xorm.Session, workLineId string, startDate time.Time, endDate time.Time, unplannedCustOrderLi []model.CustOrder) ([]model.CustOrder, error) {
	var (
		schedEngine schedule.SchedulerSrv

		err error
	)
	custOrderIdMap := make(map[string]interface{})
	returnCustOrderLi := make([]model.CustOrder, 0, len(unplannedCustOrderLi))
	custOrderMap := make(map[string]*model.CustOrder)
	for index, custOrder := range unplannedCustOrderLi {
		custOrderMap[custOrder.CustOrderId] = &unplannedCustOrderLi[index]
		custOrderIdMap[custOrder.CustOrderId] = nil
	}
	endDate = endDate.Add(1 * time.Second)
	schedEngine = schedule.SchedulerSrv{PlantNr: user.PlantNr, StartDate: startDate, EndDate: endDate}
	schedEngine.Tmsrv.StartDate = startDate
	schedEngine.Tmsrv.EndDate = endDate
	custOrderDao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
	custOrderQtyDao := dal.NewCustOrderQtyDAO(session, user.PlantNr, user.UserId)
	custOrderStatusDao := dal.NewCustOrderStatusDAO(session, user.PlantNr, user.UserId)
	// 加载激活的项目主数据
	err = schedEngine.LoadProjectData()
	if err != nil {
		return nil, err
	}
	// 加载时间模型，基于调度引擎指定的时间区间
	err = schedEngine.LoadTimeModel(session, workLineId)

	// 加载产品换型主数据
	err = schedEngine.LoadSetupData()
	if err != nil {
		return nil, err
	}
	// 加载产线主数据
	err = schedEngine.LoadWorkLineData(workLineId)
	if err != nil {
		return nil, err
	}
	// 加载产线班组计划出勤数据
	err = schedEngine.LoadWorkLineWorkShiftData()
	if err != nil {
		return nil, err
	}
	// 生成产线的时间曲线
	err = schedEngine.GenerateWorkLineTimeCurve()
	if err != nil {
		return nil, err
	}
	// 加载工单数据（调度任务）
	err = schedEngine.LoadSchedCustTask(session, workLineId, unplannedCustOrderLi)
	if err != nil {
		return nil, err
	}
	// 对调度任务进行排序
	schedEngine.SortUnplannedCustOrder()
	// 依次调度未计划工单
	err = schedEngine.AutoSchedule()
	if err != nil {
		return nil, err
	}

	// 将已计划的客户订单进行落库 状态设置为26
	for _, plannedTask := range schedEngine.WorklineDict[workLineId].SchedTaskArray {
		//过滤订单状态大于20的订单
		//if plannedTask.CustOrderStatus.Status > baseModel.WO_STATUS_PLANNED {
		//	continue
		//}
		_, exist := custOrderIdMap[plannedTask.TaskId]
		if !exist {
			continue
		}
		// 保存客户订单数据
		custOrder := custOrderMap[plannedTask.TaskId]
		custOrder.PlanEndDate = grmi.Date(plannedTask.SchedEndTime)
		custOrder.PlanStartTime = grmi.DateTime(plannedTask.SchedStartTime)
		custOrder.PlanEndTime = grmi.DateTime(plannedTask.SchedEndTime)
		err = custOrderDao.InsertOne(custOrder)
		if err != nil {
			return nil, grmi.NewBusinessError("保存客户订单数据失败, 错误:" + err.Error())
		}
		custOrderStatus := custOrder.OrderStatus
		custOrderStatus.Status = baseModel.WO_STATUS_LOCKED
		err = custOrderStatusDao.InsertOne(&custOrderStatus)
		if err != nil {
			return nil, grmi.NewBusinessError("保存客户订单状态失败, 错误:" + err.Error())
		}
		err = custOrderQtyDao.InsertOne(&custOrder.OrderQty)
		if err != nil {
			return nil, grmi.NewBusinessError("保存客户订单数量失败, 错误:" + err.Error())
		}
		returnCustOrderLi = append(returnCustOrderLi, *custOrder)
	}
	return returnCustOrderLi, nil
}
