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
|
|
}
|