|
package calloff
|
|
|
|
import (
|
|
"encoding/json"
|
|
"encoding/xml"
|
|
"fmt"
|
|
"github.com/go-xorm/xorm"
|
|
"io"
|
|
"io/ioutil"
|
|
"leit.com/leit_seat_aps/common"
|
|
"leit.com/leit_seat_aps/db"
|
|
"leit.com/leit_seat_aps/etcd"
|
|
"leit.com/leit_seat_aps/glog"
|
|
"leit.com/leit_seat_aps/service"
|
|
"os"
|
|
"regexp"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
// Calloff文件解析和保存
|
|
func ParseCalloffNew() {
|
|
for {
|
|
var (
|
|
err error
|
|
projtab db.Me_project
|
|
projtablst []db.Me_project
|
|
cfland CalloffLandData
|
|
cfProj service.CalloffProject
|
|
rd []os.FileInfo
|
|
fi os.FileInfo
|
|
edi_file string
|
|
mail db.Sendmailtab
|
|
matched bool
|
|
)
|
|
|
|
projtab = db.Me_project{}
|
|
if projtablst, err = projtab.GetAllActive(); err != nil {
|
|
glog.InfoExtln("Calloff解析", "Failed to get project list!")
|
|
return
|
|
}
|
|
|
|
for i, _ := range projtablst {
|
|
cfProj = service.CalloffProject{}
|
|
cfProj.Projecttab = projtablst[i]
|
|
cfProj.Projectid = projtablst[i].Projectid
|
|
fmt.Println("Ready to load data for project:", projtablst[i].Projectid)
|
|
// 读取文件夹内的文件并解析
|
|
if rd, err = ioutil.ReadDir(cfProj.Projecttab.Calloff_folder + "/inbox"); err != nil {
|
|
return
|
|
}
|
|
rds := common.SortByTime(rd)
|
|
for _, fi = range rds {
|
|
if fi.IsDir() {
|
|
continue
|
|
}
|
|
|
|
edi_file = cfProj.Projecttab.Calloff_folder + "/inbox" + "/" + fi.Name()
|
|
|
|
// 判断文件的合规性
|
|
if matched, err = regexp.MatchString(cfProj.Projecttab.Calloff_filename_regexp, fi.Name()); err != nil {
|
|
glog.InfoExtln("Calloff解析", "Failed to match EDI file name: due to: ", fi.Name(), err)
|
|
os.Rename(edi_file, cfProj.Projecttab.Calloff_folder+"/errbox"+"/"+fi.Name())
|
|
continue
|
|
}
|
|
if !matched {
|
|
glog.InfoExtln("Calloff解析", "The specified EDI file: doesn't match the required name specification!", fi.Name())
|
|
os.Rename(edi_file, cfProj.Projecttab.Calloff_folder+"/errbox"+"/"+fi.Name())
|
|
continue
|
|
}
|
|
|
|
// 解析CALLOFF文件到字典
|
|
fmt.Println("Ready to read tod data......")
|
|
cfland = CalloffLandData{}
|
|
cfland.Projnr = projtablst[i].Projectid
|
|
cfland.Edifile = edi_file
|
|
if err = cfland.ReadCalloffData(edi_file); err != nil {
|
|
glog.InfoExtln("Calloff解析", "Failed to parse Calloff file due to: ", err)
|
|
os.Rename(edi_file, cfProj.Projecttab.Calloff_folder+"/errbox"+"/"+fi.Name())
|
|
return
|
|
}
|
|
|
|
// 保存CALLOFF字典到临时缓存表
|
|
if err = cfland.SaveCalloffData(); err != nil {
|
|
glog.InfoExtln("Calloff解析", "Failed to save Calloff parse result due to: ", err)
|
|
//发邮件
|
|
host := projtablst[i].Emailserver_host + ":" + common.ValueToString(projtablst[i].Emailserver_port, "")
|
|
body := "项目号: " + projtablst[i].Projectid + "\r\nEdifile :" + fi.Name() + "\r\nErrorinfo :" + err.Error()
|
|
mail.Status = "waiting"
|
|
mail.Body = body
|
|
mail.Subject = "calloff解析错误"
|
|
mail.Name = projtablst[i].From_email
|
|
mail.Tomail = projtablst[i].Calloff_error_to_recievers
|
|
mail.Host = host
|
|
mail.Password = projtablst[i].From_pwd
|
|
mail.Username = projtablst[i].From_email
|
|
err = mail.Add()
|
|
os.Rename(edi_file, cfProj.Projecttab.Calloff_folder+"/errbox"+"/"+fi.Name())
|
|
continue
|
|
}
|
|
|
|
// 将文件移到outbox
|
|
os.Rename(edi_file, cfProj.Projecttab.Calloff_folder+"/outbox"+"/"+fi.Name())
|
|
}
|
|
}
|
|
time.Sleep(10 * time.Second)
|
|
}
|
|
}
|
|
|
|
// 读取Calloff信息并生成发运包装
|
|
func ParseCalloffOrder() {
|
|
for {
|
|
var (
|
|
err error
|
|
i, j, k, prevCS, m, n int
|
|
projtab db.Me_project
|
|
projtablst []db.Me_project
|
|
cfProj service.CalloffProject
|
|
cflandtab db.Pln_calloffdata_landing
|
|
cflandtablst []db.Pln_calloffdata_landing
|
|
cflandtablst2 []db.Pln_calloffdata_landing
|
|
cftab db.Pln_calloffdata_landing
|
|
cftablst []db.Pln_calloffdata_landing
|
|
edictrltab db.Edi_control
|
|
bl_co service.BL_CustOrder
|
|
bl_prevco service.BL_CustOrder
|
|
wotab db.Pln_workorder
|
|
exist, ok, audit, relstat, stop bool
|
|
prevOemord string
|
|
sgdict map[string]string
|
|
bl_pakordlst []service.BL_PackOrder
|
|
bl_pakord service.BL_PackOrder
|
|
cferror db.Pln_calloff_errorlst
|
|
errorlst []db.Pln_calloff_errorlst
|
|
mail db.Sendmailtab
|
|
session *xorm.Session
|
|
)
|
|
|
|
projtab = db.Me_project{}
|
|
if projtablst, err = projtab.GetAllActive(); err != nil {
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "Failed to get project list!")
|
|
return
|
|
}
|
|
|
|
for i, _ = range projtablst {
|
|
cfProj = service.CalloffProject{}
|
|
cfProj.Projecttab = projtablst[i]
|
|
cfProj.Projectid = projtablst[i].Projectid
|
|
glog.InfoExtln("CALLOFF-Debug", "----------------循环读取Calloff项目", projtablst[i].Projectid, "----------------")
|
|
|
|
// 判断calloff是否已暂停
|
|
edictrltab = db.Edi_control{Projectid: projtablst[i].Projectid, Ediid: "CALLOFF"}
|
|
if edictrltab, err = edictrltab.SelectOne(); edictrltab.Enabled <= 0 {
|
|
continue
|
|
}
|
|
|
|
// 加载项目主数据
|
|
fmt.Println("Ready to load data for project:", projtablst[i].Projectid)
|
|
if err = cfProj.LoadMasterData(); err != nil {
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "Failed to load project master data due to: !", err)
|
|
return
|
|
}
|
|
// 循环读取未处理的Calloff消息,按零件族和CheckSequence排序
|
|
cflandtab = db.Pln_calloffdata_landing{Projnr: cfProj.Projectid}
|
|
if cflandtablst, err = cflandtab.GetUnparsedLandingData(); err != nil {
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "Failed to get unparsed calloff landding data due to:", err)
|
|
return
|
|
}
|
|
|
|
// 遍历未处理的Calloff消息
|
|
for j = 0; j < len(cflandtablst); j++ {
|
|
// 判断calloff是否已暂停
|
|
edictrltab = db.Edi_control{Projectid: projtablst[i].Projectid, Ediid: "CALLOFF"}
|
|
if edictrltab, err = edictrltab.SelectOne(); edictrltab.Enabled <= 0 {
|
|
break
|
|
}
|
|
|
|
errorlst = []db.Pln_calloff_errorlst{}
|
|
glog.InfoExtln("CALLOFF-Debug", j, "-- calloff 解析请求", cflandtablst[j])
|
|
// 读取项目各零件族解析的最大CheckSequence号
|
|
if err = cfProj.LoadPartFamilyMaxParsedCheckSequence(); err != nil {
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "Failed to load project parsed max check sequence data for each partfamily due to: ", err)
|
|
return
|
|
}
|
|
|
|
// 验证Calloff有效性
|
|
// 1. 基于零件族判断CheckSequence是否连续
|
|
if projtablst[i].Calloff_verify_checksequence > 0 {
|
|
if prevCS, ok = cfProj.Pfcsdict[cflandtablst[j].Partfamilyid]; !ok {
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "CheckSequence不连续:", prevCS, "==>", cflandtablst[j].Checksequence)
|
|
return
|
|
}
|
|
// 检查checksequence是否连续,如果不连续查询两者之间是否有报错的解析记录,如果没有报错,如果有继续不处理
|
|
if prevCS > 0 && prevCS+1 != cflandtablst[j].Checksequence {
|
|
if exist, err = cflandtablst[j].AnyErrorRecordBetweenCheckSequence(cfProj.Projectid, cflandtablst[j].Partfamilyid, prevCS, cflandtablst[j].Checksequence); err != nil {
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "查询零件族:", cflandtablst[j].Partfamilyid, "checksequence区间失败:", prevCS, cflandtablst[j].Checksequence)
|
|
return
|
|
}
|
|
if exist {
|
|
continue
|
|
} else {
|
|
cferror = db.Pln_calloff_errorlst{}
|
|
cferror.Finr = db.G_FINR
|
|
cferror.Calloffnr = cflandtablst[j].Calloffnr
|
|
cferror.Errortype = common.CALLOFF_CHECK_SEQUENCE
|
|
cferror.Consumeplant = cflandtablst[j].Consumeplant
|
|
cferror.Partfamilyid = cflandtablst[j].Partfamilyid
|
|
cferror.Oemordernr = cflandtablst[j].Oemordernr
|
|
cferror.Errorstatus = "O"
|
|
cferror.Errorinfo = "CheckSequence不连续:" + common.ValueToString(prevCS, "") + ";" + common.ValueToString(cflandtablst[j].Checksequence, "")
|
|
cferror.Lastmodif = common.TimeFormat(time.Now(), "yyyyMMddHHmmss")
|
|
cferror.Credatuz = common.TimeFormat(time.Now(), "yyyyMMddHHmmss")
|
|
errorlst = append(errorlst, cferror)
|
|
// CheckSequence 不连续,报错
|
|
fmt.Println("CheckSequence不连续:", prevCS, "==>", cflandtablst[j].Checksequence)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 2. 判断客户订单是否存在
|
|
/* 获取锁 */
|
|
LOOP:
|
|
err = etcd.G_jobLock.TryLock("lock")
|
|
if err != nil {
|
|
fmt.Println("calloff groutine lock fail!")
|
|
time.Sleep(5 * time.Millisecond)
|
|
goto LOOP
|
|
}
|
|
fmt.Println("calloff groutine lock success!")
|
|
bl_co = service.BL_CustOrder{Projnr: cflandtablst[j].Projnr, Oemordernr: cflandtablst[j].Oemordernr, Partfamilyid: cflandtablst[j].Partfamilyid}
|
|
if exist, err = bl_co.GetCalloffOemorder(); err != nil {
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "Failed to get custorder for oemorder due to: ", cflandtablst[j].Oemordernr, err)
|
|
etcd.G_jobLock.UnLock()
|
|
return
|
|
}
|
|
if !exist {
|
|
cferror = db.Pln_calloff_errorlst{}
|
|
cferror.Finr = db.G_FINR
|
|
cferror.Calloffnr = cflandtablst[j].Calloffnr
|
|
cferror.Errortype = common.CALLOFF_ORDER_NOTEXIST
|
|
cferror.Consumeplant = cflandtablst[j].Consumeplant
|
|
cferror.Partfamilyid = cflandtablst[j].Partfamilyid
|
|
cferror.Oemordernr = cflandtablst[j].Oemordernr
|
|
cferror.Errorstatus = "O"
|
|
cferror.Errorinfo = "Calloff的客户订单不存在:Partfamilyid:" + cflandtablst[j].Partfamilyid + ";Oemordernr:" + cflandtablst[j].Oemordernr
|
|
cferror.Lastmodif = common.TimeFormat(time.Now(), "yyyyMMddHHmmss")
|
|
cferror.Credatuz = common.TimeFormat(time.Now(), "yyyyMMddHHmmss")
|
|
errorlst = append(errorlst, cferror)
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "Calloff的客户订单不存在 :", cflandtablst[j].Oemordernr, cflandtablst[j].Partfamilyid)
|
|
}
|
|
|
|
glog.InfoExtln("CALLOFF-Debug", "获取客户订单:", bl_co.Custordertab.Custordernr, "生产工单数:", len(bl_co.Custordertab.Wotablst))
|
|
// 如果没有生产工单,则不再处理
|
|
if len(bl_co.Custordertab.Wotablst) <= 0 {
|
|
fmt.Println("获取客户订单:", bl_co.Custordertab.Custordernr, "生产工单数:", len(bl_co.Custordertab.Wotablst))
|
|
etcd.G_jobLock.UnLock()
|
|
continue
|
|
}
|
|
|
|
prevCS, _ = cfProj.Pfcsdict[cflandtablst[j].Partfamilyid]
|
|
prevOemord = ""
|
|
if prevCS > 0 {
|
|
cflandtab = db.Pln_calloffdata_landing{Projnr: cfProj.Projectid, Checksequence: prevCS, Partfamilyid: cflandtablst[j].Partfamilyid}
|
|
if cflandtablst2, err = cflandtab.GetByProjectCheckSequencePartfamily(); len(cflandtablst2) > 0 {
|
|
prevOemord = cflandtablst2[0].Oemordernr
|
|
// 获取前序客户订单对应的calloff记录
|
|
cftab = db.Pln_calloffdata_landing{Projnr: cfProj.Projectid, Oemordernr: prevOemord}
|
|
// 获取前序calloff的所有记录
|
|
if cftablst, err = cftab.GetByProjectOemorder(); err != nil {
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "查询项目客户订单的calloff记录失败:", cftab.Projnr, cftab.Oemordernr, err)
|
|
etcd.G_jobLock.UnLock()
|
|
return
|
|
}
|
|
// 获取前序客户订单
|
|
bl_prevco = service.BL_CustOrder{Projnr: cfProj.Projectid, Oemordernr: cflandtablst2[0].Oemordernr, Partfamilyid: cflandtablst2[0].Partfamilyid}
|
|
if exist, err = bl_prevco.GetCalloffOemorder(); err != nil {
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "获取前序客户订单失败:", cflandtablst2[0].Oemordernr, err)
|
|
etcd.G_jobLock.UnLock()
|
|
return
|
|
}
|
|
// 校验客户订单的零件族是否齐全
|
|
sgdict = make(map[string]string)
|
|
if sgdict, err = bl_prevco.GetOemorderModelSpecPfdict(); err != nil {
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "查询项目客户订单的车型规格字典记录失败:", bl_co.Custordertab.Projnr, bl_co.Custordertab.Custordernr, err)
|
|
etcd.G_jobLock.UnLock()
|
|
return
|
|
}
|
|
if len(sgdict) != len(cftablst) {
|
|
// 整车副缺零件族
|
|
glog.InfoExtln("CALLOFF-Debug", "整车副缺零件族len(cftablst):", len(cftablst), "整车副缺零件族len(sgdict):", len(sgdict))
|
|
etcd.G_jobLock.UnLock()
|
|
continue
|
|
}
|
|
// 校验是否解析有错误
|
|
if len(cftablst) > 0 {
|
|
// 校验前车付的calloff是否有错
|
|
stop = false
|
|
for k = 0; k < len(cftablst); k++ {
|
|
//fmt.Println(k,"-->",cftablst[k])
|
|
if cftablst[k].Parsed == 0 || cftablst[k].Handlestatus != common.CO_PARSE_STATUS_OK {
|
|
stop = true
|
|
break
|
|
}
|
|
}
|
|
if stop {
|
|
fmt.Println("前序未完成处理,跳过!")
|
|
etcd.G_jobLock.UnLock()
|
|
continue
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// 3. 判断客户订单状态是否满足
|
|
if projtablst[i].Calloff_verify_orderstatus > 0 && bl_co.Custordertab.Status < common.CO_STATUS_PLANNED {
|
|
cferror = db.Pln_calloff_errorlst{}
|
|
cferror.Finr = db.G_FINR
|
|
cferror.Calloffnr = cflandtablst[j].Calloffnr
|
|
cferror.Errortype = common.CALLOFF_ORDER_NOTSTATUS
|
|
cferror.Consumeplant = cflandtablst[j].Consumeplant
|
|
cferror.Partfamilyid = cflandtablst[j].Partfamilyid
|
|
cferror.Oemordernr = cflandtablst[j].Oemordernr
|
|
cferror.Errorstatus = "O"
|
|
cferror.Errorinfo = "calloff的客户订单状态不满足:Partfamilyid:" + cflandtablst[j].Partfamilyid + ";Oemordernr:" + cflandtablst[j].Oemordernr
|
|
cferror.Lastmodif = common.TimeFormat(time.Now(), "yyyyMMddHHmmss")
|
|
cferror.Credatuz = common.TimeFormat(time.Now(), "yyyyMMddHHmmss")
|
|
errorlst = append(errorlst, cferror)
|
|
}
|
|
|
|
// 4. 判断客户订单规格是否已审核
|
|
if projtablst[i].Calloff_verify_orderspec > 0 {
|
|
if audit, err = bl_co.IsCarmodelSpecAudited(); err != nil {
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "获取客户订单规格失败 :", bl_co.Custordernr)
|
|
etcd.G_jobLock.UnLock()
|
|
return
|
|
} else {
|
|
if !audit {
|
|
cferror = db.Pln_calloff_errorlst{}
|
|
cferror.Finr = db.G_FINR
|
|
cferror.Calloffnr = cflandtablst[j].Calloffnr
|
|
cferror.Errortype = common.CALLOFF_ORDER_NOTSPEC
|
|
cferror.Consumeplant = cflandtablst[j].Consumeplant
|
|
cferror.Partfamilyid = cflandtablst[j].Partfamilyid
|
|
cferror.Oemordernr = cflandtablst[j].Oemordernr
|
|
cferror.Errorstatus = "O"
|
|
cferror.Errorinfo = "calloff的客户订单的规格型号未审核:" + cflandtablst[j].Partfamilyid + ";Oemordernr:" + cflandtablst[j].Oemordernr
|
|
cferror.Lastmodif = common.TimeFormat(time.Now(), "yyyyMMddHHmmss")
|
|
cferror.Credatuz = common.TimeFormat(time.Now(), "yyyyMMddHHmmss")
|
|
errorlst = append(errorlst, cferror)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 如果有错,则停下不解析
|
|
if len(errorlst) > 0 {
|
|
session = db.G_DbEngine.NewSession()
|
|
if err = session.Begin(); err != nil {
|
|
session.Close()
|
|
etcd.G_jobLock.UnLock()
|
|
return
|
|
}
|
|
//保存错误
|
|
if err = cferror.InsertList(session, errorlst); err != nil {
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "插入Calloff解析错误记录失败 :", err)
|
|
session.Rollback()
|
|
session.Close()
|
|
etcd.G_jobLock.UnLock()
|
|
return
|
|
}
|
|
|
|
//发邮件
|
|
host := projtablst[i].Emailserver_host + ":" + common.ValueToString(projtablst[i].Emailserver_port, "")
|
|
body := "项目号: " + projtablst[i].Projectid + "\r\nOemordernr 订单号: " + cferror.Oemordernr + "\r\nErrorinfo :" + cferror.Errorinfo
|
|
mail.Status = "waiting"
|
|
mail.Body = body
|
|
mail.Subject = "calloff解析错误"
|
|
mail.Name = projtablst[i].From_email
|
|
mail.Tomail = projtablst[i].Calloff_error_to_recievers
|
|
mail.Host = host
|
|
mail.Password = projtablst[i].From_pwd
|
|
mail.Username = projtablst[i].From_email
|
|
err = mail.Add()
|
|
if err != nil {
|
|
glog.InfoExtln("发送邮件", "err is :", err)
|
|
}
|
|
|
|
cflandtablst[j].Parsed = common.EDI_PARSE_YES
|
|
cflandtablst[j].Handlestatus = common.CO_PARSE_STATUS_ERROR
|
|
cflandtablst[j].Lastmodif = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
|
|
if err = cflandtablst[j].UpdateFields(session, "parsed,handlestatus,lastmodif"); err != nil {
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "更新Calloff解析记录失败 :", err)
|
|
session.Rollback()
|
|
session.Close()
|
|
etcd.G_jobLock.UnLock()
|
|
return
|
|
}
|
|
session.Commit()
|
|
session.Close()
|
|
etcd.G_jobLock.UnLock()
|
|
continue
|
|
}
|
|
|
|
// Hardcode: 对于G38项目的PF2的CALLOFF需要等同一客户订单的PF1的CALL进来后才解析
|
|
if cflandtablst[j].Projnr == "G38" && cflandtablst[j].Partfamilyid == "SITKD2" {
|
|
// 获取同项目OEMORDER的Calloff判断解析状态
|
|
if exist, err = cflandtab.ExistUnParsedCfByProjectOemorderPf(cfProj.Projectid, cflandtablst[j].Oemordernr, "SITKD1"); err != nil {
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "获取项目客户订单零件族的calloff记录失败 :", cfProj.Projectid, cflandtablst[j].Oemordernr, cflandtablst[j].Partfamilyid, err)
|
|
etcd.G_jobLock.UnLock()
|
|
return
|
|
}
|
|
if exist {
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "408行 exist is false :", err)
|
|
etcd.G_jobLock.UnLock()
|
|
continue
|
|
}
|
|
}
|
|
|
|
session = db.G_DbEngine.NewSession()
|
|
if err = session.Begin(); err != nil {
|
|
session.Close()
|
|
etcd.G_jobLock.UnLock()
|
|
return
|
|
}
|
|
// 遍历客户订单的生产订单列表,将生产订单加入包装
|
|
for k = 0; k < len(bl_co.Custordertab.Wotablst); k++ {
|
|
glog.InfoExtln("CALLOFF-Debug", "遍历客户订单的生产订单", k, "--", bl_co.Custordertab.Wotablst[k])
|
|
wotab = bl_co.Custordertab.Wotablst[k]
|
|
if wotab.Shippable == 0 || wotab.Packstatus == common.WO_STATUS_PACKED {
|
|
continue
|
|
}
|
|
glog.InfoExtln("CALLOFF-Debug", "需要包装的工单:", wotab.Workordernr, "供应组:", wotab.Supplygroupid, "OEMSEQ:", wotab.Oemseq, "CheckSeq:", cflandtablst[j].Checksequence)
|
|
// 初始化
|
|
bl_pakord = service.BL_PackOrder{}
|
|
|
|
// 基于checksequence和工单的供应组ID查找包装单
|
|
if exist, bl_pakord, err = cfProj.GetPackOrderByCheckSequenceSupplyGroup(session, cflandtablst[j].Checksequence, wotab.Supplygroupid); err != nil {
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "无法获取checksequence的包装订单,原因是:", cflandtablst[j].Checksequence, err)
|
|
session.Rollback()
|
|
session.Close()
|
|
etcd.G_jobLock.UnLock()
|
|
return
|
|
}
|
|
|
|
// 基于OEMSEQ和工单的供应组ID查找包装单
|
|
if !exist {
|
|
glog.InfoExtln("CALLOFF-Debug", "基于checkseq:", cflandtablst[j].Checksequence, "工单供应组:", wotab.Supplygroupid, "未找到开口包装!")
|
|
if exist, bl_pakord, err = cfProj.GetPackOrderByOemseqSupplyGroup(session, wotab); err != nil {
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "无法获取OEMSEQ的包装订单,原因是:", wotab.Oemseq, err)
|
|
session.Rollback()
|
|
session.Close()
|
|
etcd.G_jobLock.UnLock()
|
|
return
|
|
}
|
|
} else {
|
|
glog.InfoExtln("CALLOFF-Debug", "基于checkseq:", cflandtablst[j].Checksequence, "工单供应组:", wotab.Supplygroupid, "找到适配包装!")
|
|
glog.InfoExtln("CALLOFF-Debug", "适配包装:", bl_pakord.Pkotab)
|
|
}
|
|
|
|
// 不存在则新建包装单
|
|
if !exist {
|
|
glog.InfoExtln("CALLOFF-Debug", "基于OEMSEQ", wotab.Oemseq, "工单供应组:", wotab.Supplygroupid, "未找到开口包装!")
|
|
if bl_pakordlst, err = cfProj.CreatePackOrderByCheckSeqWO(session, cflandtablst[j], wotab); err != nil {
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "创建开口包装单失败,原因是:", err)
|
|
session.Rollback()
|
|
session.Close()
|
|
etcd.G_jobLock.UnLock()
|
|
return
|
|
}
|
|
// 获取当前checksequence的包装单
|
|
ok = false
|
|
glog.InfoExtln("CALLOFF-Debug", "新建开口包装成功,数量:", len(bl_pakordlst))
|
|
for m = 0; m < len(bl_pakordlst); m++ {
|
|
glog.InfoExtln("CALLOFF-Debug", m, "----遍历开口包装适配:", bl_pakordlst[m].PackorderId)
|
|
for n = 0; n < len(bl_pakordlst[m].Pkotab.Itemlst); n++ {
|
|
glog.InfoExtln("CALLOFF-Debug", n, " ----匹配包装项:", bl_pakordlst[m].Pkotab.Itemlst[n])
|
|
if bl_pakordlst[m].Pkotab.Itemlst[n].Seq == cflandtablst[j].Checksequence && bl_pakordlst[m].Pkotab.Itemlst[n].Supplygroupid == wotab.Supplygroupid {
|
|
ok = true
|
|
bl_pakord = bl_pakordlst[m]
|
|
break
|
|
}
|
|
}
|
|
if ok {
|
|
break
|
|
}
|
|
}
|
|
if !ok {
|
|
glog.InfoExtln("CALLOFF-Debug", "生产工单", wotab.Workordernr, "匹配包装失败!!!")
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "无法为当前工单找到包装单!", wotab.Workordernr)
|
|
continue
|
|
}
|
|
} else {
|
|
glog.InfoExtln("CALLOFF-Debug", "基于OEMSEQ:", wotab.Oemseq, "工单供应组:", wotab.Supplygroupid, "找到适配包装!")
|
|
glog.InfoExtln("CALLOFF-Debug", "适配包装:", bl_pakord.Pkotab)
|
|
}
|
|
|
|
// 将工单加入到当前包装单
|
|
glog.InfoExtln("CALLOFF-Debug", "尝试将工单:", wotab.Workordernr, "添加到包装单:", bl_pakord.PackorderId)
|
|
if ok, err = cfProj.AddWOToPackOrder(wotab, cflandtablst[j].Checksequence, &bl_pakord, session); err != nil {
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "添加工单到包装单出错,原因是:", wotab.Workordernr, bl_pakord.PackorderId, err)
|
|
session.Rollback()
|
|
session.Close()
|
|
etcd.G_jobLock.UnLock()
|
|
return
|
|
}
|
|
|
|
if ok {
|
|
fmt.Println("成功添加工单", wotab.Workordernr, "到包装单", bl_pakord.PackorderId)
|
|
glog.InfoExtln("CALLOFF-Debug", "成功添加工单", wotab.Workordernr, "到包装单", bl_pakord.PackorderId)
|
|
// 关闭当前包装
|
|
if relstat, err = cfProj.ReleasePackOrder(session, bl_pakord); err != nil {
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "下达包装单出错!", bl_pakord.PackorderId, err)
|
|
session.Rollback()
|
|
session.Close()
|
|
etcd.G_jobLock.UnLock()
|
|
return
|
|
}
|
|
if relstat {
|
|
glog.InfoExtln("CALLOFF-Debug", "成功下达包装单!", bl_pakord.PackorderId)
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "成功下达包装单!", bl_pakord.PackorderId)
|
|
}
|
|
} else {
|
|
glog.InfoExtln("CALLOFF-Debug", "无法添加工单", wotab.Workordernr, "到包装单", bl_pakord.PackorderId)
|
|
}
|
|
|
|
}
|
|
// 更新客户订单Call off相关信息
|
|
bl_co.Custordertab.Calloffnr = cflandtablst[j].Calloffnr
|
|
bl_co.Custordertab.Calloffswet = cflandtablst[j].Swet
|
|
bl_co.Custordertab.Checksequence = cflandtablst[j].Checksequence
|
|
bl_co.Custordertab.Consumecompany = cflandtablst[j].Consumecompany
|
|
bl_co.Custordertab.Consumeplant = cflandtablst[j].Consumeplant
|
|
bl_co.Custordertab.Consigneecompany = cflandtablst[j].Consigneecompany
|
|
bl_co.Custordertab.Consigneeplant = cflandtablst[j].Consigneeplant
|
|
bl_co.Custordertab.Vehicleidset = cflandtablst[j].Vehicleidset
|
|
bl_co.Custordertab.Vehicleid = cflandtablst[j].Vehicleid
|
|
bl_co.Custordertab.Unloadingplace = cflandtablst[j].Unloadingplace
|
|
bl_co.Custordertab.Lastmodif = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
|
|
if err = bl_co.Custordertab.UpdateFields(session, "calloffnr, calloffswet, checksequence, consumecompany, consumeplant, consigneecompany, consigneeplant, vehicleidset, vehicleid, unloadingplace, lastmodif"); err != nil {
|
|
glog.InfoExtln("读取Calloff更新客户订单数据", "Rollback", err)
|
|
session.Rollback()
|
|
session.Close()
|
|
etcd.G_jobLock.UnLock()
|
|
return
|
|
}
|
|
|
|
// calloff 客户订单成功,将landdata置位
|
|
cflandtablst[j].Handlestatus = common.CO_PARSE_STATUS_OK
|
|
cflandtablst[j].Parsed = common.EDI_PARSE_YES
|
|
cflandtablst[j].Lastmodif = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
|
|
if err = cflandtablst[j].UpdateFields(session, "parsed,handlestatus, lastmodif"); err != nil {
|
|
glog.InfoExtln("读取Calloff信息并生成发运包装", "Rollback", err)
|
|
session.Rollback()
|
|
session.Close()
|
|
etcd.G_jobLock.UnLock()
|
|
return
|
|
}
|
|
session.Commit()
|
|
session.Close()
|
|
etcd.G_jobLock.UnLock()
|
|
time.Sleep(10 * time.Millisecond)
|
|
|
|
}
|
|
}
|
|
|
|
time.Sleep(1 * time.Second)
|
|
}
|
|
}
|
|
|
|
// 将26下达的包装单加载到发运车中,系统根据实际加载情况
|
|
func GenerateDeliveryCar() {
|
|
for {
|
|
|
|
var (
|
|
err error
|
|
i, j, idx int
|
|
projtab db.Me_project
|
|
projtablst []db.Me_project
|
|
pkotab db.Jit_packorder
|
|
pkotablst []db.Jit_packorder
|
|
cfProj service.CalloffProject
|
|
bl_sco service.BL_ShipcarOrder
|
|
bl_scolst []service.BL_ShipcarOrder
|
|
fillable, canfix, canrelease bool
|
|
shiptplid string
|
|
session *xorm.Session
|
|
)
|
|
|
|
projtab = db.Me_project{}
|
|
if projtablst, err = projtab.GetAllActive(); err != nil {
|
|
glog.InfoExtln("Calloff包装单", "Failed to get project list!")
|
|
return
|
|
}
|
|
|
|
for i, _ = range projtablst {
|
|
cfProj = service.CalloffProject{}
|
|
cfProj.Projecttab = projtablst[i]
|
|
cfProj.Projectid = projtablst[i].Projectid
|
|
fmt.Println("Ready to load data for project:", projtablst[i].Projectid)
|
|
|
|
// 读取项目的包装类型主数据
|
|
if err = cfProj.LoadPackageType(); err != nil {
|
|
glog.InfoExtln("Calloff包装单", "Failed to load project package type data due to: ", err)
|
|
return
|
|
}
|
|
// 读取项目的发运车模板主数据
|
|
if err = cfProj.LoadShipCarTemplate(); err != nil {
|
|
glog.InfoExtln("Calloff包装单", "Failed to load project ship car data due to: ", err)
|
|
return
|
|
}
|
|
// 循环读取状态>=26已下达且未装车的包装单
|
|
pkotab = db.Jit_packorder{}
|
|
if pkotablst, err = pkotab.GetUnloadedPackOrders(cfProj.Projectid); err != nil {
|
|
glog.InfoExtln("Calloff包装单", "Failed to load project unloaded pack orders due to: ", err)
|
|
return
|
|
}
|
|
|
|
// 遍历包装单
|
|
for j = 0; j < len(pkotablst); j++ {
|
|
// 判断状态
|
|
if pkotablst[j].Status < common.PKO_STATUS_PLANNED || pkotablst[j].Loadstatus == common.PKO_STATUS_LOADED {
|
|
continue
|
|
}
|
|
|
|
// 获取开口发运车订单并添加到发运车中
|
|
if bl_scolst, err = cfProj.GetOpenShipCarOrder(); err != nil {
|
|
glog.InfoExtln("Calloff包装单", "Failed to get open car orders due to: ", err)
|
|
return
|
|
}
|
|
|
|
session = db.G_DbEngine.NewSession()
|
|
defer session.Close()
|
|
if err = session.Begin(); err != nil {
|
|
return
|
|
}
|
|
|
|
// 匹配所有可用模板计算各包装项最大装载量并与已填充量比较,确认是否可以继续填充 => 有可用发运车
|
|
if len(bl_scolst) > 0 {
|
|
fillable, idx = cfProj.CheckOpenCarOrdersForPackOrder(bl_scolst, pkotablst[j])
|
|
}
|
|
|
|
bl_sco = service.BL_ShipcarOrder{}
|
|
|
|
if len(bl_scolst) > 0 && fillable {
|
|
bl_sco.Shiporderid = bl_scolst[idx].Shiporderid
|
|
if err = bl_sco.AddPackOrder(session, pkotablst[j]); err != nil {
|
|
glog.InfoExtln("Calloff包装单", "Failed to add packorder :, into shipcar order :, due to: ",
|
|
pkotablst[j].Packorderid, bl_sco.Shiporderid, err)
|
|
session.Rollback()
|
|
return
|
|
}
|
|
} else {
|
|
// 如果没有开口发运车,则创建发运车并添加
|
|
if bl_sco, err = cfProj.CreateShipCarOrder(session); err != nil {
|
|
glog.InfoExtln("Calloff包装单", "Failed to create shipcar order due to: ", err)
|
|
session.Rollback()
|
|
return
|
|
}
|
|
if err = bl_sco.AddPackOrder(session, pkotablst[j]); err != nil {
|
|
glog.InfoExtln("Calloff包装单", "Failed to add packorder : , into shipcar order :, due to: ",
|
|
pkotablst[j].Packorderid, bl_sco.Shiporderid, err)
|
|
session.Rollback()
|
|
return
|
|
}
|
|
}
|
|
|
|
// 获取发运车最新的数据
|
|
if err = bl_sco.GetOrderDataBySession(session); err != nil {
|
|
glog.InfoExtln("Calloff包装单", "Failed to get ship order data!", bl_sco.Shiporderid)
|
|
session.Rollback()
|
|
return
|
|
}
|
|
|
|
// 检查发运车是否可以指定模板,状态从10 -> 20
|
|
if bl_sco.Spordtab.Status < common.SPO_STATUS_PLANNED {
|
|
cfProj.InitShipOrderWorkoload(&bl_sco)
|
|
cfProj.RecalShipItemWorkloadMaxQty(&bl_sco)
|
|
if canfix, shiptplid, err = cfProj.IsShipcarOrderFixTemplate(&bl_sco); err != nil {
|
|
glog.InfoExtln("Calloff包装单", "Failed to check shiporder fixable due to :", err)
|
|
session.Rollback()
|
|
return
|
|
}
|
|
if canfix {
|
|
// 释放发运车并更新匹配的模板
|
|
if err = cfProj.FixShipCarOrderTemplate(session, &bl_sco, shiptplid); err != nil {
|
|
glog.InfoExtln("Calloff包装单", "Failed to release ship car order!")
|
|
session.Rollback()
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
// 检查发运车是否达到上限可关闭,状态从20 -> 26
|
|
if canrelease, err = cfProj.IsShipcarOrderReleasable(&bl_sco); err != nil {
|
|
glog.InfoExtln("Calloff包装单", "Failed to check shiporder releasable due to :", err)
|
|
session.Rollback()
|
|
return
|
|
}
|
|
if canrelease {
|
|
// 释放发运车并更新匹配的模板
|
|
if err = cfProj.ReleaseShipCarOrder(session, &bl_sco); err != nil {
|
|
glog.InfoExtln("Calloff包装单", "Failed to release ship car order!")
|
|
session.Rollback()
|
|
return
|
|
}
|
|
}
|
|
|
|
fmt.Println("---------------------生成xmL_msg1")
|
|
//APS向WMS传递发运包装信息
|
|
var o = PlnCalloffdataLandingXml{}
|
|
o.Packorderid = pkotablst[j].Packorderid
|
|
o.Packtemplateid = pkotablst[j].Packtemplateid
|
|
o.Projnr = pkotablst[j].Projnr
|
|
o.Status = strconv.Itoa(pkotablst[j].Status)
|
|
o.Shortpack = strconv.Itoa(pkotablst[j].Shortpack)
|
|
o.Orderinfo = pkotablst[j].Orderinfo
|
|
o.Boxsn = pkotablst[j].Boxsn
|
|
o.Packtypeid = pkotablst[j].Packtypeid
|
|
o.Printerid = pkotablst[j].Printerid
|
|
o.Templatefile = pkotablst[j].Templatefile
|
|
o.Planqty = strconv.Itoa(pkotablst[j].Planqty)
|
|
o.Actqty = strconv.Itoa(pkotablst[j].Actqty)
|
|
for _, info := range pkotablst[j].Itemlst{
|
|
o.Details = append(o.Details, Pln_calloffdata_landing_Xml{
|
|
Packorderid :info.Packorderid,
|
|
Pos :common.ValueToString(info.Pos,""),
|
|
Poscode :info.Poscode,
|
|
Oemseq : common.ValueToString(info.Oemseq, ""),
|
|
Checkseq :common.ValueToString(info.Seq,""),
|
|
Supplygroupid : info.Supplygroupid,
|
|
Workordernr : info.Workordernr,
|
|
Status : common.ValueToString(info.Status,""),
|
|
Planqty :common.ValueToString(info.Planqty,""),
|
|
Actqty :common.ValueToString(info.Actqty,""),
|
|
})
|
|
}
|
|
|
|
jsonBytes, err := json.Marshal(o)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
bl_xmlmsg := service.BL_Xmlmsg{MsgType: common.MSG_TYPE_SHIP, Msg: string(jsonBytes)}
|
|
fmt.Println("---------------------生成xmL_msg2")
|
|
if err = bl_xmlmsg.Create(session); err != nil {
|
|
fmt.Println(err)
|
|
}
|
|
|
|
err = session.Commit()
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return
|
|
}
|
|
}
|
|
}
|
|
|
|
time.Sleep(10 * time.Second)
|
|
}
|
|
}
|
|
|
|
func CallOffXmlTick(){
|
|
timer := time.NewTicker(60 * time.Second)
|
|
for {
|
|
select {
|
|
case <-timer.C:
|
|
Xml_msg := db.Xml_msg{}
|
|
if xmllst, err := Xml_msg.GetUnXmlMessages(); err != nil {
|
|
glog.InfoExtln("Calloff包装单", "解析发运单消息失败: ", err)
|
|
}else{
|
|
for _, xmlInfo := range xmllst{
|
|
var xmlStruct PlnCalloffdataLandingXml
|
|
json.Unmarshal([]byte(xmlInfo.Msg), &xmlStruct)
|
|
|
|
resXML, err := xml.MarshalIndent(xmlStruct, " ", " ")
|
|
if err != nil {
|
|
glog.InfoExtln("Calloff包装单", "Failed to create xml due to :",err)
|
|
}
|
|
timeS := time.Now().Format("20060102150405.999")
|
|
fileName := strings.Trim(timeS,".")
|
|
f, err := os.Create("./OutData/"+fileName +".xml")
|
|
if err != nil {
|
|
glog.InfoExtln("Calloff包装单", "Failed to create xml due to :",err)
|
|
}
|
|
io.WriteString(f, xml.Header)
|
|
io.WriteString(f, string(resXML))
|
|
|
|
Xml_msg.Msgid = xmlInfo.Msgid
|
|
Xml_msg.Status = common.MSG_STATUS_FINISHED
|
|
Xml_msg.Lastmodif = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
|
|
Xml_msg.Lastuser = "service"
|
|
if err = Xml_msg.UpdateFieldsWithoutSession("status,lastmodif,lastuser"); err != nil {
|
|
glog.InfoExtln("Calloff包装单", "Failed to create xml due to :",err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
type PlnCalloffdataLandingXml struct {
|
|
XMLName xml.Name `xml:"Content"`
|
|
Packorderid string `xml:"packorderid,attr"`
|
|
Packtemplateid string `xml:"packtemplateid,attr"`
|
|
Projnr string `xml:"projnr,attr"`
|
|
Status string `xml:"status,attr"`
|
|
Shortpack string `xml:"shortpack,attr"`
|
|
Orderinfo string `xml:"orderinfo,attr"`
|
|
Boxsn string `xml:"boxsn,attr"`
|
|
Packtypeid string `xml:"packtypeid,attr"`
|
|
Printerid string `xml:"printerid,attr"`
|
|
Templatefile string `xml:"templatefile,attr"`
|
|
Planqty string `xml:"planqty,attr"`
|
|
Actqty string `xml:"actqty,attr"`
|
|
|
|
Details []Pln_calloffdata_landing_Xml `xml:"Details"`
|
|
Description string `xml:",innerxml"`
|
|
}
|
|
|
|
type Pln_calloffdata_landing_Xml struct {
|
|
XMLName xml.Name `xml:"Details"`
|
|
Packorderid string `xml:"packorderid,attr"`
|
|
Pos string `xml:"pos,attr"`
|
|
Poscode string `xml:"poscode,attr"`
|
|
Oemseq string `xml:"oemseq,attr"`
|
|
Checkseq string `xml:"checkseq,attr"`
|
|
Supplygroupid string `xml:"supplygroupid,attr"`
|
|
Workordernr string `xml:"workordernr,attr"`
|
|
Status string `xml:"status,attr"`
|
|
Planqty string `xml:"planqty,attr"`
|
|
Actqty string `xml:"actqty,attr"`
|
|
}
|