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

package implments

import (
	"LAPP_ACURA_MOM_BACKEND/conf"
	baseDal "LAPP_ACURA_MOM_BACKEND/dao/base"
	dal "LAPP_ACURA_MOM_BACKEND/dao/jit"
	meDal "LAPP_ACURA_MOM_BACKEND/dao/me"
	omDal "LAPP_ACURA_MOM_BACKEND/dao/om"
	"LAPP_ACURA_MOM_BACKEND/db"
	"LAPP_ACURA_MOM_BACKEND/global"
	"LAPP_ACURA_MOM_BACKEND/grmi"
	baseMeta "LAPP_ACURA_MOM_BACKEND/meta/base"
	meta "LAPP_ACURA_MOM_BACKEND/meta/jit"
	omMeta "LAPP_ACURA_MOM_BACKEND/meta/om"
	baseModel "LAPP_ACURA_MOM_BACKEND/models/base"
	model "LAPP_ACURA_MOM_BACKEND/models/jit"
	omModel "LAPP_ACURA_MOM_BACKEND/models/om"
	"encoding/hex"
	"strconv"
	"strings"
	"time"
)

/******************************************************************************
 *
 * @Description              : PackOrder的默认查询条件
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-10-19 10:26:40
 *
 ******************************************************************************/
var DefaultConditionOfPackOrder = grmi.NewCondition(
	map[string]grmi.ConditionItem{
		meta.PackOrder_PackOrderId.UrlParameterName:     grmi.NewConditionItem(meta.PackOrder_PackOrderId, grmi.Equal, true),
		meta.PackOrder_PackTemplateId.UrlParameterName:  grmi.NewConditionItem(meta.PackOrder_PackTemplateId, grmi.Equal, false),
		meta.PackOrder_ProjectId.UrlParameterName:       grmi.NewConditionItem(meta.PackOrder_ProjectId, grmi.Equal, false),
		meta.PackOrder_ShortPackToggle.UrlParameterName: grmi.NewConditionItem(meta.PackOrder_ShortPackToggle, grmi.Equal, false),
		meta.PackOrder_ShortBy.UrlParameterName:         grmi.NewConditionItem(meta.PackOrder_ShortBy, grmi.Equal, false),
		meta.PackOrder_ShortTime.UrlParameterName:       grmi.NewConditionItem(meta.PackOrder_ShortTime, grmi.Approximate, false),
		meta.PackOrder_OrderInfo.UrlParameterName:       grmi.NewConditionItem(meta.PackOrder_OrderInfo, grmi.Equal, false),
		meta.PackOrder_SyncSnrId.UrlParameterName:       grmi.NewConditionItem(meta.PackOrder_SyncSnrId, grmi.Equal, false),
		meta.PackOrder_BoxSnrId.UrlParameterName:        grmi.NewConditionItem(meta.PackOrder_BoxSnrId, grmi.Equal, false),
		meta.PackOrder_PackTypeId.UrlParameterName:      grmi.NewConditionItem(meta.PackOrder_PackTypeId, grmi.Equal, false),
		meta.PackOrder_PrinterId.UrlParameterName:       grmi.NewConditionItem(meta.PackOrder_PrinterId, grmi.Equal, false),
		meta.PackOrder_TemplateFile.UrlParameterName:    grmi.NewConditionItem(meta.PackOrder_TemplateFile, grmi.Equal, false),
		meta.PackOrder_PlanQty.UrlParameterName:         grmi.NewConditionItem(meta.PackOrder_PlanQty, grmi.Equal, false),
		meta.PackOrder_ActQty.UrlParameterName:          grmi.NewConditionItem(meta.PackOrder_ActQty, grmi.Equal, false),
		meta.PackOrder_OpenTime.UrlParameterName:        grmi.NewConditionItem(meta.PackOrder_OpenTime, grmi.Approximate, false),
		meta.PackOrder_CloseTime.UrlParameterName:       grmi.NewConditionItem(meta.PackOrder_CloseTime, grmi.Approximate, false),
		meta.PackOrder_Operator.UrlParameterName:        grmi.NewConditionItem(meta.PackOrder_Operator, grmi.Equal, false),
		meta.PackOrder_CheckSyncKey.UrlParameterName:    grmi.NewConditionItem(meta.PackOrder_CheckSyncKey, grmi.Equal, false),
		meta.PackOrder_PackLocation.UrlParameterName:    grmi.NewConditionItem(meta.PackOrder_PackLocation, grmi.Equal, false),
		meta.PackOrder_RFID.UrlParameterName:            grmi.NewConditionItem(meta.PackOrder_RFID, grmi.Equal, false),
		meta.PackOrder_CtrlPara1.UrlParameterName:       grmi.NewConditionItem(meta.PackOrder_CtrlPara1, grmi.Equal, false),
		meta.PackOrder_CtrlPara2.UrlParameterName:       grmi.NewConditionItem(meta.PackOrder_CtrlPara2, grmi.Equal, false),
		meta.PackOrder_CtrlStr1.UrlParameterName:        grmi.NewConditionItem(meta.PackOrder_CtrlStr1, grmi.Equal, false),
		meta.PackOrder_CtrlStr2.UrlParameterName:        grmi.NewConditionItem(meta.PackOrder_CtrlStr2, grmi.Equal, false),
		meta.PackOrder_CtrlTime1.UrlParameterName:       grmi.NewConditionItem(meta.PackOrder_CtrlTime1, grmi.Approximate, false),
		meta.PackOrder_CtrlTime2.UrlParameterName:       grmi.NewConditionItem(meta.PackOrder_CtrlTime2, grmi.Approximate, false),
		meta.PackOrder_LastModify.UrlParameterName:      grmi.NewConditionItem(meta.PackOrder_LastModify, grmi.Approximate, false),
		meta.PackOrder_LastUser.UrlParameterName:        grmi.NewConditionItem(meta.PackOrder_LastUser, grmi.Equal, false),
		meta.PackOrder_CreateTime.UrlParameterName:      grmi.NewConditionItem(meta.PackOrder_CreateTime, grmi.Approximate, false),
	},
	nil,
)

/******************************************************************************
 *
 * @Description              : PackOrder的默认分页查询条件
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-10-19 10:26:40
 *
 ******************************************************************************/
var DefaultConditionOfPackOrderAndPaging = grmi.NewCondition(
	DefaultConditionOfPackOrder.Items,
	grmi.NewPaging(),
)

/******************************************************************************
 *
 * @Struct Name              : PackOrderServiceImplement
 *-----------------------------------------------------------------------------
 *
 * @Description              : PackOrder的服务实现
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-10-19 10:26:40
 *
 ******************************************************************************/
type PackOrderServiceImplement struct {
}

/******************************************************************************
 *
 * @Function Name            : NewPackOrderDAOImplement
 *-----------------------------------------------------------------------------
 *
 * @Description              : 创建一个PackOrderDAOImplement实例
 *
 * @Return Value             : PackOrderDAOImplement实例
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-10-19 10:26:40
 *
 ******************************************************************************/
