SJA APS后端代码
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.

232 lines
7.5 KiB

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
}