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.

658 lines
24 KiB

  1. package calloff
  2. import (
  3. "fmt"
  4. "github.com/go-xorm/xorm"
  5. "io/ioutil"
  6. "leit.com/leit_seat_aps/common"
  7. "leit.com/leit_seat_aps/db"
  8. "leit.com/leit_seat_aps/service"
  9. "os"
  10. "regexp"
  11. "testing"
  12. "time"
  13. )
  14. // 测试Calloff文件解析和保存
  15. func TestParseCalloffNew(t *testing.T) {
  16. var (
  17. connstring string
  18. err error
  19. projtab db.Me_project
  20. projtablst []db.Me_project
  21. cfland CalloffLandData
  22. cfProj service.CalloffProject
  23. rd []os.FileInfo
  24. fi os.FileInfo
  25. edi_file string
  26. matched bool
  27. )
  28. // 连接数据库
  29. connstring = fmt.Sprintf("server=%s;user id=%s;password=%s;database=%s;port=%d;encrypt=disable",
  30. `localhost`, "lapp", "123fis", "SJA_APS", 1433)
  31. if err = db.InitMssqlDb(connstring); err != nil {
  32. t.Errorf("Failed to connect db due to: %v", err)
  33. return
  34. }
  35. defer db.G_DbEngine.Close()
  36. projtab = db.Me_project{}
  37. if projtablst, err = projtab.GetAllActive(); err != nil {
  38. t.Errorf("Failed to get project list!")
  39. return
  40. }
  41. for i, _ := range projtablst {
  42. cfProj = service.CalloffProject{}
  43. cfProj.Projecttab = projtablst[i]
  44. cfProj.Projectid = projtablst[i].Projectid
  45. fmt.Println("Ready to load data for project:", projtablst[i].Projectid)
  46. // 读取文件夹内的文件并解析
  47. if rd, err = ioutil.ReadDir(cfProj.Projecttab.Calloff_folder + "/inbox"); err != nil {
  48. return
  49. }
  50. for _, fi = range rd {
  51. if fi.IsDir() {
  52. continue
  53. }
  54. edi_file = cfProj.Projecttab.Calloff_folder + "/inbox" + "/" + fi.Name()
  55. // 判断文件的合规性
  56. if matched, err = regexp.MatchString(cfProj.Projecttab.Calloff_filename_regexp, fi.Name()); err != nil {
  57. t.Errorf("Failed to match EDI file name: %s due to: %v", fi.Name(), err)
  58. return
  59. }
  60. if !matched {
  61. t.Errorf("The specified EDI file: %s doesn't match the required name specification!", fi.Name())
  62. os.Rename(edi_file, cfProj.Projecttab.Calloff_folder+"/errbox"+"/"+fi.Name())
  63. return
  64. }
  65. // 解析CALLOFF文件到字典
  66. fmt.Println("Ready to read tod data......")
  67. cfland = CalloffLandData{}
  68. cfland.Projnr = projtablst[i].Projectid
  69. cfland.Edifile = edi_file
  70. if err = cfland.ReadCalloffData(edi_file); err != nil {
  71. t.Errorf("Failed to parse Calloff file due to: %v", err)
  72. os.Rename(edi_file, cfProj.Projecttab.Calloff_folder+"/errbox"+"/"+fi.Name())
  73. return
  74. }
  75. // 保存CALLOFF字典到临时缓存表
  76. if err = cfland.SaveCalloffData(); err != nil {
  77. //t.Errorf("Failed to save Calloff parse result due to: %v", err)
  78. os.Rename(edi_file, cfProj.Projecttab.Calloff_folder+"/errbox"+"/"+fi.Name())
  79. continue
  80. }
  81. // 将文件移到outbox
  82. os.Rename(edi_file, cfProj.Projecttab.Calloff_folder+"/outbox"+"/"+fi.Name())
  83. }
  84. }
  85. }
  86. // 测试读取Calloff信息并生成发运包装
  87. func TestParseCalloffOrder(t *testing.T) {
  88. var (
  89. connstring string
  90. err error
  91. i, j, k, prevCS, m, n int
  92. projtab db.Me_project
  93. projtablst []db.Me_project
  94. cfProj service.CalloffProject
  95. cflandtab db.Pln_calloffdata_landing
  96. cflandtablst []db.Pln_calloffdata_landing
  97. cflandtablst2 []db.Pln_calloffdata_landing
  98. cftab db.Pln_calloffdata_landing
  99. cftablst []db.Pln_calloffdata_landing
  100. bl_co service.BL_CustOrder
  101. bl_prevco service.BL_CustOrder
  102. wotab db.Pln_workorder
  103. sgtab db.Me_supplygroup
  104. exist, ok, audit,relstat,stop bool
  105. prevOemord string
  106. sgdict map[string]string
  107. bl_pakordlst []service.BL_PackOrder
  108. bl_pakord service.BL_PackOrder
  109. cferror db.Pln_calloff_errorlst
  110. errorlst []db.Pln_calloff_errorlst
  111. session *xorm.Session
  112. )
  113. // 连接数据库
  114. connstring = fmt.Sprintf("server=%s;user id=%s;password=%s;database=%s;port=%d;encrypt=disable",
  115. `localhost`, "lapp", "123fis", "SJA_APS", 1433)
  116. if err = db.InitMssqlDb(connstring); err != nil {
  117. t.Errorf("Failed to connect db due to: %v", err)
  118. return
  119. }
  120. defer db.G_DbEngine.Close()
  121. projtab = db.Me_project{}
  122. if projtablst, err = projtab.GetAllActive(); err != nil {
  123. t.Errorf("Failed to get project list!")
  124. return
  125. }
  126. for i, _ = range projtablst {
  127. cfProj = service.CalloffProject{}
  128. cfProj.Projecttab = projtablst[i]
  129. cfProj.Projectid = projtablst[i].Projectid
  130. fmt.Println("Ready to load data for project:", projtablst[i].Projectid)
  131. // 加载项目主数据
  132. if err = cfProj.LoadMasterData(); err != nil {
  133. t.Errorf("Failed to load project master data due to: %v!", err)
  134. return
  135. }
  136. // 循环读取未处理的Calloff消息,按零件族和CheckSequence排序
  137. cflandtab = db.Pln_calloffdata_landing{Projnr: cfProj.Projectid}
  138. if cflandtablst, err = cflandtab.GetUnparsedLandingData(); err != nil {
  139. t.Errorf("Failed to get unparsed calloff landding data due to: %v!", err)
  140. return
  141. }
  142. // 遍历未处理的Calloff消息
  143. for j = 0; j < len(cflandtablst); j++ {
  144. // 读取项目各零件族解析的最大CheckSequence号
  145. if err = cfProj.LoadPartFamilyMaxParsedCheckSequence(); err != nil {
  146. t.Errorf("Failed to load project max check sequence data for each partfamily due to: %v!", err)
  147. return
  148. }
  149. errorlst = []db.Pln_calloff_errorlst{}
  150. // 验证Calloff有效性
  151. // 1. 基于零件族判断CheckSequence是否连续
  152. if projtablst[i].Calloff_verify_checksequence > 0 {
  153. if prevCS, ok = cfProj.Pfcsdict[cflandtablst[j].Partfamilyid]; !ok {
  154. t.Errorf("Calloff landing data's partfamily %s is not existing in the global dict!", cflandtablst[j].Partfamilyid)
  155. return
  156. }
  157. // 检查checksequence是否连续,如果不连续查询两者之间是否有报错的解析记录,如果没有报错,如果有继续不处理
  158. if prevCS > 0 && prevCS+1 != cflandtablst[j].Checksequence {
  159. if exist, err = cflandtablst[j].AnyErrorRecordBetweenCheckSequence( cfProj.Projectid,cflandtablst[j].Partfamilyid,prevCS,cflandtablst[j].Checksequence ); err != nil{
  160. t.Errorf("Failed to query calloff record!")
  161. return
  162. }
  163. if exist {
  164. continue
  165. }else{
  166. cferror = db.Pln_calloff_errorlst{}
  167. cferror.Finr = db.G_FINR
  168. cferror.Calloffnr = cflandtablst[j].Calloffnr
  169. cferror.Errortype = common.CALLOFF_CHECK_SEQUENCE
  170. cferror.Consumeplant = cflandtablst[j].Consumeplant
  171. cferror.Partfamilyid = cflandtablst[j].Partfamilyid
  172. cferror.Oemordernr = cflandtablst[j].Oemordernr
  173. cferror.Errorstatus = "O"
  174. cferror.Errorinfo = "CheckSequence不连续:" + common.ValueToString(prevCS, "") + ";" + common.ValueToString(cflandtablst[j].Checksequence, "")
  175. cferror.Lastmodif = common.TimeFormat(time.Now(), "yyyyMMddHHmmss")
  176. cferror.Credatuz = common.TimeFormat(time.Now(), "yyyyMMddHHmmss")
  177. errorlst = append(errorlst, cferror)
  178. // CheckSequence 不连续,报错
  179. fmt.Println("CheckSequence不连续:", prevCS, "==>", cflandtablst[j].Checksequence)
  180. }
  181. }
  182. }
  183. // 2. 判断客户订单是否存在
  184. bl_co = service.BL_CustOrder{Projnr: cflandtablst[j].Projnr, Oemordernr: cflandtablst[j].Oemordernr, Partfamilyid: cflandtablst[j].Partfamilyid}
  185. if exist, err = bl_co.GetCalloffOemorder(); err != nil {
  186. t.Errorf("Failed to get custorder for oemorder %s due to: %v ", cflandtablst[j].Oemordernr, err)
  187. return
  188. }
  189. if !exist {
  190. cferror = db.Pln_calloff_errorlst{}
  191. cferror.Finr = db.G_FINR
  192. cferror.Calloffnr = cflandtablst[j].Calloffnr
  193. cferror.Errortype = common.CALLOFF_ORDER_NOTEXIST
  194. cferror.Consumeplant = cflandtablst[j].Consumeplant
  195. cferror.Partfamilyid = cflandtablst[j].Partfamilyid
  196. cferror.Oemordernr = cflandtablst[j].Oemordernr
  197. cferror.Errorstatus = "O"
  198. cferror.Errorinfo = "Calloff的客户订单不存在:Partfamilyid:" + cflandtablst[j].Partfamilyid + ";Oemordernr:" + cflandtablst[j].Oemordernr
  199. cferror.Lastmodif = common.TimeFormat(time.Now(), "yyyyMMddHHmmss")
  200. cferror.Credatuz = common.TimeFormat(time.Now(), "yyyyMMddHHmmss")
  201. errorlst = append(errorlst, cferror)
  202. t.Errorf("Calloff的客户订单%s - %s不存在 :", cflandtablst[j].Oemordernr, cflandtablst[j].Partfamilyid)
  203. }
  204. // 获取前面一个CheckSequence及其对应的客户订单号
  205. prevCS, _ = cfProj.Pfcsdict[cflandtablst[j].Partfamilyid]
  206. prevOemord = ""
  207. fmt.Println(cflandtablst[j].Checksequence,"的前序:",prevCS)
  208. if prevCS > 0 {
  209. cflandtab = db.Pln_calloffdata_landing{Projnr: cfProj.Projectid, Checksequence: prevCS, Partfamilyid: cflandtablst[j].Partfamilyid}
  210. if cflandtablst2, err = cflandtab.GetByProjectCheckSequencePartfamily(); len(cflandtablst2) > 0 {
  211. prevOemord = cflandtablst2[0].Oemordernr
  212. fmt.Println("前序客户订单:",prevOemord)
  213. // 获取前序客户订单对应的calloff记录
  214. cftab = db.Pln_calloffdata_landing{Projnr: cfProj.Projectid, Oemordernr: prevOemord}
  215. // 获取前序calloff的所有记录
  216. if cftablst, err = cftab.GetByProjectOemorder(); err != nil{
  217. t.Errorf("查询项目%s 客户订单%s 的calloff记录失败: %v!", cftab.Projnr, cftab.Oemordernr, err)
  218. return
  219. }
  220. // 获取前序客户订单
  221. bl_prevco = service.BL_CustOrder{Projnr: cfProj.Projectid, Oemordernr: cflandtablst2[0].Oemordernr, Partfamilyid: cflandtablst2[0].Partfamilyid}
  222. if exist, err = bl_prevco.GetCalloffOemorder(); err != nil {
  223. t.Errorf("Failed to get custorder for oemorder %s due to: %v ", cflandtablst2[0].Oemordernr, err)
  224. return
  225. }
  226. // 校验客户订单的零件族是否齐全
  227. sgdict = make(map[string]string)
  228. if sgdict, err = bl_prevco.GetOemorderModelSpecPfdict(); err!= nil{
  229. t.Errorf("查询项目%s 客户订单%s 的车型规格字典记录失败: %v!", bl_prevco.Custordertab.Projnr, bl_prevco.Custordertab.Custordernr, err)
  230. return
  231. }
  232. if len(sgdict) != len(cftablst){
  233. // 整车副缺零件族
  234. fmt.Println("客户订单",prevOemord,"的calloff不齐全无法校验!")
  235. continue
  236. }
  237. // 校验是否解析有错误
  238. if len(cftablst) > 0 {
  239. fmt.Println("遍历前序订单的calloff记录")
  240. // 校验前车付的calloff是否有错
  241. stop = false
  242. for k = 0; k < len(cftablst); k++ {
  243. fmt.Println(k,"-->",cftablst[k])
  244. if cftablst[k].Parsed == 0 || cftablst[k].Handlestatus != common.CO_PARSE_STATUS_OK {
  245. stop = true
  246. break
  247. }
  248. }
  249. if stop{
  250. fmt.Println("前序未完成处理,跳过!")
  251. continue
  252. }
  253. }
  254. }
  255. }
  256. // 3. 判断客户订单状态是否满足
  257. if projtablst[i].Calloff_verify_orderstatus > 0 && bl_co.Custordertab.Status < common.CO_STATUS_PLANNED {
  258. cferror = db.Pln_calloff_errorlst{}
  259. cferror.Finr = db.G_FINR
  260. cferror.Calloffnr = cflandtablst[j].Calloffnr
  261. cferror.Errortype = common.CALLOFF_ORDER_NOTSTATUS
  262. cferror.Consumeplant = cflandtablst[j].Consumeplant
  263. cferror.Partfamilyid = cflandtablst[j].Partfamilyid
  264. cferror.Oemordernr = cflandtablst[j].Oemordernr
  265. cferror.Errorstatus = "O"
  266. cferror.Errorinfo = "calloff的客户订单状态不满足:Partfamilyid:" + cflandtablst[j].Partfamilyid + ";Oemordernr:" + cflandtablst[j].Oemordernr
  267. cferror.Lastmodif = common.TimeFormat(time.Now(), "yyyyMMddHHmmss")
  268. cferror.Credatuz = common.TimeFormat(time.Now(), "yyyyMMddHHmmss")
  269. errorlst = append(errorlst, cferror)
  270. }
  271. // 4. 判断客户订单规格是否已审核
  272. if projtablst[i].Calloff_verify_orderspec > 0 {
  273. if audit, err = bl_co.IsCarmodelSpecAudited(); err !=nil {
  274. t.Errorf("Failed to inert error list due to : %v", err)
  275. return
  276. } else{
  277. if !audit {
  278. cferror = db.Pln_calloff_errorlst{}
  279. cferror.Finr = db.G_FINR
  280. cferror.Calloffnr = cflandtablst[j].Calloffnr
  281. cferror.Errortype = common.CALLOFF_ORDER_NOTSPEC
  282. cferror.Consumeplant = cflandtablst[j].Consumeplant
  283. cferror.Partfamilyid = cflandtablst[j].Partfamilyid
  284. cferror.Oemordernr = cflandtablst[j].Oemordernr
  285. cferror.Errorstatus = "O"
  286. cferror.Errorinfo = "calloff的客户订单的规格型号未审核:" + cflandtablst[j].Partfamilyid + ";Oemordernr:" + cflandtablst[j].Oemordernr
  287. cferror.Lastmodif = common.TimeFormat(time.Now(), "yyyyMMddHHmmss")
  288. cferror.Credatuz = common.TimeFormat(time.Now(), "yyyyMMddHHmmss")
  289. errorlst = append(errorlst, cferror)
  290. }
  291. }
  292. }
  293. // 如果有错,则停下不解析
  294. if len(errorlst) > 0 {
  295. session = db.G_DbEngine.NewSession()
  296. defer session.Close()
  297. if err = session.Begin(); err != nil {
  298. return
  299. }
  300. //保存错误
  301. if err = cferror.InsertList(session, errorlst); err != nil {
  302. t.Errorf("Failed to inert error list due to : %v", err)
  303. return
  304. }
  305. cflandtablst[j].Parsed = common.EDI_PARSE_YES
  306. cflandtablst[j].Handlestatus = common.CO_PARSE_STATUS_ERROR
  307. cflandtablst[j].Lastmodif = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
  308. if err = cflandtablst[j].UpdateFields(session, "parsed,handlestatus, lastmodif"); err != nil {
  309. t.Errorf("Failed to update calloffdata_landing due to : %v", err)
  310. session.Rollback()
  311. return
  312. }
  313. session.Commit()
  314. continue
  315. }
  316. // Hardcode: 对于G38项目的PF2的CALLOFF需要等同一客户订单的PF1的CALL进来后才解析
  317. if cflandtablst[j].Projnr == "G38" && cflandtablst[j].Partfamilyid == "SITKD2" {
  318. // 获取同项目OEMORDER的Calloff判断解析状态
  319. if exist, err = cflandtab.ExistUnParsedCfByProjectOemorderPf(cfProj.Projectid,cflandtablst[j].Oemordernr,"SITKD1"); err != nil{
  320. t.Errorf("获取项目%s 客户订单%s 零件族%s 的calloff记录失败 : %v", cfProj.Projectid,cflandtablst[j].Oemordernr,cflandtablst[j].Partfamilyid, err)
  321. return
  322. }
  323. if exist{
  324. continue
  325. }
  326. }
  327. // 遍历客户订单的生产订单列表,将生产订单加入包装
  328. fmt.Println("======================== 遍历客户订单:",bl_co.Custordernr, common.ValueToInt(bl_co.Custordertab.Oemseq, 0))
  329. for k = 0; k < len(bl_co.Custordertab.Wotablst); k++ {
  330. wotab = bl_co.Custordertab.Wotablst[k]
  331. if wotab.Shippable == 0 || wotab.Packstatus == common.WO_STATUS_PACKED {
  332. continue
  333. }
  334. fmt.Println(" === 遍历其生产订单:",wotab.Workordernr, "==>",wotab.Supplygroupid)
  335. // 获取供应组
  336. if sgtab,ok = cfProj.Sgdict[wotab.Supplygroupid]; !ok {
  337. t.Errorf("生产订单 %s 的供应组:%s 不存在!", wotab.Workordernr, wotab.Supplygroupid)
  338. session.Rollback()
  339. return
  340. }
  341. // 头枕走特殊逻辑
  342. if sgtab.Sgtype == common.SG_TYPE_CHILD {
  343. }
  344. // 初始化
  345. bl_pakord = service.BL_PackOrder{}
  346. session = db.G_DbEngine.NewSession()
  347. defer session.Close()
  348. if err = session.Begin(); err != nil {
  349. return
  350. }
  351. // 基于checksequence和工单的供应组ID查找包装单
  352. if exist, bl_pakord, err = cfProj.GetPackOrderByCheckSequenceSupplyGroup(session, cflandtablst[j].Checksequence, wotab.Supplygroupid); err != nil{
  353. t.Errorf("无法获取checksequence %d 的包装订单,原因是:%v", cflandtablst[j].Checksequence, err)
  354. session.Rollback()
  355. return
  356. }
  357. if exist{
  358. fmt.Println("基于CheckSeq获取到包装单:",bl_pakord.PackorderId)
  359. }
  360. // 基于OEMSEQ和工单的供应组ID查找包装单
  361. if !exist {
  362. if exist, bl_pakord, err = cfProj.GetPackOrderByOemseqSupplyGroup(session, wotab); err != nil{
  363. t.Errorf("无法获取工单 %s 的包装订单,原因是:%v", wotab.Workordernr, err)
  364. session.Rollback()
  365. return
  366. }
  367. }
  368. // 不存在则新建包装单
  369. if !exist {
  370. if bl_pakordlst, err = cfProj.CreatePackOrderByCheckSeqWO(session, cflandtablst[j], wotab); err != nil {
  371. fmt.Println("创建开口包装单失败,原因:", err)
  372. session.Rollback()
  373. continue
  374. }
  375. // 获取当前OEMSEQ 或 checksequence的包装单
  376. ok = false
  377. for m = 0; m < len(bl_pakordlst); m++ {
  378. for n = 0; n < len(bl_pakordlst[m].Pkotab.Itemlst); n++ {
  379. if (bl_pakordlst[m].Pkotab.Itemlst[n].Supplygroupid == wotab.Supplygroupid) && ( bl_pakordlst[m].Pkotab.Itemlst[n].Oemseq == common.ValueToInt(wotab.Oemseq, 0) || bl_pakordlst[m].Pkotab.Itemlst[n].Seq == cflandtablst[j].Checksequence ) {
  380. ok = true
  381. bl_pakord = bl_pakordlst[m]
  382. break
  383. }
  384. }
  385. if ok {
  386. break
  387. }
  388. }
  389. if !ok {
  390. fmt.Println("无法为当前工单找到包装单!")
  391. continue
  392. }
  393. }
  394. // 将工单加入到当前包装单
  395. if ok, err = cfProj.AddWOToPackOrder(wotab, cflandtablst[j].Checksequence, &bl_pakord, session); err != nil{
  396. t.Errorf("添加工单 %s 到包装单 %s 出错,原因是 %v", wotab.Workordernr,bl_pakord.PackorderId, err)
  397. session.Rollback()
  398. return
  399. }
  400. /**bl_pakord.RefreshFillStatus()
  401. fmt.Println("OEMSEQ count = ",bl_pakord.OemseqCount," CheckSeq count = ",bl_pakord.SeqCount)
  402. for n = 0; n < len(bl_pakord.Pkotab.Itemlst); n++ {
  403. fmt.Println(n,"-",bl_pakord.Pkotab.Itemlst[n].Oemseq,"--",bl_pakord.Pkotab.Itemlst[n].Seq)
  404. }**/
  405. if ok {
  406. fmt.Println("成功添加工单",wotab.Workordernr,"到包装单",bl_pakord.PackorderId)
  407. // 关闭当前包装
  408. if relstat, err = cfProj.ReleasePackOrder(session, bl_pakord); err != nil{
  409. t.Errorf("下达包装单 %s 出错,原因是 %v", bl_pakord.PackorderId, err)
  410. session.Rollback()
  411. return
  412. }
  413. if relstat{
  414. fmt.Println("成功下达包装单",bl_pakord.PackorderId)
  415. }
  416. }
  417. session.Commit()
  418. }
  419. session = db.G_DbEngine.NewSession()
  420. defer session.Close()
  421. if err = session.Begin(); err != nil {
  422. return
  423. }
  424. // 更新客户订单Call off相关信息
  425. bl_co.Custordertab.Calloffnr = cflandtablst[j].Calloffnr
  426. bl_co.Custordertab.Calloffswet = cflandtablst[j].Swet
  427. bl_co.Custordertab.Checksequence = cflandtablst[j].Checksequence
  428. bl_co.Custordertab.Consumecompany = cflandtablst[j].Consumecompany
  429. bl_co.Custordertab.Consumeplant = cflandtablst[j].Consumeplant
  430. bl_co.Custordertab.Consigneecompany = cflandtablst[j].Consigneecompany
  431. bl_co.Custordertab.Consigneeplant = cflandtablst[j].Consigneeplant
  432. bl_co.Custordertab.Vehicleidset = cflandtablst[j].Vehicleidset
  433. bl_co.Custordertab.Vehicleid = cflandtablst[j].Vehicleid
  434. bl_co.Custordertab.Unloadingplace = cflandtablst[j].Unloadingplace
  435. bl_co.Custordertab.Lastmodif = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
  436. if err = bl_co.Custordertab.UpdateFields(session, "calloffnr, calloffswet, checksequence, consumecompany, consumeplant, consigneecompany, consigneeplant, vehicleidset, vehicleid, unloadingplace, lastmodif"); err != nil {
  437. t.Errorf("Failed to update custordertab due to %v", err)
  438. session.Rollback()
  439. return
  440. }
  441. // calloff 客户订单成功,将landdata置位
  442. cflandtablst[j].Handlestatus = common.CO_PARSE_STATUS_OK
  443. cflandtablst[j].Parsed = common.EDI_PARSE_YES
  444. cflandtablst[j].Lastmodif = common.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
  445. if err = cflandtablst[j].UpdateFields(session, "parsed,handlestatus, lastmodif"); err != nil {
  446. t.Errorf("Failed to update parse status due to %v", err)
  447. session.Rollback()
  448. return
  449. }
  450. session.Commit()
  451. }
  452. }
  453. }
  454. // 将26下达的包装单加载到发运车中,系统根据实际加载情况
  455. func TestGenerateDeliveryCar(t *testing.T) {
  456. var (
  457. connstring string
  458. err error
  459. i, j, idx int
  460. projtab db.Me_project
  461. projtablst []db.Me_project
  462. pkotab db.Jit_packorder
  463. pkotablst []db.Jit_packorder
  464. cfProj service.CalloffProject
  465. bl_sco service.BL_ShipcarOrder
  466. bl_scolst []service.BL_ShipcarOrder
  467. fillable, canfix, canrelease bool
  468. shiptplid string
  469. session *xorm.Session
  470. )
  471. // 连接数据库
  472. connstring = fmt.Sprintf("server=%s;user id=%s;password=%s;database=%s;port=%d;encrypt=disable",
  473. `localhost`, "lapp", "123fis", "SJA_APS", 1433)
  474. if err = db.InitMssqlDb(connstring); err != nil {
  475. t.Errorf("Failed to connect db due to: %v", err)
  476. return
  477. }
  478. defer db.G_DbEngine.Close()
  479. projtab = db.Me_project{}
  480. if projtablst, err = projtab.GetAllActive(); err != nil {
  481. t.Errorf("Failed to get project list!")
  482. return
  483. }
  484. for i, _ = range projtablst {
  485. cfProj = service.CalloffProject{}
  486. cfProj.Projecttab = projtablst[i]
  487. cfProj.Projectid = projtablst[i].Projectid
  488. fmt.Println("Ready to load data for project:", projtablst[i].Projectid)
  489. // 读取项目的包装类型主数据
  490. if err = cfProj.LoadPackageType(); err != nil {
  491. t.Errorf("Failed to load project package type data due to: %v!", err)
  492. return
  493. }
  494. // 读取项目的发运车模板主数据
  495. if err = cfProj.LoadShipCarTemplate(); err != nil {
  496. t.Errorf("Failed to load project ship car data due to: %v!", err)
  497. return
  498. }
  499. // 循环读取状态>=26已下达且未装车的包装单
  500. pkotab = db.Jit_packorder{}
  501. if pkotablst, err = pkotab.GetUnloadedPackOrders(cfProj.Projectid); err != nil {
  502. t.Errorf("Failed to load project unloaded pack orders due to: %v!", err)
  503. return
  504. }
  505. // 遍历包装单
  506. for j = 0; j < len(pkotablst); j++ {
  507. // 判断状态
  508. if pkotablst[j].Status < common.PKO_STATUS_PLANNED || pkotablst[j].Loadstatus == common.PKO_STATUS_LOADED {
  509. continue
  510. }
  511. // 获取开口发运车订单并添加到发运车中
  512. if bl_scolst, err = cfProj.GetOpenShipCarOrder(); err != nil {
  513. t.Errorf("Failed to get open car orders due to: %v!", err)
  514. return
  515. }
  516. session = db.G_DbEngine.NewSession()
  517. defer session.Close()
  518. if err = session.Begin(); err != nil {
  519. return
  520. }
  521. // 匹配所有可用模板计算各包装项最大装载量并与已填充量比较,确认是否可以继续填充 => 有可用发运车
  522. if len(bl_scolst) > 0 {
  523. fillable, idx = cfProj.CheckOpenCarOrdersForPackOrder(bl_scolst, pkotablst[j])
  524. }
  525. bl_sco = service.BL_ShipcarOrder{}
  526. // 如果有适配的开口发运车
  527. if len(bl_scolst) > 0 && fillable {
  528. bl_sco.Shiporderid = bl_scolst[idx].Shiporderid
  529. if err = bl_sco.AddPackOrder(session, pkotablst[j]); err != nil {
  530. t.Errorf("Failed to add packorder %s into shipcar order %s due to: %v!",
  531. pkotablst[j].Packorderid, bl_scolst[idx].Shiporderid, err)
  532. session.Rollback()
  533. session.Close()
  534. return
  535. }
  536. } else {
  537. // 如果没有开口发运车,则创建发运车并添加
  538. if bl_sco, err = cfProj.CreateShipCarOrder(session); err != nil {
  539. t.Errorf("Failed to create shipcar order due to: %v!", err)
  540. session.Rollback()
  541. session.Close()
  542. return
  543. }
  544. if err = bl_sco.AddPackOrder(session, pkotablst[j]); err != nil {
  545. t.Errorf("Failed to add packorder %s into shipcar order %s due to: %v!",
  546. pkotablst[j].Packorderid, bl_sco.Shiporderid, err)
  547. session.Rollback()
  548. session.Close()
  549. return
  550. }
  551. }
  552. // 获取发运车最新的数据
  553. if err = bl_sco.GetOrderDataBySession(session); err != nil {
  554. t.Errorf("Failed to get ship order %s data!", bl_sco.Shiporderid)
  555. session.Rollback()
  556. session.Close()
  557. return
  558. }
  559. // 检查发运车是否可以指定模板,状态从10 -> 20
  560. if bl_sco.Spordtab.Status < common.SPO_STATUS_PLANNED {
  561. cfProj.InitShipOrderWorkoload(&bl_sco)
  562. cfProj.RecalShipItemWorkloadMaxQty(&bl_sco)
  563. if canfix, shiptplid, err = cfProj.IsShipcarOrderFixTemplate(&bl_sco); err != nil {
  564. t.Errorf("Failed to check shiporder fixable due to %v!", err)
  565. session.Rollback()
  566. session.Close()
  567. return
  568. }
  569. if canfix {
  570. // 释放发运车并更新匹配的模板
  571. if err = cfProj.FixShipCarOrderTemplate(session, &bl_sco, shiptplid); err != nil {
  572. t.Errorf("Failed to release ship car order!")
  573. session.Rollback()
  574. session.Close()
  575. return
  576. }
  577. }
  578. }
  579. // 检查发运车是否达到上限可关闭,状态从20 -> 26
  580. if canrelease, err = cfProj.IsShipcarOrderReleasable(&bl_sco); err != nil {
  581. t.Errorf("Failed to check shiporder releasable due to %v!", err)
  582. session.Rollback()
  583. session.Close()
  584. return
  585. }
  586. if canrelease {
  587. // 释放发运车并更新匹配的模板
  588. if err = cfProj.ReleaseShipCarOrder(session, &bl_sco); err != nil {
  589. t.Errorf("Failed to release ship car order!")
  590. session.Rollback()
  591. session.Close()
  592. return
  593. }
  594. }
  595. session.Commit()
  596. session.Close()
  597. }
  598. }
  599. }