Browse Source

上传excel并进行排程

pull/216/head
zhangxin 2 years ago
parent
commit
abfd3b7a58
3 changed files with 462 additions and 133 deletions
  1. +5
    -13
      services/base/implments/WorkLine.service.impl.go
  2. +337
    -115
      services/pln/implments/CustOrder.service.impl.go
  3. +120
    -5
      services/schedule/Scheduler.Ctrl.go

+ 5
- 13
services/base/implments/WorkLine.service.impl.go View File

@ -967,15 +967,7 @@ func (impl *WorkLineServiceImplement) WorkLineRepairSchedule(user *global.User,
func (impl *WorkLineServiceImplement) SaveWorkLineScheduler(user *global.User, data schedule.SchedulerData) error {
grmi.Log(user, "/services/base/implments/WorkLine.service.impl.go", "SaveWorkLineScheduler", "保存调度结果")
StartDate, err := utils.TimeParse(data.StartDate)
if err != nil {
return err
}
EndDate, err := utils.TimeParse(data.EndDate)
if err != nil {
return err
}
var err error
//开启事务
engine := db.Eloquent.Master()
session := engine.NewSession()
@ -997,8 +989,8 @@ func (impl *WorkLineServiceImplement) SaveWorkLineScheduler(user *global.User, d
updateCustOrder := new(plnModel.CustOrder)
updateCustOrder.PlantNr = plannedTask.PlantNr
updateCustOrder.CustOrderId = plannedTask.TaskId
updateCustOrder.PlanStartDate = grmi.Date(StartDate)
updateCustOrder.PlanEndDate = grmi.Date(EndDate)
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())
@ -1050,8 +1042,8 @@ func (impl *WorkLineServiceImplement) SaveWorkLineScheduler(user *global.User, d
updateCustOrder := new(plnModel.CustOrder)
updateCustOrder.PlantNr = task.PlantNr
updateCustOrder.CustOrderId = task.TaskId
updateCustOrder.PlanStartDate = grmi.Date(StartDate)
updateCustOrder.PlanEndDate = grmi.Date(EndDate)
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())


+ 337
- 115
services/pln/implments/CustOrder.service.impl.go View File

@ -23,16 +23,16 @@ import (
omModel "LAPP_ACURA_MOM_BACKEND/models/om"
model "LAPP_ACURA_MOM_BACKEND/models/pln"
omSvr "LAPP_ACURA_MOM_BACKEND/services/om"
"LAPP_ACURA_MOM_BACKEND/services/schedule"
"LAPP_ACURA_MOM_BACKEND/utils"
"container/list"
"errors"
"github.com/360EntSecGroup-Skylar/excelize/v2"
"github.com/go-xorm/xorm"
uuid "github.com/iris-contrib/go.uuid"
"strconv"
"strings"
"sync"
//"sync"
"time"
)
@ -2524,7 +2524,7 @@ func (impl *CustOrderServiceImplement) Dashboard(user *global.User, workLineId s
go func(wg *sync.WaitGroup) {
DashboardData.DashboardDataPic1, err1 = impl.SelectPic1(user, dayModel, workLineId)
wg.Done() // 操作完成,减少一个计数
}(&wg )
}(&wg)
//图例002
go func(wg *sync.WaitGroup) {
@ -3326,7 +3326,6 @@ func (impl *CustOrderServiceImplement) SelectPic1(user *global.User, dayModel *b
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() {
@ -3928,12 +3927,17 @@ func (impl *CustOrderServiceImplement) AnalysisPlanFromExcel(user *global.User,
engine := db.Eloquent.Master()
session := engine.NewSession()
defer session.Close()
custOrderDao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
custOrderStatusDao := dal.NewCustOrderStatusDAO(session, user.PlantNr, user.UserId)
var startDate, endDate time.Time
custOrderQtyDao := dal.NewCustOrderQtyDAO(session, user.PlantNr, user.UserId)
productFamilyDao := meDal.NewProductFamilyDAO(session, user.PlantNr, user.UserId)
productFamilyWorkLineDao := meDal.NewProductFamilyWorkLineLstDAO(session, user.PlantNr, user.UserId)
productFamilyRelateDao := meDal.NewProductFamilyRelateDAO(session, user.PlantNr, user.UserId)
productWorkLineDao := meDal.NewProductWorkLineLstDAO(session, user.PlantNr, user.UserId)
projectDao := meDal.NewProjectDAO(session, user.PlantNr, user.UserId)
serialOrderDao := omDal.NewSerialOrderDAO(session, user.PlantNr, user.UserId)
serialOrderStatusDao := omDal.NewSerialOrderStatusDAO(session, user.PlantNr, user.UserId)
snrDao := baseDal.NewSnrDAO(session, user.PlantNr, user.UserId)
workLineDao := baseDal.NewWorkLineDAO(session, user.PlantNr, user.UserId)
file, err := excelize.OpenFile(filepath)
if err != nil {
return grmi.NewBusinessError("读取文件失败, error:" + err.Error())
@ -3946,7 +3950,7 @@ func (impl *CustOrderServiceImplement) AnalysisPlanFromExcel(user *global.User,
rowIndex := 0
projectMap := make(map[string]*meModel.Project)
productFamilyMap := make(map[string]*meModel.ProductFamily)
planDateCustOrderMap := make(map[string][]model.CustOrder, 0)
custOrderWorkLineMap := make(map[string][]model.CustOrder, 0)
for rowsIterator.Next() {
rowIndex++
// 第一行标题行
@ -3962,7 +3966,7 @@ func (impl *CustOrderServiceImplement) AnalysisPlanFromExcel(user *global.User,
if err != nil {
return grmi.NewBusinessError("去读excel行数据失败, error:" + err.Error())
}
if len(row) != 4 {
if len(row) != 5 {
return grmi.NewBusinessError("excel数据列数不合规, 行数:" + strconv.Itoa(rowIndex))
}
productFamilyId := row[0]
@ -3982,6 +3986,17 @@ func (impl *CustOrderServiceImplement) AnalysisPlanFromExcel(user *global.User,
if planDate.Before(today) {
return grmi.NewBusinessError("计划日期不能早于今天")
}
if rowIndex == 2 {
startDate = planDate
endDate = planDate
}
if planDate.Before(startDate) {
startDate = planDate
}
if endDate.Before(planDate) {
endDate = planDate
}
workLineId := row[4]
productFamily, exist := productFamilyMap[productFamilyId]
if !exist {
productFamily, err = productFamilyDao.SelectOne(productFamilyId)
@ -3993,6 +4008,29 @@ func (impl *CustOrderServiceImplement) AnalysisPlanFromExcel(user *global.User,
}
productFamilyMap[productFamilyId] = productFamily
}
if !productFamily.MultiWorkLineToggle {
if productFamily.WorkLineId != workLineId {
return grmi.NewBusinessError("派生指定的产线不可生产, 派生ID:" + productFamilyId + ", 产线ID:" + workLineId)
}
} else {
workLineLi, err := productFamilyWorkLineDao.Select([]grmi.Predicate{
meMeta.ProductFamilyWorkLineLst_ProductFamilyId.NewPredicate(grmi.Equal, productFamilyId),
}, nil)
if err != nil {
return grmi.NewBusinessError("查询派生可生产产线失败, 错误:" + err.Error())
}
var match bool
for _, workLine := range workLineLi {
if workLine.WorkLineId == workLineId {
match = true
break
}
}
if !match {
return grmi.NewBusinessError("派生指定的产线不可生产, 派生ID:" + productFamilyId + ", 产线ID:" + workLineId)
}
}
project, exist := projectMap[projectId]
if !exist {
project, err = projectDao.SelectOne(projectId)
@ -4015,89 +4053,45 @@ func (impl *CustOrderServiceImplement) AnalysisPlanFromExcel(user *global.User,
ModelValue: productFamily.ModelValue,
ColorValue: productFamily.ColorValue,
PlanQty: qty,
WorkLineId: productFamily.WorkLineId,
WorkLineId: workLineId,
QuantityPerHour: int(productFamily.Jph),
PlanStartDate: grmi.Date(planDate),
PlanEndDate: grmi.Date(planDate),
}
planDateCustOrderMap[planDate.Format(grmi.DateOutFormat)] = append(planDateCustOrderMap[planDate.Format(grmi.DateOutFormat)], custOrder)
}
// 计算计划时间
// 如果根据所有的jph当天时间够用 根据jph进行分配时间 如果不够根据数量占用所有时间
// 查询当天是否有计划客户订单
for planDate, custOrderLi := range planDateCustOrderMap {
dayStartTime := planDate + " 00:00:00"
dayEndTime := planDate + " 23:59:59"
existCustOrderLi, err := custOrderDao.SelectCrossDayCustOrder(dayEndTime)
if err != nil {
return grmi.NewBusinessError("查询已存在的客户订单数据失败, 错误:" + err.Error())
SourceId: "EXCEL",
}
if len(existCustOrderLi) != 0 {
return grmi.NewBusinessError("计划日期中存在跨天的客户订单,无法计划客户订单, 日期:" + planDate)
custOrder.OrderStatus = model.CustOrderStatus{
Status: baseModel.ORDER_STATUS_UNPLANED,
}
existCustOrderLi, err = custOrderDao.SelectCurrentDayCustOrder(dayStartTime, dayEndTime)
if err != nil {
return grmi.NewBusinessError("查询已存在的客户订单数据失败, 错误:" + err.Error())
}
var startPlanTime time.Time
// 如果当天没有客户订单 使用的开始时间从0点开始
if len(existCustOrderLi) == 0 {
startPlanTime, _ = time.ParseInLocation(grmi.DateTimeOutFormat, dayStartTime, utils.TimezoneLocation)
} else {
startPlanTime = existCustOrderLi[0].PlanEndTime.Restore()
custOrder.OrderQty = model.CustOrderQty{
PlanQty: custOrder.PlanQty,
}
if startPlanTime.Before(time.Now()) {
startPlanTime = time.Now()
custOrderWorkLineMap[workLineId] = append(custOrderWorkLineMap[workLineId], custOrder)
}
// 产线组与所属产线的MAP数据结构
workLineGroupMap := make(map[string]map[string]interface{})
workLineMap := make(map[string]baseModel.WorkLine)
allWorkLineLi, err := workLineDao.Select(nil, nil)
if err != nil {
return grmi.NewBusinessError("查询工厂产线数据失败, 错误:" + err.Error())
}
for _, workLine := range allWorkLineLi {
workLineMap[workLine.WorkLineid] = workLine
if workLine.GroupType == baseModel.WORK_LINE_TYPE_GROUP {
workLineGroupMap[workLine.WorkLineid] = make(map[string]interface{})
}
// 按照jph计算当时的时间
useTimeMap := make(map[int]int)
var allUsedSeconds int
var allQty int
for index, custOrder := range custOrderLi {
jph := productFamilyMap[custOrder.ProductFamilyId].Jph
planQty := custOrder.PlanQty
useSeconds := 3600 / int(jph) * planQty
useTimeMap[index] = useSeconds
allUsedSeconds += useSeconds
allQty += custOrder.PlanQty
}
endPlanTme := startPlanTime.Add(time.Second * time.Duration(allUsedSeconds))
// 如果计算结束时间大于当天则时间剩余时间分配 如果没有大于当天则时间计划时间
endDayTime, _ := time.ParseInLocation(grmi.DateTimeOutFormat, dayEndTime, utils.TimezoneLocation)
prePlanEndTime := startPlanTime
if endPlanTme.After(endDayTime) {
// 当天还可以使用的时间
CanUsedTime := endDayTime.Sub(startPlanTime).Seconds()
// 没台套使用的时间 单位s
perCarUsedTime := int(CanUsedTime) / allQty
if perCarUsedTime < 60 {
return grmi.NewBusinessError("分配给每个台套的时间已不足一分钟, 日期:" + planDate)
}
for index, custOrder := range custOrderLi {
custOrder.PlanStartTime = grmi.DateTime(prePlanEndTime)
custOrder.PlanEndTime = grmi.DateTime(prePlanEndTime.Add(time.Duration(custOrder.PlanQty*perCarUsedTime) * time.Second))
prePlanEndTime = custOrder.PlanEndTime.Restore()
custOrderLi[index] = custOrder
}
} else {
for index, custOrder := range custOrderLi {
custOrder.PlanStartTime = grmi.DateTime(prePlanEndTime)
usedTime := useTimeMap[index]
custOrder.PlanEndTime = grmi.DateTime(prePlanEndTime.Add(time.Duration(usedTime) * time.Second))
prePlanEndTime = custOrder.PlanEndTime.Restore()
custOrderLi[index] = custOrder
}
for _, workLine := range allWorkLineLi {
if workLine.GroupType == baseModel.WORK_LINE_TYPE_REAL {
_, exist := workLineGroupMap[workLine.GroupLineId]
if exist {
workLineGroupMap[workLine.GroupLineId][workLine.WorkLineid] = nil
}
}
planDateCustOrderMap[planDate] = custOrderLi
}
if err = session.Begin(); err != nil {
return grmi.NewBusinessError("开启事务失败, 错误:" + err.Error())
}
for _, custOrderLi := range planDateCustOrderMap {
custOrderStatusLi := make([]model.CustOrderStatus, 0, 20)
custOrderQtyLi := make([]model.CustOrderQty, 0, 20)
tempCustOrderLi := make([]model.CustOrder, 0, 20)
for workLineId, custOrderLi := range custOrderWorkLineMap {
for index, custOrder := range custOrderLi {
project := projectMap[custOrder.ProjectId]
custOrderId, err := snrDao.GetNextSnr(project.CustOrderSnr)
@ -4106,54 +4100,191 @@ func (impl *CustOrderServiceImplement) AnalysisPlanFromExcel(user *global.User,
return grmi.NewBusinessError("获取客户订单流水号失败, 错误:" + err.Error())
}
custOrder.CustOrderId = custOrderId
custOrderStatus := model.CustOrderStatus{
CustOrderId: custOrderId,
Status: baseModel.WO_STATUS_PLANNED,
}
custOrderStatusLi = append(custOrderStatusLi, custOrderStatus)
custOrderQty := model.CustOrderQty{
CustOrderId: custOrderId,
PlanQty: custOrder.PlanQty,
custOrder.OrderQty.CustOrderId = custOrderId
custOrder.OrderStatus.CustOrderId = custOrderId
custOrderLi[index] = custOrder
}
custOrderWorkLineMap[workLineId] = custOrderLi
}
endDate = endDate.AddDate(0, 0, 2)
for workLineId, custOrderLi := range custOrderWorkLineMap {
plannedLi, err := impl.AutoScheduler(user, session, workLineId, startDate, endDate, custOrderLi)
if err != nil {
_ = session.Rollback()
return grmi.NewBusinessError("自动排程失败,错误:" + err.Error())
}
// 用于生成工艺的serialOrder map
productSerialOrderMap := make(map[string][]*omModel.SerialOrder)
for _, orderData := range plannedLi {
// 获取客户订单的车型配置下的所有座椅
productLi, err := productFamilyRelateDao.SelectProductByFamilyIdForCreateSerialOrder(orderData.ProjectId, orderData.ProductFamilyId)
if err != nil {
_ = session.Rollback()
return grmi.NewBusinessError("通过车型配置查询关联座椅产品失败, error:" + err.Error())
}
custOrderQtyLi = append(custOrderQtyLi, custOrderQty)
tempCustOrderLi = append(tempCustOrderLi, custOrder)
if index != 0 && index%20 == 0 {
err = custOrderDao.Insert(&tempCustOrderLi)
if len(productLi) == 0 {
_ = session.Rollback()
return grmi.NewBusinessError("该客户订单的车型配置未关联座椅产品")
}
// 通过客户订单的时间间隔进行切割 分配给每一个序列工单
duration := orderData.PlanEndTime.Restore().Sub(orderData.PlanStartTime.Restore())
totalQty := orderData.PlanQty * len(productLi)
orderData.OrderQty.SerialOrderQty = totalQty
orderData.OrderQty.ReleasedQty = orderData.OrderQty.PlanQty
err = custOrderQtyDao.UpdateOne(&orderData.OrderQty)
if err != nil {
_ = session.Rollback()
return grmi.NewBusinessError("更新客户订单数量失败, error:" + err.Error())
}
var current int
perDuration := duration.Seconds() / float64(totalQty)
var isFirstPieceToggle bool
var syncKey string
project := projectMap[orderData.ProjectId]
// 临时工单列表
serialOrderLi := make([]omModel.SerialOrder, 0)
// 临时工单状态列表
serialOrderStatusLi := make([]omModel.SerialOrderStatus, 0)
// 创建序列工单和工单状态
for i := 0; i < orderData.PlanQty; i++ {
syncKey = orderData.CustOrderId + "-" + strconv.Itoa(i)
serialNumber, err := snrDao.GetNextSnrWithTime(project.SerialOrderSnr, orderData.PlanStartTime.Restore())
if err != nil {
_ = session.Rollback()
return grmi.NewBusinessError("保存客户订单数据失败, 错误:" + err.Error())
return grmi.NewBusinessError("生成工单流水号失败, error:" + err.Error())
}
for _, product := range productLi {
// 获取生产使用的产线
var resourceId string
if product.MultiWorkLineToggle {
relateWorkLineLi, err := productWorkLineDao.Select([]grmi.Predicate{
meMeta.ProductWorkLineLst_ProductId.NewPredicate(grmi.Equal, product.ProductId),
meMeta.ProductWorkLineLst_ProjectId.NewPredicate(grmi.Equal, product.ProjectId),
}, nil)
if err != nil {
_ = session.Rollback()
return grmi.NewBusinessError("查询总成关联产线失败, 错误:" + err.Error())
}
canUsedWorkLineMap, exist := workLineGroupMap[orderData.WorkLineId]
if !exist {
_ = session.Rollback()
return grmi.NewBusinessError("未获取到该派生产线组下的实体产线")
}
for _, workLine := range relateWorkLineLi {
_, exist = canUsedWorkLineMap[workLine.WorkLineId]
if exist {
if resourceId == "" {
resourceId = workLine.WorkLineId
} else {
_ = session.Rollback()
return grmi.NewBusinessError("总成在关联了可生产产线,总成ID:" + product.ProductId)
}
}
}
if resourceId == "" {
_ = session.Rollback()
return grmi.NewBusinessError("未获取到可生产的产线")
}
} else {
resourceId = product.DefaultWorkLineId
}
planStartTime := orderData.PlanStartTime.Restore().Add(time.Duration(int(perDuration)*current) * time.Second)
planEndTime := orderData.PlanStartTime.Restore().Add(time.Duration(int(perDuration)*(current+1)) * time.Second)
current++
planStartDate := grmi.Date(planStartTime)
planEndDate := grmi.Date(planEndTime)
serialOrderId := product.MachineCode + serialNumber + product.ProductType + product.ColorValue
timeInt, err := strconv.Atoi(planStartTime.Format("060102150405"))
if err != nil {
_ = session.Rollback()
return grmi.NewBusinessError("通过时间获取工单调度Key失败, error:" + err.Error())
}
var dealedSchedKey = int64(timeInt * 100)
if i == 0 {
isFirstPieceToggle = true
}
serialOrder := omModel.SerialOrder{
SerialOrderId: serialOrderId,
ArtId: product.ProductId,
ProjectId: orderData.ProjectId,
Descr: product.Descr,
CustOrderId: orderData.CustOrderId,
OrderType: baseModel.ODER_TYPE_SEQ,
PlanResourceId: resourceId,
UsedResourceId: resourceId,
SchedKey: dealedSchedKey,
PlanQty: 1,
PlanStartDate: planStartDate,
PlanEndDate: planEndDate,
PlanStartTime: grmi.DateTime(planStartTime),
PlanEndTime: grmi.DateTime(planEndTime),
PickingFlag: product.PickingFlag,
IsFirstPieceToggle: isFirstPieceToggle,
SyncKey: syncKey,
}
isFirstPieceToggle = false
serialOrderLi = append(serialOrderLi, serialOrder)
serialOrderStatus := omModel.SerialOrderStatus{
SerialOrderId: serialOrderId,
Status: baseModel.WO_STATUS_RELEASED,
}
serialOrderStatusLi = append(serialOrderStatusLi, serialOrderStatus)
_, exist := productSerialOrderMap[product.ProductId]
if !exist {
productSerialOrderMap[product.ProductId] = make([]*omModel.SerialOrder, 0)
}
productSerialOrderMap[product.ProductId] = append(productSerialOrderMap[product.ProductId], &serialOrder)
}
err = custOrderStatusDao.Insert(&custOrderStatusLi)
}
// 将工单数据落库
tempSerialOrderLi := make([]omModel.SerialOrder, 0, 20)
for index, serialOrder := range serialOrderLi {
if index%20 == 0 && index != 0 {
err = serialOrderDao.Insert(&tempSerialOrderLi)
if err != nil {
_ = session.Rollback()
return grmi.NewBusinessError("插入序列工单数据失败, error:" + err.Error())
}
tempSerialOrderLi = make([]omModel.SerialOrder, 0, 20)
}
tempSerialOrderLi = append(tempSerialOrderLi, serialOrder)
}
if len(tempSerialOrderLi) != 0 {
err = serialOrderDao.Insert(&tempSerialOrderLi)
if err != nil {
_ = session.Rollback()
return grmi.NewBusinessError("保存客户订单状态数据失败, 错误:" + err.Error())
return grmi.NewBusinessError("插入序列工单数据失败, error:" + err.Error())
}
}
tempSerialOrderStatusLi := make([]omModel.SerialOrderStatus, 0, 20)
for index, serialOrderStatus := range serialOrderStatusLi {
if index%20 == 0 && index != 0 {
err = serialOrderStatusDao.Insert(&tempSerialOrderStatusLi)
if err != nil {
_ = session.Rollback()
return grmi.NewBusinessError("插入序列工单状态数据失败, error:" + err.Error())
}
tempSerialOrderStatusLi = make([]omModel.SerialOrderStatus, 0, 20)
}
err = custOrderQtyDao.Insert(&custOrderQtyLi)
tempSerialOrderStatusLi = append(tempSerialOrderStatusLi, serialOrderStatus)
}
if len(tempSerialOrderStatusLi) != 0 {
err = serialOrderStatusDao.Insert(&tempSerialOrderStatusLi)
if err != nil {
_ = session.Rollback()
return grmi.NewBusinessError("保存客户订单数据量数据失败, 错误:" + err.Error())
return grmi.NewBusinessError("插入序列工单状态数据失败, error:" + err.Error())
}
custOrderStatusLi = make([]model.CustOrderStatus, 0, 20)
custOrderQtyLi = make([]model.CustOrderQty, 0, 20)
tempCustOrderLi = make([]model.CustOrder, 0, 20)
}
}
if len(tempCustOrderLi) != 0 {
err = custOrderDao.Insert(&tempCustOrderLi)
if err != nil {
_ = session.Rollback()
return grmi.NewBusinessError("保存客户订单数据失败, 错误:" + err.Error())
}
err = custOrderStatusDao.Insert(&custOrderStatusLi)
if err != nil {
_ = session.Rollback()
return grmi.NewBusinessError("保存客户订单状态数据失败, 错误:" + err.Error())
}
err = custOrderQtyDao.Insert(&custOrderQtyLi)
if err != nil {
_ = session.Rollback()
return grmi.NewBusinessError("保存客户订单数据量数据失败, 错误:" + err.Error())
}
// 创建serialOrder service接口
serialOrderSvr := omSvr.NewSerialOrderService()
err = serialOrderSvr.GenerateCraftDataByCustOrder(user, session, productSerialOrderMap)
if err != nil {
_ = session.Rollback()
return grmi.NewBusinessError("生成工艺数据失败, error:" + err.Error())
}
}
_ = session.Commit()
@ -4207,3 +4338,94 @@ func (impl *CustOrderServiceImplement) QuickSortProductData(values []model.HourP
impl.QuickSortProductData(values[:head])
impl.QuickSortProductData(values[head+1:])
}
// AutoScheduler 自动排程 同时对客户订单进行落库
func (impl *CustOrderServiceImplement) AutoScheduler(user *global.User, session *xorm.Session, workLineId string, startDate time.Time, endDate time.Time, unplannedCustOrderLi []model.CustOrder) ([]model.CustOrder, error) {
var (
schedEngine schedule.SchedulerSrv
err error
)
returnCustOrderLi := make([]model.CustOrder, 0, len(unplannedCustOrderLi))
custOrderMap := make(map[string]*model.CustOrder)
for index, custOrder := range unplannedCustOrderLi {
custOrderMap[custOrder.CustOrderId] = &unplannedCustOrderLi[index]
}
endDate = endDate.Add(1 * time.Second)
schedEngine = schedule.SchedulerSrv{PlantNr: user.PlantNr, StartDate: startDate, EndDate: endDate}
schedEngine.Tmsrv.StartDate = startDate
schedEngine.Tmsrv.EndDate = endDate
custOrderDao := dal.NewCustOrderDAO(session, user.PlantNr, user.UserId)
custOrderQtyDao := dal.NewCustOrderQtyDAO(session, user.PlantNr, user.UserId)
custOrderStatusDao := dal.NewCustOrderStatusDAO(session, user.PlantNr, user.UserId)
// 加载激活的项目主数据
err = schedEngine.LoadProjectData()
if err != nil {
return nil, err
}
// 加载时间模型,基于调度引擎指定的时间区间
err = schedEngine.LoadTimeModel(session, workLineId)
// 加载产品换型主数据
err = schedEngine.LoadSetupData()
if err != nil {
return nil, err
}
// 加载产线主数据
err = schedEngine.LoadWorkLineData(workLineId)
if err != nil {
return nil, err
}
// 加载产线班组计划出勤数据
err = schedEngine.LoadWorkLineWorkShiftData()
if err != nil {
return nil, err
}
// 生成产线的时间曲线
err = schedEngine.GenerateWorkLineTimeCurve()
if err != nil {
return nil, err
}
// 加载工单数据(调度任务)
err = schedEngine.LoadSchedCustTask(session, workLineId, unplannedCustOrderLi)
if err != nil {
return nil, err
}
// 对调度任务进行排序
schedEngine.SortUnplannedCustOrder()
// 依次调度未计划工单
err = schedEngine.AutoSchedule()
if err != nil {
return nil, err
}
// 将已计划的客户订单进行落库 状态设置为26
for _, plannedTask := range schedEngine.UnPlannedTaskArray {
//过滤订单状态大于20的订单
if plannedTask.CustOrderStatus.Status > baseModel.WO_STATUS_PLANNED {
continue
}
// 保存客户订单数据
custOrder := custOrderMap[plannedTask.TaskId]
custOrder.PlanEndDate = grmi.Date(plannedTask.SchedEndTime)
custOrder.PlanStartTime = grmi.DateTime(plannedTask.SchedStartTime)
custOrder.PlanEndTime = grmi.DateTime(plannedTask.SchedEndTime)
err = custOrderDao.InsertOne(custOrder)
if err != nil {
return nil, grmi.NewBusinessError("保存客户订单数据失败, 错误:" + err.Error())
}
custOrderStatus := custOrder.OrderStatus
custOrderStatus.Status = baseModel.WO_STATUS_RELEASED
err = custOrderStatusDao.InsertOne(&custOrderStatus)
if err != nil {
return nil, grmi.NewBusinessError("保存客户订单状态失败, 错误:" + err.Error())
}
err = custOrderQtyDao.InsertOne(&custOrder.OrderQty)
if err != nil {
return nil, grmi.NewBusinessError("保存客户订单数量失败, 错误:" + err.Error())
}
returnCustOrderLi = append(returnCustOrderLi, *custOrder)
}
return returnCustOrderLi, nil
}

+ 120
- 5
services/schedule/Scheduler.Ctrl.go View File

@ -16,6 +16,7 @@ import (
"LAPP_ACURA_MOM_BACKEND/utils"
"errors"
"fmt"
"github.com/go-xorm/xorm"
uuid "github.com/iris-contrib/go.uuid"
"reflect"
"strconv"
@ -132,6 +133,37 @@ func (schedsrv *SchedulerSrv) LoadTimeModelData(workLineId string) (err error) {
return nil
}
// LoadTimeModel 加载时间模型
func (schedsrv *SchedulerSrv) LoadTimeModel(session *xorm.Session, workLineId string) (err error) {
//查询边界开始日期
// 查询已经分配到产线上的客户订单
var custOrderLi []plnModel.CustOrder
dao := plnDal.NewCustOrderDAO(session, schedsrv.PlantNr, "scheduler")
if custOrderLi, err = dao.SelectWorkLineTaskBeyondStatus(schedsrv.StartDate, schedsrv.EndDate, workLineId, common.WO_STATUS_PLANNED); err != nil {
return grmi.NewBusinessError("加载已经分配到产线上的客户订单失败, error:" + err.Error())
}
if len(custOrderLi) > 1 {
PlanStartDate := custOrderLi[0].PlanStartDate.Restore()
if PlanStartDate.Unix() < schedsrv.StartDate.Unix() {
schedsrv.StartDate = PlanStartDate
}
}
// 初始化
schedsrv.Tmsrv = TimeModelSrv{PlantNr: schedsrv.PlantNr, StartDate: schedsrv.StartDate, EndDate: schedsrv.EndDate}
// 加载指定日期范畴内的时间模型相关主数据
err = schedsrv.Tmsrv.LoadBasicData(schedsrv.StartDate, schedsrv.EndDate)
if err != nil {
return grmi.NewBusinessError("加载时间模型主数据失败, error:" + err.Error())
}
// 生成日模型的时间线列表
err = schedsrv.Tmsrv.GenDayModelLineArray()
if err != nil {
return grmi.NewBusinessError("日模型时间线失败, error:" + err.Error())
}
return nil
}
// LoadWorkLineWorkShiftData 加载产线班次的实际出勤数据,指定时段,没有按班次指定的默认值填充
func (schedsrv *SchedulerSrv) LoadWorkLineWorkShiftData() (err error) {
// 遍历产线
@ -235,6 +267,49 @@ func (schedsrv *SchedulerSrv) LoadSchedTaskData(workLineId string) (err error) {
return
}
// LoadSchedCustTask 加载调度任务
func (schedsrv *SchedulerSrv) LoadSchedCustTask(session *xorm.Session, workLineId string, unPlannedCustOrderLi []plnModel.CustOrder) (err error) {
var (
i int
tasksrv TaskSrv
custOrderLi []plnModel.CustOrder
)
// 初始化
schedsrv.LockedTaskArray = []TaskSrv{}
schedsrv.PlannedTaskArray = []TaskSrv{}
schedsrv.UnPlannedTaskArray = []TaskSrv{}
// 加载调度任务数据
// 1. 按实际开始时间先后加载状态 >= 24已开始的任务
dao := plnDal.NewCustOrderDAO(session, schedsrv.PlantNr, "scheduler")
if custOrderLi, err = dao.SelectWorkLineTaskBeyondStatus(schedsrv.StartDate, schedsrv.EndDate, workLineId, common.WO_STATUS_LOCKED); err != nil {
return grmi.NewBusinessError("加载已锁定及以上的客户订单失败, error:" + err.Error())
}
for i = 0; i < len(custOrderLi); i++ {
tasksrv = TaskSrv{}
tasksrv.Init(custOrderLi[i])
schedsrv.LockedTaskArray = append(schedsrv.LockedTaskArray, tasksrv)
}
// 2. 按计划开始时间先后加载状态 = 20 的已计划任务
if custOrderLi, err = dao.SelectWorkLineTaskEqualStatus(schedsrv.StartDate, schedsrv.EndDate, workLineId, common.WO_STATUS_PLANNED); err != nil {
return grmi.NewBusinessError("加载已计划的客户订单失败, error:" + err.Error())
}
for i = 0; i < len(custOrderLi); i++ {
tasksrv = TaskSrv{}
tasksrv.Init(custOrderLi[i])
schedsrv.PlannedTaskArray = append(schedsrv.PlannedTaskArray, tasksrv)
}
// 3. 按指定规则加载未计划的任务
//if custOrderLi, err = dao.SelectUnPlannedCustOrder(workLineId); err != nil {
// return grmi.NewBusinessError("加载未计划的客户订单失败, error:" + err.Error())
//}
for i = 0; i < len(unPlannedCustOrderLi); i++ {
tasksrv = TaskSrv{}
tasksrv.Init(unPlannedCustOrderLi[i])
schedsrv.UnPlannedTaskArray = append(schedsrv.UnPlannedTaskArray, tasksrv)
}
return
}
// RetrieveSchedule 撤回计划,将未下达的任务全部更新为未计划
func (schedsrv *SchedulerSrv) RetrieveSchedule() {
var schedTask TaskSrv
@ -1104,6 +1179,39 @@ func (schedsrv *SchedulerSrv) SortUnplannedTask() {
})
}
// 对调度任务进行排序
func (schedsrv *SchedulerSrv) SortUnplannedCustOrder() {
var (
i int
sortTasks []interface{}
)
// 计算排序任务的排序属性
//for i = 0; i < len(schedsrv.UnPlannedTaskArray); i++ {
//
//}
// 准备排序
sortTasks = []interface{}{}
for i = 0; i < len(schedsrv.UnPlannedTaskArray); i++ {
sortTasks = append(sortTasks, schedsrv.UnPlannedTaskArray[i])
}
SortBody(sortTasks, func(p, q *interface{}) bool {
v1 := reflect.ValueOf(*p)
i := v1.FieldByName("PlanStartDate")
v2 := reflect.ValueOf(*q)
j := v2.FieldByName("PlanStartDate")
if i.String() != j.String() {
return i.String() < j.String()
} else {
m := v1.FieldByName("CustOrderId")
n := v2.FieldByName("CustOrderId")
return m.String() < n.String()
}
})
}
// 调度引擎自动排程
func (schedsrv *SchedulerSrv) AutoSchedule() (err error) {
var (
@ -1111,21 +1219,28 @@ func (schedsrv *SchedulerSrv) AutoSchedule() (err error) {
)
// 遍历已锁定任务,先占位
for i = 0; i < len(schedsrv.LockedTaskArray); i++ {
schedsrv.ScheduleTask(schedsrv.LockedTaskArray[i].SchedResId, &schedsrv.LockedTaskArray[i])
err = schedsrv.ScheduleTask(schedsrv.LockedTaskArray[i].SchedResId, &schedsrv.LockedTaskArray[i])
if err != nil {
return err
}
}
// 遍历已计划任务,占位
for i = 0; i < len(schedsrv.PlannedTaskArray); i++ {
schedsrv.ScheduleTask(schedsrv.PlannedTaskArray[i].SchedResId, &schedsrv.PlannedTaskArray[i])
err = schedsrv.ScheduleTask(schedsrv.PlannedTaskArray[i].SchedResId, &schedsrv.PlannedTaskArray[i])
if err != nil {
return err
}
}
// 将未计划任务排序
// 遍历未计划任务
for i = 0; i < len(schedsrv.UnPlannedTaskArray); i++ {
// 此处可以增加选择调度资源逻辑
// 将未计划任务调度到指定的计划资源上
schedsrv.ScheduleTask(schedsrv.UnPlannedTaskArray[i].SchedResId, &schedsrv.UnPlannedTaskArray[i])
err = schedsrv.ScheduleTask(schedsrv.UnPlannedTaskArray[i].SchedResId, &schedsrv.UnPlannedTaskArray[i])
if err != nil {
return err
}
}
return
}


Loading…
Cancel
Save