func NewPackOrderServiceImplement() *PackOrderServiceImplement {
	return &PackOrderServiceImplement{}
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/jit/PackOrderService.InsertOne
 *
 ******************************************************************************/
func (impl *PackOrderServiceImplement) InsertOne(user *global.User, entity *model.PackOrder) error {

	grmi.Log(user, "/services/jit/implments/PackOrder.service.impl.go", "InsertOnePackOrder", "插入一个PackOrder")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewPackOrderDAO(session, user.PlantNr, user.UserId)
	record, err := dao.SelectOne(entity.PackOrderId)
	if err != nil {
		return err
	}
	if record != nil {
		return grmi.NewBusinessError("已经存在相同主键的记录!")
	}
	err = dao.InsertOne(entity)
	if err != nil {
		return err
	}
	return nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/jit/PackOrderService.DeleteOne
 *
 ******************************************************************************/
func (impl *PackOrderServiceImplement) DeleteOne(user *global.User, packOrderId string) error {

	grmi.Log(user, "/services/jit/implments/PackOrder.service.impl.go", "DeleteOnePackOrder", "删除一个PackOrder")

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

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/jit/PackOrderService.SelectOne
 *
 ******************************************************************************/
func (impl *PackOrderServiceImplement) SelectOne(user *global.User, packOrderId string) (*model.PackOrder, error) {

	grmi.Log(user, "/services/jit/implments/PackOrder.service.impl.go", "SelectOnePackOrder", "查询一个PackOrder")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewPackOrderDAO(session, user.PlantNr, user.UserId)
	itemDao := dal.NewPackOrderItemLstDAO(session, user.PlantNr, user.UserId)
	result, err := dao.SelectOne(packOrderId)
	if err != nil {
		return nil, err
	}
	if result == nil {
		return nil, nil
	}
	itemLi, err := itemDao.Select([]grmi.Predicate{meta.PackOrderItemLst_PackOrderId.NewPredicate(grmi.Equal, packOrderId)}, []grmi.Field{meta.PackOrderItemLst_Pos})
	if err != nil {
		return nil, grmi.NewBusinessError("查询包装单子项数据失败, error:" + err.Error())
	}
	artIdLi := make([]interface{}, 0, len(itemLi))
	for _, item := range itemLi {
		artIdLi = append(artIdLi, item.PartId)
	}
	articleDao := baseDal.NewArticleDAO(session, user.PlantNr, user.UserId)
	articleLi, err := articleDao.Select([]grmi.Predicate{baseMeta.Article_ProjectId.NewPredicate(grmi.Equal, result.ProjectId), baseMeta.Article_ArtId.NewPredicate(grmi.Include, artIdLi...)}, nil)
	if err != nil {
		return nil, grmi.NewBusinessError("查询物料数据失败, error:" + err.Error())
	}
	artMap := make(map[string]string, len(articleLi))
	for _, article := range articleLi {
		artMap[article.ArtId] = article.Descr1
	}
	for index, item := range itemLi {
		artDesc := artMap[item.PartId]
		item.ArtDesc = artDesc
		itemLi[index] = item
	}
	result.PackOrderItemLstLi = itemLi
	return result, nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/jit/PackOrderService.UpdateOne
 *
 ******************************************************************************/
func (impl *PackOrderServiceImplement) UpdateOne(user *global.User, entity *model.PackOrder) error {

	grmi.Log(user, "/services/jit/implments/PackOrder.service.impl.go", "UpdateOnePackOrder", "修改一个PackOrder")

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

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/jit/PackOrderService.Insert
 *
 ******************************************************************************/
func (impl *PackOrderServiceImplement) Insert(user *global.User, entities *[]model.PackOrder) error {

	grmi.Log(user, "/services/jit/implments/PackOrder.service.impl.go", "InsertPackOrder", "插入多个PackOrder")

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

	for _, entity := range *entities {
		record, err := dao.SelectOne(entity.PackOrderId)
		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/jit/PackOrderService.Delete
 *
 ******************************************************************************/
func (impl *PackOrderServiceImplement) Delete(user *global.User, entities *[]model.PackOrder) error {

	grmi.Log(user, "/services/jit/implments/PackOrder.service.impl.go", "DeletePackOrder", "删除多个PackOrder")

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

	for _, entity := range *entities {
		record, err := dao.SelectOne(entity.PackOrderId)
		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/jit/PackOrderService.Select
 *
 ******************************************************************************/
func (impl *PackOrderServiceImplement) Select(user *global.User, urlParameters map[string]string) ([]model.PackOrder, error) {

	grmi.Log(user, "/services/jit/implments/PackOrder.service.impl.go", "SelectPackOrder", "查询PackOrder")

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

	grmi.Log(user, "/services/jit/implments/PackOrder.service.impl.go", "SelectPackOrder", "查询PackOrder")

	condition := DefaultConditionOfPackOrderAndPaging
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	predicates, err := condition.BuildPredicates(urlParameters)
	if err != nil {
		return grmi.EmptyPagingResult, err
	}
	barcode, exist := urlParameters["barcode"]
	if exist {
		if barcode == "" {
			return grmi.EmptyPagingResult, grmi.NewBusinessError("未传入条码数据")
		}
		packOrderItemDao := dal.NewPackOrderItemLstDAO(session, user.PlantNr, user.UserId)
		result, err := packOrderItemDao.SelectPackOrderByBarcode(condition.Paging, barcode)
		if err != nil {
			return grmi.EmptyPagingResult, err
		}
		return result, nil
	}
	dao := dal.NewPackOrderDAO(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/jit/PackOrderService.Update
 *
 ******************************************************************************/
func (impl *PackOrderServiceImplement) Update(user *global.User, entities *[]model.PackOrder) error {

	grmi.Log(user, "/services/jit/implments/PackOrder.service.impl.go", "UpdatePackOrder", "修改多个PackOrder")

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

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

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

// ScanBarcode 包装扫描条码
func (impl *PackOrderServiceImplement) ScanBarcode(user *global.User, barcode string, workplaceNr int) (*model.PackOrderInfo, error) {
	grmi.Log(user, "/services/jit/implments/PackOrder.service.impl.go", "ScanBarcode", "扫描零件条码")
	result := &model.PackOrderInfo{}
	result.PLCResult = true
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	var (
		// 打包工位
		packWorkplace          *baseModel.WorkPlace
		// 打包工位配置
		packWorkplaceConfig *baseModel.WorkPlaceConfig
		// 工厂归属项目
		plantProject string
		// 当前工单的合格状态
		currentSerialOrderStatus = true
	)
	snrDao := baseDal.NewSnrDAO(session, user.PlantNr, user.UserId)
	packLstDAO := dal.NewPackOrderItemLstDAO(session, user.PlantNr, user.UserId)
	packOrderDao := dal.NewPackOrderDAO(session, user.PlantNr, user.UserId)
	packOrderStatusDao := dal.NewPackOrderStatusDAO(session, user.PlantNr, user.UserId)
	packOrderStatusHistoryDao := dal.NewPackOrderStatusHistoryDAO(session, user.PlantNr, user.UserId)
	projectDao := meDal.NewProjectDAO(session, user.PlantNr, user.UserId)
	packOrderPlcErrDao := dal.NewPackOrderPlcErrorDAO(session, user.PlantNr, user.UserId)
	plantDao := baseDal.NewPlantDAO(session, user.UserId)
	workplaceDao := baseDal.NewWorkPlaceDAO(session, user.PlantNr, user.UserId)
	workplaceConfigDao := baseDal.NewWorkPlaceConfigDAO(session, user.PlantNr, user.UserId)
	plant, err := plantDao.SelectOne(user.PlantNr)
	if err != nil {
		return nil, grmi.NewBusinessError("查询工厂数据失败, 错误:" + err.Error())
	}
	if plant == nil {
		return nil, grmi.NewBusinessError("用户归属工厂不存在, 工厂ID:" + strconv.Itoa(user.PlantNr))
	}
	plantProject = plant.PlantProject
	// 根据不同的项目做不同的预处理
	if plantProject == baseModel.PROJECT_NANSHA {
		// 南沙下线打包都需要写plc 先查询plc错误 有错误不能打包
		errorLi, err := packOrderPlcErrDao.Select([]grmi.Predicate{meta.PackOrderPlcError_Location.NewPredicate(grmi.Equal, model.PACK_LOCATION_ON_LINE),
			meta.PackOrderPlcError_Status.NewPredicate(grmi.LessThen, model.PACK_STATUS_CLOSED)}, nil)
		if err != nil {
			return nil, grmi.NewBusinessError("查询座椅下线写入PLC数据错误失败, error:" + err.Error())
		}
		if len(errorLi) != 0 {
			return nil, grmi.NewBusinessError("当前存在未处理的座椅下线写入PLC错误")
		}
	} else if plantProject == baseModel.PROJECT_ACURA {
		// 讴歌下线打包需要选择工位 查询工位配置 如果需要记录plc错误 查询plc错误 有错误不能打包
		packWorkplace, err = workplaceDao.SelectOne(workplaceNr)
		if err != nil {
			return nil, grmi.NewBusinessError("查询工位失败, 错误:" + err.Error())
		}
		if packWorkplace == nil {
			return nil, grmi.NewBusinessError("打包工位不存在")
		}
		workplaceConfigLi, err := workplaceConfigDao.Select([]grmi.Predicate{
			baseMeta.WorkPlaceConfig_WorkPlaceNr.NewPredicate(grmi.Equal, workplaceNr),
		}, nil)
		if err != nil {
			return nil, grmi.NewBusinessError("查询工位配置失败, 错误:" + err.Error())
		}
		if len(workplaceConfigLi) == 0 {
			return nil, grmi.NewBusinessError("缺少打包工位配置")
		}
		packWorkplaceConfig = &workplaceConfigLi[0]
		// 需要写入plc 座椅数据
		if packWorkplaceConfig.StrValue1 == baseModel.WORKPLACE_CONIFG_WIRTE_SEAT {
			errorLi, err := packOrderPlcErrDao.Select([]grmi.Predicate{meta.PackOrderPlcError_Location.NewPredicate(grmi.Equal, model.PACK_LOCATION_ON_LINE),
				meta.PackOrderPlcError_Status.NewPredicate(grmi.LessThen, model.PACK_STATUS_CLOSED)}, nil)
			if err != nil {
				return nil, grmi.NewBusinessError("查询座椅下线写入PLC数据错误失败, error:" + err.Error())
			}
			if len(errorLi) != 0 {
				return nil, grmi.NewBusinessError("当前存在未处理的座椅下线写入PLC错误")
			}
		}
	}
	// 初始化全局的包装模板数据
	if model.AllPackTemplate.Data == nil {
		templateLstDao := dal.NewPackTemplateItemLstDAO(session, user.PlantNr, user.UserId)
		err := templateLstDao.InitGlobalPackTemplate()
		if err != nil {
			return nil, grmi.NewBusinessError("初始化全局包装模板失败, error:" + err.Error())
		}
	}
	//判断条码是否已经生成过包装
	dataList, err := packLstDAO.Select([]grmi.Predicate{
		meta.PackOrderItemLst_SerialOrderId.NewPredicate(grmi.Equal, barcode),
		meta.PackOrderItemLst_Status.NewPredicate(grmi.NotEqual, model.PACK_STATUS_CANCELED),
	}, nil)
	if err != nil {
		return nil, grmi.NewBusinessError("查询包装单详情数据失败, error:" + err.Error())
	}
	if len(dataList) > 0 {
		return nil, grmi.NewBusinessError("该条码已经扫描过!")
	}

	// 校验Barcode是否存在 状态是否是80
	serialOrderDao := omDal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	serialOrderLi, err := serialOrderDao.Select([]grmi.Predicate{omMeta.SerialOrder_SerialOrderId.NewPredicate(grmi.Equal, barcode)}, nil)
	if len(serialOrderLi) == 0 {
		return nil, grmi.NewBusinessError("该条码不存在对应的工单")
	}
	if len(serialOrderLi) > 1 {
		return nil, grmi.NewBusinessError("该条码在系统中存在多个工单")
	}
	serialOrderStatus := serialOrderLi[0].SerialOrderStatus.Status
	if serialOrderLi[0].GenerateFlag {
		return nil, grmi.NewBusinessError("该工单条码已经失效，请使用新的工单条码")
	}
	if serialOrderStatus != baseModel.WO_STATUS_FINISHED &&
		serialOrderStatus != baseModel.WO_STATUS_STOP &&
		serialOrderStatus != baseModel.WO_STATUS_INTERRUPT &&
		serialOrderStatus != baseModel.WO_STATUS_UNCHECKED {
		return nil, grmi.NewBusinessError("条码对应的工单状态不允许打包")
	}
	serialOrder := serialOrderLi[0]
	if serialOrder.QualityCheck != baseModel.QualityCheck_STATUS_OK && serialOrder.QualityCheck != baseModel.QualityCheck_STATUS_FAIL {
		return nil, grmi.NewBusinessError("工单未进行目检")
	}
	if serialOrderStatus != baseModel.WO_STATUS_FINISHED || serialOrder.QualityCheck != baseModel.QualityCheck_STATUS_OK {
		currentSerialOrderStatus = false
	}

	// 获取用户之前是否存在未关包的包装单 如果存在则使用之前的包装单ID 如果不存在则创建包装单 如果超过一个则报错
	var packOrderId string
	packOrderLi, err := packOrderDao.SelectUserRunningPackOrder(user.UserId, model.PACK_LOCATION_ON_LINE)
	if err != nil {
		return nil, grmi.NewBusinessError("获取用户之前的操作的包装单数据失败, error:" + err.Error())
	}
	if len(packOrderLi) == 1 {
		packOrderId = packOrderLi[0].PackOrder.PackOrderId
	} else if len(packOrderLi) == 0 {
		packOrderId = ""
	} else {
		return nil, grmi.NewBusinessError("该用户现在存在多个包装中的包装单， 请确认")
	}
	// 通过工单条码获取总成
	artId := serialOrderLi[0].ArtId
	projectId := serialOrderLi[0].ProjectId
	project, err := projectDao.SelectOne(projectId)
	if err != nil {
		return nil, grmi.NewBusinessError("查询车型项目数据失败， error:" + err.Error())
	}
	if project == nil {
		return nil, grmi.NewBusinessError("车型项目数据不存在，项目ID:" + projectId)
	}
	// 台套Key
	syncKey := serialOrderLi[0].SyncKey
	if err := session.Begin(); err != nil {
		return nil, grmi.NewBusinessError("事务开启失败, error:" + err.Error())
	}
	currentPackOrder := &model.PackOrderWithStatus{}
	// 如果当前用户不存在操作中未关闭的包装单, 则创建包装单数据
	if packOrderId == "" {
		var packTypeId = model.PACK_TYPE_STD
		//if serialOrder.OrderType == baseModel.ODER_TYPE_SEQ {
		//	packTypeId = model.PACK_TYPE_STD
		//} else {
		//	packTypeId = model.PACK_TYPE_INT
		//}
		packOrderId, err = snrDao.GetNextSnr(project.PackOrderSnr)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("生成包装单流水号失败, error:" + err.Error())
		}
		packOrder := model.PackOrder{
			PackOrderId:  packOrderId,
			ProjectId:    projectId,
			PlanQty:      1,
			ActQty:       1,
			PackTypeId:   packTypeId,
			OpenTime:     grmi.DateTime(time.Now()),
			Operator:     user.UserId,
			PackLocation: model.PACK_LOCATION_ON_LINE,
		}
		if currentSerialOrderStatus {
			packOrder.CtrlStr1 = model.PACK_QUALITY_OK
		} else {
			packOrder.CtrlStr1 = model.PACK_QUALITY_NG
		}
		err = packOrderDao.InsertOne(&packOrder)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("插入包装单失败, error:" + err.Error())
		}
		packOrderStatus := model.PackOrderStatus{
			PackOrderId: packOrderId,
			Status:      model.PACK_STATUS_RUNNING,
			LoadStatus:  model.PACK_STATUS_PLANNED,
			ShipStatus:  model.SHIP_STATUS_PLANNED,
		}
		currentPackOrder.PackOrder = packOrder
		currentPackOrder.PackOrderStatus = packOrderStatus
		err = packOrderStatusDao.InsertOne(&packOrderStatus)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("保存包装单状态失败, error:" + err.Error())
		}
		// 写入当前扫描的包装单子项
		packOrderLst := model.PackOrderItemLst{
			PackOrderId:   packOrderId,
			Pos:           1,
			PartId:        artId,
			SerialOrderId: barcode,
			Status:        model.PACK_STATUS_CLOSED,
			PlanQty:       1,
			ActQty:        1,
		}
		err = packLstDAO.InsertOne(&packOrderLst)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("插入包装单细则失败, error:" + err.Error())
		}
		//if packOrder.PackTypeId == model.PACK_TYPE_INT {
		//	_ = session.Commit()
		//	result.IsClosed = false
		//	result.Message = "扫描完成, 包装单ID:" + currentPackOrder.PackOrder.PackOrderId
		//	result.PackOrderId = packOrderId
		//	result.MatchTemplateLi = make([]model.PackTemplate, 0)
		//	return result, nil
		//}
	} else {
		// 如果当前用户存在操作中的未关包的包装单 则进行查询
		currentPackOrder, err = packOrderDao.SelectOneWithStatus(packOrderId)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("查询包装单数据失败, error:" + err.Error())
		}
		if currentPackOrder == nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("对应的包装单数据不存在, 包装单ID:" + packOrderId)
		}
		// 如果工单时内部工单 则校验包装单类型 是不是符合要求 同时插入包装单
		//if serialOrder.OrderType == baseModel.ODER_TYPE_SEQ {
		//	if currentPackOrder.PackOrder.PackTypeId == model.PACK_TYPE_INT {
		//		_ = session.Rollback()
		//		return nil, grmi.NewBusinessError("当前工单是序列工单，但是包装单是内部包装单。")
		//	}
		//currentPackOrder.PackOrder.ActQty += 1
		//currentPackOrder.PackOrder.PlanQty += 1
		//currentPackOrder.PackOrder.Operator = user.UserId
		//err = packOrderDao.UpdateOne(&currentPackOrder.PackOrder)
		//if err != nil {
		//	_ = session.Rollback()
		//	return nil, grmi.NewBusinessError("更新包装单数据失败, error:" + err.Error())
		//}
		//maxPos, err := packLstDAO.GetMaxPost(packOrderId)
		//if err != nil {
		//	_ = session.Rollback()
		//	return nil, grmi.NewBusinessError("查询包装单子项位置数据失败, error:" + err.Error())
		//}
		//// 写入当前扫描的包装单子项
		//packOrderLst := model.PackOrderItemLst{
		//	PackOrderId:   packOrderId,
		//	Pos:           maxPos + 1,
		//	PartId:        artId,
		//	SerialOrderId: barcode,
		//	Status:        model.PACK_STATUS_CLOSED,
		//	PlanQty:       1,
		//	ActQty:        1,
		//}
		//err = packLstDAO.InsertOne(&packOrderLst)
		//if err != nil {
		//	_ = session.Rollback()
		//	return nil, grmi.NewBusinessError("插入包装单细则失败, error:" + err.Error())
		//}
		//_ = session.Commit()
		//result.IsClosed = false
		//result.Message = "扫描完成, 包装单ID:" + currentPackOrder.PackOrder.PackOrderId
		//result.PackOrderId = currentPackOrder.PackOrder.PackOrderId
		//result.MatchTemplateLi = make([]model.PackTemplate, 0)
		//return result, nil
		//} else {
		//	if currentPackOrder.PackOrder.PackTypeId != model.PACK_TYPE_INT {
		//		_ = session.Rollback()
		//		return nil, grmi.NewBusinessError("当前进行包装的包装单是标包, 但工单不是序列工单")
		//	}
		//}

		// 判断包装单是否校验CheckSyncKey
		if currentPackOrder.PackOrder.CheckSyncKey {
			packLstLi, err := packLstDAO.Select([]grmi.Predicate{meta.PackOrderItemLst_PackOrderId.NewPredicate(grmi.Equal, packOrderId)}, nil)
			if err != nil {
				_ = session.Rollback()
				return nil, grmi.NewBusinessError("获取包装单下的包装项失败， error:" + err.Error())
			}
			if len(packLstLi) != 0 {
				packOrderItem := packLstLi[0]
				serialOrderId := packOrderItem.SerialOrderId
				serialOrder, err := serialOrderDao.SelectOne(serialOrderId)
				if err != nil {
					_ = session.Rollback()
					return nil, grmi.NewBusinessError("查询原包装单中包装项工单失败, error:" + err.Error() + ", 工单ID:" + serialOrderId)
				}
				if serialOrder == nil {
					_ = session.Rollback()
					return nil, grmi.NewBusinessError("查询原包装单中包装项工单不存在, 工单ID:" + serialOrderId)
				}
				if serialOrder.SyncKey != syncKey {
					_ = session.Rollback()
					return nil, grmi.NewBusinessError("包装单校验同一台套座椅失败, 台套Key:" + syncKey + ", 当前台套Key:" + serialOrder.SyncKey)
				}
			}
		}

		maxPos, err := packLstDAO.GetMaxPost(packOrderId)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("获取包装项位置数据失败, error:" + err.Error())
		}
		// 如果当前包装单已经匹配到唯一模板
		if currentPackOrder.PackOrder.PackTemplateId != "" {
			packOrderItemLi, err := packLstDAO.Select([]grmi.Predicate{
				meta.PackOrderItemLst_PackOrderId.NewPredicate(grmi.Equal, currentPackOrder.PackOrder.PackOrderId),
				meta.PackOrderItemLst_PartId.NewPredicate(grmi.Equal, artId),
				meta.PackOrderItemLst_Status.NewPredicate(grmi.Equal, model.PACK_STATUS_PLANNED)}, []grmi.Field{meta.PackOrderItemLst_Pos})
			if err != nil {
				_ = session.Rollback()
				return nil, grmi.NewBusinessError("查询包装单子项失败, error:" + err.Error())
			}
			if len(packOrderItemLi) == 0 {
				_ = session.Rollback()
				return nil, grmi.NewBusinessError("当前工单无法进入到用户当前操作的包装单, 包装单已经不需要该产品，包装单ID:" + currentPackOrder.PackOrder.PackOrderId)
			}
			firstItem := packOrderItemLi[0]
			firstItem.Status = model.PACK_STATUS_CLOSED
			firstItem.ActQty = 1
			firstItem.SerialOrderId = barcode
			err = packLstDAO.UpdateOne(&firstItem)
			if err != nil {
				_ = session.Rollback()
				return nil, grmi.NewBusinessError("更新包装单子项失败, error:" + err.Error())
			}
			currentPackOrder.PackOrder.ActQty += 1
			currentPackOrder.PackOrder.Operator = user.UserId
			if currentPackOrder.PackOrder.PlanQty == currentPackOrder.PackOrder.ActQty {
				currentPackOrder.PackOrder.CloseTime = grmi.DateTime(time.Now())
				maxPos, err = packOrderStatusHistoryDao.GetMaxPos(currentPackOrder.PackOrder.PackOrderId)
				if err != nil {
					_ = session.Rollback()
					return nil, grmi.NewBusinessError("查询包装单状态变更位置数据失败, error:" + err.Error())
				}
				packOrderStatusHistory := model.PackOrderStatusHistory{
					PackOrderId:      packOrderId,
					Pos:              maxPos + 1,
					StatusChangeType: model.PACK_STATUS_CHANGE_TYPE_PACK,
					FromStatus:       currentPackOrder.PackOrderStatus.Status,
					ToStatus:         model.PACK_STATUS_CLOSED,
					ChangeTime:       grmi.DateTime(time.Now()),
				}
				err = packOrderStatusHistoryDao.InsertOne(&packOrderStatusHistory)
				if err != nil {
					_ = session.Rollback()
					return nil, grmi.NewBusinessError("保存包装单状态变更记录失败, error:" + err.Error())
				}
				currentPackOrder.PackOrderStatus.Status = model.PACK_STATUS_CLOSED
				err = packOrderStatusDao.UpdateOne(&currentPackOrder.PackOrderStatus)
				if err != nil {
					_ = session.Rollback()
					return nil, grmi.NewBusinessError("更新包装单状态失败, error:" + err.Error())
				}
			}
			// 如果当前包装为合格包装 判断当前工单 如果工单不合格 则修改包装为不合格
			if currentPackOrder.PackOrder.CtrlStr1 == model.PACK_QUALITY_OK {
				if !currentSerialOrderStatus {
					currentPackOrder.PackOrder.CtrlStr1 = model.PACK_QUALITY_NG
				}
			}
			err = packOrderDao.UpdateOne(&currentPackOrder.PackOrder)
			if err != nil {
				_ = session.Rollback()
				return nil, grmi.NewBusinessError("更新包装单数据失败, error:" + err.Error())
			}
			_ = session.Commit()
			if currentPackOrder.PackOrderStatus.Status == model.PACK_STATUS_CLOSED {
				result.IsClosed = true
				result.Message = "扫描完成, 包装单ID:" + currentPackOrder.PackOrder.PackOrderId + " , 已完成该包装单!"
			} else {
				result.IsClosed = false
				result.Message = "扫描完成, 包装单ID:" + currentPackOrder.PackOrder.PackOrderId
			}
			// 如果是南沙项目 已关包写入座椅数据
			if plantProject == baseModel.PROJECT_NANSHA {
				if result.IsClosed {
					err = impl.NSPackPLC(user, packOrderId, projectId, model.PACK_LOCATION_ON_LINE, &currentPackOrder.PackOrder)
					if err != nil {
						result.PLCResult = false
						result.PLCMessage = err.Error()
					}
				}
			} else {
				// 如果是讴歌项目 如果是讴歌线关包 写plc放行 如果是缤智线 写座椅数据
				if result.IsClosed {
					if packWorkplaceConfig.StrValue1 == baseModel.WORKPLACE_CONFIG_WRITE_SIGN {
						err = impl.AUCRAPackPLC()
						if err != nil {
							result.PLCResult = false
							result.PLCMessage = err.Error()
						}
					} else if packWorkplaceConfig.StrValue1 == baseModel.WORKPLACE_CONIFG_WIRTE_SEAT {
						err = impl.BZPackPLCWithoutCheck(user, packWorkplaceConfig, packOrderId, currentPackOrder.PackOrder.CtrlStr1, true, 0)
						if err != nil {
							result.PLCResult = false
							result.PLCMessage = err.Error()
						}
					}
				}
			}
			result.PackOrderId = currentPackOrder.PackOrder.PackOrderId
			return result, nil
		} else {
			// 当前包装单还没有匹配到唯一模板
			currentPackOrder.PackOrder.PlanQty += 1
			currentPackOrder.PackOrder.ActQty += 1
			packOrderLst := model.PackOrderItemLst{
				PackOrderId:   packOrderId,
				Pos:           maxPos + 1,
				PartId:        artId,
				SerialOrderId: barcode,
				Status:        model.PACK_STATUS_CLOSED,
				PlanQty:       1,
				ActQty:        1,
			}
			err = packLstDAO.InsertOne(&packOrderLst)
			if err != nil {
				_ = session.Rollback()
				return nil, grmi.NewBusinessError("插入包装单细则失败, error:" + err.Error())
			}
		}
	}
	// 查询当前包装单下的所有子项 用于做模板匹配
	lstLi, err := packLstDAO.Select([]grmi.Predicate{meta.PackOrderItemLst_PackOrderId.NewPredicate(grmi.Equal, packOrderId)}, []grmi.Field{meta.PackOrderItemLst_Pos})
	if err != nil {
		_ = session.Rollback()
		return nil, grmi.NewBusinessError("获取已进包的包装项数据失败, error:" + err.Error())
	}
	packOrderItemMap := make(map[string]int)
	matchLi := make([]model.PackTemplate, 0)
	for _, packOrderItem := range lstLi {
		_, exist := packOrderItemMap[packOrderItem.PartId]
		if !exist {
			packOrderItemMap[packOrderItem.PartId] = 0
		}
		packOrderItemMap[packOrderItem.PartId] += 1
	}
	for _, template := range model.AllPackTemplate.Data {
		// 如果当前包装单的包装总成数据和包装模板的总成包装数据总类不一致 进行下一次循环
		if len(packOrderItemMap) != len(template.PartIdMap) {
			continue
		}
		var matchSign = true
		for partId, qty := range packOrderItemMap {
			tempQty, exist := template.PartIdMap[partId]
			if !exist {
				matchSign = false
				break
			}
			if tempQty != qty {
				matchSign = false
				break
			}
		}
		if matchSign {
			matchLi = append(matchLi, template)
		}
	}
	tempMatchLi := make([]model.PackTemplate, 0)
	for _, template := range model.AllPackTemplate.Data {
		// 如果当前包装单的包装总成类型多余包装模板的 进行下一次循环
		if len(packOrderItemMap) > len(template.PartIdMap) {
			continue
		}
		var tempMatchSign = true
		for partId, qty := range packOrderItemMap {
			tempQty, exist := template.PartIdMap[partId]
			if !exist {
				tempMatchSign = false
				break
			}
			if tempQty > qty {
				tempMatchSign = false
				break
			}
		}
		if tempMatchSign {
			tempMatchLi = append(tempMatchLi, template)
		}
	}

	if len(matchLi) == 1 {
		// 当前包装单之前没有完全匹配到且只匹配到1个包装模板 现在只匹配到一个包装模板 进行关包处理
		template := matchLi[0]
		currentPackOrder.PackOrder.CloseTime = grmi.DateTime(time.Now())
		currentPackOrder.PackOrder.Operator = user.UserId
		currentPackOrder.PackOrder.PackTemplateId = template.PackTemplateId
		currentPackOrder.PackOrder.PackTypeId = template.PackTypeId
		currentPackOrder.PackOrder.PlanQty = template.PlanQty
		err = packOrderDao.UpdateOne(&currentPackOrder.PackOrder)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("更新包装单数据失败, error:" + err.Error())
		}
		maxPos, err := packOrderStatusHistoryDao.GetMaxPos(currentPackOrder.PackOrder.PackOrderId)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("获取包装单状态变更记录位置数据失败, error:" + err.Error())
		}
		packOrderStatusHistory := model.PackOrderStatusHistory{
			PackOrderId:      currentPackOrder.PackOrder.PackOrderId,
			Pos:              maxPos + 1,
			StatusChangeType: model.PACK_STATUS_CHANGE_TYPE_PACK,
			FromStatus:       currentPackOrder.PackOrderStatus.Status,
			ToStatus:         model.PACK_STATUS_CLOSED,
			ChangeTime:       grmi.DateTime(time.Now()),
		}
		err = packOrderStatusHistoryDao.InsertOne(&packOrderStatusHistory)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("保存包装单状态变更记录失败, error:" + err.Error())
		}
		currentPackOrder.PackOrderStatus.Status = model.PACK_STATUS_CLOSED
		err = packOrderStatusDao.UpdateOne(&currentPackOrder.PackOrderStatus)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("更新包装单状态数据失败, error:" + err.Error())
		}
		// TODO 更新包装单子项
		_ = session.Commit()
		result.IsClosed = true
		result.Message = "扫描完成, 包装单ID:" + currentPackOrder.PackOrder.PackOrderId + ", 并完成包装单"
		result.PackOrderId = currentPackOrder.PackOrder.PackOrderId
		result.MatchTemplateLi = matchLi
		// 如果是南沙项目 已关包写入座椅数据
		if plantProject == baseModel.PROJECT_NANSHA {
			if result.IsClosed {
				err = impl.NSPackPLC(user, packOrderId, projectId, model.PACK_LOCATION_ON_LINE, &currentPackOrder.PackOrder)
				if err != nil {
					result.PLCResult = false
					result.PLCMessage = err.Error()
				}
			}
		} else {
			// 如果是讴歌项目 如果是讴歌线关包 写plc放行 如果是缤智线 写座椅数据
			if result.IsClosed {
				if packWorkplaceConfig.StrValue1 == baseModel.WORKPLACE_CONFIG_WRITE_SIGN {
					err = impl.AUCRAPackPLC()
					if err != nil {
						result.PLCResult = false
						result.PLCMessage = err.Error()
					}
				} else if packWorkplaceConfig.StrValue1 == baseModel.WORKPLACE_CONIFG_WIRTE_SEAT {
					err = impl.BZPackPLCWithoutCheck(user, packWorkplaceConfig, packOrderId, currentPackOrder.PackOrder.CtrlStr1, true, 0)
					if err != nil {
						result.PLCResult = false
						result.PLCMessage = err.Error()
					}
				}
			}
		}
		return result, nil
	} else if len(matchLi) > 1 {
		// 当前包装单之前没有完全匹配到且只匹配到1个包装模板 现在只匹配到多个包装模板 进行关包处理
		currentPackOrder.PackOrder.CloseTime = grmi.DateTime(time.Now())
		currentPackOrder.PackOrder.Operator = user.UserId
		err = packOrderDao.UpdateOne(&currentPackOrder.PackOrder)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("更新包装单数据失败, error:" + err.Error())
		}
		maxPos, err := packOrderStatusHistoryDao.GetMaxPos(currentPackOrder.PackOrder.PackOrderId)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("获取包装单状态变更记录位置数据失败, error:" + err.Error())
		}
		packOrderStatusHistory := model.PackOrderStatusHistory{
			PackOrderId:      currentPackOrder.PackOrder.PackOrderId,
			Pos:              maxPos + 1,
			StatusChangeType: model.PACK_STATUS_CHANGE_TYPE_PACK,
			FromStatus:       currentPackOrder.PackOrderStatus.Status,
			ToStatus:         model.PACK_STATUS_CLOSED,
			ChangeTime:       grmi.DateTime(time.Now()),
		}
		err = packOrderStatusHistoryDao.InsertOne(&packOrderStatusHistory)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("保存包装单状态变更记录失败, error:" + err.Error())
		}
		currentPackOrder.PackOrderStatus.Status = model.PACK_STATUS_CLOSED
		err = packOrderStatusDao.UpdateOne(&currentPackOrder.PackOrderStatus)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("更新包装单状态数据失败, error:" + err.Error())
		}
		_ = session.Commit()
		result.IsClosed = true
		result.Message = "扫描完成, 包装单ID:" + currentPackOrder.PackOrder.PackOrderId + ", 并完成包装单"
		result.PackOrderId = currentPackOrder.PackOrder.PackOrderId
		result.MatchTemplateLi = matchLi
		// 如果是南沙项目 已关包写入座椅数据
		if plantProject == baseModel.PROJECT_NANSHA {
			if result.IsClosed {
				err = impl.NSPackPLC(user, packOrderId, projectId, model.PACK_LOCATION_ON_LINE, &currentPackOrder.PackOrder)
				if err != nil {
					result.PLCResult = false
					result.PLCMessage = err.Error()
				}
			}
		} else {
			// 如果是讴歌项目 如果是讴歌线关包 写plc放行 如果是缤智线 写座椅数据
			if result.IsClosed {
				if packWorkplaceConfig.StrValue1 == baseModel.WORKPLACE_CONFIG_WRITE_SIGN {
					err = impl.AUCRAPackPLC()
					if err != nil {
						result.PLCResult = false
						result.PLCMessage = err.Error()
					}
				} else if packWorkplaceConfig.StrValue1 == baseModel.WORKPLACE_CONIFG_WIRTE_SEAT {
					err = impl.BZPackPLCWithoutCheck(user, packWorkplaceConfig, packOrderId, currentPackOrder.PackOrder.CtrlStr1, true, 0)
					if err != nil {
						result.PLCResult = false
						result.PLCMessage = err.Error()
					}
				}
			}
		}
		return result, nil
	} else {
		// 如果当前包装单未匹配到任何模板 报错
		if len(tempMatchLi) == 0 {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("当前包装未匹配到任何包装模板, 请确认!")
		} else if len(tempMatchLi) == 1 {
			// 如果当前包装单匹配到一个模板 则直接将模板数据写入到当前包装单中
			template := tempMatchLi[0]
			var packTypeId string = template.PackTypeId
			//if serialOrderLi[0].OrderType == baseModel.ODER_TYPE_INTERVAL {
			//	packTypeId = model.PACK_TYPE_INT
			//} else {
			//	packTypeId = template.PackTypeId
			//}
			var checkSyncKey bool = template.CheckSyncKey
			//if currentPackOrder.PackOrder.PackTypeId == model.PACK_TYPE_INT {
			//	checkSyncKey = false
			//} else {
			//	checkSyncKey = template.CheckSyncKey
			//}
			currentPackOrder.PackOrder.PackTemplateId = template.PackTemplateId
			currentPackOrder.PackOrder.PackTypeId = packTypeId
			currentPackOrder.PackOrder.PlanQty = template.PlanQty
			currentPackOrder.CheckSyncKey = checkSyncKey
			err = packOrderDao.UpdateOne(&currentPackOrder.PackOrder)
			if err != nil {
				_ = session.Rollback()
				return nil, grmi.NewBusinessError("保存包装单数据失败, error:" + err.Error())
			}
			packTemplateItemLstDao := dal.NewPackTemplateItemLstDAO(session, user.PlantNr, user.UserId)
			packTemplateItemLi, err := packTemplateItemLstDao.Select([]grmi.Predicate{meta.PackTemplateItemLst_PackTemplateId.NewPredicate(grmi.Equal, template.PackTemplateId)}, []grmi.Field{meta.PackTemplateItemLst_Pos})
			if err != nil {
				_ = session.Rollback()
				return nil, grmi.NewBusinessError("查询包装模板子项数据失败, error:" + err.Error())
			}
			// 更新包装模板子项数据到包装单子项中
			for _, templateLst := range packTemplateItemLi {
				var needGenerateQty int
				tempQty, exist := packOrderItemMap[templateLst.PartId]
				if !exist {
					needGenerateQty = templateLst.PlanQty
				} else {
					needGenerateQty = templateLst.PlanQty - tempQty
				}
				for i := 0; i < needGenerateQty; i++ {
					maxPos, err := packLstDAO.GetMaxPost(currentPackOrder.PackOrder.PackOrderId)
					if err != nil {
						_ = session.Rollback()
						return nil, grmi.NewBusinessError("获取包装单子项位置数据失败, error:" + err.Error())
					}
					packOrderItem := model.PackOrderItemLst{
						PackOrderId: currentPackOrder.PackOrder.PackOrderId,
						Pos:         maxPos + 1,
						PosCode:     templateLst.PosCode,
						Seq:         templateLst.Seq,
						PartId:      templateLst.PartId,
						Status:      model.PACK_STATUS_PLANNED,
						PlanQty:     1,
					}
					err = packLstDAO.InsertOne(&packOrderItem)
					if err != nil {
						_ = session.Rollback()
						return nil, grmi.NewBusinessError("写入包装单子项失败, error:" + err.Error())
					}
				}

			}
			_ = session.Commit()
			result.IsClosed = false
			result.Message = "扫描完成, 包装单ID:" + currentPackOrder.PackOrder.PackOrderId + ", 并匹配到唯一包装模板"
			result.PackOrderId = currentPackOrder.PackOrder.PackOrderId
			result.MatchTemplateLi = tempMatchLi
			return result, nil
		} else {
			var checkSyncKey bool = true
			for _, template := range tempMatchLi {
				if !template.CheckSyncKey {
					checkSyncKey = false
				}
			}
			//if currentPackOrder.PackOrder.PackTypeId == model.PACK_TYPE_INT {
			//	checkSyncKey = false
			//} else {
			//	for _, template := range tempMatchLi {
			//		if !template.CheckSyncKey {
			//			checkSyncKey = false
			//		}
			//	}
			//}

			currentPackOrder.PackOrder.CheckSyncKey = checkSyncKey
			err = packOrderDao.UpdateOne(&currentPackOrder.PackOrder)
			if err != nil {
				_ = session.Rollback()
				return nil, grmi.NewBusinessError("保存包装单数据失败, error:" + err.Error())
			}
			_ = session.Commit()
			result.IsClosed = false
			result.Message = "扫描完成, 包装单ID:" + currentPackOrder.PackOrder.PackOrderId + ", 匹配到多个包装模板"
			result.PackOrderId = currentPackOrder.PackOrder.PackOrderId
			result.MatchTemplateLi = tempMatchLi
			return result, nil
		}
	}
}

