package implments

import (
	baseDal "LAPP_ACURA_MOM_BACKEND/dao/base"
	eolDal "LAPP_ACURA_MOM_BACKEND/dao/eol"
	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"
	baseMeta "LAPP_ACURA_MOM_BACKEND/meta/base"
	eolMeta "LAPP_ACURA_MOM_BACKEND/meta/eol"
	meta "LAPP_ACURA_MOM_BACKEND/meta/om"
	baseModel "LAPP_ACURA_MOM_BACKEND/models/base"
	eolModel "LAPP_ACURA_MOM_BACKEND/models/eol"
	meModel "LAPP_ACURA_MOM_BACKEND/models/me"
	model "LAPP_ACURA_MOM_BACKEND/models/om"
	"github.com/go-xorm/xorm"
	"strconv"
	"time"
)

// TraceSubArticleBatch 根据物料批次查询mes数据
func (impl *SerialOrderServiceImplement) TraceSubArticleBatch(user *global.User, barcode string, paging *grmi.Paging) (grmi.PagingResult, error) {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	recvDataDao := dal.NewSerialOrderOPDetailRecvDataLstDAO(session, user.PlantNr, user.UserId)
	result, err := recvDataDao.SelectAndPaging(paging, []grmi.Predicate{
		meta.SerialOrderOPDetailRecvDataLst_StepType.NewPredicate(grmi.Equal, baseModel.STEP_CHECK_RULE),
		meta.SerialOrderOPDetailRecvDataLst_RecvData.NewPredicate(grmi.Equal, barcode),
		meta.SerialOrderOPDetailRecvDataLst_Status.NewPredicate(grmi.Equal, 1),
	}, []grmi.Field{meta.SerialOrderOPDetailRecvDataLst_CreateTime})
	if err != nil {
		return grmi.EmptyPagingResult, grmi.NewBusinessError("查询数据失败, 错误:" + err.Error())
	}
	workplaceDao := baseDal.NewWorkPlaceDAO(session, user.PlantNr, user.UserId)
	lst := result.Records.([]model.SerialOrderOPDetailRecvDataLst)
	exportItemLi := make([]model.ExportItem, 0, len(lst))
	workplaceMap := make(map[int]string)
	for _, item := range lst {
		workplaceDesc, exist := workplaceMap[item.WorkPlaceNr]
		if !exist {
			workplace, err := workplaceDao.SelectOne(item.WorkPlaceNr)
			if err != nil {
				return grmi.EmptyPagingResult, grmi.NewBusinessError("查询工位数据失败, 错误:" + err.Error())
			}
			if workplace == nil {
				workplaceDesc = "工位系统中已不存在"
			} else {
				workplaceDesc = workplace.WorkPlaceId
			}
			workplaceMap[item.WorkPlaceNr] = workplaceDesc
		}
		exportItem := model.ExportItem{
			SerialOrderId: item.SerialOrderId,
			Po:            item.PO,
			WorkPlace:     workplaceDesc,
			ArtId:         item.SubArtId,
			BarCode:       item.RecvData,
			UsedTime:      item.CreateTime.Restore().Format(grmi.DateTimeOutFormat),
		}
		exportItemLi = append(exportItemLi, exportItem)
	}
	result.Records = exportItemLi
	return result, nil
}

// ExportTraceSubArticleBatch 导出批次零件使用记录
func (impl *SerialOrderServiceImplement) ExportTraceSubArticleBatch(user *global.User, barcode string) (string, error) {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	recvDataDao := dal.NewSerialOrderOPDetailRecvDataLstDAO(session, user.PlantNr, user.UserId)
	workplaceDao := baseDal.NewWorkPlaceDAO(session, user.PlantNr, user.UserId)
	workplaceMap := make(map[int]string)
	result, err := recvDataDao.Select([]grmi.Predicate{
		meta.SerialOrderOPDetailRecvDataLst_StepType.NewPredicate(grmi.Equal, baseModel.STEP_CHECK_RULE),
		meta.SerialOrderOPDetailRecvDataLst_RecvData.NewPredicate(grmi.Equal, barcode),
		meta.SerialOrderOPDetailRecvDataLst_Status.NewPredicate(grmi.Equal, 1),
	}, []grmi.Field{meta.SerialOrderOPDetailRecvDataLst_CreateTime})
	if err != nil {
		return "", grmi.NewBusinessError("查询数据失败, 错误:" + err.Error())
	}
	titleLi := []string{
		"工单ID",
		"使用工序",
		"使用工位",
		"物料ID",
		"批次",
		"使用时间",
	}

	exportLi := make([]interface{}, 0, len(result))
	for _, item := range result {
		workplaceDesc, exist := workplaceMap[item.WorkPlaceNr]
		if !exist {
			workplace, err := workplaceDao.SelectOne(item.WorkPlaceNr)
			if err != nil {
				return "", grmi.NewBusinessError("查询工位数据失败, 错误:" + err.Error())
			}
			if workplace == nil {
				workplaceDesc = "工位系统中已不存在"
			} else {
				workplaceDesc = workplace.WorkPlaceId
			}
			workplaceMap[item.WorkPlaceNr] = workplaceDesc
		}
		exportItem := model.ExportItem{
			SerialOrderId: item.SerialOrderId,
			Po:            item.PO,
			WorkPlace:     workplaceDesc,
			ArtId:         item.SubArtId,
			BarCode:       item.RecvData,
			UsedTime:      item.CreateTime.Restore().Format(grmi.DateTimeOutFormat),
		}
		exportLi = append(exportLi, exportItem)
	}
	filepath, err := grmi.SaveExcelFile(exportLi, titleLi, "Sheet1", "零件批次使用记录")
	return filepath, err

}

