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.

442 lines
14 KiB

package service
import (
"errors"
"fmt"
"github.com/go-xorm/xorm"
"leit.com/leit_seat_aps/common"
"leit.com/leit_seat_aps/db"
"time"
)
// 拣料单模板
type BL_PickingTemplate struct {
TemplateId string // 拣料单模板ID
WorklineId string // 产线
PrinterId string // 打印机
AdaptWay string // A = 属性 ; P = 零件
AssignAttrDict map[int]db.Pln_picktemplate_attrlst // 分配的属性
AssignPartDict map[string]db.Pln_picktemplate_itemlst // 分配的零件号
Picktemplatetab db.Pln_picktemplate
}
// 拣料单
type BL_PickingOrder struct {
OrderNr string
TemplateId string
PlanQty int
FilledTotalQty int
FilledOrderDict map[string]string // 已填充的工单
FillAttrDict map[int]int // 分配的属性
FillItemDict map[string]int // 分配的零件号
Pickordertab db.Pln_pickorder
}
// 拣料单零件数据对象
type PickingItemData struct {
PartId string
Qty int
OemSeq int
Attrcode int
Workordernr string
Wotab db.Pln_workorder
}
// 基于拣料单模板创建拣料单
func (bl_pko *BL_PickingOrder) CreatePickOrder(session *xorm.Session, pe *PickingEngine, picktmpid string) (pickorderid string, err error) {
var (
pkordtab db.Pln_pickorder
bl_pktmp BL_PickingTemplate
ok bool
)
// 查找拣料单模板是否存在
if bl_pktmp, ok = pe.PickingTmpDict[picktmpid]; !ok {
err = errors.New("The specified picking template: " + picktmpid + " is not existing in the global mdata!")
return
}
// 创建拣料单头
if pickorderid, err = SN_GetNextSnrBySession(pe.PickOrderSN, session); err != nil {
return
}
pkordtab = db.Pln_pickorder{}
pkordtab.Finr = db.G_FINR
pkordtab.Pickorderid = pickorderid
pkordtab.Picktemplateid = picktmpid
pkordtab.Status = common.PKO_STATUS_PLANNED
pkordtab.Worklineid = bl_pktmp.WorklineId
pkordtab.Printerid = bl_pktmp.PrinterId
pkordtab.Planqty = bl_pktmp.Picktemplatetab.Planqty
pkordtab.Lastuser = "service"
pkordtab.Credatuz = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
if err = pkordtab.Insert(session); err != nil {
return
}
bl_pko.OrderNr = pkordtab.Pickorderid
bl_pko.TemplateId = picktmpid
bl_pko.PlanQty = pkordtab.Planqty
bl_pko.Pickordertab = pkordtab
return
}
// 刷新拣料单当前已拣料信息, 属性字典/零件字典记录当前已填充属性或零件的总数
func (bl_pko *BL_PickingOrder) RefreshPickingStatus(bl_pktmp *BL_PickingTemplate) {
var (
ok bool
i, fillqty int
)
// 计数模式
switch bl_pktmp.Picktemplatetab.Countmode {
case common.PKT_COUNT_MODE_BY_WO: // 工单计数模式,收集所有已填充工单
bl_pko.FilledOrderDict = make(map[string]string)
bl_pko.FilledTotalQty = 0
for i = 0; i < len(bl_pko.Pickordertab.Itemlst); i++ {
bl_pko.FilledOrderDict[bl_pko.Pickordertab.Itemlst[i].Serialno] = bl_pko.Pickordertab.Itemlst[i].Serialno
bl_pko.FilledTotalQty = bl_pko.FilledTotalQty + bl_pko.Pickordertab.Itemlst[i].Fillqty
}
case common.PKT_COUNT_MODE_BY_QTY: // 零件数量计数模式,收集所有零件总数
bl_pko.FilledTotalQty = 0
for i = 0; i < len(bl_pko.Pickordertab.Itemlst); i++ {
bl_pko.FilledTotalQty = bl_pko.FilledTotalQty + bl_pko.Pickordertab.Itemlst[i].Fillqty
}
}
// 判断模板适配类型并初始化字典而后填充
switch bl_pktmp.Picktemplatetab.Adaptway {
case common.PKT_ADAPT_BY_ATTR:
bl_pko.FillAttrDict = make(map[int]int)
for i = 0; i < len(bl_pktmp.Picktemplatetab.Attrlst); i++ {
bl_pko.FillAttrDict[bl_pktmp.Picktemplatetab.Attrlst[i].Attrcode] = 0
}
// 遍历拣料单的已拣料项,计算各属性已填充数量
for i = 0; i < len(bl_pko.Pickordertab.Itemlst); i++ {
if fillqty, ok = bl_pko.FillAttrDict[bl_pko.Pickordertab.Itemlst[i].Attrcode]; !ok {
continue
}
fillqty = fillqty + bl_pko.Pickordertab.Itemlst[i].Fillqty
bl_pko.FillAttrDict[bl_pko.Pickordertab.Itemlst[i].Attrcode] = fillqty
}
case common.PKT_ADAPT_BY_PART:
bl_pko.FillItemDict = make(map[string]int)
for i = 0; i < len(bl_pktmp.Picktemplatetab.Itemlst); i++ {
bl_pko.FillItemDict[bl_pktmp.Picktemplatetab.Itemlst[i].Partid] = 0
}
// 遍历拣料单的已拣料项,计算各零件已填充数量
for i = 0; i < len(bl_pko.Pickordertab.Itemlst); i++ {
if fillqty, ok = bl_pko.FillItemDict[bl_pko.Pickordertab.Itemlst[i].Partid]; !ok {
continue
}
fillqty = fillqty + bl_pko.Pickordertab.Itemlst[i].Fillqty
bl_pko.FillItemDict[bl_pko.Pickordertab.Itemlst[i].Partid] = fillqty
}
}
return
}
// 基于拣料单的已拣料状态判断是否可继续填充指定的属性或零件
func (bl_pko *BL_PickingOrder) IsFillable(wonr string, attrcode int, partid string, bl_pktmp *BL_PickingTemplate) (fillable bool, err error) {
var (
ok bool
ipos, fillqty int
)
// 基于模板适配类型判断已填充数是否已到上限
fillable = true
switch bl_pktmp.Picktemplatetab.Countmode {
case common.PKT_COUNT_MODE_BY_WO: // 基于订单数
if len(bl_pko.FilledOrderDict) >= bl_pktmp.Picktemplatetab.Planqty {
if _, ok = bl_pko.FilledOrderDict[wonr]; !ok {
// 订单数满足的情况下,不可填充
fillable = false
fmt.Println(" PKT_COUNT_MODE_BY_WO 不可填充 ")
return
}
}
case common.PKT_COUNT_MODE_BY_QTY: // 基于零件总数
if bl_pko.FilledTotalQty == bl_pktmp.Picktemplatetab.Planqty {
// 总数已满足的情况下,不可填充
fillable = false
fmt.Println(" PKT_COUNT_MODE_BY_QTY 不可填充 ")
return
}
}
// 订单数不满足的情况下,看该属性或零件数量是否已达标
switch bl_pktmp.Picktemplatetab.Adaptway {
case common.PKT_ADAPT_BY_ATTR:
ipos = bl_pktmp.Picktemplatetab.GetAttributePos(attrcode)
if ipos < 0 {
fillable = false // 属性不匹配,不可填充
fmt.Println(ipos, " 属性不存在模板中!")
} else {
if fillqty, ok = bl_pko.FillAttrDict[attrcode]; ok {
if fillqty >= bl_pktmp.Picktemplatetab.Attrlst[ipos].Planqty {
fillable = false
fmt.Println(" 已填充数量>=计划数量", fillqty, bl_pktmp.Picktemplatetab.Attrlst[ipos].Planqty)
}
}
}
fmt.Println(" PKT_ADAPT_BY_ATTR 填充?= ", fillable)
return
case common.PKT_ADAPT_BY_PART:
ipos = bl_pktmp.Picktemplatetab.GetPartPos(partid)
if ipos < 0 {
fillable = false // 属性不匹配,不可填充
} else {
if fillqty, ok = bl_pko.FillItemDict[partid]; !ok {
fillable = false
} else {
if bl_pktmp.Picktemplatetab.Itemlst[ipos].Planqty > fillqty {
fillable = true
} else {
fillable = false
}
}
}
fmt.Println(" PKT_ADAPT_BY_PART 填充?= ", fillable)
return
}
return
}
// 基于拣料单模板查找开口的拣料单(未下达的),如果存在多个,则返回最早新建的
func (bl_pko *BL_PickingOrder) GetOpenPickOrderByTemplate(session *xorm.Session, picktmpid string, attrcode int) (exist bool, pickorderid string, err error) {
var (
i int
pkordtab db.Pln_pickorder
pkordtablst []db.Pln_pickorder
)
exist = false
// 获取最新创建已计划未下达的包装单
pkordtab = db.Pln_pickorder{}
if exist, pkordtablst, err = pkordtab.GetOpenOrdersForTemplateBySession(session, picktmpid); err != nil {
return
}
// 遍历开口拣料单适配
for i = 0; i < len(pkordtablst); i++ {
bl_pko.OrderNr = pkordtablst[i].Pickorderid
bl_pko.TemplateId = picktmpid
bl_pko.PlanQty = pkordtablst[i].Planqty
bl_pko.Pickordertab = pkordtablst[i]
}
if exist {
pickorderid = pkordtab.Pickorderid
} else {
pickorderid = ""
}
return
}
// 将零件添加到开口包装单内
func (bl_pko *BL_PickingOrder) AddPickingPart(session *xorm.Session, attrcode int, bl_wopart BL_WorkOrder_Part, pickorderid string) (err error) {
var (
pickordtab db.Pln_pickorder
pickorditemtab db.Pln_pickorder_itemlst
pos, ilen, i, iqty int
)
// 获取拣料单完整数据,检查拣料单状态是否满足
pickordtab = db.Pln_pickorder{Pickorderid: pickorderid}
if pickordtab, err = pickordtab.SelectOneBySession(session); err != nil {
return
}
// 遍历拣料单子项,获取Pos,并将零件添加到拣料单
ilen = len(pickordtab.Itemlst)
if ilen <= 0 {
pos = 1
} else {
pos = pickordtab.Itemlst[ilen-1].Pos + 1
}
pickorditemtab = db.Pln_pickorder_itemlst{}
pickorditemtab.Finr = db.G_FINR
pickorditemtab.Pickorderid = pickorderid
pickorditemtab.Pos = pos
pickorditemtab.Partid = bl_wopart.Partid
pickorditemtab.Descr1 = bl_wopart.Parttab.Descr1
pickorditemtab.Descr2 = bl_wopart.Parttab.Descr2
pickorditemtab.Planqty = bl_wopart.Qty
pickorditemtab.Fillqty = bl_wopart.Qty
pickorditemtab.Actqty = 0
pickorditemtab.Oemseq = bl_wopart.Workordertab.Oemseq
pickorditemtab.Attrcode = attrcode
pickorditemtab.Serialno = bl_wopart.Workordertab.Workordernr
pickorditemtab.Status = common.PKO_STATUS_RELEASED
pickorditemtab.Lastuser = "service"
pickorditemtab.Credatuz = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
if err = pickorditemtab.Insert(session); err != nil {
return
}
// 更新拣料单: 填充数量和更新时间
pickordtab.Itemlst = append(pickordtab.Itemlst, pickorditemtab)
iqty = 0
for i = 0; i < len(pickordtab.Itemlst); i++ {
iqty = pickordtab.Itemlst[i].Fillqty + iqty
}
pickordtab.Pickorderid = pickorderid
pickordtab.Fillqty = iqty
pickordtab.Lastmodif = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
if err = pickordtab.UpdateFields(session, "fillqty, lastmodif"); err != nil {
return
}
return
}
// 尝试下达拣料单
func (bl_pko *BL_PickingOrder) TryToRelease(session *xorm.Session, pickorderid string, bl_pktmp *BL_PickingTemplate) (released bool, err error) {
var (
pickordtab db.Pln_pickorder
i, fillqty int
releasable, ok bool
)
pickordtab = db.Pln_pickorder{Pickorderid: pickorderid}
if pickordtab, err = pickordtab.SelectOneBySession(session); err != nil {
return
}
bl_pko.Pickordertab = pickordtab
bl_pko.RefreshPickingStatus(bl_pktmp)
releasable = true
switch bl_pktmp.Picktemplatetab.Countmode {
case common.PKT_COUNT_MODE_BY_QTY:
// 逻辑1: 以填充数量是否达到计数总量为标准
if bl_pko.FilledTotalQty >= bl_pko.Pickordertab.Planqty {
switch bl_pktmp.Picktemplatetab.Adaptway {
case common.PKT_ADAPT_BY_ATTR:
for i = 0; i < len(bl_pktmp.Picktemplatetab.Attrlst); i++ {
if bl_pktmp.Picktemplatetab.Attrlst[i].Mandatory <= 0 {
continue
}
// 强制属性的数量校验
if fillqty, ok = bl_pko.FillAttrDict[bl_pktmp.Picktemplatetab.Attrlst[i].Attrcode]; !ok {
releasable = false
break
} else {
if fillqty < bl_pktmp.Picktemplatetab.Attrlst[i].Planqty {
releasable = false
break
}
}
}
case common.PKT_ADAPT_BY_PART:
for i = 0; i < len(bl_pktmp.Picktemplatetab.Itemlst); i++ {
if bl_pktmp.Picktemplatetab.Itemlst[i].Mandatory <= 0 {
continue
}
// 强制属性的数量校验
if fillqty, ok = bl_pko.FillItemDict[bl_pktmp.Picktemplatetab.Itemlst[i].Partid]; !ok {
releasable = false
break
} else {
if fillqty < bl_pktmp.Picktemplatetab.Itemlst[i].Planqty {
releasable = false
break
}
}
}
default:
releasable = false
}
} else {
// 总量未到达不可下达
releasable = false
}
case common.PKT_COUNT_MODE_BY_WO:
if len(bl_pko.FilledOrderDict) >= bl_pko.Pickordertab.Planqty {
switch bl_pktmp.Picktemplatetab.Adaptway {
case common.PKT_ADAPT_BY_ATTR:
for i = 0; i < len(bl_pktmp.Picktemplatetab.Attrlst); i++ {
if bl_pktmp.Picktemplatetab.Attrlst[i].Mandatory <= 0 {
continue
}
// 强制属性的数量校验
if fillqty, ok = bl_pko.FillAttrDict[bl_pktmp.Picktemplatetab.Attrlst[i].Attrcode]; !ok {
releasable = false
break
} else {
if fillqty < bl_pktmp.Picktemplatetab.Attrlst[i].Planqty {
releasable = false
break
}
}
}
case common.PKT_ADAPT_BY_PART:
for i = 0; i < len(bl_pktmp.Picktemplatetab.Itemlst); i++ {
if bl_pktmp.Picktemplatetab.Itemlst[i].Mandatory <= 0 {
continue
}
// 强制属性的数量校验
if fillqty, ok = bl_pko.FillItemDict[bl_pktmp.Picktemplatetab.Itemlst[i].Partid]; !ok {
releasable = false
break
} else {
if fillqty < bl_pktmp.Picktemplatetab.Itemlst[i].Planqty {
releasable = false
break
}
}
}
default:
releasable = false
}
} else {
releasable = false
}
}
if releasable {
pickordtab.Fillqty = bl_pko.FilledTotalQty
pickordtab.Status = common.PKO_STATUS_RELEASED
pickordtab.Lastuser = "service"
pickordtab.Lastmodif = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
if err = pickordtab.UpdateFields(session, "fillqty, status, lastuser, lastmodif"); err != nil {
return
}
released = true
return
}
return
}
// 下达拣料单
func (bl_pko *BL_PickingOrder) Release(session *xorm.Session) (err error) {
var i int
if bl_pko.Pickordertab.Status < common.PKO_STATUS_RELEASED {
// 遍历子项看是否有未下达的
for i = 0; i < len(bl_pko.Pickordertab.Itemlst); i++ {
if bl_pko.Pickordertab.Itemlst[i].Status < common.PKO_STATUS_RELEASED {
err = errors.New(fmt.Sprintf("Pickorder %s item %s status is %d,not allow to release!",
bl_pko.Pickordertab.Pickorderid, bl_pko.Pickordertab.Itemlst[i].Partid, bl_pko.Pickordertab.Itemlst[i].Status))
return
}
}
// 更新拣料单头的状态为下达状态
bl_pko.Pickordertab.Status = common.PKO_STATUS_RELEASED
bl_pko.Pickordertab.Lastuser = "service"
bl_pko.Pickordertab.Lastmodif = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
if err = bl_pko.Pickordertab.UpdateFields(session, "actqty, status, lastuser, lastmodif"); err != nil {
return
}
}
return
}