// ClosePackOrder 关闭包装单
func (impl *PackOrderServiceImplement) ClosePackOrder(user *global.User, packOrderId string) error {
	grmi.Log(user, "/services/jit/implments/PackOrder.service.impl.go", "ClosePackOrder", "关闭包装单")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()

	var err error
	dao := dal.NewPackOrderDAO(session, user.PlantNr, user.UserId)
	statusDao := dal.NewPackOrderStatusDAO(session, user.PlantNr, user.UserId)
	statusHistoryDao := dal.NewPackOrderStatusHistoryDAO(session, user.PlantNr, user.UserId)
	packOrder, err := dao.SelectOne(packOrderId)
	if err != nil {
		return grmi.NewBusinessError("查询包装单失败, error:" + err.Error())
	}
	if packOrder == nil {
		return grmi.NewBusinessError("不存在该包装单, 包装单Id:" + packOrderId)
	}
	if packOrder.PackTypeId != model.PACK_TYPE_INT {
		return grmi.NewBusinessError("不是内部包装单，不允许手动关包")
	}
	packOrderStatus, err := statusDao.SelectOne(packOrderId)
	if err != nil {
		return grmi.NewBusinessError("查询包装单状态失败, error:" + err.Error())
	}
	if packOrderStatus == nil {
		return grmi.NewBusinessError("未查询到包装单状态")
	}
	if packOrderStatus.Status != model.PACK_STATUS_RUNNING {
		return grmi.NewBusinessError("包状态状态不是包装中, 不能关包")
	}
	if err := session.Begin(); err != nil {
		return err
	}
	packOrder.ShortTime = grmi.DateTime(time.Now())
	packOrder.ShortBy = user.UserId
	packOrder.ShortPackToggle = true
	err = dao.UpdateOne(packOrder)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新包装单数据失败, error:" + err.Error())
	}
	maxPos, err := statusHistoryDao.GetMaxPos(packOrderId)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("获取包装单状态变更历史位置数据失败, error:" + err.Error())
	}
	statusHistory := model.PackOrderStatusHistory{
		PackOrderId:      packOrderId,
		Pos:              maxPos + 1,
		StatusChangeType: model.PACK_STATUS_CHANGE_TYPE_PACK,
		FromStatus:       model.PACK_STATUS_RUNNING,
		ToStatus:         model.PACK_STATUS_CLOSED,
		ChangeTime:       grmi.DateTime(time.Now()),
	}
	err = statusHistoryDao.InsertOne(&statusHistory)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("写入包装单状态变更历史失败, error:" + err.Error())
	}
	packOrderStatus.Status = model.PACK_STATUS_CLOSED
	err = statusDao.UpdateOne(packOrderStatus)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新包装单状态失败, error:" + err.Error())
	}
	_ = session.Commit()
	return nil
}