// GetProductTraceDataReport 工单数据追溯
func (impl *SerialOrderServiceImplement) GetProductTraceDataReport(user *global.User, serialOrderId string) (interface{}, error) {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	result := model.ProductTraceData{
		SerialOrderId: serialOrderId,
		POLi:          make([]model.ProductTracePOData, 0),
	}
	// 1. 查询工单
	// 2. 通过工单查询生产的产线
	// 4. 通过工序查询当前工序生成工步结果
	serialOrderDao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	serialOrderPoDao := dal.NewSerialOrderPOLstDAO(session, user.PlantNr, user.UserId)
	serialOrderStepDao := dal.NewSerialOrderStepLstDAO(session, user.PlantNr, user.UserId)
	recvDataDao := dal.NewSerialOrderOPDetailRecvDataLstDAO(session, user.PlantNr, user.UserId)
	serialOrder, err := serialOrderDao.SelectOne(serialOrderId)
	if err != nil {
		return nil, grmi.NewBusinessError("查询工单失败, error:" + err.Error())
	}
	if serialOrder == nil {
		return nil, grmi.NewBusinessError("工单不存在, 工单ID:" + serialOrderId)
	}
	// 所有工单ID
	allOrderIdLi := make([]interface{}, 0)
	if serialOrder.OriginSerialOrderId != "" {
		subSerialOrderLi, err := serialOrderDao.Select([]grmi.Predicate{
			meta.SerialOrder_SerialOrderId.NewPredicate(grmi.NotEqual, serialOrderId),
			meta.SerialOrder_OriginSerialOrderId.NewPredicate(grmi.Equal, serialOrder.OriginSerialOrderId),
		}, nil)
		if err != nil {
			return nil, grmi.NewBusinessError("查询工单数据失败, 错误:" + err.Error())
		}
		allOrderIdLi = append(allOrderIdLi, serialOrderId, serialOrder.OriginSerialOrderId)
		for _, subOrder := range subSerialOrderLi {
			allOrderIdLi = append(allOrderIdLi, subOrder.SerialOrderId)
		}
	} else {
		allOrderIdLi = append(allOrderIdLi, serialOrder.SerialOrderId)
	}

	articleDao := baseDal.NewArticleDAO(session, user.PlantNr, user.UserId)
	article, err := articleDao.SelectOne(serialOrder.ArtId, serialOrder.ProjectId)
	if err != nil {
		return nil, grmi.NewBusinessError("查询工单总成数据失败, error:" + err.Error())
	}
	if article == nil {
		return nil, grmi.NewBusinessError("工单绑定总成不存在, 总成ID:" + serialOrder.ArtId)
	}
	//articleAtocdDao := baseDal.NewArticleAtcodLstDAO(session, user.PlantNr, user.UserId)
	//var needEOL bool
	//var needSBR bool
	//attributeLi, err := articleAtocdDao.SelectByArtId(serialOrder.ArtId)
	//if err != nil {
	//	return nil, grmi.NewBusinessError("查询总成关联属性失败, error:" + err.Error())
	//}
	//for _, attributeItem := range attributeLi {
	//	if attributeItem.Attribute.Descr == "EOL" {
	//		needEOL = true
	//	} else if attributeItem.Attribute.Descr == "SBR检测" {
	//		needSBR = true
	//	}
	//}
	allPoLi, err := serialOrderPoDao.SelectByOrderLi(allOrderIdLi, serialOrder.UsedResourceId)
	if err != nil {
		return nil, grmi.NewBusinessError("查询工序数据失败, 错误:" + err.Error())
	}
	poMap := make(map[string]int)
	for _, poItem := range allPoLi {
		_, exist := poMap[poItem.Process.PO]
		if !exist {
			poMap[poItem.Process.PO] = len(result.POLi)
			poData := model.ProductTracePOData{
				PO:     poItem.Process.PO,
				PoDesc: poItem.Process.Descr,
				StepLi: make([]model.ProductTraceStepData, 0),
			}
			result.POLi = append(result.POLi, poData)
		}
	}
	stepLi, err := serialOrderStepDao.Select([]grmi.Predicate{
		meta.SerialOrderStepLst_SerialOrderId.NewPredicate(grmi.Include, allOrderIdLi...),
	}, []grmi.Field{meta.SerialOrderStepLst_StepNo})
	if err != nil {
		return nil, grmi.NewBusinessError("查询工步数据失败, 错误:" + err.Error())
	}
	stepMap := make(map[string]int)
	for _, stepItem := range stepLi {
		mapKey := stepItem.PO + "_" + strconv.Itoa(stepItem.StepNo)
		_, exist := stepMap[mapKey]
		if !exist {
			poIndex := poMap[stepItem.PO]
			stepMap[mapKey] = len(result.POLi[poIndex].StepLi)
			stepData := model.ProductTraceStepData{
				StepNo:     stepItem.StepNo,
				StepDesc:   stepItem.StepDesc,
				RecvDataLi: make([]model.SerialOrderOPDetailRecvDataLst, 0),
			}
			result.POLi[poIndex].StepLi = append(result.POLi[poIndex].StepLi, stepData)
		}
	}

	recvDataLi, err := recvDataDao.Select([]grmi.Predicate{
		meta.SerialOrderOPDetailRecvDataLst_SerialOrderId.NewPredicate(grmi.Include, allOrderIdLi...),
	}, []grmi.Field{
		meta.SerialOrderOPDetailRecvDataLst_SerialOrderId,
		meta.SerialOrderOPDetailRecvDataLst_PO,
		meta.SerialOrderOPDetailRecvDataLst_StepNo,
		meta.SerialOrderOPDetailRecvDataLst_OriginRuleId,
	})
	if err != nil {
		return nil, grmi.NewBusinessError("查询生产数据失败, 错误:" + err.Error())
	}
	for _, recvData := range recvDataLi {
		poIndex, exist := poMap[recvData.PO]
		if !exist {
			continue
		}
		stepKey := recvData.PO + "_" + strconv.Itoa(recvData.StepNo)
		stepIndex, exist := stepMap[stepKey]

		if !exist {
			continue
		}
		result.POLi[poIndex].StepLi[stepIndex].RecvDataLi = append(result.POLi[poIndex].StepLi[stepIndex].RecvDataLi, recvData)
	}
	return result, nil
}

