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"
	"LAPP_ACURA_MOM_BACKEND/infra/logger"
	baseMeta "LAPP_ACURA_MOM_BACKEND/meta/base"
	meMeta "LAPP_ACURA_MOM_BACKEND/meta/me"
	meta "LAPP_ACURA_MOM_BACKEND/meta/om"
	baseModel "LAPP_ACURA_MOM_BACKEND/models/base"
	model "LAPP_ACURA_MOM_BACKEND/models/om"
	"LAPP_ACURA_MOM_BACKEND/utils"
	"github.com/go-xorm/xorm"
	uuid "github.com/iris-contrib/go.uuid"
	"strconv"
	"strings"
	"time"
)

// CreateBatchSerialOrder 批量创建工单
func (impl *SerialOrderServiceImplement) CreateBatchSerialOrder(user *global.User, productId string, projectId string, workLineId string, qty int, preSchKey int, priority int, planDate string) error {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	writeSerialOrderLi := make([]model.SerialOrder, 0)
	writeSerialOrderStatusLi := make([]model.SerialOrderStatus, 0)
	writeSerialOrderStepLi := make([]model.SerialOrderStepLst, 0)
	writeSerialOrderPoLi := make([]model.SerialOrderPOLst, 0)
	writeSerialOrderOpLi := make([]model.SerialOrderOPDetail, 0)
	writeLabelHeadLi := make([]baseModel.LabelHead, 0)
	writeLabelDetailLi := make([]baseModel.LabelDetail, 0)
	planDateT, err := time.ParseInLocation(grmi.DateOutFormat, planDate, utils.TimezoneLocation)
	if err != nil {
		return grmi.NewBusinessError("计划日期格式错误")
	}
	productDao := meDal.NewProductDAO(session, user.PlantNr, user.UserId)
	serialOrderDao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	serialOrderStatusDao := dal.NewSerialOrderStatusDAO(session, user.PlantNr, user.UserId)
	snrDao := baseDal.NewSnrDAO(session, user.PlantNr, user.UserId)
	projectDao := meDal.NewProjectDAO(session, user.PlantNr, user.UserId)
	labelHeadDao := baseDal.NewLabelHeadDAO(session, user.PlantNr, user.UserId)
	labelDetailDao := baseDal.NewLabelDetailDAO(session, user.PlantNr, user.UserId)
	serialOrderPoDao := dal.NewSerialOrderPOLstDAO(session, user.PlantNr, user.UserId)
	serialOrderStepDao := dal.NewSerialOrderStepLstDAO(session, user.PlantNr, user.UserId)
	serialOrderOPDetailDao := dal.NewSerialOrderOPDetailDAO(session, user.PlantNr, user.UserId)
	product, err := productDao.SelectOne(productId, projectId)
	if err != nil {
		return grmi.NewBusinessError("查询总成数据失败, error:" + err.Error())
	}
	if product == nil {
		return grmi.NewBusinessError("总成不存在")
	}
	project, err := projectDao.SelectOne(projectId)
	if err != nil {
		return grmi.NewBusinessError("查询项目数据失败, error:" + err.Error())
	}
	if product.MultiWorkLineToggle {
		productWorkLineDao := meDal.NewProductWorkLineLstDAO(session, user.PlantNr, user.UserId)
		workLineLi, err := productWorkLineDao.Select([]grmi.Predicate{
			meMeta.ProductWorkLineLst_ProductId.NewPredicate(grmi.Equal, productId),
			meMeta.ProductWorkLineLst_ProjectId.NewPredicate(grmi.Equal, projectId),
		}, nil)
		if err != nil {
			return grmi.NewBusinessError("查询总成可生产产线失败, 错误:" + err.Error())
		}
		var canProduct bool
		for _, workLine := range workLineLi {
			if workLine.WorkLineId == workLineId {
				canProduct = true
				break
			}
		}
		if !canProduct {
			return grmi.NewBusinessError("该总成不能在指定的产线上生产！")
		}
	} else {
		if product.DefaultWorkLineId != workLineId {
			return grmi.NewBusinessError("该总成不能在指定的产线上生产！")
		}
	}
	insertSerialOrderLi := make([]model.SerialOrder, 0, qty)

	if priority != 0 {
		for i := 1; i <= qty; i++ {
			serialOrderId := product.MachineCode + "$serialNumber$" + product.ProductType + product.ColorValue
			insertOrder := model.SerialOrder{
				SerialOrderId:  serialOrderId,
				ArtId:          productId,
				ProjectId:      projectId,
				Descr:          product.Descr,
				PreSchedKey:    0,
				SchedKey:       0,
				Priority:       priority,
				OrderType:      baseModel.ODER_TYPE_INTERVAL,
				PlanResourceId: workLineId,
				UsedResourceId: workLineId,
				PlanQty:        1,
				PlanStartDate:  grmi.Date(planDateT),
				PlanEndDate:    grmi.Date(planDateT),
				PlanStartTime:  grmi.DateTime(planDateT),
				PlanEndTime:    grmi.DateTime(planDateT),
				PickingFlag:    product.PickingFlag,
			}
			insertOrder.SerialOrderStatus = model.SerialOrderStatus{
				SerialOrderId: serialOrderId,
				Status:        baseModel.WO_STATUS_RELEASED,
			}
			insertSerialOrderLi = append(insertSerialOrderLi, insertOrder)
		}
	} else {
		serialOrder, err := serialOrderDao.Select([]grmi.Predicate{meta.SerialOrder_SchedKey.NewPredicate(grmi.Equal, preSchKey)}, nil)
		if err != nil {
			return grmi.NewBusinessError("查询工单数据失败, error:" + err.Error())
		}
		if serialOrder == nil {
			return grmi.NewBusinessError("指定前序的工单不存在")
		}
		schedKeyLi := make([]interface{}, 0, qty)
		for i := 1; i <= qty; i++ {
			schedKeyLi = append(schedKeyLi, preSchKey+i)
		}
		serialOrderLi, err := serialOrderDao.Select([]grmi.Predicate{meta.SerialOrder_SchedKey.NewPredicate(grmi.Include, schedKeyLi...)}, nil)
		if err != nil {
			return grmi.NewBusinessError("查询工单数据失败, error:" + err.Error())
		}
		if len(serialOrderLi) > 0 {
			return grmi.NewBusinessError("生成的排序Key已存在工单")
		}
		for i := 1; i <= qty; i++ {
			serialOrderId := product.MachineCode + "$serialNumber$" + product.ProductType + product.ColorValue
			if int64(preSchKey+i)%100 == 0 {
				return grmi.NewBusinessError("该调度Key为序列工单预留, 调度Key:" + strconv.Itoa(preSchKey+i))
			}
			insertOrder := model.SerialOrder{
				SerialOrderId:  serialOrderId,
				ArtId:          productId,
				ProjectId:      projectId,
				Descr:          product.Descr,
				PreSchedKey:    int64(preSchKey + i - 1),
				SchedKey:       int64(preSchKey + i),
				Priority:       0,
				OrderType:      baseModel.ODER_TYPE_INTERVAL,
				PlanResourceId: workLineId,
				UsedResourceId: workLineId,
				PlanQty:        1,
				PlanStartDate:  grmi.Date(planDateT),
				PlanEndDate:    grmi.Date(planDateT),
				PlanStartTime:  grmi.DateTime(planDateT),
				PlanEndTime:    grmi.DateTime(planDateT),
				PickingFlag:    product.PickingFlag,
			}
			insertOrder.SerialOrderStatus = model.SerialOrderStatus{
				SerialOrderId: serialOrderId,
				Status:        baseModel.WO_STATUS_RELEASED,
			}
			insertSerialOrderLi = append(insertSerialOrderLi, insertOrder)
		}
	}
	var preSerialOrder model.SerialOrder
	for index, serialOrder := range insertSerialOrderLi {
		if index == 0 {
			err = impl.GenerateProductCraft(user, session, &serialOrder)
			if err != nil {
				return grmi.NewBusinessError("生成工单工艺数据失败, 错误：" + err.Error())
			}
			preSerialOrder = serialOrder
			preSerialOrder.PreOrderLi = make([]model.SerialOrder, 0, len(serialOrder.PreOrderLi))
			preSerialOrder.SerialOrderPOLstLi = make([]model.SerialOrderPOLst, len(serialOrder.SerialOrderPOLstLi), len(serialOrder.SerialOrderPOLstLi))
			preSerialOrder.SerialOrderStepLstLi = make([]model.SerialOrderStepLst, len(serialOrder.SerialOrderStepLstLi), len(serialOrder.SerialOrderStepLstLi))
			preSerialOrder.SerialOrderOPDetailLi = make([]model.SerialOrderOPDetail, len(serialOrder.SerialOrderOPDetailLi), len(serialOrder.SerialOrderOPDetailLi))
			preSerialOrder.LabelHeadLi = make([]baseModel.LabelHead, len(serialOrder.LabelHeadLi), len(serialOrder.LabelHeadLi))
			preSerialOrder.LabelDetailLi = make([]baseModel.LabelDetail, len(serialOrder.LabelDetailLi), len(serialOrder.LabelDetailLi))
			copy(preSerialOrder.SerialOrderPOLstLi, serialOrder.SerialOrderPOLstLi)
			copy(preSerialOrder.SerialOrderStepLstLi, serialOrder.SerialOrderStepLstLi)
			copy(preSerialOrder.SerialOrderOPDetailLi, serialOrder.SerialOrderOPDetailLi)
			copy(preSerialOrder.LabelHeadLi, serialOrder.LabelHeadLi)
			copy(preSerialOrder.LabelDetailLi, serialOrder.LabelDetailLi)
			for _, preOrder := range serialOrder.PreOrderLi {
				newPreOrder := preOrder
				newPreOrder.SerialOrderPOLstLi = make([]model.SerialOrderPOLst, len(preOrder.SerialOrderPOLstLi), len(preOrder.SerialOrderPOLstLi))
				newPreOrder.SerialOrderStepLstLi = make([]model.SerialOrderStepLst, len(preOrder.SerialOrderStepLstLi), len(preOrder.SerialOrderStepLstLi))
				newPreOrder.SerialOrderOPDetailLi = make([]model.SerialOrderOPDetail, len(preOrder.SerialOrderOPDetailLi), len(preOrder.SerialOrderOPDetailLi))
				newPreOrder.LabelHeadLi = make([]baseModel.LabelHead, len(preOrder.LabelHeadLi), len(preOrder.LabelHeadLi))
				newPreOrder.LabelDetailLi = make([]baseModel.LabelDetail, len(preOrder.LabelDetailLi), len(preOrder.LabelDetailLi))
				copy(newPreOrder.SerialOrderPOLstLi, preOrder.SerialOrderPOLstLi)
				copy(newPreOrder.SerialOrderStepLstLi, preOrder.SerialOrderStepLstLi)
				copy(newPreOrder.SerialOrderOPDetailLi, preOrder.SerialOrderOPDetailLi)
				copy(newPreOrder.LabelHeadLi, preOrder.LabelHeadLi)
				copy(newPreOrder.LabelDetailLi, preOrder.LabelDetailLi)
				preSerialOrder.PreOrderLi = append(preSerialOrder.PreOrderLi, newPreOrder)
			}
		} else {
			serialOrder.PreOrderLi = make([]model.SerialOrder, 0, len(preSerialOrder.PreOrderLi))
			serialOrder.SerialOrderPOLstLi = make([]model.SerialOrderPOLst, len(preSerialOrder.SerialOrderPOLstLi), len(preSerialOrder.SerialOrderPOLstLi))
			serialOrder.SerialOrderStepLstLi = make([]model.SerialOrderStepLst, len(preSerialOrder.SerialOrderStepLstLi), len(preSerialOrder.SerialOrderStepLstLi))
			serialOrder.SerialOrderOPDetailLi = make([]model.SerialOrderOPDetail, len(preSerialOrder.SerialOrderOPDetailLi), len(preSerialOrder.SerialOrderOPDetailLi))
			serialOrder.LabelHeadLi = make([]baseModel.LabelHead, len(preSerialOrder.LabelHeadLi), len(preSerialOrder.LabelHeadLi))
			serialOrder.LabelDetailLi = make([]baseModel.LabelDetail, len(preSerialOrder.LabelDetailLi), len(preSerialOrder.LabelDetailLi))
			copy(serialOrder.SerialOrderPOLstLi, preSerialOrder.SerialOrderPOLstLi)
			copy(serialOrder.SerialOrderStepLstLi, preSerialOrder.SerialOrderStepLstLi)
			copy(serialOrder.SerialOrderOPDetailLi, preSerialOrder.SerialOrderOPDetailLi)
			copy(serialOrder.LabelHeadLi, preSerialOrder.LabelHeadLi)
			copy(serialOrder.LabelDetailLi, preSerialOrder.LabelDetailLi)
			for _, preOrder := range preSerialOrder.PreOrderLi {
				newPreOrder := preOrder
				newPreOrder.SerialOrderPOLstLi = make([]model.SerialOrderPOLst, len(preOrder.SerialOrderPOLstLi), len(preOrder.SerialOrderPOLstLi))
				newPreOrder.SerialOrderStepLstLi = make([]model.SerialOrderStepLst, len(preOrder.SerialOrderStepLstLi), len(preOrder.SerialOrderStepLstLi))
				newPreOrder.SerialOrderOPDetailLi = make([]model.SerialOrderOPDetail, len(preOrder.SerialOrderOPDetailLi), len(preOrder.SerialOrderOPDetailLi))
				newPreOrder.LabelHeadLi = make([]baseModel.LabelHead, len(preOrder.LabelHeadLi), len(preOrder.LabelHeadLi))
				newPreOrder.LabelDetailLi = make([]baseModel.LabelDetail, len(preOrder.LabelDetailLi), len(preOrder.LabelDetailLi))
				copy(newPreOrder.SerialOrderPOLstLi, preOrder.SerialOrderPOLstLi)
				copy(newPreOrder.SerialOrderStepLstLi, preOrder.SerialOrderStepLstLi)
				copy(newPreOrder.SerialOrderOPDetailLi, preOrder.SerialOrderOPDetailLi)
				copy(newPreOrder.LabelHeadLi, preOrder.LabelHeadLi)
				copy(newPreOrder.LabelDetailLi, preOrder.LabelDetailLi)
				serialOrder.PreOrderLi = append(serialOrder.PreOrderLi, newPreOrder)
			}
		}
		insertSerialOrderLi[index] = serialOrder
	}
	if err = session.Begin(); err != nil {
		return grmi.NewBusinessError("开启事务失败, 错误:" + err.Error())
	}
	for _, serialOrder := range insertSerialOrderLi {
		serialNumber, err := snrDao.GetNextSnrWithTime(project.INTSerialOrderSnr, serialOrder.PlanStartTime.Restore())
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("生成工单流水号失败, error:" + err.Error())
		}
		impl.ReplaceData(&serialOrder, serialNumber, false)
		for index, preOrder := range serialOrder.PreOrderLi {
			preOrder.MainOrderId = serialOrder.SerialOrderId
			serialNumber, err = snrDao.GetNextSnr(project.PreOrderSnr)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("获取流水号失败，错误:" + err.Error())
			}
			impl.ReplaceData(&preOrder, serialNumber, true)
			serialOrder.PreOrderLi[index] = preOrder
		}
		writeSerialOrderLi = append(writeSerialOrderLi, serialOrder)
		writeSerialOrderStatusLi = append(writeSerialOrderStatusLi, serialOrder.SerialOrderStatus)
		writeSerialOrderPoLi = append(writeSerialOrderPoLi, serialOrder.SerialOrderPOLstLi...)
		writeSerialOrderStepLi = append(writeSerialOrderStepLi, serialOrder.SerialOrderStepLstLi...)
		writeSerialOrderOpLi = append(writeSerialOrderOpLi, serialOrder.SerialOrderOPDetailLi...)
		writeLabelHeadLi = append(writeLabelHeadLi, serialOrder.LabelHeadLi...)
		writeLabelDetailLi = append(writeLabelDetailLi, serialOrder.LabelDetailLi...)
		for _, preOrder := range serialOrder.PreOrderLi {
			writeSerialOrderLi = append(writeSerialOrderLi, preOrder)
			writeSerialOrderStatusLi = append(writeSerialOrderStatusLi, preOrder.SerialOrderStatus)
			writeSerialOrderPoLi = append(writeSerialOrderPoLi, preOrder.SerialOrderPOLstLi...)
			writeSerialOrderStepLi = append(writeSerialOrderStepLi, preOrder.SerialOrderStepLstLi...)
			writeSerialOrderOpLi = append(writeSerialOrderOpLi, preOrder.SerialOrderOPDetailLi...)
			writeLabelHeadLi = append(writeLabelHeadLi, preOrder.LabelHeadLi...)
			writeLabelDetailLi = append(writeLabelDetailLi, preOrder.LabelDetailLi...)
		}
	}
	// 插入工单
	num := len(writeSerialOrderLi) / 30
	remainder := len(writeSerialOrderLi) % 30
	for i := 0; i < num; i++ {
		insertLi := writeSerialOrderLi[30*i : (i+1)*30]
		err = serialOrderDao.Insert(&insertLi)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("保存工单失败, 错误:" + err.Error())
		}
	}
	if remainder != 0 {
		insertLi := writeSerialOrderLi[num*30:]
		err = serialOrderDao.Insert(&insertLi)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("保存工单失败, 错误:" + err.Error())
		}
	}
	// 插入工单状态
	num = len(writeSerialOrderStatusLi) / 30
	remainder = len(writeSerialOrderStatusLi) % 30
	for i := 0; i < num; i++ {
		insertLi := writeSerialOrderStatusLi[30*i : (i+1)*30]
		err = serialOrderStatusDao.Insert(&insertLi)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("保存工单状态失败, 错误:" + err.Error())
		}
	}
	if remainder != 0 {
		insertLi := writeSerialOrderStatusLi[num*30:]
		err = serialOrderStatusDao.Insert(&insertLi)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("保存工单状态失败, 错误:" + err.Error())
		}
	}
	// 插入工单工序数据
	num = len(writeSerialOrderPoLi) / 30
	remainder = len(writeSerialOrderPoLi) % 30
	for i := 0; i < num; i++ {
		insertLi := writeSerialOrderPoLi[30*i : (i+1)*30]
		err = serialOrderPoDao.Insert(&insertLi)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("保存工单工序失败, 错误:" + err.Error())
		}
	}
	if remainder != 0 {
		insertLi := writeSerialOrderPoLi[num*30:]
		err = serialOrderPoDao.Insert(&insertLi)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("保存工单工序失败, 错误:" + err.Error())
		}
	}
	// 插入工单工步数据
	num = len(writeSerialOrderStepLi) / 30
	remainder = len(writeSerialOrderStepLi) % 30
	for i := 0; i < num; i++ {
		insertLi := writeSerialOrderStepLi[30*i : (i+1)*30]
		err = serialOrderStepDao.Insert(&insertLi)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("保存工单工步失败, 错误:" + err.Error())
		}
	}
	if remainder != 0 {
		insertLi := writeSerialOrderStepLi[num*30:]
		err = serialOrderStepDao.Insert(&insertLi)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("保存工单工步失败, 错误:" + err.Error())
		}
	}
	// 插入工单工艺数据
	num = len(writeSerialOrderOpLi) / 30
	remainder = len(writeSerialOrderOpLi) % 30
	for i := 0; i < num; i++ {
		insertLi := writeSerialOrderOpLi[30*i : (i+1)*30]
		err = serialOrderOPDetailDao.Insert(&insertLi)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("保存工单工艺失败, 错误:" + err.Error())
		}
	}
	if remainder != 0 {
		insertLi := writeSerialOrderOpLi[num*30:]
		err = serialOrderOPDetailDao.Insert(&insertLi)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("保存工单工艺失败, 错误:" + err.Error())
		}
	}
	// 写入打印标签数据
	num = len(writeLabelHeadLi) / 30
	remainder = len(writeLabelHeadLi) % 30
	for i := 0; i < num; i++ {
		insertLi := writeLabelHeadLi[30*i : (i+1)*30]
		err = labelHeadDao.Insert(&insertLi)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("保存标签头部失败, 错误:" + err.Error())
		}
	}
	if remainder != 0 {
		insertLi := writeLabelHeadLi[num*30:]
		err = labelHeadDao.Insert(&insertLi)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("保存标签头部失败, 错误:" + err.Error())
		}
	}
	num = len(writeLabelDetailLi) / 30
	remainder = len(writeLabelDetailLi) % 30
	for i := 0; i < num; i++ {
		insertLi := writeLabelDetailLi[30*i : (i+1)*30]
		err = labelDetailDao.Insert(&insertLi)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("保存标签详情失败, 错误:" + err.Error())
		}
	}
	if remainder != 0 {
		insertLi := writeLabelDetailLi[num*30:]
		err = labelDetailDao.Insert(&insertLi)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("保存标签详情失败, 错误:" + err.Error())
		}
	}

	_ = session.Commit()
	return nil
}