// CreateByTemplate 通过模板创建包装单
func (impl *PackOrderServiceImplement) CreateByTemplate(user *global.User, packTemplateId string) (err error) {
	grmi.Log(user, "/services/jit/implments/PackOrder.service.impl.go", "CreateByTemplate", "通过包装模板创建包装单")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()

	packOrderDao := dal.NewPackOrderDAO(session, user.PlantNr, user.UserId)
	packOrderStatusDao := dal.NewPackOrderStatusDAO(session, user.PlantNr, user.UserId)
	packOrderItemDao := dal.NewPackOrderItemLstDAO(session, user.PlantNr, user.UserId)
	projectDao := meDal.NewProjectDAO(session, user.PlantNr, user.UserId)
	snrDao := baseDal.NewSnrDAO(session, user.PlantNr, user.UserId)
	packTemplateDao := dal.NewPackTemplateDAO(session, user.PlantNr, user.UserId)
	packTemplateItemDao := dal.NewPackTemplateItemLstDAO(session, user.PlantNr, user.UserId)
	// 查询校验模板数据
	packTemplate, err := packTemplateDao.SelectOne(packTemplateId)
	if err != nil {
		return grmi.NewBusinessError("查询包装模板失败, error:" + err.Error())
	}
	if packTemplate == nil {
		return grmi.NewBusinessError("不存在选定的包装模板，模板ID:" + packTemplateId)
	}
	if !packTemplate.EnabledToggle {
		return grmi.NewBusinessError("该包装模板未启用, 模板ID:" + packTemplateId)
	}
	packTemplateItemLi, err := packTemplateItemDao.Select([]grmi.Predicate{meta.PackTemplateItemLst_PackTemplateId.NewPredicate(grmi.Equal, packTemplateId)}, []grmi.Field{meta.PackTemplateItemLst_Pos})
	if err != nil {
		return grmi.NewBusinessError("查询包装模板子项失败, error:" + err.Error())
	}
	project, err := projectDao.SelectOne(packTemplate.ProjectId)
	if err != nil {
		return grmi.NewBusinessError("查询车型项目数据失败, error:" + err.Error())
	}
	if project == nil {
		return grmi.NewBusinessError("车型项目数据不存在, 项目ID:" + packTemplate.ProjectId)
	}
	if err = session.Begin(); err != nil {
		return grmi.NewBusinessError("开启事务失败, error:" + err.Error())
	}
	packOrderId, err := snrDao.GetNextSnr(project.PackOrderSnr)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("生成包装单流水号失败， error:" + err.Error())
	}
	packOrder := model.PackOrder{
		PackOrderId:    packOrderId,
		PackTemplateId: packTemplateId,
		ProjectId:      packTemplate.ProjectId,
		PackTypeId:     packTemplate.PackTypeId,
		PlanQty:        packTemplate.PlanQty,
		OpenTime:       grmi.DateTime(time.Now()),
		Operator:       user.UserId,
	}

	err = packOrderDao.InsertOne(&packOrder)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("保存包装单数据失败, error:" + err.Error())
	}
	packOrderStatus := model.PackOrderStatus{
		PackOrderId: packOrderId,
		Status:      model.PACK_STATUS_PLANNED,
		LoadStatus:  model.PACK_STATUS_PLANNED,
		ShipStatus:  model.SHIP_STATUS_PLANNED,
	}
	err = packOrderStatusDao.InsertOne(&packOrderStatus)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("保存包装单状态失败, error:" + err.Error())
	}
	for index, packTemplateItem := range packTemplateItemLi {
		for i := 0; i < packTemplateItem.PlanQty; i++ {
			packOrderItem := model.PackOrderItemLst{
				PackOrderId: packOrderId,
				Pos:         index + 1,
				PosCode:     packTemplateItem.PosCode,
				OemSeq:      0,
				Seq:         packTemplateItem.Seq,
				PartId:      packTemplateItem.PartId,
				Status:      model.PACK_STATUS_PLANNED,
				PlanQty:     1,
			}
			err = packOrderItemDao.InsertOne(&packOrderItem)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("保存包装单子项失败, error:" + err.Error())
			}
		}

	}
	_ = session.Commit()
	return nil
}

