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.
 
 
 
 
 

570 lines
31 KiB

  1. package com.ffii.fpsms.m18.service
  2. import com.ffii.core.utils.JwtTokenUtil
  3. import com.ffii.fpsms.api.service.ApiCallerService
  4. import com.ffii.fpsms.m18.M18Config
  5. import com.ffii.fpsms.m18.enums.M18DataLogStatus
  6. import com.ffii.fpsms.m18.model.*
  7. import com.ffii.fpsms.m18.model.SyncResult
  8. import com.ffii.fpsms.m18.utils.CommonUtils
  9. import com.ffii.fpsms.m18.web.models.M18CommonRequest
  10. import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderLineStatus
  11. import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatus
  12. import com.ffii.fpsms.modules.deliveryOrder.service.DeliveryOrderLineService
  13. import com.ffii.fpsms.modules.deliveryOrder.service.DeliveryOrderService
  14. import com.ffii.fpsms.modules.deliveryOrder.entity.DeliveryOrderRepository
  15. import com.ffii.fpsms.modules.deliveryOrder.web.models.SaveDeliveryOrderLineRequest
  16. import com.ffii.fpsms.modules.deliveryOrder.web.models.SaveDeliveryOrderRequest
  17. import com.ffii.fpsms.modules.master.entity.ItemUom
  18. import com.ffii.fpsms.modules.master.service.ItemUomService
  19. import com.ffii.fpsms.modules.master.service.ItemsService
  20. import com.ffii.fpsms.modules.master.service.ShopService
  21. import com.ffii.fpsms.modules.master.web.models.ConvertUomByItemRequest
  22. import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderType
  23. import org.slf4j.Logger
  24. import org.slf4j.LoggerFactory
  25. import org.springframework.stereotype.Service
  26. import java.sql.SQLException
  27. import java.time.LocalDateTime
  28. import java.time.format.DateTimeFormatter
  29. import kotlin.reflect.full.memberProperties
  30. import kotlin.text.substring
  31. @Service
  32. open class M18DeliveryOrderService(
  33. val m18Config: M18Config,
  34. val apiCallerService: ApiCallerService,
  35. val m18DataLogService: M18DataLogService,
  36. val deliveryOrderService: DeliveryOrderService,
  37. val deliveryOrderRepository: DeliveryOrderRepository,
  38. val deliveryOrderLineService: DeliveryOrderLineService,
  39. val itemsService: ItemsService,
  40. val shopService: ShopService,
  41. val itemUomService: ItemUomService,
  42. val m18MasterDataService: M18MasterDataService,
  43. ) {
  44. val commonUtils = CommonUtils()
  45. val logger: Logger = LoggerFactory.getLogger(JwtTokenUtil::class.java)
  46. val lastModifyDateStart = "2025-05-14 14:00:00"
  47. val lastModifyDateEnd = "2025-05-14 14:30:00"
  48. // val lastModifyDateConds =
  49. // "lastModifyDate=largerOrEqual=${lastModifyDateStart}=and=lastModifyDate=lessOrEqual=${lastModifyDateEnd}"
  50. // val lastModifyDate = LocalDateTime.now().minusMinutes(30)
  51. // val commonConds =
  52. // "(beId=equal=${m18Config.BEID_PF}=or=beId=equal=${m18Config.BEID_PP}=or=beId=equal=${m18Config.BEID_TOA})=and=lastModifyDate=largerOrEqual=${lastModifyDate}"
  53. // M18 API
  54. // Sharing same API with po
  55. val M18_LOAD_PURCHASE_ORDER_API = "/root/api/read/po"
  56. val M18_FETCH_PURCHASE_ORDER_LIST_API = "/search/search"
  57. // Include shop po
  58. open fun getDeliveryOrdersWithType(request: M18CommonRequest): M18PurchaseOrderListResponseWithType? {
  59. val deliveryOrders = M18PurchaseOrderListResponseWithType(mutableListOf())
  60. val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
  61. val lastDateConds = if (request.modifiedDateFrom != null && request.modifiedDateTo != null) {
  62. val dateFrom = LocalDateTime.parse(request.modifiedDateFrom, formatter).toString()
  63. val dateTo = LocalDateTime.parse(request.modifiedDateTo, formatter).toString()
  64. "lastModifyDate=largerOrEqual=$dateFrom=and=lastModifyDate=lessOrEqual=$dateTo"
  65. } else {
  66. ""
  67. }
  68. val dDateConds = if (request.dDateFrom != null && request.dDateTo != null) {
  69. val dateFrom = LocalDateTime.parse(request.dDateFrom, formatter).toLocalDate().toString()
  70. val dateTo = LocalDateTime.parse(request.dDateTo, formatter).toLocalDate().toString()
  71. "dDate=largerOrEqual=$dateFrom=and=dDate=lessOrEqual=$dateTo"
  72. } else {
  73. ""
  74. }
  75. val dDateEqualConds = if (request.dDateEqual != null) {
  76. val dDateEqual = LocalDateTime.parse(request.dDateEqual, formatter).toLocalDate().toString()
  77. "dDate=equal=$dDateEqual"
  78. } else {
  79. ""
  80. }
  81. // Shop PO
  82. val shopPoBuyers = commonUtils.listToString(listOf(m18Config.BEID_TOA), "beId=equal=", "=or=")
  83. val shopPoSupplier = commonUtils.listToString(
  84. shopService.findM18VendorIdsByCodeRegexp(m18Config.SHOP_PO_SUPPLIER),
  85. "venId=equal=",
  86. "=or="
  87. )
  88. var shopPoConds = "(${shopPoBuyers})=and=(${shopPoSupplier})"
  89. if (request.modifiedDateFrom != null && request.modifiedDateTo != null) {
  90. shopPoConds += "=and=(${lastDateConds})"
  91. }
  92. if (request.dDateFrom != null && request.dDateTo != null) {
  93. shopPoConds += "=and=(${dDateConds})"
  94. }
  95. if (request.dDateEqual != null) {
  96. shopPoConds += "=and=(${dDateEqualConds})"
  97. }
  98. logger.info("shopPoConds: ${shopPoConds}")
  99. val shopPoParams = M18PurchaseOrderListRequest(
  100. params = null,
  101. conds = shopPoConds
  102. )
  103. try {
  104. deliveryOrders.valuesWithType += Pair(
  105. PurchaseOrderType.SHOP, apiCallerService.get<M18PurchaseOrderListResponse, M18PurchaseOrderListRequest>(
  106. M18_FETCH_PURCHASE_ORDER_LIST_API,
  107. shopPoParams
  108. ).block()
  109. )
  110. } catch (e: Exception) {
  111. logger.error("(Getting Shop Po list) Error on Function - ${e.stackTrace}")
  112. logger.error(e.message)
  113. }
  114. deliveryOrders.query = shopPoConds
  115. return deliveryOrders
  116. }
  117. open fun getDeliveryOrder(id: Long): M18PurchaseOrderResponse? {
  118. val deliveryOrderParams = M18PurchaseOrderRequest(
  119. id = id
  120. )
  121. var deliveryOrder: M18PurchaseOrderResponse? = null
  122. try {
  123. deliveryOrder = apiCallerService.get<M18PurchaseOrderResponse, M18PurchaseOrderRequest>(
  124. M18_LOAD_PURCHASE_ORDER_API,
  125. deliveryOrderParams
  126. ).block()
  127. } catch (e: Exception) {
  128. logger.error("(Getting Po Detail) Error on Function - ${e.stackTrace}")
  129. logger.error(e.message)
  130. }
  131. return deliveryOrder
  132. }
  133. open fun saveDeliveryOrders(request: M18CommonRequest): SyncResult {
  134. val deliveryOrdersWithType = getDeliveryOrdersWithType(request)
  135. return saveDeliveryOrdersWithPreparedList(deliveryOrdersWithType, syncIsEtra = false)
  136. }
  137. /**
  138. * Sync a single M18 shop PO / delivery order by document [code], same search pattern as
  139. * [com.ffii.fpsms.m18.service.M18PurchaseOrderService.savePurchaseOrderByCode].
  140. *
  141. * @param isEtraSync when true, persist local `delivery_order.isEtra=true` (manual DO(加單) sync).
  142. * No M18-side "加單" filtering is used.
  143. * @param newOnly when true, skip if a non-deleted local DO already exists with the same `code`.
  144. */
  145. open fun saveDeliveryOrderByCode(
  146. code: String,
  147. isEtraSync: Boolean = false,
  148. newOnly: Boolean = false,
  149. ): SyncResult {
  150. if (newOnly && deliveryOrderRepository.existsByCodeAndDeletedIsFalse(code)) {
  151. return SyncResult(
  152. totalProcessed = 1,
  153. totalSuccess = 0,
  154. totalFail = 0,
  155. query = "skipped (newOnly=true): delivery_order.code already exists: $code",
  156. )
  157. }
  158. val conds = "(code=equal=$code)"
  159. val searchRequest = M18PurchaseOrderListRequest(
  160. stSearch = "po",
  161. params = null,
  162. conds = conds
  163. )
  164. val doListResponse = try {
  165. apiCallerService.get<M18PurchaseOrderListResponse, M18PurchaseOrderListRequest>(
  166. M18_FETCH_PURCHASE_ORDER_LIST_API,
  167. searchRequest
  168. ).block()
  169. } catch (e: Exception) {
  170. logger.error("(Getting DO list By Code) Error on Function - ${e.stackTrace}")
  171. logger.error(e.message)
  172. null
  173. }
  174. val doValues = doListResponse?.values
  175. if (doValues.isNullOrEmpty()) {
  176. return SyncResult(
  177. totalProcessed = 1,
  178. totalSuccess = 0,
  179. totalFail = 1,
  180. query = conds
  181. )
  182. }
  183. val prepared = M18PurchaseOrderListResponseWithType(
  184. valuesWithType = mutableListOf(Pair(PurchaseOrderType.SHOP, doListResponse)),
  185. query = conds
  186. )
  187. return saveDeliveryOrdersWithPreparedList(prepared, syncIsEtra = isEtraSync)
  188. }
  189. private fun saveDeliveryOrdersWithPreparedList(
  190. deliveryOrdersWithType: M18PurchaseOrderListResponseWithType?,
  191. syncIsEtra: Boolean = false,
  192. ): SyncResult {
  193. logger.info("--------------------------------------------Start - Saving M18 Delivery Order--------------------------------------------")
  194. val successList = mutableListOf<Long>()
  195. val successDetailList = mutableListOf<Long>()
  196. val failList = mutableListOf<Long>()
  197. val failDetailList = mutableListOf<Long>()
  198. val failItemDetailList = mutableListOf<Long>()
  199. val uomByM18IdCache = mutableMapOf<Long, ItemUom?>()
  200. val itemIdCache = mutableMapOf<Long, Long?>()
  201. val stockUomIdCache = mutableMapOf<Pair<Long, Long>, Long?>()
  202. val doRefType = "Delivery Order"
  203. val doLineRefType = "Delivery Order Line"
  204. if (deliveryOrdersWithType != null) {
  205. // Loop for Delivery Orders (values)
  206. deliveryOrdersWithType.valuesWithType.forEach { deliveryOrderWithType ->
  207. val type = deliveryOrderWithType.first
  208. // if success
  209. val deliveryOrdersValues = deliveryOrderWithType.second?.values
  210. // if fail
  211. val deliveryOrdersMessages = deliveryOrderWithType.second?.messages
  212. if (deliveryOrdersValues != null) {
  213. deliveryOrdersValues.forEach { deliveryOrder ->
  214. val deliveryOrderDetail = getDeliveryOrder(deliveryOrder.id)
  215. var deliveryOrderId: Long? = null //FP-MTMS
  216. // Process for Delivery Order (mainpo)
  217. // Assume only one DO in the DO (search by DO ID)
  218. val mainpo = deliveryOrderDetail?.data?.mainpo?.get(0)
  219. // logger.info("deliveryOrderDetail: data is null? ${deliveryOrderDetail?.data == null} | mainpo is null? ${deliveryOrderDetail?.data?.mainpo == null} | get(0) is null? ${deliveryOrderDetail?.data?.mainpo?.get(0) == null}")
  220. val pot = deliveryOrderDetail?.data?.pot
  221. val deliveryOrderLineMessage = deliveryOrderDetail?.messages
  222. // delivery_order + m18_data_log table
  223. if (mainpo != null) {
  224. // Find the latest m18 data log by m18 id & type
  225. // logger.info("${doRefType}: Finding For Latest M18 Data Log...")
  226. val latestDeliveryOrderLog =
  227. m18DataLogService.findLatestM18DataLogWithSuccess(deliveryOrder.id, doRefType)
  228. //logger.info(latestDeliveryOrderLog.toString())
  229. // Save to m18_data_log table
  230. // logger.info("${doRefType}: Saving for M18 Data Log...")
  231. val mainpoJson =
  232. mainpo::class.memberProperties.associate { prop -> prop.name to prop.getter.call(mainpo) }
  233. .toMutableMap()
  234. val saveM18DeliveryOrderLogRequest = SaveM18DataLogRequest(
  235. id = null,
  236. refType = doRefType,
  237. m18Id = deliveryOrder.id,
  238. m18LastModifyDate = commonUtils.timestampToLocalDateTime(mainpo.lastModifyDate),
  239. // dataLog = mainpoJson,
  240. statusEnum = M18DataLogStatus.NOT_PROCESS
  241. )
  242. val saveM18DeliveryOrderLog =
  243. m18DataLogService.saveM18DataLog(saveM18DeliveryOrderLogRequest)
  244. // logger.info("${doRefType}: Saved M18 Data Log. ID: ${saveM18DeliveryOrderLog.id}")
  245. try {
  246. // Find the delivery_order if exist
  247. // logger.info("${doRefType}: Finding exising delivery order...")
  248. val existingDeliveryOrder =
  249. latestDeliveryOrderLog?.id?.let { deliveryOrderService.findByM18DataLogId(it) }
  250. // logger.info("${doRefType}: Exising delivery order ID: ${existingDeliveryOrder?.id}")
  251. // Save to delivery_order table
  252. // logger.info("${doRefType}: Saving delivery order...")
  253. val saveDeliveryOrderRequest = SaveDeliveryOrderRequest(
  254. id = existingDeliveryOrder?.id,
  255. code = mainpo.code,
  256. m18SupplierId = mainpo.venId,
  257. m18ShopId = mainpo.virDeptId,
  258. m18CurrencyId = mainpo.curId,
  259. orderDate = commonUtils.timestampToLocalDateTime(mainpo.tDate),
  260. estimatedArrivalDate = commonUtils.timestampToLocalDateTime(mainpo.dDate),
  261. completeDate = null,
  262. status = DeliveryOrderStatus.PENDING.value,
  263. type = type.value,
  264. m18DataLogId = saveM18DeliveryOrderLog.id,
  265. handlerId = null,
  266. m18BeId = mainpo.beId,
  267. deleted = mainpo.udfIsVoid == true,
  268. isEtra = syncIsEtra,
  269. )
  270. val saveDeliveryOrderResponse =
  271. deliveryOrderService.saveDeliveryOrder(saveDeliveryOrderRequest)
  272. deliveryOrderId = saveDeliveryOrderResponse.id
  273. // Update m18_data_log with success
  274. val successSaveM18DeliveryOrderLogRequest = SaveM18DataLogRequest(
  275. id = saveM18DeliveryOrderLog.id,
  276. dataLog = mainpoJson,
  277. statusEnum = M18DataLogStatus.SUCCESS
  278. )
  279. m18DataLogService.saveM18DataLog(successSaveM18DeliveryOrderLogRequest)
  280. // log success info
  281. successList.add(deliveryOrder.id)
  282. logger.info("${doRefType}: Saved delivery order. ID: ${saveDeliveryOrderResponse.id} | M18 ${doRefType} ID: ${deliveryOrder.id}")
  283. } catch (e: Exception) {
  284. failList.add(deliveryOrder.id)
  285. // logger.error("${doRefType}: Saving Failure!")
  286. logger.error("Error on Function - ${e.stackTrace} | Type: ${doRefType} | M18 ID: ${deliveryOrder.id} | Different? ${mainpo.id}")
  287. logger.error(e.message)
  288. val errorSaveM18DeliveryOrderLogRequest = SaveM18DataLogRequest(
  289. id = saveM18DeliveryOrderLog.id,
  290. dataLog = mutableMapOf(Pair("Exception Message", e.message)),
  291. statusEnum = M18DataLogStatus.FAIL
  292. )
  293. m18DataLogService.saveM18DataLog(errorSaveM18DeliveryOrderLogRequest)
  294. // logger.error("${doRefType}: M18 Data Log Updated! Please see the error. ID: ${saveM18DeliveryOrderLogRequest.id}")
  295. }
  296. // delivery_order_line + m18_data_log
  297. if (pot != null) {
  298. val m18LineIds = pot.map { it.id }.toSet()
  299. // Loop for Delivery Order Lines (pot)
  300. pot.forEach { line ->
  301. // Find the latest m18 data log by m18 id & type
  302. // logger.info("${doLineRefType}: Finding For Latest M18 Data Log...")
  303. val latestDeliveryOrderLineLog =
  304. m18DataLogService.findLatestM18DataLogWithSuccess(line.id, doLineRefType)
  305. // logger.info("${doLineRefType}: Latest M18 Data Log ID: ${latestDeliveryOrderLineLog?.id}")
  306. // Save to m18_data_log table
  307. // logger.info("${doLineRefType}: Saving for M18 Data Log...")
  308. val lineJson =
  309. line::class.memberProperties.associate { prop ->
  310. prop.name to prop.getter.call(
  311. line
  312. )
  313. }
  314. .toMutableMap()
  315. val saveM18DeliveryOrderLineLogRequest = SaveM18DataLogRequest(
  316. id = null,
  317. refType = doLineRefType,
  318. m18Id = line.id,
  319. m18LastModifyDate = commonUtils.timestampToLocalDateTime(mainpo.lastModifyDate),
  320. // dataLog = lineJson,
  321. statusEnum = M18DataLogStatus.NOT_PROCESS
  322. )
  323. val saveM18DeliveryOrderLineLog =
  324. m18DataLogService.saveM18DataLog(saveM18DeliveryOrderLineLogRequest)
  325. // logger.info("${doLineRefType}: Saved M18 Data Log. ID: ${saveM18DeliveryOrderLineLog.id}")
  326. // logger.info("${doLineRefType}: Finding item...")
  327. val itemId: Long? = itemIdCache.getOrPut(line.proId) {
  328. val item = itemsService.findByM18Id(line.proId)
  329. if (item == null) {
  330. m18MasterDataService.saveProduct(line.proId)?.id
  331. } else {
  332. item.id
  333. }
  334. }
  335. val stockUomId: Long? = if (itemId != null) {
  336. val key = line.proId to line.unitId // safe key
  337. stockUomIdCache.getOrPut(key) {
  338. val uom = itemUomService.findByM18Id(line.unitId)
  339. itemUomService.findStockUnitByItemId(itemId)?.uom?.id
  340. }
  341. } else null
  342. // logger.info("${doLineRefType}: Item ID: ${itemId} | M18 Item ID: ${line.proId}")
  343. try {
  344. // Find the delivery_order_line if exist
  345. // logger.info("${doLineRefType}: Finding exising delivery order line...")
  346. val existingDeliveryOrderLine = latestDeliveryOrderLineLog?.id?.let {
  347. deliveryOrderLineService.findDeliveryOrderLineByM18Id(it)
  348. }
  349. // logger.info("${doLineRefType}: Exising delivery order line ID: ${existingDeliveryOrderLine?.id}")
  350. // Save to delivery_order_line table
  351. // logger.info("${doLineRefType}: Saving delivery order line...")
  352. val itemUom = uomByM18IdCache.getOrPut(line.unitId) {
  353. itemUomService.findByM18Id(line.unitId)
  354. }
  355. val saveDeliveryOrderLineRequest = SaveDeliveryOrderLineRequest(
  356. id = existingDeliveryOrderLine?.id,
  357. itemId = itemId,
  358. uomIdM18 = itemUom?.uom?.id,
  359. uomId= stockUomId,
  360. deliveryOrderId = deliveryOrderId,
  361. qtyM18 = line.qty,
  362. qty = itemUomService.convertQtyToStockQty(itemId?:0, itemUom?.uom?.id?: 0, line.qty),
  363. up = line.up,
  364. price = line.amt,
  365. // m18CurrencyId = mainpo.curId,
  366. status = existingDeliveryOrderLine?.status?.value
  367. ?: DeliveryOrderLineStatus.PENDING.value,
  368. m18DataLogId = saveM18DeliveryOrderLineLog.id,
  369. m18Discount = line.disc,
  370. m18Lot = line.lot
  371. )
  372. val saveDeliveryOrderLineResponse =
  373. deliveryOrderLineService.saveDeliveryOrderLine(saveDeliveryOrderLineRequest)
  374. // Update m18_data_log with success
  375. val successSaveM18DeliveryOrderLineLogRequest = SaveM18DataLogRequest(
  376. id = saveM18DeliveryOrderLineLog.id,
  377. dataLog = lineJson,
  378. statusEnum = M18DataLogStatus.SUCCESS
  379. )
  380. m18DataLogService.saveM18DataLog(successSaveM18DeliveryOrderLineLogRequest)
  381. // log success info
  382. successDetailList.add(line.id)
  383. // logger.info("${doLineRefType}: Delivery order ID: ${deliveryOrderId} | M18 ID: ${deliveryOrder.id}")
  384. //logger.info("${doLineRefType}: Saved delivery order line. ID: ${saveDeliveryOrderLineResponse.id} | M18 Line ID: ${line.id} | Delivery order ID: ${deliveryOrderId} | M18 ID: ${deliveryOrder.id}")
  385. } catch (e: SQLException) {
  386. failDetailList.add(line.id)
  387. failItemDetailList.add(line.proId)
  388. // logger.error("${doLineRefType}: Saving Failure!")
  389. logger.error("Error on Function - ${e.stackTrace} | Type: ${doLineRefType} | M18 ID: ${line.id}")
  390. logger.error(e.message)
  391. val errorSaveM18DeliveryOrderLineLogRequest = SaveM18DataLogRequest(
  392. id = saveM18DeliveryOrderLineLog.id,
  393. dataLog = mutableMapOf(Pair("Exception Message", e.message)),
  394. statusEnum = M18DataLogStatus.FAIL
  395. )
  396. m18DataLogService.saveM18DataLog(errorSaveM18DeliveryOrderLineLogRequest)
  397. // logger.error("${doLineRefType}: M18 Data Log Updated! Please see the error. ID: ${saveM18DeliveryOrderLineLog.id}")
  398. }
  399. }
  400. if (deliveryOrderId != null) {
  401. val markedDeleted = deliveryOrderLineService.markDeletedLinesMissingFromM18(
  402. deliveryOrderId = deliveryOrderId,
  403. existingM18LineIds = m18LineIds,
  404. m18RefType = doLineRefType
  405. )
  406. if (markedDeleted > 0) {
  407. logger.info("${doLineRefType}: Marked ${markedDeleted} stale line(s) as deleted for deliveryOrderId=${deliveryOrderId}")
  408. }
  409. val dupesRemoved = deliveryOrderLineService.markDuplicateDeliveryOrderLinesForSameM18LineId(
  410. deliveryOrderId = deliveryOrderId,
  411. existingM18LineIds = m18LineIds,
  412. m18RefType = doLineRefType
  413. )
  414. if (dupesRemoved > 0) {
  415. logger.info("${doLineRefType}: Marked ${dupesRemoved} duplicate line(s) as deleted (same M18 line id) for deliveryOrderId=${deliveryOrderId}")
  416. }
  417. }
  418. } else {
  419. // pot
  420. // logger.error("${doLineRefType}: Saving Failure!")
  421. val saveM18DeliveryOrderLineLogRequest = SaveM18DataLogRequest(
  422. id = null,
  423. refType = "${doLineRefType}",
  424. m18Id = deliveryOrder.id,
  425. m18LastModifyDate = commonUtils.timestampToLocalDateTime(mainpo.lastModifyDate),
  426. // dataLog = mutableMapOf(Pair("Error Message", "${doLineRefType} is null")),
  427. dataLog = mutableMapOf(
  428. Pair(
  429. "${doLineRefType} Error Message",
  430. "pot is null"
  431. ),
  432. Pair(
  433. "${doLineRefType} Error Code",
  434. deliveryOrderLineMessage?.get(0)?.msgCode ?: "No Msg Code from M18"
  435. ),
  436. Pair(
  437. "${doLineRefType} Error Detail",
  438. deliveryOrderLineMessage?.get(0)?.msgDetail ?: "No Msg Detail from M18"
  439. ),
  440. ),
  441. statusEnum = M18DataLogStatus.FAIL
  442. )
  443. val errorLog = m18DataLogService.saveM18DataLog(saveM18DeliveryOrderLineLogRequest)
  444. logger.error("${doLineRefType}: M18 Data Log Updated! Please see the error. ID: ${errorLog.id}")
  445. }
  446. } else {
  447. // mainpo
  448. failList.add(deliveryOrder.id)
  449. // logger.error("${doRefType}: Saving Failure!")
  450. val saveM18DataLogRequest = SaveM18DataLogRequest(
  451. id = null,
  452. refType = "${doRefType}",
  453. m18Id = deliveryOrder.id,
  454. // m18LastModifyDate = if(mainpo?.lastModifyDate != null) commonUtils.instantToLocalDateTime(mainpo.lastModifyDate) else LocalDateTime.now(),
  455. m18LastModifyDate = LocalDateTime.now(),
  456. dataLog = mutableMapOf(
  457. Pair(
  458. "${doRefType} Error",
  459. "mainpo is null"
  460. ),
  461. Pair(
  462. "${doRefType} Error Code",
  463. deliveryOrdersMessages?.get(0)?.msgCode ?: "No Msg Code from M18"
  464. ),
  465. Pair(
  466. "${doRefType} Error Detail",
  467. deliveryOrdersMessages?.get(0)?.msgDetail ?: "No Msg Detail from M18"
  468. ),
  469. ),
  470. statusEnum = M18DataLogStatus.FAIL
  471. )
  472. val errorLog = m18DataLogService.saveM18DataLog(saveM18DataLogRequest)
  473. logger.error("${doLineRefType}: M18 Data Log Updated! Please see the error. ID: ${errorLog.id}")
  474. }
  475. }
  476. } else {
  477. logger.error("${doRefType} List is null. May occur errors.")
  478. }
  479. }
  480. } else {
  481. logger.error("${doRefType} List is null. May occur errors.")
  482. }
  483. // End of save. Check result
  484. logger.info("Total Success (${doRefType}) (${successList.size})")
  485. logger.error("Total Fail (${doRefType}) (${failList.size}): $failList")
  486. logger.info("Total Success (${doLineRefType}) (${successDetailList.size})")
  487. logger.error("Total Fail (${doLineRefType}) (${failDetailList.size}): $failDetailList")
  488. // Fee cleanup for DO lines (currently disabled; keep for future use)
  489. // val feeMarked = deliveryOrderLineService.markDeletedLinesWithFeeItems()
  490. // if (feeMarked > 0) {
  491. // logger.info("Marked $feeMarked DO line(s) as deleted (isFee items).")
  492. // }
  493. logger.info("--------------------------------------------End - Saving M18 Delivery Order--------------------------------------------")
  494. return SyncResult(
  495. totalProcessed = successList.size + failList.size,
  496. totalSuccess = successList.size,
  497. totalFail = failList.size,
  498. query = deliveryOrdersWithType?.query ?: ""
  499. )
  500. }
  501. }