|
|
- package seq
-
- import (
- "fmt"
- "github.com/go-xorm/xorm"
- "leit.com/leit_seat_aps/common"
- "leit.com/leit_seat_aps/db"
- "leit.com/leit_seat_aps/glog"
- "leit.com/leit_seat_aps/service"
- "strings"
- "time"
- )
-
- /**
- 基于已派工生产订单计算拣料单
- 基本逻辑:
- 1. 加载产线对应的拣料单模板
- 2. 循环加载派工生产订单,按产线和schedKey排序
- 3. 遍历生产订单零件列表
- 4. 遍历零件属性和生产订单对应产线的拣料单属性进行适配,满足则将该零件和数量添加到该拣料单中
- 5. 拣料单满,关闭拣料单并新建一个空拣料单
- **/
-
- // 拣料单服务
- // 功能描述:基于排序产线对应的已下达的生产订单,通过属性匹配自动创建拣料单,并填充待拣料项,直至到达需求上限
- // 拣料单创建初始状态 = 20 计划;填充完 = 26 下达;
- func RunPicker() (err error) {
- var (
- pkordsn string
- pe service.PickingEngine
- bl_wolist []service.BL_WorkOrder
- bl_wline service.BL_Workline
- i int
- //pln db.Pln_custorder
- )
-
- // 获取拣料单序列号
- if pkordsn, err = service.GetSysStringParameter(2, "*", "JIS_PICKORDER_SN"); err != nil {
- return
- }
- if strings.TrimSpace(pkordsn) == "" {
- pkordsn = "PICKORDER" // 默认流水ID
- }
- fmt.Println("JIS_PICKORDER_SN = ", pkordsn)
- // 初始化
- pe = service.PickingEngine{PickOrderSN: pkordsn}
-
- // 加载主数据
- fmt.Println("准备开始加载主数据......")
- if err = pe.LoadMasterData(); err != nil {
- return
- }
- fmt.Println("完成主数据加载!")
- glog.InfoExtln("PickingTmpDict","PickingTmpDict:",pe.PickingTmpDict)
- // 循环服务
- for {
- fmt.Println("循环服务开启......")
- //判断生成订单是否有未下达的,如果有的话,那么不往下进行
- //data, err := pln.SelectTenArr()
- //if err != nil || len(data) > 0 {
- // //有未下达的,则等待五秒
- // time.Sleep(5 * time.Second)
- // continue
- //}
- // 遍历产线
- for _, bl_wline = range pe.WorklineDict {
- fmt.Println(" 遍历产线:", bl_wline.WorklineId)
- // 从数据库中循环读取指定产线已派工下达未拣料的排序订单
- if bl_wolist, err = bl_wline.GetUnpickedWorkorderList(); err != nil {
- glog.InfoExtln("拣料单服务", "Failed to GetUnpickedWorkorderList:", err)
- continue
- }
- if len(bl_wolist) == 0{
- //判断生成订单的长度
- time.Sleep(5 * time.Second)
- continue
- }
- // 遍历产线上未拣料的生产订单并对它进行拣料
- for i = 0; i < len(bl_wolist); i++ {
- if err = PickLineWorkorder(&bl_wline, &bl_wolist[i], &pe); err != nil {
- glog.InfoExtln("拣料单服务", "Failed to PickLineWorkorder:", err)
- continue
- }
- }
- }
-
- time.Sleep(10 * time.Second)
- }
-
- }
-
- // 对产线上的派工订单进行拣料
- func PickLineWorkorder(bl_wline *service.BL_Workline, bl_wo *service.BL_WorkOrder, pe *service.PickingEngine) (err error) {
- var (
- session *xorm.Session
- bl_wopart service.BL_WorkOrder_Part
- bl_part service.BL_Part
- bl_pktmp service.BL_PickingTemplate
- bl_pko service.BL_PickingOrder
- bl_ordmsg service.BL_Ordmsg
- pktmpattrtab db.Pln_picktemplate_attrlst
- pktmpparttab db.Pln_picktemplate_itemlst
- i,attrcode int
- pickorderid, picktmpid, partid, wonr string
- ok, bflag, matched, exist, released bool
- pkodict map[string]service.BL_PickingTemplate
- )
-
- // 生产订单项目是否存在,如果不存在则不作处理
- if _, ok = pe.Projectdict[bl_wo.Workordertab.Projnr]; !ok {
- return
- }
-
- session = db.G_DbEngine.NewSession()
- defer session.Close()
- if err = session.Begin(); err != nil {
- return
- }
-
- // 遍历订单零件列表
- bflag = true
- pkodict = make(map[string]service.BL_PickingTemplate)
- for i = 0; i < len(bl_wo.Workordertab.Partlst); i++ {
- // 如果遍历零件不能存在则跳过
- if bl_part, ok = pe.Projectdict[bl_wo.Projnr].Partdict[bl_wo.Workordertab.Partlst[i].Partid]; !ok {
- continue
- }
- if bl_wopart, ok = bl_wo.Bl_wopartdict[bl_wo.Workordertab.Partlst[i].Partid]; !ok {
- continue
- }
- bl_wopart.Workordertab = bl_wo.Workordertab
- bl_wopart.Parttab = bl_part.Parttab
- // 获取零件在当前产线的拣料单模板,如果适配
- matched = false
- // 零件只能进入到一个匹配模板,因此要遍历产线上的所有拣料单模板,一旦适配则返回
- for _, bl_pktmp = range bl_wline.PickTmpDict {
- // 基于不同的适配模式做属性或者零件的适配
- switch bl_pktmp.Picktemplatetab.Adaptway {
- case common.PKT_ADAPT_BY_ATTR: // 比对零件属性是否在模板分配的属性中
- for _, pktmpattrtab = range bl_pktmp.AssignAttrDict {
- if _, ok = bl_part.AtcodDict[pktmpattrtab.Attrcode]; ok {
- matched = true
- wonr = bl_wo.Workordertab.Workordernr
- attrcode = pktmpattrtab.Attrcode
- picktmpid = bl_pktmp.TemplateId
- break
- }
- }
- case common.PKT_ADAPT_BY_PART: // 比对订单零件和模板分配零件是否相同
- for _, pktmpparttab = range bl_pktmp.AssignPartDict {
- if bl_wopart.Partid == pktmpparttab.Partid {
- matched = true
- wonr = bl_wo.Workordertab.Workordernr
- partid = bl_wo.Workordertab.Partlst[i].Partid
- picktmpid = bl_pktmp.TemplateId
- break
- }
- }
- default:
- continue
- }
- // 匹配成功,则该零件将不再进行对其它模板的匹配
- if matched {
- break
- }
- }
- // 如果适配,则将该零件加入到开口拣料单
- if matched {
- // 基于拣料单模板得到当前产线开口的拣料单
- bl_pko.TemplateId = picktmpid
- if exist, pickorderid, err = pe.GetOpenPickOrderByTemplate(session, &bl_pko, wonr, attrcode, partid); err != nil {
- bflag = false
- break
- }
- if !exist {
- // 不存在开口拣料单则新建
- if pickorderid, err = bl_pko.CreatePickOrder(session, pe, picktmpid); err != nil {
- bflag = false
- break
- }
- }
- // 将零件加入开口拣料单
- if err = bl_pko.AddPickingPart(session, attrcode, bl_wopart, pickorderid); err != nil {
- bflag = false
- break
- }
-
- // 判断拣料单是否已满,满则下达并生成拣料单消息用于拣料单打印
- if bl_pktmp.Picktemplatetab.Countmode == common.PKT_COUNT_MODE_BY_QTY {
- if released, err = bl_pko.TryToRelease(session, pickorderid, &bl_pktmp); err != nil {
- return
- }
- if released {
- // 生成用于打印的拣料单消息
- bl_ordmsg = service.BL_Ordmsg{MsgType: common.MSG_TYPE_PICK, MsgObjid: pickorderid, MsgEvent: common.MSG_EVENT_PRINT}
- if err = bl_ordmsg.Create(session); err != nil {
- return
- }
- }
- } else {
- pkodict[pickorderid] = bl_pktmp
- }
- }
- }
-
- // 检查那些按工单计数的开口拣料单是否达到计数要求,如是则关闭这些拣料单
- for pickorderid, bl_pktmp = range pkodict {
- if released, err = bl_pko.TryToRelease(session, pickorderid, &bl_pktmp); err != nil {
- return
- }
- if released {
- // 生成用于打印的拣料单消息
- bl_ordmsg = service.BL_Ordmsg{MsgType: common.MSG_TYPE_PICK, MsgObjid: pickorderid, MsgEvent: common.MSG_EVENT_PRINT}
- if err = bl_ordmsg.Create(session); err != nil {
- return
- }
- }
- }
-
- // 完成工单所有零件的匹配,更新工单的拣料状态
- if err = bl_wo.SetPickingStatus(session, 1); err != nil {
- bflag = false
- }
-
- if bflag {
- session.Commit()
- } else {
- session.Rollback()
- }
- session.Close()
- return
- }
|