// ExtractEOL 提取工单的电检数据
func (impl *SerialOrderServiceImplement) ExtractEOL(session *xorm.Session, user *global.User, serialOrder *model.SerialOrder) (status bool, remark string, recordT time.Time, err error) {
	eolEngine := db.Eloquent.Slaves()[0]
	eolSession := eolEngine.NewSession()
	eolDrDao := eolDal.NewEOLDRDAO(eolSession, user.UserId)
	eolPaDao := eolDal.NewEOLPADAO(eolSession, user.UserId)
	eolBrDao := eolDal.NewEOLBRDAO(eolSession, user.UserId)
	productDao := meDal.NewProductDAO(session, user.PlantNr, user.UserId)
	// 查询工单是否有返修记录 如果有返修记录 需要在返修记录后有电检数据
	var repairTime time.Time
	repairInfoDao := baseDal.NewRepairInfoDAO(session, user.UserId)
	repairInfoLi, err := repairInfoDao.Select([]grmi.Predicate{
		baseMeta.RepairInfo_SerialOrderId.NewPredicate(grmi.Equal, serialOrder.SerialOrderId),
	}, []grmi.Field{baseMeta.RepairInfo_CreateTime})
	if err != nil {
		return false, "", recordT, grmi.NewBusinessError("查询工单返修记录失败, 错误:" + err.Error())
	}
	if len(repairInfoLi) != 0 {
		repairTime = repairInfoLi[len(repairInfoLi)-1].CreateTime.Restore()
	}
	product, err := productDao.SelectOne(serialOrder.ArtId, serialOrder.ProjectId)
	if err != nil {
		return false, "", recordT, grmi.NewBusinessError("查询工单总成信息失败, 错误:" + err.Error())
	}
	if product == nil {
		return false, "", recordT, grmi.NewBusinessError("工单总成数据不存在")
	}
	if product.CtrlStr1 == meModel.PRODUCT_TYPE_MS || product.CtrlStr1 == meModel.PRODUCT_TYPE_PS {
		drLi, err := eolDrDao.Select([]grmi.Predicate{eolMeta.EOLDR_CODE.NewPredicate(grmi.Equal, serialOrder.SerialOrderId),
			eolMeta.EOLDR_TESTDATA.NewPredicate(grmi.GreaterOrEqual, repairTime)}, []grmi.Field{eolMeta.EOLDR_TESTDATA})
		if err != nil {
			return false, "", recordT, grmi.NewBusinessError("查询电检数据失败, 错误：" + err.Error())
		}
		paLi, err := eolPaDao.Select([]grmi.Predicate{eolMeta.EOLPA_CODE.NewPredicate(grmi.Equal, serialOrder.SerialOrderId),
			eolMeta.EOLPA_TESTDATA.NewPredicate(grmi.GreaterOrEqual, repairTime)}, []grmi.Field{eolMeta.EOLPA_TESTDATA})
		if err != nil {
			return false, "", recordT, grmi.NewBusinessError("查询电检数据失败, 错误:" + err.Error())
		}
		var lastDr *eolModel.EOLDR
		var lastPa *eolModel.EOLPA
		if len(drLi) > 0 {
			lastDr = &drLi[len(drLi)-1]
		}
		if len(paLi) > 0 {
			lastPa = &paLi[len(paLi)-1]
		}
		var totalResult string
		var recordTime time.Time
		if lastDr == nil && lastPa == nil {
			return false, "未获取到有效电检数据", recordT, nil
		} else if lastDr != nil && lastPa != nil {
			if lastDr.TESTDATA.Restore().After(lastPa.TESTDATA.Restore()) {
				totalResult = lastDr.TOTALRESULT
				recordTime = lastDr.TESTDATA.Restore()
			} else {
				totalResult = lastPa.TOTALRESULT
				recordTime = lastPa.TESTDATA.Restore()
			}
		} else if lastDr != nil && lastPa == nil {
			totalResult = lastDr.TOTALRESULT
			recordTime = lastDr.TESTDATA.Restore()
		} else if lastDr == nil && lastPa != nil {
			totalResult = lastPa.TOTALRESULT
			recordTime = lastPa.TESTDATA.Restore()
		}
		if totalResult == model.EOL_STATUS_OK {
			return true, "电检合格", recordTime, nil
		} else {
			return false, "电检不合格", recordTime, nil
		}
	} else {
		brLi, err := eolBrDao.Select([]grmi.Predicate{eolMeta.EOLBR_CODE.NewPredicate(grmi.Equal, serialOrder.SerialOrderId),
			eolMeta.EOLBR_TESTDATA.NewPredicate(grmi.GreaterOrEqual, repairTime)}, []grmi.Field{eolMeta.EOLBR_TESTDATA})
		if err != nil {
			return false, "", recordT, grmi.NewBusinessError("查询电检数据失败, 错误:" + err.Error())
		}
		if len(brLi) == 0 {
			return false, "未获取到有效电检数据", recordT, nil
		}
		lastBr := brLi[len(brLi)-1]
		if lastBr.TOTALRESULT == model.EOL_STATUS_OK {
			return true, "电检合格", lastBr.TESTDATA.Restore(), nil
		} else {
			return false, "电检不合格", lastBr.TESTDATA.Restore(), nil
		}
	}
}