// SplitPackOrder 拆包
func (impl *PackOrderServiceImplement) SplitPackOrder(user *global.User, packOrderId string) error {
	grmi.Log(user, "/services/jit/implments/PackOrder.service.impl.go", "SplitPackOrder", "拆包")
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()

	packOrderDao := dal.NewPackOrderDAO(session, user.PlantNr, user.UserId)
	packOrderItemDao := dal.NewPackOrderItemLstDAO(session, user.PlantNr, user.UserId)
	packOrderStatusDao := dal.NewPackOrderStatusDAO(session, user.PlantNr, user.UserId)
	packOrderStatusHistoryDao := dal.NewPackOrderStatusHistoryDAO(session, user.PlantNr, user.UserId)
	// 校验包装单
	packOrder, err := packOrderDao.SelectOneWithStatus(packOrderId)
	if err != nil {
		return grmi.NewBusinessError("查询包装单数据失败, error:" + err.Error())
	}
	if packOrder == nil {
		return grmi.NewBusinessError("不存在对应的包装单, 包装单ID:" + packOrderId)
	}
	if packOrder.PackOrderStatus.LoadStatus == model.SHIP_STATUS_CLOSED || packOrder.PackOrderStatus.ShipStatus == model.SHIP_STATUS_CLOSED {
		return grmi.NewBusinessError("该包装单已在发运中或已发运,不允许拆包")
	}
	//开启事务
	if err = session.Begin(); err != nil {
		return err
	}
	// 更新包装单操作人员
	packOrder.PackOrder.Operator = user.UserId
	packOrder.PackOrder.CloseTime = grmi.DateTime(time.Now())
	err = packOrderDao.UpdateOne(&packOrder.PackOrder)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新包装单数据失败, error:" + err.Error())
	}
	// 更新包状态状态 及写入变更记录
	maxPos, err := packOrderStatusHistoryDao.GetMaxPos(packOrderId)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("查询包装单状态变更位置失败, error:" + err.Error())
	}
	packOrderStatusHistory := model.PackOrderStatusHistory{
		PackOrderId:      packOrderId,
		Pos:              maxPos + 1,
		StatusChangeType: model.PACK_STATUS_CHANGE_TYPE_PACK,
		FromStatus:       packOrder.PackOrderStatus.Status,
		ToStatus:         model.PACK_STATUS_CANCELED,
		ChangeTime:       grmi.DateTime(time.Now()),
	}
	err = packOrderStatusHistoryDao.InsertOne(&packOrderStatusHistory)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("保存包装单状态变更记录失败, error:" + err.Error())
	}
	packOrder.PackOrderStatus.Status = model.PACK_STATUS_CANCELED
	err = packOrderStatusDao.UpdateOne(&packOrder.PackOrderStatus)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新包装单状态失败, error:" + err.Error())
	}
	// 更新包装单子项状态
	updatePackOrderItem := model.PackOrderItemLst{
		Status: model.PACK_STATUS_CANCELED,
	}
	err = packOrderItemDao.UpdateWhere([]grmi.Predicate{meta.PackOrderItemLst_PackOrderId.NewPredicate(grmi.Equal, packOrderId)}, &updatePackOrderItem, []string{meta.PackOrderItemLst_Status.Name}...)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新包状态子项状态失败, error:" + err.Error())
	}
	_ = session.Commit()
	return nil
}

