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 }