广汽安道拓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

2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
2 years ago
  1. package schedule
  2. import (
  3. dal "LAPP_ACURA_MOM_BACKEND/dao/om"
  4. plnDal "LAPP_ACURA_MOM_BACKEND/dao/pln"
  5. "LAPP_ACURA_MOM_BACKEND/db"
  6. "LAPP_ACURA_MOM_BACKEND/grmi"
  7. common "LAPP_ACURA_MOM_BACKEND/models/base"
  8. model "LAPP_ACURA_MOM_BACKEND/models/om"
  9. plnModel "LAPP_ACURA_MOM_BACKEND/models/pln"
  10. "errors"
  11. "fmt"
  12. "github.com/go-xorm/xorm"
  13. "time"
  14. )
  15. // TaskSrv 调度批次任务对象
  16. type TaskSrv struct {
  17. TaskId string
  18. TaskType string
  19. PlantNr int
  20. ProjectId string
  21. SortKey int64 // 用于给MES用的排序号
  22. ArtId string // 任务产品ID
  23. Priority int
  24. Status int
  25. SchedResGrpId string // 调度资源组ID
  26. SchedResId string // 调度资源
  27. FixResource bool // 锁定资源
  28. PlanQty float64 // 计划数量
  29. CancelQty float64 // 取消数量
  30. ReleasedQty float64 // 已下达数量 - 每个独立生成序列订单
  31. FinishedQty float64 // 已完成数量
  32. Duration time.Duration // 任务所需工时
  33. EarliestStartTime time.Time // 最早开始时间
  34. LatestEndTime time.Time // 最迟结束时间
  35. SetupStartTime time.Time // 换型开始时间
  36. SetupEndTime time.Time // 换型结束时间
  37. FixStartTime bool // 锁定派车给开始时间
  38. SchedStartTime time.Time // 排程开始时间
  39. SchedEndTime time.Time // 排程结束时间
  40. ActStartTime time.Time // 实际开始时间
  41. ActEndTime time.Time // 实际结束时间
  42. CustOrder plnModel.CustOrder
  43. CustOrderStatus plnModel.CustOrderStatus
  44. CustOrderQty plnModel.CustOrderQty
  45. SerialTaskArray []SerialTaskSrv // 批次订单的序列订单
  46. }
  47. // SerialTaskSrv 序列任务对象
  48. type SerialTaskSrv struct {
  49. TaskId string
  50. TaskType string
  51. ParentTaskId string
  52. PlantNr int
  53. ProjectId string
  54. Barcode string // 序列订单条码
  55. ArtId string // 任务产品ID
  56. Status int
  57. SchedResId string // 调度资源
  58. PlanQty float64 // 计划数量
  59. Duration time.Duration // 任务所需工时
  60. EarliestStartTime time.Time // 最早开始时间
  61. LatestEndTime time.Time // 最迟结束时间
  62. SetupStartTime time.Time // 换型开始时间
  63. SetupEndTime time.Time // 换型结束时间
  64. SchedStartTime time.Time // 排程开始时间
  65. SchedEndTime time.Time // 排程结束时间
  66. ActStartTime time.Time // 实际开始时间
  67. ActEndTime time.Time // 实际结束时间
  68. SerialOrderTab model.SerialOrder
  69. SerialOrderStatusTab model.SerialOrderStatus
  70. }
  71. // Get 基于指定的批次订单号获取批次订单对象
  72. func (tasksrv *TaskSrv) Get() (err error) {
  73. engine := db.Eloquent.Master()
  74. session := engine.NewSession()
  75. defer session.Close()
  76. dao := plnDal.NewCustOrderDAO(session, tasksrv.PlantNr, "scheduler")
  77. var custOrder *plnModel.CustOrder
  78. if custOrder, err = dao.SelectOne(tasksrv.TaskId); err != nil {
  79. return grmi.NewBusinessError("获取工厂客户订单失败, 客户订单ID:" + tasksrv.TaskId + ", error:" + err.Error())
  80. }
  81. tasksrv.Init(*custOrder)
  82. return
  83. }
  84. // Init 基于给定的订单表和订单状态表进行结构初始化
  85. func (tasksrv *TaskSrv) Init(custOrder plnModel.CustOrder) {
  86. // 初始化批次任务的批次订单信息
  87. tasksrv.TaskId = custOrder.CustOrderId
  88. tasksrv.TaskType = custOrder.OrderType
  89. tasksrv.SortKey = custOrder.PlanStartTime.Restore().Unix() // 用于给MES用的排序号
  90. tasksrv.ArtId = custOrder.ProductFamilyId // 任务产品ID
  91. //tasksrv.Priority = custOrder.Priority // 优先级
  92. tasksrv.Status = custOrder.OrderStatus.Status // 订单状态
  93. //tasksrv.SchedResGrpId = wotab.PlanResourceGroupId // 调度资源组ID
  94. tasksrv.SchedResId = custOrder.WorkLineId // 调度资源
  95. tasksrv.FixResource = false // 锁定资源
  96. tasksrv.PlanQty = float64(custOrder.OrderQty.PlanQty) // 计划数量
  97. tasksrv.ReleasedQty = float64(custOrder.OrderQty.ReleasedQty) // 已下达数量 - 每个独立生成序列订单
  98. tasksrv.FinishedQty = float64(custOrder.OrderQty.ActQty) // 已完成数量
  99. tasksrv.CancelQty = float64(custOrder.OrderQty.CancelQty)
  100. tasksrv.EarliestStartTime = custOrder.PlanStartDate.Restore() // 最早开始时间
  101. tasksrv.LatestEndTime = custOrder.PlanEndTime.Restore() // 最迟结束时间
  102. tasksrv.SetupStartTime = custOrder.SetupStartTime.Restore() // 换型开始时间
  103. tasksrv.SetupEndTime = custOrder.SetupEndTime.Restore() // 换型结束时间
  104. if custOrder.FixStartTimeToggle { // 锁定开始时间
  105. tasksrv.FixStartTime = true
  106. } else {
  107. tasksrv.FixStartTime = false
  108. }
  109. tasksrv.SchedStartTime = custOrder.PlanStartTime.Restore() // 排程开始时间
  110. tasksrv.SchedEndTime = custOrder.PlanEndTime.Restore() // 排程结束时间
  111. tasksrv.ActStartTime = custOrder.ActStartTime.Restore() // 实际开始时间
  112. tasksrv.ActEndTime = custOrder.ActEndTime.Restore() // 实际结束时间
  113. // 获取调度任务所需要的工时
  114. calQty := custOrder.PlanQty - custOrder.OrderQty.CancelQty
  115. //if custOrder.RatePerHourToggle {
  116. if custOrder.QuantityPerHour <= 0 || calQty <= 0 {
  117. tasksrv.Duration = 0
  118. } else {
  119. tasksrv.Duration = time.Duration(float64(calQty)/float64(custOrder.QuantityPerHour)*3600) * time.Second
  120. }
  121. //}
  122. //if wotab.TimePerItemToggle {
  123. // perItemSeconds := float64(wotab.OpTimePerItem) * GetTimeUomSeconds(wotab.TimeUomId)
  124. // tasksrv.Duration = time.Duration(float64(calQty)*perItemSeconds) * time.Second
  125. //}
  126. //if wotab.TimePerBatchToggle {
  127. // if wotab.BatchTime <= 0 || wotab.BatchQuantity <= 0 || calQty <= 0 {
  128. // tasksrv.Duration = 0
  129. // } else {
  130. // perBatchSeconds := float64(wotab.BatchTime) * GetTimeUomSeconds(wotab.TimeUomId)
  131. // tasksrv.Duration = time.Duration(perBatchSeconds*float64(calQty)/float64(wotab.BatchQuantity)) * time.Hour
  132. // }
  133. //}
  134. tasksrv.CustOrder = custOrder
  135. tasksrv.CustOrderStatus = custOrder.OrderStatus
  136. tasksrv.CustOrderQty = custOrder.OrderQty
  137. }
  138. // LoadSerialOrders 加载批次订单的序列订单
  139. func (tasksrv *TaskSrv) LoadSerialOrders(session *xorm.Session) (err error) {
  140. var (
  141. i int
  142. sordertablst []model.SerialOrder
  143. serialtasksrv SerialTaskSrv
  144. )
  145. // 初始化批次订单的序列订单信息
  146. tasksrv.SerialTaskArray = []SerialTaskSrv{}
  147. dao := dal.NewSerialOrderDAO(session, tasksrv.PlantNr, "scheduler")
  148. if sordertablst, err = dao.SelectByCustOrder(tasksrv.CustOrder.CustOrderId, common.WO_STATUS_LOCKED); err != nil {
  149. return grmi.NewBusinessError(fmt.Sprintf("查询客户订单的序列订单失败!, error:" + err.Error() + " ,客户订单ID: " + tasksrv.CustOrder.CustOrderId))
  150. }
  151. for i = 0; i < len(sordertablst); i++ {
  152. serialtasksrv = SerialTaskSrv{}
  153. serialtasksrv.Init(sordertablst[i])
  154. tasksrv.SerialTaskArray = append(tasksrv.SerialTaskArray, serialtasksrv)
  155. }
  156. return
  157. }
  158. // CreateStatusRecord 生成状态记录
  159. func (tasksrv *TaskSrv) CreateStatusRecord(prevstatus int, eventsrv EventSrv) (err error) {
  160. var wostatusrectab model.WorkOrderStatusRecLst
  161. // 初始化
  162. wostatusrectab = model.WorkOrderStatusRecLst{}
  163. wostatusrectab.PlantNr = tasksrv.PlantNr
  164. wostatusrectab.WorkOrderId = tasksrv.TaskId
  165. wostatusrectab.PrevStatus = prevstatus
  166. wostatusrectab.Status = tasksrv.Status
  167. wostatusrectab.TriggerEvent = eventsrv.TriggerEvent
  168. wostatusrectab.TriggerObjectId = eventsrv.TriggerObjectId
  169. wostatusrectab.TriggerSubObjectId = eventsrv.TriggerSubObjectId
  170. wostatusrectab.OutputStatus = common.OUTPUT_TRIGGER_UNHANDLED // 未处理
  171. wostatusrectab.OutputEvent = eventsrv.OutputEvent
  172. wostatusrectab.OutputEventMessageId = eventsrv.OutputEventMsgId
  173. wostatusrectab.OutputObjectId = eventsrv.OutputObjectId
  174. wostatusrectab.OutputSubObjectId = eventsrv.OutputSubObjectId
  175. SetTableLastModify(&wostatusrectab, wostatusrectab, common.MODIFY_MODE_CREATE, eventsrv.TriggerService)
  176. engine := db.Eloquent.Master()
  177. session := engine.NewSession()
  178. defer session.Close()
  179. dao := dal.NewWorkOrderStatusRecLstDAO(session, tasksrv.PlantNr, "scheduler")
  180. if err := dao.InsertOne(&wostatusrectab); err != nil {
  181. err = errors.New(fmt.Sprintf("无法为工单%s插入状态变更记录%v!", tasksrv.TaskId, err))
  182. return err
  183. }
  184. return
  185. }
  186. // ReleaseSerialOrder 下达批次订单,同步生成对应的序列订单
  187. func (tasksrv *TaskSrv) ReleaseSerialOrder(relQty int, releaseId string) (err error) {
  188. //engine := db.Eloquent.Master()
  189. //session := engine.NewSession()
  190. //defer session.Close()
  191. //if err = session.Begin(); err != nil {
  192. // return grmi.NewBusinessError("开启事务失败, error:" + err.Error())
  193. //}
  194. //var user = "scheduler"
  195. //workLineDao := baseDal.NewWorkLineDAO(session, tasksrv.PlantNr, user)
  196. //innerLog, _ := logger.NewLogger("scheduler", "scheduler")
  197. //innerLog.Debug("开始派工, 派工任务ID:"+releaseId, ", 客户订单ID:"+tasksrv.CustOrder.CustOrderId+", 通过数量进行派工,派工数量:"+strconv.Itoa(relQty))
  198. //// 判断批次订单状态是否满足下达条件 >= 24 && < 80
  199. //if tasksrv.CustOrderStatus.Status < common.WO_STATUS_LOCKED || tasksrv.CustOrderStatus.Status >= common.WO_STATUS_FINISHED {
  200. // _ = session.Rollback()
  201. // return grmi.NewBusinessError("客户订单状态不满足派工条件, 无法下达, 客户订单ID:" + tasksrv.CustOrder.CustOrderId + ", 订单状态:" + strconv.Itoa(tasksrv.CustOrderStatus.Status))
  202. //}
  203. //innerLog.Debug("开始派工, 派工任务ID:"+releaseId, ", 客户订单ID:"+tasksrv.CustOrder.CustOrderId+", 加载客户订单下的序列订单完成")
  204. //// 计算实际可下达的序列订单数量
  205. //actRelQty := len(tasksrv.SerialTaskArray)
  206. //if actRelQty <= 0 {
  207. // _ = session.Rollback()
  208. // innerLog.Error("开始派工, 派工任务ID:" + releaseId + ", 客户订单ID:" + tasksrv.CustOrder.CustOrderId + ", 该客户订单下可派工的订单数量为0")
  209. // return grmi.NewBusinessError("客户订单可下达数量为0, 客户订单ID:" + tasksrv.CustOrder.CustOrderId)
  210. //}
  211. //if relQty > actRelQty {
  212. // _ = session.Rollback()
  213. // innerLog.Error("开始派工, 派工任务ID:" + releaseId + ", 客户订单ID:" + tasksrv.CustOrder.CustOrderId + ", 需要派工数量大于客户订单可派工数量, 需要派工数量:" + strconv.Itoa(relQty) + ", 可派工数量:" + strconv.Itoa(actRelQty))
  214. // return grmi.NewBusinessError("客户订单需要派工数量大于可派工数量, 客户订单ID:" + tasksrv.CustOrder.CustOrderId)
  215. //}
  216. //workLine, err := workLineDao.SelectOne(tasksrv.CustOrder.WorkLineId)
  217. //if err != nil {
  218. // _ = session.Rollback()
  219. // innerLog.Error("开始派工, 派工任务ID:" + releaseId + ", 客户订单ID:" + tasksrv.CustOrder.CustOrderId + ", 获取产线数据失败, error:" + err.Error())
  220. // return grmi.NewBusinessError("获取产线数据失败, 客户订单ID:" + tasksrv.CustOrder.CustOrderId + ", error:" + err.Error())
  221. //}
  222. //if workLine == nil {
  223. // _ = session.Rollback()
  224. // innerLog.Error("开始派工, 派工任务ID:" + releaseId + ", 客户订单ID:" + tasksrv.CustOrder.CustOrderId + ", 产线不存在, 产线ID:" + tasksrv.CustOrder.WorkLineId)
  225. // return grmi.NewBusinessError("获取产线不存在, 产线ID:" + tasksrv.CustOrder.WorkLineId + ", 客户订单ID:" + tasksrv.CustOrder.CustOrderId)
  226. //}
  227. //custOrderSvr := plnSvr.NewCustOrderService()
  228. //resCustOrder, err := custOrderSvr.ReleaseCustOrder(session, relQty, &tasksrv.CustOrder)
  229. //if err != nil {
  230. // _ = session.Rollback()
  231. // innerLog.Error("开始派工, 派工任务ID:" + releaseId + ", 客户订单ID:" + tasksrv.CustOrder.CustOrderId + ", 客户订单派工阶段失败, error:" + err.Error())
  232. //}
  233. //_ = session.Commit()
  234. //innerLog.Debug("派工完成, 派工任务ID:"+releaseId, ", 客户订单ID:"+tasksrv.CustOrder.CustOrderId+", 派工数量:"+strconv.Itoa(relQty))
  235. //tasksrv.Init(*resCustOrder)
  236. return
  237. }
  238. // Get 基于指定的序列订单号获取序列订单对象
  239. func (stasksrv *SerialTaskSrv) Get() (err error) {
  240. var serordtab model.SerialOrder
  241. engine := db.Eloquent.Master()
  242. session := engine.NewSession()
  243. defer session.Close()
  244. dao := dal.NewSerialOrderDAO(session, stasksrv.PlantNr, "scheduler")
  245. if serordtab, err = dao.SelectInfo(stasksrv.TaskId); err != nil {
  246. err = errors.New(fmt.Sprintf("获取工厂%d序列订单%s失败!", stasksrv.PlantNr, stasksrv.TaskId))
  247. return
  248. }
  249. stasksrv.Init(serordtab)
  250. return
  251. }
  252. // Init 初始化序列订单
  253. func (stasksrv *SerialTaskSrv) Init(serialordertab model.SerialOrder) {
  254. stasksrv.SerialOrderTab = serialordertab
  255. stasksrv.SerialOrderStatusTab = serialordertab.SerialOrderStatus
  256. }
  257. // Create 创建序列订单
  258. func (stasksrv *SerialTaskSrv) Create() (err error) {
  259. // 插入序列订单
  260. stasksrv.SerialOrderTab = model.SerialOrder{}
  261. stasksrv.SerialOrderTab.PlantNr = stasksrv.PlantNr
  262. stasksrv.SerialOrderTab.ProjectId = stasksrv.ProjectId
  263. stasksrv.SerialOrderTab.ArtId = stasksrv.ArtId
  264. stasksrv.SerialOrderTab.WorkOrderId = stasksrv.ParentTaskId
  265. stasksrv.SerialOrderTab.PlanResourceId = stasksrv.SchedResId
  266. stasksrv.SerialOrderTab.OrderType = stasksrv.TaskType
  267. stasksrv.SerialOrderTab.SerialOrderId = stasksrv.TaskId
  268. stasksrv.SerialOrderTab.PlanQty = float64(stasksrv.PlanQty)
  269. stasksrv.SerialOrderTab.PlanStartTime = grmi.DateTime(stasksrv.SchedStartTime)
  270. stasksrv.SerialOrderTab.PlanEndTime = grmi.DateTime(stasksrv.SchedEndTime)
  271. SetTableLastModify(&stasksrv.SerialOrderTab, stasksrv.SerialOrderTab, common.MODIFY_MODE_CREATE, "rel_service")
  272. engine := db.Eloquent.Master()
  273. session := engine.NewSession()
  274. defer session.Close()
  275. dao := dal.NewSerialOrderDAO(session, stasksrv.PlantNr, "rel_service")
  276. if err = dao.InsertOne(&stasksrv.SerialOrderTab); err != nil {
  277. err = errors.New(fmt.Sprintf("工单%s的序列订单%s头创建失败%v!", stasksrv.ParentTaskId, stasksrv.TaskId, err))
  278. return
  279. }
  280. // 插入序列订单状态行
  281. stasksrv.SerialOrderStatusTab = model.SerialOrderStatus{}
  282. stasksrv.SerialOrderStatusTab.PlantNr = stasksrv.PlantNr
  283. stasksrv.SerialOrderStatusTab.SerialOrderId = stasksrv.TaskId
  284. stasksrv.SerialOrderStatusTab.Status = common.WO_STATUS_PLANNED
  285. stasksrv.SerialOrderStatusTab.TriggerObjectId = stasksrv.ParentTaskId
  286. stasksrv.SerialOrderStatusTab.TriggerEvent = common.BATORD_EVENT_LOCK
  287. SetTableLastModify(&stasksrv.SerialOrderStatusTab, stasksrv.SerialOrderStatusTab, common.MODIFY_MODE_CREATE, "rel_service")
  288. serial := dal.NewSerialOrderStatusDAO(session, stasksrv.PlantNr, "rel_service")
  289. if err = serial.InsertOne(&stasksrv.SerialOrderStatusTab); err != nil {
  290. err = errors.New(fmt.Sprintf("工单%s的序列订单%s状态头创建失败%v!", stasksrv.ParentTaskId, stasksrv.TaskId, err))
  291. return
  292. }
  293. // 插入序列订单状态记录行
  294. // 如果需要触发动作可在此处添加
  295. serordstatrectab := model.SerialOrderStatusRecLst{}
  296. serordstatrectab.PlantNr = stasksrv.PlantNr
  297. serordstatrectab.SerialOrderId = stasksrv.TaskId
  298. serordstatrectab.PrevStatus = 0
  299. serordstatrectab.Status = common.WO_STATUS_PLANNED
  300. serordstatrectab.OutputEvent = common.OUTPUT_EVENT_SER_NEW
  301. serordstatrectab.OutputObjectId = serordstatrectab.SerialOrderId
  302. serordstatrectab.OutputStatus = common.OUTPUT_TRIGGER_UNHANDLED
  303. SetTableLastModify(&serordstatrectab, serordstatrectab, common.MODIFY_MODE_CREATE, "rel_service")
  304. serord := dal.NewSerialOrderStatusRecLstDAO(session, stasksrv.PlantNr, "rel_service")
  305. if err = serord.InsertOne(&serordstatrectab); err != nil {
  306. err = errors.New(fmt.Sprintf("工单%s的序列订单%s状态记录行创建失败%v!", stasksrv.ParentTaskId, stasksrv.TaskId, err))
  307. return
  308. }
  309. return
  310. }
  311. // Release 下达序列订单
  312. func (stasksrv *SerialTaskSrv) Release() (err error) {
  313. var prevstatus int
  314. // 判断序列订单是否可以被下达
  315. if stasksrv.SerialOrderStatusTab.Status >= common.WO_STATUS_RELEASED {
  316. return
  317. }
  318. // 获取序列订单当前状态
  319. prevstatus = stasksrv.SerialOrderStatusTab.Status
  320. // 更新序列订单状态行
  321. stasksrv.SerialOrderStatusTab.Status = common.WO_STATUS_RELEASED
  322. stasksrv.SerialOrderStatusTab.TriggerObjectId = stasksrv.ParentTaskId
  323. stasksrv.SerialOrderStatusTab.TriggerEvent = common.BATORD_EVENT_RELEASE
  324. SetTableLastModify(&stasksrv.SerialOrderStatusTab, stasksrv.SerialOrderStatusTab, common.MODIFY_MODE_UPDATE, "rel_service")
  325. engine := db.Eloquent.Master()
  326. session := engine.NewSession()
  327. defer session.Close()
  328. serial := dal.NewSerialOrderStatusDAO(session, stasksrv.PlantNr, "rel_service")
  329. if err = serial.UpdateOne(&stasksrv.SerialOrderStatusTab); err != nil {
  330. err = errors.New(fmt.Sprintf("工单%s的序列订单%s状态头更新失败%v!", stasksrv.ParentTaskId, stasksrv.TaskId, err))
  331. return
  332. }
  333. // 插入序列订单状态记录行
  334. // 如果需要触发动作可在此处添加
  335. serordstatrectab := model.SerialOrderStatusRecLst{}
  336. serordstatrectab.PlantNr = stasksrv.PlantNr
  337. serordstatrectab.SerialOrderId = stasksrv.TaskId
  338. serordstatrectab.PrevStatus = prevstatus
  339. serordstatrectab.Status = common.WO_STATUS_RELEASED
  340. serordstatrectab.OutputEvent = common.OUTPUT_EVENT_SER_REL
  341. serordstatrectab.OutputObjectId = serordstatrectab.SerialOrderId
  342. serordstatrectab.OutputStatus = common.OUTPUT_TRIGGER_UNHANDLED
  343. SetTableLastModify(&serordstatrectab, serordstatrectab, common.MODIFY_MODE_UPDATE, "rel_service")
  344. serord := dal.NewSerialOrderStatusRecLstDAO(session, stasksrv.PlantNr, "rel_service")
  345. if err = serord.UpdateOne(&serordstatrectab); err != nil {
  346. err = errors.New(fmt.Sprintf("工单%s的序列订单%s状态记录行创建失败%v!", stasksrv.ParentTaskId, stasksrv.TaskId, err))
  347. return
  348. }
  349. return
  350. }