package service import ( "container/list" "errors" "fmt" "leit.com/leit_seat_aps/common" conf "leit.com/leit_seat_aps/config" "leit.com/leit_seat_aps/db" "leit.com/leit_seat_aps/etcd" "leit.com/leit_seat_aps/glog" "strconv" "strings" "time" ) // 产线对象 type BL_Workline struct { WorklineId string MixSort bool // 是否混线 SortMode string // 不混线排序方式 MixSortMode string // 混线排序方式 MixSortRule string // 混线规则 ReleaseMode string // 派工下达模式 ReleaseValue int // 下达参数 ProjList []string // 解析出来的项目号数组,顺序排序 ProjTaskDict map[string]BL_Workline_ProjTask // 如果混线,项目任务字典 Bl_wolst []BL_WorkOrder // 不混线任务队列 PickTmpDict map[string]BL_PickingTemplate // 分配的拣料单模板 Worklinetab db.Workline } // 调度到产线的任务 type BL_Workline_ProjTask struct { Projnr string MixRatioQty int // 按数量混线,指定的数量 Bl_wolst *list.List // 用链表来存储产线的计划任务 } // 解析产线的混线逻辑 func (bl_wl *BL_Workline) ParseMixRule() (err error) { var ( kvlist, kv []string i int bl_wlpt BL_Workline_ProjTask ) bl_wl.ProjTaskDict = make(map[string]BL_Workline_ProjTask) bl_wl.ProjList = []string{} kvlist = strings.Split(bl_wl.MixSortRule, ";") if len(kvlist) < 2 { // 报错 err = errors.New("Workline: " + bl_wl.WorklineId + " mixsortrule: " + bl_wl.MixSortRule + " parameters are less than 2!") return } else { for i = 0; i < len(kvlist); i++ { kv = strings.Split(strings.TrimSpace(kvlist[i]), ":") if len(kv) < 2 { // 报错 err = errors.New("Workline: " + bl_wl.WorklineId + " parameter: " + kvlist[i] + " values are less than 2!") return } bl_wlpt = BL_Workline_ProjTask{} bl_wlpt.Projnr = kv[0] bl_wlpt.MixRatioQty, _ = strconv.Atoi(kv[1]) bl_wl.ProjTaskDict[bl_wlpt.Projnr] = bl_wlpt bl_wl.ProjList = append(bl_wl.ProjList, kv[0]) } } return } // 加载产线的计划任务队列 func (bl_wl *BL_Workline) LoadPlannedTask() (err error) { var ( bl_wlpt BL_Workline_ProjTask wotab db.Pln_workorder wotablst []db.Pln_workorder bl_wo BL_WorkOrder i int ) wotab = db.Pln_workorder{} if bl_wl.MixSort { // 如果产线是混线排序,按项目加载已计划未下达生产订单 // 初始化项目任务列表,然后加载项目的生产订单 for _, bl_wlpt = range bl_wl.ProjTaskDict { bl_wlpt.Bl_wolst = list.New() // 按产线项目加载已计划未下达的生产订单 if wotablst, err = wotab.GetLineProjectPlannedTasks(bl_wlpt.Projnr, bl_wl.WorklineId); err != nil { err = errors.New(fmt.Sprintf("Failed to load work order for workline: %s project: %s due to: %v", bl_wl.WorklineId, bl_wlpt.Projnr, err)) return } for i = 0; i < len(wotablst); i++ { wotablst[i].Clipped() bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst[i].Workordernr bl_wo.Custordernr = wotablst[i].Custordernr bl_wo.Worklineid = wotablst[i].Worklineid bl_wo.Projnr = wotablst[i].Projnr bl_wo.Ordertype = wotablst[i].Ordertype bl_wo.Status = wotablst[i].Status bl_wo.Preschedseq = common.ValueToInt(wotablst[i].Preschedseq, 0) bl_wo.Schedseq = wotablst[i].Schedseq bl_wo.Oemseq = common.ValueToInt(wotablst[i].Oemseq, 0) bl_wo.Partfamilyid = wotablst[i].Partfamilyid bl_wo.Supplygroupid = wotablst[i].Supplygroupid bl_wo.Workordertab = wotablst[i] bl_wlpt.Bl_wolst.PushBack(bl_wo) } bl_wl.ProjTaskDict[bl_wlpt.Projnr] = bl_wlpt } } else { // 非混线排序,则正常加载已计划未下达生产订单 if wotablst, err = wotab.GetLinePlannedTasks(bl_wl.WorklineId); err != nil { err = errors.New(fmt.Sprintf("Failed to load work order for workline: %s due to: %v", bl_wl.WorklineId, err)) return } bl_wl.Bl_wolst = []BL_WorkOrder{} for i = 0; i < len(wotablst); i++ { wotablst[i].Clipped() bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst[i].Workordernr bl_wo.Custordernr = wotablst[i].Custordernr bl_wo.Worklineid = wotablst[i].Worklineid bl_wo.Projnr = wotablst[i].Projnr bl_wo.Ordertype = wotablst[i].Ordertype bl_wo.Status = wotablst[i].Status bl_wo.Preschedseq = common.ValueToInt(wotablst[i].Preschedseq, 0) bl_wo.Schedseq = wotablst[i].Schedseq bl_wo.Oemseq = common.ValueToInt(wotablst[i].Oemseq, 0) bl_wo.Partfamilyid = wotablst[i].Partfamilyid bl_wo.Supplygroupid = wotablst[i].Supplygroupid bl_wo.Workordertab = wotablst[i] bl_wl.Bl_wolst = append(bl_wl.Bl_wolst, bl_wo) } } return } // 基于指定派工数量获取产线需派工生产订单 // 返回需要派工下达的排好序的生产订单 func (bl_wl *BL_Workline) GetTaskToReleaseByQty() (bl_wolst []BL_WorkOrder, err error) { var ( totalRelQty int toRelQty int wotablst []db.Pln_workorder bl_wo BL_WorkOrder i int wotablst1 []db.Pln_workorder wotablst2 []db.Pln_workorder swet1, swet2 string ) LOOP: // 获取产线已派工未开始的订单数 if totalRelQty, err = bl_wl.GetReleasedTaskQty(); err != nil { glog.InfoExtln("排序调度", "GetReleasedTaskQty err: ", err) // 报错并返回 time.Sleep(5 * time.Millisecond) goto LOOP } // 遍历队列,去重获取剩余下达数 toRelQty = bl_wl.ReleaseValue - totalRelQty if toRelQty <= 0 { return } //查询需要下单的工单 if bl_wl.MixSort { // 如果产线是混线排序,按项目加载已计划未下达生产订单 // 混线模式 switch bl_wl.MixSortMode { case common.LINE_MIXSORT_IN_SWET: // 按交货时间紧急度 case common.LINE_MIXSORT_IN_SWET_RATIO: // 按交付时间和比例 //解析数据(G38:2;G18:1 ) data := strings.Split(bl_wl.Worklinetab.Mixsortlogic, ";") if len(data) >= 2 { /* 获取锁 */ MixLOCK: err = etcd.G_jobLock.TryLock("lock") if err != nil { fmt.Println("seq groutine lock fail!") time.Sleep(10 * time.Millisecond) goto MixLOCK } //项目1 info1 := strings.Split(data[0], ":") if len(info1) >= 2 { projnr1 := info1[0] value1 := common.ValueToInt(info1[1], 0) if common.ValueIsEmpty(value1) { value1 = 1 } if wotablst1, err = bl_wl.GetLineProjectTaskWorkordersBySwet(projnr1, bl_wl.WorklineId, value1); err != nil { err = errors.New(fmt.Sprintf("Failed to load work order for workline: %s due to: %v", bl_wl.WorklineId, err)) etcd.G_jobLock.UnLock() return } } else { etcd.G_jobLock.UnLock() return } info2 := strings.Split(data[1], ":") if len(info2) >= 2 { projnr2 := info2[0] value2 := common.ValueToInt(info2[1], 0) if common.ValueIsEmpty(value2) { value2 = 1 } if wotablst2, err = bl_wl.GetLineProjectTaskWorkordersBySwet(projnr2, bl_wl.WorklineId, value2); err != nil { err = errors.New(fmt.Sprintf("Failed to load work order for workline: %s due to: %v", bl_wl.WorklineId, err)) etcd.G_jobLock.UnLock() return } } else { etcd.G_jobLock.UnLock() return } etcd.G_jobLock.UnLock() //比较swet时间 if len(wotablst1) > 0 { swet1 = wotablst1[0].Swet } if len(wotablst2) > 0 { swet2 = wotablst2[0].Swet } //记录日志 glog.InfoExtln("scheduler", "swet1", swet1) glog.InfoExtln("scheduler", "swet2", swet2) if common.ValueIsEmpty(swet1) { if common.ValueIsEmpty(swet2) { etcd.G_jobLock.UnLock() return } else { for i = 0; i < len(wotablst2); i++ { wotablst2[i].Clipped() bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst2[i].Workordernr bl_wo.Custordernr = wotablst2[i].Custordernr bl_wo.Worklineid = wotablst2[i].Worklineid bl_wo.Projnr = wotablst2[i].Projnr bl_wo.Ordertype = wotablst2[i].Ordertype bl_wo.Status = wotablst2[i].Status bl_wo.Preschedseq = common.ValueToInt(wotablst2[i].Preschedseq, 0) bl_wo.Schedseq = wotablst2[i].Schedseq bl_wo.Oemseq = common.ValueToInt(wotablst2[i].Oemseq, 0) bl_wo.Partfamilyid = wotablst2[i].Partfamilyid bl_wo.Supplygroupid = wotablst2[i].Supplygroupid bl_wo.Workordertab = wotablst2[i] bl_wolst = append(bl_wolst, bl_wo) } } } else { if common.ValueIsEmpty(swet2) { for i = 0; i < len(wotablst1); i++ { wotablst1[i].Clipped() bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst1[i].Workordernr bl_wo.Custordernr = wotablst1[i].Custordernr bl_wo.Worklineid = wotablst1[i].Worklineid bl_wo.Projnr = wotablst1[i].Projnr bl_wo.Ordertype = wotablst1[i].Ordertype bl_wo.Status = wotablst1[i].Status bl_wo.Preschedseq = common.ValueToInt(wotablst1[i].Preschedseq, 0) bl_wo.Schedseq = wotablst1[i].Schedseq bl_wo.Oemseq = common.ValueToInt(wotablst1[i].Oemseq, 0) bl_wo.Partfamilyid = wotablst1[i].Partfamilyid bl_wo.Supplygroupid = wotablst1[i].Supplygroupid bl_wo.Workordertab = wotablst1[i] bl_wolst = append(bl_wolst, bl_wo) } } else { //比较swet1和swet2 if swet1 <= swet2 { for i = 0; i < len(wotablst1); i++ { wotablst1[i].Clipped() bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst1[i].Workordernr bl_wo.Custordernr = wotablst1[i].Custordernr bl_wo.Worklineid = wotablst1[i].Worklineid bl_wo.Projnr = wotablst1[i].Projnr bl_wo.Ordertype = wotablst1[i].Ordertype bl_wo.Status = wotablst1[i].Status bl_wo.Preschedseq = common.ValueToInt(wotablst1[i].Preschedseq, 0) bl_wo.Schedseq = wotablst1[i].Schedseq bl_wo.Oemseq = common.ValueToInt(wotablst1[i].Oemseq, 0) bl_wo.Partfamilyid = wotablst1[i].Partfamilyid bl_wo.Supplygroupid = wotablst1[i].Supplygroupid bl_wo.Workordertab = wotablst1[i] bl_wolst = append(bl_wolst, bl_wo) } } else { for i = 0; i < len(wotablst2); i++ { wotablst2[i].Clipped() bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst2[i].Workordernr bl_wo.Custordernr = wotablst2[i].Custordernr bl_wo.Worklineid = wotablst2[i].Worklineid bl_wo.Projnr = wotablst2[i].Projnr bl_wo.Ordertype = wotablst2[i].Ordertype bl_wo.Status = wotablst2[i].Status bl_wo.Preschedseq = common.ValueToInt(wotablst2[i].Preschedseq, 0) bl_wo.Schedseq = wotablst2[i].Schedseq bl_wo.Oemseq = common.ValueToInt(wotablst2[i].Oemseq, 0) bl_wo.Partfamilyid = wotablst2[i].Partfamilyid bl_wo.Supplygroupid = wotablst2[i].Supplygroupid bl_wo.Workordertab = wotablst2[i] bl_wolst = append(bl_wolst, bl_wo) } } } } } else if len(data) == 1 { //项目1 info1 := strings.Split(data[0], ":") if len(info1) >= 2 { projnr1 := info1[0] value1 := common.ValueToInt(info1[1], 0) if common.ValueIsEmpty(value1) { value1 = 1 } if wotablst1, err = bl_wl.GetLineProjectTaskWorkordersBySwet(projnr1, bl_wl.WorklineId, value1); err != nil { err = errors.New(fmt.Sprintf("Failed to load work order for workline: %s due to: %v", bl_wl.WorklineId, err)) return } } else { return } for i = 0; i < len(wotablst1); i++ { wotablst1[i].Clipped() bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst1[i].Workordernr bl_wo.Custordernr = wotablst1[i].Custordernr bl_wo.Worklineid = wotablst1[i].Worklineid bl_wo.Projnr = wotablst1[i].Projnr bl_wo.Ordertype = wotablst1[i].Ordertype bl_wo.Status = wotablst1[i].Status bl_wo.Preschedseq = common.ValueToInt(wotablst1[i].Preschedseq, 0) bl_wo.Schedseq = wotablst1[i].Schedseq bl_wo.Oemseq = common.ValueToInt(wotablst1[i].Oemseq, 0) bl_wo.Partfamilyid = wotablst1[i].Partfamilyid bl_wo.Supplygroupid = wotablst1[i].Supplygroupid bl_wo.Workordertab = wotablst1[i] bl_wolst = append(bl_wolst, bl_wo) } } else { return } } } else { //非混线逻辑 // 获取待下达任务数 // 非混线排序,则正常加载已计划未下达生产订单 /* 获取锁 */ LOCK: err = etcd.G_jobLock.TryLock("lock") if err != nil { fmt.Println("seq groutine lock fail!") time.Sleep(10 * time.Millisecond) goto LOCK } if wotablst, err = bl_wl.GetLineTaskWorkorders(bl_wl.WorklineId, toRelQty); err != nil { err = errors.New(fmt.Sprintf("Failed to load work order for workline: %s due to: %v", bl_wl.WorklineId, err)) return } etcd.G_jobLock.UnLock() for i = 0; i < len(wotablst); i++ { wotablst[i].Clipped() bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst[i].Workordernr bl_wo.Custordernr = wotablst[i].Custordernr bl_wo.Worklineid = wotablst[i].Worklineid bl_wo.Projnr = wotablst[i].Projnr bl_wo.Ordertype = wotablst[i].Ordertype bl_wo.Status = wotablst[i].Status bl_wo.Preschedseq = common.ValueToInt(wotablst[i].Preschedseq, 0) bl_wo.Schedseq = wotablst[i].Schedseq bl_wo.Oemseq = common.ValueToInt(wotablst[i].Oemseq, 0) bl_wo.Partfamilyid = wotablst[i].Partfamilyid bl_wo.Supplygroupid = wotablst[i].Supplygroupid bl_wo.Workordertab = wotablst[i] bl_wolst = append(bl_wolst, bl_wo) } } return } // 基于指定时间点获取产线需派工生产订单 // 返回需要派工下达的排好序的生产订单 func (bl_wl *BL_Workline) GetTaskToReleaseByTime() (bl_wolst []BL_WorkOrder, err error) { var ( i int wotablst []db.Pln_workorder wotablst1 []db.Pln_workorder wotablst2 []db.Pln_workorder bl_wo BL_WorkOrder swet1, swet2 string ) // 基于产线派工模式分别处理 if bl_wl.MixSort { // 混线模式 switch bl_wl.MixSortMode { case common.LINE_MIXSORT_IN_SWET: // 按交货时间紧急度 case common.LINE_MIXSORT_IN_SWET_RATIO: // 按交付时间和比例 //解析数据(G38:2;G18:1 ) data := strings.Split(bl_wl.Worklinetab.Mixsortlogic, ";") //oemseq 数据限制(G38:123456;G18:123456789)bl_wl.Worklinetab.Releasetparameter oemseqs := strings.Split(bl_wl.Worklinetab.Releasetparameter, ";") if len(oemseqs) == 2 { //两条线都限制 projnr1info := strings.Split(oemseqs[0], ":") if len(projnr1info) < 2 { return } projnr2info := strings.Split(oemseqs[1], ":") if len(projnr2info) < 2 { return } if len(data) >= 2 { //项目1 info1 := strings.Split(data[0], ":") if len(info1) >= 2 { projnr1 := info1[0] value1 := common.ValueToInt(info1[1], 0) if common.ValueIsEmpty(value1) { value1 = 1 } if projnr1 == projnr1info[0] { if wotablst1, err = bl_wl.GetLineProjectTaskWorkordersBySwetLimitOemseq(projnr1, bl_wl.WorklineId, value1, common.ValueToFloat(projnr1info[1], 0.0)); err != nil { err = errors.New(fmt.Sprintf("Failed to load work order for workline: %s due to: %v", bl_wl.WorklineId, err)) return } } else { if wotablst1, err = bl_wl.GetLineProjectTaskWorkordersBySwetLimitOemseq(projnr1, bl_wl.WorklineId, value1, common.ValueToFloat(projnr2info[1], 0.0)); err != nil { err = errors.New(fmt.Sprintf("Failed to load work order for workline: %s due to: %v", bl_wl.WorklineId, err)) return } } } else { return } info2 := strings.Split(data[1], ":") if len(info2) >= 2 { projnr2 := info2[0] value2 := common.ValueToInt(info2[1], 0) if common.ValueIsEmpty(value2) { value2 = 1 } if projnr2 == projnr1info[0] { if wotablst2, err = bl_wl.GetLineProjectTaskWorkordersBySwetLimitOemseq(projnr2, bl_wl.WorklineId, value2, common.ValueToFloat(projnr1info[1], 0.0)); err != nil { err = errors.New(fmt.Sprintf("Failed to load work order for workline: %s due to: %v", bl_wl.WorklineId, err)) return } } else { if wotablst2, err = bl_wl.GetLineProjectTaskWorkordersBySwetLimitOemseq(projnr2, bl_wl.WorklineId, value2, common.ValueToFloat(projnr2info[1], 0.0)); err != nil { err = errors.New(fmt.Sprintf("Failed to load work order for workline: %s due to: %v", bl_wl.WorklineId, err)) return } } } else { return } //比较swet时间 if len(wotablst1) > 0 { swet1 = wotablst1[0].Swet } if len(wotablst2) > 0 { swet2 = wotablst2[0].Swet } if common.ValueIsEmpty(swet1) { if common.ValueIsEmpty(swet2) { return } else { for i = 0; i < len(wotablst2); i++ { wotablst2[i].Clipped() bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst2[i].Workordernr bl_wo.Custordernr = wotablst2[i].Custordernr bl_wo.Worklineid = wotablst2[i].Worklineid bl_wo.Projnr = wotablst2[i].Projnr bl_wo.Ordertype = wotablst2[i].Ordertype bl_wo.Status = wotablst2[i].Status bl_wo.Preschedseq = common.ValueToInt(wotablst2[i].Preschedseq, 0) bl_wo.Schedseq = wotablst2[i].Schedseq bl_wo.Oemseq = common.ValueToInt(wotablst2[i].Oemseq, 0) bl_wo.Partfamilyid = wotablst2[i].Partfamilyid bl_wo.Supplygroupid = wotablst2[i].Supplygroupid bl_wo.Workordertab = wotablst2[i] bl_wolst = append(bl_wolst, bl_wo) } } } else { if common.ValueIsEmpty(swet2) { for i = 0; i < len(wotablst1); i++ { wotablst1[i].Clipped() bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst1[i].Workordernr bl_wo.Custordernr = wotablst1[i].Custordernr bl_wo.Worklineid = wotablst1[i].Worklineid bl_wo.Projnr = wotablst1[i].Projnr bl_wo.Ordertype = wotablst1[i].Ordertype bl_wo.Status = wotablst1[i].Status bl_wo.Preschedseq = common.ValueToInt(wotablst1[i].Preschedseq, 0) bl_wo.Schedseq = wotablst1[i].Schedseq bl_wo.Oemseq = common.ValueToInt(wotablst1[i].Oemseq, 0) bl_wo.Partfamilyid = wotablst1[i].Partfamilyid bl_wo.Supplygroupid = wotablst1[i].Supplygroupid bl_wo.Workordertab = wotablst1[i] bl_wolst = append(bl_wolst, bl_wo) } } else { //比较swet1和swet2 if swet1 <= swet2 { for i = 0; i < len(wotablst1); i++ { wotablst1[i].Clipped() bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst1[i].Workordernr bl_wo.Custordernr = wotablst1[i].Custordernr bl_wo.Worklineid = wotablst1[i].Worklineid bl_wo.Projnr = wotablst1[i].Projnr bl_wo.Ordertype = wotablst1[i].Ordertype bl_wo.Status = wotablst1[i].Status bl_wo.Preschedseq = common.ValueToInt(wotablst1[i].Preschedseq, 0) bl_wo.Schedseq = wotablst1[i].Schedseq bl_wo.Oemseq = common.ValueToInt(wotablst1[i].Oemseq, 0) bl_wo.Partfamilyid = wotablst1[i].Partfamilyid bl_wo.Supplygroupid = wotablst1[i].Supplygroupid bl_wo.Workordertab = wotablst1[i] bl_wolst = append(bl_wolst, bl_wo) } } else { for i = 0; i < len(wotablst2); i++ { wotablst2[i].Clipped() bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst2[i].Workordernr bl_wo.Custordernr = wotablst2[i].Custordernr bl_wo.Worklineid = wotablst2[i].Worklineid bl_wo.Projnr = wotablst2[i].Projnr bl_wo.Ordertype = wotablst2[i].Ordertype bl_wo.Status = wotablst2[i].Status bl_wo.Preschedseq = common.ValueToInt(wotablst2[i].Preschedseq, 0) bl_wo.Schedseq = wotablst2[i].Schedseq bl_wo.Oemseq = common.ValueToInt(wotablst2[i].Oemseq, 0) bl_wo.Partfamilyid = wotablst2[i].Partfamilyid bl_wo.Supplygroupid = wotablst2[i].Supplygroupid bl_wo.Workordertab = wotablst2[i] bl_wolst = append(bl_wolst, bl_wo) } } } } } else { return } } else if len(oemseqs) == 1 { //只限制一条产线 projnrinfo := strings.Split(oemseqs[0], ":") if len(projnrinfo) < 2 { return } if len(data) >= 2 { //项目1 info1 := strings.Split(data[0], ":") if len(info1) >= 2 { projnr1 := info1[0] value1 := common.ValueToInt(info1[1], 0) if common.ValueIsEmpty(value1) { value1 = 1 } //判断是否有限制 if projnrinfo[0] == projnr1 { if wotablst1, err = bl_wl.GetLineProjectTaskWorkordersBySwetLimitOemseq(projnr1, bl_wl.WorklineId, value1, common.ValueToFloat(projnrinfo[1], 0.0)); err != nil { err = errors.New(fmt.Sprintf("Failed to load work order for workline: %s due to: %v", bl_wl.WorklineId, err)) return } } else { if wotablst1, err = bl_wl.GetLineProjectTaskWorkordersBySwet(projnr1, bl_wl.WorklineId, value1); err != nil { err = errors.New(fmt.Sprintf("Failed to load work order for workline: %s due to: %v", bl_wl.WorklineId, err)) return } } } else { return } info2 := strings.Split(data[1], ":") if len(info2) >= 2 { projnr2 := info2[0] value2 := common.ValueToInt(info2[1], 0) if common.ValueIsEmpty(value2) { value2 = 1 } //判断是否有限制 if projnrinfo[0] == projnr2 { if wotablst1, err = bl_wl.GetLineProjectTaskWorkordersBySwetLimitOemseq(projnr2, bl_wl.WorklineId, value2, common.ValueToFloat(projnrinfo[1], 0.0)); err != nil { err = errors.New(fmt.Sprintf("Failed to load work order for workline: %s due to: %v", bl_wl.WorklineId, err)) return } } else { if wotablst2, err = bl_wl.GetLineProjectTaskWorkordersBySwet(projnr2, bl_wl.WorklineId, value2); err != nil { err = errors.New(fmt.Sprintf("Failed to load work order for workline: %s due to: %v", bl_wl.WorklineId, err)) return } } } else { return } //比较swet时间 if len(wotablst1) > 0 { swet1 = wotablst1[0].Swet } if len(wotablst2) > 0 { swet2 = wotablst2[0].Swet } if common.ValueIsEmpty(swet1) { if common.ValueIsEmpty(swet2) { return } else { for i = 0; i < len(wotablst2); i++ { wotablst2[i].Clipped() bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst2[i].Workordernr bl_wo.Custordernr = wotablst2[i].Custordernr bl_wo.Worklineid = wotablst2[i].Worklineid bl_wo.Projnr = wotablst2[i].Projnr bl_wo.Ordertype = wotablst2[i].Ordertype bl_wo.Status = wotablst2[i].Status bl_wo.Preschedseq = common.ValueToInt(wotablst2[i].Preschedseq, 0) bl_wo.Schedseq = wotablst2[i].Schedseq bl_wo.Oemseq = common.ValueToInt(wotablst2[i].Oemseq, 0) bl_wo.Partfamilyid = wotablst2[i].Partfamilyid bl_wo.Supplygroupid = wotablst2[i].Supplygroupid bl_wo.Workordertab = wotablst2[i] bl_wolst = append(bl_wolst, bl_wo) } } } else { if common.ValueIsEmpty(swet2) { for i = 0; i < len(wotablst1); i++ { wotablst1[i].Clipped() bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst1[i].Workordernr bl_wo.Custordernr = wotablst1[i].Custordernr bl_wo.Worklineid = wotablst1[i].Worklineid bl_wo.Projnr = wotablst1[i].Projnr bl_wo.Ordertype = wotablst1[i].Ordertype bl_wo.Status = wotablst1[i].Status bl_wo.Preschedseq = common.ValueToInt(wotablst1[i].Preschedseq, 0) bl_wo.Schedseq = wotablst1[i].Schedseq bl_wo.Oemseq = common.ValueToInt(wotablst1[i].Oemseq, 0) bl_wo.Partfamilyid = wotablst1[i].Partfamilyid bl_wo.Supplygroupid = wotablst1[i].Supplygroupid bl_wo.Workordertab = wotablst1[i] bl_wolst = append(bl_wolst, bl_wo) } } else { //比较swet1和swet2 if swet1 <= swet2 { for i = 0; i < len(wotablst1); i++ { wotablst1[i].Clipped() bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst1[i].Workordernr bl_wo.Custordernr = wotablst1[i].Custordernr bl_wo.Worklineid = wotablst1[i].Worklineid bl_wo.Projnr = wotablst1[i].Projnr bl_wo.Ordertype = wotablst1[i].Ordertype bl_wo.Status = wotablst1[i].Status bl_wo.Preschedseq = common.ValueToInt(wotablst1[i].Preschedseq, 0) bl_wo.Schedseq = wotablst1[i].Schedseq bl_wo.Oemseq = common.ValueToInt(wotablst1[i].Oemseq, 0) bl_wo.Partfamilyid = wotablst1[i].Partfamilyid bl_wo.Supplygroupid = wotablst1[i].Supplygroupid bl_wo.Workordertab = wotablst1[i] bl_wolst = append(bl_wolst, bl_wo) } } else { for i = 0; i < len(wotablst2); i++ { wotablst2[i].Clipped() bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst2[i].Workordernr bl_wo.Custordernr = wotablst2[i].Custordernr bl_wo.Worklineid = wotablst2[i].Worklineid bl_wo.Projnr = wotablst2[i].Projnr bl_wo.Ordertype = wotablst2[i].Ordertype bl_wo.Status = wotablst2[i].Status bl_wo.Preschedseq = common.ValueToInt(wotablst2[i].Preschedseq, 0) bl_wo.Schedseq = wotablst2[i].Schedseq bl_wo.Oemseq = common.ValueToInt(wotablst2[i].Oemseq, 0) bl_wo.Partfamilyid = wotablst2[i].Partfamilyid bl_wo.Supplygroupid = wotablst2[i].Supplygroupid bl_wo.Workordertab = wotablst2[i] bl_wolst = append(bl_wolst, bl_wo) } } } } } else { return } } else { glog.InfoExtln("LINE_REL_BY_OEMSEQ", "len(data): ", len(data)) //没有oemseq限制 if len(data) >= 2 { //项目1 info1 := strings.Split(data[0], ":") if len(info1) >= 2 { projnr1 := info1[0] value1 := common.ValueToInt(info1[1], 0) if common.ValueIsEmpty(value1) { value1 = 1 } if wotablst1, err = bl_wl.GetLineProjectTaskWorkordersBySwet(projnr1, bl_wl.WorklineId, value1); err != nil { err = errors.New(fmt.Sprintf("Failed to load work order for workline: %s due to: %v", bl_wl.WorklineId, err)) return } } else { return } info2 := strings.Split(data[1], ":") if len(info2) >= 2 { projnr2 := info2[0] value2 := common.ValueToInt(info2[1], 0) if common.ValueIsEmpty(value2) { value2 = 1 } if wotablst2, err = bl_wl.GetLineProjectTaskWorkordersBySwet(projnr2, bl_wl.WorklineId, value2); err != nil { err = errors.New(fmt.Sprintf("Failed to load work order for workline: %s due to: %v", bl_wl.WorklineId, err)) return } } else { return } //比较swet时间 if len(wotablst1) > 0 { swet1 = wotablst1[0].Swet } if len(wotablst2) > 0 { swet2 = wotablst2[0].Swet } if common.ValueIsEmpty(swet1) { if common.ValueIsEmpty(swet2) { return } else { for i = 0; i < len(wotablst2); i++ { wotablst2[i].Clipped() bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst2[i].Workordernr bl_wo.Custordernr = wotablst2[i].Custordernr bl_wo.Worklineid = wotablst2[i].Worklineid bl_wo.Projnr = wotablst2[i].Projnr bl_wo.Ordertype = wotablst2[i].Ordertype bl_wo.Status = wotablst2[i].Status bl_wo.Preschedseq = common.ValueToInt(wotablst2[i].Preschedseq, 0) bl_wo.Schedseq = wotablst2[i].Schedseq bl_wo.Oemseq = common.ValueToInt(wotablst2[i].Oemseq, 0) bl_wo.Partfamilyid = wotablst2[i].Partfamilyid bl_wo.Supplygroupid = wotablst2[i].Supplygroupid bl_wo.Workordertab = wotablst2[i] bl_wolst = append(bl_wolst, bl_wo) } } } else { if common.ValueIsEmpty(swet2) { for i = 0; i < len(wotablst1); i++ { wotablst1[i].Clipped() bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst1[i].Workordernr bl_wo.Custordernr = wotablst1[i].Custordernr bl_wo.Worklineid = wotablst1[i].Worklineid bl_wo.Projnr = wotablst1[i].Projnr bl_wo.Ordertype = wotablst1[i].Ordertype bl_wo.Status = wotablst1[i].Status bl_wo.Preschedseq = common.ValueToInt(wotablst1[i].Preschedseq, 0) bl_wo.Schedseq = wotablst1[i].Schedseq bl_wo.Oemseq = common.ValueToInt(wotablst1[i].Oemseq, 0) bl_wo.Partfamilyid = wotablst1[i].Partfamilyid bl_wo.Supplygroupid = wotablst1[i].Supplygroupid bl_wo.Workordertab = wotablst1[i] bl_wolst = append(bl_wolst, bl_wo) } } else { //比较swet1和swet2 if swet1 <= swet2 { for i = 0; i < len(wotablst1); i++ { wotablst1[i].Clipped() bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst1[i].Workordernr bl_wo.Custordernr = wotablst1[i].Custordernr bl_wo.Worklineid = wotablst1[i].Worklineid bl_wo.Projnr = wotablst1[i].Projnr bl_wo.Ordertype = wotablst1[i].Ordertype bl_wo.Status = wotablst1[i].Status bl_wo.Preschedseq = common.ValueToInt(wotablst1[i].Preschedseq, 0) bl_wo.Schedseq = wotablst1[i].Schedseq bl_wo.Oemseq = common.ValueToInt(wotablst1[i].Oemseq, 0) bl_wo.Partfamilyid = wotablst1[i].Partfamilyid bl_wo.Supplygroupid = wotablst1[i].Supplygroupid bl_wo.Workordertab = wotablst1[i] bl_wolst = append(bl_wolst, bl_wo) } } else { for i = 0; i < len(wotablst2); i++ { wotablst2[i].Clipped() bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst2[i].Workordernr bl_wo.Custordernr = wotablst2[i].Custordernr bl_wo.Worklineid = wotablst2[i].Worklineid bl_wo.Projnr = wotablst2[i].Projnr bl_wo.Ordertype = wotablst2[i].Ordertype bl_wo.Status = wotablst2[i].Status bl_wo.Preschedseq = common.ValueToInt(wotablst2[i].Preschedseq, 0) bl_wo.Schedseq = wotablst2[i].Schedseq bl_wo.Oemseq = common.ValueToInt(wotablst2[i].Oemseq, 0) bl_wo.Partfamilyid = wotablst2[i].Partfamilyid bl_wo.Supplygroupid = wotablst2[i].Supplygroupid bl_wo.Workordertab = wotablst2[i] bl_wolst = append(bl_wolst, bl_wo) } } } } } else { return } } } } else { // 非混线模式 // 非混线排序,则正常加载已计划未下达生产订单 if wotablst, err = bl_wl.GetLineTaskWorkordersBySwet(bl_wl.WorklineId); err != nil { err = errors.New(fmt.Sprintf("Failed to load work order for workline: %s due to: %v", bl_wl.WorklineId, err)) return } for i = 0; i < len(wotablst); i++ { wotablst[i].Clipped() if common.ValueToInt(wotablst[i].Oemseq, 0) <= common.ValueToInt(bl_wl.Worklinetab.Releasetparameter, 0) { bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst[i].Workordernr bl_wo.Custordernr = wotablst[i].Custordernr bl_wo.Worklineid = wotablst[i].Worklineid bl_wo.Projnr = wotablst[i].Projnr bl_wo.Ordertype = wotablst[i].Ordertype bl_wo.Status = wotablst[i].Status bl_wo.Preschedseq = common.ValueToInt(wotablst[i].Preschedseq, 0) bl_wo.Schedseq = wotablst[i].Schedseq bl_wo.Oemseq = common.ValueToInt(wotablst[i].Oemseq, 0) bl_wo.Partfamilyid = wotablst[i].Partfamilyid bl_wo.Supplygroupid = wotablst[i].Supplygroupid bl_wo.Workordertab = wotablst[i] bl_wolst = append(bl_wolst, bl_wo) } else { return } } } return } // 基于指定时长获取产线需派工生产订单 // 返回需要派工下达的排好序的生产订单 func (bl_wl *BL_Workline) GetTaskToReleaseByDuration(bl_wolst *[]BL_WorkOrder) (err error) { // 基于产线派工模式分别处理 if bl_wl.MixSort { // 混线模式 switch bl_wl.MixSortMode { case common.LINE_MIXSORT_IN_SWET: // 按交货时间紧急度 case common.LINE_MIXSORT_IN_SWET_RATIO: // 按交付时间和比例 } } else { // 非混线模式 } return } // 获取产线需要下达的工单数 func (bl_wl *BL_Workline) GetLineTaskWorkorders(lineid string, relQty int) (wotabs []db.Pln_workorder, err error) { var ( wotab db.Pln_workorder ) if wotabs, err = wotab.GetLineUnfinishedTaskWorkorders(lineid, relQty); err != nil { return } return } // 获取产线需要下达的工单数 func (bl_wl *BL_Workline) GetLineProjectTaskWorkorders(projnr string, lineid string, relQty int) (wotabs []db.Pln_workorder, err error) { var ( wotab db.Pln_workorder ) // 基于产线设置的参考状态 if wotabs, err = wotab.GetLineProjectUnfinishedTaskWorkorders(projnr, lineid, relQty); err != nil { return } return } // 获取产线需要下达的工单数(混线逻辑,按照swet方式下达) func (bl_wl *BL_Workline) GetLineProjectTaskWorkordersBySwet(projnr string, lineid string, relQty int) (wotabs []db.Pln_workorder, err error) { var ( wotab db.Pln_workorder ) // 基于产线设置的参考状态 if wotabs, err = wotab.GetLineProjectUnfinishedTaskWorkordersBySwet(projnr, lineid, relQty); err != nil { return } return } // 获取产线需要下达的工单数(混线逻辑,按照swet方式下达)但是有oemseq限制 func (bl_wl *BL_Workline) GetLineProjectTaskWorkordersBySwetLimitOemseq(projnr string, lineid string, relQty int, oemseq float64) (wotabs []db.Pln_workorder, err error) { var ( wotab db.Pln_workorder ) // 基于产线设置的参考状态 if wotabs, err = wotab.GetLineProjectUnfinishedTaskWorkordersBySwetLimitOemseq(projnr, lineid, relQty, oemseq); err != nil { return } return } // 按照oemseq号排序,查询100条数据 func (bl_wl *BL_Workline) GetLineTaskWorkordersBySwet(lineid string) (wotabs []db.Pln_workorder, err error) { var ( wotab db.Pln_workorder ) if wotabs, err = wotab.GetLineUnfinishedTaskWorkordersBySwet(lineid); err != nil { return } return } // 混线排序派工,基于最早swet下达 func (bl_wl *BL_Workline) GetTaskFromMixQueueToReleaseBySwet(bl_wolst *[]BL_WorkOrder, relQty int) (err error) { var ( bl_wlpt BL_Workline_ProjTask node *list.Element bl_wo *BL_WorkOrder key, tkey string t time.Time loadQty int ) // 先判断一下所有项目可派工的任务数,如果数量小于等于relQty,则将所有的都派工下去 loadQty = 0 for key, bl_wlpt = range bl_wl.ProjTaskDict { loadQty = loadQty + bl_wlpt.Bl_wolst.Len() } if loadQty < relQty { relQty = loadQty } for { if relQty <= 0 { break } // 初始化,默认比较时间是1年后 tkey = "" t = time.Now().Add(24 * 365 * time.Hour) // 遍历产线上的多个项目的任务队列,取列头比较,时间最早的取走 for key, bl_wlpt = range bl_wl.ProjTaskDict { // 取每个项目任务队列的队首,对Swet做比较,最小的优先处理 node = bl_wlpt.Bl_wolst.Front() bl_wo = node.Value.(*BL_WorkOrder) if bl_wo.Swet.Unix() < t.Unix() { tkey = key t = bl_wo.Swet } } // 从项目任务队列中移除指定节点 if tkey != "" { node = bl_wl.ProjTaskDict[tkey].Bl_wolst.Front() bl_wo = node.Value.(*BL_WorkOrder) *bl_wolst = append(*bl_wolst, *bl_wo) bl_wl.ProjTaskDict[tkey].Bl_wolst.Remove(node) } relQty-- } return } // 混线排序派工,基于项目指定的比例数量下达 func (bl_wl *BL_Workline) GetTaskFromMixQueueToReleaseByRatio(bl_wolst *[]BL_WorkOrder, relQty int) (err error) { var ( bl_wlpt BL_Workline_ProjTask node *list.Element bl_wo *BL_WorkOrder i, j int projnr string loadQty int flag bool ) // 先判断一下所有项目可派工的任务数,如果数量小于等于relQty,则将所有的都派工下去 loadQty = 0 for _, bl_wlpt = range bl_wl.ProjTaskDict { loadQty = loadQty + bl_wlpt.Bl_wolst.Len() } if loadQty < relQty { relQty = loadQty } // 循环遍历项目,派工 for { if relQty <= 0 { break } // 先判断一下所有项目一次循环可派工的任务数是否足够,如果不够则跳出循环 flag = true for i = 0; i < len(bl_wl.ProjList); i++ { projnr = bl_wl.ProjList[i] if bl_wl.ProjTaskDict[projnr].Bl_wolst.Len() < bl_wl.ProjTaskDict[projnr].MixRatioQty { flag = false break } } if !flag { break } // 遍历混线项目 for i = 0; i < len(bl_wl.ProjList); i++ { projnr = bl_wl.ProjList[i] // 先判断一下所有项目一次循环可派工的任务数是否足够,如果不够则跳出循环 if bl_wl.ProjTaskDict[projnr].Bl_wolst.Len() < bl_wl.ProjTaskDict[projnr].MixRatioQty { flag = false break } for j = 0; j < bl_wl.ProjTaskDict[projnr].MixRatioQty; j++ { node = bl_wl.ProjTaskDict[projnr].Bl_wolst.Front() bl_wo = node.Value.(*BL_WorkOrder) *bl_wolst = append(*bl_wolst, *bl_wo) bl_wl.ProjTaskDict[projnr].Bl_wolst.Remove(node) relQty-- } } } return } // 获取产线已派工的订单数 func (bl_wl *BL_Workline) GetReleasedTaskQty() (retQty int, err error) { var ( istat int wotab db.Pln_workorder ) // 基于产线设置的参考状态 if istat, err = strconv.Atoi(bl_wl.Worklinetab.Releasecparameter); err != nil { glog.InfoExtln("排序调度", "GetReleasedTaskQty4 err: ", err) //默认是未下线(完成)订单数 istat = 80 } switch istat { case 40: if retQty, err = wotab.GetLineReleasedTaskQty(bl_wl.WorklineId); err != nil { glog.InfoExtln("排序调度", "GetReleasedTaskQty5 err: ", err) return } break case 80: if retQty, err = wotab.GetLineUnfinishedTaskQty(bl_wl.WorklineId); err != nil { glog.InfoExtln("排序调度", "GetReleasedTaskQty6 err: ", err) return } break default: if retQty, err = wotab.GetLineUnfinishedTaskQty(bl_wl.WorklineId); err != nil { glog.InfoExtln("排序调度", "GetReleasedTaskQty7 err: ", err) return } } return } // 将指定序列的生产订单下达,更新状态为26 func (bl_wl *BL_Workline) ReleaseTasks(bl_wolst []BL_WorkOrder, se *SchedEngine) (err error) { var ( i, startseq int wotablst []db.Pln_workorder wotab db.Pln_workorder intstatus db.Pln_workorder_intstatus cotab db.Pln_custorder looptime int ) looptime = 0 LOOPTIME: // 获取产线最大的排序号 if err = db.G_DbEngine.Where("finr = ? and worklineid = ?", db.G_FINR, bl_wl.WorklineId).Desc("schedseq").Limit(1, 0).Find(&wotablst); err != nil { return } looptime++ if len(wotablst) > 0 { startseq = wotablst[0].Schedseq + 1 } else if looptime >= 100 { startseq = 1 } else { glog.InfoExtln("排序调度", "LOOP起始排序号 = ", bl_wl.WorklineId, startseq) time.Sleep(100 * time.Millisecond) goto LOOPTIME } // 遍历下达订单,依次更新内部排序号和状态 glog.InfoExtln("排序调度", "起始排序号 = ", bl_wl.WorklineId, startseq) fmt.Println(bl_wl.WorklineId, "起始排序号 = ", startseq) for i = 0; i < len(bl_wolst); i++ { /* 获取锁 */ LOOP: err = etcd.G_jobLock.TryLock("lock") if err != nil { fmt.Println("seq groutine lock fail!") if conf.ConfValue.TimeInterval < 1 { time.Sleep(10 * time.Millisecond) } else { time.Sleep(time.Duration(conf.ConfValue.TimeInterval) * time.Millisecond) } glog.InfoExtln("排序调度", "conf.ConfValue.TimeInterval = ",conf.ConfValue.TimeInterval) goto LOOP } //开启事务 session := db.G_DbEngine.NewSession() if err = session.Begin(); err != nil { session.Close() etcd.G_jobLock.UnLock() return } wotab = db.Pln_workorder{} wotab = bl_wolst[i].Workordertab wotab.Schedseq = startseq wotab.Status = common.WO_STATUS_RELEASED wotab.Lastmodif = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss") // 处理生产订单的拣料零件 if err = wotab.UpdateFields(session, "schedseq,status,pickstatus,lastmodif"); err != nil { glog.InfoExtln("排序调度", "err is : ", err) session.Rollback() session.Close() etcd.G_jobLock.UnLock() return } //下达的订单放到缓存数据表里,为接口数据做准备 intstatus = db.Pln_workorder_intstatus{} intstatus.Finr = db.G_FINR intstatus.Workordernr = wotab.Workordernr intstatus.Releaseflag = 0 intstatus.Runningflag = 0 intstatus.Finishflag = 0 intstatus.Lastmodif = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss") intstatus.Credatuz = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss") intstatus.Lastuser = "scheduler" err = intstatus.Insert(session) if err != nil { glog.InfoExtln("排序调度", "err is : ", err) session.Rollback() session.Close() etcd.G_jobLock.UnLock() return } startseq = startseq + 1 // 更新客户订单状态 cotab = db.Pln_custorder{Finr: db.G_FINR, Custordernr: wotab.Custordernr, Status: common.WO_STATUS_RELEASED} err = cotab.UpdateToFields(session, "status") if err != nil { glog.InfoExtln("排序调度", "err is : ", err) session.Rollback() session.Close() etcd.G_jobLock.UnLock() return } session.Commit() session.Close() etcd.G_jobLock.UnLock() } return } // 获取指定产线未拣料的生产订单 func (bl_wl *BL_Workline) GetUnpickedWorkorderList() (bl_wolst []BL_WorkOrder, err error) { var ( bl_wo BL_WorkOrder bl_wopt BL_WorkOrder_Part bl_woattr BL_OrdAttribute wotab db.Pln_workorder wotablst []db.Pln_workorder i, j, k int ) // 获取产线所有未拣料(status = 26)生产订单 wotab = db.Pln_workorder{} if wotablst, err = wotab.GetLineUnpickedTasksFullData(bl_wl.WorklineId); err != nil { return } if len(wotablst) == 0 { return } bl_wolst = []BL_WorkOrder{} for i = 0; i < len(wotablst); i++ { bl_wo = BL_WorkOrder{} bl_wo.Workordernr = wotablst[i].Workordernr bl_wo.Custordernr = wotablst[i].Custordernr bl_wo.Projnr = wotablst[i].Projnr bl_wo.Partfamilyid = wotablst[i].Partfamilyid bl_wo.Supplygroupid = wotablst[i].Supplygroupid bl_wo.Oemseq = common.ValueToInt(wotablst[i].Oemseq, 0) bl_wo.Schedseq = wotablst[i].Schedseq bl_wo.Status = wotablst[i].Status bl_wo.Workordertab = wotablst[i] // 加载生产订单的零件清单 bl_wo.Bl_wopartdict = make(map[string]BL_WorkOrder_Part) for j = 0; j < len(wotablst[i].Partlst); j++ { bl_wopt = BL_WorkOrder_Part{} bl_wopt.Workordernr = bl_wo.Workordernr bl_wopt.Partid = wotablst[i].Partlst[j].Partid bl_wopt.Qty = wotablst[i].Partlst[j].Partqty bl_wo.Bl_wopartdict[bl_wopt.Partid] = bl_wopt } // 加载生产订单的属性清单 bl_wo.Bl_ordattrdict = make(map[int]BL_OrdAttribute) for k = 0; k < len(wotablst[i].Attrlst); k++ { bl_woattr = BL_OrdAttribute{} bl_woattr.Attrcode = wotablst[i].Attrlst[k].Attrcode bl_wo.Bl_ordattrdict[bl_woattr.Attrcode] = bl_woattr } bl_wolst = append(bl_wolst, bl_wo) } return } //查询产线信息 func (bl_wl *BL_Workline) SelectWorkline() (data db.Workline, err error) { var bl_wo db.Workline bl_wo.Finr = db.G_FINR bl_wo.Worklineid = bl_wl.WorklineId data, err = bl_wo.SelectOne() if err != nil { return } return }