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

package implments

import (
	baseDal "LAPP_ACURA_MOM_BACKEND/dao/base"
	dalJit "LAPP_ACURA_MOM_BACKEND/dao/jit"
	dalMe "LAPP_ACURA_MOM_BACKEND/dao/me"
	dal "LAPP_ACURA_MOM_BACKEND/dao/pln"
	"LAPP_ACURA_MOM_BACKEND/db"
	"LAPP_ACURA_MOM_BACKEND/global"
	"LAPP_ACURA_MOM_BACKEND/grmi"
	"LAPP_ACURA_MOM_BACKEND/infra/logger"
	metaJit "LAPP_ACURA_MOM_BACKEND/meta/jit"
	meta "LAPP_ACURA_MOM_BACKEND/meta/pln"
	baseModel "LAPP_ACURA_MOM_BACKEND/models/base"
	modelJit "LAPP_ACURA_MOM_BACKEND/models/jit"
	modelMe "LAPP_ACURA_MOM_BACKEND/models/me"
	model "LAPP_ACURA_MOM_BACKEND/models/pln"
	"LAPP_ACURA_MOM_BACKEND/utils"
	"bufio"
	"github.com/go-xorm/xorm"
	"golang.org/x/text/encoding/simplifiedchinese"
	"golang.org/x/text/transform"
	"io"
	"os"
	"regexp"
	"strconv"
	"strings"
	"time"
)

/******************************************************************************
 *
 * @Description              : HondaCalloff的默认查询条件
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-11-09 13:35:31
 *
 ******************************************************************************/
var DefaultConditionOfHondaCalloff = grmi.NewCondition(
	map[string]grmi.ConditionItem{
		meta.HondaCalloff_CalloffId.UrlParameterName:       grmi.NewConditionItem(meta.HondaCalloff_CalloffId, grmi.Equal, true),
		meta.HondaCalloff_CardNo.UrlParameterName:          grmi.NewConditionItem(meta.HondaCalloff_CardNo, grmi.Equal, false),
		meta.HondaCalloff_SerialNo.UrlParameterName:        grmi.NewConditionItem(meta.HondaCalloff_SerialNo, grmi.Equal, false),
		meta.HondaCalloff_LineNo.UrlParameterName:          grmi.NewConditionItem(meta.HondaCalloff_LineNo, grmi.Equal, false),
		meta.HondaCalloff_Parsed.UrlParameterName:          grmi.NewConditionItem(meta.HondaCalloff_Parsed, grmi.Equal, false),
		meta.HondaCalloff_CalloffDateTime.UrlParameterName: grmi.NewConditionItem(meta.HondaCalloff_CalloffDateTime, grmi.Approximate, false),
		meta.HondaCalloff_PlanQty.UrlParameterName:         grmi.NewConditionItem(meta.HondaCalloff_PlanQty, grmi.Equal, false),
		meta.HondaCalloff_EdiFile.UrlParameterName:         grmi.NewConditionItem(meta.HondaCalloff_EdiFile, grmi.Equal, false),
		meta.HondaCalloff_EdiFileType.UrlParameterName:     grmi.NewConditionItem(meta.HondaCalloff_EdiFileType, grmi.Equal, false),
		meta.HondaCalloff_CtrlPara1.UrlParameterName:       grmi.NewConditionItem(meta.HondaCalloff_CtrlPara1, grmi.Equal, false),
		meta.HondaCalloff_CtrlPara2.UrlParameterName:       grmi.NewConditionItem(meta.HondaCalloff_CtrlPara2, grmi.Equal, false),
		meta.HondaCalloff_CtrlStr1.UrlParameterName:        grmi.NewConditionItem(meta.HondaCalloff_CtrlStr1, grmi.Equal, false),
		meta.HondaCalloff_CtrlStr2.UrlParameterName:        grmi.NewConditionItem(meta.HondaCalloff_CtrlStr2, grmi.Equal, false),
		meta.HondaCalloff_CtrlTime1.UrlParameterName:       grmi.NewConditionItem(meta.HondaCalloff_CtrlTime1, grmi.Approximate, false),
		meta.HondaCalloff_CtrlTime2.UrlParameterName:       grmi.NewConditionItem(meta.HondaCalloff_CtrlTime2, grmi.Approximate, false),
		meta.HondaCalloff_LastModify.UrlParameterName:      grmi.NewConditionItem(meta.HondaCalloff_LastModify, grmi.Approximate, false),
		meta.HondaCalloff_LastUser.UrlParameterName:        grmi.NewConditionItem(meta.HondaCalloff_LastUser, grmi.Equal, false),
		meta.HondaCalloff_CreateTime.UrlParameterName:      grmi.NewConditionItem(meta.HondaCalloff_CreateTime, grmi.Approximate, false),
	},
	nil,
)

/******************************************************************************
 *
 * @Description              : HondaCalloff的默认分页查询条件
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-11-09 13:35:31
 *
 ******************************************************************************/
var DefaultConditionOfHondaCalloffAndPaging = grmi.NewCondition(
	DefaultConditionOfHondaCalloff.Items,
	grmi.NewPaging(),
)

/******************************************************************************
 *
 * @Struct Name              : HondaCalloffServiceImplement
 *-----------------------------------------------------------------------------
 *
 * @Description              : HondaCalloff的服务实现
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-11-09 13:35:31
 *
 ******************************************************************************/
type HondaCalloffServiceImplement struct {
}

/******************************************************************************
 *
 * @Function Name            : NewHondaCalloffDAOImplement
 *-----------------------------------------------------------------------------
 *
 * @Description              : 创建一个HondaCalloffDAOImplement实例
 *
 * @Return Value             : HondaCalloffDAOImplement实例
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-11-09 13:35:31
 *
 ******************************************************************************/
func NewHondaCalloffServiceImplement() *HondaCalloffServiceImplement {
	return &HondaCalloffServiceImplement{}
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/pln/HondaCalloffServiceImplement.InsertOne
 *
 ******************************************************************************/
func (impl *HondaCalloffServiceImplement) InsertOne(user *global.User, entity *model.HondaCalloff) error {
	grmi.Log(user, "/services/pln/implments/HondaCalloff.service.impl.go", "InsertOneHondaCalloff", "插入一个HondaCalloff")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	// 判断文件是否存在
	_, err := os.Stat("web/public/Honda/CallOff/" + entity.EdiFile)
	if err != nil {
		return grmi.NewBusinessError("检测文件失败, error:" + err.Error())
	}
	// 从文件中提取头部数据和详情数据
	itemLi, err := impl.LoadFile(entity)
	if err != nil {
		return grmi.NewBusinessError("加载文件失败, error:" + err.Error())
	}
	if len(*itemLi) == 0 {
		return grmi.NewBusinessError("未提取到要货详情数据")
	}
	snrDao := baseDal.NewSnrDAO(session, user.PlantNr, user.UserId)
	dao := dal.NewHondaCalloffDAO(session, user.PlantNr, user.UserId)
	detailDao := dal.NewHondaCalloffItemLstDAO(session, user.PlantNr, user.UserId)
	// 检查文件是否已经上传过
	existLi, err := dao.Select([]grmi.Predicate{meta.HondaCalloff_EdiFile.NewPredicate(grmi.Equal, entity.EdiFile)}, nil)
	if err != nil {
		return grmi.NewBusinessError("查询文件是否已经存在失败, error:" + err.Error())
	}
	if len(existLi) != 0 {
		return grmi.NewBusinessError("该文件名已经存在")
	}

	// 开启事务
	if err := session.Begin(); err != nil {
		return err
	}
	// 生成流水号
	entity.CalloffId, err = snrDao.GetNextSnr("HondaCallOffId")
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("生成CallOff记录流水号失败, error:" + err.Error())
	}
	entity.Parsed = model.CALL_OFF_LOADED
	// 数据入库
	err = dao.InsertOne(entity)
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("保存CallOff概要数据失败")
	}
	tempItemLi := make([]model.HondaCalloffItemLst, 0, 20)
	for index, item := range *itemLi {
		if index != 0 && len(tempItemLi)%20 == 0 {
			err = detailDao.Insert(&tempItemLi)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("保存CallOff子项数据失败, error:" + err.Error())
			}
			tempItemLi = make([]model.HondaCalloffItemLst, 0, 20)
		}
		item.CalloffId = entity.CalloffId
		tempItemLi = append(tempItemLi, item)
	}
	if len(tempItemLi) != 0 {
		err = detailDao.Insert(&tempItemLi)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("保存CallOff子项数据失败, error:" + err.Error())
		}
	}
	_ = session.Commit()
	return nil
}