// ReplaceData 替换工单数据中的工单ID
func (impl *SerialOrderServiceImplement) ReplaceData(serialOrder *model.SerialOrder, serialNumber string, isPre bool) {
	day := serialOrder.PlanStartTime.Restore().Format("060102")
	serialOrderId := strings.Replace(serialOrder.SerialOrderId, "$serialNumber$", serialNumber, 1)
	if isPre {
		serialOrderId = strings.Replace(serialOrderId, "$date$", day, 1)
	}
	serialOrder.SerialOrderId = serialOrderId
	serialOrder.SerialOrderStatus.SerialOrderId = serialOrderId
	for index, serialOrderPo := range serialOrder.SerialOrderPOLstLi {
		serialOrderPo.SerialOrderId = serialOrderId
		serialOrder.SerialOrderPOLstLi[index] = serialOrderPo
	}
	for index, serialOrderStep := range serialOrder.SerialOrderStepLstLi {
		serialOrderStep.SerialOrderId = serialOrderId
		serialOrder.SerialOrderStepLstLi[index] = serialOrderStep
	}
	for index, serialOrderOp := range serialOrder.SerialOrderOPDetailLi {
		serialOrderOp.SerialOrderId = serialOrderId
		serialOrderOp.CharPara1 = strings.Replace(serialOrderOp.CharPara1, "$serialNumber$", serialNumber, 1)
		serialOrderOp.CharPara2 = strings.Replace(serialOrderOp.CharPara2, "$serialNumber$", serialNumber, 1)
		serialOrderOp.CharPara3 = strings.Replace(serialOrderOp.CharPara3, "$serialNumber$", serialNumber, 1)
		serialOrderOp.CharPara4 = strings.Replace(serialOrderOp.CharPara4, "$serialNumber$", serialNumber, 1)
		serialOrderOp.CharPara5 = strings.Replace(serialOrderOp.CharPara5, "$serialNumber$", serialNumber, 1)
		serialOrderOp.CharPara6 = strings.Replace(serialOrderOp.CharPara6, "$serialNumber$", serialNumber, 1)
		serialOrderOp.CharPara7 = strings.Replace(serialOrderOp.CharPara7, "$serialNumber$", serialNumber, 1)
		serialOrderOp.CharPara8 = strings.Replace(serialOrderOp.CharPara8, "$serialNumber$", serialNumber, 1)
		serialOrderOp.CharPara9 = strings.Replace(serialOrderOp.CharPara9, "$serialNumber$", serialNumber, 1)
		serialOrderOp.CharPara10 = strings.Replace(serialOrderOp.CharPara10, "$serialNumber$", serialNumber, 1)
		if isPre {
			serialOrderOp.CharPara1 = strings.Replace(serialOrderOp.CharPara1, "$date$", day, 1)
			serialOrderOp.CharPara2 = strings.Replace(serialOrderOp.CharPara2, "$date$", day, 1)
			serialOrderOp.CharPara3 = strings.Replace(serialOrderOp.CharPara3, "$date$", day, 1)
			serialOrderOp.CharPara4 = strings.Replace(serialOrderOp.CharPara4, "$date$", day, 1)
			serialOrderOp.CharPara5 = strings.Replace(serialOrderOp.CharPara5, "$date$", day, 1)
			serialOrderOp.CharPara6 = strings.Replace(serialOrderOp.CharPara6, "$date$", day, 1)
			serialOrderOp.CharPara7 = strings.Replace(serialOrderOp.CharPara7, "$date$", day, 1)
			serialOrderOp.CharPara8 = strings.Replace(serialOrderOp.CharPara8, "$date$", day, 1)
			serialOrderOp.CharPara9 = strings.Replace(serialOrderOp.CharPara9, "$date$", day, 1)
			serialOrderOp.CharPara10 = strings.Replace(serialOrderOp.CharPara10, "$date$", day, 1)
		}
		serialOrder.SerialOrderOPDetailLi[index] = serialOrderOp
	}
	for index, labelHead := range serialOrder.LabelHeadLi {
		labelHead.BusinessObjId = serialOrderId
		labelHead.LabelId = strings.Replace(labelHead.LabelId, "$serialNumber$", serialNumber, 1)
		if isPre {
			labelHead.LabelId = strings.Replace(labelHead.LabelId, "$date$", day, 1)
		}
		serialOrder.LabelHeadLi[index] = labelHead
	}
	for index, labelDetail := range serialOrder.LabelDetailLi {
		labelDetail.LabelId = strings.Replace(labelDetail.LabelId, "$serialNumber$", serialNumber, 1)
		if isPre {
			labelDetail.LabelId = strings.Replace(labelDetail.LabelId, "$date$", day, 1)
		}
		switch labelDetail.VariableName {
		case "$SerialOrderId$", "$Barcode$", "$OrderId$":
			labelDetail.VariableValue = serialOrderId
		case "*$SerialOrderId$*":
			labelDetail.VariableValue = "*" + serialOrderId + "*"
		}
		serialOrder.LabelDetailLi[index] = labelDetail
	}
}

