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

package implments

import (
	dal "LAPP_ACURA_MOM_BACKEND/dao/base"
	cacheDal "LAPP_ACURA_MOM_BACKEND/dao/cache"
	plnDal "LAPP_ACURA_MOM_BACKEND/dao/pln"
	"LAPP_ACURA_MOM_BACKEND/db"
	"LAPP_ACURA_MOM_BACKEND/global"
	"LAPP_ACURA_MOM_BACKEND/grmi"
	meta "LAPP_ACURA_MOM_BACKEND/meta/base"
	model "LAPP_ACURA_MOM_BACKEND/models/base"
	cacheModel "LAPP_ACURA_MOM_BACKEND/models/cache"
	plnModel "LAPP_ACURA_MOM_BACKEND/models/pln"
	"LAPP_ACURA_MOM_BACKEND/services/schedule"
	"LAPP_ACURA_MOM_BACKEND/utils"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/google/uuid"
	"sort"
	"time"
)

/******************************************************************************
 *
 * @Description              : WorkLine的默认查询条件
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-10-28 14:57:09
 *
 ******************************************************************************/
var DefaultConditionOfWorkLine = grmi.NewCondition(
	map[string]grmi.ConditionItem{
		meta.WorkLine_WorkLineid.UrlParameterName:               grmi.NewConditionItem(meta.WorkLine_WorkLineid, grmi.Equal, true),
		meta.WorkLine_Descr.UrlParameterName:                    grmi.NewConditionItem(meta.WorkLine_Descr, grmi.Equal, false),
		meta.WorkLine_LineType.UrlParameterName:                 grmi.NewConditionItem(meta.WorkLine_LineType, grmi.Equal, false),
		meta.WorkLine_GroupType.UrlParameterName:                grmi.NewConditionItem(meta.WorkLine_GroupType, grmi.Equal, false),
		meta.WorkLine_GroupLineId.UrlParameterName:              grmi.NewConditionItem(meta.WorkLine_GroupLineId, grmi.Equal, false),
		meta.WorkLine_LinePlanMode.UrlParameterName:             grmi.NewConditionItem(meta.WorkLine_LinePlanMode, grmi.Equal, false),
		meta.WorkLine_WeekModelNr.UrlParameterName:              grmi.NewConditionItem(meta.WorkLine_WeekModelNr, grmi.Equal, false),
		meta.WorkLine_WorkCalendarNr.UrlParameterName:           grmi.NewConditionItem(meta.WorkLine_WorkCalendarNr, grmi.Equal, false),
		meta.WorkLine_Location.UrlParameterName:                 grmi.NewConditionItem(meta.WorkLine_Location, grmi.Equal, false),
		meta.WorkLine_CostCenterId.UrlParameterName:             grmi.NewConditionItem(meta.WorkLine_CostCenterId, grmi.Equal, false),
		meta.WorkLine_CostRate.UrlParameterName:                 grmi.NewConditionItem(meta.WorkLine_CostRate, grmi.Equal, false),
		meta.WorkLine_ProdEff.UrlParameterName:                  grmi.NewConditionItem(meta.WorkLine_ProdEff, grmi.Equal, false),
		meta.WorkLine_ReqWorkers.UrlParameterName:               grmi.NewConditionItem(meta.WorkLine_ReqWorkers, grmi.Equal, false),
		meta.WorkLine_Pos.UrlParameterName:                      grmi.NewConditionItem(meta.WorkLine_Pos, grmi.Equal, false),
		meta.WorkLine_TaskQueueSortWay.UrlParameterName:         grmi.NewConditionItem(meta.WorkLine_TaskQueueSortWay, grmi.Equal, false),
		meta.WorkLine_MultiQueueMixSortToggle.UrlParameterName:  grmi.NewConditionItem(meta.WorkLine_MultiQueueMixSortToggle, grmi.Equal, false),
		meta.WorkLine_TaskQueueMixSortWay.UrlParameterName:      grmi.NewConditionItem(meta.WorkLine_TaskQueueMixSortWay, grmi.Equal, false),
		meta.WorkLine_MixSortLogic.UrlParameterName:             grmi.NewConditionItem(meta.WorkLine_MixSortLogic, grmi.Equal, false),
		meta.WorkLine_TaskReleaseWay.UrlParameterName:           grmi.NewConditionItem(meta.WorkLine_TaskReleaseWay, grmi.Equal, false),
		meta.WorkLine_ReleaseQtyParameter.UrlParameterName:      grmi.NewConditionItem(meta.WorkLine_ReleaseQtyParameter, grmi.Equal, false),
		meta.WorkLine_ReleaseTimeParameter.UrlParameterName:     grmi.NewConditionItem(meta.WorkLine_ReleaseTimeParameter, grmi.Approximate, false),
		meta.WorkLine_ReleaseCtrlParameter.UrlParameterName:     grmi.NewConditionItem(meta.WorkLine_ReleaseCtrlParameter, grmi.Equal, false),
		meta.WorkLine_ReleaseDurationParameter.UrlParameterName: grmi.NewConditionItem(meta.WorkLine_ReleaseDurationParameter, grmi.Equal, false),
		meta.WorkLine_SchedKeySnr.UrlParameterName:              grmi.NewConditionItem(meta.WorkLine_SchedKeySnr, grmi.Equal, false),
		meta.WorkLine_SerialOrderSnr.UrlParameterName:           grmi.NewConditionItem(meta.WorkLine_SerialOrderSnr, grmi.Equal, false),
		meta.WorkLine_LastModify.UrlParameterName:               grmi.NewConditionItem(meta.WorkLine_LastModify, grmi.Approximate, false),
		meta.WorkLine_LastUser.UrlParameterName:                 grmi.NewConditionItem(meta.WorkLine_LastUser, grmi.Equal, false),
		meta.WorkLine_CreateTime.UrlParameterName:               grmi.NewConditionItem(meta.WorkLine_CreateTime, grmi.Approximate, false),
	},
	nil,
)