// LoadFile 从CallOf文件中提取数据
func (impl *HondaCalloffServiceImplement) LoadFile(entity *model.HondaCalloff) (*[]model.HondaCalloffItemLst, error) {
	result := make([]model.HondaCalloffItemLst, 0)
	file, err := os.Open("web/public/Honda/CallOff/" + entity.EdiFile)
	if err != nil {
		return nil, grmi.NewBusinessError("打开文件失败, error:" + err.Error())
	}
	defer file.Close()
	lineNoReg := regexp.MustCompile(`Line No:(.*)`)
	if lineNoReg == nil {
		return nil, grmi.NewBusinessError("生成lineNo正则失败")
	}
	cardNoReg := regexp.MustCompile(`CardNo:(.*)`)
	if cardNoReg == nil {
		return nil, grmi.NewBusinessError("生成carNo正则失败")
	}
	serialNoReg := regexp.MustCompile(`Serial No:(.*)`)
	if serialNoReg == nil {
		return nil, grmi.NewBusinessError("生成serialNo正则失败")
	}
	planEndTimeReg := regexp.MustCompile(`Plan Datetime:(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})`)
	if planEndTimeReg == nil {
		return nil, grmi.NewBusinessError("生成planEndTime正则失败")
	}
	lineReg := regexp.MustCompile(`\d+,(?P<date>\d{4}-\d{2}-\d{2}),(?P<time>\d{2}:\d{2}:\d{2}),\d+,(?P<model>.*?),(?P<config>.*?) (?P<VinNo>.*?)\s+(?P<color>.*?),.*`)
	if lineReg == nil {
		return nil, grmi.NewBusinessError("生成发运行数据正则失败")
	}
	r := transform.NewReader(file, simplifiedchinese.GBK.NewDecoder())
	reader := bufio.NewReader(r)
	currentRow := 0
	itemPos := 1
	for {

		line, err := reader.ReadString('\n')
		if err == io.EOF {
			break
		}
		if err != nil {
			return nil, grmi.NewBusinessError("读取行数据失败, error:" + err.Error())
		}
		line = strings.Trim(line, "\n")
		line = strings.Trim(line, "\r")
		currentRow += 1
		if currentRow == 1 {
			continue
		}
		if currentRow == 2 {
			matchLi := lineNoReg.FindStringSubmatch(line)
			if len(matchLi) < 2 {
				return nil, grmi.NewBusinessError("未匹配到LineNo")
			}
			entity.LineNo = matchLi[1]
			continue
		} else if currentRow == 3 {
			matchLi := cardNoReg.FindStringSubmatch(line)
			if len(matchLi) < 2 {
				return nil, grmi.NewBusinessError("未匹配到CardNo")
			}
			entity.CardNo = matchLi[1]
			continue
		} else if currentRow == 4 {
			matchLi := serialNoReg.FindStringSubmatch(line)
			if len(matchLi) < 2 {
				return nil, grmi.NewBusinessError("未匹配到SerialNo")
			}
			entity.SerialNo = matchLi[1]
			continue
		} else if currentRow == 5 {
			matchLi := planEndTimeReg.FindStringSubmatch(line)
			if len(matchLi) < 2 {
				return nil, grmi.NewBusinessError("未匹配到Plan Datetime")
			}
			callOffEndTime, err := time.ParseInLocation(grmi.DateTimeOutFormat, matchLi[1], utils.TimezoneLocation)
			if err != nil {
				return nil, grmi.NewBusinessError("解析Plan Datetime失败, error:" + err.Error())
			}
			entity.CalloffDateTime = grmi.DateTime(callOffEndTime)
			continue
		} else if currentRow == 6 {
			continue
		} else {
			matchLi := lineReg.FindStringSubmatch(line)
			if len(matchLi) != 7 {
				return nil, grmi.NewBusinessError("行数据缺失数据, 行号:" + strconv.Itoa(currentRow))
			}
			if len(matchLi[4]) < 7 {
				return nil, grmi.NewBusinessError("行数据中的车型配置值长度小于4位, 行号:" + strconv.Itoa(currentRow))
			}

			planEndDateStr := matchLi[1]
			planEndTimeStr := planEndDateStr + " " + matchLi[2]
			planEndDate, err := time.ParseInLocation(grmi.DateOutFormat, planEndDateStr, utils.TimezoneLocation)
			if err != nil {
				return nil, grmi.NewBusinessError("行数据中的需求日期解析失败, error:" + err.Error() + ", 行号:" + strconv.Itoa(currentRow))
			}
			planEndTime, err := time.ParseInLocation(grmi.DateTimeOutFormat, planEndTimeStr, utils.TimezoneLocation)
			if err != nil {
				return nil, grmi.NewBusinessError("行数据中的需求时间解析失败, error:" + err.Error() + ", 行号:" + strconv.Itoa(currentRow))
			}
			modelValue := matchLi[4][4:7]
			configValue := matchLi[4][1:4]
			vinNo := matchLi[5]
			color := matchLi[6]
			productFamilyId := configValue + " " + modelValue + " " + "(" + color + ")"
			callOffDetail := model.HondaCalloffItemLst{
				CalloffId:       entity.CalloffId,
				Pos:             itemPos,
				CalloffDate:     grmi.Date(planEndDate),
				CalloffTime:     grmi.Time(planEndTime),
				PlanQty:         1,
				ConfigValue:     configValue,
				ModelValue:      modelValue,
				ColorValue:      color,
				ProductFamilyId: productFamilyId,
				VinNo:           vinNo,
			}
			itemPos++
			result = append(result, callOffDetail)
		}
	}
	return &result, nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/pln/HondaCalloffService.DeleteOne
 *
 ******************************************************************************/
func (impl *HondaCalloffServiceImplement) DeleteOne(user *global.User, calloffId string) error {

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

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

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/pln/HondaCalloffService.SelectOne
 *
 ******************************************************************************/
func (impl *HondaCalloffServiceImplement) SelectOne(user *global.User, calloffId string) (*model.HondaCalloff, error) {

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

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

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/pln/HondaCalloffService.UpdateOne
 *
 ******************************************************************************/
func (impl *HondaCalloffServiceImplement) UpdateOne(user *global.User, entity *model.HondaCalloff) error {

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

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewHondaCalloffDAO(session, user.PlantNr, user.UserId)
	record, err := dao.SelectOne(entity.CalloffId)
	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/pln/HondaCalloffService.Insert
 *
 ******************************************************************************/
func (impl *HondaCalloffServiceImplement) Insert(user *global.User, entities *[]model.HondaCalloff) error {

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

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

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

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

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/pln/HondaCalloffService.Delete
 *
 ******************************************************************************/
func (impl *HondaCalloffServiceImplement) Delete(user *global.User, entities *[]model.HondaCalloff) error {

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

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

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

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

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/pln/HondaCalloffService.Select
 *
 ******************************************************************************/
func (impl *HondaCalloffServiceImplement) Select(user *global.User, urlParameters map[string]string) ([]model.HondaCalloff, error) {

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

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

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

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

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

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/pln/HondaCalloffService.Update
 *
 ******************************************************************************/
func (impl *HondaCalloffServiceImplement) Update(user *global.User, entities *[]model.HondaCalloff) error {

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

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

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

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

// AnalysisData 解析CallOff已经加载到数据库中的数据
func (impl *HondaCalloffServiceImplement) AnalysisData(entity *model.HondaCalloff, plantNr int, userId string) (err error) {
	// 派生不存在这种数据项的错误不影响解析 状态给部分解析 且可以在前端页面点击再次解析
	callOffId := entity.CalloffId
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	errDao := dal.NewHondaCalloffErrorLstDAO(session, plantNr, userId)
	dao := dal.NewHondaCalloffDAO(session, plantNr, userId)
	detailDao := dal.NewHondaCalloffItemLstDAO(session, plantNr, userId)
	productFamilyDao := dalMe.NewProductFamilyDAO(session, plantNr, userId)
	projectDao := dalMe.NewProjectDAO(session, plantNr, userId)
	packTemplateDao := dalJit.NewPackTemplateDAO(session, plantNr, userId)
	if err = session.Begin(); err != nil {
		return err
	}
	//删除错误信息
	err = errDao.DeleteWhere([]grmi.Predicate{meta.HondaCalloffErrorLst_CalloffId.NewPredicate(grmi.Equal, callOffId)})
	if err != nil {
		errData := model.HondaCalloffErrorLst{
			CalloffId:   callOffId,
			Pos:         0,
			ErrorType:   model.ERROR_TYPE_SYSTEM,
			ErrorInfo:   "系统解析异常,删除历史错误数据失败:" + err.Error() + ";",
			ErrorStatus: model.ERROR_STATUS_ON,
		}
		err = errDao.InsertOne(&errData)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("插入解析错误项失败, error:" + err.Error())
		}
		entity.Parsed = model.CALL_OFF_PARSE_FAILED
		err = dao.UpdateOne(entity)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新callOf状态数据失败, error:" + err.Error())
		}
		_ = session.Commit()
		return err
	}

	// 查询callOf子项数据
	detailLi, err := detailDao.Select([]grmi.Predicate{meta.HondaCalloffItemLst_CalloffId.NewPredicate(grmi.Equal, entity.CalloffId)}, []grmi.Field{meta.HondaCalloffItemLst_Pos})
	if err != nil {
		errData := model.HondaCalloffErrorLst{
			CalloffId:   callOffId,
			Pos:         0,
			ErrorType:   model.ERROR_TYPE_SYSTEM,
			ErrorInfo:   "系统解析异常，查询解析详情数据失败:" + err.Error() + ";",
			ErrorStatus: model.ERROR_STATUS_ON,
		}
		err = errDao.InsertOne(&errData)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("插入解析错误项失败, error:" + err.Error())
		}
		entity.Parsed = model.CALL_OFF_PARSE_FAILED
		err = dao.UpdateOne(entity)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新callOf状态数据失败, error:" + err.Error())
		}
		_ = session.Commit()
		return err
	}
	// 出现派生不存在时的 需要把派生存在的数据项写入发运单
	saveDetailLi := make([]model.HondaCalloffItemLst, 0)
	var projectId string
	errorLi := make([]model.HondaCalloffErrorLst, 0)
	productFamilyMap := make(map[string]*modelMe.ProductFamily)
	for _, detail := range detailLi {
		_, exist := productFamilyMap[detail.ProductFamilyId]
		if !exist {
			productFamily, err := productFamilyDao.SelectOne(detail.ProductFamilyId)
			if err != nil {
				errData := model.HondaCalloffErrorLst{
					CalloffId:   callOffId,
					Pos:         0,
					ErrorType:   model.ERROR_TYPE_SYSTEM,
					ErrorInfo:   "系统解析异常，查询车型配置数据失败:" + err.Error() + ";",
					ErrorStatus: model.ERROR_STATUS_ON,
				}
				err = errDao.InsertOne(&errData)
				if err != nil {
					_ = session.Rollback()
					return grmi.NewBusinessError("插入解析错误项失败, error:" + err.Error())
				}
				entity.Parsed = model.CALL_OFF_PARSE_FAILED
				err = dao.UpdateOne(entity)
				if err != nil {
					_ = session.Rollback()
					return grmi.NewBusinessError("更新callOf状态数据失败, error:" + err.Error())
				}
				_ = session.Commit()
				return err
			}
			if productFamily == nil {
				errData := model.HondaCalloffErrorLst{
					CalloffId:   callOffId,
					Pos:         detail.Pos,
					ErrorType:   model.ERROR_TYPE_DATA,
					ErrorInfo:   "车型配置不存在, 车型配置ID:" + detail.ProductFamilyId + ";",
					ErrorStatus: model.ERROR_STATUS_ON,
				}
				errorLi = append(errorLi, errData)
			} else {
				if projectId == "" {
					projectId = productFamily.ProjectId
				}
				productFamilyMap[detail.ProductFamilyId] = productFamily
				saveDetailLi = append(saveDetailLi, detail)
			}
		} else {
			saveDetailLi = append(saveDetailLi, detail)
		}
	}
	// 如果没有数据层面的错误 创建发运单 并进行数据落库
	if len(errorLi) == 0 {
		// 获取一个新的session 用于保存发运单数据
		txSession := engine.NewSession()
		defer txSession.Close()
		// 开启事务
		if err := txSession.Begin(); err != nil {
			errData := model.HondaCalloffErrorLst{
				CalloffId:   callOffId,
				Pos:         0,
				ErrorType:   model.ERROR_TYPE_SYSTEM,
				ErrorInfo:   "系统解析异常,开启事务失败，错误:" + err.Error() + ";",
				ErrorStatus: model.ERROR_STATUS_ON,
			}
			err = errDao.InsertOne(&errData)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("插入解析错误项失败, error:" + err.Error())
			}
			entity.Parsed = model.CALL_OFF_PARSE_FAILED
			err = dao.UpdateOne(entity)
			if err != nil {
				_ = session.Rollback()
				return grmi.NewBusinessError("更新callOf状态数据失败, error:" + err.Error())
			}
			_ = session.Commit()
			return err
		}
		//snrDao := baseDal.NewSnrDAO(txSession, plantNr, userId)
		shipOrderDao := dalJit.NewShipOrderDAO(txSession, plantNr, userId)
		shipOrderStatusDao := dalJit.NewShipOrderStatusDAO(txSession, plantNr, userId)
		shipOrderItemDao := dalJit.NewShipOrderItemLstDAO(txSession, plantNr, userId)
		packTemplateMap := make(map[string]*modelJit.PackTemplate)
		shipOrderItemLi := make([]modelJit.ShipOrderItemLst, 0)
		project, err := projectDao.SelectOne(projectId)
		if err != nil {
			errData := model.HondaCalloffErrorLst{
				CalloffId:   callOffId,
				Pos:         0,
				ErrorType:   model.ERROR_TYPE_SYSTEM,
				ErrorInfo:   "系统解析异常，查询车型配置数据失败:" + err.Error() + ";",
				ErrorStatus: model.ERROR_STATUS_ON,
			}
			_ = txSession.Rollback()
			innerErr := errDao.InsertOne(&errData)
			if innerErr != nil {
				_ = session.Rollback()
				return err
			}
			entity.Parsed = model.CALL_OFF_PARSE_FAILED
			innerErr = dao.UpdateOne(entity)
			if innerErr != nil {
				_ = session.Rollback()
				return err
			}
			_ = session.Commit()
			return err
		}
		if project == nil {
			errData := model.HondaCalloffErrorLst{
				CalloffId:   callOffId,
				Pos:         0,
				ErrorType:   model.ERROR_TYPE_SYSTEM,
				ErrorInfo:   "系统解析异常，查询车型项目数据不存在, 车型项目ID:" + projectId + ";",
				ErrorStatus: model.ERROR_STATUS_ON,
			}
			err = grmi.NewBusinessError("系统解析异常，查询车型项目数据不存在, 车型项目ID:" + projectId + ";")
			_ = txSession.Rollback()
			innerErr := errDao.InsertOne(&errData)
			if innerErr != nil {
				_ = session.Rollback()
				return err
			}
			entity.Parsed = model.CALL_OFF_PARSE_FAILED
			innerErr = dao.UpdateOne(entity)
			if innerErr != nil {
				_ = session.Rollback()
				return err
			}
			_ = session.Commit()
			return err
		}
		//shipOrderId, err := snrDao.GetNextSnr(project.ShipOrderSnr)
		//if err != nil {
		//	errData := model.HondaCalloffErrorLst{
		//		CalloffId:   callOffId,
		//		Pos:         0,
		//		ErrorType:   model.ERROR_TYPE_SYSTEM,
		//		ErrorInfo:   "系统解析异常，生成发运单ID失败:" + err.Error() + ";",
		//		ErrorStatus: model.ERROR_STATUS_ON,
		//	}
		//	_ = txSession.Rollback()
		//	innerErr := errDao.InsertOne(&errData)
		//	if innerErr != nil {
		//		_ = session.Rollback()
		//		return err
		//	}
		//	entity.Parsed = model.CALL_OFF_PARSE_FAILED
		//	innerErr = dao.UpdateOne(entity)
		//	if innerErr != nil {
		//		_ = session.Rollback()
		//		return err
		//	}
		//	_ = session.Commit()
		//	return err
		//}
		shipOrderId := entity.CardNo
		shipOrder := modelJit.ShipOrder{
			ShipOrderId: shipOrderId,
			ProjectId:   projectId,
			ShipType:    modelJit.SHIP_TYPE_FORMAL,
			PlanQty:     len(detailLi),
			OpenTime:    grmi.DateTime(time.Now()),
			Operator:    userId,
			CtrlStr1:    callOffId,
		}
		err = shipOrderDao.InsertOne(&shipOrder)
		if err != nil {
			errData := model.HondaCalloffErrorLst{
				CalloffId:   callOffId,
				Pos:         0,
				ErrorType:   model.ERROR_TYPE_SYSTEM,
				ErrorInfo:   "系统解析异常，保存发运单失败:" + err.Error() + ";",
				ErrorStatus: model.ERROR_STATUS_ON,
			}
			_ = txSession.Rollback()
			innerErr := errDao.InsertOne(&errData)
			if innerErr != nil {
				_ = session.Rollback()
				return err
			}
			entity.Parsed = model.CALL_OFF_PARSE_FAILED
			innerErr = dao.UpdateOne(entity)
			if innerErr != nil {
				_ = session.Rollback()
				return err
			}
			_ = session.Commit()
			return err
		}
		shipOrderStatus := modelJit.ShipOrderStatus{
			ShipOrderId: shipOrderId,
			Status:      modelJit.SHIP_STATUS_PLANNED,
			Status1:     modelJit.SHIP_STATUS_PLANNED,
			Status2:     modelJit.SHIP_STATUS_PLANNED,
		}
		err = shipOrderStatusDao.InsertOne(&shipOrderStatus)
		if err != nil {
			errData := model.HondaCalloffErrorLst{
				CalloffId:   callOffId,
				Pos:         0,
				ErrorType:   model.ERROR_TYPE_SYSTEM,
				ErrorInfo:   "系统解析异常，保存发运单状态失败:" + err.Error() + ";",
				ErrorStatus: model.ERROR_STATUS_ON,
			}
			_ = txSession.Rollback()
			innerErr := errDao.InsertOne(&errData)
			if innerErr != nil {
				_ = session.Rollback()
				return err
			}
			entity.Parsed = model.CALL_OFF_PARSE_FAILED
			innerErr = dao.UpdateOne(entity)
			if innerErr != nil {
				_ = session.Rollback()
				return err
			}
			_ = session.Commit()
			return err
		}
		for _, detail := range detailLi {
			packTemplate, exist := packTemplateMap[detail.ProductFamilyId]
			if !exist {
				packTemplate, err = packTemplateDao.SelectOne(detail.ProductFamilyId)
				if err != nil {
					errData := model.HondaCalloffErrorLst{
						CalloffId:   callOffId,
						Pos:         0,
						ErrorType:   model.ERROR_TYPE_SYSTEM,
						ErrorInfo:   "系统解析异常，查询包装模板失败:" + err.Error() + ";",
						ErrorStatus: model.ERROR_STATUS_ON,
					}
					_ = txSession.Rollback()
					innerErr := errDao.InsertOne(&errData)
					if innerErr != nil {
						_ = session.Rollback()
						return err
					}
					entity.Parsed = model.CALL_OFF_PARSE_FAILED
					innerErr = dao.UpdateOne(entity)
					if innerErr != nil {
						_ = session.Rollback()
						return err
					}
					_ = session.Commit()
					return err
				}
				if packTemplate == nil {
					errData := model.HondaCalloffErrorLst{
						CalloffId:   callOffId,
						Pos:         0,
						ErrorType:   model.ERROR_TYPE_SYSTEM,
						ErrorInfo:   "系统解析异常，该车型配置还没有生成包装模板, 车型配置ID:" + detail.ProductFamilyId + ";",
						ErrorStatus: model.ERROR_STATUS_ON,
					}
					_ = txSession.Rollback()
					innerErr := errDao.InsertOne(&errData)
					if innerErr != nil {
						_ = session.Rollback()
						return err
					}
					entity.Parsed = model.CALL_OFF_PARSE_FAILED
					innerErr = dao.UpdateOne(entity)
					if innerErr != nil {
						_ = session.Rollback()
						return err
					}
					_ = session.Commit()
					return err
				}
				packTemplateMap[detail.ProductFamilyId] = packTemplate
			}
			shipOrderItem := modelJit.ShipOrderItemLst{
				ShipOrderId:    shipOrderId,
				Pos:            detail.Pos,
				PackTypeId:     packTemplate.PackTypeId,
				PackTemplateId: detail.ProductFamilyId,
				Status:         modelJit.SHIP_STATUS_PLANNED,
				PlanQty:        1,
			}
			shipOrderItemLi = append(shipOrderItemLi, shipOrderItem)
		}
		tempShipOrderItemLi := make([]modelJit.ShipOrderItemLst, 0, 20)
		for index, shipOrderItem := range shipOrderItemLi {
			if index != 0 && index%20 == 0 {
				err = shipOrderItemDao.Insert(&tempShipOrderItemLi)
				if err != nil {
					errData := model.HondaCalloffErrorLst{
						CalloffId:   callOffId,
						Pos:         0,
						ErrorType:   model.ERROR_TYPE_SYSTEM,
						ErrorInfo:   "系统解析异常，保存发运单子项失败:" + err.Error() + ";",
						ErrorStatus: model.ERROR_STATUS_ON,
					}
					_ = txSession.Rollback()
					innerErr := errDao.InsertOne(&errData)
					if innerErr != nil {
						_ = session.Rollback()
						return err
					}
					entity.Parsed = model.CALL_OFF_PARSE_FAILED
					innerErr = dao.UpdateOne(entity)
					if innerErr != nil {
						_ = session.Rollback()
						return err
					}
					_ = session.Commit()
					return err
				}
				tempShipOrderItemLi = make([]modelJit.ShipOrderItemLst, 0, 20)
			}
			tempShipOrderItemLi = append(tempShipOrderItemLi, shipOrderItem)
		}
		if len(tempShipOrderItemLi) != 0 {
			err = shipOrderItemDao.Insert(&tempShipOrderItemLi)
			if err != nil {
				errData := model.HondaCalloffErrorLst{
					CalloffId:   callOffId,
					Pos:         0,
					ErrorType:   model.ERROR_TYPE_SYSTEM,
					ErrorInfo:   "系统解析异常，保存发运单子项失败:" + err.Error() + ";",
					ErrorStatus: model.ERROR_STATUS_ON,
				}
				_ = txSession.Rollback()
				innerErr := errDao.InsertOne(&errData)
				if innerErr != nil {
					_ = session.Rollback()
					return err
				}
				entity.Parsed = model.CALL_OFF_PARSE_FAILED
				innerErr = dao.UpdateOne(entity)
				if innerErr != nil {
					_ = session.Rollback()
					return err
				}
				_ = session.Commit()
				return err
			}
		}
		entity.Parsed = model.CALL_OFF_PARED
		innerErr := dao.UpdateOne(entity)
		if innerErr != nil {
			_ = session.Rollback()
			_ = txSession.Rollback()
			return innerErr
		}
		_ = session.Commit()
		_ = txSession.Commit()
		return nil
	} else {
		//	如果有数据层面的错误 进行错误项落库
		tempErrorLi := make([]model.HondaCalloffErrorLst, 0, 20)
		for index, errorItem := range errorLi {
			if index != 0 && index%20 == 0 {
				err = errDao.Insert(&tempErrorLi)
				if err != nil {
					_ = session.Rollback()
					return err
				}
				tempErrorLi = make([]model.HondaCalloffErrorLst, 0, 20)
			}
			tempErrorLi = append(tempErrorLi, errorItem)
		}
		if len(tempErrorLi) != 0 {
			err = errDao.Insert(&tempErrorLi)
			if err != nil {
				_ = session.Rollback()
				return err
			}
		}
		if len(saveDetailLi) != 0 {
			// 保存完错误之后，将派生存在的数据项写入发运单
			// 获取一个新的session 用于保存发运单数据
			txSession := engine.NewSession()
			defer txSession.Close()
			// 开启事务
			if err := txSession.Begin(); err != nil {
				errData := model.HondaCalloffErrorLst{
					CalloffId:   callOffId,
					Pos:         0,
					ErrorType:   model.ERROR_TYPE_SYSTEM,
					ErrorInfo:   "系统解析异常,开启事务失败，错误:" + err.Error() + ";",
					ErrorStatus: model.ERROR_STATUS_ON,
				}
				err = errDao.InsertOne(&errData)
				if err != nil {
					_ = session.Rollback()
					return grmi.NewBusinessError("插入解析错误项失败, error:" + err.Error())
				}
				entity.Parsed = model.CALL_OFF_PARSE_FAILED
				err = dao.UpdateOne(entity)
				if err != nil {
					_ = session.Rollback()
					return grmi.NewBusinessError("更新callOf状态数据失败, error:" + err.Error())
				}
				_ = session.Commit()
				return err
			}
			//snrDao := baseDal.NewSnrDAO(txSession, plantNr, userId)
			shipOrderDao := dalJit.NewShipOrderDAO(txSession, plantNr, userId)
			shipOrderStatusDao := dalJit.NewShipOrderStatusDAO(txSession, plantNr, userId)
			shipOrderItemDao := dalJit.NewShipOrderItemLstDAO(txSession, plantNr, userId)
			packTemplateMap := make(map[string]*modelJit.PackTemplate)
			shipOrderItemLi := make([]modelJit.ShipOrderItemLst, 0)
			project, err := projectDao.SelectOne(projectId)
			if err != nil {
				errData := model.HondaCalloffErrorLst{
					CalloffId:   callOffId,
					Pos:         0,
					ErrorType:   model.ERROR_TYPE_SYSTEM,
					ErrorInfo:   "系统解析异常，查询车型配置数据失败:" + err.Error() + ";",
					ErrorStatus: model.ERROR_STATUS_ON,
				}
				_ = txSession.Rollback()
				innerErr := errDao.InsertOne(&errData)
				if innerErr != nil {
					_ = session.Rollback()
					return err
				}
				entity.Parsed = model.CALL_OFF_PARSE_FAILED
				innerErr = dao.UpdateOne(entity)
				if innerErr != nil {
					_ = session.Rollback()
					return err
				}
				_ = session.Commit()
				return err
			}
			if project == nil {
				errData := model.HondaCalloffErrorLst{
					CalloffId:   callOffId,
					Pos:         0,
					ErrorType:   model.ERROR_TYPE_SYSTEM,
					ErrorInfo:   "系统解析异常，查询车型项目数据不存在, 车型项目ID:" + projectId + ";",
					ErrorStatus: model.ERROR_STATUS_ON,
				}
				err = grmi.NewBusinessError("系统解析异常，查询车型项目数据不存在, 车型项目ID:" + projectId + ";")
				_ = txSession.Rollback()
				innerErr := errDao.InsertOne(&errData)
				if innerErr != nil {
					_ = session.Rollback()
					return err
				}
				entity.Parsed = model.CALL_OFF_PARSE_FAILED
				innerErr = dao.UpdateOne(entity)
				if innerErr != nil {
					_ = session.Rollback()
					return err
				}
				_ = session.Commit()
				return err
			}

			shipOrderId := entity.CardNo
			shipOrder := modelJit.ShipOrder{
				ShipOrderId: shipOrderId,
				ProjectId:   projectId,
				ShipType:    modelJit.SHIP_TYPE_FORMAL,
				PlanQty:     len(saveDetailLi),
				OpenTime:    grmi.DateTime(time.Now()),
				Operator:    userId,
				CtrlStr1:    callOffId,
			}
			err = shipOrderDao.InsertOne(&shipOrder)
			if err != nil {
				errData := model.HondaCalloffErrorLst{
					CalloffId:   callOffId,
					Pos:         0,
					ErrorType:   model.ERROR_TYPE_SYSTEM,
					ErrorInfo:   "系统解析异常，保存发运单失败:" + err.Error() + ";",
					ErrorStatus: model.ERROR_STATUS_ON,
				}
				_ = txSession.Rollback()
				innerErr := errDao.InsertOne(&errData)
				if innerErr != nil {
					_ = session.Rollback()
					return err
				}
				entity.Parsed = model.CALL_OFF_PARSE_FAILED
				innerErr = dao.UpdateOne(entity)
				if innerErr != nil {
					_ = session.Rollback()
					return err
				}
				_ = session.Commit()
				return err
			}
			shipOrderStatus := modelJit.ShipOrderStatus{
				ShipOrderId: shipOrderId,
				Status:      modelJit.SHIP_STATUS_PLANNED,
				Status1:     modelJit.SHIP_STATUS_PLANNED,
				Status2:     modelJit.SHIP_STATUS_PLANNED,
			}
			err = shipOrderStatusDao.InsertOne(&shipOrderStatus)
			if err != nil {
				errData := model.HondaCalloffErrorLst{
					CalloffId:   callOffId,
					Pos:         0,
					ErrorType:   model.ERROR_TYPE_SYSTEM,
					ErrorInfo:   "系统解析异常，保存发运单状态失败:" + err.Error() + ";",
					ErrorStatus: model.ERROR_STATUS_ON,
				}
				_ = txSession.Rollback()
				innerErr := errDao.InsertOne(&errData)
				if innerErr != nil {
					_ = session.Rollback()
					return err
				}
				entity.Parsed = model.CALL_OFF_PARSE_FAILED
				innerErr = dao.UpdateOne(entity)
				if innerErr != nil {
					_ = session.Rollback()
					return err
				}
				_ = session.Commit()
				return err
			}
			for _, detail := range saveDetailLi {
				packTemplate, exist := packTemplateMap[detail.ProductFamilyId]
				if !exist {
					packTemplate, err = packTemplateDao.SelectOne(detail.ProductFamilyId)
					if err != nil {
						errData := model.HondaCalloffErrorLst{
							CalloffId:   callOffId,
							Pos:         0,
							ErrorType:   model.ERROR_TYPE_SYSTEM,
							ErrorInfo:   "系统解析异常，查询包装模板失败:" + err.Error() + ";",
							ErrorStatus: model.ERROR_STATUS_ON,
						}
						_ = txSession.Rollback()
						innerErr := errDao.InsertOne(&errData)
						if innerErr != nil {
							_ = session.Rollback()
							return err
						}
						entity.Parsed = model.CALL_OFF_PARSE_FAILED
						innerErr = dao.UpdateOne(entity)
						if innerErr != nil {
							_ = session.Rollback()
							return err
						}
						_ = session.Commit()
						return err
					}
					if packTemplate == nil {
						errData := model.HondaCalloffErrorLst{
							CalloffId:   callOffId,
							Pos:         0,
							ErrorType:   model.ERROR_TYPE_SYSTEM,
							ErrorInfo:   "系统解析异常，该车型配置还没有生成包装模板, 车型配置ID:" + detail.ProductFamilyId + ";",
							ErrorStatus: model.ERROR_STATUS_ON,
						}
						_ = txSession.Rollback()
						innerErr := errDao.InsertOne(&errData)
						if innerErr != nil {
							_ = session.Rollback()
							return err
						}
						entity.Parsed = model.CALL_OFF_PARSE_FAILED
						innerErr = dao.UpdateOne(entity)
						if innerErr != nil {
							_ = session.Rollback()
							return err
						}
						_ = session.Commit()
						return err
					}
					packTemplateMap[detail.ProductFamilyId] = packTemplate
				}
				shipOrderItem := modelJit.ShipOrderItemLst{
					ShipOrderId:    shipOrderId,
					Pos:            detail.Pos,
					PackTypeId:     packTemplate.PackTypeId,
					PackTemplateId: detail.ProductFamilyId,
					Status:         modelJit.SHIP_STATUS_PLANNED,
					PlanQty:        1,
				}
				shipOrderItemLi = append(shipOrderItemLi, shipOrderItem)
			}
			tempShipOrderItemLi := make([]modelJit.ShipOrderItemLst, 0, 20)
			for index, shipOrderItem := range shipOrderItemLi {
				if index != 0 && index%20 == 0 {
					err = shipOrderItemDao.Insert(&tempShipOrderItemLi)
					if err != nil {
						errData := model.HondaCalloffErrorLst{
							CalloffId:   callOffId,
							Pos:         0,
							ErrorType:   model.ERROR_TYPE_SYSTEM,
							ErrorInfo:   "系统解析异常，保存发运单子项失败:" + err.Error() + ";",
							ErrorStatus: model.ERROR_STATUS_ON,
						}
						_ = txSession.Rollback()
						innerErr := errDao.InsertOne(&errData)
						if innerErr != nil {
							_ = session.Rollback()
							return err
						}
						entity.Parsed = model.CALL_OFF_PARSE_FAILED
						innerErr = dao.UpdateOne(entity)
						if innerErr != nil {
							_ = session.Rollback()
							return err
						}
						_ = session.Commit()
						return err
					}
					tempShipOrderItemLi = make([]modelJit.ShipOrderItemLst, 0, 20)
				}
				tempShipOrderItemLi = append(tempShipOrderItemLi, shipOrderItem)
			}
			if len(tempShipOrderItemLi) != 0 {
				err = shipOrderItemDao.Insert(&tempShipOrderItemLi)
				if err != nil {
					errData := model.HondaCalloffErrorLst{
						CalloffId:   callOffId,
						Pos:         0,
						ErrorType:   model.ERROR_TYPE_SYSTEM,
						ErrorInfo:   "系统解析异常，保存发运单子项失败:" + err.Error() + ";",
						ErrorStatus: model.ERROR_STATUS_ON,
					}
					_ = txSession.Rollback()
					innerErr := errDao.InsertOne(&errData)
					if innerErr != nil {
						_ = session.Rollback()
						return err
					}
					entity.Parsed = model.CALL_OFF_PARSE_FAILED
					innerErr = dao.UpdateOne(entity)
					if innerErr != nil {
						_ = session.Rollback()
						return err
					}
					_ = session.Commit()
					return err
				}
			}
			entity.Parsed = model.CALL_OFF_PARSED_PART
			innerErr := dao.UpdateOne(entity)
			if innerErr != nil {
				_ = session.Rollback()
				_ = txSession.Rollback()
				return innerErr
			}
			_ = session.Commit()
			_ = txSession.Commit()
			return nil
		} else {
			entity.Parsed = model.CALL_OFF_PARSE_FAILED
			err = dao.UpdateOne(entity)
			if err != nil {
				_ = session.Rollback()
				return err
			}
			_ = session.Commit()
			return nil
		}
	}
}

// AnalysisDataWithSession 解析CallOff已经加载到数据库中的数据
func (impl *HondaCalloffServiceImplement) AnalysisDataWithSession(entity *model.HondaCalloff, plantNr int, userId string, session *xorm.Session) (err error) {
	// 派生不存在这种数据项的错误不影响解析 状态给部分解析 且可以在前端页面点击再次解析
	callOffId := entity.CalloffId
	errDao := dal.NewHondaCalloffErrorLstDAO(session, plantNr, userId)
	dao := dal.NewHondaCalloffDAO(session, plantNr, userId)
	detailDao := dal.NewHondaCalloffItemLstDAO(session, plantNr, userId)
	productFamilyDao := dalMe.NewProductFamilyDAO(session, plantNr, userId)
	projectDao := dalMe.NewProjectDAO(session, plantNr, userId)
	packTemplateDao := dalJit.NewPackTemplateDAO(session, plantNr, userId)
	//删除错误信息
	err = errDao.DeleteWhere([]grmi.Predicate{meta.HondaCalloffErrorLst_CalloffId.NewPredicate(grmi.Equal, callOffId)})
	if err != nil {
		return grmi.NewBusinessError("删除原有错误数据失败, error:" + err.Error())
	}

	// 查询callOf子项数据
	detailLi, err := detailDao.Select([]grmi.Predicate{meta.HondaCalloffItemLst_CalloffId.NewPredicate(grmi.Equal, entity.CalloffId)}, []grmi.Field{meta.HondaCalloffItemLst_Pos})
	if err != nil {
		return grmi.NewBusinessError("查询解析详情数据失败， error:" + err.Error())
	}
	// 出现派生不存在时的 需要把派生存在的数据项写入发运单
	saveDetailLi := make([]model.HondaCalloffItemLst, 0)
	var projectId string
	errorLi := make([]model.HondaCalloffErrorLst, 0)
	productFamilyMap := make(map[string]*modelMe.ProductFamily)
	for _, detail := range detailLi {
		_, exist := productFamilyMap[detail.ProductFamilyId]
		if !exist {
			productFamily, err := productFamilyDao.SelectOne(detail.ProductFamilyId)
			if err != nil {
				return grmi.NewBusinessError("查询车型配置失败, error:" + err.Error())
			}
			if productFamily == nil {
				errData := model.HondaCalloffErrorLst{
					CalloffId:   callOffId,
					Pos:         detail.Pos,
					ErrorType:   model.ERROR_TYPE_DATA,
					ErrorInfo:   "车型配置不存在, 车型配置ID:" + detail.ProductFamilyId + ";",
					ErrorStatus: model.ERROR_STATUS_ON,
				}
				errorLi = append(errorLi, errData)
			} else {
				if projectId == "" {
					projectId = productFamily.ProjectId
				}
				productFamilyMap[detail.ProductFamilyId] = productFamily
				saveDetailLi = append(saveDetailLi, detail)
			}
		} else {
			saveDetailLi = append(saveDetailLi, detail)
		}
	}
	shipOrderDao := dalJit.NewShipOrderDAO(session, plantNr, userId)
	shipOrderStatusDao := dalJit.NewShipOrderStatusDAO(session, plantNr, userId)
	shipOrderItemDao := dalJit.NewShipOrderItemLstDAO(session, plantNr, userId)
	packTemplateMap := make(map[string]*modelJit.PackTemplate)
	shipOrderItemLi := make([]modelJit.ShipOrderItemLst, 0)
	project, err := projectDao.SelectOne(projectId)
	if err != nil {
		return grmi.NewBusinessError("查询项目数据失败, error:" + err.Error())
	}
	if project == nil {
		errData := model.HondaCalloffErrorLst{
			CalloffId:   callOffId,
			Pos:         0,
			ErrorType:   model.ERROR_TYPE_SYSTEM,
			ErrorInfo:   "系统解析异常，查询车型项目数据不存在, 车型项目ID:" + projectId + ";",
			ErrorStatus: model.ERROR_STATUS_ON,
		}
		err = grmi.NewBusinessError("系统解析异常，查询车型项目数据不存在, 车型项目ID:" + projectId + ";")
		innerErr := errDao.InsertOne(&errData)
		if innerErr != nil {
			return grmi.NewBusinessError("写入错误数据失败, error:" + err.Error())
		}
		entity.Parsed = model.CALL_OFF_PARSE_FAILED
		innerErr = dao.UpdateOne(entity)
		if innerErr != nil {
			return grmi.NewBusinessError("更新callOff状态失败, error:" + err.Error())
		}
		return nil
	}
	// 如果没有数据层面的错误 创建发运单 并进行数据落库
	if len(errorLi) == 0 {
		shipOrderId := entity.CardNo
		shipOrder := modelJit.ShipOrder{
			ShipOrderId: shipOrderId,
			ProjectId:   projectId,
			ShipType:    modelJit.SHIP_TYPE_FORMAL,
			PlanQty:     len(detailLi),
			OpenTime:    grmi.DateTime(time.Now()),
			Operator:    userId,
			CtrlStr1:    callOffId,
		}
		err = shipOrderDao.InsertOne(&shipOrder)
		if err != nil {
			return grmi.NewBusinessError("写入发运单数据失败， error:" + err.Error())
		}
		shipOrderStatus := modelJit.ShipOrderStatus{
			ShipOrderId: shipOrderId,
			Status:      modelJit.SHIP_STATUS_PLANNED,
			Status1:     modelJit.SHIP_STATUS_PLANNED,
			Status2:     modelJit.SHIP_STATUS_PLANNED,
		}
		err = shipOrderStatusDao.InsertOne(&shipOrderStatus)
		if err != nil {
			return grmi.NewBusinessError("写入发运单状态数据失败, error:" + err.Error())
		}
		for _, detail := range detailLi {
			packTemplate, exist := packTemplateMap[detail.ProductFamilyId]
			if !exist {
				packTemplate, err = packTemplateDao.SelectOne(detail.ProductFamilyId)
				if err != nil {
					return grmi.NewBusinessError("查询包装模板失败:" + err.Error())
				}
				if packTemplate == nil {
					errData := model.HondaCalloffErrorLst{
						CalloffId:   callOffId,
						Pos:         0,
						ErrorType:   model.ERROR_TYPE_SYSTEM,
						ErrorInfo:   "系统解析异常，该车型配置还没有生成包装模板, 车型配置ID:" + detail.ProductFamilyId + ";",
						ErrorStatus: model.ERROR_STATUS_ON,
					}
					innerErr := errDao.InsertOne(&errData)
					if innerErr != nil {
						return grmi.NewBusinessError("写入错误数据失败, error:" + err.Error())
					}
					entity.Parsed = model.CALL_OFF_PARSE_FAILED
					innerErr = dao.UpdateOne(entity)
					if innerErr != nil {
						return grmi.NewBusinessError("更新callOff状态失败, error:" + err.Error())
					}
					return nil
				}
				packTemplateMap[detail.ProductFamilyId] = packTemplate
			}
			shipOrderItem := modelJit.ShipOrderItemLst{
				ShipOrderId:    shipOrderId,
				Pos:            detail.Pos,
				PackTypeId:     packTemplate.PackTypeId,
				PackTemplateId: detail.ProductFamilyId,
				Status:         modelJit.SHIP_STATUS_PLANNED,
				PlanQty:        1,
			}
			shipOrderItemLi = append(shipOrderItemLi, shipOrderItem)
		}
		tempShipOrderItemLi := make([]modelJit.ShipOrderItemLst, 0, 20)
		for index, shipOrderItem := range shipOrderItemLi {
			if index != 0 && index%20 == 0 {
				err = shipOrderItemDao.Insert(&tempShipOrderItemLi)
				if err != nil {
					return grmi.NewBusinessError("保存发运单子项失败， error:" + err.Error())
				}
				tempShipOrderItemLi = make([]modelJit.ShipOrderItemLst, 0, 20)
			}
			tempShipOrderItemLi = append(tempShipOrderItemLi, shipOrderItem)
		}
		if len(tempShipOrderItemLi) != 0 {
			err = shipOrderItemDao.Insert(&tempShipOrderItemLi)
			if err != nil {
				return grmi.NewBusinessError("保存发运单子项失败， error:" + err.Error())
			}
		}
		entity.Parsed = model.CALL_OFF_PARED
		innerErr := dao.UpdateOne(entity)
		if innerErr != nil {
			return grmi.NewBusinessError("更新callOff状态失败, error:" + err.Error())
		}
		return nil
	} else {
		//	如果有数据层面的错误 进行错误项落库
		tempErrorLi := make([]model.HondaCalloffErrorLst, 0, 20)
		for index, errorItem := range errorLi {
			if index != 0 && index%20 == 0 {
				err = errDao.Insert(&tempErrorLi)
				if err != nil {
					return grmi.NewBusinessError("写入错误失败, error:" + err.Error())
				}
				tempErrorLi = make([]model.HondaCalloffErrorLst, 0, 20)
			}
			tempErrorLi = append(tempErrorLi, errorItem)
		}
		if len(tempErrorLi) != 0 {
			err = errDao.Insert(&tempErrorLi)
			if err != nil {
				return grmi.NewBusinessError("写入错误失败, error:" + err.Error())
			}
		}
		if len(saveDetailLi) != 0 {
			shipOrderId := entity.CardNo
			shipOrder := modelJit.ShipOrder{
				ShipOrderId: shipOrderId,
				ProjectId:   projectId,
				ShipType:    modelJit.SHIP_TYPE_FORMAL,
				PlanQty:     len(saveDetailLi),
				OpenTime:    grmi.DateTime(time.Now()),
				Operator:    userId,
				CtrlStr1:    callOffId,
			}
			err = shipOrderDao.InsertOne(&shipOrder)
			if err != nil {
				return grmi.NewBusinessError("写入发运单数据失败， error:" + err.Error())
			}
			shipOrderStatus := modelJit.ShipOrderStatus{
				ShipOrderId: shipOrderId,
				Status:      modelJit.SHIP_STATUS_PLANNED,
				Status1:     modelJit.SHIP_STATUS_PLANNED,
				Status2:     modelJit.SHIP_STATUS_PLANNED,
			}
			err = shipOrderStatusDao.InsertOne(&shipOrderStatus)
			if err != nil {
				return grmi.NewBusinessError("写入发运单状态数据失败, error:" + err.Error())
			}
			for _, detail := range saveDetailLi {
				packTemplate, exist := packTemplateMap[detail.ProductFamilyId]
				if !exist {
					packTemplate, err = packTemplateDao.SelectOne(detail.ProductFamilyId)
					if err != nil {
						return grmi.NewBusinessError("查询包装模板失败:" + err.Error())
					}
					if packTemplate == nil {
						errData := model.HondaCalloffErrorLst{
							CalloffId:   callOffId,
							Pos:         0,
							ErrorType:   model.ERROR_TYPE_SYSTEM,
							ErrorInfo:   "系统解析异常，该车型配置还没有生成包装模板, 车型配置ID:" + detail.ProductFamilyId + ";",
							ErrorStatus: model.ERROR_STATUS_ON,
						}
						innerErr := errDao.InsertOne(&errData)
						if innerErr != nil {
							return grmi.NewBusinessError("写入错误数据失败, error:" + err.Error())
						}
						entity.Parsed = model.CALL_OFF_PARSE_FAILED
						innerErr = dao.UpdateOne(entity)
						if innerErr != nil {
							return grmi.NewBusinessError("更新callOff状态失败, error:" + err.Error())
						}
						return nil
					}
					packTemplateMap[detail.ProductFamilyId] = packTemplate
				}
				shipOrderItem := modelJit.ShipOrderItemLst{
					ShipOrderId:    shipOrderId,
					Pos:            detail.Pos,
					PackTypeId:     packTemplate.PackTypeId,
					PackTemplateId: detail.ProductFamilyId,
					Status:         modelJit.SHIP_STATUS_PLANNED,
					PlanQty:        1,
				}
				shipOrderItemLi = append(shipOrderItemLi, shipOrderItem)
			}
			tempShipOrderItemLi := make([]modelJit.ShipOrderItemLst, 0, 20)
			for index, shipOrderItem := range shipOrderItemLi {
				if index != 0 && index%20 == 0 {
					err = shipOrderItemDao.Insert(&tempShipOrderItemLi)
					if err != nil {
						return grmi.NewBusinessError("保存发运单子项失败， error:" + err.Error())
					}
					tempShipOrderItemLi = make([]modelJit.ShipOrderItemLst, 0, 20)
				}
				tempShipOrderItemLi = append(tempShipOrderItemLi, shipOrderItem)
			}
			if len(tempShipOrderItemLi) != 0 {
				err = shipOrderItemDao.Insert(&tempShipOrderItemLi)
				if err != nil {
					return grmi.NewBusinessError("保存发运单子项失败， error:" + err.Error())
				}
			}
			entity.Parsed = model.CALL_OFF_PARSED_PART
			innerErr := dao.UpdateOne(entity)
			if innerErr != nil {
				return grmi.NewBusinessError("更新callOff状态失败, error:" + err.Error())
			}
			return nil
		} else {
			entity.Parsed = model.CALL_OFF_PARSE_FAILED
			err = dao.UpdateOne(entity)
			if err != nil {
				return grmi.NewBusinessError("更新callOff状态失败, error:" + err.Error())
			}
			return nil
		}
	}
}

// AnalysisDataAgain 重新解析callOff数据
func (impl *HondaCalloffServiceImplement) AnalysisDataAgain(user *global.User, callOffId string) (err error) {
	grmi.Log(user, "/services/pln/implments/HondaCalloff.service.impl.go", "AnalysisDataAgain", "重新解析")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewHondaCalloffDAO(session, user.PlantNr, user.UserId)
	errDao := dal.NewHondaCalloffErrorLstDAO(session, user.PlantNr, user.UserId)
	// 校验callOff数据
	callOff, err := dao.SelectOne(callOffId)
	if err != nil {
		return grmi.NewBusinessError("查询CallOff数据失败, error:" + err.Error())
	}
	if callOff == nil {
		return grmi.NewBusinessError("不存在对应的CallOff数据")
	}
	if callOff.Parsed != model.CALL_OFF_LOADED && callOff.Parsed != model.CALL_OFF_PARSE_FAILED && callOff.Parsed != model.CALL_OFF_PARSED_PART {
		return grmi.NewBusinessError("该CallOff状态不是已加载或解析失败, 不允许进行该操作")
	}
	if callOff.Parsed == model.CALL_OFF_PARSE_FAILED {
		errorLi, err := errDao.Select([]grmi.Predicate{meta.HondaCalloffErrorLst_CalloffId.NewPredicate(grmi.Equal, callOff.CalloffId),
			meta.HondaCalloffErrorLst_ErrorType.NewPredicate(grmi.Equal, model.ERROR_TYPE_DATA),
			meta.HondaCalloffErrorLst_ErrorStatus.NewPredicate(grmi.Equal, model.ERROR_STATUS_ON)}, nil)
		if err != nil {
			return grmi.NewBusinessError("查询错误列表失败, error:" + err.Error())
		}
		if len(errorLi) != 0 {
			return grmi.NewBusinessError("存在未关闭的数据错误项")
		}
	} else if callOff.Parsed == model.CALL_OFF_PARSED_PART {
		// 如果是部分解析
		// 1. 校验已经生成的发运单没有操作过
		// 2. 删除已经生成的发运单数据
		// 3. 重新解析
		shipOrderDao := dalJit.NewShipOrderDAO(session, user.PlantNr, user.UserId)
		shipOrderStatusDao := dalJit.NewShipOrderStatusDAO(session, user.PlantNr, user.UserId)
		shipOrderItemDao := dalJit.NewShipOrderItemLstDAO(session, user.PlantNr, user.UserId)
		shipOrderLi, err := shipOrderDao.Select([]grmi.Predicate{metaJit.ShipOrder_CtrlStr1.NewPredicate(grmi.Equal, callOffId)}, nil)
		if err != nil {
			return grmi.NewBusinessError("该CallOff状态为部分解析， 查询解析的发运单数据失败, 错误:" + err.Error())
		}
		if len(shipOrderLi) == 0 {
			return grmi.NewBusinessError("该CallOff状态为部分解析， 未查询到解析的发运单")
		} else if len(shipOrderLi) > 1 {
			return grmi.NewBusinessError("该CallOff状态为部分解析， 查询到多个发运单")
		}
		shipOrder := shipOrderLi[0]
		shipOrderStatus, err := shipOrderStatusDao.SelectOne(shipOrder.ShipOrderId)
		if err != nil {
			return grmi.NewBusinessError("该CallOff状态为部分解析， 查询解析的发运单状态数据失败, 错误:" + err.Error())
		}
		if shipOrderStatus == nil {
			return grmi.NewBusinessError("该CallOff状态为部分解析， 不存在发运单状态数据,  发运单ID:" + shipOrder.ShipOrderId)
		}
		if shipOrderStatus.Status != modelJit.SHIP_STATUS_PLANNED {
			return grmi.NewBusinessError("该CallOff状态为部分解析，解析的发运单已操作, 发运单ID:" + shipOrder.ShipOrderId)
		}
		if err = session.Begin(); err != nil {
			return grmi.NewBusinessError("开启事务失败, error:" + err.Error())
		}
		err = shipOrderDao.DeleteOne(shipOrder.ShipOrderId)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("该CallOff状态为部分解析， 删除已经解析的发运单数据失败, 错误:" + err.Error())
		}
		err = shipOrderStatusDao.DeleteOne(shipOrder.ShipOrderId)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("该CallOff状态为部分解析， 删除已经解析的发运单状态数据失败, 错误:" + err.Error())
		}
		err = shipOrderItemDao.DeleteWhere([]grmi.Predicate{metaJit.ShipOrderItemLst_ShipOrderId.NewPredicate(grmi.Equal, shipOrder.ShipOrderId)})
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("该CallOff状态为部分解析， 删除已经解析的发运单状态数据失败, 错误:" + err.Error())
		}
		err = impl.AnalysisDataWithSession(callOff, user.PlantNr, user.UserId, session)
		if err != nil {
			_ = session.Rollback()
			return err
		}
		_ = session.Commit()
		return nil
	}
	// 调用解析方法 并同步返回错误
	err = impl.AnalysisData(callOff, user.PlantNr, user.UserId)
	return err
}