func (impl *SerialOrderServiceImplement) SingleProductTask(user *global.User, session *xorm.Session, task *baseModel.CrossPlanTask, productId string) (*model.SerialOrder ,error) {
	writeSerialOrderLi := make([]model.SerialOrder, 0)
	workLinePoDao := baseDal.NewWorkLineProcessLstDAO(session, user.PlantNr, user.UserId)
	productDao := meDal.NewProductDAO(session, user.PlantNr, user.UserId)
	workLineLi, err := workLinePoDao.Select([]grmi.Predicate{
		baseMeta.WorkLineProcessLst_PO.NewPredicate(grmi.Equal, task.LastPo),
	}, nil)
	if err != nil {
		return nil, grmi.NewBusinessError("查询工序关联产线失败, 错误:" + err.Error())
	}
	if len(workLineLi) == 0 {
		return nil, grmi.NewBusinessError("拆分工单指定末道序未关联产线， 末道序:" + task.LastPo)
	}
	if len(workLineLi) != 1 {
		return nil, grmi.NewBusinessError("拆分工单指定末道序关联多条产线， 末道序:" + task.LastPo)
	}
	workLineId := workLineLi[0].WorkLineId
	product, err := productDao.SelectOne(productId, task.ProjectId)
	if err != nil {
		return nil, grmi.NewBusinessError("查询总成失败, 错误:" + err.Error())
	}
	if product == nil {
		return nil, grmi.NewBusinessError("总成不存在, 总成ID:" + productId)
	}
	serialOrderId := strings.Replace(productId, "-", "", -1) + "$date$" + "$serialNumber$"
	insertOrder := model.SerialOrder{
		SerialOrderId:  serialOrderId,
		ArtId:          productId,
		ProjectId:      task.ProjectId,
		Descr:          product.Descr,
		PreSchedKey:    0,
		SchedKey:       0,
		Priority:       0,
		OrderType:      baseModel.ORDER_TYPE_PRE,
		PlanResourceId: workLineId,
		UsedResourceId: workLineId,
		PlanQty:        1,
		PickingFlag:    product.PickingFlag,
	}
	insertOrder.SerialOrderStatus = model.SerialOrderStatus{
		SerialOrderId: serialOrderId,
		Status:        baseModel.WO_STATUS_RELEASED,
	}
	writeSerialOrderLi = append(writeSerialOrderLi, insertOrder)
	err = impl.GenerateProductCraft(user, session, &insertOrder)
	if err != nil {
		return nil, grmi.NewBusinessError("生成工单工艺数据失败, 错误:" + err.Error())
	}
	return &insertOrder, nil
}


