package schedule import ( "errors" "fmt" "leit.com/LAPP_GAAS_GFrame/models" "time" ) // 调度批次任务对象 type TaskSrv struct { TaskId string TaskType string PlantNr int ProjectId string SortKey int64 // 用于给MES用的排序号 ArtId string // 任务产品ID Priority int Status int SchedResGrpId string // 调度资源组ID SchedResId string // 调度资源 FixResource bool // 锁定资源 PlanQty float64 // 计划数量 ReleasedQty float64 // 已下达数量 - 每个独立生成序列订单 FinishedQty float64 // 已完成数量 Duration time.Duration // 任务所需工时 EarliestStartTime time.Time // 最早开始时间 LatestEndTime time.Time // 最迟结束时间 SetupStartTime time.Time // 换型开始时间 SetupEndTime time.Time // 换型结束时间 FixStartTime bool // 锁定派车给开始时间 SchedStartTime time.Time // 排程开始时间 SchedEndTime time.Time // 排程结束时间 ActStartTime time.Time // 实际开始时间 ActEndTime time.Time // 实际结束时间 Wotab models.OmWorkorder WoStatusTab models.OmWorkorderstatus WoQtyTab models.OmWorkorderqty SerialTaskArray []SerialTaskSrv // 批次订单的序列订单 } // 序列任务对象 type SerialTaskSrv struct { TaskId string TaskType string ParentTaskId string PlantNr int ProjectId string Barcode string // 序列订单条码 ArtId string // 任务产品ID Status int SchedResId string // 调度资源 PlanQty float64 // 计划数量 Duration time.Duration // 任务所需工时 EarliestStartTime time.Time // 最早开始时间 LatestEndTime time.Time // 最迟结束时间 SetupStartTime time.Time // 换型开始时间 SetupEndTime time.Time // 换型结束时间 SchedStartTime time.Time // 排程开始时间 SchedEndTime time.Time // 排程结束时间 ActStartTime time.Time // 实际开始时间 ActEndTime time.Time // 实际结束时间 SerialOrderTab models.OmSerialorder SerialOrderStatusTab models.OmSerialorderstatus } // 基于指定的批次订单号获取批次订单对象 func(tasksrv *TaskSrv)Get()(err error){ var wotab models.OmWorkorder wotab = models.OmWorkorder{Plantnr: tasksrv.PlantNr, Workorderid: tasksrv.TaskId} if wotab, err = wotab.SelectOne(); err != nil{ err = errors.New(fmt.Sprintf("获取工厂%d批次订单%s失败!",tasksrv.PlantNr,tasksrv.TaskId)) return } tasksrv.Init(wotab) return } // 基于给定的订单表和订单状态表进行结构初始化 func(tasksrv *TaskSrv)Init(wotab models.OmWorkorder){ // 初始化批次任务的批次订单信息 tasksrv.TaskId = wotab.Workorderid tasksrv.TaskType = wotab.Ordertype tasksrv.SortKey = wotab.Planstarttime.Unix() // 用于给MES用的排序号 tasksrv.ArtId = wotab.Artid // 任务产品ID tasksrv.Priority = wotab.Priority // 优先级 tasksrv.Status = wotab.Wostatustab.Status // 订单状态 tasksrv.SchedResGrpId = wotab.Planresourcegroupid // 调度资源组ID tasksrv.SchedResId = wotab.Planresourceid // 调度资源 tasksrv.FixResource = false // 锁定资源 tasksrv.PlanQty = float64(wotab.Planqty ) // 计划数量 tasksrv.ReleasedQty = float64(wotab.Woqtytab.Releasedqty) // 已下达数量 - 每个独立生成序列订单 tasksrv.FinishedQty = float64(wotab.Woqtytab.Actqty) // 已完成数量 tasksrv.EarliestStartTime = wotab.Planstartdate // 最早开始时间 tasksrv.LatestEndTime = wotab.Planendtime // 最迟结束时间 tasksrv.SetupStartTime = wotab.Setupstarttime // 换型开始时间 tasksrv.SetupEndTime = wotab.Setupendtime // 换型结束时间 if wotab.Fixstarttime > 0 { // 锁定开始时间 tasksrv.FixStartTime = true }else{ tasksrv.FixStartTime = false } tasksrv.SchedStartTime = wotab.Planstarttime // 排程开始时间 tasksrv.SchedEndTime = wotab.Planendtime // 排程结束时间 tasksrv.ActStartTime = wotab.Actstarttime // 实际开始时间 tasksrv.ActEndTime = wotab.Actendtime // 实际结束时间 // 获取调度任务所需要的工时 calQty := wotab.Planqty - wotab.Woqtytab.Actqty if wotab.Rateperhourtoggle > 0 { if wotab.Quantityperhour <= 0 { tasksrv.Duration = 0 }else{ tasksrv.Duration = time.Duration(calQty / wotab.Quantityperhour) * time.Hour } } if wotab.Timeperitemtoggle > 0 { perItemSeconds := float64(wotab.Optimeperitem) * GetTimeUomSeconds(wotab.Timeuomid) tasksrv.Duration = time.Duration(float64(calQty) * perItemSeconds ) * time.Second } if wotab.Timeperbatchtoggle > 0 { if wotab.Batchtime <= 0 || wotab.Batchquantity <= 0{ tasksrv.Duration = 0 }else{ perBatchSeconds := float64(wotab.Batchtime) * GetTimeUomSeconds(wotab.Timeuomid) tasksrv.Duration = time.Duration(perBatchSeconds * float64(calQty) / float64(wotab.Batchquantity)) * time.Hour } } tasksrv.Wotab = wotab tasksrv.WoStatusTab = wotab.Wostatustab tasksrv.WoQtyTab = wotab.Woqtytab } // 加载批次订单的序列订单 func(tasksrv *TaskSrv)LoadSerialOrders()(err error){ var( i int sordertab models.OmSerialorder sordertablst []models.OmSerialorder serialtasksrv SerialTaskSrv ) // 初始化批次订单的序列订单信息 tasksrv.SerialTaskArray = []SerialTaskSrv{} sordertab = models.OmSerialorder{Plantnr: tasksrv.Wotab.Plantnr, Workorderid: tasksrv.Wotab.Workorderid} if sordertablst, err = sordertab.SelectByBatchOrder(); err != nil{ err = errors.New(fmt.Sprintf("查询批次订单%s的序列订单失败!",sordertab.Workorderid)) return } for i = 0; i < len(sordertablst); i++ { serialtasksrv = SerialTaskSrv{} serialtasksrv.Init(sordertablst[i]) tasksrv.SerialTaskArray = append(tasksrv.SerialTaskArray, serialtasksrv) } return } // 生成状态记录 func(tasksrv *TaskSrv)CreateStatusRecord(prevstatus int, eventsrv EventSrv)(err error){ var wostatusrectab models.OMWorkorderstatusrecLst // 初始化 wostatusrectab = models.OMWorkorderstatusrecLst{} wostatusrectab.Plantnr = tasksrv.PlantNr wostatusrectab.Workorderid = tasksrv.TaskId wostatusrectab.Prevstatus = prevstatus wostatusrectab.Status = tasksrv.Status wostatusrectab.Triggerevent = eventsrv.TriggerEvent wostatusrectab.Triggerobjectid = eventsrv.TriggerObjectId wostatusrectab.Triggersubobjectid = eventsrv.TriggerSubObjectId wostatusrectab.Outputstatus = OUTPUT_TRIGGER_UNHANDLED // 未处理 wostatusrectab.Outputevent = eventsrv.OutputEvent wostatusrectab.OutputeventmessageId = eventsrv.OutputEventMsgId wostatusrectab.OutputobjectId = eventsrv.OutputObjectId wostatusrectab.OutputsubobjectId = eventsrv.OutputSubObjectId SetTableLastModify(&wostatusrectab, wostatusrectab, MODIFY_MODE_CREATE, eventsrv.TriggerService) if err = wostatusrectab.Add(); err != nil { err = errors.New(fmt.Sprintf("无法为工单%s插入状态变更记录%v!",tasksrv.TaskId, err)) return } return } // 下达批次订单 func(tasksrv *TaskSrv)Release()(err error){ var( wostatrectab models.OMWorkorderstatusrecLst ) if tasksrv.WoStatusTab.Status != WO_STATUS_LOCKED { err = errors.New(fmt.Sprintf("批次订单%s状态%d不满足下达条件,无法下达!", tasksrv.WoStatusTab.Workorderid, tasksrv.WoStatusTab.Status)) return } // 变更状态 tasksrv.Status = WO_STATUS_RELEASED tasksrv.WoStatusTab.Status = WO_STATUS_RELEASED SetTableLastModify(&tasksrv.WoStatusTab, tasksrv.WoStatusTab,MODIFY_MODE_UPDATE,"rel_service") if err = tasksrv.WoStatusTab.Update(); err != nil{ err = errors.New(fmt.Sprintf("批次订单%s更新状态出错%v!", tasksrv.WoStatusTab.Workorderid, err)) return } // 新增批次订单状态变更记录 wostatrectab = models.OMWorkorderstatusrecLst{} wostatrectab.Plantnr = tasksrv.WoStatusTab.Plantnr wostatrectab.Workorderid = tasksrv.WoStatusTab.Workorderid wostatrectab.Prevstatus = WO_STATUS_LOCKED wostatrectab.Status = WO_STATUS_RELEASED wostatrectab.Triggerevent = BATORD_EVENT_RELEASE wostatrectab.Triggerobjectid = tasksrv.WoStatusTab.Workorderid wostatrectab.Outputstatus = OUTPUT_TRIGGER_UNHANDLED wostatrectab.Outputevent = BATORD_EVENT_RELEASE wostatrectab.OutputobjectId = tasksrv.WoStatusTab.Workorderid SetTableLastModify(&wostatrectab, wostatrectab, MODIFY_MODE_CREATE,"rel_service") if err = wostatrectab.Add(); err != nil{ err = errors.New(fmt.Sprintf("批次订单%s无法插入状态变更记录%v!", tasksrv.WoStatusTab.Workorderid, err)) return } return } // 下达批次订单,同步生成对应的序列订单 func(tasksrv *TaskSrv)ReleaseSerialOrder(relqty int)(err error){ var( i,actrelqty int ) // 获取批次订单对象 if err = tasksrv.Get(); err != nil{ return } // 判断批次订单状态是否满足下达条件 >= 24 && < 80 if tasksrv.WoStatusTab.Status < WO_STATUS_LOCKED || tasksrv.WoStatusTab.Status >= WO_STATUS_FINISHED { err = errors.New(fmt.Sprintf("批次订单%s状态%d不满足下达条件,无法下达!", tasksrv.WoStatusTab.Workorderid, tasksrv.WoStatusTab.Status)) return } // 获取批次订单已下达序列订单 if err = tasksrv.LoadSerialOrders(); err != nil { return } // 计算实际可下达的序列订单数量 actrelqty = int(tasksrv.PlanQty) - len(tasksrv.SerialTaskArray) if actrelqty <= 0 { err = errors.New(fmt.Sprintf("批次订单%s可下达数量小于0!", tasksrv.WoStatusTab.Workorderid)) return } // 置位批次订单状态 if tasksrv.WoStatusTab.Status == WO_STATUS_LOCKED { if err = tasksrv.Release(); err != nil{ err = errors.New(fmt.Sprintf("下达批次订单%s失败!",tasksrv.TaskId)) return } } // 下达指定数量的序列订单,置位序列订单为26 for i = 0; i < actrelqty; i++ { } return } // 基于指定的序列订单号获取序列订单对象 func(stasksrv *SerialTaskSrv)Get()(err error){ var serordtab models.OmSerialorder serordtab = models.OmSerialorder{Plantnr: stasksrv.PlantNr, Workorderid: stasksrv.TaskId} if serordtab, err = serordtab.SelectOne(); err != nil{ err = errors.New(fmt.Sprintf("获取工厂%d序列订单%s失败!",stasksrv.PlantNr,stasksrv.TaskId)) return } stasksrv.Init(serordtab) return } // 初始化序列订单 func(stasksrv *SerialTaskSrv)Init(serialordertab models.OmSerialorder){ stasksrv.SerialOrderTab = serialordertab stasksrv.SerialOrderStatusTab = serialordertab.Serstatustab } // 创建序列订单 func(stasksrv *SerialTaskSrv)Create()(err error){ // 插入序列订单 stasksrv.SerialOrderTab = models.OmSerialorder{} stasksrv.SerialOrderTab.Plantnr = stasksrv.PlantNr stasksrv.SerialOrderTab.Projectid = stasksrv.ProjectId stasksrv.SerialOrderTab.Artid = stasksrv.ArtId stasksrv.SerialOrderTab.Workorderid = stasksrv.ParentTaskId stasksrv.SerialOrderTab.Planresourceid = stasksrv.SchedResId stasksrv.SerialOrderTab.Ordertype = stasksrv.TaskType stasksrv.SerialOrderTab.Serialorderid = stasksrv.TaskId stasksrv.SerialOrderTab.Planqty = float32(stasksrv.PlanQty) stasksrv.SerialOrderTab.Planstarttime = stasksrv.SchedStartTime stasksrv.SerialOrderTab.Planendtime = stasksrv.SchedEndTime SetTableLastModify(&stasksrv.SerialOrderTab, stasksrv.SerialOrderTab, MODIFY_MODE_CREATE, "rel_service") if err = stasksrv.SerialOrderTab.Add(); err != nil{ err = errors.New(fmt.Sprintf("工单%s的序列订单%s头创建失败%v!",stasksrv.ParentTaskId, stasksrv.TaskId, err)) return } // 插入序列订单状态行 stasksrv.SerialOrderStatusTab = models.OmSerialorderstatus{} stasksrv.SerialOrderStatusTab.Plantnr = stasksrv.PlantNr stasksrv.SerialOrderStatusTab.Serialorderid = stasksrv.TaskId stasksrv.SerialOrderStatusTab.Status = WO_STATUS_PLANNED stasksrv.SerialOrderStatusTab.Triggerobjectid = stasksrv.ParentTaskId stasksrv.SerialOrderStatusTab.Triggerevent = BATORD_EVENT_LOCK SetTableLastModify(&stasksrv.SerialOrderStatusTab, stasksrv.SerialOrderStatusTab, MODIFY_MODE_CREATE, "rel_service") if err = stasksrv.SerialOrderStatusTab.Add(); err != nil{ err = errors.New(fmt.Sprintf("工单%s的序列订单%s状态头创建失败%v!",stasksrv.ParentTaskId, stasksrv.TaskId, err)) return } // 插入序列订单状态记录行 // 如果需要触发动作可在此处添加 serordstatrectab := models.OmSerialorderstatusrecLst{} serordstatrectab.Plantnr = stasksrv.PlantNr serordstatrectab.Serialorderid = stasksrv.TaskId serordstatrectab.Prevstatus = 0 serordstatrectab.Status = WO_STATUS_PLANNED serordstatrectab.Outputevent = OUTPUT_EVENT_SER_NEW serordstatrectab.OutputobjectId = serordstatrectab.Serialorderid serordstatrectab.Outputstatus = OUTPUT_TRIGGER_UNHANDLED SetTableLastModify(&serordstatrectab, serordstatrectab, MODIFY_MODE_CREATE, "rel_service") if err = serordstatrectab.Add(); err != nil{ err = errors.New(fmt.Sprintf("工单%s的序列订单%s状态记录行创建失败%v!",stasksrv.ParentTaskId, stasksrv.TaskId, err)) return } return } // 下达序列订单 func(stasksrv *SerialTaskSrv)Release()(err error){ var prevstatus int // 判断序列订单是否可以被下达 if stasksrv.SerialOrderStatusTab.Status >= WO_STATUS_RELEASED { return } // 获取序列订单当前状态 prevstatus = stasksrv.SerialOrderStatusTab.Status // 更新序列订单状态行 stasksrv.SerialOrderStatusTab.Status = WO_STATUS_RELEASED stasksrv.SerialOrderStatusTab.Triggerobjectid = stasksrv.ParentTaskId stasksrv.SerialOrderStatusTab.Triggerevent = BATORD_EVENT_RELEASE SetTableLastModify(&stasksrv.SerialOrderStatusTab, stasksrv.SerialOrderStatusTab, MODIFY_MODE_UPDATE, "rel_service") if err = stasksrv.SerialOrderStatusTab.Update(); err != nil{ err = errors.New(fmt.Sprintf("工单%s的序列订单%s状态头更新失败%v!",stasksrv.ParentTaskId, stasksrv.TaskId, err)) return } // 插入序列订单状态记录行 // 如果需要触发动作可在此处添加 serordstatrectab := models.OmSerialorderstatusrecLst{} serordstatrectab.Plantnr = stasksrv.PlantNr serordstatrectab.Serialorderid = stasksrv.TaskId serordstatrectab.Prevstatus = prevstatus serordstatrectab.Status = WO_STATUS_RELEASED serordstatrectab.Outputevent = OUTPUT_EVENT_SER_REL serordstatrectab.OutputobjectId = serordstatrectab.Serialorderid serordstatrectab.Outputstatus = OUTPUT_TRIGGER_UNHANDLED SetTableLastModify(&serordstatrectab, serordstatrectab, MODIFY_MODE_UPDATE, "rel_service") if err = serordstatrectab.Add(); err != nil{ err = errors.New(fmt.Sprintf("工单%s的序列订单%s状态记录行创建失败%v!",stasksrv.ParentTaskId, stasksrv.TaskId, err)) return } return }