diff --git a/src/main/java/com/ffii/fpsms/m18/service/M18DeliveryOrderService.kt b/src/main/java/com/ffii/fpsms/m18/service/M18DeliveryOrderService.kt index b7e86e3..0ec68f5 100644 --- a/src/main/java/com/ffii/fpsms/m18/service/M18DeliveryOrderService.kt +++ b/src/main/java/com/ffii/fpsms/m18/service/M18DeliveryOrderService.kt @@ -24,7 +24,6 @@ import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderType import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.stereotype.Service -import java.sql.SQLException import java.time.LocalDateTime import java.time.format.DateTimeFormatter import kotlin.reflect.full.memberProperties @@ -225,7 +224,7 @@ open class M18DeliveryOrderService( val failDetailList = mutableListOf() val failItemDetailList = mutableListOf() val uomByM18IdCache = mutableMapOf() - val itemIdCache = mutableMapOf() + val itemIdCache = mutableMapOf() val stockUomIdCache = mutableMapOf, Long?>() val doRefType = "Delivery Order" @@ -374,14 +373,10 @@ open class M18DeliveryOrderService( // logger.info("${doLineRefType}: Saved M18 Data Log. ID: ${saveM18DeliveryOrderLineLog.id}") // logger.info("${doLineRefType}: Finding item...") - val itemId: Long? = itemIdCache.getOrPut(line.proId) { - val item = itemsService.findByM18Id(line.proId) - if (item == null) { - m18MasterDataService.saveProduct(line.proId)?.id - } else { - item.id + val itemId: Long? = itemIdCache[line.proId] + ?: m18MasterDataService.resolveLocalItemId(line.proId)?.also { + itemIdCache[line.proId] = it } - } val stockUomId: Long? = if (itemId != null) { val key = line.proId to line.unitId // safe key @@ -393,6 +388,23 @@ open class M18DeliveryOrderService( // logger.info("${doLineRefType}: Item ID: ${itemId} | M18 Item ID: ${line.proId}") + if (itemId == null) { + failDetailList.add(line.id) + failItemDetailList.add(line.proId) + logger.error( + "${doLineRefType}: Cannot resolve local item for M18 proId=${line.proId}, skipping line ${line.id}" + ) + val errorSaveM18DeliveryOrderLineLogRequest = SaveM18DataLogRequest( + id = saveM18DeliveryOrderLineLog.id, + dataLog = mutableMapOf( + "Exception Message" to "Cannot resolve local item for M18 proId=${line.proId}" + ), + statusEnum = M18DataLogStatus.FAIL + ) + m18DataLogService.saveM18DataLog(errorSaveM18DeliveryOrderLineLogRequest) + return@forEach + } + try { // Find the delivery_order_line if exist // logger.info("${doLineRefType}: Finding exising delivery order line...") @@ -454,7 +466,7 @@ open class M18DeliveryOrderService( 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} | Delivery order ID: ${deliveryOrderId} | M18 ID: ${deliveryOrder.id}") - } catch (e: SQLException) { + } catch (e: Exception) { failDetailList.add(line.id) failItemDetailList.add(line.proId) // logger.error("${doLineRefType}: Saving Failure!") 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 3b01ec7..459ad0b 100644 --- a/src/main/java/com/ffii/fpsms/m18/service/M18MasterDataService.kt +++ b/src/main/java/com/ffii/fpsms/m18/service/M18MasterDataService.kt @@ -188,6 +188,13 @@ open class M18MasterDataService( ) } + /** Resolve local items.id for an M18 product id; sync from M18 when missing. */ + open fun resolveLocalItemId(m18ItemId: Long): Long? { + itemsService.findByM18Id(m18ItemId)?.id?.let { return it } + saveProduct(m18ItemId)?.id?.let { return it } + return itemsService.findByM18Id(m18ItemId)?.id + } + open fun saveProduct(id: Long): MessageResponse? { try { ensureCunitSeededForAllIfEmpty() @@ -231,9 +238,18 @@ open class M18MasterDataService( ) val savedItem = itemsService.saveItem(saveItemRequest) + val localItemId = savedItem.id + if (localItemId == null) { + logger.error("saveItem returned null id for M18 item $id (code=${pro.code}): ${savedItem.message}") + return null + } + if (savedItem.errorPosition == "code") { + logger.error("saveItem duplicate code for M18 item $id (code=${pro.code}): ${savedItem.message}") + return null + } 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 existingItemUoms = itemUomService.findAllByItemsId(localItemId) val m18ItemUomIds = price?.map { it.id } ?: listOf() // Delete the item uom @@ -267,7 +283,7 @@ open class M18MasterDataService( ) val itemUomRequest = ItemUomRequest( m18UomId = it.unitId, - itemId = savedItem.id, + itemId = localItemId, baseUnit = it.basicUnit, stockUnit = it.stkUnit, pickingUnit = it.pickUnit, @@ -284,12 +300,11 @@ open class M18MasterDataService( deleted = it.expired || endInstant.isBefore(now) ) -// logger.info("saved item id: ${savedItem.id}") itemUomService.saveItemUom(itemUomRequest) } logger.info("Success (M18 Item): ${id} | ${pro.code} | ${pro.desc}") - return savedItem + return savedItem.copy(id = localItemId) } else { logger.error("Fail Message: ${itemDetail?.messages?.get(0)?.msgDetail}") logger.error("Fail: Item ID - ${id} Not Found") @@ -404,11 +419,20 @@ open class M18MasterDataService( ) val savedItem = itemsService.saveItem(saveItemRequest) + val localItemId = savedItem.id + if (localItemId == null) { + failList.add(item.id) + logger.error("saveItem returned null id for M18 item ${item.id} (code=${pro.code}): ${savedItem.message}") + return@forEach + } + if (savedItem.errorPosition == "code") { + failList.add(item.id) + logger.error("saveItem duplicate code for M18 item ${item.id} (code=${pro.code}): ${savedItem.message}") + return@forEach + } logger.info("Processing item uom...") - // Optional: cache findAllByItemsId if you think it might be called multiple times - // (usually not needed here because each savedItem.id is unique) - val existingItemUoms = savedItem.id?.let { itemUomService.findAllByItemsId(it) } + val existingItemUoms = itemUomService.findAllByItemsId(localItemId) val m18ItemUomIds = price?.map { it.id } ?: listOf() @@ -442,7 +466,7 @@ open class M18MasterDataService( val itemUomRequest = ItemUomRequest( m18UomId = it.unitId, - itemId = savedItem.id, + itemId = localItemId, baseUnit = it.basicUnit, stockUnit = it.stkUnit, pickingUnit = it.pickUnit, 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 e805eb0..daa2977 100644 --- a/src/main/java/com/ffii/fpsms/m18/service/M18PurchaseOrderService.kt +++ b/src/main/java/com/ffii/fpsms/m18/service/M18PurchaseOrderService.kt @@ -439,14 +439,25 @@ open class M18PurchaseOrderService( // logger.info("${poLineRefType}: Saved M18 Data Log. ID: ${saveM18PurchaseOrderLineLog.id}") // logger.info("${poLineRefType}: Finding item...") - val item = itemsService.findByM18Id(line.proId) - val itemId: Long? = if (item == null) { - m18MasterDataService.saveProduct(line.proId)?.id - } else { - item.id - } + val itemId: Long? = m18MasterDataService.resolveLocalItemId(line.proId) logger.info("${poLineRefType}: Item ID: ${itemId} | M18 Item ID: ${line.proId}") + if (itemId == null) { + failDetailList.add(line.id) + logger.error( + "${poLineRefType}: Cannot resolve local item for M18 proId=${line.proId}, skipping line ${line.id}" + ) + val errorSaveM18PurchaseOrderLineLogRequest = SaveM18DataLogRequest( + id = saveM18PurchaseOrderLineLog.id, + dataLog = mutableMapOf( + "Exception Message" to "Cannot resolve local item for M18 proId=${line.proId}" + ), + statusEnum = M18DataLogStatus.FAIL + ) + m18DataLogService.saveM18DataLog(errorSaveM18PurchaseOrderLineLogRequest) + return@forEach + } + try { // Find the purchase_order_line if exist (stable key: PO + M18 line id) // logger.info("${poLineRefType}: Finding exising purchase order line...") diff --git a/src/main/java/com/ffii/fpsms/modules/master/service/ItemsService.kt b/src/main/java/com/ffii/fpsms/modules/master/service/ItemsService.kt index cd7cca9..ce85564 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/service/ItemsService.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/service/ItemsService.kt @@ -647,8 +647,21 @@ open class ItemsService( open fun saveItem(request: NewItemRequest): MessageResponse { val duplicatedItem = itemsRepository.findByCodeAndTypeAndDeletedFalse(request.code, request.type) if (duplicatedItem != null && duplicatedItem.id != request.id) { + if (request.m18Id != null && request.id == null && duplicatedItem.m18Id == null) { + duplicatedItem.m18Id = request.m18Id + duplicatedItem.m18LastModifyDate = request.m18LastModifyDate + val linked = itemsRepository.saveAndFlush(duplicatedItem) + return MessageResponse( + id = linked.id, + code = linked.code, + name = linked.name, + type = linked.type.toString(), + message = "Linked m18Id to existing item with same code", + errorPosition = null, + ) + } return MessageResponse( - id = request.id, + id = request.id ?: duplicatedItem.id, code = request.code, name = request.name, type = request.type.toString(),