package implments

import (
	baseDal "LAPP_ACURA_MOM_BACKEND/dao/base"
	jitDal "LAPP_ACURA_MOM_BACKEND/dao/jit"
	meDal "LAPP_ACURA_MOM_BACKEND/dao/me"
	omDal "LAPP_ACURA_MOM_BACKEND/dao/om"
	dal "LAPP_ACURA_MOM_BACKEND/dao/pln"
	qmDal "LAPP_ACURA_MOM_BACKEND/dao/qm"
	"LAPP_ACURA_MOM_BACKEND/db"
	"LAPP_ACURA_MOM_BACKEND/global"
	"LAPP_ACURA_MOM_BACKEND/grmi"
	baseMeta "LAPP_ACURA_MOM_BACKEND/meta/base"
	meta "LAPP_ACURA_MOM_BACKEND/meta/pln"
	qmMeta "LAPP_ACURA_MOM_BACKEND/meta/qm"
	baseModel "LAPP_ACURA_MOM_BACKEND/models/base"
	meModel "LAPP_ACURA_MOM_BACKEND/models/me"
	omModel "LAPP_ACURA_MOM_BACKEND/models/om"
	model "LAPP_ACURA_MOM_BACKEND/models/pln"
	"LAPP_ACURA_MOM_BACKEND/utils"
	"container/list"
	"errors"
	"strconv"
	"sync"
	"time"
)

/******************************************************************************
 *
 * @Reference LAPP_ACURA_MOM_BACKEND/services/pln/CustOrderService.Select
 *
 ******************************************************************************/
