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.

251 lines
8.2 KiB

package tod
import (
"errors"
"fmt"
"github.com/go-xorm/xorm"
"io/ioutil"
"leit.com/leit_seat_aps/common"
"leit.com/leit_seat_aps/db"
"leit.com/leit_seat_aps/service"
"log"
"os"
"path/filepath"
"regexp"
"time"
"xorm.io/core"
)
// TOD 缓存数据对象定义
type TodLandData struct {
Projnr string // 项目号
Edifile string // EDI 文件名
Bl_CoDict map[string]service.BL_CustOrder // 解析的客户订单对象
Covtablst []db.Pln_custorder_ver // 客户订单版本头
}
// 加载TOD文件并将文件中的客户订单数据解析到客户订单字典,key值是OemOrderNr
func (blt *TodLandData) ReadTodData(tod_file string) (err error) {
var (
tod TOD
seq SEQ
sg service.BL_SupplyGroup
lin LIN
bl_sgpt service.BL_SgPart
bl_co service.BL_CustOrder
edifile string
ok bool
)
// 读取并解析TOD文件
tod = TOD{}
if err = ParseTodEdi(tod_file, &tod); err != nil {
log.Printf("Failed to load tod file: %s due to: %v", tod_file, err)
return
}
// 获取TOD文件名
_, edifile = filepath.Split(tod_file)
// 初始化客户订单字典
blt.Bl_CoDict = make(map[string]service.BL_CustOrder)
// 遍历TOD文件将数据填充到订单字典中
for _, seq = range tod.SeqList {
if bl_co, ok = blt.Bl_CoDict[seq.Gir.CustOrderNr]; !ok {
// 客户订单不存在,初始化一个新的客户订单
bl_co = service.BL_CustOrder{}
bl_co.Oemordernr = seq.Gir.CustOrderNr
bl_co.Projnr = blt.Projnr
bl_co.Partfamilyid = seq.Gir.PartFamily
bl_co.SeqType = seq.SeqType
bl_co.Ordertime = tod.Dtm.MsgTime
bl_co.Swet = seq.Dtm.MsgTime
bl_co.Edifile = edifile
bl_co.Bl_sgdict = make(map[string]service.BL_SupplyGroup)
bl_co.Bl_ordattrdict = make(map[int]service.BL_OrdAttribute)
bl_co.Bl_verrdict = make(map[string]service.BL_VerifyError)
}
// 获取供应组下所有的零件信息
sg = service.BL_SupplyGroup{}
sg.Bl_sgpartDict = make(map[string]service.BL_SgPart)
sg.Partfamilyid = seq.Gir.PartFamily
sg.Supplygroupid = seq.Gir.SupplyGroup
for _, lin = range seq.LinList {
bl_sgpt = service.BL_SgPart{}
bl_sgpt.Partid = lin.PartNr + "-" + lin.Pia.Ai // 零件号
bl_sgpt.Ai = lin.Pia.Ai // 零件版本号
bl_sgpt.Qty = lin.Qty.Qty // 零件数量
bl_sgpt.Supplygroupid = sg.Supplygroupid
bl_sgpt.Originalsgid = sg.Supplygroupid
bl_sgpt.AtcodDict = make(map[int]service.BL_Attribute)
sg.Bl_sgpartDict[bl_sgpt.Partid] = bl_sgpt
}
bl_co.Bl_sgdict[sg.Supplygroupid] = sg
blt.Bl_CoDict[bl_co.Oemordernr] = bl_co
}
return
}
// 将TOD解析数据保存到数据库:客户订单版本和零件清单
func (blt *TodLandData) SaveTodData(mdata *service.TodProject) (err error) {
var (
cotab db.Pln_custorder
bl_co service.BL_CustOrder
exist bool
session *xorm.Session
)
for _, bl_co = range blt.Bl_CoDict {
//开启事务
session = db.G_DbEngine.NewSession()
if err = session.Begin(); err != nil {
session.Close()
return
}
// 查找OEM订单是否存在,不存在则创建
cotab = db.Pln_custorder{Oemordernr: bl_co.Oemordernr, Partfamilyid: bl_co.Partfamilyid, Projnr: blt.Projnr}
if exist, cotab, err = cotab.GetByOemOrderNrBySession(session); err != nil {
err = errors.New(fmt.Sprintf("Failed to get cust order for oemorder: %s due to: %v", bl_co.Oemordernr, err))
session.Rollback()
session.Close()
return
}
// 如果客户订单存在
if exist {
// 获取客户订单头信息并更新它的处理状态
cotab.Handlestatus = "RC"
cotab.Lastmodif = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
if _, err = session.ID(core.PK{db.G_FINR, cotab.Custordernr}).Cols("handlestatus", "lastmodif").Update(cotab); err != nil {
err = errors.New(fmt.Sprintf("Failed to update cust order: %s due to: %v", cotab.Custordernr, err))
session.Rollback()
session.Close()
return
}
bl_co.Custordernr = cotab.Custordernr
bl_co.Custordertab = cotab
} else {
if err = bl_co.CreateCOHead(session, mdata.Projecttab.Custorder_snr); err != nil {
err = errors.New(fmt.Sprintf("Failed to create cust order for oemorder: %s due to: %v", bl_co.Oemordernr, err))
session.Rollback()
session.Close()
return
}
}
// 保存客户订单版本信息
if err = bl_co.SaveCOHeadVersion(session); err != nil {
err = errors.New(fmt.Sprintf("Failed to save cust order: %s history version due to: %v", bl_co.Custordernr, err))
session.Rollback()
session.Close()
return
}
session.Commit()
session.Close()
}
return
}
// 测试TOD解析缓存并创建客户订单头
func ReadTodFileToLand() (err error) {
var (
projtab db.Me_project
projtablst []db.Me_project
todland TodLandData
todProj service.TodProject
rd []os.FileInfo
fi os.FileInfo
edi_file string
matched bool
)
projtab = db.Me_project{}
if projtablst, err = projtab.GetAllActive(); err != nil {
err = errors.New(fmt.Sprintf("加载项目失败,原因是: %v", err))
return
}
for i, _ := range projtablst {
todProj = service.TodProject{}
todProj.Projecttab = projtablst[i]
todProj.Projectid = projtablst[i].Projectid
fmt.Println("Ready to load data for project:", projtablst[i].Projectid)
if err = todProj.GetAttributeList(common.ATCOD_TYPE_PART); err != nil {
err = errors.New(fmt.Sprintf("加载项目:%s的属性失败,原因是: %v", projtablst[i].Projectid, err))
return
}
if err = todProj.GetPartFamilyList(); err != nil {
err = errors.New(fmt.Sprintf("加载项目:%s的零件族失败,原因是: %v", projtablst[i].Projectid, err))
return
}
if err = todProj.GetSupplyGroupList(); err != nil {
err = errors.New(fmt.Sprintf("加载项目:%s的供应组失败,原因是: %v", projtablst[i].Projectid, err))
return
}
if err = todProj.GetPartList(); err != nil {
err = errors.New(fmt.Sprintf("加载项目:%s的零件清单失败,原因是: %v", projtablst[i].Projectid, err))
return
}
if err = todProj.GetCarModelList(); err != nil {
err = errors.New(fmt.Sprintf("加载项目:%s的Carmodel失败,原因是: %v", projtablst[i].Projectid, err))
return
}
if err = todProj.GetPartRuleList(); err != nil {
err = errors.New(fmt.Sprintf("加载项目:%s的共用件规则失败,原因是: %v", projtablst[i].Projectid, err))
return
}
fmt.Println("完成项目主数据加载!")
fmt.Println(projtablst[i].Projectid, " ==> Try to load file from folder:", projtablst[i].Tod_folder)
if rd, err = ioutil.ReadDir(projtablst[i].Tod_folder + "/inbox"); err != nil {
err = errors.New(fmt.Sprintf("读取TOD的Inbox文件夹失败,原因是: %v", err))
return
}
for _, fi = range rd {
if fi.IsDir() {
continue
}
edi_file = projtablst[i].Tod_folder + "/inbox" + "/" + fi.Name()
fmt.Println("Try to load tod file:", edi_file)
// 判断文件的合规性
if matched, err = regexp.MatchString(todProj.Projecttab.Tod_filename_regexp, fi.Name()); err != nil {
err = errors.New(fmt.Sprintf("TOD文件名: %s : 匹配规范错误: %v !", fi.Name(), err))
os.Rename(edi_file, todProj.Projecttab.Tod_folder+"/errbox"+"/"+fi.Name())
continue
}
if !matched {
err = errors.New(fmt.Sprintf("TOD文件名: %s 不符合规范: %s !", fi.Name(), todProj.Projecttab.Tod_filename_regexp))
os.Rename(edi_file, todProj.Projecttab.Tod_folder+"/errbox"+"/"+fi.Name())
continue
}
fmt.Println("Ready to read tod data......")
todland = TodLandData{}
todland.Projnr = projtablst[i].Projectid
todland.Edifile = edi_file
if err = todland.ReadTodData(edi_file); err != nil {
err = errors.New(fmt.Sprintf("TOD文件: %s : 解析错误: %v !", fi.Name(), err))
os.Rename(edi_file, todProj.Projecttab.Tod_folder+"/errbox"+"/"+fi.Name())
continue
}
if err = todland.SaveTodData(&todProj); err != nil {
err = errors.New(fmt.Sprintf("TOD文件: %s : 保存错误: %v !", fi.Name(), err))
os.Rename(edi_file, todProj.Projecttab.Tod_folder+"/errbox"+"/"+fi.Name())
continue
}
// 将TOD文件移到已处理文件夹 outbox
os.Rename(edi_file, todProj.Projecttab.Tod_folder+"/outbox"+"/"+fi.Name())
}
}
return
}