/******************************************************************************
 *
 * @Description              : WorkLine的默认分页查询条件
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-10-28 14:57:09
 *
 ******************************************************************************/
var DefaultConditionOfWorkLineAndPaging = grmi.NewCondition(
	DefaultConditionOfWorkLine.Items,
	grmi.NewPaging(),
)

/******************************************************************************
 *
 * @Struct Name              : WorkLineServiceImplement
 *-----------------------------------------------------------------------------
 *
 * @Description              : WorkLine的服务实现
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-10-28 14:57:09
 *
 ******************************************************************************/
type WorkLineServiceImplement struct {
}

/******************************************************************************
 *
 * @Function Name            : NewWorkLineDAOImplement
 *-----------------------------------------------------------------------------
 *
 * @Description              : 创建一个WorkLineDAOImplement实例
 *
 * @Return Value             : WorkLineDAOImplement实例
 *
 * @Author                   : 代码生成器创建
 *
 * @Date                     : 2021-10-28 14:57:09
 *
 ******************************************************************************/
func NewWorkLineServiceImplement() *WorkLineServiceImplement {
	return &WorkLineServiceImplement{}
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/base/WorkLineService.InsertOne
 *
 ******************************************************************************/
func (impl *WorkLineServiceImplement) InsertOne(user *global.User, entity *model.WorkLine) error {

	grmi.Log(user, "/services/base/implments/WorkLine.service.impl.go", "InsertOneWorkLine", "插入一个WorkLine")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewWorkLineDAO(session, user.PlantNr, user.UserId)
	record, err := dao.SelectOne(entity.WorkLineid)
	if err != nil {
		return err
	}
	if record != nil {
		return grmi.NewBusinessError("已经存在相同主键的记录!")
	}
	weekModelDao := dal.NewWeekModelDAO(session, user.PlantNr, user.UserId)
	if entity.WeekModelNr != 0 {
		weekModel, err := weekModelDao.SelectOne(entity.WeekModelNr)
		if err != nil {
			return err
		}
		if weekModel == nil {
			return grmi.NewBusinessError("不存在对应的周模型，请检查")
		}
	}
	if entity.WorkCalendarNr != 0 {
		calendarDao := dal.NewWorkCalendarDAO(session, user.PlantNr, user.UserId)
		calendar, err := calendarDao.SelectOne(entity.WorkCalendarNr)
		if err != nil {
			return err
		}
		if calendar == nil {
			return grmi.NewBusinessError("不存在对应的日历模型")
		}
	}
	if entity.TaskReleaseWay != "BY_QTY" && entity.TaskReleaseWay != "BY_DURA" {
		return grmi.NewBusinessError("未选择正确的派工类型")
	}
	if entity.TaskReleaseWay == "BY_QTY" && entity.ReleaseQtyParameter == 0 {
		return grmi.NewBusinessError("未填写派工控制参数")
	}
	if entity.TaskReleaseWay == "BY_DURA" && entity.ReleaseDurationParameter == 0 {
		return grmi.NewBusinessError("未填写派工控制参数")
	}
	if entity.GroupType == model.WORK_LINE_TYPE_REAL && entity.GroupLineId != "" {
		groupLine, err := dao.SelectOne(entity.GroupLineId)
		if err != nil {
			return grmi.NewBusinessError("查询产线组产线数据失败，error:" + err.Error())
		}
		if groupLine == nil {
			return grmi.NewBusinessError("设置的产线组产线不存在, 产线ID:" + entity.GroupLineId)
		}
		if groupLine.GroupType != model.WORK_LINE_TYPE_GROUP {
			return grmi.NewBusinessError("关联的产线组产线不是产线组类型, 产线ID:" + entity.GroupLineId)
		}
	}
	err = dao.InsertOne(entity)
	if err != nil {
		return err
	}

	return nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/base/WorkLineService.DeleteOne
 *
 ******************************************************************************/
func (impl *WorkLineServiceImplement) DeleteOne(user *global.User, workLineid string) error {

	grmi.Log(user, "/services/base/implments/WorkLine.service.impl.go", "DeleteOneWorkLine", "删除一个WorkLine")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	err := session.Begin()
	if err != nil {
		return err
	}
	dao := dal.NewWorkLineDAO(session, user.PlantNr, user.UserId)
	workLineProcessDao := dal.NewWorkLineProcessLstDAO(session, user.PlantNr, user.UserId)
	record, err := dao.SelectOne(workLineid)
	if err != nil {
		return err
	}
	if record == nil {
		return grmi.NewBusinessError("不存在指定记录!")
	}
	specialDayDao := dal.NewWorkLineSpecialDayDAO(session, user.PlantNr, user.UserId)
	err = specialDayDao.DeleteWhere([]grmi.Predicate{meta.WorkLineSpecialDay_WorkLineid.NewPredicate(grmi.Equal, workLineid)})
	if err != nil {
		session.Rollback()
		return err
	}
	workLineShiftDao := dal.NewWorkLineWorkShiftLstDAO(session, user.PlantNr, user.UserId)
	err = workLineShiftDao.DeleteWhere([]grmi.Predicate{meta.WorkLineWorkShiftLst_WorkLineId.NewPredicate(grmi.Equal, workLineid)})
	if err != nil {
		session.Rollback()
		return err
	}
	err = dao.DeleteOne(workLineid)
	if err != nil {
		session.Rollback()
		return err
	}
	lstdao := dal.NewWorkLineWorkPlaceLstDAO(session, user.PlantNr, user.UserId)
	err = lstdao.DeleteWhere([]grmi.Predicate{meta.WorkLineWorkPlaceLst_WorkLineId.NewPredicate(grmi.Equal, workLineid)})
	if err != nil {
		session.Rollback()
		return err
	}
	err = workLineProcessDao.DeleteWhere([]grmi.Predicate{meta.WorkLineProcessLst_WorkLineId.NewPredicate(grmi.Equal, workLineid)})
	if err != nil {
		_ = session.Rollback()
		return grmi.NewBusinessError("删除产线工序关联关系失败, error:" + err.Error())
	}
	session.Commit()
	return nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/base/WorkLineService.SelectOne
 *
 ******************************************************************************/
func (impl *WorkLineServiceImplement) SelectOne(user *global.User, workLineid string) (*model.WorkLine, error) {

	grmi.Log(user, "/services/base/implments/WorkLine.service.impl.go", "SelectOneWorkLine", "查询一个WorkLine")

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

	lstdao := dal.NewWorkLineWorkPlaceLstDAO(session, user.PlantNr, user.UserId)
	list, err := lstdao.SelectAllot(workLineid)
	if err != nil {
		return nil, err
	}
	if utils.ValueIsEmpty(result) {
		return nil, err
	}
	//获取已分配的属性集合
	var workPlaceNrs []int
	for _, v := range list {
		workPlaceNrs = append(workPlaceNrs, v.WorkPlaceNr)
	}
	unlist, err := lstdao.SelectUnAllot(workPlaceNrs)
	if err != nil {
		return nil, err
	}
	//查询已分配
	result.WorkPlaceValst = list
	//查询未分配
	result.WorkPlaceUnValst = unlist
	return result, nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/base/WorkLineService.UpdateOne
 *
 ******************************************************************************/
func (impl *WorkLineServiceImplement) UpdateOne(user *global.User, entity *model.WorkLine) error {

	grmi.Log(user, "/services/base/implments/WorkLine.service.impl.go", "UpdateOneWorkLine", "修改一个WorkLine")

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

	dao := dal.NewWorkLineDAO(session, user.PlantNr, user.UserId)
	record, err := dao.SelectOne(entity.WorkLineid)
	if err != nil {
		return err
	}
	if record == nil {
		return grmi.NewBusinessError("不存在指定记录!")
	}
	if record.WeekModelNr != entity.WeekModelNr {
		weekModelDao := dal.NewWeekModelDAO(session, user.PlantNr, user.UserId)
		weekModel, err := weekModelDao.SelectOne(entity.WeekModelNr)
		if err != nil {
			return err
		}
		if weekModel == nil {
			return grmi.NewBusinessError("不存在对应的周模型，请检查")
		}
	}
	if record.WorkCalendarNr != entity.WorkCalendarNr && entity.WorkCalendarNr != 0 {
		calendarDao := dal.NewWorkCalendarDAO(session, user.PlantNr, user.UserId)
		calendar, err := calendarDao.SelectOne(entity.WorkCalendarNr)
		if err != nil {
			return err
		}
		if calendar == nil {
			return grmi.NewBusinessError("不存在对应的日历模型，请检查")
		}
	}
	if entity.TaskReleaseWay != "BY_QTY" && entity.TaskReleaseWay != "BY_DURA" {
		return grmi.NewBusinessError("未选择正确的派工类型")
	}
	if entity.TaskReleaseWay == "BY_QTY" && entity.ReleaseQtyParameter == 0 {
		return grmi.NewBusinessError("未填写派工控制参数")
	}
	if entity.TaskReleaseWay == "BY_DURA" && entity.ReleaseDurationParameter == 0 {
		return grmi.NewBusinessError("未填写派工控制参数")
	}
	entity.WorkLineid = record.WorkLineid
	entity.Pos = record.Pos
	if entity.GroupType == model.WORK_LINE_TYPE_REAL && entity.GroupLineId != "" {
		groupLine, err := dao.SelectOne(entity.GroupLineId)
		if err != nil {
			return grmi.NewBusinessError("查询产线组产线数据失败，error:" + err.Error())
		}
		if groupLine == nil {
			return grmi.NewBusinessError("设置的产线组产线不存在, 产线ID:" + entity.GroupLineId)
		}
		if groupLine.GroupType != model.WORK_LINE_TYPE_GROUP {
			return grmi.NewBusinessError("关联的产线组产线不是产线组类型, 产线ID:" + entity.GroupLineId)
		}
	}
	err = dao.UpdateOne(entity)
	if err != nil {
		return err
	}

	return nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/base/WorkLineService.Insert
 *
 ******************************************************************************/
func (impl *WorkLineServiceImplement) Insert(user *global.User, entities *[]model.WorkLine) error {

	grmi.Log(user, "/services/base/implments/WorkLine.service.impl.go", "InsertWorkLine", "插入多个WorkLine")

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

	for _, entity := range *entities {
		record, err := dao.SelectOne(entity.WorkLineid)
		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/base/WorkLineService.Delete
 *
 ******************************************************************************/
func (impl *WorkLineServiceImplement) Delete(user *global.User, entities *[]model.WorkLine) error {

	grmi.Log(user, "/services/base/implments/WorkLine.service.impl.go", "DeleteWorkLine", "删除多个WorkLine")

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

	for _, entity := range *entities {
		record, err := dao.SelectOne(entity.WorkLineid)
		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/base/WorkLineService.Select
 *
 ******************************************************************************/
func (impl *WorkLineServiceImplement) Select(user *global.User, urlParameters map[string]string) (interface{}, error) {

	grmi.Log(user, "/services/base/implments/WorkLine.service.impl.go", "SelectWorkLine", "查询WorkLine")

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

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/base/WorkLineService.Update
 *
 ******************************************************************************/
func (impl *WorkLineServiceImplement) Update(user *global.User, entities *[]model.WorkLine) error {

	grmi.Log(user, "/services/base/implments/WorkLine.service.impl.go", "UpdateWorkLine", "修改多个WorkLine")

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

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

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

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/base/WorkLineService.SelectJoinWorkPlace
 *
 ******************************************************************************/
func (impl *WorkLineServiceImplement) SelectJoinWorkPlace(user *global.User) ([]model.WorkLine, error) {

	grmi.Log(user, "/services/base/implments/WorkLine.service.impl.go", "SelectJoinWorkPlace", "联查出产线和工位之间的关系")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewWorkLineDAO(session, user.PlantNr, user.UserId)
	place := dal.NewWorkLineWorkPlaceLstDAO(session, user.PlantNr, user.UserId)
	list, err := dao.SelectAll()
	if err != nil {
		return nil, err
	}
	for k, v := range list {
		record, err := place.SelectAllot(v.WorkLineid)
		if err != nil {
			continue
		}
		if record == nil {
			continue
		}
		list[k].WorkPlaceValst = record
	}
	return list, nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/base/WorkLineService.WorkLineTree
 *
 ******************************************************************************/
func (impl *WorkLineServiceImplement) WorkLineTree(user *global.User) (model.WorkLineArr, error) {

	grmi.Log(user, "/services/base/implments/WorkLine.service.impl.go", "WorkLineTree", "构造出列表树状图")
	var data model.WorkLineArr
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	// 查询角色关联产线
	//roleRelDao := dal.NewRoleRelDAO(session, user.PlantNr, user.UserId)
	//roleRelLi, err := roleRelDao.Select([]grmi.Predicate{meta.RoleRel_RoleId.NewPredicate(grmi.Equal, user.RoleId)}, nil)
	//if err != nil {
	//	return data, err
	//}
	//workLineIdLi := make([]interface{}, 0, len(roleRelLi))
	//for _, roleRel := range roleRelLi {
	//	workLineIdLi = append(workLineIdLi, roleRel.WorkLineid)
	//}
	// 查询产线组类型的产线
	dao := dal.NewWorkLineDAO(session, user.PlantNr, user.UserId)
	workLineLi, err := dao.Select([]grmi.Predicate{meta.WorkLine_GroupType.NewPredicate(grmi.Equal, model.WORK_LINE_TYPE_GROUP)}, nil)
	if err != nil {
		return data, err
	}
	plant := dal.NewPlantDAO(session, user.UserId)
	plantInfo, err := plant.SelectOne(user.PlantNr)
	if err != nil {
		return data, err
	}
	fmt.Println()
	data.PlantNr = user.PlantNr
	data.Disabled = true
	data.Descr = plantInfo.Abrevname
	data.Childrens = workLineLi
	return data, nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/base/WorkLineService.WorkLineScheduler
 *
 ******************************************************************************/
func (impl *WorkLineServiceImplement) WorkLineScheduler(user *global.User, worklineid string, startDate time.Time, endDate time.Time) (schedule.SchedulerSrv, error) {

	grmi.Log(user, "/services/base/implments/WorkLine.service.impl.go", "WorkLineScheduler", "一键调度排程")

	var (
		schedeng schedule.SchedulerSrv
		err      error
	)
	endDate = endDate.Add(1 * time.Second)
	schedeng = schedule.SchedulerSrv{PlantNr: user.PlantNr, StartDate: startDate, EndDate: endDate}
	schedeng.Tmsrv.StartDate = startDate
	schedeng.Tmsrv.EndDate = endDate
	// 加载激活的项目主数据
	err = schedeng.LoadProjectData()
	if err != nil {
		return schedeng, err
	}
	// 加载时间模型，基于调度引擎指定的时间区间
	schedeng.LoadTimeModelData(worklineid)
	// 加载产品换型主数据
	err = schedeng.LoadSetupData()
	if err != nil {
		return schedeng, err
	}
	// 加载产线主数据
	err = schedeng.LoadWorkLineData(worklineid)
	if err != nil {
		return schedeng, err
	}
	// 加载产线班组计划出勤数据
	err = schedeng.LoadWorkLineWorkShiftData()
	if err != nil {
		return schedeng, err
	}
	// 生成产线的时间曲线
	err = schedeng.GenerateWorkLineTimeCurve()
	if err != nil {
		return schedeng, err
	}
	// 加载工单数据（调度任务）
	err = schedeng.LoadSchedTaskData(worklineid)
	if err != nil {
		return schedeng, err
	}
	// 对调度任务进行排序
	schedeng.SortUnplannedTask()
	// 依次调度未计划工单
	err = schedeng.AutoSchedule()
	if err != nil {
		return schedeng, err
	}
	//计算产线负载
	schedeng.WorklineDict[worklineid].CalDailyWorkload()
	//从未计划任务中移除
	TemUnData := make([]schedule.TaskSrv, 0)
	//添加到已计划中
	for _, v := range schedeng.UnPlannedTaskArray {
		schedeng.PlannedTaskArray = append(schedeng.PlannedTaskArray, v)
	}
	schedeng.UnPlannedTaskArray = TemUnData

	//保存到mongodb里
	data, _ := json.Marshal(schedeng)
	dao := cacheDal.NewSchedulerCacheDAO()
	cacheInfo := new(cacheModel.SchedulerCache)
	cacheInfo.TaskId = uuid.New().String()
	cacheInfo.WorkLineId = worklineid
	cacheInfo.Data = string(data)
	cacheInfo.CreateBy = user.UserId
	cacheInfo.CreateTime = utils.TimeFormat(time.Now(), "yyyy-MM-dd HH:mm:ss")
	_, err = dao.InsertOne(cacheInfo)
	if err == nil {
		schedeng.TaskId = cacheInfo.TaskId
	}
	return schedeng, nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/base/WorkLineService.WorkLineSchedulerManPower
 *
 ******************************************************************************/
func (impl *WorkLineServiceImplement) WorkLineSchedulerManPower(user *global.User, worklineid string, startDate time.Time, endDate time.Time) (schedule.SchedulerSrv, error) {

	grmi.Log(user, "/services/base/implments/WorkLine.service.impl.go", "WorkLineSchedulerManPower", "人工调度排程")

	var (
		schedulerEngine schedule.SchedulerSrv
		err             error
	)
	endDate = endDate.Add(1 * time.Second)
	schedulerEngine = schedule.SchedulerSrv{PlantNr: user.PlantNr, StartDate: startDate, EndDate: endDate}
	schedulerEngine.Tmsrv.StartDate = startDate
	schedulerEngine.Tmsrv.EndDate = endDate
	// 加载激活的项目主数据
	err = schedulerEngine.LoadProjectData()
	if err != nil {
		return schedulerEngine, err
	}
	// 加载时间模型，基于调度引擎指定的时间区间
	err = schedulerEngine.LoadTimeModelData(worklineid)
	if err != nil {
		return schedulerEngine, err
	}
	// 加载产品换型主数据
	err = schedulerEngine.LoadSetupData()
	if err != nil {
		return schedulerEngine, err
	}
	// 加载产线主数据
	err = schedulerEngine.LoadWorkLineData(worklineid)
	if err != nil {
		return schedulerEngine, err
	}
	// 加载产线班组计划出勤数据
	err = schedulerEngine.LoadWorkLineWorkShiftData()
	if err != nil {
		return schedulerEngine, err
	}
	// 生成产线的时间曲线
	err = schedulerEngine.GenerateWorkLineTimeCurve()
	if err != nil {
		return schedulerEngine, err
	}
	// 加载工单数据（调度任务）
	err = schedulerEngine.LoadSchedTaskData(worklineid)
	if err != nil {
		return schedulerEngine, err
	}
	// 对调度任务进行排序
	schedulerEngine.SortUnplannedTask()
	// 依次调度未计划工单
	err = schedulerEngine.ManPowerSchedule()
	if err != nil {
		return schedulerEngine, err
	}
	//计算产线负载
	schedulerEngine.WorklineDict[worklineid].CalDailyWorkload()
	//保存到mongodb里
	data, _ := json.Marshal(schedulerEngine)
	dao := cacheDal.NewSchedulerCacheDAO()
	cacheInfo := new(cacheModel.SchedulerCache)
	cacheInfo.TaskId = uuid.New().String()
	cacheInfo.WorkLineId = worklineid
	cacheInfo.Data = string(data)
	cacheInfo.CreateBy = user.UserId
	cacheInfo.CreateTime = utils.TimeFormat(time.Now(), "yyyy-MM-dd HH:mm:ss")
	_, err = dao.InsertOne(cacheInfo)
	if err == nil {
		schedulerEngine.TaskId = cacheInfo.TaskId
	}
	return schedulerEngine, nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/base/WorkLineService.WorkLineSchedulerManualr
 *
 ******************************************************************************/
func (impl *WorkLineServiceImplement) WorkLineSchedulerManualr(user *global.User, data schedule.SchedulerSrv) (schedule.SchedulerSrv, error) {

	grmi.Log(user, "/services/base/implments/WorkLine.service.impl.go", "WorkLineSchedulerManualr", "手动移动调度排程")
	var (
		schedeng schedule.SchedulerSrv
		err      error
	)
	//第一步:查询当前的任务信息
	dao := cacheDal.NewSchedulerCacheDAO()
	cacheData := new(cacheModel.SchedulerCache)
	cacheData.TaskId = data.TaskId
	result, err := dao.SelectOne(cacheData)
	if err != nil {
		return schedeng, err
	}
	err = json.Unmarshal([]byte(result.Data), &schedeng)
	if err != nil {
		return schedeng, err
	}

	//判断移动的任务状态
	if data.ManualPlannedTask.Status > model.WO_STATUS_PLANNED {
		return schedeng, errors.New("工单状态大于20,无法移除！")
	}
	//第二步:根据操作，更新计划任务
	switch data.Operation {
	case "UP":
		//注释:前端传的Duration错误，目前先用这个方法取值
		var Duration time.Duration
		for _, v := range schedeng.UnPlannedTaskArray {
			if v.TaskId == data.ManualPlannedTask.TaskId {
				Duration = v.Duration
				break
			}
		}
		/******
		*注释:对任务进行排序
		*实现方法：
		*第一步：把SchedStartTime转成unix()时间格式，
		*第二步：构造成一个unix()时间的map数组
		*第三步：按照unix()时间取对应的map值，构建新的[]schedule.TaskSrv
		*****************/
		isJoin := false
		//校验是否已经存在
		TemData := make([]schedule.TaskSrv, 0)
		for _, v := range data.PlannedTaskArray {
			if v.TaskId == data.ManualPlannedTask.TaskId {
				isJoin = true
				continue
			}
			TemData = append(TemData, v)
		}
		if !isJoin {
			//不存在添加
			data.ManualPlannedTask.Duration = Duration
			TemData = append(TemData, data.ManualPlannedTask)
		}
		//排序
		var unixSorts []int
		mapData := make(map[int]schedule.TaskSrv)
		for _, v := range TemData {
			unixTime := int(v.SchedStartTime.Unix())
			unixSorts = append(unixSorts, unixTime)
			mapData[unixTime] = v
		}
		sort.Ints(unixSorts)
		resultData := make([]schedule.TaskSrv, 0)
		for _, v := range unixSorts {
			key := v
			resultData = append(resultData, mapData[key])
		}
		//添加到计划任务中
		schedeng.PlannedTaskArray = resultData

		//从未计划任务中移除
		TemUnData := make([]schedule.TaskSrv, 0)
		for _, v := range data.UnPlannedTaskArray {
			if v.TaskId == data.ManualPlannedTask.TaskId {
				continue
			}
			TemUnData = append(TemUnData, v)
		}
		schedeng.UnPlannedTaskArray = TemUnData
		break
	case "DOWN":
		//从已计划的队列中移除
		TemData := make([]schedule.TaskSrv, 0)
		for _, v := range data.PlannedTaskArray {
			if v.TaskId == data.ManualPlannedTask.TaskId {
				continue
			}
			TemData = append(TemData, v)
		}
		schedeng.PlannedTaskArray = TemData
		//添加到未计划中
		isJoin := false
		TemUnData := make([]schedule.TaskSrv, 0)
		for _, v := range data.UnPlannedTaskArray {
			if v.TaskId == data.ManualPlannedTask.TaskId {
				isJoin = true
				continue
			}
			TemUnData = append(TemUnData, v)
		}
		if !isJoin {
			//不存在添加
			TemUnData = append(TemUnData, data.ManualPlannedTask)
		}
		//添加到计划任务中
		schedeng.UnPlannedTaskArray = TemUnData
		break
	case "MOVE":
		TemData := make([]schedule.TaskSrv, 0)
		//替换当前已计划的任务
		for _, v := range data.PlannedTaskArray {
			if v.TaskId == data.ManualPlannedTask.TaskId {
				TemData = append(TemData, data.ManualPlannedTask)
			} else {
				TemData = append(TemData, v)
			}
		}

		//排序
		var unixSorts []int
		mapData := make(map[int]schedule.TaskSrv)
		for _, v := range TemData {
			unixTime := int(v.SchedStartTime.Unix())
			unixSorts = append(unixSorts, unixTime)
			mapData[unixTime] = v
		}
		sort.Ints(unixSorts)
		resultData := make([]schedule.TaskSrv, 0)
		for _, v := range unixSorts {
			key := v
			resultData = append(resultData, mapData[key])
		}
		//添加到计划任务中
		schedeng.PlannedTaskArray = resultData
		break
	default:
		return schedeng, errors.New("操作类型错误！")

	}

	// 获取产线对象
	_, ok := schedeng.WorklineDict[result.WorkLineId]
	if ok {
		//重新计算(相当于置位)
		TemData := make([]schedule.TaskSrv, 0)
		schedeng.WorklineDict[result.WorkLineId].SchedTaskArray = TemData
		schedeng.WorklineDict[result.WorkLineId].SchedTimeCurve = schedeng.WorklineDict[result.WorkLineId].TimeCurve
		schedeng.WorklineDict[result.WorkLineId].SchedTimeCurve.GetLineList()
	}
	//第三步:生成调度
	err = schedeng.ManualrSchedule()
	if err != nil {
		return schedeng, err
	}
	//计算产线负载
	schedeng.WorklineDict[result.WorkLineId].CalDailyWorkload()
	//保存到mongodb里
	dataTem, _ := json.Marshal(schedeng)
	cacheInfo := new(cacheModel.SchedulerCache)
	cacheInfo.TaskId = data.TaskId
	cacheInfo.WorkLineId = result.WorkLineId
	cacheInfo.Data = string(dataTem)
	cacheInfo.CreateBy = user.UserId
	cacheInfo.CreateTime = utils.TimeFormat(time.Now(), "yyyy-MM-dd HH:mm:ss")
	err = dao.UpdateOne(cacheInfo)
	if err == nil {
		schedeng.TaskId = cacheInfo.TaskId
	}
	return schedeng, nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/base/WorkLineService.WorkLineRepairSchedule
 *
 ******************************************************************************/
func (impl *WorkLineServiceImplement) WorkLineRepairSchedule(user *global.User, data schedule.SchedulerSrv) (schedule.SchedulerSrv, error) {

	grmi.Log(user, "/services/base/implments/WorkLine.service.impl.go", "WorkLineSchedulerManualr", "手动移动调度排程")
	var (
		schedeng schedule.SchedulerSrv
		err      error
	)
	//第一步:查询当前的任务信息
	dao := cacheDal.NewSchedulerCacheDAO()
	cacheData := new(cacheModel.SchedulerCache)
	cacheData.TaskId = data.TaskId
	result, err := dao.SelectOne(cacheData)
	if err != nil {
		return schedeng, err
	}
	err = json.Unmarshal([]byte(result.Data), &schedeng)
	if err != nil {
		return schedeng, err
	}

	// 获取产线对象
	_, ok := schedeng.WorklineDict[result.WorkLineId]
	if ok {
		//排序
		var unixSorts []int
		mapData := make(map[int]schedule.TaskSrv)
		for _, v := range schedeng.WorklineDict[result.WorkLineId].SchedTaskArray {
			unixTime := int(v.SchedStartTime.Unix())
			unixSorts = append(unixSorts, unixTime)
			mapData[unixTime] = v
		}
		sort.Ints(unixSorts)
		resultData := make([]schedule.TaskSrv, 0)
		for _, v := range unixSorts {
			key := v
			resultData = append(resultData, mapData[key])
		}
		//添加到计划任务中
		schedeng.WorklineDict[result.WorkLineId].SchedTaskArray = resultData

		//第三步:生成调度
		err = schedeng.RepairSchedule(result.WorkLineId)
		if err != nil {
			return schedeng, err
		}
		//计算产线负载
		schedeng.WorklineDict[result.WorkLineId].CalDailyWorkload()
	}

	//保存到mongodb里
	dataTem, _ := json.Marshal(schedeng)
	cacheInfo := new(cacheModel.SchedulerCache)
	cacheInfo.TaskId = data.TaskId
	cacheInfo.WorkLineId = result.WorkLineId
	cacheInfo.Data = string(dataTem)
	cacheInfo.CreateBy = user.UserId
	cacheInfo.CreateTime = utils.TimeFormat(time.Now(), "yyyy-MM-dd HH:mm:ss")
	err = dao.UpdateOne(cacheInfo)
	if err == nil {
		schedeng.TaskId = cacheInfo.TaskId
	}
	return schedeng, nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/base/WorkLineService.SaveWorkLineScheduler
 *
 ******************************************************************************/
func (impl *WorkLineServiceImplement) SaveWorkLineScheduler(user *global.User, data schedule.SchedulerData) error {

	grmi.Log(user, "/services/base/implments/WorkLine.service.impl.go", "SaveWorkLineScheduler", "保存调度结果")
	var err error
	//开启事务
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	err = session.Begin()
	if err != nil {
		return err
	}
	custOrderDao := plnDal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
	custOrderStatusDao := plnDal.NewCustOrderStatusDAO(session, user.PlantNr, user.UserId)
	custOrderStatusHistoryDao := plnDal.NewCustOrderStatusHistoryDAO(session, user.PlantNr, user.UserId)
	//如果存在已计划的订单
	for _, plannedTask := range data.PlannedTaskArray {
		//过滤订单状态大于20的订单
		if plannedTask.CustOrderStatus.Status > model.WO_STATUS_PLANNED {
			continue
		}
		//1.更新CustOrder表的时间
		updateCustOrder := new(plnModel.CustOrder)
		updateCustOrder.PlantNr = plannedTask.PlantNr
		updateCustOrder.CustOrderId = plannedTask.TaskId
		updateCustOrder.PlanStartDate = grmi.Date(plannedTask.SchedStartTime)
		updateCustOrder.PlanEndDate = grmi.Date(plannedTask.SchedEndTime)
		updateCustOrder.PlanStartTime = grmi.DateTime(plannedTask.SchedStartTime)
		updateCustOrder.PlanEndTime = grmi.DateTime(plannedTask.SchedEndTime)
		updateCustOrder.LastModify = grmi.DateTime(time.Now())
		updateCustOrder.LastUser = user.UserId
		err = custOrderDao.UpdateOneInfo(updateCustOrder)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新客户订单失败, 客户订单ID:" + updateCustOrder.CustOrderId + ", error:" + err.Error())
		}
		//2.更新CustOrderStatus表的状态
		custOrderStatus := new(plnModel.CustOrderStatus)
		custOrderStatus.PlantNr = plannedTask.PlantNr
		custOrderStatus.CustOrderId = plannedTask.TaskId
		custOrderStatus.Status = model.WO_STATUS_PLANNED
		custOrderStatus.LastModify = grmi.DateTime(time.Now())
		custOrderStatus.LastUser = user.UserId
		err = custOrderStatusDao.UpdateOneInfo(custOrderStatus)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新客户订单状态失败, 客户订单ID:" + plannedTask.TaskId + ", error:" + err.Error())
		}

		//3.添加CustOrderHistory表的变更记录
		//maxPos, err := custOrderStatusHistoryDao.GetMaxPos(plannedTask.TaskId)
		//if err != nil {
		//	_ = session.Rollback()
		//	return grmi.NewBusinessError("获取客户订单状态变更记录位置失败,, 客户订单ID:" + plannedTask.TaskId + ", error:" + err.Error())
		//}
		statusHistory := &plnModel.CustOrderStatusHistory{
			CustOrderId: plannedTask.TaskId,
			//Pos:         maxPos + 1,
			StatusChangeType: plnModel.STATUS__CHANGE_TYPE_SCHUDLER,
			FromStatus: model.WO_STATUS_UNPLANNED,
			ToStatus: model.WO_STATUS_PLANNED,
			ChangeTime: grmi.DateTime(time.Now()),
		}
		err = custOrderStatusHistoryDao.InsertOne(statusHistory)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("保存客户订单状态变更记录失败, 客户订单ID:" + plannedTask.TaskId + "error:" + err.Error())
		}
	}
	for _, task := range data.UnPlannedTaskArray {
		//过滤订单状态大于20的订单
		if task.CustOrderStatus.Status > model.WO_STATUS_PLANNED {
			continue
		}
		//1.更新CustOrder表的时间
		updateCustOrder := new(plnModel.CustOrder)
		updateCustOrder.PlantNr = task.PlantNr
		updateCustOrder.CustOrderId = task.TaskId
		updateCustOrder.PlanStartDate = grmi.Date(task.SchedStartTime)
		updateCustOrder.PlanEndDate = grmi.Date(task.SchedEndTime)
		updateCustOrder.PlanStartTime = grmi.DateTime(task.SchedStartTime)
		updateCustOrder.PlanEndTime = grmi.DateTime(task.SchedEndTime)
		updateCustOrder.LastModify = grmi.DateTime(time.Now())
		updateCustOrder.LastUser = user.UserId
		err = custOrderDao.UpdateOneInfo(updateCustOrder)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新客户订单失败, 客户订单ID:" + updateCustOrder.CustOrderId + ", error:" + err.Error())
		}
		//2.更新CustOrderStatus表的状态
		custOrderStatus := new(plnModel.CustOrderStatus)
		custOrderStatus.PlantNr = task.PlantNr
		custOrderStatus.CustOrderId = task.TaskId
		custOrderStatus.Status = model.WO_STATUS_UNPLANNED
		custOrderStatus.LastModify = grmi.DateTime(time.Now())
		custOrderStatus.LastUser = user.UserId
		err = custOrderStatusDao.UpdateOneInfo(custOrderStatus)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("更新客户订单状态失败, 客户订单ID:" + task.TaskId + ", error:" + err.Error())
		}

		//3.添加WorkOrderStatusRecLst表的变更记录
		//maxPos, err := custOrderStatusHistoryDao.GetMaxPos(task.TaskId)
		//if err != nil {
		//	_ = session.Rollback()
		//	return grmi.NewBusinessError("获取客户订单状态变更记录位置失败,, 客户订单ID:" + task.TaskId + ", error:" + err.Error())
		//}
		statusHistory := &plnModel.CustOrderStatusHistory{
			CustOrderId: task.TaskId,
			//Pos:         maxPos + 1,
			StatusChangeType: plnModel.STATUS__CHANGE_TYPE_SCHUDLER,
			FromStatus: model.WO_STATUS_PLANNED,
			ToStatus: model.WO_STATUS_UNPLANNED,
			ChangeTime: grmi.DateTime(time.Now()),
		}
		err = custOrderStatusHistoryDao.InsertOne(statusHistory)
		if err != nil {
			_ = session.Rollback()
			return grmi.NewBusinessError("保存客户订单状态变更记录失败, 客户订单ID:" + task.TaskId + "error:" + err.Error())
		}
	}
	_ = session.Commit()
	return nil
}

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/base/WorkLineService.SelectVirtualWorkLine
 *
 ******************************************************************************/
func (impl *WorkLineServiceImplement) SelectVirtualWorkLine(user *global.User) ([]model.WorkLine, error) {

	grmi.Log(user, "/services/base/implments/WorkLine.service.impl.go", "SelectVirtualWorkLine", "查询虚拟产线")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	dao := dal.NewWorkLineDAO(session, user.PlantNr, user.UserId)
	workLineLi, err := dao.Select([]grmi.Predicate{
		meta.WorkLine_GroupType.NewPredicate(grmi.Equal, model.WORK_LINE_TYPE_GROUP),
	}, []grmi.Field{meta.WorkLine_WorkLineid})
	return workLineLi, err
}