package com.ffii.fpsms.m18.service import com.ffii.core.utils.JwtTokenUtil import com.ffii.fpsms.api.service.ApiCallerService import com.ffii.fpsms.m18.M18Config import com.ffii.fpsms.m18.model.* import com.ffii.fpsms.m18.utils.CommonUtils import com.ffii.fpsms.modules.master.service.ItemsService import com.ffii.fpsms.modules.master.service.ShopService import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderLineStatus import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderStatus import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderType import com.ffii.fpsms.modules.purchaseOrder.service.PurchaseOrderLineService import com.ffii.fpsms.modules.purchaseOrder.service.PurchaseOrderService import com.ffii.fpsms.modules.purchaseOrder.web.model.SavePurchaseOrderLineRequest import com.ffii.fpsms.modules.purchaseOrder.web.model.SavePurchaseOrderRequest import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.stereotype.Service import java.time.LocalDateTime import kotlin.reflect.full.memberProperties @Service open class M18PurchaseOrderService( val m18Config: M18Config, val apiCallerService: ApiCallerService, val m18DataLogService: M18DataLogService, val purchaseOrderService: PurchaseOrderService, val purchaseOrderLineService: PurchaseOrderLineService, val itemsService: ItemsService, val shopService: ShopService, ) { val commonUtils = CommonUtils() val logger: Logger = LoggerFactory.getLogger(JwtTokenUtil::class.java) val lastModifyDate = LocalDateTime.now().minusMinutes(30) // val commonConds = // "(beId=equal=${m18Config.BEID_PF}=or=beId=equal=${m18Config.BEID_PP}=or=beId=equal=${m18Config.BEID_TOA})=and=lastModifyDate=largerOrEqual=${lastModifyDate}" // M18 API val M18_LOAD_PURCHASE_ORDER_API = "/root/api/read/po" val M18_FETCH_PURCHASE_ORDER_LIST_API = "/search/search" // Include material po, shop po, oem po open fun getPurchaseOrdersWithType(): M18PurchaseOrderListResponseWithType? { val purchaseOrders = M18PurchaseOrderListResponseWithType(mutableListOf()) // Material PO val materialPoBuyers = commonUtils.ListToString(listOf(m18Config.BEID_PP, m18Config.BEID_PF), "beId=equal=", "=or=") val materialPoSupplierNot = "venId=unequal=${m18Config.MATERIAL_PO_SUPPLIER_NOT}" val materialPoConds = "${materialPoBuyers}=and=${materialPoSupplierNot}" val materialPoParams = M18PurchaseOrderListRequest( params = null, conds = materialPoConds ) try { purchaseOrders.valuesWithType += Pair( PurchaseOrderType.MATERIAL, apiCallerService.get( M18_FETCH_PURCHASE_ORDER_LIST_API, materialPoParams ).block()?.values ?: mutableListOf() ) } catch (e: Exception) { logger.error("Error on Function - ${e.stackTrace}") logger.error(e.message) } // Shop PO val shopPoBuyers = commonUtils.ListToString(listOf(m18Config.BEID_TOA), "beId=equal=", "=or=") val shopPoSupplier = "venId=equal=${m18Config.SHOP_PO_SUPPLIER}" val shopPoConds = "${shopPoBuyers}=and=${shopPoSupplier}" val shopPoParams = M18PurchaseOrderListRequest( params = null, conds = shopPoConds ) try { purchaseOrders.valuesWithType += Pair( PurchaseOrderType.SHOP, apiCallerService.get( M18_FETCH_PURCHASE_ORDER_LIST_API, shopPoParams ).block()?.values ?: mutableListOf() ) } catch (e: Exception) { logger.error("Error on Function - ${e.stackTrace}") logger.error(e.message) } // OEM PO val oemPoBuyers = commonUtils.ListToString(listOf(m18Config.BEID_PF, m18Config.BEID_PP), "beId=equal=", "=or=") val oemPoSupplier = "venId=equal=${m18Config.OEM_PO_SUPPLIER}" val oemPoConds = "${oemPoBuyers}=and=${oemPoSupplier}" val oemPoParams = M18PurchaseOrderListRequest( params = null, conds = oemPoConds ) try { purchaseOrders.valuesWithType += Pair( PurchaseOrderType.OEM, apiCallerService.get( M18_FETCH_PURCHASE_ORDER_LIST_API, oemPoParams ).block()?.values ) } catch (e: Exception) { logger.error("Error on Function - ${e.stackTrace}") logger.error(e.message) } return purchaseOrders } open fun getPurchaseOrder(id: Long): M18PurchaseOrderResponse? { val purchaseOrderParams = M18PurchaseOrderRequest( id = id ) var purchaseOrder: M18PurchaseOrderResponse? = null try { purchaseOrder = apiCallerService.get( M18_LOAD_PURCHASE_ORDER_API, purchaseOrderParams ).block() } catch (e: Exception) { logger.error("Error on Function - ${e.stackTrace}") logger.error(e.message) } return purchaseOrder } open fun savePurchaseOrders() { logger.info("--------------------------------------------Start - Saving M18 Purchase Order--------------------------------------------") val purchaseOrdersWithType = getPurchaseOrdersWithType() val examplePurchaseOrders = listOf(4764034L) val successList = mutableListOf() val successDetailList = mutableListOf() val failList = mutableListOf() val failDetailList = mutableListOf() val poRefType = "Purchase Order" val poLineRefType = "Purchase Order Line" if (purchaseOrdersWithType != null) { // Loop for Purchase Orders (values) purchaseOrdersWithType.valuesWithType.forEach { purchaseOrderWithType -> val type = purchaseOrderWithType.first val purchaseOrders = purchaseOrderWithType.second if (purchaseOrders != null) { purchaseOrders.forEach { purchaseOrder -> val purchaseOrderDetail = getPurchaseOrder(purchaseOrder.id) var purchaseOrderId: Long? = null //FP-MTMS // Process for Purchase Order (mainpo) // Assume only one PO in the PO (search by PO ID) val mainpo = purchaseOrderDetail?.data?.mainpo?.get(0) val pot = purchaseOrderDetail?.data?.pot // purchase_order + m18_data_log table if (mainpo != null) { // Find the latest m18 data log by m18 id & type logger.info("${poRefType}: Finding For Latest M18 Data Log...") val latestPurchaseOrderLog = m18DataLogService.findLatestM18DataLog(purchaseOrder.id, poRefType) // logger.info("${poRefType}: Latest M18 Data Log ID: ${latestPurchaseOrderLog?.id}") // Save to m18_data_log table logger.info("${poRefType}: Saving for M18 Data Log...") val mainpoJson = mainpo::class.memberProperties.associate { prop -> prop.name to prop.getter.call(mainpo) } .toMutableMap() val saveM18PurchaseOrderLogRequest = SaveM18DataLogRequest( id = null, refType = poRefType, m18Id = purchaseOrder.id, m18LastModifyDate = commonUtils.InstantToLocalDateTime(mainpo.lastModifyDate), dataLog = mainpoJson, status = true ) val saveM18PurchaseOrderLog = m18DataLogService.saveM18DataLog(saveM18PurchaseOrderLogRequest) // logger.info("${poRefType}: Saved M18 Data Log. ID: ${saveM18PurchaseOrderLog.id}") try { // Find the purchase_order if exist logger.info("${poRefType}: Finding exising purchase order...") val existingPurchaseOrder = latestPurchaseOrderLog?.id?.let { purchaseOrderService.findPurchaseOrderByM18Id(it) } logger.info("${poRefType}: Exising purchase order ID: ${existingPurchaseOrder?.id}") // Save to purchase_order table logger.info("${poRefType}: Saving purchase order...") val supplierId = shopService.findByM18Id(mainpo.venId)?.id val savePurchaseOrderRequest = SavePurchaseOrderRequest( id = existingPurchaseOrder?.id, code = mainpo.code, supplierId = supplierId, orderDate = commonUtils.InstantToLocalDateTime(mainpo.tDate), estimatedArrivalDate = commonUtils.InstantToLocalDateTime(mainpo.dDate), completeDate = null, status = PurchaseOrderStatus.PENDING.value, type = type.value, m18DataLogId = saveM18PurchaseOrderLog.id, ) val savePurchaseOrderResponse = purchaseOrderService.savePurchaseOrder(savePurchaseOrderRequest) purchaseOrderId = savePurchaseOrderResponse.id successList.add(purchaseOrder.id) logger.info("${poRefType}: Saved purchase order. ID: ${savePurchaseOrderResponse.id} | M18 ${poRefType} ID: ${purchaseOrder.id}") } catch (e: Exception) { failList.add(purchaseOrder.id) logger.error("${poRefType}: Saving Failure!") logger.error("Error on Function - ${e.stackTrace} | Type: ${poRefType} | M18 ID: ${purchaseOrder.id} | Different? ${mainpo.id}") logger.error(e.message) val errorSaveM18PurchaseOrderLogRequest = SaveM18DataLogRequest( id = saveM18PurchaseOrderLogRequest.id, refType = poRefType, m18Id = purchaseOrder.id, m18LastModifyDate = commonUtils.InstantToLocalDateTime(mainpo.lastModifyDate), dataLog = mainpoJson, status = false ) m18DataLogService.saveM18DataLog(errorSaveM18PurchaseOrderLogRequest) logger.error("${poRefType}: M18 Data Log Updated! Please see the error. ID: ${saveM18PurchaseOrderLogRequest.id}") } // purchase_order_line + m18_data_log if (pot != null) { // Loop for Purchase Order Lines (pot) pot.forEach { line -> // // Find the latest m18 data log by m18 id & type logger.info("${poLineRefType}: Finding For Latest M18 Data Log...") val latestPurchaseOrderLineLog = m18DataLogService.findLatestM18DataLog(line.id, poLineRefType) // logger.info("${poLineRefType}: Latest M18 Data Log ID: ${latestPurchaseOrderLineLog?.id}") // Save to m18_data_log table logger.info("${poLineRefType}: Saving for M18 Data Log...") val lineJson = line::class.memberProperties.associate { prop -> prop.name to prop.getter.call( line ) } .toMutableMap() val saveM18PurchaseOrderLineLogRequest = SaveM18DataLogRequest( id = null, refType = poLineRefType, m18Id = line.id, m18LastModifyDate = commonUtils.InstantToLocalDateTime(mainpo.lastModifyDate), dataLog = lineJson, status = true ) val saveM18PurchaseOrderLineLog = m18DataLogService.saveM18DataLog(saveM18PurchaseOrderLineLogRequest) // logger.info("${poLineRefType}: Saved M18 Data Log. ID: ${saveM18PurchaseOrderLineLog.id}") logger.info("${poLineRefType}: Finding item...") val item = itemsService.findByM18Id(line.proId) logger.info("${poLineRefType}: Item ID: ${item?.id} | M18 Item ID: ${line.proId}") try { // Find the purchase_order_line if exist logger.info("${poLineRefType}: Finding exising purchase order line...") val existingPurchaseOrderLine = latestPurchaseOrderLineLog?.id?.let { purchaseOrderLineService.findPurchaseOrderLineByM18Id(it) } logger.info("${poLineRefType}: Exising purchase order line ID: ${existingPurchaseOrderLine?.id}") // Save to purchase_order_line table logger.info("${poLineRefType}: Saving purchase order line...") val lineUom = val savePurchaseOrderLineRequest = SavePurchaseOrderLineRequest( id = existingPurchaseOrderLine?.id, itemId = item?.id, uomId = null, purchaseOrderId = purchaseOrderId, qty = line.qty, price = line.amt, m18CurrencyId = line.curId, status = existingPurchaseOrderLine?.status?.value ?: PurchaseOrderLineStatus.PENDING.value, m18DataLogId = saveM18PurchaseOrderLineLog.id, ) val savePurchaseOrderLineResponse = purchaseOrderLineService.savePurchaseOrderLine(savePurchaseOrderLineRequest) logger.info("${poLineRefType}: Purchase order ID: ${purchaseOrderId} | M18 ID: ${purchaseOrder.id}") logger.info("${poLineRefType}: Saved purchase order line. ID: ${savePurchaseOrderLineResponse.id} | M18 Line ID: ${line.id}") } catch (e: Exception) { failDetailList.add(line.id) logger.error("${poLineRefType}: Saving Failure!") logger.error("Error on Function - ${e.stackTrace} | Type: ${poLineRefType} | M18 ID: ${line.id}") logger.error(e.message) val errorSaveM18PurchaseOrderLineLogRequest = SaveM18DataLogRequest( id = saveM18PurchaseOrderLineLog.id, refType = "${poRefType}", m18Id = line.id, m18LastModifyDate = commonUtils.InstantToLocalDateTime(mainpo.lastModifyDate), dataLog = lineJson, status = false ) m18DataLogService.saveM18DataLog(errorSaveM18PurchaseOrderLineLogRequest) logger.error("${poLineRefType}: M18 Data Log Updated! Please see the error. ID: ${saveM18PurchaseOrderLineLog.id}") } } } else { // pot logger.error("${poLineRefType}: Saving Failure!") val saveM18PurchaseOrderLineLogRequest = SaveM18DataLogRequest( id = null, refType = "${poLineRefType}", m18Id = purchaseOrder.id, m18LastModifyDate = commonUtils.InstantToLocalDateTime(mainpo.lastModifyDate), dataLog = mutableMapOf(Pair("Error Message", "${poLineRefType} is null")), status = false ) val errorLog = m18DataLogService.saveM18DataLog(saveM18PurchaseOrderLineLogRequest) logger.error("${poLineRefType}: M18 Data Log Updated! Please see the error. ID: ${errorLog.id}") } } else { // mainpo logger.error("${poRefType}: Saving Failure!") val saveM18DataLogRequest = SaveM18DataLogRequest( id = null, refType = "${poRefType}", m18Id = purchaseOrder.id, // m18LastModifyDate = if(mainpo?.lastModifyDate != null) commonUtils.InstantToLocalDateTime(mainpo.lastModifyDate) else LocalDateTime.now(), m18LastModifyDate = LocalDateTime.now(), dataLog = mutableMapOf(Pair("Error Message", "${poRefType} is null")), status = false ) val errorLog = m18DataLogService.saveM18DataLog(saveM18DataLogRequest) logger.error("${poLineRefType}: M18 Data Log Updated! Please see the error. ID: ${errorLog.id}") } } } else { logger.error("${poRefType} List is null. May occur errors.") } } } else { logger.error("${poRefType} List is null. May occur errors.") } // End of save. Check result logger.info("Total Success (${poRefType}) (${successList.size}): $successList") if (failList.size > 0) { logger.error("Total Fail (${poRefType}) (${failList.size}): $failList") } logger.info("Total Success (${poLineRefType}) (${successDetailList.size}): $successDetailList") if (failDetailList.size > 0) { logger.error("Total Fail (${poLineRefType}) (${failDetailList.size}): $failDetailList") } logger.info("--------------------------------------------End - Saving M18 Purchase Order--------------------------------------------") } }