// SplitPackOrderBySerialOrderId 通过工单ID进行拆包
func (impl *PackOrderServiceImplement) SplitPackOrderBySerialOrderId(user *global.User, serialOrderId string) error {
	grmi.Log(user, "/services/jit/implments/PackOrder.service.impl.go", "SplitPackOrderBySerialOrderId", "拆包")
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()

	packOrderDao := dal.NewPackOrderDAO(session, user.PlantNr, user.UserId)
	packOrderItemDao := dal.NewPackOrderItemLstDAO(session, user.PlantNr, user.UserId)
	packOrderStatusDao := dal.NewPackOrderStatusDAO(session, user.PlantNr, user.UserId)
	packOrderStatusHistoryDao := dal.NewPackOrderStatusHistoryDAO(session, user.PlantNr, user.UserId)
	// 通过工单ID查询包装单
	packItemLi, err := packOrderItemDao.Select([]grmi.Predicate{meta.PackOrderItemLst_SerialOrderId.NewPredicate(grmi.Equal, serialOrderId),
		meta.PackOrderItemLst_Status.NewPredicate(grmi.Equal, model.PACK_STATUS_CLOSED)}, nil)
	if len(packItemLi) == 0 {
		return grmi.NewBusinessError("该工单未进行包")
	}
	packOrderId := packItemLi[0].PackOrderId
	// 校验包装单
	packOrder, err := packOrderDao.SelectOneWithStatus(packOrderId)
	if err != nil {
		return grmi.NewBusinessError("查询包装单数据失败, error:" + err.Error())
	}
	if packOrder == nil {
		return grmi.NewBusinessError("不存在对应的包装单, 包装单ID:" + packOrderId)
	}
	if packOrder.PackOrderStatus.LoadStatus == model.SHIP_STATUS_CLOSED || packOrder.PackOrderStatus.ShipStatus == model.SHIP_STATUS_CLOSED {
		return grmi.NewBusinessError("该包装单已在发运中或已发运,不允许拆包")
	}
	//开启事务
	if err = session.Begin(); err != nil {
		return err
	}
	// 更新包装单操作人员
	packOrder.PackOrder.Operator = user.UserId
	packOrder.PackOrder.CloseTime = grmi.DateTime(time.Now())
	err = packOrderDao.UpdateOne(&packOrder.PackOrder)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新包装单数据失败, error:" + err.Error())
	}
	// 更新包状态状态 及写入变更记录
	maxPos, err := packOrderStatusHistoryDao.GetMaxPos(packOrderId)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("查询包装单状态变更位置失败, error:" + err.Error())
	}
	packOrderStatusHistory := model.PackOrderStatusHistory{
		PackOrderId:      packOrderId,
		Pos:              maxPos + 1,
		StatusChangeType: model.PACK_STATUS_CHANGE_TYPE_PACK,
		FromStatus:       packOrder.PackOrderStatus.Status,
		ToStatus:         model.PACK_STATUS_CANCELED,
		ChangeTime:       grmi.DateTime(time.Now()),
	}
	err = packOrderStatusHistoryDao.InsertOne(&packOrderStatusHistory)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("保存包装单状态变更记录失败, error:" + err.Error())
	}
	packOrder.PackOrderStatus.Status = model.PACK_STATUS_CANCELED
	err = packOrderStatusDao.UpdateOne(&packOrder.PackOrderStatus)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新包装单状态失败, error:" + err.Error())
	}
	// 更新包装单子项状态
	updatePackOrderItem := model.PackOrderItemLst{
		Status: model.PACK_STATUS_CANCELED,
	}
	err = packOrderItemDao.UpdateWhere([]grmi.Predicate{meta.PackOrderItemLst_PackOrderId.NewPredicate(grmi.Equal, packOrderId)}, &updatePackOrderItem, []string{meta.PackOrderItemLst_Status.Name}...)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("更新包状态子项状态失败, error:" + err.Error())
	}
	_ = session.Commit()
	return nil
}

// GetUserOperatePackOrder 获取当前用户操作的包装单
func (impl *PackOrderServiceImplement) GetUserOperatePackOrder(user *global.User, location string) (string, error) {
	grmi.Log(user, "/services/jit/implments/PackOrder.service.impl.go", "GetUserOperatePackOrder", "获取当前用户操作的包装单")
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()

	dao := dal.NewPackOrderDAO(session, user.PlantNr, user.UserId)
	packOrderLi, err := dao.SelectUserRunningPackOrder(user.UserId, location)
	if err != nil {
		return "", grmi.NewBusinessError("查询用户操作中的包装单失败, error:" + err.Error())
	}
	if len(packOrderLi) == 0 {
		return "", nil
	} else {
		return packOrderLi[0].PackOrder.PackOrderId, nil
	}
}

