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.

1127 lines
35 KiB

package service
import (
"errors"
"fmt"
"github.com/go-xorm/xorm"
"leit.com/leit_seat_aps/common"
"leit.com/leit_seat_aps/db"
"leit.com/leit_seat_aps/glog"
"strings"
"time"
)
// 用于CALLOFF解析的项目主数据对象
type CalloffProject struct {
Projectid string
Projecttab db.Me_project // 项目表
Packtypedict map[string]db.Jit_packtype // 所有的包装类型
Packtmpldict map[string]BL_Package // 发运包装模板
Cartmpldict map[string]BL_Shipcar // 发运车模板
Sgdict map[string]db.Me_supplygroup // 供应组
Pfdict map[string]db.Me_partfamily // 零件族
Pfcsdict map[string]int // 用于存放项目各零件族解析的最大的CheckSequence
}
// 加载项目的主数据
func (cop *CalloffProject) LoadMasterData() (err error) {
// 读取项目的零件族主数据
if err = cop.LoadPartFamily(); err != nil {
return
}
// 读取项目的供应组主数据
if err = cop.LoadSupplyGroup(); err != nil {
return
}
// 读取项目的包装类型主数据
if err = cop.LoadPackageType(); err != nil {
return
}
// 读取项目的发运包装模板主数据
if err = cop.LoadPackageTemplate(); err != nil {
return
}
// 读取项目的发运车模板主数据
if err = cop.LoadShipCarTemplate(); err != nil {
return
}
return
}
// 加载项目的包装类型
func (cop *CalloffProject) LoadPackageType() (err error) {
var (
paktyptab db.Jit_packtype
paktyptablst []db.Jit_packtype
i int
)
// 初始化
cop.Packtypedict = make(map[string]db.Jit_packtype)
paktyptab = db.Jit_packtype{}
if paktyptablst, err = paktyptab.GetProjectAll(cop.Projectid); err != nil {
return
}
for i = 0; i < len(paktyptablst); i++ {
cop.Packtypedict[paktyptablst[i].Packtypeid] = paktyptablst[i]
}
return
}
// 加载项目的发运包装模板
func (cop *CalloffProject) LoadPackageTemplate() (err error) {
var (
paktmpltab db.Jit_packtemplate
paktmpltablst []db.Jit_packtemplate
bl_sp BL_Package
i, j, count int
ok bool
)
// 初始化
cop.Packtmpldict = make(map[string]BL_Package)
paktmpltab = db.Jit_packtemplate{}
// 读取项目发运包装模板数据
if paktmpltablst, err = paktmpltab.GetProjectAll(cop.Projectid); err != nil {
return
}
for i = 0; i < len(paktmpltablst); i++ {
bl_sp = BL_Package{}
bl_sp.SgDict = make(map[string]int)
bl_sp.PackTmplId = paktmpltablst[i].Packtemplateid
bl_sp.Paktmpltab = paktmpltablst[i]
for j = 0; j < len(paktmpltablst[i].Itemlst); j++ {
if count, ok = bl_sp.SgDict[paktmpltablst[i].Itemlst[j].Supplygroupid]; !ok {
bl_sp.SgDict[paktmpltablst[i].Itemlst[j].Supplygroupid] = 1
} else {
bl_sp.SgDict[paktmpltablst[i].Itemlst[j].Supplygroupid] = count + 1
}
}
cop.Packtmpldict[bl_sp.PackTmplId] = bl_sp
}
return
}
// 加载项目的发运车模板
func (cop *CalloffProject) LoadShipCarTemplate() (err error) {
var (
cartmpltab db.Jit_shiptemplate
cartmpltablst []db.Jit_shiptemplate
bl_scar BL_Shipcar
i, j int
)
// 初始化
cop.Cartmpldict = make(map[string]BL_Shipcar)
cartmpltab = db.Jit_shiptemplate{}
// 读取项目发运车模板数据
if cartmpltablst, err = cartmpltab.GetProjectAll(cop.Projectid); err != nil {
return
}
for i = 0; i < len(cartmpltablst); i++ {
bl_scar = BL_Shipcar{}
bl_scar.ShipTmplId = cartmpltablst[i].Shiptemplateid
bl_scar.Shipcartab = cartmpltablst[i]
bl_scar.Paktypdict = make(map[string]db.Jit_shiptemplate_itemlst)
for j = 0; j < len(cartmpltablst[i].Itemlst); j++ {
bl_scar.Paktypdict[cartmpltablst[i].Itemlst[j].Packtypeid] = cartmpltablst[i].Itemlst[j]
}
cop.Cartmpldict[bl_scar.ShipTmplId] = bl_scar
}
return
}
// 加载供应组信息
func (cop *CalloffProject) LoadSupplyGroup() (err error) {
var (
sgtab db.Me_supplygroup
sgtablst []db.Me_supplygroup
i int
)
// 初始化
cop.Sgdict = make(map[string]db.Me_supplygroup)
sgtab = db.Me_supplygroup{}
sgtablst = []db.Me_supplygroup{}
if sgtablst, err = sgtab.GetProjectAll(cop.Projectid); err != nil {
return
}
for i = 0; i < len(sgtablst); i++ {
cop.Sgdict[sgtablst[i].Supplygroupid] = sgtablst[i]
}
return
}
// 获取项目的零件族字典
func (cop *CalloffProject) LoadPartFamily() (err error) {
var (
pftab db.Me_partfamily
pftablst []db.Me_partfamily
i int
)
// 初始化项目的零件族字典
cop.Pfdict = make(map[string]db.Me_partfamily)
pftab = db.Me_partfamily{}
if pftablst, err = pftab.GetProjectPfList(cop.Projectid); err != nil {
return
}
// 遍历零件族列表并写入字典
for i = 0; i < len(pftablst); i++ {
cop.Pfdict[pftablst[i].Partfamilyid] = pftablst[i]
}
return
}
// 加载项目各零件族已解析的最大的CheckSequence信息
func (cop *CalloffProject) LoadPartFamilyMaxParsedCheckSequence() (err error) {
var (
pftab db.Me_partfamily
pftablst []db.Me_partfamily
cflandtab db.Pln_calloffdata_landing
i, maxcsnr int
)
// 初始化
cop.Pfcsdict = make(map[string]int)
// 加载项目零件族
pftab = db.Me_partfamily{}
if pftablst, err = pftab.GetProjectAll(cop.Projectid); err != nil {
return
}
// 查询各项目已解析的最大的CheckSequence号
for i = 0; i < len(pftablst); i++ {
cflandtab = db.Pln_calloffdata_landing{}
if maxcsnr, err = cflandtab.GetParsedMaxCheckSequence(cop.Projectid, pftablst[i].Partfamilyid); err != nil {
return
}
cop.Pfcsdict[pftablst[i].Partfamilyid] = maxcsnr
}
return
}
// 判断两者的pfid是否一致
func (cop *CalloffProject) IsSamePartFamily(sgid, chksgid string) (same bool) {
var (
sgtab, chksgtab db.Me_supplygroup
)
sgtab, _ = cop.Sgdict[sgid]
chksgtab, _ = cop.Sgdict[chksgid]
if chksgtab.Partfamilyid != sgtab.Partfamilyid {
return false
} else {
return true
}
}
// 尝试下达包装单
// 检查oemseq的数量和seq的数量是否一致,一致则下达
func (cop *CalloffProject) TryReleasePackOrder(session *xorm.Session, bl_pakord BL_PackOrder) (relordlst []string, err error) {
var (
i int
pakordtab db.Jit_packorder
pkotablst []db.Jit_packorder
bl_syncpo BL_PackOrder
bl_paktpl BL_Package
ok, canrel bool
)
relordlst = []string{}
// 获取包装单完整数据,检查包装单状态是否满足
if bl_pakord.Pkotab.Status >= common.PKO_STATUS_RELEASED {
return
}
// 更新包装单的填充状态
bl_pakord.RefreshFillStatus()
// 获取包装单的模板
if bl_paktpl, ok = cop.Packtmpldict[bl_pakord.Pkotab.Packtemplateid]; !ok {
err = errors.New(fmt.Sprintf("Packorder %s template %s is not existing in global template dict!", bl_pakord.Pkotab.Packorderid, bl_pakord.Pkotab.Packtemplateid))
return
}
// 基于不同类型的包装下达模式进行处理
if bl_paktpl.Paktmpltab.Unfullfillable > 0 {
if canrel, err = bl_pakord.IsUnfullfillPackorderReleasable(session, cop); err != nil {
return
}
if canrel {
if err = bl_pakord.Release(session, bl_pakord.GetFilledItemQty()); err != nil {
return
}
relordlst = append(relordlst, bl_pakord.PackorderId)
// 下达同步号相同的开口包装
if pkotablst, err = pakordtab.GetOpenPackOrdersBySyncid(session, cop.Projectid, bl_pakord.Pkotab.Syncsn, bl_pakord.PackorderId); err != nil {
return
}
for i = 0; i < len(pkotablst); i++ {
bl_syncpo = BL_PackOrder{PackorderId: pkotablst[i].Packorderid}
bl_syncpo.Pkotab = pkotablst[i]
if canrel, err = bl_syncpo.IsUnfullfillPackorderReleasable(session, cop); err != nil {
return
}
if canrel {
if err = bl_syncpo.Release(session, bl_syncpo.GetFilledItemQty()); err != nil {
return
}
relordlst = append(relordlst, bl_syncpo.PackorderId)
}
}
return
}
} else {
// 检查包装项是否都已填满,如果是,则释放包装订单
if bl_pakord.FillQty >= bl_pakord.Pkotab.Planqty {
// 达到下达条件
fmt.Println("包装单:", bl_pakord.PackorderId, " 计划数量:", bl_pakord.Pkotab.Planqty, " 填充数量:", bl_pakord.FillQty)
if err = bl_pakord.Release(session, bl_pakord.FillQty); err != nil {
return
}
relordlst = append(relordlst, bl_pakord.PackorderId)
}
}
return
}
// 下达包装单
// 1. 必须满包,检查包装项数量是否满足
// 2. 可以不满包,检查已下达的OEMSEQ数是否达标,如果不达标,则检查剩余填充项是否存在维保的WO(基于OEMSEQ+SGID检索)
func (cop *CalloffProject) ReleasePackOrder(session *xorm.Session, bl_pakord BL_PackOrder) (relstat bool, err error) {
var (
i int
pakordtab db.Jit_packorder
wotab db.Pln_workorder
bl_paktpl BL_Package
ok, exist bool
)
relstat = false
// 查询包装单数据
pakordtab = db.Jit_packorder{Finr: db.G_FINR, Packorderid: bl_pakord.PackorderId}
if bl_pakord.Pkotab, err = pakordtab.SelectOneBySession(session); err != nil {
return
}
// 获取包装单完整数据,检查包装单状态是否满足
if bl_pakord.Pkotab.Status >= common.PKO_STATUS_RELEASED {
return
}
// 获取包装单的模板
if bl_paktpl, ok = cop.Packtmpldict[bl_pakord.Pkotab.Packtemplateid]; !ok {
err = errors.New(fmt.Sprintf("Packorder %s template %s is not existing in global template dict!", bl_pakord.Pkotab.Packorderid, bl_pakord.Pkotab.Packtemplateid))
return
}
// 更新包装单模板和包装单的填充状态
bl_paktpl.RefreshFillStatus()
bl_pakord.RefreshFillStatus()
// 基于不同类型的包装下达模式进行处理
if bl_paktpl.Paktmpltab.Unfullfillable > 0 {
if bl_pakord.OemseqCount >= bl_paktpl.OemseqCount {
// 检查剩余未填充的工单是否存在
ok = true
for i = 0; i < len(bl_pakord.Pkotab.Itemlst); i++ {
if bl_pakord.Pkotab.Itemlst[i].Status >= common.PKO_STATUS_RELEASED {
continue
}
if exist, wotab, err = wotab.GetByProjectOemSeqSg(session, bl_pakord.Pkotab.Projnr, common.ValueToInt(bl_pakord.Pkotab.Itemlst[i].Oemseq, 0), bl_pakord.Pkotab.Itemlst[i].Supplygroupid); err != nil {
err = errors.New(fmt.Sprintf("查找项目 %s OEMSEQ %s 供应组 %s 的工单失败!", bl_pakord.Pkotab.Projnr, bl_pakord.Pkotab.Itemlst[i].Oemseq, bl_pakord.Pkotab.Itemlst[i].Supplygroupid))
return
}
if exist && (wotab.Packstatus <= 0) {
ok = false
break
}
}
if ok {
// 达到下达条件
if err = bl_pakord.Release(session, bl_pakord.FillQty); err != nil {
return
}
relstat = true
}
}
} else {
// 检查包装项是否都已填满,如果是,则释放包装订单
if bl_pakord.FillQty >= bl_pakord.Pkotab.Planqty {
// 达到下达条件
if err = bl_pakord.Release(session, bl_pakord.FillQty); err != nil {
return
}
relstat = true
}
}
return
}
// 基于指定供应组寻找匹配的包装单模板
func (cop *CalloffProject) GetPackTemplateListBySupplyGroup(sgid string) (rettpldict map[string]string) {
var (
tpldict map[string]BL_Package
bl_paktpl, bl_paktpl2 BL_Package
i int
matched bool
)
// 初始化
tpldict = make(map[string]BL_Package)
// 基于sgid查询获取包装模板ID
for _, bl_paktpl = range cop.Packtmpldict {
matched = false
for i = 0; i < len(bl_paktpl.Paktmpltab.Itemlst); i++ {
if strings.TrimSpace(sgid) == strings.TrimSpace(bl_paktpl.Paktmpltab.Itemlst[i].Supplygroupid) {
matched = true
break
}
}
if matched {
tpldict[bl_paktpl.Paktmpltab.Packtemplateid] = bl_paktpl
}
}
// 遍历获取的模板ID,获取具有相同同步号的模板
rettpldict = make(map[string]string)
for _, bl_paktpl = range tpldict {
rettpldict[bl_paktpl.Paktmpltab.Packtemplateid] = bl_paktpl.Paktmpltab.Packtemplateid
for _, bl_paktpl2 = range cop.Packtmpldict {
if bl_paktpl.Paktmpltab.Syncnr == bl_paktpl2.Paktmpltab.Syncnr {
rettpldict[bl_paktpl2.Paktmpltab.Packtemplateid] = bl_paktpl2.Paktmpltab.Packtemplateid
}
}
}
return
}
// 获取指定项目,OEMSEQ和supplygroup的开口包装
func (cop *CalloffProject) GetPackOrderByOemseqSupplyGroup(session *xorm.Session, wotab db.Pln_workorder) (exist bool, bl_pakord BL_PackOrder, err error) {
var (
pakord db.Jit_packorder
pakordlst []db.Jit_packorder
)
if pakordlst, err = pakord.GetByOemSeqSupplyGroup(session, cop.Projectid, common.ValueToInt(wotab.Oemseq, 0), wotab.Supplygroupid); err != nil {
err = errors.New(fmt.Sprintf("基于项目 %s Oemseq %d 供应组 %s 查询开口包装单失败!", cop.Projectid, wotab.Oemseq, wotab.Supplygroupid))
return
}
exist = false
if len(pakordlst) > 0 {
bl_pakord = BL_PackOrder{PackorderId: pakordlst[0].Packorderid, Pkotab: pakordlst[0]}
exist = true
return
}
return
}
// 获取指定项目,checksequence和supplygroup的开口包装
func (cop *CalloffProject) GetPackOrderByCheckSequenceSupplyGroup(session *xorm.Session, cs int, sgid string) (exist bool, bl_pakord BL_PackOrder, err error) {
var (
pakord db.Jit_packorder
pakordlst []db.Jit_packorder
)
if pakordlst, err = pakord.GetByCheckSeqSupplyGroup(session, cop.Projectid, cs, sgid); err != nil {
err = errors.New(fmt.Sprintf("基于项目 %s CheckSequence %d 供应组 %s 查询开口包装单失败!", cop.Projectid, cs, sgid))
return
}
exist = false
if len(pakordlst) > 0 {
bl_pakord = BL_PackOrder{PackorderId: pakordlst[0].Packorderid, Pkotab: pakordlst[0]}
exist = true
return
}
return
}
// 获取指定项目,checksequence的开口包装
func (cop *CalloffProject) GetOpenPackOrderByCheckSequence(session *xorm.Session, cs int) (bl_pakordlst []BL_PackOrder, err error) {
var (
i int
pakord db.Jit_packorder
pakordlst []db.Jit_packorder
bl_pakord BL_PackOrder
)
bl_pakordlst = []BL_PackOrder{}
if pakordlst, err = pakord.GetByCheckSeq(session, cop.Projectid, cs); err != nil {
err = errors.New(fmt.Sprintf("基于项目 %s CheckSequence %d 查询开口包装单失败!", cop.Projectid, cs))
return
}
for i = 0; i < len(pakordlst); i++ {
bl_pakord = BL_PackOrder{PackorderId: pakordlst[i].Packorderid, Pkotab: pakordlst[i]}
bl_pakordlst = append(bl_pakordlst, bl_pakord)
}
return
}
func (cop *CalloffProject) CreatePackOrderByCheckSeqWO(session *xorm.Session, cftab db.Pln_calloffdata_landing, wotab db.Pln_workorder) (bl_polst []BL_PackOrder, err error) {
var (
bl_pak BL_Package
bl_pakord BL_PackOrder
paktmpitemtab db.Jit_packtemplate_itemlst
syncid, boxid, paktpl string
sgdict map[string]string
tpldict map[string]string
ok bool
)
// 初始化
bl_polst = []BL_PackOrder{}
tpldict = make(map[string]string)
// 1. 基于供应组ID获取包含它的模板ID列表
tpldict = cop.GetPackTemplateListBySupplyGroup(wotab.Supplygroupid)
if len(tpldict) <= 0 {
err = errors.New(fmt.Sprintf("供应组 %s 没有任何适配的包装模板!", wotab.Supplygroupid))
return
}
// 2. 如果有多个匹配模板,则获取自动同步号
if len(tpldict) > 1 {
if strings.TrimSpace(cop.Projecttab.Shippacksync_snr) != "" {
if syncid, err = SN_GetNextSnrBySession(strings.TrimSpace(cop.Projecttab.Shippacksync_snr), session); err != nil {
return
}
} else {
if syncid, err = SN_GetNextSnrBySession("PACKORDERSYNC", session); err != nil {
return
}
}
} else {
syncid = ""
}
// 3. 获取包装模板
sgdict = make(map[string]string)
for _, paktpl = range tpldict {
if bl_pak, ok = cop.Packtmpldict[paktpl]; !ok {
err = errors.New(fmt.Sprintf("包装模板 %s 不存在!", paktpl))
return
}
for _, paktmpitemtab = range bl_pak.Paktmpltab.Itemlst {
sgdict[paktmpitemtab.Supplygroupid] = paktmpitemtab.Supplygroupid
}
}
// 4. 获取包装箱流水号( 默认取多个模板最后一个模板为参照)
if bl_pak.Paktmpltab.Boxsn != "" {
glog.InfoExtln("流水号","bl_pak.Paktmpltab.Boxsn",bl_pak.Paktmpltab.Boxsn)
if boxid, err = SN_GetNextSnrBySession(bl_pak.Paktmpltab.Boxsn, session); err != nil {
return
}
} else {
boxid = ""
}
// 5. 根据获取的模板列表依次创建包装单,并设置同步号
for _, paktpl = range tpldict {
if bl_pakord, err = cop.CreatePackOrderForCheckSeq(paktpl, syncid, boxid, cftab.Checksequence, wotab, session); err != nil {
return
}
bl_polst = append(bl_polst, bl_pakord)
fmt.Println("--------------------新建包装:", bl_pakord.PackorderId, "---------------")
}
return
}
func (cop *CalloffProject) CreatePackOrderForCheckSeq(paktplid, syncid, boxid string, cs int, wotab db.Pln_workorder, session *xorm.Session) (bl_pako BL_PackOrder, err error) {
var (
pkoitemtab db.Jit_packorder_itemlst
bl_pak BL_Package
i int
ok bool
pkoid string
)
// 获取包装模板
if bl_pak, ok = cop.Packtmpldict[paktplid]; !ok {
err = errors.New(fmt.Sprintf("包装模板 %s 不存在!", paktplid))
return
}
// 获取项目的包装单号
if strings.TrimSpace(cop.Projecttab.Shippack_snr) != "" {
if pkoid, err = SN_GetNextSnrBySession(strings.TrimSpace(cop.Projecttab.Shippack_snr), session); err != nil {
return
}
} else {
if pkoid, err = SN_GetNextSnrBySession("PACKORDER", session); err != nil {
return
}
}
// 创建包装单头
bl_pako = BL_PackOrder{}
bl_pako.Pkotab.Finr = db.G_FINR
bl_pako.Pkotab.Packorderid = pkoid
bl_pako.Pkotab.Packtemplateid = bl_pak.PackTmplId
bl_pako.Pkotab.Projnr = bl_pak.Paktmpltab.Projnr
bl_pako.Pkotab.Packtypeid = bl_pak.Paktmpltab.Packtypeid
bl_pako.Pkotab.Boxsn = boxid
bl_pako.Pkotab.Syncsn = syncid
bl_pako.Pkotab.Orderinfo = bl_pak.Paktmpltab.Syncflag
bl_pako.Pkotab.Planqty = bl_pak.Paktmpltab.Planqty
bl_pako.Pkotab.Actqty = 0
bl_pako.Pkotab.Printerid = bl_pak.Paktmpltab.Printerid
bl_pako.Pkotab.Templatefile = bl_pak.Paktmpltab.Templatefile
bl_pako.Pkotab.Status = common.PKO_STATUS_PLANNED
bl_pako.Pkotab.Loadstatus = common.PKO_STATUS_UNLOADED
bl_pako.Pkotab.Credatuz = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
bl_pako.Pkotab.Lastuser = "service"
bl_pako.Pkotab.Itemlst = []db.Jit_packorder_itemlst{}
for i = 0; i < len(bl_pak.Paktmpltab.Itemlst); i++ {
pkoitemtab = db.Jit_packorder_itemlst{}
pkoitemtab.Finr = db.G_FINR
pkoitemtab.Packorderid = pkoid
pkoitemtab.Supplygroupid = bl_pak.Paktmpltab.Itemlst[i].Supplygroupid
pkoitemtab.Pos = bl_pak.Paktmpltab.Itemlst[i].Pos
pkoitemtab.Poscode = bl_pak.Paktmpltab.Itemlst[i].Poscode
// 相同零件族的置位CheckSequence
if cop.IsSamePartFamily(wotab.Supplygroupid, bl_pak.Paktmpltab.Itemlst[i].Supplygroupid) {
pkoitemtab.Seq = cs + bl_pak.Paktmpltab.Itemlst[i].Seq - 1
}
if bl_pak.Paktmpltab.Itemlst[i].Seq == 1 {
pkoitemtab.Oemseq = wotab.Oemseq
}
pkoitemtab.Planqty = bl_pak.Paktmpltab.Itemlst[i].Planqty
pkoitemtab.Actqty = 0
pkoitemtab.Status = common.PKO_STATUS_PLANNED
pkoitemtab.Credatuz = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
pkoitemtab.Lastuser = "service"
bl_pako.Pkotab.Itemlst = append(bl_pako.Pkotab.Itemlst, pkoitemtab)
}
if err = bl_pako.Pkotab.Insert(session); err != nil {
return
}
bl_pako.PlanQty = bl_pak.Paktmpltab.Planqty
bl_pako.PackorderId = pkoid
return
}
// 将生产订单加入包装单
func (cop *CalloffProject) AddWOToPackOrder(wotab db.Pln_workorder, cs int, bl_pakord *BL_PackOrder, session *xorm.Session) (success bool, err error) {
var (
pakordtab db.Jit_packorder
bl_paktpl BL_Package
i, pos int
ok bool
)
// 获取包装单完整数据
pakordtab = db.Jit_packorder{Finr: db.G_FINR, Packorderid: bl_pakord.PackorderId}
if bl_pakord.Pkotab, err = pakordtab.SelectOneBySession(session); err != nil {
return
}
glog.InfoExtln("CALLOFF-Debug", "获取包装单完整数据:", bl_pakord.Pkotab)
// 检查包装单状态是否满足
success = false
if bl_pakord.Pkotab.Status >= common.PKO_STATUS_RELEASED {
return
}
// 获取包装单模板
if bl_paktpl, ok = cop.Packtmpldict[bl_pakord.Pkotab.Packtemplateid]; !ok {
err = errors.New(fmt.Sprintf("Packorder %s template %s is not existing in global template dict!", bl_pakord.Pkotab.Packorderid, bl_pakord.Pkotab.Packtemplateid))
return
}
// 遍历包装单项,匹配WO并更新
pos = -1
for i = 0; i < len(bl_pakord.Pkotab.Itemlst); i++ {
// 找到WO对应的包装项更新对应的状态和OEMSEQ信息
if (bl_pakord.Pkotab.Itemlst[i].Supplygroupid == wotab.Supplygroupid) && (bl_pakord.Pkotab.Itemlst[i].Seq == cs || common.ValueToInt(bl_pakord.Pkotab.Itemlst[i].Oemseq, 0) == common.ValueToInt(wotab.Oemseq, 0)) {
// 更新包装子项的计划包装信息
bl_pakord.Pkotab.Itemlst[i].Status = common.PKO_STATUS_RELEASED
bl_pakord.Pkotab.Itemlst[i].Workordernr = wotab.Workordernr
bl_pakord.Pkotab.Itemlst[i].Oemseq = wotab.Oemseq
bl_pakord.Pkotab.Itemlst[i].Seq = cs
bl_pakord.Pkotab.Itemlst[i].Lastmodif = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
if !bl_pakord.Pkotab.Itemlst[i].UpdateBySession(session) {
err = errors.New("Failed to update jit_packorder_itemlst!")
return
}
// 更新生产订单的包装状态
wotab.Packstatus = 1
wotab.Lastmodif = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
if err = wotab.UpdateFields(session, "packstatus, lastmodif"); err != nil {
err = errors.New("Failed to update pln_workorder!")
return
}
pos = i
success = true
break
}
}
// 遍历包装单,根据pos插入的WO更新其它包装项
if pos >= 0 {
for i = 0; i < len(bl_pakord.Pkotab.Itemlst); i++ {
if i == pos || bl_pakord.Pkotab.Itemlst[i].Status >= common.PKO_STATUS_RELEASED {
continue
}
// 根据WO的OEMSEQ和CheckSeq更新其它包装项
if cop.IsSamePartFamily(wotab.Supplygroupid, bl_pakord.Pkotab.Itemlst[i].Supplygroupid) {
// 更新同PF的CHEECKSEQ
if bl_paktpl.Paktmpltab.Itemlst[i].Seq >= bl_paktpl.Paktmpltab.Itemlst[pos].Seq {
if bl_pakord.Pkotab.Itemlst[i].Seq != (cs + bl_paktpl.Paktmpltab.Itemlst[i].Seq - bl_paktpl.Paktmpltab.Itemlst[pos].Seq) {
bl_pakord.Pkotab.Itemlst[i].Seq = cs
bl_pakord.Pkotab.Itemlst[i].Lastmodif = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
if !bl_pakord.Pkotab.Itemlst[i].UpdateBySession(session) {
err = errors.New("Failed to update jit_packorder_itemlst!")
return
}
}
}
}
// 如果模板中的SEQ一致,尝试更新OEMSEQ
if bl_paktpl.Paktmpltab.Itemlst[i].Seq == bl_paktpl.Paktmpltab.Itemlst[pos].Seq {
if common.ValueToInt(bl_pakord.Pkotab.Itemlst[i].Oemseq, 0) != common.ValueToInt(wotab.Oemseq, 0) {
bl_pakord.Pkotab.Itemlst[i].Oemseq = wotab.Oemseq
bl_pakord.Pkotab.Itemlst[i].Lastmodif = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
if !bl_pakord.Pkotab.Itemlst[i].UpdateBySession(session) {
err = errors.New("Failed to update jit_packorder_itemlst!")
return
}
}
}
}
glog.InfoExtln("CALLOFF-Debug", "插入工单后,包装的状态:", bl_pakord.Pkotab)
} else {
glog.InfoExtln("CALLOFF-Debug", "无法在包装单:", bl_pakord.Pkotab, "给工单找到包装位:", wotab)
glog.InfoExtln("工单选包装", "无法在包装单:", bl_pakord.Pkotab, "给工单找到包装位:", wotab)
}
return
}
// 校验给定的包装单是否适配开口的发运车订单,适配返回
func (cop *CalloffProject) CheckOpenCarOrdersForPackOrder(bl_scolst []BL_ShipcarOrder, pkotab db.Jit_packorder) (fillable bool, idx int) {
var i int
fillable = false
idx = 0
// 按照状态做不同的处理,10未计划需要适配模板,20已计划无需适配模板,直接匹配数量
for i = 0; i < len(bl_scolst); i++ {
// 更新发运车订单各包装项的最大可装载量
if bl_scolst[i].Spordtab.Status < common.SPO_STATUS_PLANNED {
cop.RecalShipItemWorkloadMaxQty(&bl_scolst[i])
}
// 判断是否可装载包装单
if bl_scolst[i].CanFillPackOrder(pkotab) {
fillable = true
idx = i
break
}
}
return
}
// 刷新发运车订单各包装项的最大可装载量
func (cop *CalloffProject) RecalShipItemWorkloadMaxQty(bl_scord *BL_ShipcarOrder) {
var (
bl_sc BL_Shipcar
bl_scwl BL_ShipcarWorkload
scitemtab db.Jit_shiptemplate_itemlst
ok, match bool
)
for _, bl_sc = range cop.Cartmpldict {
match = true
// 与当前发运车的包装类型上限数进行匹配,确定是否适配
for _, bl_scwl = range bl_scord.Workloaddict {
if scitemtab, ok = bl_sc.Paktypdict[bl_scwl.Packtypeid]; !ok {
match = false
break
}
// 如果发运单项的已填充数量 > 模板在该填充项的计划数量,也不匹配
if bl_scwl.Fillqty > scitemtab.Planqty {
match = false
break
}
}
if !match {
continue
}
// 适配,更新最大装载数
for _, bl_scwl = range bl_scord.Workloaddict {
if bl_scwl.Maxqty < bl_sc.Paktypdict[bl_scwl.Packtypeid].Planqty {
bl_scwl.Maxqty = bl_sc.Paktypdict[bl_scwl.Packtypeid].Planqty
bl_scord.Workloaddict[bl_scwl.Packtypeid] = bl_scwl
}
}
}
return
}
// 基于发运车订单当前实际workload动态计算每个包装类型可装载的最大量并判定是否可以唯一指定模板
func (cop *CalloffProject) IsShipcarOrderFixTemplate(bl_scord *BL_ShipcarOrder) (canfix bool, shiptplid string, err error) {
var (
bl_sc BL_Shipcar
bl_scwl BL_ShipcarWorkload
soitemtab db.Jit_shiporder_itemlst
scitemtab db.Jit_shiptemplate_itemlst
ok, match bool
machcardict map[string]BL_Shipcar // 匹配的发运车模板
)
// 更新发运订单各包装项的负载
for _, soitemtab = range bl_scord.Spordtab.Itemlst {
if bl_scwl, ok = bl_scord.Workloaddict[soitemtab.Packtypeid]; !ok {
err = errors.New(fmt.Sprintf("Ship order item's packtype %s is not existing in ship order %s workload dict!",
soitemtab.Packtypeid, bl_scord.Shiporderid))
return
}
bl_scwl.Fillqty = len(soitemtab.Itemlst)
bl_scord.Workloaddict[bl_scwl.Packtypeid] = bl_scwl
}
machcardict = make(map[string]BL_Shipcar)
canfix = false
for _, bl_sc = range cop.Cartmpldict {
match = true
// 与当前发运车的包装类型上限数进行匹配,确定是否适配
for _, bl_scwl = range bl_scord.Workloaddict {
if scitemtab, ok = bl_sc.Paktypdict[bl_scwl.Packtypeid]; !ok {
match = false
break
}
if bl_scwl.Fillqty > scitemtab.Planqty {
match = false
break
}
}
if !match {
continue
}
machcardict[bl_sc.ShipTmplId] = bl_sc
// 适配,更新最大装载数
for _, bl_scwl = range bl_scord.Workloaddict {
if bl_scwl.Maxqty < bl_sc.Paktypdict[bl_scwl.Packtypeid].Planqty {
bl_scwl.Maxqty = bl_sc.Paktypdict[bl_scwl.Packtypeid].Planqty
}
}
bl_scord.Workloaddict[bl_scwl.Packtypeid] = bl_scwl
}
if len(machcardict) <= 0 {
// 没有适配,报错
err = errors.New(fmt.Sprintf("Failed to match ship car template!"))
return
}
// 适配一个发运车模板,确认可以关闭发运车并返回发运车模板ID
if len(machcardict) == 1 {
canfix = true
for _, bl_sc = range machcardict {
shiptplid = bl_sc.ShipTmplId
}
return
}
return
}
// 基于发运车订单当前实际workload动态计算每个包装类型可装载的最大量并判定已填充量是否已达到
func (cop *CalloffProject) IsShipcarOrderReleasable(bl_scord *BL_ShipcarOrder) (canclose bool, err error) {
var (
soitemtab db.Jit_shiporder_itemlst
)
// 判断是否已锁定模板,status = 20
if bl_scord.Spordtab.Status < 20 {
canclose = false
return
}
// 比较各包装项实际已填充数和计划数
canclose = true
for _, soitemtab = range bl_scord.Spordtab.Itemlst {
if soitemtab.Shortship > 0 {
if len(soitemtab.Itemlst) < soitemtab.Shortshipqty {
canclose = false
break
}
} else {
if len(soitemtab.Itemlst) < soitemtab.Planqty {
canclose = false
break
}
}
}
return
}
// 找到适配包装单的开口发运车
func (cop *CalloffProject) GetOpenShipCarOrder() (bl_scolst []BL_ShipcarOrder, err error) {
var (
spotab db.Jit_shiporder
spotablst []db.Jit_shiporder
bl_sco BL_ShipcarOrder
bl_scwl BL_ShipcarWorkload
i, j int
)
// 获取项目的开口发运车列表
spotab = db.Jit_shiporder{}
if spotablst, err = spotab.GetOpenShipOrders(cop.Projectid); err != nil {
return
}
bl_scolst = []BL_ShipcarOrder{}
for i = 0; i < len(spotablst); i++ {
bl_sco = BL_ShipcarOrder{}
bl_sco.Shiporderid = spotablst[i].Shiporderid
bl_sco.Workloaddict = make(map[string]BL_ShipcarWorkload)
bl_sco.Spordtab = spotablst[i]
// 初始化发运车订单各子项的负荷
for j = 0; j < len(spotablst[i].Itemlst); j++ {
bl_scwl = BL_ShipcarWorkload{}
bl_scwl.Packtypeid = spotablst[i].Itemlst[j].Packtypeid
bl_scwl.Fillqty = len(spotablst[i].Itemlst[j].Itemlst)
bl_sco.Workloaddict[bl_scwl.Packtypeid] = bl_scwl
}
bl_scolst = append(bl_scolst, bl_sco)
}
return
}
// 新建发运车订单
func (cop *CalloffProject) CreateShipCarOrder(session *xorm.Session) (bl_sco BL_ShipcarOrder, err error) {
var (
spotab db.Jit_shiporder
spoitemtab db.Jit_shiporder_itemlst
spoid string
bl_scar BL_Shipcar
bl_scwl BL_ShipcarWorkload
i int
)
// 判断项目是否有模板可用
if len(cop.Cartmpldict) <= 0 {
err = errors.New("Project doesn't have any ship template for shiporder creation!")
return
}
// 获取默认创建模板,如果不存在则取字典最后一个
for _, bl_scar = range cop.Cartmpldict {
if bl_scar.Shipcartab.Defaultcreate == 1 {
break
}
}
// 初始化
bl_sco = BL_ShipcarOrder{}
bl_sco.Workloaddict = make(map[string]BL_ShipcarWorkload)
// 基于设置获取发运车订单号
if cop.Projecttab.Shipcar_snr != "" {
if spoid, err = SN_GetNextSnrBySession(cop.Projecttab.Shipcar_snr, session); err != nil {
return
}
} else {
if spoid, err = SN_GetNextSnrBySession("SHIPCAR", session); err != nil {
return
}
}
// 创建发运车订单头信息
spotab = db.Jit_shiporder{}
spotab.Finr = db.G_FINR
spotab.Shiporderid = spoid
spotab.Projnr = cop.Projectid
spotab.Planqty = 0
spotab.Shiptemplateid = ""
spotab.Printerid = ""
spotab.Shiptype = ""
spotab.Actqty = 0
spotab.Status = common.SPO_STATUS_UNPLANNED
spotab.Opentime = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
spotab.Lastuser = "service"
spotab.Credatuz = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
if err = spotab.Insert(session); err != nil {
return
}
spotab.Itemlst = []db.Jit_shiporder_itemlst{}
// 基于项目的默认创建发运模板创建子项
for i = 0; i < len(bl_scar.Shipcartab.Itemlst); i++ {
spoitemtab = db.Jit_shiporder_itemlst{}
spoitemtab.Finr = db.G_FINR
spoitemtab.Shiporderid = spoid
spoitemtab.Packtypeid = bl_scar.Shipcartab.Itemlst[i].Packtypeid
spoitemtab.Pos = bl_scar.Shipcartab.Itemlst[i].Pos
spoitemtab.Planqty = 0
spoitemtab.Actqty = 0
spoitemtab.Fillqty = 0
spoitemtab.Status = common.SPO_STATUS_UNPLANNED
spoitemtab.Lastuser = "service"
spoitemtab.Credatuz = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
if err = spoitemtab.Insert(session); err != nil {
return
}
spotab.Itemlst = append(spotab.Itemlst, spoitemtab)
// 初始化各包装项的负载
bl_scwl = BL_ShipcarWorkload{}
bl_scwl.Packtypeid = spoitemtab.Packtypeid
bl_scwl.Planqty = spoitemtab.Planqty
bl_scwl.Fillqty = spoitemtab.Fillqty
bl_sco.Workloaddict[bl_scwl.Packtypeid] = bl_scwl
}
bl_sco.Spordtab = spotab
bl_sco.Shiporderid = spoid
return
}
// 初始化发运车的负载字典
func (cop *CalloffProject) InitShipOrderWorkoload(bl_sco *BL_ShipcarOrder) {
var (
i int
bl_scar BL_Shipcar
bl_scwl BL_ShipcarWorkload
)
// 获取默认创建模板,如果不存在则取字典最后一个
for _, bl_scar = range cop.Cartmpldict {
if bl_scar.Shipcartab.Defaultcreate == 1 {
break
}
}
bl_sco.Workloaddict = make(map[string]BL_ShipcarWorkload)
for i = 0; i < len(bl_scar.Shipcartab.Itemlst); i++ {
// 初始化各包装项的负载
bl_scwl = BL_ShipcarWorkload{}
bl_scwl.Packtypeid = bl_scar.Shipcartab.Itemlst[i].Packtypeid
bl_scwl.Planqty = bl_scar.Shipcartab.Itemlst[i].Planqty
bl_scwl.Fillqty = 0
bl_sco.Workloaddict[bl_scwl.Packtypeid] = bl_scwl
}
}
// 固化发运车订单的模板,状态置位20已计划
func (cop *CalloffProject) FixShipCarOrderTemplate(session *xorm.Session, bl_sco *BL_ShipcarOrder, shiptplid string) (err error) {
var (
bl_sctpl BL_Shipcar
sptplitemtab db.Jit_shiptemplate_itemlst
ok bool
i int
)
bl_sctpl = BL_Shipcar{}
if bl_sctpl, ok = cop.Cartmpldict[shiptplid]; !ok {
err = errors.New(fmt.Sprintf("Failled to get shipcar template %s from global dict!", shiptplid))
return
}
// 更新各子项
for i = 0; i < len(bl_sco.Spordtab.Itemlst); i++ {
if sptplitemtab, ok = bl_sctpl.Paktypdict[bl_sco.Spordtab.Itemlst[i].Packtypeid]; !ok {
err = errors.New(fmt.Sprintf("Shipcar order %s packtype %s is not existing in global dict!",
bl_sco.Spordtab.Shiporderid, bl_sco.Spordtab.Itemlst[i].Packtypeid))
return
}
bl_sco.Spordtab.Itemlst[i].Planqty = sptplitemtab.Planqty
bl_sco.Spordtab.Itemlst[i].Fillqty = len(bl_sco.Spordtab.Itemlst[i].Itemlst)
if bl_sco.Spordtab.Itemlst[i].Fillqty >= bl_sco.Spordtab.Itemlst[i].Planqty {
bl_sco.Spordtab.Itemlst[i].Status = common.SPO_STATUS_RELEASED
} else {
bl_sco.Spordtab.Itemlst[i].Status = common.SPO_STATUS_PLANNED
}
bl_sco.Spordtab.Itemlst[i].Lastmodif = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
if err = bl_sco.Spordtab.Itemlst[i].UpdateFields(session, "planqty, fillqty, status, lastmodif"); err != nil {
return
}
}
// 更新订单头
bl_sco.Spordtab.Shiptemplateid = shiptplid
bl_sco.Spordtab.Printerid = bl_sctpl.Shipcartab.Printerid
bl_sco.Spordtab.Planqty = bl_sctpl.Shipcartab.Planqty
bl_sco.Spordtab.Status = common.SPO_STATUS_PLANNED
bl_sco.Spordtab.Lastmodif = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
if err = bl_sco.Spordtab.UpdateFields(session, "shiptemplateid, printerid, planqty, status, lastmodif"); err != nil {
return
}
return
}
// 固化发运车订单的模板,状态置位20已计划
func (cop *CalloffProject) ReleaseShipCarOrder(session *xorm.Session, bl_sco *BL_ShipcarOrder) (err error) {
var (
i int
bl_ordmsg BL_Ordmsg
)
// 更新各子项
for i = 0; i < len(bl_sco.Spordtab.Itemlst); i++ {
if bl_sco.Spordtab.Itemlst[i].Status >= common.SPO_STATUS_RELEASED {
continue
}
bl_sco.Spordtab.Itemlst[i].Status = common.SPO_STATUS_RELEASED
bl_sco.Spordtab.Itemlst[i].Lastmodif = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
if err = bl_sco.Spordtab.Itemlst[i].UpdateFields(session, "status, lastmodif"); err != nil {
return
}
}
// 更新订单头
bl_sco.Spordtab.Status = common.SPO_STATUS_RELEASED
bl_sco.Spordtab.Lastmodif = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
if err = bl_sco.Spordtab.UpdateFields(session, "status, lastmodif"); err != nil {
return
}
// 创建发运单消息
bl_ordmsg = BL_Ordmsg{MsgType: common.MSG_TYPE_SHIP, MsgObjid: bl_sco.Spordtab.Shiporderid, MsgcPara1: cop.Projectid}
if err = bl_ordmsg.Create(session); err != nil {
return
}
return
}