func (impl *SerialOrderServiceImplement) ExecuteCrossPlantTask(task baseModel.CrossPlanTask) {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	user := &global.User{
		PlantNr: task.ToPlantNr,
		UserId: "MultiPlantTask",
	}
	releaseId, err := uuid.NewV4()
	if err != nil {
		return
	}
	log, _ := logger.NewLogger("跨工厂生成计划,id:"+releaseId.String(), "CrossPlant")
	taskDao := baseDal.NewCrossPlanTaskDAO(session, user.UserId)
	// 获取生产的物料
	productIdLi := strings.Split(task.ArtId, ";")
	if len(productIdLi) == 0 {
		task.Status = baseModel.CROSS_TASK_STATUS_ERROR
		task.ErrorMsg = "任务未包含物料数据"
		err = taskDao.UpdateOne(&task)
		if err != nil {
			log.Error("更新任务状态失败, 错误:" + err.Error() + ", 任务ID:" + strconv.Itoa(task.TaskNr))
		}
		return
	}
	if task.PlanEndTime.Restore().Before(task.PlanStartTime.Restore()) {
		task.Status = baseModel.CROSS_TASK_STATUS_ERROR
		task.ErrorMsg = "任务计划结束时间早于开始时间"
		err = taskDao.UpdateOne(&task)
		if err != nil {
			log.Error("更新任务状态失败, 错误:" + err.Error() + ", 任务ID:" + strconv.Itoa(task.TaskNr))
		}
		return
	}
	subTime := task.PlanEndTime.Restore().Sub(task.PlanStartTime.Restore())
	totalQty := len(productIdLi) * task.PlanQty
	perDuration := int(subTime.Seconds()) / totalQty
	// 调度模式
	schedQty, err := strconv.Atoi(task.SchedType)
	if err != nil || schedQty == 0 {
		task.Status = baseModel.CROSS_TASK_STATUS_ERROR
		task.ErrorMsg = "不支持的调度模式"
		err = taskDao.UpdateOne(&task)
		if err != nil {
			log.Error("更新任务状态失败, 错误:" + err.Error() + ", 任务ID:" + strconv.Itoa(task.TaskNr))
		}
		return
	}
	// 记录生成计划中间的数量
	type ProductQty struct {
		ArtId string // 物料id
		CurrentQty int // 当前数量
	}

	productQtyCacheLi := make([]ProductQty, 0, len(productIdLi))
	for _, productId := range productIdLi {
		productQtyData := ProductQty{
			ArtId: productId,
		}
		productQtyCacheLi = append(productQtyCacheLi, productQtyData)
	}
	productCraftMap := make(map[string]*model.SerialOrder)
	for _, productId := range productIdLi {
		serialOrderCraft, err := impl.SingleProductTask(user, session, &task, productId)
		if err != nil {
			task.Status = baseModel.CROSS_TASK_STATUS_ERROR
			task.ErrorMsg = "生成工单工艺失败, 错误:" + err.Error()
			err = taskDao.UpdateOne(&task)
			if err != nil {
				log.Error("更新任务状态失败, 错误:" + err.Error() + ", 任务ID:" + strconv.Itoa(task.TaskNr))
			}
			return
		}
		productCraftMap[productId] = serialOrderCraft
	}
	for index, productQtyCache := range productQtyCacheLi {
		if productQtyCache.CurrentQty == schedQty {
			productQtyCache.CurrentQty = 0
			productQtyCacheLi[index] = productQtyCache
			continue
		}
		startNum :=
	}
}