// ScanBarcodeOutLine 线外工位包装扫描条码
func (impl *PackOrderServiceImplement) ScanBarcodeOutLine(user *global.User, barcode string) (*model.PackOrderInfo, error) {
	grmi.Log(user, "/services/jit/implments/PackOrder.service.impl.go", "ScanBarcodeOutLine", "线外打包")
	result := &model.PackOrderInfo{}
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	result.PLCResult = true
	snrDao := baseDal.NewSnrDAO(session, user.PlantNr, user.UserId)
	packLstDAO := dal.NewPackOrderItemLstDAO(session, user.PlantNr, user.UserId)
	packOrderDao := dal.NewPackOrderDAO(session, user.PlantNr, user.UserId)
	packOrderStatusDao := dal.NewPackOrderStatusDAO(session, user.PlantNr, user.UserId)
	packOrderStatusHistoryDao := dal.NewPackOrderStatusHistoryDAO(session, user.PlantNr, user.UserId)
	projectDao := meDal.NewProjectDAO(session, user.PlantNr, user.UserId)
	packOrderPlcErrDao := dal.NewPackOrderPlcErrorDAO(session, user.PlantNr, user.UserId)
	plantDao := baseDal.NewPlantDAO(session, user.UserId)
	plant, err := plantDao.SelectOne(user.PlantNr)
	if err != nil {
		return nil, grmi.NewBusinessError("查询工厂数据失败, 错误:" + err.Error())
	}
	if plant == nil {
		return nil, grmi.NewBusinessError("用户归属工厂不存在, 工厂ID:" + strconv.Itoa(user.PlantNr))
	}
	plantProject := plant.PlantProject
	if plantProject == baseModel.PROJECT_NANSHA {
		errorLi, err := packOrderPlcErrDao.Select([]grmi.Predicate{meta.PackOrderPlcError_Location.NewPredicate(grmi.Equal, model.PACK_LOCATION_ON_LINE),
			meta.PackOrderPlcError_Status.NewPredicate(grmi.LessThen, model.PACK_STATUS_CLOSED)}, nil)
		if err != nil {
			return nil, grmi.NewBusinessError("查询座椅下线写入PLC数据错误失败, error:" + err.Error())
		}
		if len(errorLi) != 0 {
			return nil, grmi.NewBusinessError("当前存在未处理的座椅下线写入PLC错误")
		}
	}
	// 初始化全局的包装模板数据
	if model.AllPackTemplate.Data == nil {
		templateLstDao := dal.NewPackTemplateItemLstDAO(session, user.PlantNr, user.UserId)
		err := templateLstDao.InitGlobalPackTemplate()
		if err != nil {
			return nil, grmi.NewBusinessError("初始化全局包装模板失败, error:" + err.Error())
		}
	}
	//判断条码是否已经生成过包装
	dataList, err := packLstDAO.Select([]grmi.Predicate{
		meta.PackOrderItemLst_SerialOrderId.NewPredicate(grmi.Equal, barcode),
		meta.PackOrderItemLst_Status.NewPredicate(grmi.NotEqual, model.PACK_STATUS_CANCELED),
	}, nil)
	if err != nil {
		return nil, grmi.NewBusinessError("查询包装单详情数据失败, error:" + err.Error())
	}
	if len(dataList) > 0 {
		return nil, grmi.NewBusinessError("该条码已经扫描过!")
	}

	// 校验Barcode是否存在 状态是否是80
	serialOrderDao := omDal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	serialOrderLi, err := serialOrderDao.Select([]grmi.Predicate{omMeta.SerialOrder_SerialOrderId.NewPredicate(grmi.Equal, barcode)}, nil)
	if len(serialOrderLi) == 0 {
		return nil, grmi.NewBusinessError("该条码不存在对应的工单")
	}
	if len(serialOrderLi) > 1 {
		return nil, grmi.NewBusinessError("该条码在系统中存在多个工单")
	}
	serialOrderStatus := serialOrderLi[0].SerialOrderStatus.Status
	if serialOrderLi[0].GenerateFlag {
		return nil, grmi.NewBusinessError("该工单条码已经失效，请使用新的工单条码")
	}
	//if serialOrderStatus != baseModel.WO_STATUS_FINISHED &&
	//	serialOrderStatus != baseModel.WO_STATUS_STOP &&
	//	serialOrderStatus != baseModel.WO_STATUS_INTERRUPT &&
	//	serialOrderStatus != baseModel.WO_STATUS_UNCHECKED {
	//	return nil, grmi.NewBusinessError("条码对应的工单状态不允许打包")
	//}
	if serialOrderStatus != baseModel.WO_STATUS_FINISHED {
		return nil, grmi.NewBusinessError("工单状态不是已完成")
	}
	serialOrder := serialOrderLi[0]
	if serialOrder.QualityCheck != baseModel.QualityCheck_STATUS_OK {
		return nil, grmi.NewBusinessError("工单目检结果不符合要求")
	}
	if serialOrder.EOLCheck == omModel.EOL_STATUS_NG {
		return nil, grmi.NewBusinessError("工单电检不合格")
	}
	// 获取用户之前是否存在未关包的包装单 如果存在则使用之前的包装单ID 如果不存在则创建包装单 如果超过一个则报错
	var packOrderId string
	packOrderLi, err := packOrderDao.SelectUserRunningPackOrder(user.UserId, model.PACK_LOCATION_OUT_LINE)
	if err != nil {
		return nil, grmi.NewBusinessError("获取用户之前的操作的包装单数据失败, error:" + err.Error())
	}
	if len(packOrderLi) == 1 {
		packOrderId = packOrderLi[0].PackOrder.PackOrderId
	} else if len(packOrderLi) == 0 {
		packOrderId = ""
	} else {
		return nil, grmi.NewBusinessError("该用户现在存在多个包装中的包装单， 请确认")
	}
	// 通过工单条码获取总成
	artId := serialOrderLi[0].ArtId
	projectId := serialOrderLi[0].ProjectId
	project, err := projectDao.SelectOne(projectId)
	if err != nil {
		return nil, grmi.NewBusinessError("查询车型项目数据失败， error:" + err.Error())
	}
	if project == nil {
		return nil, grmi.NewBusinessError("车型项目数据不存在，项目ID:" + projectId)
	}

	if err := session.Begin(); err != nil {
		return nil, grmi.NewBusinessError("事务开启失败, error:" + err.Error())
	}
	currentPackOrder := &model.PackOrderWithStatus{}
	// 如果当前用户不存在操作中未关闭的包装单, 则创建包装单数据
	if packOrderId == "" {
		packOrderId, err = snrDao.GetNextSnr(project.PackOrderSnr)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("生成包装单流水号失败, error:" + err.Error())
		}
		packOrder := model.PackOrder{
			PackOrderId:  packOrderId,
			ProjectId:    projectId,
			PlanQty:      1,
			ActQty:       1,
			PackTypeId:   model.PACK_TYPE_STD,
			OpenTime:     grmi.DateTime(time.Now()),
			Operator:     user.UserId,
			PackLocation: model.PACK_LOCATION_OUT_LINE,
		}
		err = packOrderDao.InsertOne(&packOrder)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("插入包装单失败, error:" + err.Error())
		}
		packOrderStatus := model.PackOrderStatus{
			PackOrderId: packOrderId,
			Status:      model.PACK_STATUS_RUNNING,
			LoadStatus:  model.PACK_STATUS_PLANNED,
			ShipStatus:  model.SHIP_STATUS_PLANNED,
		}
		currentPackOrder.PackOrder = packOrder
		currentPackOrder.PackOrderStatus = packOrderStatus
		err = packOrderStatusDao.InsertOne(&packOrderStatus)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("保存包装单状态失败, error:" + err.Error())
		}
		// 写入当前扫描的包装单子项
		packOrderLst := model.PackOrderItemLst{
			PackOrderId:   packOrderId,
			Pos:           1,
			PartId:        artId,
			SerialOrderId: barcode,
			Status:        model.PACK_STATUS_CLOSED,
			PlanQty:       1,
			ActQty:        1,
		}
		err = packLstDAO.InsertOne(&packOrderLst)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("插入包装单细则失败, error:" + err.Error())
		}
	} else {
		// 如果当前用户存在操作中的未关包的包装单 则进行查询
		currentPackOrder, err = packOrderDao.SelectOneWithStatus(packOrderId)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("查询包装单数据失败, error:" + err.Error())
		}
		if currentPackOrder == nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("对应的包装单数据不存在, 包装单ID:" + packOrderId)
		}

		maxPos, err := packLstDAO.GetMaxPost(packOrderId)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("获取包装项位置数据失败, error:" + err.Error())
		}
		// 如果当前包装单已经匹配到唯一模板
		if currentPackOrder.PackOrder.PackTemplateId != "" {
			packOrderItemLi, err := packLstDAO.Select([]grmi.Predicate{
				meta.PackOrderItemLst_PackOrderId.NewPredicate(grmi.Equal, currentPackOrder.PackOrder.PackOrderId),
				meta.PackOrderItemLst_PartId.NewPredicate(grmi.Equal, artId),
				meta.PackOrderItemLst_Status.NewPredicate(grmi.Equal, model.PACK_STATUS_PLANNED)}, []grmi.Field{meta.PackOrderItemLst_Pos})
			if err != nil {
				_ = session.Rollback()
				return nil, grmi.NewBusinessError("查询包装单子项失败, error:" + err.Error())
			}
			if len(packOrderItemLi) == 0 {
				_ = session.Rollback()
				return nil, grmi.NewBusinessError("当前工单无法进入到用户当前操作的包装单, 包装单已经不需要该产品，包装单ID:" + currentPackOrder.PackOrder.PackOrderId)
			}
			firstItem := packOrderItemLi[0]
			firstItem.Status = model.PACK_STATUS_CLOSED
			firstItem.ActQty = 1
			firstItem.SerialOrderId = barcode
			err = packLstDAO.UpdateOne(&firstItem)
			if err != nil {
				_ = session.Rollback()
				return nil, grmi.NewBusinessError("更新包装单子项失败, error:" + err.Error())
			}
			currentPackOrder.PackOrder.ActQty += 1
			currentPackOrder.PackOrder.Operator = user.UserId
			if currentPackOrder.PackOrder.PlanQty == currentPackOrder.PackOrder.ActQty {
				currentPackOrder.PackOrder.CloseTime = grmi.DateTime(time.Now())
				maxPos, err = packOrderStatusHistoryDao.GetMaxPos(currentPackOrder.PackOrder.PackOrderId)
				if err != nil {
					_ = session.Rollback()
					return nil, grmi.NewBusinessError("查询包装单状态变更位置数据失败, error:" + err.Error())
				}
				packOrderStatusHistory := model.PackOrderStatusHistory{
					PackOrderId:      packOrderId,
					Pos:              maxPos + 1,
					StatusChangeType: model.PACK_STATUS_CHANGE_TYPE_PACK,
					FromStatus:       currentPackOrder.PackOrderStatus.Status,
					ToStatus:         model.PACK_STATUS_CLOSED,
					ChangeTime:       grmi.DateTime(time.Now()),
				}
				err = packOrderStatusHistoryDao.InsertOne(&packOrderStatusHistory)
				if err != nil {
					_ = session.Rollback()
					return nil, grmi.NewBusinessError("保存包装单状态变更记录失败, error:" + err.Error())
				}
				currentPackOrder.PackOrderStatus.Status = model.PACK_STATUS_CLOSED
				err = packOrderStatusDao.UpdateOne(&currentPackOrder.PackOrderStatus)
				if err != nil {
					_ = session.Rollback()
					return nil, grmi.NewBusinessError("更新包装单状态失败, error:" + err.Error())
				}
			}
			err = packOrderDao.UpdateOne(&currentPackOrder.PackOrder)
			if err != nil {
				_ = session.Rollback()
				return nil, grmi.NewBusinessError("更新包装单数据失败, error:" + err.Error())
			}
			_ = session.Commit()
			if currentPackOrder.PackOrderStatus.Status == model.PACK_STATUS_CLOSED {
				result.IsClosed = true
				result.Message = "扫描完成, 包装单ID:" + currentPackOrder.PackOrder.PackOrderId + " , 已完成该包装单!"
			} else {
				result.IsClosed = false
				result.Message = "扫描完成, 包装单ID:" + currentPackOrder.PackOrder.PackOrderId
			}
			if plantProject == baseModel.PROJECT_NANSHA {
				if result.IsClosed {
					err = impl.NSPackPLC(user, packOrderId, projectId, model.PACK_LOCATION_ON_LINE, &currentPackOrder.PackOrder)
					if err != nil {
						result.PLCResult = false
						result.PLCMessage = err.Error()
					}
				}
			}
			result.PackOrderId = currentPackOrder.PackOrder.PackOrderId
			return result, nil
		} else {
			// 当前包装单还没有匹配到唯一模板
			currentPackOrder.PackOrder.PlanQty += 1
			currentPackOrder.PackOrder.ActQty += 1
			packOrderLst := model.PackOrderItemLst{
				PackOrderId:   packOrderId,
				Pos:           maxPos + 1,
				PartId:        artId,
				SerialOrderId: barcode,
				Status:        model.PACK_STATUS_CLOSED,
				PlanQty:       1,
				ActQty:        1,
			}
			err = packLstDAO.InsertOne(&packOrderLst)
			if err != nil {
				_ = session.Rollback()
				return nil, grmi.NewBusinessError("插入包装单细则失败, error:" + err.Error())
			}

		}

	}

	lstLi, err := packLstDAO.Select([]grmi.Predicate{meta.PackOrderItemLst_PackOrderId.NewPredicate(grmi.Equal, packOrderId)}, []grmi.Field{meta.PackOrderItemLst_Pos})
	if err != nil {
		_ = session.Rollback()
		return nil, grmi.NewBusinessError("获取已进包的包装项数据失败, error:" + err.Error())
	}
	packOrderItemMap := make(map[string]int)
	matchLi := make([]model.PackTemplate, 0)
	for _, packOrderItem := range lstLi {
		_, exist := packOrderItemMap[packOrderItem.PartId]
		if !exist {
			packOrderItemMap[packOrderItem.PartId] = 0
		}
		packOrderItemMap[packOrderItem.PartId] += 1
	}
	for _, template := range model.AllPackTemplate.Data {
		// 如果当前包装单的包装总成数据和包装模板的总成包装数据总类不一致 进行下一次循环
		if len(packOrderItemMap) != len(template.PartIdMap) {
			continue
		}
		var matchSign = true
		for partId, qty := range packOrderItemMap {
			tempQty, exist := template.PartIdMap[partId]
			if !exist {
				matchSign = false
				break
			}
			if tempQty != qty {
				matchSign = false
				break
			}
		}
		if matchSign {
			matchLi = append(matchLi, template)
		}
	}
	tempMatchLi := make([]model.PackTemplate, 0)
	for _, template := range model.AllPackTemplate.Data {
		// 如果当前包装单的包装总成类型多余包装模板的 进行下一次循环
		if len(packOrderItemMap) > len(template.PartIdMap) {
			continue
		}
		var tempMatchSign = true
		for partId, qty := range packOrderItemMap {
			tempQty, exist := template.PartIdMap[partId]
			if !exist {
				tempMatchSign = false
				break
			}
			if tempQty > qty {
				tempMatchSign = false
				break
			}
		}
		if tempMatchSign {
			tempMatchLi = append(tempMatchLi, template)
		}
	}

	if len(matchLi) == 1 {
		// 当前包装单之前没有完全匹配到且只匹配到1个包装模板 现在只匹配到一个包装模板 进行关包处理
		template := matchLi[0]
		currentPackOrder.PackOrder.CloseTime = grmi.DateTime(time.Now())
		currentPackOrder.PackOrder.Operator = user.UserId
		currentPackOrder.PackOrder.PackTemplateId = template.PackTemplateId
		currentPackOrder.PackOrder.PackTypeId = template.PackTypeId
		currentPackOrder.PackOrder.PlanQty = template.PlanQty
		err = packOrderDao.UpdateOne(&currentPackOrder.PackOrder)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("更新包装单数据失败, error:" + err.Error())
		}
		maxPos, err := packOrderStatusHistoryDao.GetMaxPos(currentPackOrder.PackOrder.PackOrderId)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("获取包装单状态变更记录位置数据失败, error:" + err.Error())
		}
		packOrderStatusHistory := model.PackOrderStatusHistory{
			PackOrderId:      currentPackOrder.PackOrder.PackOrderId,
			Pos:              maxPos + 1,
			StatusChangeType: model.PACK_STATUS_CHANGE_TYPE_PACK,
			FromStatus:       currentPackOrder.PackOrderStatus.Status,
			ToStatus:         model.PACK_STATUS_CLOSED,
			ChangeTime:       grmi.DateTime(time.Now()),
		}
		err = packOrderStatusHistoryDao.InsertOne(&packOrderStatusHistory)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("保存包装单状态变更记录失败, error:" + err.Error())
		}
		currentPackOrder.PackOrderStatus.Status = model.PACK_STATUS_CLOSED
		err = packOrderStatusDao.UpdateOne(&currentPackOrder.PackOrderStatus)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("更新包装单状态数据失败, error:" + err.Error())
		}
		// TODO 更新包装单子项
		_ = session.Commit()
		result.IsClosed = true
		result.Message = "扫描完成, 包装单ID:" + currentPackOrder.PackOrder.PackOrderId + ", 并完成包装单"
		result.PackOrderId = currentPackOrder.PackOrder.PackOrderId
		result.MatchTemplateLi = matchLi
		if plantProject == baseModel.PROJECT_NANSHA {
			if result.IsClosed {
				err = impl.NSPackPLC(user, packOrderId, projectId, model.PACK_LOCATION_ON_LINE, &currentPackOrder.PackOrder)
				if err != nil {
					result.PLCResult = false
					result.PLCMessage = err.Error()
				}
			}
		}
		return result, nil
	} else if len(matchLi) > 1 {
		// 当前包装单之前没有完全匹配到且只匹配到1个包装模板 现在只匹配到多个包装模板 进行关包处理
		currentPackOrder.PackOrder.CloseTime = grmi.DateTime(time.Now())
		currentPackOrder.PackOrder.Operator = user.UserId
		err = packOrderDao.UpdateOne(&currentPackOrder.PackOrder)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("更新包装单数据失败, error:" + err.Error())
		}
		maxPos, err := packOrderStatusHistoryDao.GetMaxPos(currentPackOrder.PackOrder.PackOrderId)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("获取包装单状态变更记录位置数据失败, error:" + err.Error())
		}
		packOrderStatusHistory := model.PackOrderStatusHistory{
			PackOrderId:      currentPackOrder.PackOrder.PackOrderId,
			Pos:              maxPos + 1,
			StatusChangeType: model.PACK_STATUS_CHANGE_TYPE_PACK,
			FromStatus:       currentPackOrder.PackOrderStatus.Status,
			ToStatus:         model.PACK_STATUS_CLOSED,
			ChangeTime:       grmi.DateTime(time.Now()),
		}
		err = packOrderStatusHistoryDao.InsertOne(&packOrderStatusHistory)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("保存包装单状态变更记录失败, error:" + err.Error())
		}
		currentPackOrder.PackOrderStatus.Status = model.PACK_STATUS_CLOSED
		err = packOrderStatusDao.UpdateOne(&currentPackOrder.PackOrderStatus)
		if err != nil {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("更新包装单状态数据失败, error:" + err.Error())
		}
		_ = session.Commit()
		result.IsClosed = true
		result.Message = "扫描完成, 包装单ID:" + currentPackOrder.PackOrder.PackOrderId + ", 并完成包装单"
		result.PackOrderId = currentPackOrder.PackOrder.PackOrderId
		result.MatchTemplateLi = matchLi
		if plantProject == baseModel.PROJECT_NANSHA {
			if result.IsClosed {
				err = impl.NSPackPLC(user, packOrderId, projectId, model.PACK_LOCATION_ON_LINE, &currentPackOrder.PackOrder)
				if err != nil {
					result.PLCResult = false
					result.PLCMessage = err.Error()
				}
			}
		}
		return result, nil
	} else {
		// 如果当前包装单未匹配到任何模板 报错
		if len(tempMatchLi) == 0 {
			_ = session.Rollback()
			return nil, grmi.NewBusinessError("当前包装未匹配到任何包装模板, 请确认!")
		} else if len(tempMatchLi) == 1 {
			// 如果当前包装单匹配到一个模板 则直接将模板数据写入到当前包装单中
			template := tempMatchLi[0]
			currentPackOrder.PackOrder.PackTemplateId = template.PackTemplateId
			currentPackOrder.PackOrder.PackTypeId = template.PackTypeId
			currentPackOrder.PackOrder.PlanQty = template.PlanQty
			err = packOrderDao.UpdateOne(&currentPackOrder.PackOrder)
			if err != nil {
				_ = session.Rollback()
				return nil, grmi.NewBusinessError("保存包装单数据失败, error:" + err.Error())
			}
			packTemplateItemLstDao := dal.NewPackTemplateItemLstDAO(session, user.PlantNr, user.UserId)
			packTemplateItemLi, err := packTemplateItemLstDao.Select([]grmi.Predicate{meta.PackTemplateItemLst_PackTemplateId.NewPredicate(grmi.Equal, template.PackTemplateId)}, []grmi.Field{meta.PackTemplateItemLst_Pos})
			if err != nil {
				_ = session.Rollback()
				return nil, grmi.NewBusinessError("查询包装模板子项数据失败, error:" + err.Error())
			}
			// 更新包装模板子项数据到包装单子项中
			for _, templateLst := range packTemplateItemLi {
				var needGenerateQty int
				tempQty, exist := packOrderItemMap[templateLst.PartId]
				if !exist {
					needGenerateQty = templateLst.PlanQty
				} else {
					needGenerateQty = templateLst.PlanQty - tempQty
				}
				for i := 0; i < needGenerateQty; i++ {
					maxPos, err := packLstDAO.GetMaxPost(currentPackOrder.PackOrder.PackOrderId)
					if err != nil {
						_ = session.Rollback()
						return nil, grmi.NewBusinessError("获取包装单子项位置数据失败, error:" + err.Error())
					}
					packOrderItem := model.PackOrderItemLst{
						PackOrderId: currentPackOrder.PackOrder.PackOrderId,
						Pos:         maxPos + 1,
						PosCode:     templateLst.PosCode,
						Seq:         templateLst.Seq,
						PartId:      templateLst.PartId,
						Status:      model.PACK_STATUS_PLANNED,
						PlanQty:     1,
					}
					err = packLstDAO.InsertOne(&packOrderItem)
					if err != nil {
						_ = session.Rollback()
						return nil, grmi.NewBusinessError("写入包装单子项失败, error:" + err.Error())
					}
				}

			}
			_ = session.Commit()
			result.IsClosed = false
			result.Message = "扫描完成, 包装单ID:" + currentPackOrder.PackOrder.PackOrderId + ", 并匹配到唯一包装模板"
			result.PackOrderId = currentPackOrder.PackOrder.PackOrderId
			result.MatchTemplateLi = tempMatchLi
			return result, nil
		} else {
			err = packOrderDao.UpdateOne(&currentPackOrder.PackOrder)
			if err != nil {
				_ = session.Rollback()
				return nil, grmi.NewBusinessError("保存包装单数据失败, error:" + err.Error())
			}
			_ = session.Commit()
			result.IsClosed = false
			result.Message = "扫描完成, 包装单ID:" + currentPackOrder.PackOrder.PackOrderId + ", 匹配到多个包装模板"
			result.PackOrderId = currentPackOrder.PackOrder.PackOrderId
			result.MatchTemplateLi = tempMatchLi
			return result, nil
		}
	}
}

