Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 

478 строки
27 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.service.DeliveryOrderLineService
  10. import com.ffii.fpsms.modules.deliveryOrder.service.DeliveryOrderService
  11. import com.ffii.fpsms.modules.master.service.ItemUomService
  12. import com.ffii.fpsms.modules.master.service.ItemsService
  13. import com.ffii.fpsms.modules.master.service.ShopService
  14. import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderLineStatus
  15. import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderStatus
  16. import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderType
  17. import com.ffii.fpsms.modules.purchaseOrder.service.PurchaseOrderLineService
  18. import com.ffii.fpsms.modules.purchaseOrder.service.PurchaseOrderService
  19. import com.ffii.fpsms.modules.purchaseOrder.web.model.SavePurchaseOrderLineRequest
  20. import com.ffii.fpsms.modules.purchaseOrder.web.model.SavePurchaseOrderRequest
  21. import org.slf4j.Logger
  22. import org.slf4j.LoggerFactory
  23. import org.springframework.stereotype.Service
  24. import java.time.LocalDateTime
  25. import kotlin.reflect.full.memberProperties
  26. import java.time.format.DateTimeFormatter
  27. @Service
  28. open class M18PurchaseOrderService(
  29. val m18Config: M18Config,
  30. val apiCallerService: ApiCallerService,
  31. val m18DataLogService: M18DataLogService,
  32. val purchaseOrderService: PurchaseOrderService,
  33. val purchaseOrderLineService: PurchaseOrderLineService,
  34. val deliveryOrderService: DeliveryOrderService,
  35. val deliveryOrderLineService: DeliveryOrderLineService,
  36. val itemsService: ItemsService,
  37. val shopService: ShopService,
  38. val itemUomService: ItemUomService,
  39. val m18MasterDataService: M18MasterDataService
  40. ) {
  41. val commonUtils = CommonUtils()
  42. val logger: Logger = LoggerFactory.getLogger(JwtTokenUtil::class.java)
  43. val lastModifyDateStart = "2025-05-14 14:00:00"
  44. val lastModifyDateEnd = "2025-05-14 14:30:00"
  45. // val lastModifyDateConds =
  46. // "lastModifyDate=largerOrEqual=${lastModifyDateStart}=and=lastModifyDate=lessOrEqual=${lastModifyDateEnd}"
  47. // val lastModifyDate = LocalDateTime.now().minusMinutes(30)
  48. // val commonConds =
  49. // "(beId=equal=${m18Config.BEID_PF}=or=beId=equal=${m18Config.BEID_PP}=or=beId=equal=${m18Config.BEID_TOA})=and=lastModifyDate=largerOrEqual=${lastModifyDate}"
  50. // M18 API
  51. val M18_LOAD_PURCHASE_ORDER_API = "/root/api/read/po"
  52. val M18_FETCH_PURCHASE_ORDER_LIST_API = "/search/search"
  53. // Include material po, oem po
  54. open fun getPurchaseOrdersWithType(request: M18CommonRequest): M18PurchaseOrderListResponseWithType? {
  55. val purchaseOrders = M18PurchaseOrderListResponseWithType(mutableListOf())
  56. val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
  57. val dateFrom = request.modifiedDateFrom?.let {
  58. LocalDateTime.parse(it, formatter).toLocalDate().toString()
  59. }
  60. val dateTo = request.modifiedDateTo?.let {
  61. LocalDateTime.parse(it, formatter).toLocalDate().toString()
  62. }
  63. val lastDateConds =
  64. //"lastModifyDate=largerOrEqual=${request.modifiedDateFrom ?: lastModifyDateStart}=and=lastModifyDate=lessOrEqual=${request.modifiedDateTo ?: lastModifyDateEnd}"
  65. "dDate=largerOrEqual=${dateFrom ?: lastModifyDateStart}=and=dDate=lessOrEqual=${dateTo ?: lastModifyDateEnd}"
  66. // Material PO
  67. val materialPoBuyers =
  68. commonUtils.listToString(listOf(m18Config.BEID_PP, m18Config.BEID_PF), "beId=equal=", "=or=")
  69. val materialPoSupplierNot = commonUtils.listToString(
  70. shopService.findM18VendorIdsByCodeRegexp(m18Config.MATERIAL_PO_SUPPLIER_NOT),
  71. "venId=unequal=",
  72. "=or="
  73. )
  74. val materialPoConds = "(${materialPoBuyers})=and=(${materialPoSupplierNot})=and=(${lastDateConds})"
  75. println("materialPoConds: ${materialPoConds}")
  76. val materialPoParams = M18PurchaseOrderListRequest(
  77. params = null,
  78. conds = materialPoConds
  79. )
  80. try {
  81. purchaseOrders.valuesWithType += Pair(
  82. PurchaseOrderType.MATERIAL,
  83. apiCallerService.get<M18PurchaseOrderListResponse, M18PurchaseOrderListRequest>(
  84. M18_FETCH_PURCHASE_ORDER_LIST_API,
  85. materialPoParams
  86. ).block()
  87. )
  88. } catch (e: Exception) {
  89. logger.error("(Getting Material Po list) Error on Function - ${e.stackTrace}")
  90. logger.error(e.message)
  91. }
  92. // Shop PO
  93. /* val shopPoBuyers = commonUtils.listToString(listOf(m18Config.BEID_TOA), "beId=equal=", "=or=")
  94. val shopPoSupplier = commonUtils.listToString(
  95. shopService.findM18VendorIdsByCodeRegexp(m18Config.SHOP_PO_SUPPLIER),
  96. "venId=equal=",
  97. "=or="
  98. )
  99. val shopPoConds = "(${shopPoBuyers})=and=(${shopPoSupplier})=and=(${lastModifyDateConds})"
  100. println("shopPoConds: ${shopPoConds}")
  101. val shopPoParams = M18PurchaseOrderListRequest(
  102. params = null,
  103. conds = shopPoConds
  104. )
  105. try {
  106. purchaseOrders.valuesWithType += Pair(
  107. PurchaseOrderType.SHOP, apiCallerService.get<M18PurchaseOrderListResponse, M18PurchaseOrderListRequest>(
  108. M18_FETCH_PURCHASE_ORDER_LIST_API,
  109. shopPoParams
  110. ).block()
  111. )
  112. } catch (e: Exception) {
  113. logger.error("(Getting Shop Po list) Error on Function - ${e.stackTrace}")
  114. logger.error(e.message)
  115. } */
  116. // OEM PO
  117. /* val oemPoBuyers = commonUtils.listToString(listOf(m18Config.BEID_PF, m18Config.BEID_PP), "beId=equal=", "=or=")
  118. val oemPoSupplier = commonUtils.listToString(
  119. shopService.findM18VendorIdsByCodeRegexp(m18Config.OEM_PO_SUPPLIER),
  120. "venId=equal=",
  121. "=or="
  122. )
  123. val oemPoConds = "(${oemPoBuyers})=and=(${oemPoSupplier})=and=(${lastModifyDateConds})"
  124. println("oemPoConds: ${oemPoConds}")
  125. val oemPoParams = M18PurchaseOrderListRequest(
  126. params = null,
  127. conds = oemPoConds
  128. )
  129. try {
  130. purchaseOrders.valuesWithType += Pair(
  131. PurchaseOrderType.OEM, apiCallerService.get<M18PurchaseOrderListResponse, M18PurchaseOrderListRequest>(
  132. M18_FETCH_PURCHASE_ORDER_LIST_API,
  133. oemPoParams
  134. ).block()
  135. )
  136. } catch (e: Exception) {
  137. logger.error("(Getting OEM Po list) Error on Function - ${e.stackTrace}")
  138. logger.error(e.message)
  139. } */
  140. return purchaseOrders
  141. }
  142. open fun getPurchaseOrder(id: Long): M18PurchaseOrderResponse? {
  143. val purchaseOrderParams = M18PurchaseOrderRequest(
  144. id = id
  145. )
  146. var purchaseOrder: M18PurchaseOrderResponse? = null
  147. try {
  148. purchaseOrder = apiCallerService.get<M18PurchaseOrderResponse, M18PurchaseOrderRequest>(
  149. M18_LOAD_PURCHASE_ORDER_API,
  150. purchaseOrderParams
  151. ).block()
  152. } catch (e: Exception) {
  153. logger.error("(Getting Po Detail) Error on Function - ${e.stackTrace}")
  154. logger.error(e.message)
  155. }
  156. return purchaseOrder
  157. }
  158. open fun savePurchaseOrders(request: M18CommonRequest) {
  159. logger.info("--------------------------------------------Start - Saving M18 Purchase Order--------------------------------------------")
  160. val purchaseOrdersWithType = getPurchaseOrdersWithType(request)
  161. val examplePurchaseOrders = listOf<Long>(4764034L)
  162. val successList = mutableListOf<Long>()
  163. val successDetailList = mutableListOf<Long>()
  164. val failList = mutableListOf<Long>()
  165. val failDetailList = mutableListOf<Long>()
  166. val poRefType = "Purchase Order"
  167. val poLineRefType = "Purchase Order Line"
  168. if (purchaseOrdersWithType != null) {
  169. // Loop for Purchase Orders (values)
  170. purchaseOrdersWithType.valuesWithType.forEach { purchaseOrderWithType ->
  171. val type = purchaseOrderWithType.first
  172. // if success
  173. val purchaseOrdersValues = purchaseOrderWithType.second?.values
  174. // if fail
  175. val purchaseOrdersMessages = purchaseOrderWithType.second?.messages
  176. if (purchaseOrdersValues != null) {
  177. purchaseOrdersValues.forEach { purchaseOrder ->
  178. val purchaseOrderDetail = getPurchaseOrder(purchaseOrder.id)
  179. var purchaseOrderId: Long? = null //FP-MTMS
  180. // Process for Purchase Order (mainpo)
  181. // Assume only one PO in the PO (search by PO ID)
  182. val mainpo = purchaseOrderDetail?.data?.mainpo?.get(0)
  183. val pot = purchaseOrderDetail?.data?.pot
  184. val purchaseOrderLineMessage = purchaseOrderDetail?.messages
  185. logger.info("purchaseOrderDetail: data is null? ${purchaseOrderDetail?.data == null} | mainpo is null? ${purchaseOrderDetail?.data?.mainpo == null} | get(0) is null? ${purchaseOrderDetail?.data?.mainpo?.get(0) == null}")
  186. // purchase_order + m18_data_log table
  187. if (mainpo != null) {
  188. // Find the latest m18 data log by m18 id & type
  189. // logger.info("${poRefType}: Finding For Latest M18 Data Log...")
  190. val latestPurchaseOrderLog =
  191. m18DataLogService.findLatestM18DataLogWithSuccess(purchaseOrder.id, poRefType)
  192. // logger.info(latestPurchaseOrderLog.toString())
  193. // Save to m18_data_log table
  194. // logger.info("${poRefType}: Saving for M18 Data Log...")
  195. val mainpoJson =
  196. mainpo::class.memberProperties.associate { prop -> prop.name to prop.getter.call(mainpo) }
  197. .toMutableMap()
  198. val saveM18PurchaseOrderLogRequest = SaveM18DataLogRequest(
  199. id = null,
  200. refType = poRefType,
  201. m18Id = purchaseOrder.id,
  202. m18LastModifyDate = commonUtils.timestampToLocalDateTime(mainpo.lastModifyDate),
  203. // dataLog = mainpoJson,
  204. statusEnum = M18DataLogStatus.NOT_PROCESS
  205. )
  206. val saveM18PurchaseOrderLog =
  207. m18DataLogService.saveM18DataLog(saveM18PurchaseOrderLogRequest)
  208. // logger.info("${poRefType}: Saved M18 Data Log. ID: ${saveM18PurchaseOrderLog.id}")
  209. try {
  210. // Find the purchase_order if exist
  211. // logger.info("${poRefType}: Finding exising purchase order...")
  212. val existingPurchaseOrder =
  213. latestPurchaseOrderLog?.id?.let { purchaseOrderService.findByM18DataLogId(it) }
  214. // logger.info("${poRefType}: Exising purchase order ID: ${existingPurchaseOrder?.id}")
  215. // Save to purchase_order table
  216. // logger.info("${poRefType}: Saving purchase order...")
  217. val savePurchaseOrderRequest = SavePurchaseOrderRequest(
  218. id = existingPurchaseOrder?.id,
  219. code = mainpo.code,
  220. m18SupplierId = mainpo.venId,
  221. m18ShopId = mainpo.virDeptId,
  222. m18CurrencyId = mainpo.curId,
  223. orderDate = commonUtils.timestampToLocalDateTime(mainpo.tDate),
  224. estimatedArrivalDate = commonUtils.timestampToLocalDateTime(mainpo.dDate),
  225. completeDate = null,
  226. status = PurchaseOrderStatus.PENDING.value,
  227. type = type.value,
  228. m18DataLogId = saveM18PurchaseOrderLog.id,
  229. m18BeId = mainpo.beId
  230. )
  231. val savePurchaseOrderResponse =
  232. purchaseOrderService.savePurchaseOrder(savePurchaseOrderRequest)
  233. purchaseOrderId = savePurchaseOrderResponse.id
  234. // Update m18_data_log with success
  235. val successSaveM18PurchaseOrderLogRequest = SaveM18DataLogRequest(
  236. id = saveM18PurchaseOrderLog.id,
  237. dataLog = mainpoJson,
  238. statusEnum = M18DataLogStatus.SUCCESS
  239. )
  240. m18DataLogService.saveM18DataLog(successSaveM18PurchaseOrderLogRequest)
  241. // log success info
  242. successList.add(purchaseOrder.id)
  243. logger.info("${poRefType}: Saved purchase order. ID: ${savePurchaseOrderResponse.id} | M18 ${poRefType} ID: ${purchaseOrder.id}")
  244. } catch (e: Exception) {
  245. failList.add(purchaseOrder.id)
  246. // logger.error("${poRefType}: Saving Failure!")
  247. logger.error("Error on Function - ${e.stackTrace} | Type: ${poRefType} | M18 ID: ${purchaseOrder.id} | Different? ${mainpo.id}")
  248. logger.error(e.message)
  249. val errorSaveM18PurchaseOrderLogRequest = SaveM18DataLogRequest(
  250. id = saveM18PurchaseOrderLog.id,
  251. dataLog = mutableMapOf(Pair("Exception Message", e.message)),
  252. statusEnum = M18DataLogStatus.FAIL
  253. )
  254. m18DataLogService.saveM18DataLog(errorSaveM18PurchaseOrderLogRequest)
  255. // logger.error("${poRefType}: M18 Data Log Updated! Please see the error. ID: ${saveM18PurchaseOrderLogRequest.id}")
  256. }
  257. // purchase_order_line + m18_data_log
  258. // TODO: check deleted po line?
  259. if (pot != null) {
  260. // Loop for Purchase Order Lines (pot)
  261. pot.forEach { line ->
  262. // Find the latest m18 data log by m18 id & type
  263. // logger.info("${poLineRefType}: Finding For Latest M18 Data Log...")
  264. val latestPurchaseOrderLineLog =
  265. m18DataLogService.findLatestM18DataLogWithSuccess(line.id, poLineRefType)
  266. // logger.info("${poLineRefType}: Latest M18 Data Log ID: ${latestPurchaseOrderLineLog?.id}")
  267. // Save to m18_data_log table
  268. // logger.info("${poLineRefType}: Saving for M18 Data Log...")
  269. val lineJson =
  270. line::class.memberProperties.associate { prop ->
  271. prop.name to prop.getter.call(
  272. line
  273. )
  274. }
  275. .toMutableMap()
  276. val saveM18PurchaseOrderLineLogRequest = SaveM18DataLogRequest(
  277. id = null,
  278. refType = poLineRefType,
  279. m18Id = line.id,
  280. m18LastModifyDate = commonUtils.timestampToLocalDateTime(mainpo.lastModifyDate),
  281. // dataLog = lineJson,
  282. statusEnum = M18DataLogStatus.NOT_PROCESS
  283. )
  284. val saveM18PurchaseOrderLineLog =
  285. m18DataLogService.saveM18DataLog(saveM18PurchaseOrderLineLogRequest)
  286. // logger.info("${poLineRefType}: Saved M18 Data Log. ID: ${saveM18PurchaseOrderLineLog.id}")
  287. // logger.info("${poLineRefType}: Finding item...")
  288. val item = itemsService.findByM18Id(line.proId)
  289. var itemId: Long? = null
  290. if (item == null) {
  291. itemId = m18MasterDataService.saveProduct(line.proId)?.id
  292. } else {
  293. itemId = item.id
  294. }
  295. logger.info("${poLineRefType}: Item ID: ${itemId} | M18 Item ID: ${line.proId}")
  296. try {
  297. // Find the purchase_order_line if exist
  298. // logger.info("${poLineRefType}: Finding exising purchase order line...")
  299. val existingPurchaseOrderLine = latestPurchaseOrderLineLog?.id?.let {
  300. purchaseOrderLineService.findPurchaseOrderLineByM18Id(it)
  301. }
  302. // logger.info("${poLineRefType}: Exising purchase order line ID: ${existingPurchaseOrderLine?.id}")
  303. // Save to purchase_order_line table
  304. // logger.info("${poLineRefType}: Saving purchase order line...")
  305. val itemUom = itemId?.let { itemUomService.findPurchaseUnitByItemId(it) }
  306. val savePurchaseOrderLineRequest = SavePurchaseOrderLineRequest(
  307. id = existingPurchaseOrderLine?.id,
  308. itemId = itemId,
  309. uomId = itemUom?.uom?.id,
  310. purchaseOrderId = purchaseOrderId,
  311. qty = line.qty,
  312. up = line.up,
  313. price = line.amt,
  314. // m18CurrencyId = mainpo.curId,
  315. status = existingPurchaseOrderLine?.status?.value
  316. ?: PurchaseOrderLineStatus.PENDING.value,
  317. m18DataLogId = saveM18PurchaseOrderLineLog.id,
  318. m18Discount = line.disc,
  319. m18Lot = line.lot
  320. )
  321. val savePurchaseOrderLineResponse =
  322. purchaseOrderLineService.savePurchaseOrderLine(savePurchaseOrderLineRequest)
  323. // Update m18_data_log with success
  324. val successSaveM18PurchaseOrderLineLogRequest = SaveM18DataLogRequest(
  325. id = saveM18PurchaseOrderLineLog.id,
  326. dataLog = lineJson,
  327. statusEnum = M18DataLogStatus.SUCCESS
  328. )
  329. m18DataLogService.saveM18DataLog(successSaveM18PurchaseOrderLineLogRequest)
  330. // log success info
  331. successDetailList.add(line.id)
  332. // logger.info("${poLineRefType}: Purchase order ID: ${purchaseOrderId} | M18 ID: ${purchaseOrder.id}")
  333. logger.info("${poLineRefType}: Saved purchase order line. ID: ${savePurchaseOrderLineResponse.id} | M18 Line ID: ${line.id} | Purchase order ID: ${purchaseOrderId} | M18 ID: ${purchaseOrder.id}")
  334. } catch (e: Exception) {
  335. failDetailList.add(line.id)
  336. // logger.error("${poLineRefType}: Saving Failure!")
  337. logger.error("Error on Function - ${e.stackTrace} | Type: ${poLineRefType} | M18 ID: ${line.id}")
  338. logger.error(e.message)
  339. val errorSaveM18PurchaseOrderLineLogRequest = SaveM18DataLogRequest(
  340. id = saveM18PurchaseOrderLineLog.id,
  341. dataLog = mutableMapOf(Pair("Exception Message", e.message)),
  342. statusEnum = M18DataLogStatus.FAIL
  343. )
  344. m18DataLogService.saveM18DataLog(errorSaveM18PurchaseOrderLineLogRequest)
  345. // logger.error("${poLineRefType}: M18 Data Log Updated! Please see the error. ID: ${saveM18PurchaseOrderLineLog.id}")
  346. }
  347. }
  348. } else {
  349. // pot
  350. // logger.error("${poLineRefType}: Saving Failure!")
  351. val saveM18PurchaseOrderLineLogRequest = SaveM18DataLogRequest(
  352. id = null,
  353. refType = "${poLineRefType}",
  354. m18Id = purchaseOrder.id,
  355. m18LastModifyDate = commonUtils.timestampToLocalDateTime(mainpo.lastModifyDate),
  356. // dataLog = mutableMapOf(Pair("Error Message", "${poLineRefType} is null")),
  357. dataLog = mutableMapOf(
  358. Pair(
  359. "${poLineRefType} Error Message",
  360. "pot is null"
  361. ),
  362. Pair(
  363. "${poLineRefType} Error Code",
  364. purchaseOrderLineMessage?.get(0)?.msgCode ?: "No Msg Code from M18"
  365. ),
  366. Pair(
  367. "${poLineRefType} Error Detail",
  368. purchaseOrderLineMessage?.get(0)?.msgDetail ?: "No Msg Detail from M18"
  369. ),
  370. ),
  371. statusEnum = M18DataLogStatus.FAIL
  372. )
  373. val errorLog = m18DataLogService.saveM18DataLog(saveM18PurchaseOrderLineLogRequest)
  374. logger.error("${poLineRefType}: M18 Data Log Updated! Please see the error. ID: ${errorLog.id}")
  375. }
  376. } else {
  377. // mainpo
  378. failList.add(purchaseOrder.id)
  379. // logger.error("${poRefType}: Saving Failure!")
  380. val saveM18DataLogRequest = SaveM18DataLogRequest(
  381. id = null,
  382. refType = "${poRefType}",
  383. m18Id = purchaseOrder.id,
  384. // m18LastModifyDate = if(mainpo?.lastModifyDate != null) commonUtils.instantToLocalDateTime(mainpo.lastModifyDate) else LocalDateTime.now(),
  385. m18LastModifyDate = LocalDateTime.now(),
  386. dataLog = mutableMapOf(
  387. Pair(
  388. "${poRefType} Error",
  389. "mainpo is null"
  390. ),
  391. Pair(
  392. "${poRefType} Error Code",
  393. purchaseOrdersMessages?.get(0)?.msgCode ?: "No Msg Code from M18"
  394. ),
  395. Pair(
  396. "${poRefType} Error Detail",
  397. purchaseOrdersMessages?.get(0)?.msgDetail ?: "No Msg Detail from M18"
  398. ),
  399. ),
  400. statusEnum = M18DataLogStatus.FAIL
  401. )
  402. val errorLog = m18DataLogService.saveM18DataLog(saveM18DataLogRequest)
  403. logger.error("${poLineRefType}: M18 Data Log Updated! Please see the error. ID: ${errorLog.id}")
  404. }
  405. }
  406. } else {
  407. logger.error("${poRefType} List is null. May occur errors.")
  408. }
  409. }
  410. } else {
  411. logger.error("${poRefType} List is null. May occur errors.")
  412. }
  413. // End of save. Check result
  414. // logger.info("Total Success (${poRefType}) (${successList.size}): $successList")
  415. logger.info("Total Success (${poRefType}) (${successList.size})")
  416. // if (failList.size > 0) {
  417. logger.error("Total Fail (${poRefType}) (${failList.size}): $failList")
  418. // }
  419. // logger.info("Total Success (${poLineRefType}) (${successDetailList.size}): $successDetailList")
  420. logger.info("Total Success (${poLineRefType}) (${successDetailList.size})")
  421. // if (failDetailList.size > 0) {
  422. logger.error("Total Fail (${poLineRefType}) (${failDetailList.size}): $failDetailList")
  423. // }
  424. logger.info("--------------------------------------------End - Saving M18 Purchase Order--------------------------------------------")
  425. }
  426. }