广汽安道拓Acura项目MES后台
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

379 lines
18 KiB

package schedule
import (
dal "LAPP_ACURA_MOM_BACKEND/dao/om"
plnDal "LAPP_ACURA_MOM_BACKEND/dao/pln"
"LAPP_ACURA_MOM_BACKEND/db"
"LAPP_ACURA_MOM_BACKEND/grmi"
common "LAPP_ACURA_MOM_BACKEND/models/base"
model "LAPP_ACURA_MOM_BACKEND/models/om"
plnModel "LAPP_ACURA_MOM_BACKEND/models/pln"
"errors"
"fmt"
"github.com/go-xorm/xorm"
"time"
)
// TaskSrv 调度批次任务对象
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 // 计划数量
CancelQty 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 // 实际结束时间
CustOrder plnModel.CustOrder
CustOrderStatus plnModel.CustOrderStatus
CustOrderQty plnModel.CustOrderQty
SerialTaskArray []SerialTaskSrv // 批次订单的序列订单
}
// 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 model.SerialOrder
SerialOrderStatusTab model.SerialOrderStatus
}
// Get 基于指定的批次订单号获取批次订单对象
func (tasksrv *TaskSrv) Get() (err error) {
engine := db.Eloquent.Master()
session := engine.NewSession()
defer session.Close()
dao := plnDal.NewCustOrderDAO(session, tasksrv.PlantNr, "scheduler")
var custOrder *plnModel.CustOrder
if custOrder, err = dao.SelectOne(tasksrv.TaskId); err != nil {
return grmi.NewBusinessError("获取工厂客户订单失败, 客户订单ID:" + tasksrv.TaskId + ", error:" + err.Error())
}
tasksrv.Init(*custOrder)
return
}
// Init 基于给定的订单表和订单状态表进行结构初始化
func (tasksrv *TaskSrv) Init(custOrder plnModel.CustOrder) {
// 初始化批次任务的批次订单信息
tasksrv.TaskId = custOrder.CustOrderId
tasksrv.TaskType = custOrder.OrderType
tasksrv.SortKey = custOrder.PlanStartTime.Restore().Unix() // 用于给MES用的排序号
tasksrv.ArtId = custOrder.ProductFamilyId // 任务产品ID
//tasksrv.Priority = custOrder.Priority // 优先级
tasksrv.Status = custOrder.OrderStatus.Status // 订单状态
//tasksrv.SchedResGrpId = wotab.PlanResourceGroupId // 调度资源组ID
tasksrv.SchedResId = custOrder.WorkLineId // 调度资源
tasksrv.FixResource = false // 锁定资源
tasksrv.PlanQty = float64(custOrder.OrderQty.PlanQty) // 计划数量
tasksrv.ReleasedQty = float64(custOrder.OrderQty.ReleasedQty) // 已下达数量 - 每个独立生成序列订单
tasksrv.FinishedQty = float64(custOrder.OrderQty.ActQty) // 已完成数量
tasksrv.CancelQty = float64(custOrder.OrderQty.CancelQty)
tasksrv.EarliestStartTime = custOrder.PlanStartDate.Restore() // 最早开始时间
tasksrv.LatestEndTime = custOrder.PlanEndTime.Restore() // 最迟结束时间
tasksrv.SetupStartTime = custOrder.SetupStartTime.Restore() // 换型开始时间
tasksrv.SetupEndTime = custOrder.SetupEndTime.Restore() // 换型结束时间
if custOrder.FixStartTimeToggle { // 锁定开始时间
tasksrv.FixStartTime = true
} else {
tasksrv.FixStartTime = false
}
tasksrv.SchedStartTime = custOrder.PlanStartTime.Restore() // 排程开始时间
tasksrv.SchedEndTime = custOrder.PlanEndTime.Restore() // 排程结束时间
tasksrv.ActStartTime = custOrder.ActStartTime.Restore() // 实际开始时间
tasksrv.ActEndTime = custOrder.ActEndTime.Restore() // 实际结束时间
// 获取调度任务所需要的工时
calQty := custOrder.PlanQty - custOrder.OrderQty.CancelQty
//if custOrder.RatePerHourToggle {
if custOrder.QuantityPerHour <= 0 || calQty <= 0 {
tasksrv.Duration = 0
} else {
tasksrv.Duration = time.Duration(float64(calQty)/float64(custOrder.QuantityPerHour)*3600) * time.Second
}
//}
//if wotab.TimePerItemToggle {
// perItemSeconds := float64(wotab.OpTimePerItem) * GetTimeUomSeconds(wotab.TimeUomId)
// tasksrv.Duration = time.Duration(float64(calQty)*perItemSeconds) * time.Second
//}
//if wotab.TimePerBatchToggle {
// if wotab.BatchTime <= 0 || wotab.BatchQuantity <= 0 || calQty <= 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.CustOrder = custOrder
tasksrv.CustOrderStatus = custOrder.OrderStatus
tasksrv.CustOrderQty = custOrder.OrderQty
}
// LoadSerialOrders 加载批次订单的序列订单
func (tasksrv *TaskSrv) LoadSerialOrders(session *xorm.Session) (err error) {
var (
i int
sordertablst []model.SerialOrder
serialtasksrv SerialTaskSrv
)
// 初始化批次订单的序列订单信息
tasksrv.SerialTaskArray = []SerialTaskSrv{}
dao := dal.NewSerialOrderDAO(session, tasksrv.PlantNr, "scheduler")
if sordertablst, err = dao.SelectByCustOrder(tasksrv.CustOrder.CustOrderId, common.WO_STATUS_LOCKED); err != nil {
return grmi.NewBusinessError(fmt.Sprintf("查询客户订单的序列订单失败!, error:" + err.Error() + " ,客户订单ID: " + tasksrv.CustOrder.CustOrderId))
}
for i = 0; i < len(sordertablst); i++ {
serialtasksrv = SerialTaskSrv{}
serialtasksrv.Init(sordertablst[i])
tasksrv.SerialTaskArray = append(tasksrv.SerialTaskArray, serialtasksrv)
}
return
}
// CreateStatusRecord 生成状态记录
func (tasksrv *TaskSrv) CreateStatusRecord(prevstatus int, eventsrv EventSrv) (err error) {
var wostatusrectab model.WorkOrderStatusRecLst
// 初始化
wostatusrectab = model.WorkOrderStatusRecLst{}
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 = common.OUTPUT_TRIGGER_UNHANDLED // 未处理
wostatusrectab.OutputEvent = eventsrv.OutputEvent
wostatusrectab.OutputEventMessageId = eventsrv.OutputEventMsgId
wostatusrectab.OutputObjectId = eventsrv.OutputObjectId
wostatusrectab.OutputSubObjectId = eventsrv.OutputSubObjectId
SetTableLastModify(&wostatusrectab, wostatusrectab, common.MODIFY_MODE_CREATE, eventsrv.TriggerService)
engine := db.Eloquent.Master()
session := engine.NewSession()
defer session.Close()
dao := dal.NewWorkOrderStatusRecLstDAO(session, tasksrv.PlantNr, "scheduler")
if err := dao.InsertOne(&wostatusrectab); err != nil {
err = errors.New(fmt.Sprintf("无法为工单%s插入状态变更记录%v!", tasksrv.TaskId, err))
return err
}
return
}
// ReleaseSerialOrder 下达批次订单,同步生成对应的序列订单
func (tasksrv *TaskSrv) ReleaseSerialOrder(relQty int, releaseId string) (err error) {
//engine := db.Eloquent.Master()
//session := engine.NewSession()
//defer session.Close()
//if err = session.Begin(); err != nil {
// return grmi.NewBusinessError("开启事务失败, error:" + err.Error())
//}
//var user = "scheduler"
//workLineDao := baseDal.NewWorkLineDAO(session, tasksrv.PlantNr, user)
//innerLog, _ := logger.NewLogger("scheduler", "scheduler")
//innerLog.Debug("开始派工, 派工任务ID:"+releaseId, ", 客户订单ID:"+tasksrv.CustOrder.CustOrderId+", 通过数量进行派工,派工数量:"+strconv.Itoa(relQty))
//// 判断批次订单状态是否满足下达条件 >= 24 && < 80
//if tasksrv.CustOrderStatus.Status < common.WO_STATUS_LOCKED || tasksrv.CustOrderStatus.Status >= common.WO_STATUS_FINISHED {
// _ = session.Rollback()
// return grmi.NewBusinessError("客户订单状态不满足派工条件, 无法下达, 客户订单ID:" + tasksrv.CustOrder.CustOrderId + ", 订单状态:" + strconv.Itoa(tasksrv.CustOrderStatus.Status))
//}
//innerLog.Debug("开始派工, 派工任务ID:"+releaseId, ", 客户订单ID:"+tasksrv.CustOrder.CustOrderId+", 加载客户订单下的序列订单完成")
//// 计算实际可下达的序列订单数量
//actRelQty := len(tasksrv.SerialTaskArray)
//if actRelQty <= 0 {
// _ = session.Rollback()
// innerLog.Error("开始派工, 派工任务ID:" + releaseId + ", 客户订单ID:" + tasksrv.CustOrder.CustOrderId + ", 该客户订单下可派工的订单数量为0")
// return grmi.NewBusinessError("客户订单可下达数量为0, 客户订单ID:" + tasksrv.CustOrder.CustOrderId)
//}
//if relQty > actRelQty {
// _ = session.Rollback()
// innerLog.Error("开始派工, 派工任务ID:" + releaseId + ", 客户订单ID:" + tasksrv.CustOrder.CustOrderId + ", 需要派工数量大于客户订单可派工数量, 需要派工数量:" + strconv.Itoa(relQty) + ", 可派工数量:" + strconv.Itoa(actRelQty))
// return grmi.NewBusinessError("客户订单需要派工数量大于可派工数量, 客户订单ID:" + tasksrv.CustOrder.CustOrderId)
//}
//workLine, err := workLineDao.SelectOne(tasksrv.CustOrder.WorkLineId)
//if err != nil {
// _ = session.Rollback()
// innerLog.Error("开始派工, 派工任务ID:" + releaseId + ", 客户订单ID:" + tasksrv.CustOrder.CustOrderId + ", 获取产线数据失败, error:" + err.Error())
// return grmi.NewBusinessError("获取产线数据失败, 客户订单ID:" + tasksrv.CustOrder.CustOrderId + ", error:" + err.Error())
//}
//if workLine == nil {
// _ = session.Rollback()
// innerLog.Error("开始派工, 派工任务ID:" + releaseId + ", 客户订单ID:" + tasksrv.CustOrder.CustOrderId + ", 产线不存在, 产线ID:" + tasksrv.CustOrder.WorkLineId)
// return grmi.NewBusinessError("获取产线不存在, 产线ID:" + tasksrv.CustOrder.WorkLineId + ", 客户订单ID:" + tasksrv.CustOrder.CustOrderId)
//}
//custOrderSvr := plnSvr.NewCustOrderService()
//resCustOrder, err := custOrderSvr.ReleaseCustOrder(session, relQty, &tasksrv.CustOrder)
//if err != nil {
// _ = session.Rollback()
// innerLog.Error("开始派工, 派工任务ID:" + releaseId + ", 客户订单ID:" + tasksrv.CustOrder.CustOrderId + ", 客户订单派工阶段失败, error:" + err.Error())
//}
//_ = session.Commit()
//innerLog.Debug("派工完成, 派工任务ID:"+releaseId, ", 客户订单ID:"+tasksrv.CustOrder.CustOrderId+", 派工数量:"+strconv.Itoa(relQty))
//tasksrv.Init(*resCustOrder)
return
}
// Get 基于指定的序列订单号获取序列订单对象
func (stasksrv *SerialTaskSrv) Get() (err error) {
var serordtab model.SerialOrder
engine := db.Eloquent.Master()
session := engine.NewSession()
defer session.Close()
dao := dal.NewSerialOrderDAO(session, stasksrv.PlantNr, "scheduler")
if serordtab, err = dao.SelectInfo(stasksrv.TaskId); err != nil {
err = errors.New(fmt.Sprintf("获取工厂%d序列订单%s失败!", stasksrv.PlantNr, stasksrv.TaskId))
return
}
stasksrv.Init(serordtab)
return
}
// Init 初始化序列订单
func (stasksrv *SerialTaskSrv) Init(serialordertab model.SerialOrder) {
stasksrv.SerialOrderTab = serialordertab
stasksrv.SerialOrderStatusTab = serialordertab.SerialOrderStatus
}
// Create 创建序列订单
func (stasksrv *SerialTaskSrv) Create() (err error) {
// 插入序列订单
stasksrv.SerialOrderTab = model.SerialOrder{}
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 = float64(stasksrv.PlanQty)
stasksrv.SerialOrderTab.PlanStartTime = grmi.DateTime(stasksrv.SchedStartTime)
stasksrv.SerialOrderTab.PlanEndTime = grmi.DateTime(stasksrv.SchedEndTime)
SetTableLastModify(&stasksrv.SerialOrderTab, stasksrv.SerialOrderTab, common.MODIFY_MODE_CREATE, "rel_service")
engine := db.Eloquent.Master()
session := engine.NewSession()
defer session.Close()
dao := dal.NewSerialOrderDAO(session, stasksrv.PlantNr, "rel_service")
if err = dao.InsertOne(&stasksrv.SerialOrderTab); err != nil {
err = errors.New(fmt.Sprintf("工单%s的序列订单%s头创建失败%v!", stasksrv.ParentTaskId, stasksrv.TaskId, err))
return
}
// 插入序列订单状态行
stasksrv.SerialOrderStatusTab = model.SerialOrderStatus{}
stasksrv.SerialOrderStatusTab.PlantNr = stasksrv.PlantNr
stasksrv.SerialOrderStatusTab.SerialOrderId = stasksrv.TaskId
stasksrv.SerialOrderStatusTab.Status = common.WO_STATUS_PLANNED
stasksrv.SerialOrderStatusTab.TriggerObjectId = stasksrv.ParentTaskId
stasksrv.SerialOrderStatusTab.TriggerEvent = common.BATORD_EVENT_LOCK
SetTableLastModify(&stasksrv.SerialOrderStatusTab, stasksrv.SerialOrderStatusTab, common.MODIFY_MODE_CREATE, "rel_service")
serial := dal.NewSerialOrderStatusDAO(session, stasksrv.PlantNr, "rel_service")
if err = serial.InsertOne(&stasksrv.SerialOrderStatusTab); err != nil {
err = errors.New(fmt.Sprintf("工单%s的序列订单%s状态头创建失败%v!", stasksrv.ParentTaskId, stasksrv.TaskId, err))
return
}
// 插入序列订单状态记录行
// 如果需要触发动作可在此处添加
serordstatrectab := model.SerialOrderStatusRecLst{}
serordstatrectab.PlantNr = stasksrv.PlantNr
serordstatrectab.SerialOrderId = stasksrv.TaskId
serordstatrectab.PrevStatus = 0
serordstatrectab.Status = common.WO_STATUS_PLANNED
serordstatrectab.OutputEvent = common.OUTPUT_EVENT_SER_NEW
serordstatrectab.OutputObjectId = serordstatrectab.SerialOrderId
serordstatrectab.OutputStatus = common.OUTPUT_TRIGGER_UNHANDLED
SetTableLastModify(&serordstatrectab, serordstatrectab, common.MODIFY_MODE_CREATE, "rel_service")
serord := dal.NewSerialOrderStatusRecLstDAO(session, stasksrv.PlantNr, "rel_service")
if err = serord.InsertOne(&serordstatrectab); err != nil {
err = errors.New(fmt.Sprintf("工单%s的序列订单%s状态记录行创建失败%v!", stasksrv.ParentTaskId, stasksrv.TaskId, err))
return
}
return
}
// Release 下达序列订单
func (stasksrv *SerialTaskSrv) Release() (err error) {
var prevstatus int
// 判断序列订单是否可以被下达
if stasksrv.SerialOrderStatusTab.Status >= common.WO_STATUS_RELEASED {
return
}
// 获取序列订单当前状态
prevstatus = stasksrv.SerialOrderStatusTab.Status
// 更新序列订单状态行
stasksrv.SerialOrderStatusTab.Status = common.WO_STATUS_RELEASED
stasksrv.SerialOrderStatusTab.TriggerObjectId = stasksrv.ParentTaskId
stasksrv.SerialOrderStatusTab.TriggerEvent = common.BATORD_EVENT_RELEASE
SetTableLastModify(&stasksrv.SerialOrderStatusTab, stasksrv.SerialOrderStatusTab, common.MODIFY_MODE_UPDATE, "rel_service")
engine := db.Eloquent.Master()
session := engine.NewSession()
defer session.Close()
serial := dal.NewSerialOrderStatusDAO(session, stasksrv.PlantNr, "rel_service")
if err = serial.UpdateOne(&stasksrv.SerialOrderStatusTab); err != nil {
err = errors.New(fmt.Sprintf("工单%s的序列订单%s状态头更新失败%v!", stasksrv.ParentTaskId, stasksrv.TaskId, err))
return
}
// 插入序列订单状态记录行
// 如果需要触发动作可在此处添加
serordstatrectab := model.SerialOrderStatusRecLst{}
serordstatrectab.PlantNr = stasksrv.PlantNr
serordstatrectab.SerialOrderId = stasksrv.TaskId
serordstatrectab.PrevStatus = prevstatus
serordstatrectab.Status = common.WO_STATUS_RELEASED
serordstatrectab.OutputEvent = common.OUTPUT_EVENT_SER_REL
serordstatrectab.OutputObjectId = serordstatrectab.SerialOrderId
serordstatrectab.OutputStatus = common.OUTPUT_TRIGGER_UNHANDLED
SetTableLastModify(&serordstatrectab, serordstatrectab, common.MODIFY_MODE_UPDATE, "rel_service")
serord := dal.NewSerialOrderStatusRecLstDAO(session, stasksrv.PlantNr, "rel_service")
if err = serord.UpdateOne(&serordstatrectab); err != nil {
err = errors.New(fmt.Sprintf("工单%s的序列订单%s状态记录行创建失败%v!", stasksrv.ParentTaskId, stasksrv.TaskId, err))
return
}
return
}