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.

530 lines
15 KiB

  1. package calloff
  2. import (
  3. "errors"
  4. "fmt"
  5. "leit.com/leit_seat_aps/common"
  6. "strconv"
  7. "strings"
  8. "time"
  9. )
  10. // SEQ 数据交换头
  11. type UNB struct {
  12. Sender string // 发送方
  13. Reciever string // 接收方
  14. MsgTime time.Time // 消息时间
  15. MsgCtrlPara string // 消息交互控制参数
  16. ParseString string // 原始消息数据串
  17. }
  18. // CALLOFF 数据消息头
  19. type UNH struct {
  20. MsgId string // 消息标识ID
  21. MsgType string // 消息类型 DELJIT
  22. MsgTypeVersion string // 消息类型版本号
  23. MsgTypeRelNo string // 消息类型版本释放号
  24. ParseString string // 原始数据串
  25. }
  26. // CALLOFF 数据消息开始
  27. type BGM struct {
  28. MessageType int // 消息类型 30 = TOD / 221 = SEQ / 36 = CALLOFF
  29. DeliveryPlant int // 发运目标工厂 92 = BBA
  30. CheckSequence string // 检查排序号
  31. ParseString string // 原始数据串
  32. }
  33. // CALLOFF 数据消息日期时间信息
  34. type DTM struct {
  35. DateTimeType int // 137 = 消息日期 / 42 = 计划开始装配时间 / 2 = SWET 客户要求的来料时间
  36. DateTimeFormat int // 日期时间格式:203 = CCYYMMDDHHMM / 204 = CCYYMMDDHHMMSS
  37. MsgTime time.Time // 消息时间
  38. MsgTimeFormat string // 消息时间格式
  39. ParseString string // 原始数据串
  40. }
  41. // CALLOFF 参考信息
  42. type RFF struct {
  43. RefType string // CALLOFF = AAN / PARTFAMILY = ZZZ
  44. CallOffNum string // 发运排序号
  45. PartFamily string // 零件族
  46. ParseString string // 原始数据串
  47. }
  48. // CALLOFF 数据消息名称地址信息
  49. type NAD struct {
  50. Consignee string // 收货人
  51. ConsigneePlant int // 收货厂编号 10 = Dadong / 66 = Shengbei / 88 = Tiexi
  52. ConsigneeCompany int // 收货公司编号 92 = BBA
  53. ParseString string // 原始数据串
  54. }
  55. // CALLOFF 地点信息
  56. // LOC+4+PD::92:00+PC::92:10’
  57. // Location + 4=goods receipt place + PD=place of unloading :: 92 = BBA: Place of unloading
  58. // + PC=place of consumption :: 92 = BBA : Place of consumption
  59. type LOC struct {
  60. LocType int // 44 = 文档发出地 / 83 = 货物发运地 / 4 = 收货地
  61. UnloadingPlace string // 卸货地点
  62. ConsumeCompany int // 使用公司
  63. ConsumePlant int // 使用工厂
  64. ParseString string // 原始数据串
  65. }
  66. // CALLOFF 排序号
  67. type SEQ struct {
  68. SeqType int // 3=新建;1=变更;2=取消
  69. Gir GIR
  70. ParseString string // 原始数据串
  71. }
  72. // CALLOFF 排序订单相关信息
  73. // 示例:GIR+4+43738111:AN+4173’
  74. // Related Identification Numbers + 4=vehicle identification set
  75. // + EINSTEIN order number : AN=Manufacturing reference number
  76. // + Data string with free format vehicle identification = last 4 digits of check sequence number
  77. // out of BGM segment (BGM+36::92+00014173’) It can be used as vehicle identification like VIN in production release message
  78. type GIR struct {
  79. VehicleIdSet string // 车辆识别集
  80. CustOrderNr string // 客户订单号
  81. VehicleId string // 车辆识别号
  82. ParseString string // 原始数据串
  83. }
  84. // CALLOFF 数据消息尾
  85. type UNT struct {
  86. DataRows int // 数据行数,从UNH到UNT总数
  87. MsgId string // 消息标识
  88. ParseString string // 原始数据串
  89. }
  90. // CALLOFF 数据交换结束符
  91. type UNZ struct {
  92. MsgCount int // 消息数
  93. MsgRefId string // 消息参考号
  94. ParseString string // 原始数据串
  95. }
  96. // CALLOFF 消息对象
  97. type CALLOFF struct {
  98. FileName string // TOD文件名
  99. DataRows int // 包含数据行 UNH->UNT
  100. Unb UNB // 数据交换头
  101. Unh UNH // 数据消息头
  102. Bgm BGM // 数据消息开始
  103. DtmMsg DTM // 数据消息日期时间信息
  104. DtmDelivery DTM // 发运时间信息
  105. RffCF RFF // 参考信息: 发运Calloff号
  106. RffPF RFF // 参考信息:发运的PartFamily号
  107. Nad NAD // 数据消息名称地址信息
  108. Loc LOC // 地址信息
  109. SeqList []SEQ // 数据消息的零件族信息:零件、零件族、供应组、数量等信息
  110. Unt UNT // 数据消息尾
  111. Unz UNZ // 数据消息交换结束
  112. }
  113. func (unb *UNB) Parse(parseString string) (err error) {
  114. var (
  115. kvlist []string
  116. kv4 []string
  117. )
  118. // 输入为空,返回错误
  119. if strings.TrimSpace(parseString) == "" {
  120. return errors.New("UNB: parse string is empty!")
  121. }
  122. // 基于+分隔符来解析字符串
  123. kvlist = strings.Split(parseString, "+")
  124. if len(kvlist) < 5 {
  125. return errors.New("UNB: Key value length less than 5, failed to parse!")
  126. }
  127. kv4 = strings.Split(kvlist[4], ":")
  128. if len(kv4) < 2 {
  129. return errors.New("UNB: Key4 value length less than 2, failed to parse!")
  130. }
  131. // 填充值
  132. unb.Sender = kvlist[2] // 发送方
  133. unb.Reciever = kvlist[3] // 接收方
  134. if unb.MsgTime, err = common.DateParse(kv4[0]+kv4[1], "ymdHi"); err != nil {
  135. return errors.New("UNB: Failed to get the MsgTime!")
  136. }
  137. unb.MsgCtrlPara = kvlist[5] // 消息控制参数
  138. unb.ParseString = parseString
  139. // 校验关键字段是否为空
  140. if strings.TrimSpace(unb.Sender) == "" {
  141. return errors.New("UNB: Sender is empty!")
  142. }
  143. if strings.TrimSpace(unb.Reciever) == "" {
  144. return errors.New("UNB: Reciever is empty!")
  145. }
  146. return
  147. }
  148. func (unb *UNB) Print() {
  149. fmt.Println("UNB | Sender:", unb.Sender, " | Reciever:", unb.Reciever, " | MsgTime:", unb.MsgTime, " | MsgCtrlPara:", unb.MsgCtrlPara)
  150. }
  151. func (unh *UNH) Parse(parseString string) (err error) {
  152. var (
  153. kvlist []string
  154. kv2 []string
  155. )
  156. // 输入为空,返回错误
  157. if strings.TrimSpace(parseString) == "" {
  158. return errors.New("UNH: parse string is empty!")
  159. }
  160. // 基于+分隔符来解析字符串
  161. kvlist = strings.Split(parseString, "+")
  162. kv2 = strings.Split(kvlist[2], ":")
  163. if len(kv2) < 3 {
  164. return errors.New("UNH: kv2 value length less than 3, failed to parse!")
  165. }
  166. // 填充值
  167. unh.MsgId = kvlist[1] // 消息ID
  168. unh.MsgType = kv2[0] // 消息类型
  169. unh.MsgTypeVersion = kv2[1]
  170. unh.MsgTypeRelNo = kv2[2]
  171. unh.ParseString = parseString
  172. // 校验关键字段是否为空
  173. if strings.TrimSpace(unh.MsgId) == "" {
  174. return errors.New("UNH: MsgId is empty!")
  175. }
  176. if strings.TrimSpace(unh.MsgType) == "" {
  177. return errors.New("UNH: MsgType is empty!")
  178. }
  179. if strings.ToUpper(strings.TrimSpace(unh.MsgType)) != "DELJIT" {
  180. return errors.New("UNH: MsgType is not DELJIT!")
  181. }
  182. return
  183. }
  184. func (unh *UNH) Print() {
  185. fmt.Println("UNH | MsgId:", unh.MsgId, " | MsgType:", unh.MsgType)
  186. }
  187. // 示例:BGM+36::92+00200557'
  188. // 解析:+37生产下达36发运CallOff::92BBA+检查排序号(允许供应商检查所有请求已接收)
  189. func (bgm *BGM) Parse(parseString string) (err error) {
  190. var (
  191. kvlist []string
  192. kv1 []string
  193. )
  194. // 输入为空,返回错误
  195. if strings.TrimSpace(parseString) == "" {
  196. return errors.New("BGM: parse string is empty!")
  197. }
  198. // 基于+分隔符来解析字符串
  199. kvlist = strings.Split(parseString, "+")
  200. kv1 = strings.Split(kvlist[1], ":")
  201. if len(kv1) < 3 {
  202. return errors.New("BGM: kv1 value length less than 3, failed to parse!")
  203. }
  204. // 填充值
  205. bgm.MessageType, _ = strconv.Atoi(kv1[0]) // 30=TOD;37生产下达 36发运 242=SEQ
  206. bgm.DeliveryPlant, _ = strconv.Atoi(kv1[2]) // 92 = BBA
  207. bgm.CheckSequence = kvlist[2] // 检查排序号
  208. bgm.ParseString = parseString
  209. // 校验关键字段是否为空
  210. if strings.TrimSpace(bgm.CheckSequence) == "" {
  211. return errors.New("BGM: CheckSequence is empty!")
  212. }
  213. return
  214. }
  215. func (bgm *BGM) Print() {
  216. fmt.Println("BGM | CheckSequence:", bgm.CheckSequence)
  217. }
  218. // 消息文档时间:DTM+137:200902201510:203'
  219. // 发运时间信息:DTM+2:200902231011:203' OR DTM+2:20090223101159:204'
  220. func (dtm *DTM) Parse(parseString string) (err error) {
  221. var (
  222. kvlist []string
  223. kv1 []string
  224. )
  225. // 输入为空,返回错误
  226. if strings.TrimSpace(parseString) == "" {
  227. return errors.New("DTM: parse string is empty!")
  228. }
  229. // 基于+分隔符来解析字符串
  230. kvlist = strings.Split(parseString, "+")
  231. kv1 = strings.Split(kvlist[1], ":")
  232. if len(kv1) < 3 {
  233. return errors.New("DTM: kv1 value length less than 3, failed to parse!")
  234. }
  235. // 填充值
  236. dtm.DateTimeType, _ = strconv.Atoi(kv1[0]) // 时间格式
  237. dtm.DateTimeFormat, _ = strconv.Atoi(kv1[2])
  238. dtm.MsgTimeFormat = common.GetTimeFormatByType(dtm.DateTimeFormat)
  239. if dtm.MsgTime, err = common.DateParse(kv1[1], dtm.MsgTimeFormat); err != nil {
  240. return errors.New("DTM: Failed to get the MsgTime!")
  241. }
  242. dtm.ParseString = parseString
  243. // 校验关键字段是否为空
  244. if strings.TrimSpace(dtm.MsgTimeFormat) == "" {
  245. return errors.New("DTM: MsgTimeFormat is empty!")
  246. }
  247. return
  248. }
  249. func (dtm *DTM) Print() {
  250. fmt.Println("DTM | DateTimeType:", dtm.DateTimeType, " | DateTimeFormat:", dtm.DateTimeFormat, " | MsgTime:", dtm.MsgTime)
  251. }
  252. // RFF+AAN:131642' => +AAN(Delivery CallOff号):131553
  253. // RFF+ZZZ:STFKBR3 ' =>+ZZZ:零件族号(<8位)
  254. func (rff *RFF) Parse(parseString string) (err error) {
  255. var (
  256. kvlist []string
  257. kv1 []string
  258. )
  259. // 输入为空,返回错误
  260. if strings.TrimSpace(parseString) == "" {
  261. return errors.New("RFF: parse string is empty!")
  262. }
  263. // 基于+分隔符来解析字符串
  264. kvlist = strings.Split(parseString, "+")
  265. kv1 = strings.Split(kvlist[1], ":")
  266. if len(kv1) < 2 {
  267. return errors.New("RFF: kv1 value length less than 2, failed to parse!")
  268. }
  269. // 填充值
  270. rff.ParseString = parseString
  271. switch strings.TrimSpace(kv1[0]) {
  272. case "AAN":
  273. rff.RefType = "CALLOFF"
  274. rff.CallOffNum = kv1[1]
  275. if strings.TrimSpace(rff.CallOffNum) == "" {
  276. return errors.New("RFF: CallOffNum is empty!")
  277. }
  278. case "ZZZ":
  279. rff.RefType = "PARTFAMILY"
  280. rff.PartFamily = kv1[1] // 零件族
  281. if strings.TrimSpace(rff.PartFamily) == "" {
  282. return errors.New("RFF: Partfamily is empty!")
  283. }
  284. default:
  285. }
  286. return
  287. }
  288. func (rff *RFF) Print() {
  289. fmt.Println("RFF | CallOffNum:", rff.CallOffNum, "| Partfamily:", rff.PartFamily)
  290. }
  291. // 示例:NAD+CN+88::92
  292. func (nad *NAD) Parse(parseString string) (err error) {
  293. var (
  294. kvlist []string
  295. kv2 []string
  296. )
  297. // 输入为空,返回错误
  298. if strings.TrimSpace(parseString) == "" {
  299. return errors.New("NAD: parse string is empty!")
  300. }
  301. // 基于+分隔符来解析字符串
  302. kvlist = strings.Split(parseString, "+")
  303. kv2 = strings.Split(kvlist[2], ":")
  304. if len(kv2) < 1 {
  305. return errors.New("NAD: kv2 value length less than 1, failed to parse!")
  306. }
  307. // 填充值
  308. nad.Consignee = kvlist[1] // 收货人
  309. nad.ConsigneePlant, _ = strconv.Atoi(kv2[0]) // 收货厂编号 10=Dadong,66=Shengbei;88=Tiexi
  310. nad.ConsigneeCompany, _ = strconv.Atoi(kv2[2]) // 收货公司编号 92 = BBA
  311. nad.ParseString = parseString
  312. // 校验关键字段是否为空
  313. if strings.TrimSpace(nad.Consignee) == "" {
  314. return errors.New("NAD: Consignee is empty!")
  315. }
  316. if nad.ConsigneePlant <= 0 {
  317. return errors.New("NAD: ConsigneePlant is not existing!")
  318. }
  319. if nad.ConsigneeCompany <= 0 {
  320. return errors.New("NAD: ConsigneeCompany is not existing!")
  321. }
  322. return
  323. }
  324. func (nad *NAD) Print() {
  325. fmt.Println("NAD | Consignee:", nad.Consignee, " | ConsigneePlant:", nad.ConsigneePlant, " | ConsigneeCompany:", nad.ConsigneeCompany)
  326. }
  327. // 示例1:LOC+4+PD::92:00+PC::92:88'
  328. // +4收货地点标识+PD卸货地点::92BBA:00+PC消耗地点::92BBA:88Tiexi
  329. func (loc *LOC) Parse(parseString string) (err error) {
  330. var (
  331. kvlist []string
  332. kv2 []string
  333. kv3 []string
  334. )
  335. // 输入为空,返回错误
  336. if strings.TrimSpace(parseString) == "" {
  337. return errors.New("LOC: parse string is empty!")
  338. }
  339. // 基于+分隔符来解析字符串
  340. kvlist = strings.Split(parseString, "+")
  341. kv2 = strings.Split(kvlist[2], ":")
  342. if len(kv2) < 4 {
  343. return errors.New("LOC: kv2 value length less than 4, failed to parse!")
  344. }
  345. kv3 = strings.Split(kvlist[3], ":")
  346. if len(kv3) < 4 {
  347. return errors.New("LOC: kv3 value length less than 4, failed to parse!")
  348. }
  349. // 填充值
  350. loc.LocType, _ = strconv.Atoi(kvlist[1]) // 44 = 文档发出地 / 83 = 货物发运地 / 4 = 收货地
  351. loc.UnloadingPlace = kv2[2]
  352. loc.ConsumeCompany, _ = strconv.Atoi(kv3[2])
  353. loc.ConsumePlant, _ = strconv.Atoi(kv3[3])
  354. loc.ParseString = parseString
  355. // 校验关键字段是否为空
  356. if loc.LocType <= 0 {
  357. return errors.New("LOC: LocType is empty!")
  358. }
  359. return
  360. }
  361. func (loc *LOC) Print() {
  362. fmt.Println("LOC | LocType:", loc.LocType, " | UnloadingPlace:", loc.UnloadingPlace, " | ConsumeCompany:", loc.ConsumeCompany, " | ConsumePlantSite:", loc.ConsumePlant)
  363. }
  364. // 示例:SEQ+3’
  365. func (seq *SEQ) Parse(parseString string) (err error) {
  366. var (
  367. kvlist []string
  368. )
  369. // 输入为空,返回错误
  370. if strings.TrimSpace(parseString) == "" {
  371. return errors.New("SEQ: parse string is empty!")
  372. }
  373. // 基于+分隔符来解析字符串
  374. kvlist = strings.Split(parseString, "+")
  375. // 填充值
  376. seq.SeqType, _ = strconv.Atoi(kvlist[1]) // 3=新建;1=更新;2=取消
  377. seq.ParseString = parseString
  378. // 校验关键字段是否为空
  379. if seq.SeqType < 1 || seq.SeqType > 3 {
  380. return errors.New("SEQ: Unvalid seq type!")
  381. }
  382. return
  383. }
  384. func (seq *SEQ) Print() {
  385. fmt.Println("SEQ | SEQ + ", seq.SeqType)
  386. }
  387. // 示例:GIR+4+69472141:AN+0557'
  388. // +4车辆识别集+订单号订单类型(最后一位是订单类型):AN+车辆识别的自由文本
  389. func (gir *GIR) Parse(parseString string) (err error) {
  390. var (
  391. kvlist []string
  392. kv2 []string
  393. )
  394. // 输入为空,返回错误
  395. if strings.TrimSpace(parseString) == "" {
  396. return errors.New("GIR: parse string is empty!")
  397. }
  398. // 基于+分隔符来解析字符串
  399. // GIR+1+00024391:AQ+00000966:ML+12373531:AN + GX38594 : VN
  400. kvlist = strings.Split(parseString, "+")
  401. kv2 = strings.Split(kvlist[2], ":")
  402. if len(kv2) < 2 {
  403. return errors.New("GIR: kv2 value length less than 2, failed to parse!")
  404. }
  405. // 填充值
  406. gir.VehicleIdSet = kvlist[1] // 车辆识别集
  407. gir.CustOrderNr = kv2[0] // 客户订单号
  408. gir.VehicleId = kvlist[3] // 车辆识别号
  409. gir.ParseString = parseString
  410. // 校验关键字段是否为空
  411. if strings.TrimSpace(gir.CustOrderNr) == "" {
  412. return errors.New("GIR: CustOrderNr is empty!")
  413. }
  414. if strings.TrimSpace(gir.VehicleId) == "" {
  415. return errors.New("GIR: VehicleId is empty!")
  416. }
  417. return
  418. }
  419. func (gir *GIR) Print() {
  420. fmt.Println("GIR | CustOrderNr:", gir.CustOrderNr, " | VehicleId:", gir.VehicleId)
  421. }
  422. func (unt *UNT) Parse(parseString string) (err error) {
  423. var (
  424. kvlist []string
  425. )
  426. // 输入为空,返回错误
  427. if strings.TrimSpace(parseString) == "" {
  428. return errors.New("UNT: parse string is empty!")
  429. }
  430. // 基于+分隔符来解析字符串
  431. kvlist = strings.Split(parseString, "+")
  432. // 填充值
  433. if unt.DataRows, err = strconv.Atoi(kvlist[1]); err != nil {
  434. return errors.New("UNT: Failed to get data rows!")
  435. }
  436. unt.MsgId = kvlist[2]
  437. unt.ParseString = parseString
  438. // 校验关键字段是否为空
  439. if strings.TrimSpace(unt.MsgId) == "" {
  440. return errors.New("UNT: MsgId is empty!")
  441. }
  442. return
  443. }
  444. func (unt *UNT) Print() {
  445. fmt.Println("UNT | MsgId:", unt.MsgId, " | DataRows:", unt.DataRows)
  446. }
  447. func (unz *UNZ) Parse(parseString string) (err error) {
  448. var (
  449. kvlist []string
  450. )
  451. // 输入为空,返回错误
  452. if strings.TrimSpace(parseString) == "" {
  453. return errors.New("UNZ: parse string is empty!")
  454. }
  455. // 基于+分隔符来解析字符串
  456. kvlist = strings.Split(parseString, "+")
  457. // 填充值
  458. if unz.MsgCount, err = strconv.Atoi(kvlist[1]); err != nil {
  459. return errors.New("UNZ: Failed to get message count!")
  460. }
  461. unz.MsgRefId = kvlist[2]
  462. unz.ParseString = parseString
  463. // 校验关键字段是否为空
  464. if strings.TrimSpace(unz.MsgRefId) == "" {
  465. return errors.New("UNZ: MsgRefId is empty!")
  466. }
  467. return
  468. }
  469. func (unz *UNZ) Print() {
  470. fmt.Println("UNZ | MsgRefId:", unz.MsgRefId, " | MsgCount:", unz.MsgCount)
  471. }