diff --git a/src/main/java/com/ffii/fpsms/m18/service/M18DeliveryOrderService.kt b/src/main/java/com/ffii/fpsms/m18/service/M18DeliveryOrderService.kt new file mode 100644 index 0000000..a8b8a03 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/m18/service/M18DeliveryOrderService.kt @@ -0,0 +1,412 @@ +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.enums.M18DataLogStatus +import com.ffii.fpsms.m18.model.* +import com.ffii.fpsms.m18.utils.CommonUtils +import com.ffii.fpsms.m18.web.models.M18TestDoRequest +import com.ffii.fpsms.m18.web.models.M18TestPoRequest +import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderLineStatus +import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatus +import com.ffii.fpsms.modules.deliveryOrder.service.DeliveryOrderLineService +import com.ffii.fpsms.modules.deliveryOrder.service.DeliveryOrderService +import com.ffii.fpsms.modules.deliveryOrder.web.models.SaveDeliveryOrderLineRequest +import com.ffii.fpsms.modules.deliveryOrder.web.models.SaveDeliveryOrderRequest +import com.ffii.fpsms.modules.master.entity.Items +import com.ffii.fpsms.modules.master.service.ItemUomService +import com.ffii.fpsms.modules.master.service.ItemsService +import com.ffii.fpsms.modules.master.service.ShopService +import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderType +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 M18DeliveryOrderService( + val m18Config: M18Config, + val apiCallerService: ApiCallerService, + val m18DataLogService: M18DataLogService, + val deliveryOrderService: DeliveryOrderService, + val deliveryOrderLineService: DeliveryOrderLineService, + val itemsService: ItemsService, + val shopService: ShopService, + val itemUomService: ItemUomService, + val m18MasterDataService: M18MasterDataService, +) { + val commonUtils = CommonUtils() + val logger: Logger = LoggerFactory.getLogger(JwtTokenUtil::class.java) + + val lastModifyDateStart = "2025-05-14 14:00:00" + val lastModifyDateEnd = "2025-05-14 14:30:00" +// val lastModifyDateConds = +// "lastModifyDate=largerOrEqual=${lastModifyDateStart}=and=lastModifyDate=lessOrEqual=${lastModifyDateEnd}" +// 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 + // Sharing same API with po + val M18_LOAD_PURCHASE_ORDER_API = "/root/api/read/po" + val M18_FETCH_PURCHASE_ORDER_LIST_API = "/search/search" + + // Include shop po + open fun getDeliveryOrdersWithType(request: M18TestDoRequest): M18PurchaseOrderListResponseWithType? { + val deliveryOrders = M18PurchaseOrderListResponseWithType(mutableListOf()) + val lastModifyDateConds = + "lastModifyDate=largerOrEqual=${request.modifiedDateFrom ?: lastModifyDateStart}=and=lastModifyDate=lessOrEqual=${request.modifiedDateTo ?: lastModifyDateEnd}" + + // Shop PO + val shopPoBuyers = commonUtils.listToString(listOf(m18Config.BEID_TOA), "beId=equal=", "=or=") + val shopPoSupplier = commonUtils.listToString( + shopService.findM18VendorIdsByCodeRegexp(m18Config.SHOP_PO_SUPPLIER), + "venId=equal=", + "=or=" + ) + val shopPoConds = "(${shopPoBuyers})=and=(${shopPoSupplier})=and=(${lastModifyDateConds})" + println("shopPoConds: ${shopPoConds}") + val shopPoParams = M18PurchaseOrderListRequest( + params = null, + conds = shopPoConds + ) + + try { + deliveryOrders.valuesWithType += Pair( + PurchaseOrderType.SHOP, apiCallerService.get( + M18_FETCH_PURCHASE_ORDER_LIST_API, + shopPoParams + ).block() + ) + } catch (e: Exception) { + logger.error("(Getting Shop Po list) Error on Function - ${e.stackTrace}") + logger.error(e.message) + } + + return deliveryOrders + } + + open fun getDeliveryOrder(id: Long): M18PurchaseOrderResponse? { + val deliveryOrderParams = M18PurchaseOrderRequest( + id = id + ) + + var deliveryOrder: M18PurchaseOrderResponse? = null + + try { + deliveryOrder = apiCallerService.get( + M18_LOAD_PURCHASE_ORDER_API, + deliveryOrderParams + ).block() + } catch (e: Exception) { + logger.error("(Getting Po Detail) Error on Function - ${e.stackTrace}") + logger.error(e.message) + } + + return deliveryOrder + } + + open fun saveDeliveryOrders(request: M18TestDoRequest) { + logger.info("--------------------------------------------Start - Saving M18 Delivery Order--------------------------------------------") + val deliveryOrdersWithType = getDeliveryOrdersWithType(request) + + val successList = mutableListOf() + val successDetailList = mutableListOf() + val failList = mutableListOf() + val failDetailList = mutableListOf() + val failItemDetailList = mutableListOf() + + val doRefType = "Delivery Order" + val doLineRefType = "Delivery Order Line" + + if (deliveryOrdersWithType != null) { + // Loop for Delivery Orders (values) + deliveryOrdersWithType.valuesWithType.forEach { deliveryOrderWithType -> + val type = deliveryOrderWithType.first + // if success + val deliveryOrdersValues = deliveryOrderWithType.second?.values + // if fail + val deliveryOrdersMessages = deliveryOrderWithType.second?.messages + + if (deliveryOrdersValues != null) { + deliveryOrdersValues.forEach { deliveryOrder -> + val deliveryOrderDetail = getDeliveryOrder(deliveryOrder.id) + + var deliveryOrderId: Long? = null //FP-MTMS + + // Process for Delivery Order (mainpo) + // Assume only one DO in the DO (search by DO ID) + val mainpo = deliveryOrderDetail?.data?.mainpo?.get(0) + val pot = deliveryOrderDetail?.data?.pot + val deliveryOrderLineMessage = deliveryOrderDetail?.messages + + // delivery_order + m18_data_log table + if (mainpo != null) { + // Find the latest m18 data log by m18 id & type + logger.info("${doRefType}: Finding For Latest M18 Data Log...") + val latestDeliveryOrderLog = + m18DataLogService.findLatestM18DataLogWithSuccess(deliveryOrder.id, doRefType) + + logger.info(latestDeliveryOrderLog.toString()) + // Save to m18_data_log table + logger.info("${doRefType}: Saving for M18 Data Log...") + val mainpoJson = + mainpo::class.memberProperties.associate { prop -> prop.name to prop.getter.call(mainpo) } + .toMutableMap() + + val saveM18DeliveryOrderLogRequest = SaveM18DataLogRequest( + id = null, + refType = doRefType, + m18Id = deliveryOrder.id, + m18LastModifyDate = commonUtils.timestampToLocalDateTime(mainpo.lastModifyDate), +// dataLog = mainpoJson, + statusEnum = M18DataLogStatus.NOT_PROCESS + ) + + val saveM18DeliveryOrderLog = + m18DataLogService.saveM18DataLog(saveM18DeliveryOrderLogRequest) +// logger.info("${doRefType}: Saved M18 Data Log. ID: ${saveM18DeliveryOrderLog.id}") + + try { + // Find the delivery_order if exist + logger.info("${doRefType}: Finding exising delivery order...") + val existingDeliveryOrder = + latestDeliveryOrderLog?.id?.let { deliveryOrderService.findByM18DataLogId(it) } + logger.info("${doRefType}: Exising delivery order ID: ${existingDeliveryOrder?.id}") + + // Save to delivery_order table + logger.info("${doRefType}: Saving delivery order...") + val saveDeliveryOrderRequest = SaveDeliveryOrderRequest( + id = existingDeliveryOrder?.id, + code = mainpo.code, + m18SupplierId = mainpo.venId, + m18ShopId = mainpo.virDeptId, + m18CurrencyId = mainpo.curId, + orderDate = commonUtils.timestampToLocalDateTime(mainpo.tDate), + estimatedArrivalDate = commonUtils.timestampToLocalDateTime(mainpo.dDate), + completeDate = null, + status = DeliveryOrderStatus.PENDING.value, + type = type.value, + m18DataLogId = saveM18DeliveryOrderLog.id, + handlerId = null + ) + + val saveDeliveryOrderResponse = + deliveryOrderService.saveDeliveryOrder(saveDeliveryOrderRequest) + deliveryOrderId = saveDeliveryOrderResponse.id + + // Update m18_data_log with success + val successSaveM18DeliveryOrderLogRequest = SaveM18DataLogRequest( + id = saveM18DeliveryOrderLog.id, + dataLog = mainpoJson, + statusEnum = M18DataLogStatus.SUCCESS + ) + + m18DataLogService.saveM18DataLog(successSaveM18DeliveryOrderLogRequest) + + // log success info + successList.add(deliveryOrder.id) + logger.info("${doRefType}: Saved delivery order. ID: ${saveDeliveryOrderResponse.id} | M18 ${doRefType} ID: ${deliveryOrder.id}") + + } catch (e: Exception) { + failList.add(deliveryOrder.id) + logger.error("${doRefType}: Saving Failure!") + logger.error("Error on Function - ${e.stackTrace} | Type: ${doRefType} | M18 ID: ${deliveryOrder.id} | Different? ${mainpo.id}") + logger.error(e.message) + + val errorSaveM18DeliveryOrderLogRequest = SaveM18DataLogRequest( + id = saveM18DeliveryOrderLog.id, + dataLog = mutableMapOf(Pair("Exception Message", e.message)), + statusEnum = M18DataLogStatus.FAIL + ) + + m18DataLogService.saveM18DataLog(errorSaveM18DeliveryOrderLogRequest) + logger.error("${doRefType}: M18 Data Log Updated! Please see the error. ID: ${saveM18DeliveryOrderLogRequest.id}") + } + + // delivery_order_line + m18_data_log + // TODO: check deleted po line? + if (pot != null) { + // Loop for Delivery Order Lines (pot) + pot.forEach { line -> + + // Find the latest m18 data log by m18 id & type + logger.info("${doLineRefType}: Finding For Latest M18 Data Log...") + val latestDeliveryOrderLineLog = + m18DataLogService.findLatestM18DataLogWithSuccess(line.id, doLineRefType) + // logger.info("${doLineRefType}: Latest M18 Data Log ID: ${latestDeliveryOrderLineLog?.id}") + + // Save to m18_data_log table + logger.info("${doLineRefType}: Saving for M18 Data Log...") + val lineJson = + line::class.memberProperties.associate { prop -> + prop.name to prop.getter.call( + line + ) + } + .toMutableMap() + val saveM18DeliveryOrderLineLogRequest = SaveM18DataLogRequest( + id = null, + refType = doLineRefType, + m18Id = line.id, + m18LastModifyDate = commonUtils.timestampToLocalDateTime(mainpo.lastModifyDate), +// dataLog = lineJson, + statusEnum = M18DataLogStatus.NOT_PROCESS + ) + + val saveM18DeliveryOrderLineLog = + m18DataLogService.saveM18DataLog(saveM18DeliveryOrderLineLogRequest) + + // logger.info("${doLineRefType}: Saved M18 Data Log. ID: ${saveM18DeliveryOrderLineLog.id}") + logger.info("${doLineRefType}: Finding item...") + val item = itemsService.findByM18Id(line.proId) + var itemId: Long? = null + if (item == null) { + itemId = m18MasterDataService.saveProduct(line.proId)?.id + } else { + itemId = item.id + } + + logger.info("${doLineRefType}: Item ID: ${itemId} | M18 Item ID: ${line.proId}") + + try { + // Find the delivery_order_line if exist + logger.info("${doLineRefType}: Finding exising delivery order line...") + val existingDeliveryOrderLine = latestDeliveryOrderLineLog?.id?.let { + deliveryOrderLineService.findDeliveryOrderLineByM18Id(it) + } + logger.info("${doLineRefType}: Exising delivery order line ID: ${existingDeliveryOrderLine?.id}") + + // Save to delivery_order_line table + logger.info("${doLineRefType}: Saving delivery order line...") + val itemUom = itemId?.let { itemUomService.findSalesUnitByItemId(it) } + val saveDeliveryOrderLineRequest = SaveDeliveryOrderLineRequest( + id = existingDeliveryOrderLine?.id, + itemId = itemId, + uomId = itemUom?.uom?.id, + deliveryOrderId = deliveryOrderId, + qty = line.qty, + price = line.amt, +// m18CurrencyId = mainpo.curId, + status = existingDeliveryOrderLine?.status?.value + ?: DeliveryOrderLineStatus.PENDING.value, + m18DataLogId = saveM18DeliveryOrderLineLog.id, + ) + + val saveDeliveryOrderLineResponse = + deliveryOrderLineService.saveDeliveryOrderLine(saveDeliveryOrderLineRequest) + + // Update m18_data_log with success + val successSaveM18DeliveryOrderLineLogRequest = SaveM18DataLogRequest( + id = saveM18DeliveryOrderLineLog.id, + dataLog = lineJson, + statusEnum = M18DataLogStatus.SUCCESS + ) + + m18DataLogService.saveM18DataLog(successSaveM18DeliveryOrderLineLogRequest) + + // log success info + successDetailList.add(line.id) + logger.info("${doLineRefType}: Delivery order ID: ${deliveryOrderId} | M18 ID: ${deliveryOrder.id}") + logger.info("${doLineRefType}: Saved delivery order line. ID: ${saveDeliveryOrderLineResponse.id} | M18 Line ID: ${line.id}") + } catch (e: Exception) { + failDetailList.add(line.id) + failItemDetailList.add(line.proId) + logger.error("${doLineRefType}: Saving Failure!") + logger.error("Error on Function - ${e.stackTrace} | Type: ${doLineRefType} | M18 ID: ${line.id}") + logger.error(e.message) + + val errorSaveM18DeliveryOrderLineLogRequest = SaveM18DataLogRequest( + id = saveM18DeliveryOrderLineLog.id, + dataLog = mutableMapOf(Pair("Exception Message", e.message)), + statusEnum = M18DataLogStatus.FAIL + ) + + m18DataLogService.saveM18DataLog(errorSaveM18DeliveryOrderLineLogRequest) + logger.error("${doLineRefType}: M18 Data Log Updated! Please see the error. ID: ${saveM18DeliveryOrderLineLog.id}") + } + } + } else { + // pot + logger.error("${doLineRefType}: Saving Failure!") + val saveM18DeliveryOrderLineLogRequest = SaveM18DataLogRequest( + id = null, + refType = "${doLineRefType}", + m18Id = deliveryOrder.id, + m18LastModifyDate = commonUtils.timestampToLocalDateTime(mainpo.lastModifyDate), +// dataLog = mutableMapOf(Pair("Error Message", "${doLineRefType} is null")), + dataLog = mutableMapOf( + Pair( + "${doLineRefType} Error Message", + "pot is null" + ), + Pair( + "${doLineRefType} Error Code", + deliveryOrderLineMessage?.get(0)?.msgCode ?: "No Msg Code from M18" + ), + Pair( + "${doLineRefType} Error Detail", + deliveryOrderLineMessage?.get(0)?.msgDetail ?: "No Msg Detail from M18" + ), + ), + statusEnum = M18DataLogStatus.FAIL + ) + + val errorLog = m18DataLogService.saveM18DataLog(saveM18DeliveryOrderLineLogRequest) + logger.error("${doLineRefType}: M18 Data Log Updated! Please see the error. ID: ${errorLog.id}") + } + } else { + // mainpo + failList.add(deliveryOrder.id) + logger.error("${doRefType}: Saving Failure!") + val saveM18DataLogRequest = SaveM18DataLogRequest( + id = null, + refType = "${doRefType}", + m18Id = deliveryOrder.id, + // m18LastModifyDate = if(mainpo?.lastModifyDate != null) commonUtils.instantToLocalDateTime(mainpo.lastModifyDate) else LocalDateTime.now(), + m18LastModifyDate = LocalDateTime.now(), + dataLog = mutableMapOf( + Pair( + "${doRefType} Error", + "mainpo is null" + ), + Pair( + "${doRefType} Error Code", + deliveryOrdersMessages?.get(0)?.msgCode ?: "No Msg Code from M18" + ), + Pair( + "${doRefType} Error Detail", + deliveryOrdersMessages?.get(0)?.msgDetail ?: "No Msg Detail from M18" + ), + ), + statusEnum = M18DataLogStatus.FAIL + ) + + val errorLog = m18DataLogService.saveM18DataLog(saveM18DataLogRequest) + logger.error("${doLineRefType}: M18 Data Log Updated! Please see the error. ID: ${errorLog.id}") + } + } + } else { + logger.error("${doRefType} List is null. May occur errors.") + } + } + } else { + logger.error("${doRefType} List is null. May occur errors.") + } + + // End of save. Check result + logger.info("Total Success (${doRefType}) (${successList.size}): $successList") +// if (failList.size > 0) { + logger.error("Total Fail (${doRefType}) (${failList.size}): $failList") +// } + + logger.info("Total Success (${doLineRefType}) (${successDetailList.size}): $successDetailList") +// if (failDetailList.size > 0) { + logger.error("Total Fail (${doLineRefType}) (${failDetailList.size}): $failDetailList") + logger.error("Total Fail M18 Items (${doLineRefType}) (${failItemDetailList.distinct().size}): ${failItemDetailList.distinct()}") +// } + logger.info("--------------------------------------------End - Saving M18 Delivery Order--------------------------------------------") + } +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/m18/service/M18MasterDataService.kt b/src/main/java/com/ffii/fpsms/m18/service/M18MasterDataService.kt index 77b5465..fdf765e 100644 --- a/src/main/java/com/ffii/fpsms/m18/service/M18MasterDataService.kt +++ b/src/main/java/com/ffii/fpsms/m18/service/M18MasterDataService.kt @@ -6,6 +6,7 @@ import com.ffii.fpsms.m18.M18Config import com.ffii.fpsms.m18.model.* import com.ffii.fpsms.m18.utils.CommonUtils import com.ffii.fpsms.m18.web.models.M18TestMasterDateRequest +import com.ffii.fpsms.modules.master.entity.Items import com.ffii.fpsms.modules.master.entity.UomConversion import com.ffii.fpsms.modules.master.enums.ShopType import com.ffii.fpsms.modules.master.service.* @@ -137,6 +138,82 @@ open class M18MasterDataService( ) } + open fun saveProduct(id: Long): MessageResponse? { + try { + val itemDetail = getProduct(id) + val pro = itemDetail?.data?.pro?.get(0) + val price = itemDetail?.data?.price + + if (itemDetail != null && pro != null) { + val existingItem = itemsService.findByM18Id(id) + val saveItemRequest = NewItemRequest( + code = pro.code, + name = pro.desc, +// type = if (pro.seriesId == m18Config.SERIESID_PF) ProductType.MATERIAL +// else ItemType.PRODUCT, + type = ItemType.MATERIAL, + id = existingItem?.id, + description = pro.desc, + remarks = null, + shelfLife = null, + countryOfOrigin = null, + maxQty = null, + m18Id = id, + m18LastModifyDate = commonUtils.timestampToLocalDateTime(pro.lastModifyDate) + ) + + val savedItem = itemsService.saveItem(saveItemRequest) + logger.info("Processing item uom...") + // Find the item uom that ready to delete (not in m18) + val existingItemUoms = savedItem.id?.let { itemUomService.findAllByItemsId(it) } + val m18ItemUomIds = price?.map { it.id } ?: listOf() + + // Delete the item uom + logger.info("Deleting item uom...") +// logger.info("Item Uom: ${existingItemUoms?.map { it.m18Id }}") +// logger.info("M18: ${m18ItemUomIds}") + existingItemUoms?.filter { it.m18Id !in m18ItemUomIds }?.mapNotNull { it.id } + ?.let { itemUomService.deleteItemUoms(it) } + + // Update the item uom + logger.info("Updating item uom...") + price?.forEach { + val itemUomRequest = ItemUomRequest( + m18UomId = it.unitId, + itemId = savedItem.id, + baseUnit = it.basicUnit, + stockUnit = it.stkUnit, + pickingUnit = it.pickUnit, + salesUnit = it.saleUnit, + purchaseUnit = it.purUnit, + price = null, + currencyId = null, + m18Id = it.id, + m18LastModifyDate = commonUtils.timestampToLocalDateTime(pro.lastModifyDate), + ratioD = it.ratioD, + ratioN = it.ratioN, + deleted = it.expired + ) + +// logger.info("saved item id: ${savedItem.id}") + itemUomService.saveItemUom(itemUomRequest) + } + + logger.info("Success (M18 Item): ${id} | ${pro.code} | ${pro.desc}") + return savedItem + } else { + logger.error("Fail Message: ${itemDetail?.messages?.get(0)?.msgDetail}") + logger.error("Fail: Item ID - ${id} Not Found") + return null + } + } catch (e: Exception) { + logger.error("Exception") + logger.error("Fail Message: ${e.message}") + logger.error("Fail: Item ID - ${id}") + return null + } + } + open fun saveProducts(request: M18TestMasterDateRequest) { logger.info("--------------------------------------------Start - Saving M18 Products / Materials--------------------------------------------") val items = getProducts(request) diff --git a/src/main/java/com/ffii/fpsms/m18/service/M18PurchaseOrderService.kt b/src/main/java/com/ffii/fpsms/m18/service/M18PurchaseOrderService.kt index 74271e2..784f933 100644 --- a/src/main/java/com/ffii/fpsms/m18/service/M18PurchaseOrderService.kt +++ b/src/main/java/com/ffii/fpsms/m18/service/M18PurchaseOrderService.kt @@ -7,6 +7,8 @@ import com.ffii.fpsms.m18.enums.M18DataLogStatus import com.ffii.fpsms.m18.model.* import com.ffii.fpsms.m18.utils.CommonUtils import com.ffii.fpsms.m18.web.models.M18TestPoRequest +import com.ffii.fpsms.modules.deliveryOrder.service.DeliveryOrderLineService +import com.ffii.fpsms.modules.deliveryOrder.service.DeliveryOrderService import com.ffii.fpsms.modules.master.service.ItemUomService import com.ffii.fpsms.modules.master.service.ItemsService import com.ffii.fpsms.modules.master.service.ShopService @@ -30,9 +32,12 @@ open class M18PurchaseOrderService( val m18DataLogService: M18DataLogService, val purchaseOrderService: PurchaseOrderService, val purchaseOrderLineService: PurchaseOrderLineService, + val deliveryOrderService: DeliveryOrderService, + val deliveryOrderLineService: DeliveryOrderLineService, val itemsService: ItemsService, val shopService: ShopService, val itemUomService: ItemUomService, + val m18MasterDataService: M18MasterDataService ) { val commonUtils = CommonUtils() val logger: Logger = LoggerFactory.getLogger(JwtTokenUtil::class.java) @@ -49,7 +54,7 @@ open class M18PurchaseOrderService( 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 + // Include material po, oem po open fun getPurchaseOrdersWithType(request: M18TestPoRequest): M18PurchaseOrderListResponseWithType? { val purchaseOrders = M18PurchaseOrderListResponseWithType(mutableListOf()) val lastModifyDateConds = @@ -83,7 +88,7 @@ open class M18PurchaseOrderService( } // Shop PO - val shopPoBuyers = commonUtils.listToString(listOf(m18Config.BEID_TOA), "beId=equal=", "=or=") + /* val shopPoBuyers = commonUtils.listToString(listOf(m18Config.BEID_TOA), "beId=equal=", "=or=") val shopPoSupplier = commonUtils.listToString( shopService.findM18VendorIdsByCodeRegexp(m18Config.SHOP_PO_SUPPLIER), "venId=equal=", @@ -106,7 +111,7 @@ open class M18PurchaseOrderService( } catch (e: Exception) { logger.error("(Getting Shop Po list) 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=") @@ -310,7 +315,13 @@ open class M18PurchaseOrderService( // 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}") + var itemId: Long? = null + if (item == null) { + itemId = m18MasterDataService.saveProduct(line.proId)?.id + } else { + itemId = item.id + } + logger.info("${poLineRefType}: Item ID: ${itemId} | M18 Item ID: ${line.proId}") try { // Find the purchase_order_line if exist @@ -322,10 +333,10 @@ open class M18PurchaseOrderService( // Save to purchase_order_line table logger.info("${poLineRefType}: Saving purchase order line...") - val itemUom = item?.id?.let { itemUomService.findPurchaseUnitByItemId(it) } + val itemUom = itemId?.let { itemUomService.findPurchaseUnitByItemId(it) } val savePurchaseOrderLineRequest = SavePurchaseOrderLineRequest( id = existingPurchaseOrderLine?.id, - itemId = item?.id, + itemId = itemId, uomId = itemUom?.uom?.id, purchaseOrderId = purchaseOrderId, qty = line.qty, diff --git a/src/main/java/com/ffii/fpsms/m18/web/M18TestController.kt b/src/main/java/com/ffii/fpsms/m18/web/M18TestController.kt index 60f2b00..cad08c9 100644 --- a/src/main/java/com/ffii/fpsms/m18/web/M18TestController.kt +++ b/src/main/java/com/ffii/fpsms/m18/web/M18TestController.kt @@ -2,9 +2,11 @@ package com.ffii.fpsms.m18.web import com.ffii.core.utils.JwtTokenUtil import com.ffii.fpsms.m18.M18Config +import com.ffii.fpsms.m18.service.M18DeliveryOrderService import com.ffii.fpsms.m18.service.M18MasterDataService import com.ffii.fpsms.m18.service.M18PurchaseOrderService import com.ffii.fpsms.m18.service.M18PurchaseQuotationService +import com.ffii.fpsms.m18.web.models.M18TestDoRequest import com.ffii.fpsms.m18.web.models.M18TestMasterDateRequest import com.ffii.fpsms.m18.web.models.M18TestPoRequest import com.ffii.fpsms.m18.web.models.M18TestPqRequest @@ -18,12 +20,7 @@ import com.ffii.fpsms.modules.master.service.ShopService import jakarta.validation.Valid import org.slf4j.Logger import org.slf4j.LoggerFactory -import org.springframework.web.bind.annotation.GetMapping -import org.springframework.web.bind.annotation.PostMapping -import org.springframework.web.bind.annotation.RequestBody -import org.springframework.web.bind.annotation.RequestMapping -import org.springframework.web.bind.annotation.RequestParam -import org.springframework.web.bind.annotation.RestController +import org.springframework.web.bind.annotation.* @RestController @@ -37,6 +34,7 @@ class M18TestController ( private val m18Config: M18Config, private val itemUomService: ItemUomService, private val m18PurchaseQuotationService: M18PurchaseQuotationService, + private val m18DeliveryOrderService: M18DeliveryOrderService, ) { var logger: Logger = LoggerFactory.getLogger(JwtTokenUtil::class.java) @@ -95,6 +93,12 @@ class M18TestController ( m18MasterDataService.saveProducts(request) } + @GetMapping("/product/{id}") + fun m18Product(@PathVariable id: Long) { + logger.info("Access token: ${m18Config.ACCESS_TOKEN}") + m18MasterDataService.saveProduct(id) + } + @PostMapping("/vendor") fun m18Vendor(@Valid @RequestBody request: M18TestMasterDateRequest) { logger.info("Access token: ${m18Config.ACCESS_TOKEN}") @@ -132,6 +136,13 @@ class M18TestController ( m18PurchaseOrderService.savePurchaseOrders(request) } + // --------------------------------------------- Purchase Order --------------------------------------------- /// + @PostMapping("/do") + fun m18DO(@Valid @RequestBody request: M18TestDoRequest) { + logger.info("Access token: ${m18Config.ACCESS_TOKEN}") + m18DeliveryOrderService.saveDeliveryOrders(request) + } + // --------------------------------------------- Purchase Quotation --------------------------------------------- /// @PostMapping("/pq") fun m18PQ(@Valid @RequestBody request: M18TestPqRequest) { diff --git a/src/main/java/com/ffii/fpsms/m18/web/models/M18TestRequest.kt b/src/main/java/com/ffii/fpsms/m18/web/models/M18TestRequest.kt index 71bc2e2..9b7a2ec 100644 --- a/src/main/java/com/ffii/fpsms/m18/web/models/M18TestRequest.kt +++ b/src/main/java/com/ffii/fpsms/m18/web/models/M18TestRequest.kt @@ -5,6 +5,11 @@ data class M18TestPoRequest( val modifiedDateTo: String?, ) +data class M18TestDoRequest( + val modifiedDateFrom: String?, + val modifiedDateTo: String?, +) + data class M18TestPqRequest( val modifiedDateFrom: String? = null, val modifiedDateTo: String? = null, diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderLine.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderLine.kt index aaf7482..81b78ec 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderLine.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderLine.kt @@ -3,6 +3,9 @@ package com.ffii.fpsms.modules.deliveryOrder.entity import com.fasterxml.jackson.annotation.JsonBackReference import com.ffii.core.entity.BaseEntity import com.ffii.fpsms.m18.entity.M18DataLog +import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderLineStatus +import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderLineStatusConverter +import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderStatusConverter import com.ffii.fpsms.modules.master.entity.Items import com.ffii.fpsms.modules.master.entity.UomConversion import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrderLine @@ -35,10 +38,10 @@ open class DeliveryOrderLine: BaseEntity() { @Column(name = "price", precision = 14, scale = 2) open var price: BigDecimal? = null - @Size(max = 30) @NotNull @Column(name = "status", nullable = false, length = 30) - open var status: String? = null + @Convert(converter = DeliveryOrderLineStatusConverter::class) + open var status: DeliveryOrderLineStatus? = null @NotNull @ManyToOne diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderLineRepository.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderLineRepository.kt index 1057b71..2ebac47 100644 --- a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderLineRepository.kt +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderLineRepository.kt @@ -2,7 +2,9 @@ package com.ffii.fpsms.modules.deliveryOrder.entity import com.ffii.core.support.AbstractRepository import org.springframework.stereotype.Repository +import java.io.Serializable @Repository interface DeliveryOrderLineRepository : AbstractRepository { + fun findByM18DataLogIdAndDeletedIsFalse(m18datalogId: Serializable): DeliveryOrderLine? } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/enums/DeliveryOrderLineEnum.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/enums/DeliveryOrderLineEnum.kt new file mode 100644 index 0000000..69cb367 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/enums/DeliveryOrderLineEnum.kt @@ -0,0 +1,7 @@ +package com.ffii.fpsms.modules.deliveryOrder.enums + +enum class DeliveryOrderLineStatus(val value: String) { + PENDING("pending"), + PICKING("picking"), + COMPLETED("completed"); +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/enums/DeliveryOrderLineEnumConverter.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/enums/DeliveryOrderLineEnumConverter.kt new file mode 100644 index 0000000..fb5370b --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/enums/DeliveryOrderLineEnumConverter.kt @@ -0,0 +1,18 @@ +package com.ffii.fpsms.modules.deliveryOrder.enums + +import jakarta.persistence.AttributeConverter +import jakarta.persistence.Converter + +// Delivery Order Line Status +@Converter(autoApply = true) +class DeliveryOrderLineStatusConverter : AttributeConverter{ + override fun convertToDatabaseColumn(status: DeliveryOrderLineStatus?): String? { + return status?.value + } + + override fun convertToEntityAttribute(value: String?): DeliveryOrderLineStatus? { + return value?.let { v -> + DeliveryOrderLineStatus.entries.find { it.value == v } + } + } +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderLineService.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderLineService.kt new file mode 100644 index 0000000..d0cdeb6 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderLineService.kt @@ -0,0 +1,64 @@ +package com.ffii.fpsms.modules.deliveryOrder.service + +import com.ffii.fpsms.m18.entity.M18DataLogRepository +import com.ffii.fpsms.modules.deliveryOrder.entity.DeliveryOrderLine +import com.ffii.fpsms.modules.deliveryOrder.entity.DeliveryOrderLineRepository +import com.ffii.fpsms.modules.deliveryOrder.entity.DeliveryOrderRepository +import com.ffii.fpsms.modules.deliveryOrder.enums.DeliveryOrderLineStatus +import com.ffii.fpsms.modules.deliveryOrder.web.models.SaveDeliveryOrderLineRequest +import com.ffii.fpsms.modules.deliveryOrder.web.models.SaveDeliveryOrderLineResponse +import com.ffii.fpsms.modules.master.entity.ItemsRepository +import com.ffii.fpsms.modules.master.service.UomConversionService +import org.springframework.stereotype.Service +import kotlin.jvm.optionals.getOrDefault +import kotlin.jvm.optionals.getOrNull + +@Service +open class DeliveryOrderLineService( + private val deliveryOrderService: DeliveryOrderService, + private val deliveryOrderRepository: DeliveryOrderRepository, + private val deliveryOrderLineRepository: DeliveryOrderLineRepository, + private val itemsRepository: ItemsRepository, + private val m18DataLogRepository: M18DataLogRepository, + private val uomConversionService: UomConversionService, +) { + open fun findDeliveryOrderLineByM18Id(m18DataLogId: Long): DeliveryOrderLine? { + return deliveryOrderLineRepository.findByM18DataLogIdAndDeletedIsFalse(m18DataLogId) + } + + open fun saveDeliveryOrderLine(request: SaveDeliveryOrderLineRequest): SaveDeliveryOrderLineResponse { + val deliveryOrderLine = request.id?.let { + deliveryOrderLineRepository.findById(it).getOrDefault( + DeliveryOrderLine() + ) + } ?: DeliveryOrderLine(); + val item = request.itemId?.let { itemsRepository.findById(it).getOrNull() } + val deliveryOrder = request.deliveryOrderId?.let { deliveryOrderRepository.findById(it).getOrNull() } + val status = request.status?.let { status -> DeliveryOrderLineStatus.entries.find { it.value == status } } + val m18DataLog = request.m18DataLogId?.let { m18DataLogRepository.findById(it).getOrNull() } + val uom = request.uomId?.let { uomConversionService.find(it).getOrNull() } + + deliveryOrderLine.apply { + this.item = item + itemNo = item?.code + this.deliveryOrder = deliveryOrder + qty = request.qty + price = request.price + this.uom = uom + this.status = status + this.m18DataLog = m18DataLog ?: this.m18DataLog + } + + val savedDeliveryOrderLine = deliveryOrderLineRepository.saveAndFlush(deliveryOrderLine).let { + SaveDeliveryOrderLineResponse( + id = it.id, + itemNo = it.itemNo, + qty = it.qty, + price = it.price, + status = it.status?.value + ) + } + + return savedDeliveryOrderLine + } +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/SaveDeliveryOrderLineRequest.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/SaveDeliveryOrderLineRequest.kt new file mode 100644 index 0000000..96b642e --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/SaveDeliveryOrderLineRequest.kt @@ -0,0 +1,14 @@ +package com.ffii.fpsms.modules.deliveryOrder.web.models + +import java.math.BigDecimal + +data class SaveDeliveryOrderLineRequest( + val id: Long?, + val itemId: Long?, + val uomId: Long?, + val deliveryOrderId: Long?, + val qty: BigDecimal?, + val price: BigDecimal?, + val status: String?, + val m18DataLogId: Long?, +) diff --git a/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/SaveDeliveryOrderLineResponse.kt b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/SaveDeliveryOrderLineResponse.kt new file mode 100644 index 0000000..3008f66 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/SaveDeliveryOrderLineResponse.kt @@ -0,0 +1,11 @@ +package com.ffii.fpsms.modules.deliveryOrder.web.models + +import java.math.BigDecimal + +data class SaveDeliveryOrderLineResponse( + val id: Long?, + val itemNo: String?, + val qty: BigDecimal?, + val price: BigDecimal?, + val status: String?, +) diff --git a/src/main/java/com/ffii/fpsms/modules/master/entity/ItemUomRespository.kt b/src/main/java/com/ffii/fpsms/modules/master/entity/ItemUomRespository.kt index b273e79..eeefde1 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/entity/ItemUomRespository.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/entity/ItemUomRespository.kt @@ -17,6 +17,8 @@ interface ItemUomRespository : AbstractRepository { fun findByItemIdAndPurchaseUnitIsTrueAndDeletedIsFalse(itemId: Serializable): ItemUom? + fun findByItemIdAndSalesUnitIsTrueAndDeletedIsFalse(itemId: Serializable): ItemUom? + fun findByItemM18IdAndPurchaseUnitIsTrueAndDeletedIsFalse(itemM18Id: Long): ItemUom? fun findBaseUnitByItemIdAndBaseUnitIsTrueAndDeletedIsFalse(itemId: Long): ItemUom? } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/service/ItemUomService.kt b/src/main/java/com/ffii/fpsms/modules/master/service/ItemUomService.kt index 22f10c1..a35e4af 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/service/ItemUomService.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/service/ItemUomService.kt @@ -31,6 +31,10 @@ open class ItemUomService( return itemUomRespository.findByItemIdAndPurchaseUnitIsTrueAndDeletedIsFalse(itemId) } + open fun findSalesUnitByItemId(itemId: Long): ItemUom? { + return itemUomRespository.findByItemIdAndSalesUnitIsTrueAndDeletedIsFalse(itemId) + } + open fun findPurchaseUnitByM18ItemId(m18ItemId: Long): ItemUom? { return itemUomRespository.findByItemM18IdAndPurchaseUnitIsTrueAndDeletedIsFalse(m18ItemId) }