// AnalysisTask 解析任务
func (impl *HondaCalloffServiceImplement) AnalysisTask() {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	userId := "scheduler"
	log, _ := logger.NewLogger(userId, "PLN")
	plantDao := baseDal.NewPlantDAO(session, userId)
	plantLi, err := plantDao.Select(nil, nil)
	if err != nil {
		log.Error("定时解析CallOff任务, 获取工厂数据失败, error:" + err.Error())
		return
	}
	for _, plant := range plantLi {
		if plant.PlantProject != baseModel.PROJECT_ACURA {
			continue
		}
		go func(plant baseModel.Plant) {
			dao := dal.NewHondaCalloffDAO(session, plant.PlantNr, userId)
			callOffLi, err := dao.Select([]grmi.Predicate{meta.HondaCalloff_Parsed.NewPredicate(grmi.Equal, model.CALL_OFF_LOADED)}, []grmi.Field{meta.HondaCalloff_CalloffId})
			if err != nil {
				log.Error("定时解析CallOff任务, 获取CallOff数据失败, error:" + err.Error())
				return
			}
			if len(callOffLi) == 0 {
				log.Debug("定时解析CallOff任务, 当前没有待解析的CallOff")
				return
			}
			firstCallOff := callOffLi[0]
			firstCallOff.Parsed = model.CALL_OFF_PARSING
			err = dao.UpdateOne(&firstCallOff)
			if err != nil {
				log.Error("定时解析CallOff任务, 更新CallOff状态为解析中失败, error:" + err.Error())
				return
			}
			// 调用解析方法 并同步返回错误
			err = impl.AnalysisData(&firstCallOff, plant.PlantNr, userId)
			if err != nil {
				log.Error("定时解析CallOff任务, 解析失败, CallOffId: " + firstCallOff.CalloffId + ", error:" + err.Error())
				return
			} else {
				log.Debug("定时解析CallOff任务, 解析完成, CallOffId:" + firstCallOff.CalloffId)
				return
			}
		}(plant)
	}

}