// RepairPlcErr 修复包装单和plc相互的错误
func (impl *PackOrderServiceImplement) RepairPlcErr(user *global.User, packOrderId string) error {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	packOrderDao := dal.NewPackOrderDAO(session, user.PlantNr, user.UserId)
	packOrderStatusDao := dal.NewPackOrderStatusDAO(session, user.PlantNr, user.UserId)
	packOrderPlcErrDao := dal.NewPackOrderPlcErrorDAO(session, user.PlantNr, user.UserId)
	workplaceConfigDao := baseDal.NewWorkPlaceConfigDAO(session, user.PlantNr, user.UserId)
	packOrderError, err := packOrderPlcErrDao.SelectOne(packOrderId)
	if err != nil {
		return grmi.NewBusinessError("查询错误项失败, error:" + err.Error())
	}
	if packOrderError == nil {
		return grmi.NewBusinessError("错误项不存在")
	}
	if packOrderError.Status == model.PACK_STATUS_CLOSED {
		return grmi.NewBusinessError("错误项已修复")
	}
	switch packOrderError.Source {
	case "NS":
		// 座椅数据回写错误处理
		if packOrderError.Location == model.PACK_LOCATION_BACKFLUSH {
			seatData := packOrderError.SeatData
			var seatStr string
			switch packOrderError.Step {
			case -1: // plc数据解析成字符串
				seatBytes, err := hex.DecodeString(seatData)
				if err != nil {
					return grmi.NewBusinessError("解析座椅数据失败, 错误:" + err.Error())
				}
				seatStr = string(seatBytes)
				fallthrough
			case -2: // 座椅数据绑定包装单 更新包装单状态
				packOrderLi, err := packOrderDao.Select([]grmi.Predicate{meta.PackOrder_RFID.NewPredicate(grmi.Equal, seatStr)}, nil)
				if err != nil {
					return grmi.NewBusinessError("查询包装单数据失败, 错误:" + err.Error())
				}
				if len(packOrderLi) == 0 {
					return grmi.NewBusinessError("不存RFID对应的包装单, RFID:" + seatStr)
				}
				if len(packOrderLi) > 1 {
					return grmi.NewBusinessError("该RFID匹配到多个包装单, RFID:" + seatStr)
				}
				packOrder := packOrderLi[0]
				packOrderStatus, err := packOrderStatusDao.SelectOne(packOrder.PackOrderId)
				if err != nil {
					return grmi.NewBusinessError("查询包装单状态数据失败, 错误:" + err.Error())
				}
				packOrderStatus.ShipStatus = model.SHIP_STATUS_CLOSED
				err = packOrderStatusDao.UpdateOne(packOrderStatus)
				if err != nil {
					return grmi.NewBusinessError("更新包装单状态失败, 错误:" + err.Error())
				}
				packOrder.CtrlTime1 = grmi.DateTime(time.Now())
				err = packOrderDao.UpdateOne(&packOrder)
				if err != nil {
					return grmi.NewBusinessError("更新包装单回写时间失败, 错误:" + err.Error())
				}
			}
			return nil
		} else {
			// 座椅下线和线外打包plc错误处理
			plcType := conf.DbConfig.OfflinePLCType
			retryCount := conf.DbConfig.OfflinePLCRetry
			var plcAddress string
			var DBAddress string
			if packOrderError.Location == model.PACK_LOCATION_ON_LINE {
				plcAddress = conf.DbConfig.OfflinePLCAddress
			}
			var seatData string
			if packOrderError.Step != 0 {
				seatData = packOrderError.SeatData
			}
			switch packOrderError.Step {
			case 0, 1: // 组装座椅数据
				packOrder, err := packOrderDao.SelectOne(packOrderId)
				if err != nil {
					return grmi.NewBusinessError("查询包装单数据失败, error:" + err.Error())
				}
				if packOrder == nil {
					return grmi.NewBusinessError("包装单不存在")
				}
				seatData, err = impl.MakeUpSeatData(session, user, packOrderId, packOrderError.Location, packOrder.ProjectId)
				if err != nil {
					packOrderError.ErrorInfo = err.Error()
					innerErr := packOrderPlcErrDao.UpdateOne(packOrderError)
					if innerErr != nil {
						return grmi.NewBusinessError(err.Error() + ", 保存错误失败, error:" + err.Error())
					}
					return err
				}
				if seatData == "" {
					return grmi.NewBusinessError("待写入座椅数据为空")
				}
				packOrder.RFID = seatData
				err = packOrderDao.UpdateOne(packOrder)
				if err != nil {
					errorInfo := "保存座椅数据到包装单上失败, 错误:" + err.Error()
					packOrderError.ErrorInfo = err.Error()
					innerErr := packOrderPlcErrDao.UpdateOne(packOrderError)
					if innerErr != nil {
						return grmi.NewBusinessError(err.Error() + ", 保存错误失败, error:" + err.Error())
					}
					return grmi.NewBusinessError(errorInfo)
				}
				fallthrough
			case 2, 3: // 读取标识位 写入座椅数据
				if packOrderError.Location == model.PACK_LOCATION_ON_LINE {
					DBAddress = conf.DbConfig.OfflineDBSign
				}
				valueType := "Boolean"
				data := baseModel.PLC{
					PLCType:      plcType,
					PLCAddress:   plcAddress,
					ValueAddress: DBAddress,
					ValueType:    valueType,
					RetryCount:   retryCount,
				}
				err = impl.SeatOfflineReadSign(data)
				if err != nil {
					packOrderError.Step = 1
					packOrderError.ErrorInfo = err.Error()
					packOrderError.SeatData = seatData
					innerErr := packOrderPlcErrDao.UpdateOne(packOrderError)
					if innerErr != nil {
						return grmi.NewBusinessError(err.Error() + ", 保存错误失败, error:" + err.Error())
					}
					return err
				}
				if packOrderError.Location == model.PACK_LOCATION_ON_LINE {
					DBAddress = conf.DbConfig.OfflineDBSave
				}
				valueType = "Bytes"
				data = baseModel.PLC{
					PLCType:      plcType,
					PLCAddress:   plcAddress,
					ValueAddress: DBAddress,
					ValueType:    valueType,
					RetryCount:   retryCount,
					ValueText:    packOrderError.SeatData,
					ByteCount:    conf.DbConfig.OfflineDBSaveLen,
				}
				err = impl.SeatOfflineWriteSeatData(data)
				if err != nil {
					packOrderError.Step = 2
					packOrderError.ErrorInfo = err.Error()
					packOrderError.SeatData = seatData
					innerErr := packOrderPlcErrDao.UpdateOne(packOrderError)
					if innerErr != nil {
						return grmi.NewBusinessError(err.Error() + ", 保存错误失败, error:" + err.Error())
					}
					return err
				}
				fallthrough
			case 4: // 写入标识位数据
				if packOrderError.Location == model.PACK_LOCATION_ON_LINE {
					DBAddress = conf.DbConfig.OfflineDBSign
				}
				valueType := "Boolean"
				data := baseModel.PLC{
					PLCType:      plcType,
					PLCAddress:   plcAddress,
					ValueAddress: DBAddress,
					ValueType:    valueType,
					RetryCount:   retryCount,
					ValueText:    true,
				}
				err = impl.SeatOfflineWriteSign(data)
				if err != nil {
					packOrderError.Step = 3
					packOrderError.ErrorInfo = err.Error()
					packOrderError.SeatData = seatData
					innerErr := packOrderPlcErrDao.UpdateOne(packOrderError)
					if innerErr != nil {
						return grmi.NewBusinessError(err.Error() + ", 保存错误失败, error:" + err.Error())
					}
					return err
				}
			}
			packOrderError.Status = model.PACK_STATUS_CLOSED
			packOrderError.SeatData = seatData
			err = packOrderPlcErrDao.UpdateOne(packOrderError)
			if err != nil {
				return grmi.NewBusinessError("问题已修复, 但是更新错误项数据状态失败请删除, error:" + err.Error())
			}
			return nil
		}
	case "BZ-OK", "BZ-NG":
		workplaceConfig, err := workplaceConfigDao.SelectOne(packOrderError.IntCtrl2)
		if err != nil {
			return grmi.NewBusinessError("查询工位配置失败, 错误:" + err.Error())
		}
		if workplaceConfig == nil {
			return grmi.NewBusinessError("查询工位配置不存在")
		}
		quality := strings.Split(packOrderError.Source, "-")[1]
		err = impl.BZPackPLCWithoutCheck(user, workplaceConfig, packOrderId, quality, false, packOrderError.Step)
		if err != nil {
			return err
		}
		packOrderError.Status = model.PACK_STATUS_CLOSED
		err = packOrderPlcErrDao.UpdateOne(packOrderError)
		if err != nil {
			return grmi.NewBusinessError("问题已修复, 但是更新错误项数据状态失败请删除, error:" + err.Error())
		}
		return nil
	default:
		return grmi.NewBusinessError("不支持该来源的错误修复")
	}

}