func (impl *CustOrderServiceImplement) Dashboard(user *global.User, workLineId string) (interface{}, error) {
	grmi.Log(user, "/services/pln/implments/CustOrder.service.impl.go", "SelectCustOrder", "查询CustOrder")

	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	daoWorkLine := baseDal.NewWorkLineDAO(session, user.PlantNr, user.UserId)
	daoDayModel := baseDal.NewDayModelDAO(session, user.PlantNr, user.UserId)
	//daoWeekModel := baseDal.NewWeekModelLstDAO(session, user.PlantNr, user.UserId)
	daoWeekModelLst := baseDal.NewWeekModelLstDAO(session, user.PlantNr, user.UserId)
	//daoWorkCalendar := baseDal.NewWorkCalendarDAO(session, user.PlantNr, user.UserId)
	daoWorkCalendarLst := baseDal.NewWorkCalendarLstDAO(session, user.PlantNr, user.UserId)
	daoWorkShift := baseDal.NewWorkShiftDAO(session, user.PlantNr, user.UserId)
	dashlisDao := baseDal.NewRPDashBoardLstDAO(session, user.PlantNr, user.UserId)
	dashlist, err := dashlisDao.Select([]grmi.Predicate{baseMeta.RPDashBoardLst_DashboardId.NewPredicate(grmi.Equal, 1)}, nil)
	if err != nil {
		return nil, err
	}
	var personNum int    //当班人数
	var timeBeat float64 //节拍
	var days int         //展示天数
	var ippmTarge int    //IPPM
	for _, v := range dashlist {
		if v.ParamName == "TimeBeat" {
			timeBeat = v.FloatParam1
		}
		if v.ParamName == "PersonNum" {
			personNum = v.IntParam1
		}
		if v.ParamName == "Days" {
			days = v.IntParam1
		}
		if v.ParamName == "IppmTarge" {
			ippmTarge = v.IntParam1
		}
	}
	if personNum <= 0 {
		return nil, errors.New("当班人数不能为空!")
	}
	if timeBeat <= 0 {
		return nil, errors.New("节拍不能为空!")
	}
	if days <= 0 {
		return nil, errors.New("日期长度不能为空!")
	}
	// 获取产线今天的时间模型
	workLine, err := daoWorkLine.SelectOne(workLineId)
	if err != nil {
		return nil, grmi.NewBusinessError("查询产线失败, error:" + err.Error())
	}
	if workLine == nil {
		return nil, grmi.NewBusinessError("产线不存在")
	}
	var dayModelNr int
	// 优先使用产线工作日历
	if workLine.WorkCalendarNr != 0 {
		workCalendarLstLi, err := daoWorkCalendarLst.Select([]grmi.Predicate{baseMeta.WorkCalendarLst_WorkCalendarNr.NewPredicate(grmi.Equal, workLine.WorkCalendarNr)}, []grmi.Field{baseMeta.WorkCalendarLst_WorkDate})
		if err != nil {
			return nil, grmi.NewBusinessError("查询产线工作日历子项失败, error:" + err.Error())
		}
		for _, workCalendarLst := range workCalendarLstLi {
			if workCalendarLst.WorkDate == grmi.Date(time.Now()) {
				dayModelNr = workCalendarLst.DayModelNr
				break
			}
		}
	}
	// 如果产线工作日不存在当天 则使用周模型
	if dayModelNr == 0 {
		weekModelLstLi, err := daoWeekModelLst.Select([]grmi.Predicate{baseMeta.WeekModelLst_WeekModelNr.NewPredicate(grmi.Equal, workLine.WeekModelNr)}, []grmi.Field{baseMeta.WeekModelLst_WorkDate})
		if err != nil {
			return nil, grmi.NewBusinessError("查询周模型子项失败, error:" + err.Error())
		}
		weeKDay := time.Now().Weekday()
		for _, weekModelLst := range weekModelLstLi {
			if weekModelLst.WorkDate.Restore().Weekday() == weeKDay {
				dayModelNr = weekModelLst.DayModelNr
				break
			}
		}
	}
	if dayModelNr == 0 {
		return nil, grmi.NewBusinessError("未获取到匹配今天的时间模型")
	}
	dayModel, err := daoDayModel.SelectOne(dayModelNr)
	if err != nil {
		return nil, grmi.NewBusinessError("查询日模型失败, error:" + err.Error())
	}
	if dayModel == nil {
		return nil, grmi.NewBusinessError("关联的日模型不存在")
	}
	var dayModelStartTime int
	var dayModelEndTime int
	nowTime := time.Now()
	var WorkShift int
	_ = WorkShift
	//构建开始时间和结束时间
	startDayTime := utils.GetZeroTime(time.Now())
	if dayModel.WorkShiftToggle {
		if dayModel.S1WorkShiftNr == 0 {
			return nil, grmi.NewBusinessError("绑定的日模型错误")
		}

		s1WorkShift, err := daoWorkShift.SelectOne(dayModel.S1WorkShiftNr)
		if err != nil {
			return nil, err
		}
		if s1WorkShift != nil {
			if dayModelStartTime > 0 {
				if dayModelStartTime > dayModel.S1Beg {
					dayModelStartTime = dayModel.S1Beg
				}
			} else {
				dayModelStartTime = dayModel.S1Beg
			}
			if dayModelEndTime != 0 {
				if dayModelEndTime < dayModel.S1End {
					dayModelEndTime = dayModel.S1End
				}
			} else {
				dayModelEndTime = dayModel.S1End
			}
			dayModelStartHour1 := startDayTime.Add(time.Duration(dayModel.S1Beg) * time.Second)
			dayModelEndHour1 := startDayTime.Add(time.Duration(dayModel.S1End) * time.Second)
			if nowTime.Unix() >= dayModelStartHour1.Unix() && nowTime.Unix() <= dayModelEndHour1.Unix() {
				WorkShift = 1
			}
		}

		if dayModel.S2WorkShiftNr != 0 {
			s2WorkShift, err := daoWorkShift.SelectOne(dayModel.S2WorkShiftNr)
			if err != nil {
				return nil, err
			}
			if s2WorkShift != nil {
				dayModel.S2WorkShift = *s2WorkShift
				if dayModelStartTime > 0 {
					if dayModelStartTime > dayModel.S2Beg {
						dayModelStartTime = dayModel.S2Beg
					}
				} else {
					dayModelStartTime = dayModel.S2Beg
				}
				if dayModelEndTime != 0 {
					if dayModelEndTime < dayModel.S2End {
						dayModelEndTime = dayModel.S2End
					}
				} else {
					dayModelEndTime = dayModel.S2End
				}

				dayModelStartHour2 := startDayTime.Add(time.Duration(dayModel.S2Beg) * time.Second)
				dayModelEndHour2 := startDayTime.Add(time.Duration(dayModel.S2End) * time.Second)
				if nowTime.Unix() >= dayModelStartHour2.Unix() && nowTime.Unix() <= dayModelEndHour2.Unix() {
					WorkShift = 2
				}
			}

		}
		if dayModel.S3WorkShiftNr != 0 {
			s3WorkShift, err := daoWorkShift.SelectOne(dayModel.S3WorkShiftNr)
			if err != nil {
				return nil, err
			}
			if s3WorkShift != nil {
				dayModel.S3WorkShift = *s3WorkShift

				if dayModelStartTime > 0 {
					if dayModelStartTime > dayModel.S3Beg {
						dayModelStartTime = dayModel.S3Beg
					}
				} else {
					dayModelStartTime = dayModel.S3Beg
				}
				if dayModelEndTime != 0 {
					if dayModelEndTime < dayModel.S3End {
						dayModelEndTime = dayModel.S3End
					}
				} else {
					dayModelEndTime = dayModel.S3End
				}
				dayModelStartHour3 := startDayTime.Add(time.Duration(dayModel.S3Beg) * time.Second)
				dayModelEndHour3 := startDayTime.Add(time.Duration(dayModel.S3End) * time.Second)
				if nowTime.Unix() >= dayModelStartHour3.Unix() && nowTime.Unix() <= dayModelEndHour3.Unix() {
					WorkShift = 3
				}
			}

		}
	} else {
		if dayModelStartTime > 0 {
			if dayModelStartTime > dayModel.S1Beg {
				dayModelStartTime = dayModel.S1Beg
			}
		} else {
			dayModelStartTime = dayModel.S1Beg
		}
		if dayModelEndTime != 0 {
			if dayModelEndTime < dayModel.S1End {
				dayModelEndTime = dayModel.S1End
			}
		} else {
			dayModelEndTime = dayModel.S1End
		}
		dayModelStartHour1 := startDayTime.Add(time.Duration(dayModel.S1Beg) * time.Second)
		dayModelEndHour1 := startDayTime.Add(time.Duration(dayModel.S1End) * time.Second)
		if nowTime.Unix() >= dayModelStartHour1.Unix() && nowTime.Unix() <= dayModelEndHour1.Unix() {
			WorkShift = 1
		}

		if dayModelStartTime > 0 {
			if dayModelStartTime > dayModel.S2Beg {
				dayModelStartTime = dayModel.S2Beg
			}
		} else {
			dayModelStartTime = dayModel.S2Beg
		}
		if dayModelEndTime != 0 {
			if dayModelEndTime < dayModel.S2End {
				dayModelEndTime = dayModel.S2End
			}
		} else {
			dayModelEndTime = dayModel.S2End
		}

		dayModelStartHour2 := startDayTime.Add(time.Duration(dayModel.S2Beg) * time.Second)
		dayModelEndHour2 := startDayTime.Add(time.Duration(dayModel.S2End) * time.Second)
		if nowTime.Unix() >= dayModelStartHour2.Unix() && nowTime.Unix() <= dayModelEndHour2.Unix() {
			WorkShift = 2
		}

		if dayModelStartTime > 0 {
			if dayModelStartTime > dayModel.S3Beg {
				dayModelStartTime = dayModel.S3Beg
			}
		} else {
			dayModelStartTime = dayModel.S3Beg
		}
		if dayModelEndTime != 0 {
			if dayModelEndTime < dayModel.S3End {
				dayModelEndTime = dayModel.S3End
			}
		} else {
			dayModelEndTime = dayModel.S3End
		}
		dayModelStartHour3 := startDayTime.Add(time.Duration(dayModel.S3Beg) * time.Second)
		dayModelEndHour3 := startDayTime.Add(time.Duration(dayModel.S3End) * time.Second)
		if nowTime.Unix() >= dayModelStartHour3.Unix() && nowTime.Unix() <= dayModelEndHour3.Unix() {
			WorkShift = 3
		}
	}
	if dayModelEndTime < dayModelStartTime {
		return nil, errors.New("日模型开始时间大于结束时间")
	}
	dayModelStartHour := startDayTime.Add(time.Duration(dayModelStartTime) * time.Second)
	dayModelEndHour := startDayTime.Add(time.Duration(dayModelEndTime) * time.Second)
	endDayTime := utils.GetZeroTime(time.Now().AddDate(0, 0, 1))

	DayModelHours, err := utils.GetHoursData(dayModelStartHour, dayModelEndHour)
	if err != nil {
		return nil, err
	}
	DashboardData := model.DashboardPic{}
	var err1, err2, err3, err4, err5, err6 error
	var wg sync.WaitGroup
	wg.Add(6)
	//图例001
	go func(wg *sync.WaitGroup) {
		DashboardData.DashboardDataPic1, err1 = impl.SelectPic1(user, dayModel, workLineId)
		wg.Done() // 操作完成，减少一个计数
	}(&wg)
	//图例002
	go func(wg *sync.WaitGroup) {
		DashboardData.DashboardDataPic2, err2 = impl.SelectDefectNumber(user, days, workLineId)
		wg.Done() // 操作完成，减少一个计数
	}(&wg)
	//图例003
	go func(wg *sync.WaitGroup) {
		DashboardData.DashboardDataPic3, err3 = impl.SelectPic3(user, DayModelHours, dayModel, startDayTime, endDayTime, timeBeat, personNum, workLineId)
		wg.Done() // 操作完成，减少一个计数
	}(&wg)
	//图例004
	go func(wg *sync.WaitGroup) {
		DashboardData.DashboardDataPic4, err4 = impl.CountTarget(user, workLineId)
		wg.Done() // 操作完成，减少一个计数
	}(&wg)
	//计算当前节拍,及其平均
	go func(wg *sync.WaitGroup) {
		DashboardData.TeamTemPo, DashboardData.PerHourTemPo, err5 = impl.SelectTeamTemPo(user, dayModel, personNum, startDayTime, WorkShift, workLineId)
		wg.Done() // 操作完成，减少一个计数
	}(&wg)
	go func(wg *sync.WaitGroup) {
		DashboardData.DashboardDataStatus, err6 = impl.SelectAndonInfo(user)
		wg.Done() // 操作完成，减少一个计数
	}(&wg)
	wg.Wait()
	if err1 != nil {
		return nil, err1
	}
	if err2 != nil {
		return nil, err2
	}
	if err3 != nil {
		return nil, err3
	}

	if err4 != nil {
		return nil, err4
	}

	if err5 != nil {
		return nil, err5
	}

	if err6 != nil {
		return nil, err6
	}
	//当班人数
	DashboardData.TemPoPerson = personNum
	//节拍
	DashboardData.CurrentTempo = timeBeat
	DashboardData.IppmTarge = ippmTarge

	DashboardData.DateTimeNow = utils.TimeFormat(time.Now(), "yyyy-MM-dd HH:00")
	return DashboardData, err

}

