25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

416 lines
24 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.utils.CommonUtils
  8. import com.ffii.fpsms.m18.web.models.M18CommonRequest
  9. import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderLineStatus
  10. import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatus
  11. import com.ffii.fpsms.modules.deliveryOrder.service.DeliveryOrderLineService
  12. import com.ffii.fpsms.modules.deliveryOrder.service.DeliveryOrderService
  13. import com.ffii.fpsms.modules.deliveryOrder.web.models.SaveDeliveryOrderLineRequest
  14. import com.ffii.fpsms.modules.deliveryOrder.web.models.SaveDeliveryOrderRequest
  15. import com.ffii.fpsms.modules.master.service.ItemUomService
  16. import com.ffii.fpsms.modules.master.service.ItemsService
  17. import com.ffii.fpsms.modules.master.service.ShopService
  18. import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderType
  19. import org.slf4j.Logger
  20. import org.slf4j.LoggerFactory
  21. import org.springframework.stereotype.Service
  22. import java.time.LocalDateTime
  23. import kotlin.reflect.full.memberProperties
  24. @Service
  25. open class M18DeliveryOrderService(
  26. val m18Config: M18Config,
  27. val apiCallerService: ApiCallerService,
  28. val m18DataLogService: M18DataLogService,
  29. val deliveryOrderService: DeliveryOrderService,
  30. val deliveryOrderLineService: DeliveryOrderLineService,
  31. val itemsService: ItemsService,
  32. val shopService: ShopService,
  33. val itemUomService: ItemUomService,
  34. val m18MasterDataService: M18MasterDataService,
  35. ) {
  36. val commonUtils = CommonUtils()
  37. val logger: Logger = LoggerFactory.getLogger(JwtTokenUtil::class.java)
  38. val lastModifyDateStart = "2025-05-14 14:00:00"
  39. val lastModifyDateEnd = "2025-05-14 14:30:00"
  40. // val lastModifyDateConds =
  41. // "lastModifyDate=largerOrEqual=${lastModifyDateStart}=and=lastModifyDate=lessOrEqual=${lastModifyDateEnd}"
  42. // val lastModifyDate = LocalDateTime.now().minusMinutes(30)
  43. // val commonConds =
  44. // "(beId=equal=${m18Config.BEID_PF}=or=beId=equal=${m18Config.BEID_PP}=or=beId=equal=${m18Config.BEID_TOA})=and=lastModifyDate=largerOrEqual=${lastModifyDate}"
  45. // M18 API
  46. // Sharing same API with po
  47. val M18_LOAD_PURCHASE_ORDER_API = "/root/api/read/po"
  48. val M18_FETCH_PURCHASE_ORDER_LIST_API = "/search/search"
  49. // Include shop po
  50. open fun getDeliveryOrdersWithType(request: M18CommonRequest): M18PurchaseOrderListResponseWithType? {
  51. val deliveryOrders = M18PurchaseOrderListResponseWithType(mutableListOf())
  52. val lastModifyDateConds =
  53. "lastModifyDate=largerOrEqual=${request.modifiedDateFrom ?: lastModifyDateStart}=and=lastModifyDate=lessOrEqual=${request.modifiedDateTo ?: lastModifyDateEnd}"
  54. // Shop PO
  55. val shopPoBuyers = commonUtils.listToString(listOf(m18Config.BEID_TOA), "beId=equal=", "=or=")
  56. val shopPoSupplier = commonUtils.listToString(
  57. shopService.findM18VendorIdsByCodeRegexp(m18Config.SHOP_PO_SUPPLIER),
  58. "venId=equal=",
  59. "=or="
  60. )
  61. val shopPoConds = "(${shopPoBuyers})=and=(${shopPoSupplier})=and=(${lastModifyDateConds})"
  62. println("shopPoConds: ${shopPoConds}")
  63. val shopPoParams = M18PurchaseOrderListRequest(
  64. params = null,
  65. conds = shopPoConds
  66. )
  67. try {
  68. deliveryOrders.valuesWithType += Pair(
  69. PurchaseOrderType.SHOP, apiCallerService.get<M18PurchaseOrderListResponse, M18PurchaseOrderListRequest>(
  70. M18_FETCH_PURCHASE_ORDER_LIST_API,
  71. shopPoParams
  72. ).block()
  73. )
  74. } catch (e: Exception) {
  75. logger.error("(Getting Shop Po list) Error on Function - ${e.stackTrace}")
  76. logger.error(e.message)
  77. }
  78. return deliveryOrders
  79. }
  80. open fun getDeliveryOrder(id: Long): M18PurchaseOrderResponse? {
  81. val deliveryOrderParams = M18PurchaseOrderRequest(
  82. id = id
  83. )
  84. var deliveryOrder: M18PurchaseOrderResponse? = null
  85. try {
  86. deliveryOrder = apiCallerService.get<M18PurchaseOrderResponse, M18PurchaseOrderRequest>(
  87. M18_LOAD_PURCHASE_ORDER_API,
  88. deliveryOrderParams
  89. ).block()
  90. } catch (e: Exception) {
  91. logger.error("(Getting Po Detail) Error on Function - ${e.stackTrace}")
  92. logger.error(e.message)
  93. }
  94. return deliveryOrder
  95. }
  96. open fun saveDeliveryOrders(request: M18CommonRequest) {
  97. logger.info("--------------------------------------------Start - Saving M18 Delivery Order--------------------------------------------")
  98. val deliveryOrdersWithType = getDeliveryOrdersWithType(request)
  99. val successList = mutableListOf<Long>()
  100. val successDetailList = mutableListOf<Long>()
  101. val failList = mutableListOf<Long>()
  102. val failDetailList = mutableListOf<Long>()
  103. val failItemDetailList = mutableListOf<Long>()
  104. val doRefType = "Delivery Order"
  105. val doLineRefType = "Delivery Order Line"
  106. if (deliveryOrdersWithType != null) {
  107. // Loop for Delivery Orders (values)
  108. deliveryOrdersWithType.valuesWithType.forEach { deliveryOrderWithType ->
  109. val type = deliveryOrderWithType.first
  110. // if success
  111. val deliveryOrdersValues = deliveryOrderWithType.second?.values
  112. // if fail
  113. val deliveryOrdersMessages = deliveryOrderWithType.second?.messages
  114. if (deliveryOrdersValues != null) {
  115. deliveryOrdersValues.forEach { deliveryOrder ->
  116. val deliveryOrderDetail = getDeliveryOrder(deliveryOrder.id)
  117. var deliveryOrderId: Long? = null //FP-MTMS
  118. // Process for Delivery Order (mainpo)
  119. // Assume only one DO in the DO (search by DO ID)
  120. val mainpo = deliveryOrderDetail?.data?.mainpo?.get(0)
  121. // 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}")
  122. val pot = deliveryOrderDetail?.data?.pot
  123. val deliveryOrderLineMessage = deliveryOrderDetail?.messages
  124. // delivery_order + m18_data_log table
  125. if (mainpo != null) {
  126. // Find the latest m18 data log by m18 id & type
  127. // logger.info("${doRefType}: Finding For Latest M18 Data Log...")
  128. val latestDeliveryOrderLog =
  129. m18DataLogService.findLatestM18DataLogWithSuccess(deliveryOrder.id, doRefType)
  130. logger.info(latestDeliveryOrderLog.toString())
  131. // Save to m18_data_log table
  132. // logger.info("${doRefType}: Saving for M18 Data Log...")
  133. val mainpoJson =
  134. mainpo::class.memberProperties.associate { prop -> prop.name to prop.getter.call(mainpo) }
  135. .toMutableMap()
  136. val saveM18DeliveryOrderLogRequest = SaveM18DataLogRequest(
  137. id = null,
  138. refType = doRefType,
  139. m18Id = deliveryOrder.id,
  140. m18LastModifyDate = commonUtils.timestampToLocalDateTime(mainpo.lastModifyDate),
  141. // dataLog = mainpoJson,
  142. statusEnum = M18DataLogStatus.NOT_PROCESS
  143. )
  144. val saveM18DeliveryOrderLog =
  145. m18DataLogService.saveM18DataLog(saveM18DeliveryOrderLogRequest)
  146. // logger.info("${doRefType}: Saved M18 Data Log. ID: ${saveM18DeliveryOrderLog.id}")
  147. try {
  148. // Find the delivery_order if exist
  149. // logger.info("${doRefType}: Finding exising delivery order...")
  150. val existingDeliveryOrder =
  151. latestDeliveryOrderLog?.id?.let { deliveryOrderService.findByM18DataLogId(it) }
  152. // logger.info("${doRefType}: Exising delivery order ID: ${existingDeliveryOrder?.id}")
  153. // Save to delivery_order table
  154. // logger.info("${doRefType}: Saving delivery order...")
  155. val saveDeliveryOrderRequest = SaveDeliveryOrderRequest(
  156. id = existingDeliveryOrder?.id,
  157. code = mainpo.code,
  158. m18SupplierId = mainpo.venId,
  159. m18ShopId = mainpo.virDeptId,
  160. m18CurrencyId = mainpo.curId,
  161. orderDate = commonUtils.timestampToLocalDateTime(mainpo.tDate),
  162. estimatedArrivalDate = commonUtils.timestampToLocalDateTime(mainpo.dDate),
  163. completeDate = null,
  164. status = DeliveryOrderStatus.PENDING.value,
  165. type = type.value,
  166. m18DataLogId = saveM18DeliveryOrderLog.id,
  167. handlerId = null,
  168. m18BeId = mainpo.beId
  169. )
  170. val saveDeliveryOrderResponse =
  171. deliveryOrderService.saveDeliveryOrder(saveDeliveryOrderRequest)
  172. deliveryOrderId = saveDeliveryOrderResponse.id
  173. // Update m18_data_log with success
  174. val successSaveM18DeliveryOrderLogRequest = SaveM18DataLogRequest(
  175. id = saveM18DeliveryOrderLog.id,
  176. dataLog = mainpoJson,
  177. statusEnum = M18DataLogStatus.SUCCESS
  178. )
  179. m18DataLogService.saveM18DataLog(successSaveM18DeliveryOrderLogRequest)
  180. // log success info
  181. successList.add(deliveryOrder.id)
  182. logger.info("${doRefType}: Saved delivery order. ID: ${saveDeliveryOrderResponse.id} | M18 ${doRefType} ID: ${deliveryOrder.id}")
  183. } catch (e: Exception) {
  184. failList.add(deliveryOrder.id)
  185. // logger.error("${doRefType}: Saving Failure!")
  186. logger.error("Error on Function - ${e.stackTrace} | Type: ${doRefType} | M18 ID: ${deliveryOrder.id} | Different? ${mainpo.id}")
  187. logger.error(e.message)
  188. val errorSaveM18DeliveryOrderLogRequest = SaveM18DataLogRequest(
  189. id = saveM18DeliveryOrderLog.id,
  190. dataLog = mutableMapOf(Pair("Exception Message", e.message)),
  191. statusEnum = M18DataLogStatus.FAIL
  192. )
  193. m18DataLogService.saveM18DataLog(errorSaveM18DeliveryOrderLogRequest)
  194. // logger.error("${doRefType}: M18 Data Log Updated! Please see the error. ID: ${saveM18DeliveryOrderLogRequest.id}")
  195. }
  196. // delivery_order_line + m18_data_log
  197. // TODO: check deleted po line?
  198. if (pot != null) {
  199. // Loop for Delivery Order Lines (pot)
  200. pot.forEach { line ->
  201. // Find the latest m18 data log by m18 id & type
  202. // logger.info("${doLineRefType}: Finding For Latest M18 Data Log...")
  203. val latestDeliveryOrderLineLog =
  204. m18DataLogService.findLatestM18DataLogWithSuccess(line.id, doLineRefType)
  205. // logger.info("${doLineRefType}: Latest M18 Data Log ID: ${latestDeliveryOrderLineLog?.id}")
  206. // Save to m18_data_log table
  207. // logger.info("${doLineRefType}: Saving for M18 Data Log...")
  208. val lineJson =
  209. line::class.memberProperties.associate { prop ->
  210. prop.name to prop.getter.call(
  211. line
  212. )
  213. }
  214. .toMutableMap()
  215. val saveM18DeliveryOrderLineLogRequest = SaveM18DataLogRequest(
  216. id = null,
  217. refType = doLineRefType,
  218. m18Id = line.id,
  219. m18LastModifyDate = commonUtils.timestampToLocalDateTime(mainpo.lastModifyDate),
  220. // dataLog = lineJson,
  221. statusEnum = M18DataLogStatus.NOT_PROCESS
  222. )
  223. val saveM18DeliveryOrderLineLog =
  224. m18DataLogService.saveM18DataLog(saveM18DeliveryOrderLineLogRequest)
  225. // logger.info("${doLineRefType}: Saved M18 Data Log. ID: ${saveM18DeliveryOrderLineLog.id}")
  226. // logger.info("${doLineRefType}: Finding item...")
  227. val item = itemsService.findByM18Id(line.proId)
  228. var itemId: Long? = null
  229. if (item == null) {
  230. itemId = m18MasterDataService.saveProduct(line.proId)?.id
  231. } else {
  232. itemId = item.id
  233. }
  234. // logger.info("${doLineRefType}: Item ID: ${itemId} | M18 Item ID: ${line.proId}")
  235. try {
  236. // Find the delivery_order_line if exist
  237. // logger.info("${doLineRefType}: Finding exising delivery order line...")
  238. val existingDeliveryOrderLine = latestDeliveryOrderLineLog?.id?.let {
  239. deliveryOrderLineService.findDeliveryOrderLineByM18Id(it)
  240. }
  241. // logger.info("${doLineRefType}: Exising delivery order line ID: ${existingDeliveryOrderLine?.id}")
  242. // Save to delivery_order_line table
  243. // logger.info("${doLineRefType}: Saving delivery order line...")
  244. val itemUom = itemId?.let { itemUomService.findSalesUnitByItemId(it) }
  245. val saveDeliveryOrderLineRequest = SaveDeliveryOrderLineRequest(
  246. id = existingDeliveryOrderLine?.id,
  247. itemId = itemId,
  248. uomId = itemUom?.uom?.id,
  249. deliveryOrderId = deliveryOrderId,
  250. qty = line.qty,
  251. up = line.up,
  252. price = line.amt,
  253. // m18CurrencyId = mainpo.curId,
  254. status = existingDeliveryOrderLine?.status?.value
  255. ?: DeliveryOrderLineStatus.PENDING.value,
  256. m18DataLogId = saveM18DeliveryOrderLineLog.id,
  257. m18Discount = line.disc,
  258. m18Lot = line.lot
  259. )
  260. val saveDeliveryOrderLineResponse =
  261. deliveryOrderLineService.saveDeliveryOrderLine(saveDeliveryOrderLineRequest)
  262. // Update m18_data_log with success
  263. val successSaveM18DeliveryOrderLineLogRequest = SaveM18DataLogRequest(
  264. id = saveM18DeliveryOrderLineLog.id,
  265. dataLog = lineJson,
  266. statusEnum = M18DataLogStatus.SUCCESS
  267. )
  268. m18DataLogService.saveM18DataLog(successSaveM18DeliveryOrderLineLogRequest)
  269. // log success info
  270. successDetailList.add(line.id)
  271. // logger.info("${doLineRefType}: Delivery order ID: ${deliveryOrderId} | M18 ID: ${deliveryOrder.id}")
  272. logger.info("${doLineRefType}: Saved delivery order line. ID: ${saveDeliveryOrderLineResponse.id} | M18 Line ID: ${line.id} | Delivery order ID: ${deliveryOrderId} | M18 ID: ${deliveryOrder.id}")
  273. } catch (e: Exception) {
  274. failDetailList.add(line.id)
  275. failItemDetailList.add(line.proId)
  276. // logger.error("${doLineRefType}: Saving Failure!")
  277. logger.error("Error on Function - ${e.stackTrace} | Type: ${doLineRefType} | M18 ID: ${line.id}")
  278. logger.error(e.message)
  279. val errorSaveM18DeliveryOrderLineLogRequest = SaveM18DataLogRequest(
  280. id = saveM18DeliveryOrderLineLog.id,
  281. dataLog = mutableMapOf(Pair("Exception Message", e.message)),
  282. statusEnum = M18DataLogStatus.FAIL
  283. )
  284. m18DataLogService.saveM18DataLog(errorSaveM18DeliveryOrderLineLogRequest)
  285. // logger.error("${doLineRefType}: M18 Data Log Updated! Please see the error. ID: ${saveM18DeliveryOrderLineLog.id}")
  286. }
  287. }
  288. } else {
  289. // pot
  290. // logger.error("${doLineRefType}: Saving Failure!")
  291. val saveM18DeliveryOrderLineLogRequest = SaveM18DataLogRequest(
  292. id = null,
  293. refType = "${doLineRefType}",
  294. m18Id = deliveryOrder.id,
  295. m18LastModifyDate = commonUtils.timestampToLocalDateTime(mainpo.lastModifyDate),
  296. // dataLog = mutableMapOf(Pair("Error Message", "${doLineRefType} is null")),
  297. dataLog = mutableMapOf(
  298. Pair(
  299. "${doLineRefType} Error Message",
  300. "pot is null"
  301. ),
  302. Pair(
  303. "${doLineRefType} Error Code",
  304. deliveryOrderLineMessage?.get(0)?.msgCode ?: "No Msg Code from M18"
  305. ),
  306. Pair(
  307. "${doLineRefType} Error Detail",
  308. deliveryOrderLineMessage?.get(0)?.msgDetail ?: "No Msg Detail from M18"
  309. ),
  310. ),
  311. statusEnum = M18DataLogStatus.FAIL
  312. )
  313. val errorLog = m18DataLogService.saveM18DataLog(saveM18DeliveryOrderLineLogRequest)
  314. logger.error("${doLineRefType}: M18 Data Log Updated! Please see the error. ID: ${errorLog.id}")
  315. }
  316. } else {
  317. // mainpo
  318. failList.add(deliveryOrder.id)
  319. // logger.error("${doRefType}: Saving Failure!")
  320. val saveM18DataLogRequest = SaveM18DataLogRequest(
  321. id = null,
  322. refType = "${doRefType}",
  323. m18Id = deliveryOrder.id,
  324. // m18LastModifyDate = if(mainpo?.lastModifyDate != null) commonUtils.instantToLocalDateTime(mainpo.lastModifyDate) else LocalDateTime.now(),
  325. m18LastModifyDate = LocalDateTime.now(),
  326. dataLog = mutableMapOf(
  327. Pair(
  328. "${doRefType} Error",
  329. "mainpo is null"
  330. ),
  331. Pair(
  332. "${doRefType} Error Code",
  333. deliveryOrdersMessages?.get(0)?.msgCode ?: "No Msg Code from M18"
  334. ),
  335. Pair(
  336. "${doRefType} Error Detail",
  337. deliveryOrdersMessages?.get(0)?.msgDetail ?: "No Msg Detail from M18"
  338. ),
  339. ),
  340. statusEnum = M18DataLogStatus.FAIL
  341. )
  342. val errorLog = m18DataLogService.saveM18DataLog(saveM18DataLogRequest)
  343. logger.error("${doLineRefType}: M18 Data Log Updated! Please see the error. ID: ${errorLog.id}")
  344. }
  345. }
  346. } else {
  347. logger.error("${doRefType} List is null. May occur errors.")
  348. }
  349. }
  350. } else {
  351. logger.error("${doRefType} List is null. May occur errors.")
  352. }
  353. // End of save. Check result
  354. // logger.info("Total Success (${doRefType}) (${successList.size}): $successList")
  355. logger.info("Total Success (${doRefType}) (${successList.size})")
  356. // if (failList.size > 0) {
  357. logger.error("Total Fail (${doRefType}) (${failList.size}): $failList")
  358. // }
  359. // logger.info("Total Success (${doLineRefType}) (${successDetailList.size}): $successDetailList")
  360. logger.info("Total Success (${doLineRefType}) (${successDetailList.size})")
  361. // if (failDetailList.size > 0) {
  362. logger.error("Total Fail (${doLineRefType}) (${failDetailList.size}): $failDetailList")
  363. // logger.error("Total Fail M18 Items (${doLineRefType}) (${failItemDetailList.distinct().size}): ${failItemDetailList.distinct()}")
  364. // }
  365. logger.info("--------------------------------------------End - Saving M18 Delivery Order--------------------------------------------")
  366. }
  367. }