// GetSerialOrderOperationTraceData 工单数据追溯
func (impl *SerialOrderServiceImplement) GetSerialOrderOperationTraceData(user *global.User, serialOrderId string) (interface{}, error) {
	var totalResult = &model.TraceData{
		BarCode: serialOrderId,
		Status:  true,
	}
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	result := model.ProductTraceData{
		SerialOrderId: serialOrderId,
		POLi:          make([]model.ProductTracePOData, 0),
	}
	// 1. 查询工单
	// 2. 通过工单查询生产的产线
	// 4. 通过工序查询当前工序生成工步结果
	serialOrderDao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	serialOrderPoDao := dal.NewSerialOrderPOLstDAO(session, user.PlantNr, user.UserId)
	serialOrderStepDao := dal.NewSerialOrderStepLstDAO(session, user.PlantNr, user.UserId)
	recvDataDao := dal.NewSerialOrderOPDetailRecvDataLstDAO(session, user.PlantNr, user.UserId)
	serialOrder, err := serialOrderDao.SelectOne(serialOrderId)
	if err != nil {
		return nil, grmi.NewBusinessError("查询工单失败, error:" + err.Error())
	}
	if serialOrder == nil {
		return nil, grmi.NewBusinessError("工单不存在, 工单ID:" + serialOrderId)
	}

	articleDao := baseDal.NewArticleDAO(session, user.PlantNr, user.UserId)
	article, err := articleDao.SelectOne(serialOrder.ArtId, serialOrder.ProjectId)
	if err != nil {
		return nil, grmi.NewBusinessError("查询工单总成数据失败, error:" + err.Error())
	}
	if article == nil {
		return nil, grmi.NewBusinessError("工单绑定总成不存在, 总成ID:" + serialOrder.ArtId)
	}
	articleAtocdDao := baseDal.NewArticleAtcodLstDAO(session, user.PlantNr, user.UserId)
	var needEOL bool
	attributeLi, err := articleAtocdDao.SelectByArtId(serialOrder.ArtId)
	if err != nil {
		return nil, grmi.NewBusinessError("查询总成关联属性失败, error:" + err.Error())
	}
	for _, attributeItem := range attributeLi {
		if attributeItem.Attribute.Descr == "EOL" {
			needEOL = true
		}
	}
	totalResult.Desc = article.Descr1
	totalResult.IsFirstPiece = serialOrder.IsFirstPieceToggle
	// 所有工单ID
	allOrderIdLi := make([]interface{}, 0)
	if serialOrder.OriginSerialOrderId != "" {
		subSerialOrderLi, err := serialOrderDao.Select([]grmi.Predicate{
			meta.SerialOrder_SerialOrderId.NewPredicate(grmi.NotEqual, serialOrderId),
			meta.SerialOrder_OriginSerialOrderId.NewPredicate(grmi.Equal, serialOrder.OriginSerialOrderId),
		}, nil)
		if err != nil {
			return nil, grmi.NewBusinessError("查询工单数据失败, 错误:" + err.Error())
		}
		allOrderIdLi = append(allOrderIdLi, serialOrderId, serialOrder.OriginSerialOrderId)
		for _, subOrder := range subSerialOrderLi {
			allOrderIdLi = append(allOrderIdLi, subOrder.SerialOrderId)
		}
	} else {
		allOrderIdLi = append(allOrderIdLi, serialOrder.SerialOrderId)
	}

	allPoLi, err := serialOrderPoDao.SelectByOrderLi(allOrderIdLi, serialOrder.UsedResourceId)
	if err != nil {
		return nil, grmi.NewBusinessError("查询工序数据失败, 错误:" + err.Error())
	}
	poMap := make(map[string]int)
	for _, poItem := range allPoLi {
		var status string
		if poItem.Status == baseModel.ORDER_STATUS_CLOSED {
			status = "成功"
		} else {
			status = "失败"
		}
		_, exist := poMap[poItem.Process.PO]
		if !exist {
			poMap[poItem.Process.PO] = len(result.POLi)
			poData := model.ProductTracePOData{
				PO:       poItem.Process.PO,
				PoDesc:   poItem.Process.Descr,
				PoStatus: status,
				StepLi:   make([]model.ProductTraceStepData, 0),
			}
			result.POLi = append(result.POLi, poData)
		} else {
			index := poMap[poItem.Process.PO]
			originPoData := result.POLi[index]
			originPoData.PoStatus = status
			result.POLi[index] = originPoData
		}
	}
	stepLi, err := serialOrderStepDao.Select([]grmi.Predicate{
		meta.SerialOrderStepLst_SerialOrderId.NewPredicate(grmi.Include, allOrderIdLi...),
	}, []grmi.Field{meta.SerialOrderStepLst_StepNo})
	if err != nil {
		return nil, grmi.NewBusinessError("查询工步数据失败, 错误:" + err.Error())
	}
	stepMap := make(map[string]int)
	for _, stepItem := range stepLi {
		mapKey := stepItem.PO + "_" + strconv.Itoa(stepItem.StepNo)
		_, exist := stepMap[mapKey]
		if !exist {
			poIndex := poMap[stepItem.PO]
			stepMap[mapKey] = len(result.POLi[poIndex].StepLi)
			stepData := model.ProductTraceStepData{
				StepNo:     stepItem.StepNo,
				StepDesc:   stepItem.StepDesc,
				RecvDataLi: make([]model.SerialOrderOPDetailRecvDataLst, 0),
			}
			result.POLi[poIndex].StepLi = append(result.POLi[poIndex].StepLi, stepData)
		}
	}

	recvDataLi, err := recvDataDao.Select([]grmi.Predicate{
		meta.SerialOrderOPDetailRecvDataLst_SerialOrderId.NewPredicate(grmi.Include, allOrderIdLi...),
	}, []grmi.Field{
		meta.SerialOrderOPDetailRecvDataLst_SerialOrderId,
		meta.SerialOrderOPDetailRecvDataLst_PO,
		meta.SerialOrderOPDetailRecvDataLst_StepNo,
		meta.SerialOrderOPDetailRecvDataLst_OriginRuleId,
	})
	if err != nil {
		return nil, grmi.NewBusinessError("查询生产数据失败, 错误:" + err.Error())
	}
	for _, recvData := range recvDataLi {
		poIndex, exist := poMap[recvData.PO]
		if !exist {
			continue
		}
		stepKey := recvData.PO + "_" + strconv.Itoa(recvData.StepNo)
		stepIndex, exist := stepMap[stepKey]

		if !exist {
			continue
		}
		result.POLi[poIndex].StepLi[stepIndex].RecvDataLi = append(result.POLi[poIndex].StepLi[stepIndex].RecvDataLi, recvData)
	}
	for _, poData := range result.POLi {
		var poOperationData model.POOperationData
		poOperationData.PO = poData.PO
		poOperationData.Status = poData.PoStatus
		if poData.PoStatus == "失败" {
			totalResult.Status = false
		}
		for _, stepData := range poData.StepLi {
			for _, recvItem := range stepData.RecvDataLi {
				var status string
				if recvItem.Status == 1 {
					status = "成功"
				} else {
					status = "失败"
				}
				recvData := model.RecvDataItem{
					SerialOrderId: recvItem.SerialOrderId,
					ArtId:         recvItem.SubArtId,
					PO:            recvItem.PO,
					OperationDesc: stepData.StepDesc,
					RecvData:      recvItem.RecvData,
					Status:        status,
					Remark1:       recvItem.Remark1,
					ExecuteTime:   recvItem.CreateTime.ToString(),
				}
				poOperationData.RecvDataLi = append(poOperationData.RecvDataLi, recvData)
			}
		}
		totalResult.TraceDataTraceData = append(totalResult.TraceDataTraceData, poOperationData)
	}
	if needEOL {
		var poOperationData model.POOperationData
		poOperationData.PO = "电检"
		// 电检 主驾和副驾需要查询EOLDR 和 EOLPA 两张表 后排 查询EOLBR
		eolStatus, remark, recordTime, err := impl.ExtractEOL(session, user, serialOrder)
		if err != nil {
			return nil, err
		}
		if eolStatus {
			poOperationData.Status = "成功"
		} else {
			poOperationData.Status = "失败"
			totalResult.Status = false
		}
		recvData := model.RecvDataItem{
			SerialOrderId: serialOrderId,
			ArtId:         "",
			PO:            "EOL",
			OperationDesc: "电检",
			Status:        poOperationData.Status,
			RecvData:      "",
			Remark1:       remark,
			ExecuteTime:   recordTime.Format(grmi.DateTimeOutFormat),
		}

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

/******************************************************************************
*
* @Reference LAPP_LF_MOM_BACKEND/services/om/SerialOrderService.GetSerialOrderOPTrace
*
******************************************************************************/
func (impl *SerialOrderServiceImplement) GetSerialOrderOPTrace(user *global.User, status int, workLineId, start, end, serialOrderId string, pageNumber int64, pageSize int64) (interface{}, error) {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	var exist bool
	serialOrderPoDao := dal.NewSerialOrderPOLstDAO(session, user.PlantNr, user.UserId)
	serialOrderDao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	poStatusRecDao := dal.NewSerialOrderPOStatusRecLstDAO(session, user.PlantNr, user.UserId)
	//roleRelDao := baseDal.NewRoleRelDAO(session, user.PlantNr, user.UserId)
	workLineDao := baseDal.NewWorkLineDAO(session, user.PlantNr, user.UserId)
	if workLineId == "" && serialOrderId == "" {
		//relLi, err := roleRelDao.Select([]grmi.Predicate{baseMeta.RoleRel_RoleId.NewPredicate(grmi.Equal, user.RoleId)}, []grmi.Field{baseMeta.RoleRel_WorkLineid})
		//if err != nil {
		//	return nil, grmi.NewBusinessError("查询角色绑定产线失败, error:" + err.Error())
		//}
		//if len(relLi) == 0 {
		//	return nil, grmi.NewBusinessError("角色未关联产线")
		//}
		//workLineId = relLi[0].WorkLineid
		workLineLi, err := workLineDao.Select([]grmi.Predicate{baseMeta.WorkLine_GroupType.NewPredicate(grmi.Equal, baseModel.WORK_LINE_TYPE_REAL)}, nil)
		if err != nil {
			return nil, grmi.NewBusinessError("查询工厂产线数据失败, error:" + err.Error())
		}
		if len(workLineLi) == 0 {
			return nil, grmi.NewBusinessError("未查询到实体产线")
		}
		workLineId = workLineLi[0].WorkLineid
	}
	pageResult, err := serialOrderDao.SelectTraceOrder(workLineId, serialOrderId, start, end, status, pageNumber, pageSize)
	if err != nil {
		return nil, grmi.NewBusinessError("查询工单数据失败, error:" + err.Error())
	}
	serialOrderDataLi := pageResult.Records.([]model.VOmSerialorder)
	// 构建响应数据
	// 标题头 用来存储最后传递给前端的抬头
	titleLi := make([]string, 0)
	// 用于存储po的map
	titleMap := make(map[string]interface{})
	// 每个工单工序格子显示的数据
	type POData struct {
		PO        string `json:"po"`
		StartTime string `json:"startTime"`
		Status    int    `json:"status"`
	}
	// 每行工单聚合的工序数据
	type SerialOrderPOLiData struct {
		SerialOrderId string   `json:"serialOrderId"`
		POLi          []POData `json:"poLi"`
	}
	// 返回给前端的结果
	type Result struct {
		TitleLi    []string              `json:"titleLi"` // 展示的标题头
		Data       []SerialOrderPOLiData `json:"data"`    // 展示的工单数据列表
		Count      int64                 `json:"count"`   // 工单总数量
		PageNumber int64                 `json:"pageNumber"`
		PageSize   int64                 `json:"pageSize"`
	}
	// 临时的工单工序数据 因为标题工序的排序不确定 先做成map
	type TempSerialOrderPOItem struct {
		SerialOrderId string
		ItemMap       map[string]POData
	}
	tempLi := make([]TempSerialOrderPOItem, 0, len(serialOrderDataLi))
	//	 遍历需要展示工单列表
	for _, serialOrderData := range serialOrderDataLi {
		var tempItem TempSerialOrderPOItem
		tempItem.SerialOrderId = serialOrderData.SerialOrder.SerialOrderId
		tempItem.ItemMap = make(map[string]POData)
		var traceOrderId string
		if serialOrderData.SerialOrder.OriginSerialOrderId != "" {
			traceOrderId = serialOrderData.SerialOrder.OriginSerialOrderId
		} else {
			traceOrderId = serialOrderData.SerialOrder.SerialOrderId
		}
		// 查询工单的所有工序状态结果
		SerialOrderPOLi, err := serialOrderPoDao.SelectBySerialOrderId(traceOrderId, serialOrderData.SerialOrder.UsedResourceId)
		if err != nil {
			return nil, grmi.NewBusinessError("查询工单工序数据失败, error:" + err.Error())
		}
		// 查询工单的所有工序状态变更记录 由于计算每个工序的开始时间
		poStatusRecLi, err := poStatusRecDao.Select([]grmi.Predicate{meta.SerialOrderPOStatusRecLst_SerialOrderId.NewPredicate(grmi.Equal, traceOrderId), meta.SerialOrderPOStatusRecLst_Status.NewPredicate(grmi.Equal, baseModel.ORDER_STATUS_RUNNING)}, []grmi.Field{meta.SerialOrderPOStatusRecLst_Pos})
		if err != nil {
			return nil, grmi.NewBusinessError("查询工序开始时间失败, error:" + err.Error())
		}
		poStatusRecMap := make(map[string][]time.Time)
		for _, statusRec := range poStatusRecLi {
			_, exist := poStatusRecMap[statusRec.PO]
			if !exist {
				poStatusRecMap[statusRec.PO] = make([]time.Time, 0)
			}
			poStatusRecMap[statusRec.PO] = append(poStatusRecMap[statusRec.PO], statusRec.CreateTime.Restore())
		}
		for _, serialOrderPO := range SerialOrderPOLi {
			_, exist = titleMap[serialOrderPO.PO]
			if !exist {
				titleMap[serialOrderPO.PO] = nil
				titleLi = append(titleLi, serialOrderPO.PO)
			}
			var poData POData
			poData.PO = serialOrderPO.PO
			poData.Status = serialOrderPO.Status
			_, exist = poStatusRecMap[serialOrderPO.PO]
			if exist {
				poData.StartTime = poStatusRecMap[serialOrderPO.PO][0].Format(grmi.DateTimeOutFormat)
			}
			tempItem.ItemMap[serialOrderPO.PO] = poData
		}
		tempLi = append(tempLi, tempItem)
	}

	var result Result
	result.TitleLi = titleLi
	result.Data = make([]SerialOrderPOLiData, 0)
	result.Count = pageResult.Count
	result.PageNumber = pageResult.PageNumber
	result.PageSize = pageResult.PageSize
	titleNum := len(titleLi)
	// 此时标题头部已经排好顺序 开始聚合数据
	for _, tempItem := range tempLi {
		var serialOrderPOData SerialOrderPOLiData
		serialOrderPOData.SerialOrderId = tempItem.SerialOrderId
		serialOrderPOData.POLi = make([]POData, 0, titleNum)
		for _, title := range titleLi {
			_, exist = tempItem.ItemMap[title]
			if exist {
				serialOrderPOData.POLi = append(serialOrderPOData.POLi, tempItem.ItemMap[title])
			} else {
				serialOrderPOData.POLi = append(serialOrderPOData.POLi, POData{PO: title})
			}
		}
		result.Data = append(result.Data, serialOrderPOData)
	}
	return result, nil
}

/******************************************************************************
*
* @Reference LAPP_LF_MOM_BACKEND/services/om/SerialOrderService.GetSerialOrderDetailTrace
*
******************************************************************************/
func (impl *SerialOrderServiceImplement) GetSerialOrderDetailTrace(user *global.User, serialOrderId string) (interface{}, error) {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	result := make([]model.SerialOrderOPTrace, 0)
	opDao := dal.NewSerialOrderOPDetailRecvDataLstDAO(session, user.PlantNr, user.UserId)
	workPlaceDao := baseDal.NewWorkPlaceDAO(session, user.PlantNr, user.UserId)
	serialOrderDao := dal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	serialOrder, err := serialOrderDao.SelectOne(serialOrderId)
	if err != nil {
		return nil, grmi.NewBusinessError("查询工单失败, error:" + err.Error())
	}
	if serialOrder == nil {
		return nil, grmi.NewBusinessError("工单不存在, 工单ID:" + serialOrderId)
	}
	var traceOrderId string
	if serialOrder.OriginSerialOrderId != "" {
		traceOrderId = serialOrder.OriginSerialOrderId
	} else {
		traceOrderId = serialOrderId
	}
	opLi, err := opDao.SelectOPDetailData(traceOrderId, serialOrder.UsedResourceId)
	if err != nil {
		return nil, grmi.NewBusinessError("查询工艺操作数据失败, error:" + err.Error())
	}
	workPlaceNrMap := make(map[int]interface{})
	workPlaceNrLi := make([]interface{}, 0)
	for _, op := range opLi {
		_, exist := workPlaceNrMap[op.SerialOrderOPDetailRecvDataLst.WorkPlaceNr]
		if !exist {
			workPlaceNrMap[op.SerialOrderOPDetailRecvDataLst.WorkPlaceNr] = nil
			workPlaceNrLi = append(workPlaceNrLi, op.SerialOrderOPDetailRecvDataLst.WorkPlaceNr)
		}
	}
	workPlaceLi, err := workPlaceDao.Select([]grmi.Predicate{baseMeta.WorkPlace_WorkPlaceNr.NewPredicate(grmi.Include, workPlaceNrLi...)}, nil)
	if err != nil {
		return nil, grmi.NewBusinessError("查询工位数据失败, error:" + err.Error())
	}
	workPlaceMap := make(map[int]string)
	for _, workPlace := range workPlaceLi {
		workPlaceMap[workPlace.WorkPlaceNr] = workPlace.WorkPlaceId
	}
	for _, op := range opLi {
		if op.SerialOrderOPDetailRecvDataLst.StepType == baseModel.STEP_GUIDE_RULE {
			continue
		}
		if op.SerialOrderOPDetailRecvDataLst.StepType == baseModel.STEP_OPC_RULE && (op.OPCComRule.ActionType == baseModel.ACTION_TYPE_VERIFY || op.OPCComRule.ActionType == baseModel.ACTION_TYPE_WRITE) {
			continue
		}
		var stepDesc string
		if op.SerialOrderOPDetail.StepType == baseModel.STEP_OPC_RULE {
			stepDesc = op.OPCComRule.DBlockDesc
		} else {
			stepDesc = op.Operation.StepDesc
		}
		var status string
		if op.SerialOrderOPDetailRecvDataLst.Status == 1 {
			status = "是"
		} else {
			status = "否"
		}
		workPlaceId := workPlaceMap[op.SerialOrderOPDetailRecvDataLst.WorkPlaceNr]

		trace := model.SerialOrderOPTrace{
			ArtId:         op.SerialOrderOPDetail.SubArtId,
			SerialOrderId: op.SerialOrderOPDetailRecvDataLst.SerialOrderId,
			PO:            op.SerialOrderOPDetailRecvDataLst.PO,
			WorkPlaceId:   workPlaceId,
			StepDesc:      stepDesc,
			RecvData:      op.SerialOrderOPDetailRecvDataLst.RecvData,
			Status:        status,
			ExecuteTime:   op.SerialOrderOPDetailRecvDataLst.CreateTime.ToString(),
		}
		if status != "是" {
			trace.Remark1 = op.SerialOrderOPDetailRecvDataLst.Remark1
		}
		result = append(result, trace)
	}
	return result, nil
}