// InitDayModelList 生成日模型时间双向连表
func (impl *CustOrderServiceImplement) InitDayModelList(dayModel *baseModel.DayModel, date time.Time) *list.List {
	dayModelList := list.New()
	dayModelList = dayModelList.Init()
	var element model.ListElement
	if dayModel.WorkShiftToggle {
		s1WorkShift := dayModel.S1WorkShift
		s2WorkShift := dayModel.S2WorkShift
		s3WorkShift := dayModel.S3WorkShift
		element.Start = date.Add(time.Duration(s1WorkShift.SBeg) * time.Second)
		if s1WorkShift.SB1Beg != 0 {
			var end time.Time
			element.End = date.Add(time.Duration(s1WorkShift.SB1Beg) * time.Second)
			element.Duration = element.End.Sub(element.Start)
			dayModelList.PushBack(element)
			end = date.Add(time.Duration(s1WorkShift.SB1End) * time.Second)
			if s1WorkShift.SB2Beg != 0 {
				element.Start = end
				element.End = date.Add(time.Duration(s1WorkShift.SB2Beg) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
				end = date.Add(time.Duration(s1WorkShift.SB2End) * time.Second)
			}
			if s1WorkShift.SB3Beg != 0 {
				element.Start = end
				element.End = date.Add(time.Duration(s1WorkShift.SB3Beg) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
				end = date.Add(time.Duration(s1WorkShift.SB3End) * time.Second)
			}
			if s1WorkShift.SB4Beg != 0 {
				element.Start = end
				element.End = date.Add(time.Duration(s1WorkShift.SB4Beg) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
				end = date.Add(time.Duration(s1WorkShift.SB4End) * time.Second)
			}
			if s1WorkShift.SB5Beg != 0 {
				element.Start = end
				element.End = date.Add(time.Duration(s1WorkShift.SB5Beg) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
				end = date.Add(time.Duration(s1WorkShift.SB5End) * time.Second)
			}
			element.Start = end
			element.End = date.Add(time.Duration(s1WorkShift.SEnd) * time.Second)
			element.Duration = element.End.Sub(element.Start)
			dayModelList.PushBack(element)
		} else {
			element.End = date.Add(time.Duration(s1WorkShift.SEnd) * time.Second)
			element.Duration = element.End.Sub(element.Start)
			dayModelList.PushBack(element)
		}
		if s2WorkShift.SB1Beg != 0 {
			var end time.Time
			element.End = date.Add(time.Duration(s2WorkShift.SB1Beg) * time.Second)
			element.Duration = element.End.Sub(element.Start)
			dayModelList.PushBack(element)
			end = date.Add(time.Duration(s2WorkShift.SB1End) * time.Second)
			if s2WorkShift.SB2Beg != 0 {
				element.Start = end
				element.End = date.Add(time.Duration(s2WorkShift.SB2Beg) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
				end = date.Add(time.Duration(s2WorkShift.SB2End) * time.Second)
			}
			if s2WorkShift.SB3Beg != 0 {
				element.Start = end
				element.End = date.Add(time.Duration(s2WorkShift.SB3Beg) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
				end = date.Add(time.Duration(s2WorkShift.SB3End) * time.Second)
			}
			if s2WorkShift.SB4Beg != 0 {
				element.Start = end
				element.End = date.Add(time.Duration(s2WorkShift.SB4Beg) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
				end = date.Add(time.Duration(s2WorkShift.SB4End) * time.Second)
			}
			if s2WorkShift.SB5Beg != 0 {
				element.Start = end
				element.End = date.Add(time.Duration(s2WorkShift.SB5Beg) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
				end = date.Add(time.Duration(s2WorkShift.SB5End) * time.Second)
			}
			element.Start = end
			element.End = date.Add(time.Duration(s2WorkShift.SEnd) * time.Second)
			element.Duration = element.End.Sub(element.Start)
			dayModelList.PushBack(element)
		} else {
			element.End = date.Add(time.Duration(s2WorkShift.SEnd) * time.Second)
			element.Duration = element.End.Sub(element.Start)
			dayModelList.PushBack(element)
		}
		if s3WorkShift.SB1Beg != 0 {
			var end time.Time
			element.End = date.Add(time.Duration(s3WorkShift.SB1Beg) * time.Second)
			element.Duration = element.End.Sub(element.Start)
			dayModelList.PushBack(element)
			end = date.Add(time.Duration(s3WorkShift.SB1End) * time.Second)
			if s3WorkShift.SB2Beg != 0 {
				element.Start = end
				element.End = date.Add(time.Duration(s3WorkShift.SB2Beg) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
				end = date.Add(time.Duration(s3WorkShift.SB2End) * time.Second)
			}
			if s3WorkShift.SB3Beg != 0 {
				element.Start = end
				element.End = date.Add(time.Duration(s3WorkShift.SB3Beg) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
				end = date.Add(time.Duration(s3WorkShift.SB3End) * time.Second)
			}
			if s3WorkShift.SB4Beg != 0 {
				element.Start = end
				element.End = date.Add(time.Duration(s3WorkShift.SB4Beg) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
				end = date.Add(time.Duration(s3WorkShift.SB4End) * time.Second)
			}
			if s3WorkShift.SB5Beg != 0 {
				element.Start = end
				element.End = date.Add(time.Duration(s3WorkShift.SB5Beg) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
				end = date.Add(time.Duration(s3WorkShift.SB5End) * time.Second)
			}
			element.Start = end
			element.End = date.Add(time.Duration(s3WorkShift.SEnd) * time.Second)
			element.Duration = element.End.Sub(element.Start)
			dayModelList.PushBack(element)
		} else {
			element.End = date.Add(time.Duration(s3WorkShift.SEnd) * time.Second)
			element.Duration = element.End.Sub(element.Start)
			dayModelList.PushBack(element)
		}
	} else {

		element.Start = date.Add(time.Duration(dayModel.S1Beg) * time.Second)
		if dayModel.S1B1Beg != 0 {
			var end time.Time
			element.End = date.Add(time.Duration(dayModel.S1B1Beg) * time.Second)
			element.Duration = element.End.Sub(element.Start)
			dayModelList.PushBack(element)
			end = date.Add(time.Duration(dayModel.S1B1End) * time.Second)
			if dayModel.S1B2Beg != 0 {
				element.Start = end
				element.End = date.Add(time.Duration(dayModel.S1B2Beg) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
				end = date.Add(time.Duration(dayModel.S1B2End) * time.Second)
			}
			if dayModel.S1B3Beg != 0 {
				element.Start = end
				element.End = date.Add(time.Duration(dayModel.S1B3Beg) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
				end = date.Add(time.Duration(dayModel.S1B3End) * time.Second)
			}
			if dayModel.S1B4Beg != 0 {
				element.Start = end
				element.End = date.Add(time.Duration(dayModel.S1B4Beg) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
				end = date.Add(time.Duration(dayModel.S1B4End) * time.Second)
			}
			if dayModel.S1B5Beg != 0 {
				element.Start = end
				element.End = date.Add(time.Duration(dayModel.S1B5Beg) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
				end = date.Add(time.Duration(dayModel.S1B5End) * time.Second)
			}
			element.Start = end
			element.End = date.Add(time.Duration(dayModel.S1End) * time.Second)
			element.Duration = element.End.Sub(element.Start)
			dayModelList.PushBack(element)
		} else {
			element.End = date.Add(time.Duration(dayModel.S1End) * time.Second)
			element.Duration = element.End.Sub(element.Start)
			dayModelList.PushBack(element)
		}
		if dayModel.S2Toggle {
			element.Start = date.Add(time.Duration(dayModel.S2Beg) * time.Second)
			if dayModel.S2B1Beg != 0 {
				var end time.Time
				element.End = date.Add(time.Duration(dayModel.S2B1Beg) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
				end = date.Add(time.Duration(dayModel.S2B1End) * time.Second)
				if dayModel.S2B2Beg != 0 {
					element.Start = end
					element.End = date.Add(time.Duration(dayModel.S2B2Beg) * time.Second)
					element.Duration = element.End.Sub(element.Start)
					dayModelList.PushBack(element)
					end = date.Add(time.Duration(dayModel.S2B2End) * time.Second)
				}
				if dayModel.S2B3Beg != 0 {
					element.Start = end
					element.End = date.Add(time.Duration(dayModel.S2B3Beg) * time.Second)
					element.Duration = element.End.Sub(element.Start)
					dayModelList.PushBack(element)
					end = date.Add(time.Duration(dayModel.S2B3End) * time.Second)
				}
				if dayModel.S2B4Beg != 0 {
					element.Start = end
					element.End = date.Add(time.Duration(dayModel.S2B4Beg) * time.Second)
					element.Duration = element.End.Sub(element.Start)
					dayModelList.PushBack(element)
					end = date.Add(time.Duration(dayModel.S2B4End) * time.Second)
				}
				if dayModel.S2B5Beg != 0 {
					element.Start = end
					element.End = date.Add(time.Duration(dayModel.S2B5Beg) * time.Second)
					element.Duration = element.End.Sub(element.Start)
					dayModelList.PushBack(element)
					end = date.Add(time.Duration(dayModel.S2B5End) * time.Second)
				}
				element.Start = end
				element.End = date.Add(time.Duration(dayModel.S2End) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
			} else {
				element.End = date.Add(time.Duration(dayModel.S2End) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
			}
		}
		if dayModel.S3Toggle {
			element.Start = date.Add(time.Duration(dayModel.S3Beg) * time.Second)
			if dayModel.S3B1Beg != 0 {
				var end time.Time
				element.End = date.Add(time.Duration(dayModel.S3B1Beg) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
				end = date.Add(time.Duration(dayModel.S3B1End) * time.Second)
				if dayModel.S3B2Beg != 0 {
					element.Start = end
					element.End = date.Add(time.Duration(dayModel.S3B2Beg) * time.Second)
					element.Duration = element.End.Sub(element.Start)
					dayModelList.PushBack(element)
					end = date.Add(time.Duration(dayModel.S3B2End) * time.Second)
				}
				if dayModel.S3B3Beg != 0 {
					element.Start = end
					element.End = date.Add(time.Duration(dayModel.S3B3Beg) * time.Second)
					element.Duration = element.End.Sub(element.Start)
					dayModelList.PushBack(element)
					end = date.Add(time.Duration(dayModel.S3B3End) * time.Second)
				}
				if dayModel.S3B4Beg != 0 {
					element.Start = end
					element.End = date.Add(time.Duration(dayModel.S3B4Beg) * time.Second)
					element.Duration = element.End.Sub(element.Start)
					dayModelList.PushBack(element)
					end = date.Add(time.Duration(dayModel.S3B4End) * time.Second)
				}
				if dayModel.S3B5Beg != 0 {
					element.Start = end
					element.End = date.Add(time.Duration(dayModel.S3B5Beg) * time.Second)
					element.Duration = element.End.Sub(element.Start)
					dayModelList.PushBack(element)
					end = date.Add(time.Duration(dayModel.S3B5End) * time.Second)
				}
				element.Start = end
				element.End = date.Add(time.Duration(dayModel.S3End) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
			} else {
				element.End = date.Add(time.Duration(dayModel.S3End) * time.Second)
				element.Duration = element.End.Sub(element.Start)
				dayModelList.PushBack(element)
			}
		}
	}
	return dayModelList
}

// SelectDefectNumber dashboard右上角 查询缺陷数据
func (impl *CustOrderServiceImplement) SelectDefectNumber(user *global.User, days int, workLineId string) ([]model.DefectItem, error) {
	result := make([]model.DefectItem, 0, days)
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	defectRecordDao := qmDal.NewDefectRecordDAO(session, user.PlantNr, user.UserId)
	repairInfoDao := baseDal.NewRepairInfoDAO(session, user.UserId)
	custOrderDao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
	serialOrderDao := omDal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	productFamilyRelateDao := meDal.NewProductFamilyRelateDAO(session, user.PlantNr, user.UserId)
	productFamilyMap := make(map[string]int)
	now := time.Now()
	custOrderMap := make(map[string]*model.CustOrder)
	for i := 0; i < days; i++ {
		var defectItem model.DefectItem
		day := now.AddDate(0, 0, -1*i).Format(grmi.DateOutFormat)
		start := day + " " + "00:00:00"
		end := day + " " + "23:59:59"
		defectRecordLi, err := defectRecordDao.Select([]grmi.Predicate{
			qmMeta.DefectRecord_CreateTime.NewPredicate(grmi.GreaterOrEqual, start),
			qmMeta.DefectRecord_CreateTime.NewPredicate(grmi.LessOrEqual, end),
		}, []grmi.Field{qmMeta.DefectRecord_SerialOrderId})
		if err != nil {
			return nil, grmi.NewBusinessError("查询缺陷记录失败，错误:" + err.Error())
		}
		serialOrderMap := make(map[string]interface{})
		for _, defectRecord := range defectRecordLi {
			_, exist := serialOrderMap[defectRecord.SerialOrderId]
			if !exist {
				serialOrderMap[defectRecord.SerialOrderId] = nil
			}
		}
		repairInfoLi, err := repairInfoDao.Select([]grmi.Predicate{
			baseMeta.RepairInfo_CreateTime.NewPredicate(grmi.GreaterOrEqual, start),
			baseMeta.RepairInfo_CreateTime.NewPredicate(grmi.LessOrEqual, end),
		}, []grmi.Field{baseMeta.RepairInfo_SerialOrderId})
		if err != nil {
			return nil, grmi.NewBusinessError("查询返修记录失败, 错误:" + err.Error())
		}
		for _, repairInfo := range repairInfoLi {
			_, exist := serialOrderMap[repairInfo.SerialOrderId]
			if !exist {
				serialOrderMap[repairInfo.SerialOrderId] = nil
			}
		}
		// 判断缺陷的这些工单归属的
		for serialOrderId := range serialOrderMap {
			serialOrder, err := serialOrderDao.SelectOne(serialOrderId)
			if err != nil {
				return nil, grmi.NewBusinessError("查询工单数据失败, 错误:" + err.Error())
			}
			if serialOrder == nil {
				delete(serialOrderMap, serialOrderId)
				continue
			}
			if serialOrder.CustOrderId == "" {
				delete(serialOrderMap, serialOrderId)
				continue
			}
			if serialOrder.OrderType == baseModel.ORDER_TYPE_PRE {
				delete(serialOrderMap, serialOrderId)
				continue
			}
			custOrder, exist := custOrderMap[serialOrder.CustOrderId]
			if !exist {
				custOrder, err = custOrderDao.SelectOne(serialOrder.CustOrderId)
				if err != nil {
					return nil, grmi.NewBusinessError("查询客户订单失败, 错误:" + err.Error())
				}
				if custOrder == nil {
					delete(serialOrderMap, serialOrderId)
					continue
				}
				custOrderMap[serialOrder.CustOrderId] = custOrder
			}
			if custOrder.WorkLineId != workLineId {
				delete(serialOrderMap, serialOrderId)
			}
		}
		defectNumber := len(serialOrderMap)
		custOrderLi, err := custOrderDao.JoinSelect([]grmi.Predicate{
			meta.CustOrder_PlanStartTime.NewPredicate(grmi.GreaterOrEqual, start),
			meta.CustOrder_PlanStartTime.NewPredicate(grmi.LessThen, end),
		}, []grmi.Field{meta.CustOrder_PlanStartTime})
		if err != nil {
			return nil, grmi.NewBusinessError("查询客户订单失败, 错误:" + err.Error())
		}
		var planQty int
		for _, custOrder := range custOrderLi {
			packNum, exist := productFamilyMap[custOrder.ProductFamilyId]
			if !exist {
				productLi, err := productFamilyRelateDao.SelectProductByFamilyId(custOrder.ProjectId, custOrder.ProductFamilyId)
				if err != nil {
					return nil, grmi.NewBusinessError("查询派生数据失败, 错误:" + err.Error())
				}
				packNum = len(productLi)
				productFamilyMap[custOrder.ProductFamilyId] = packNum
			}
			planQty += packNum * (custOrder.OrderQty.PlanQty - custOrder.OrderQty.CancelQty)
		}
		var percent int64
		if planQty == 0 {
			percent = 0
		} else {
			percent = int64(float64(defectNumber) / float64(planQty) * 1000000)
		}
		defectItem.Number = percent
		defectItem.Date = day
		result = append(result, defectItem)
	}
	return result, nil
}

func (impl *CustOrderServiceImplement) CountTarget(user *global.User, workLineId string) (model.TargetItem, error) {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	now := time.Now()
	result := model.TargetItem{}
	custOrderDao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
	packDao := jitDal.NewPackOrderDAO(session, user.PlantNr, user.UserId)
	workLineDao := baseDal.NewWorkLineDAO(session, user.PlantNr, user.UserId)
	workLineLi, err := workLineDao.Select([]grmi.Predicate{baseMeta.WorkLine_GroupLineId.NewPredicate(grmi.Equal, workLineId)}, nil)
	if err != nil {
		return result, grmi.NewBusinessError("查询工厂产线数据失败, error:" + err.Error())
	}
	if len(workLineLi) == 0 {
		return result, grmi.NewBusinessError("未查询到实体产线")
	}
	var workLineIds []string
	for _, v := range workLineLi {
		workLineIds = append(workLineIds, v.WorkLineid)
	}
	today := now.Format(grmi.DateOutFormat)
	start := today + " " + "00:00:00"
	end := today + " " + "23:59:59"
	custOrderLi, err := custOrderDao.JoinSelect([]grmi.Predicate{
		meta.CustOrder_WorkLineId.NewPredicate(grmi.Equal, workLineId),
		meta.CustOrder_PlanStartTime.NewPredicate(grmi.GreaterOrEqual, start),
		meta.CustOrder_PlanStartTime.NewPredicate(grmi.LessThen, end),
	}, []grmi.Field{meta.CustOrder_PlanStartTime})
	if err != nil {
		return result, err
	}
	//计算计划数量
	for _, custOrderData := range custOrderLi {
		result.Target += custOrderData.OrderQty.PlanQty - custOrderData.OrderQty.CancelQty

	}
	//计算打包数量
	packList, err := packDao.SelectUserClosePackOrder(start, end, workLineIds)
	if err != nil {
		return result, err
	}
	result.Current = len(packList)
	return result, nil
}

//计算当班节拍数量
func (impl *CustOrderServiceImplement) SelectTeamTemPo(user *global.User, dayModel *baseModel.DayModel, num int, startDayTime time.Time, WorkShift int, workLineId string) (TeamTemPoNumber float64, PerTeamTemPoNumber float64, err error) {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	packOrderDao := jitDal.NewPackOrderDAO(session, user.PlantNr, user.UserId)
	workLineDao := baseDal.NewWorkLineDAO(session, user.PlantNr, user.UserId)
	workLineLi, err := workLineDao.Select([]grmi.Predicate{baseMeta.WorkLine_GroupLineId.NewPredicate(grmi.Equal, workLineId)}, nil)
	if err != nil {
		return 0, 0, grmi.NewBusinessError("查询工厂产线数据失败, error:" + err.Error())
	}
	if len(workLineLi) == 0 {
		return 0, 0, grmi.NewBusinessError("未查询到实体产线")
	}
	var workLineIds []string
	for _, v := range workLineLi {
		workLineIds = append(workLineIds, v.WorkLineid)
	}

	//计算当班平均节拍
	switch WorkShift {
	case 1:
		//查询当班开始和结束时间
		WorkShift1StartTime := startDayTime.Add(time.Duration(dayModel.S1Beg) * time.Second)
		WorkShift1EndTime := startDayTime.Add(time.Duration(dayModel.S1End) * time.Second)

		startTime := utils.TimeFormat(WorkShift1StartTime, "yyyy-MM-dd HH:mm:ss")
		endTime := utils.TimeFormat(WorkShift1EndTime, "yyyy-MM-dd HH:mm:ss")

		packData, err := packOrderDao.SelectUserClosePackOrder(startTime, endTime, workLineIds)
		if err != nil {
			return 0, 0, err
		}
		countPack := len(packData)
		packTimes := time.Now().Unix() - WorkShift1StartTime.Unix()
		if countPack > 0 {
			TeamTemPoNumber = utils.Decimal(float64(packTimes)/float64(countPack), 2)
			PerTeamTemPoNumber = utils.Decimal(float64(countPack)/float64(num), 4)
		} else {
			TeamTemPoNumber = 0
			PerTeamTemPoNumber = 0
		}
		return TeamTemPoNumber, PerTeamTemPoNumber, nil
	case 2:
		//查询当班开始和结束时间

		WorkShift2StartTime := startDayTime.Add(time.Duration(dayModel.S2Beg) * time.Second)
		WorkShift2EndTime := startDayTime.Add(time.Duration(dayModel.S2End) * time.Second)

		startTime := utils.TimeFormat(WorkShift2StartTime, "yyyy-MM-dd HH:mm:ss")
		endTime := utils.TimeFormat(WorkShift2EndTime, "yyyy-MM-dd HH:mm:ss")

		packData, err := packOrderDao.SelectUserClosePackOrder(startTime, endTime, workLineIds)
		if err != nil {
			return 0, 0, err
		}
		countPack := len(packData)
		packTimes := time.Now().Unix() - WorkShift2StartTime.Unix()
		if countPack > 0 {
			TeamTemPoNumber = utils.Decimal(float64(packTimes)/float64(countPack), 2)
			PerTeamTemPoNumber = utils.Decimal(float64(countPack)/float64(num), 4)
		} else {
			TeamTemPoNumber = 0
			PerTeamTemPoNumber = 0
		}
		return TeamTemPoNumber, PerTeamTemPoNumber, nil
	case 3:
		//查询当班开始和结束时间

		WorkShift3StartTime := startDayTime.Add(time.Duration(dayModel.S3Beg) * time.Second)
		WorkShift3EndTime := startDayTime.Add(time.Duration(dayModel.S3End) * time.Second)

		startTime := utils.TimeFormat(WorkShift3StartTime, "yyyy-MM-dd HH:mm:ss")
		endTime := utils.TimeFormat(WorkShift3EndTime, "yyyy-MM-dd HH:mm:ss")

		packData, err := packOrderDao.SelectUserClosePackOrder(startTime, endTime, workLineIds)
		if err != nil {
			return 0, 0, err
		}
		countPack := len(packData)
		packTimes := time.Now().Unix() - WorkShift3StartTime.Unix()
		if countPack > 0 {
			TeamTemPoNumber = utils.Decimal(float64(packTimes)/float64(countPack), 2)
			PerTeamTemPoNumber = utils.Decimal(float64(countPack)/float64(num), 4)
		} else {
			TeamTemPoNumber = 0
			PerTeamTemPoNumber = 0
		}
		return TeamTemPoNumber, PerTeamTemPoNumber, nil
	}
	return 0, 0, nil
}

//图例1
func (impl *CustOrderServiceImplement) SelectPic1(user *global.User, dayModel *baseModel.DayModel, workLineId string) (result model.CutLine1, err error) {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	custOrderDao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
	productFamilyDao := meDal.NewProductFamilyDAO(session, user.PlantNr, user.UserId)
	productFamilyRelateDao := meDal.NewProductFamilyRelateDAO(session, user.PlantNr, user.UserId)
	serialOrderDao := omDal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	productFamilyMap := make(map[string]*meModel.ProductFamily)
	productFamilyRelateMap := make(map[string]map[string]interface{})
	productFamilyMeterMap := make(map[string]float64)
	now := time.Now()
	//now, _ := time.ParseInLocation(grmi.DateTimeOutFormat, "2022-04-28 23:00:00", utils.TimezoneLocation)
	endTime := now.Format(grmi.DateOutFormat) + " 23:59:59"
	todayStart := now.Format(grmi.DateOutFormat) + " 00:00:00"
	dateTimeLi := make([]int, 0, now.Hour())
	todayStartTime, _ := time.ParseInLocation(grmi.DateTimeOutFormat, todayStart, utils.TimezoneLocation)
	var num int
	for {
		if todayStartTime.Add(time.Hour * time.Duration(num)).After(now) {
			break
		}
		dateTimeLi = append(dateTimeLi, num)
		num++
	}
	timeModelList := impl.InitDayModelList(dayModel, todayStartTime)
	// 查询正在正在生产的客户订单
	custOrderLi, err := custOrderDao.SelectRunningCustOrder(workLineId)

	if err != nil {
		return result, grmi.NewBusinessError("查询正在生产的客户订单失败, 错误:" + err.Error())
	}

	var currentMeter int
	if len(custOrderLi) == 0 {
		currentMeter = 0
	} else {
		custOrder := custOrderLi[0]
		productFamily, err := productFamilyDao.SelectOne(custOrder.ProductFamilyId)
		if err != nil {
			return result, grmi.NewBusinessError("查询派生数据失败, 错误:" + err.Error())
		}
		if productFamily == nil {
			return result, grmi.NewBusinessError("客户订单派生不存在, 派生ID:" + custOrder.ProductFamilyId)
		}
		if productFamily.Jph == 0 {
			return result, grmi.NewBusinessError("派生JPH为0 派生ID:" + custOrder.ProductFamilyId)
		}
		currentMeter = int(float64(3600) / productFamily.Jph)
		productFamilyMeterMap[custOrder.ProductFamilyId] = float64(3600) / productFamily.Jph
		productFamilyMap[custOrder.ProductFamilyId] = productFamily
		productLi, err := productFamilyRelateDao.SelectProductByFamilyId(custOrder.ProjectId, custOrder.ProductFamilyId)
		if err != nil {
			return result, grmi.NewBusinessError("查询派生下总成数据失败, 错误:" + err.Error())
		}
		if len(productLi) == 0 {
			return result, grmi.NewBusinessError("派生下未关联需要生产的座椅总成, 派生ID:" + custOrder.ProductFamilyId)
		}
		productFamilyRelateMap[custOrder.ProductFamilyId] = make(map[string]interface{}, len(productLi))
		for _, product := range productLi {
			productFamilyRelateMap[custOrder.ProductFamilyId][product.ProductId] = nil
		}
	}

	// 查询客户订单 两类:
	// 1.  今天开始时间 < 实际结束时间 < 当前时间 状态 > 26 && != 98
	// 2. 实际结束时间为空 实际开始时间 < 当前时间 状态 > 26 && != 98
	custOrderDataLi, err := custOrderDao.SelectProduceOrder(todayStart, endTime, workLineId)
	if err != nil {
		return result, grmi.NewBusinessError("查询客户订单失败, 错误:" + err.Error())
	}

	productFamilyAccomplishMap := make(map[int]map[string]model.HourProductData)
	for _, custOrderData := range custOrderDataLi {
		productFamilyId := custOrderData.CustOrder.ProductFamilyId
		productFamily, exist := productFamilyMap[productFamilyId]
		if !exist {
			productFamily, err = productFamilyDao.SelectOne(productFamilyId)
			if err != nil {
				return result, grmi.NewBusinessError("查询派生数据失败, 错误:" + err.Error())
			}
			if productFamily == nil {
				return result, grmi.NewBusinessError("客户订单中派生不存在, 派生Id:" + productFamilyId + ", 客户订单Id:" + custOrderData.CustOrder.CustOrderId)
			}
			if productFamily.Jph == 0 {
				return result, grmi.NewBusinessError("派生JPH为0 派生ID:" + productFamilyId)
			}
			productLi, err := productFamilyRelateDao.SelectProductByFamilyId(custOrderData.CustOrder.ProjectId, productFamilyId)
			if err != nil {
				return result, grmi.NewBusinessError("查询派生下总成数据失败, 错误:" + err.Error())
			}
			if len(productLi) == 0 {
				return result, grmi.NewBusinessError("派生下未关联需要生产的座椅总成, 派生ID:" + productFamilyId)
			}
			productFamilyRelateMap[productFamilyId] = make(map[string]interface{}, len(productLi))
			for _, product := range productLi {
				productFamilyRelateMap[productFamilyId][product.ProductId] = nil
			}
			productFamilyMap[productFamilyId] = productFamily
			productFamilyMeterMap[productFamilyId] = float64(3600) / productFamily.Jph
		}
		// 查询客户订单下的工单
		serialOrderDataLi, err := serialOrderDao.SelectByCustOrderIdForDashboard(custOrderData.CustOrder.CustOrderId, todayStart, endTime)
		if err != nil {
			return result, grmi.NewBusinessError("查询客户订单下工单失败, 错误:" + err.Error())
		}
		// 记录生产每个台套下面的工单数量
		syncKeyMap := make(map[string][]omModel.SerialOrder)
		syncKeyAccomplishTimeMap := make(map[string]time.Time)
		for _, serialOrder := range serialOrderDataLi {
			_, exist = syncKeyMap[serialOrder.SyncKey]
			if !exist {
				syncKeyMap[serialOrder.SyncKey] = make([]omModel.SerialOrder, 0, len(productFamilyRelateMap[productFamilyId]))
			}
			syncKeyMap[serialOrder.SyncKey] = append(syncKeyMap[serialOrder.SyncKey], serialOrder)
		}
		// 找到每个台套的最后完成时间
		for syncKey, orderLi := range syncKeyMap {
			if len(orderLi) == len(productFamilyRelateMap[productFamilyId]) {
				var match = true
				orderArtIdMap := make(map[string]interface{})
				for _, order := range orderLi {
					orderArtIdMap[order.ArtId] = nil
				}
				for artId, _ := range productFamilyRelateMap[productFamilyId] {
					_, exist = orderArtIdMap[artId]
					if !exist {
						match = false
						break
					}
				}
				if !match {
					continue
				}
				var accomplishTime time.Time
				for _, serialOrder := range orderLi {
					if serialOrder.ActEndTime.Restore().After(accomplishTime) {
						accomplishTime = serialOrder.ActEndTime.Restore()
					}
				}
				syncKeyAccomplishTimeMap[syncKey] = accomplishTime
			}
		}
		// 记录每个小时完成的数量和时间
		for _, accomplishTime := range syncKeyAccomplishTimeMap {
			hour := accomplishTime.Hour()
			hourProductMap, exist := productFamilyAccomplishMap[hour]
			if !exist {
				productFamilyAccomplishMap[hour] = make(map[string]model.HourProductData)
				hourProductMap = productFamilyAccomplishMap[hour]
			}
			productFamilyData, exist := hourProductMap[productFamilyId]
			if !exist {
				hourProductMap[productFamilyId] = model.HourProductData{
					ProductFamilyId: productFamilyId,
					Qty:             1,
					LastDoneTime:    accomplishTime,
				}
			} else {
				productFamilyData.Qty++
				if productFamilyData.LastDoneTime.Before(accomplishTime) {
					productFamilyData.LastDoneTime = accomplishTime
				}
				hourProductMap[productFamilyId] = productFamilyData
			}
			productFamilyAccomplishMap[hour] = hourProductMap
		}
	}
	displayHourLi := make([]string, 0, len(productFamilyAccomplishMap))
	for hour := 0; hour < 24; hour++ {
		_, exist := productFamilyAccomplishMap[hour]
		if exist {
			displayHourLi = append(displayHourLi, strconv.Itoa(hour)+"时")
		}
	}
	result = model.CutLine1{
		TimeLi:             displayHourLi,
		Standard:           1.0,
		ProductFamilyMeter: currentMeter,
		ProduceData:        make([]float64, 0, len(displayHourLi)),
	}
	for hour := 0; hour < 24; hour++ {
		hourData, exist := productFamilyAccomplishMap[hour]
		if !exist {
			continue
		}
		var hourPercent float64
		productDataLi := make([]model.HourProductData, 0, len(hourData))
		for _, data := range hourData {
			productDataLi = append(productDataLi, data)
		}
		impl.QuickSortProductData(productDataLi)
		currentTime := todayStartTime.Add(time.Hour * time.Duration(hour))
		var hourAllUsedTime int
		for _, productFamilyProductData := range productDataLi {
			usedTime := impl.GetUsefulTime(currentTime, productFamilyProductData.LastDoneTime, timeModelList)
			currentTime = productFamilyProductData.LastDoneTime
			hourAllUsedTime += usedTime
		}
		currentTime = todayStartTime.Add(time.Hour * time.Duration(hour))
		for _, productFamilyProductData := range productDataLi {
			usedTime := impl.GetUsefulTime(currentTime, productFamilyProductData.LastDoneTime, timeModelList)
			currentTime = productFamilyProductData.LastDoneTime
			meter := productFamilyMeterMap[productFamilyProductData.ProductFamilyId]
			var percent float64
			if productFamilyProductData.Qty != 0 && usedTime != 0 && hourAllUsedTime != 0 {
				percent = float64(productFamilyProductData.Qty) / (meter * (float64(usedTime) / float64(hourAllUsedTime)))
				//percent = meter / (float64(usedTime) / float64(productFamilyProductData.Qty)) * (float64(usedTime) / float64(hourAllUsedTime))
			}
			hourPercent += percent
		}
		result.ProduceData = append(result.ProduceData, hourPercent)
	}
	return result, nil
}

func (impl *CustOrderServiceImplement) GetUsefulTime(start, end time.Time, timeLine *list.List) int {
	var duration int
	for element := timeLine.Front(); element != nil; element = element.Next() {
		listElement := element.Value.(model.ListElement)
		//比较开始时间
		if listElement.Start.Before(start) {

			/*
				     /----------------------/  start ---- end

				/----------------------/       listElement

			*/
			if listElement.End.After(start) && listElement.End.Before(end) {

				duration += int(listElement.End.Sub(start).Seconds())
			}

			/*
				     /----------------------/  start ---- end

				/---------------------------------/       listElement

			*/
			if listElement.End.After(end) {
				duration += int(end.Sub(start).Seconds())
			}
		} else if listElement.Start.After(start) && listElement.Start.Before(end) {
			/*
			   /----------------------/  start ---- end

			          /-----------/       listElement

			*/

			if listElement.End.Before(end) {
				duration += int(listElement.End.Sub(listElement.Start).Seconds())
			}

			/*
			   /----------------------/  start ---- end

			          /----------------------/       listElement

			*/
			if listElement.End.After(end) {
				duration += int(end.Sub(listElement.Start).Seconds())
			}
		}
	}
	return duration
}

//图例3
func (impl *CustOrderServiceImplement) SelectPic3(user *global.User, DayModelHours []string, dayModel *baseModel.DayModel, startDayTime time.Time, endDayTime time.Time, timeBeat float64, personNum int, workLineId string) (model.PerDashboardData, error) {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	custOrderDao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
	productFamilyDao := meDal.NewProductFamilyDAO(session, user.PlantNr, user.UserId)
	productFamilyRelateDao := meDal.NewProductFamilyRelateDAO(session, user.PlantNr, user.UserId)
	serialOrderDao := omDal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
	productFamilyMap := make(map[string]*meModel.ProductFamily)
	productFamilyRelateMap := make(map[string]map[string]interface{})
	productFamilyMeterMap := make(map[string]float64)
	now := time.Now()
	//now, _ := time.ParseInLocation(grmi.DateTimeOutFormat, "2022-04-28 23:00:00", utils.TimezoneLocation)
	endTime := now.Format(grmi.DateOutFormat) + " 23:59:59"
	todayStart := now.Format(grmi.DateOutFormat) + " 00:00:00"
	packDao := jitDal.NewPackOrderDAO(session, user.PlantNr, user.UserId)
	//图例003
	DashboardData3 := model.PerDashboardData{}
	//图例001
	workLineDao := baseDal.NewWorkLineDAO(session, user.PlantNr, user.UserId)
	workLineLi, err := workLineDao.Select([]grmi.Predicate{baseMeta.WorkLine_GroupLineId.NewPredicate(grmi.Equal, workLineId)}, nil)
	if err != nil {
		return DashboardData3, grmi.NewBusinessError("查询工厂产线数据失败, error:" + err.Error())
	}
	if len(workLineLi) == 0 {
		return DashboardData3, grmi.NewBusinessError("未查询到实体产线")
	}
	var workLineIds []string
	for _, v := range workLineLi {
		workLineIds = append(workLineIds, v.WorkLineid)
	}

	timeModelList := impl.InitDayModelList(dayModel, startDayTime)

	// 查询正在正在生产的客户订单
	custOrderLi, err := custOrderDao.SelectRunningCustOrder(workLineId)

	if err != nil {
		return DashboardData3, grmi.NewBusinessError("查询正在生产的客户订单失败, 错误:" + err.Error())
	}

	if len(custOrderLi) > 0 {
		custOrder := custOrderLi[0]
		productFamily, err := productFamilyDao.SelectOne(custOrder.ProductFamilyId)
		if err != nil {
			return DashboardData3, grmi.NewBusinessError("查询派生数据失败, 错误:" + err.Error())
		}
		if productFamily == nil {
			return DashboardData3, grmi.NewBusinessError("客户订单派生不存在, 派生ID:" + custOrder.ProductFamilyId)
		}
		if productFamily.Jph == 0 {
			return DashboardData3, grmi.NewBusinessError("派生JPH为0 派生ID:" + custOrder.ProductFamilyId)
		}
		productFamilyMeterMap[custOrder.ProductFamilyId] = float64(3600) / productFamily.Jph
		productFamilyMap[custOrder.ProductFamilyId] = productFamily
		productLi, err := productFamilyRelateDao.SelectProductByFamilyId(custOrder.ProjectId, custOrder.ProductFamilyId)
		if err != nil {
			return DashboardData3, grmi.NewBusinessError("查询派生下总成数据失败, 错误:" + err.Error())
		}
		if len(productLi) == 0 {
			return DashboardData3, grmi.NewBusinessError("派生下未关联需要生产的座椅总成, 派生ID:" + custOrder.ProductFamilyId)
		}
		productFamilyRelateMap[custOrder.ProductFamilyId] = make(map[string]interface{}, len(productLi))
		for _, product := range productLi {
			productFamilyRelateMap[custOrder.ProductFamilyId][product.ProductId] = nil
		}
	}

	// 查询客户订单 两类:
	// 1.  今天开始时间 < 实际结束时间 < 当前时间 状态 > 26 && != 98
	// 2. 实际结束时间为空 实际开始时间 < 当前时间 状态 > 26 && != 98
	custOrderDataLi, err := custOrderDao.SelectProduceOrder(todayStart, endTime, workLineId)
	if err != nil {
		return DashboardData3, grmi.NewBusinessError("查询客户订单失败, 错误:" + err.Error())
	}

	productFamilyAccomplishMap := make(map[int]map[string]model.HourProductData)
	for _, custOrderData := range custOrderDataLi {
		productFamilyId := custOrderData.CustOrder.ProductFamilyId
		productFamily, exist := productFamilyMap[productFamilyId]
		if !exist {
			productFamily, err = productFamilyDao.SelectOne(productFamilyId)
			if err != nil {
				return DashboardData3, grmi.NewBusinessError("查询派生数据失败, 错误:" + err.Error())
			}
			if productFamily == nil {
				return DashboardData3, grmi.NewBusinessError("客户订单中派生不存在, 派生Id:" + productFamilyId + ", 客户订单Id:" + custOrderData.CustOrder.CustOrderId)
			}
			if productFamily.Jph == 0 {
				return DashboardData3, grmi.NewBusinessError("派生JPH为0 派生ID:" + productFamilyId)
			}
			productLi, err := productFamilyRelateDao.SelectProductByFamilyId(custOrderData.CustOrder.ProjectId, productFamilyId)
			if err != nil {
				return DashboardData3, grmi.NewBusinessError("查询派生下总成数据失败, 错误:" + err.Error())
			}
			if len(productLi) == 0 {
				return DashboardData3, grmi.NewBusinessError("派生下未关联需要生产的座椅总成, 派生ID:" + productFamilyId)
			}
			productFamilyRelateMap[productFamilyId] = make(map[string]interface{}, len(productLi))
			for _, product := range productLi {
				productFamilyRelateMap[productFamilyId][product.ProductId] = nil
			}
			productFamilyMap[productFamilyId] = productFamily
			productFamilyMeterMap[productFamilyId] = float64(3600) / productFamily.Jph
		}
		// 查询客户订单下的工单
		serialOrderDataLi, err := serialOrderDao.SelectByCustOrderIdForDashboard(custOrderData.CustOrder.CustOrderId, todayStart, endTime)
		if err != nil {
			return DashboardData3, grmi.NewBusinessError("查询客户订单下工单失败, 错误:" + err.Error())
		}
		// 记录生产每个台套下面的工单数量
		syncKeyMap := make(map[string][]omModel.SerialOrder)
		syncKeyAccomplishTimeMap := make(map[string]time.Time)
		for _, serialOrder := range serialOrderDataLi {
			_, exist = syncKeyMap[serialOrder.SyncKey]
			if !exist {
				syncKeyMap[serialOrder.SyncKey] = make([]omModel.SerialOrder, 0, len(productFamilyRelateMap[productFamilyId]))
			}
			syncKeyMap[serialOrder.SyncKey] = append(syncKeyMap[serialOrder.SyncKey], serialOrder)
		}
		// 找到每个台套的最后完成时间
		for syncKey, orderLi := range syncKeyMap {
			if len(orderLi) == len(productFamilyRelateMap[productFamilyId]) {
				var match = true
				orderArtIdMap := make(map[string]interface{})
				for _, order := range orderLi {
					orderArtIdMap[order.ArtId] = nil
				}
				for artId, _ := range productFamilyRelateMap[productFamilyId] {
					_, exist = orderArtIdMap[artId]
					if !exist {
						match = false
						break
					}
				}
				if !match {
					continue
				}
				var accomplishTime time.Time
				for _, serialOrder := range orderLi {
					if serialOrder.ActEndTime.Restore().After(accomplishTime) {
						accomplishTime = serialOrder.ActEndTime.Restore()
					}
				}
				syncKeyAccomplishTimeMap[syncKey] = accomplishTime
			}
		}
		// 记录每个小时完成的数量和时间
		for _, accomplishTime := range syncKeyAccomplishTimeMap {
			hour := accomplishTime.Hour()
			hourProductMap, exist := productFamilyAccomplishMap[hour]
			if !exist {
				productFamilyAccomplishMap[hour] = make(map[string]model.HourProductData)
				hourProductMap = productFamilyAccomplishMap[hour]
			}
			productFamilyData, exist := hourProductMap[productFamilyId]
			if !exist {
				hourProductMap[productFamilyId] = model.HourProductData{
					ProductFamilyId: productFamilyId,
					Qty:             1,
					LastDoneTime:    accomplishTime,
				}
			} else {
				productFamilyData.Qty++
				if productFamilyData.LastDoneTime.Before(accomplishTime) {
					productFamilyData.LastDoneTime = accomplishTime
				}
				hourProductMap[productFamilyId] = productFamilyData
			}
			productFamilyAccomplishMap[hour] = hourProductMap
		}
	}
	//定义动态JPH
	jphMap := make(map[string]float64)
	for hour := 0; hour < 24; hour++ {

		key := utils.TimeFormat(startDayTime.Add(time.Duration(hour)*time.Hour), "yyyy-MM-dd HH:00")
		hourData, exist := productFamilyAccomplishMap[hour]
		if !exist {
			continue
		}
		var hourPercent float64
		productDataLi := make([]model.HourProductData, 0, len(hourData))
		for _, data := range hourData {
			productDataLi = append(productDataLi, data)
		}
		impl.QuickSortProductData(productDataLi)
		currentTime := startDayTime.Add(time.Hour * time.Duration(hour))
		var hourAllUsedTime int
		for _, productFamilyProductData := range productDataLi {
			usedTime := impl.GetUsefulTime(currentTime, productFamilyProductData.LastDoneTime, timeModelList)
			currentTime = productFamilyProductData.LastDoneTime
			hourAllUsedTime += usedTime
		}
		currentTime = startDayTime.Add(time.Hour * time.Duration(hour))
		for _, productFamilyProductData := range productDataLi {
			usedTime := impl.GetUsefulTime(currentTime, productFamilyProductData.LastDoneTime, timeModelList)
			currentTime = productFamilyProductData.LastDoneTime
			meter := productFamilyMeterMap[productFamilyProductData.ProductFamilyId]
			var percent float64
			if productFamilyProductData.Qty != 0 && usedTime != 0 && hourAllUsedTime != 0 {
				percent = (meter * (float64(usedTime) / float64(hourAllUsedTime)))
				//percent = meter / (float64(usedTime) / float64(productFamilyProductData.Qty)) * (float64(usedTime) / float64(hourAllUsedTime))
			}
			hourPercent += percent
		}
		jphMap[key] = hourPercent
	}
	//查询当天所有的包装单情况
	jitData, err := packDao.SelectUserClosePackOrder(utils.TimeFormat(startDayTime, "yyyy-MM-dd HH:mm:ss"), utils.TimeFormat(endDayTime, "yyyy-MM-dd HH:mm:ss"), workLineIds)
	if err != nil {
		return DashboardData3, err
	}
	jitMap := make(map[string]int)

	for _, v := range jitData {

		key := utils.TimeFormat(v.CloseTime.Restore(), "yyyy-MM-dd HH:00")

		_, ok := jitMap[key]
		if ok {
			jitMap[key] += 1
		} else {
			jitMap[key] = 1
		}
	}
	for i := 0; i < len(DayModelHours); i++ {
		key := DayModelHours[i]
		val, ok := jitMap[key]
		one := model.DashboardData{}
		one.Date = DayModelHours[i]
		if ok {
			one.Val = utils.Decimal((float64(val)/float64(personNum)), 2)
		} else {
			one.Val = 0
		}
		DashboardData3.DashboardData1 = append(DashboardData3.DashboardData1, one)

		two := model.DashboardData{}
		two.Date = DayModelHours[i]
		timeBeat, ok := jphMap[key]
		if !ok {
			two.Val = 0
		} else {
			if timeBeat > 0 {
				two.Val = utils.Decimal(float64((3600/timeBeat)/float64(personNum)), 2)
			} else {
				two.Val = 0
			}

		}
		DashboardData3.DashboardData2 = append(DashboardData3.DashboardData2, two)
	}
	return DashboardData3, nil
}

//查询状态
func (impl *CustOrderServiceImplement) SelectAndonInfo(user *global.User) (int, error) {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	andonDao := baseDal.NewAndonInfoDAO(session, user.UserId)
	andonInfo, err := andonDao.Select([]grmi.Predicate{baseMeta.AndonInfo_IsActive.NewPredicate(grmi.Equal, 1)}, nil)
	if err != nil {
		return 0, err
	}
	if len(andonInfo) > 0 {
		return 1, nil
	}
	return 0, nil
}