浏览代码

Add Delivery Order Line & Update M18 Purchase Order & Delivery Order

production_process
cyril.tsui 2 个月前
父节点
当前提交
3ec014d101
共有 14 个文件被更改,包括 655 次插入14 次删除
  1. +412
    -0
      src/main/java/com/ffii/fpsms/m18/service/M18DeliveryOrderService.kt
  2. +77
    -0
      src/main/java/com/ffii/fpsms/m18/service/M18MasterDataService.kt
  3. +17
    -6
      src/main/java/com/ffii/fpsms/m18/service/M18PurchaseOrderService.kt
  4. +17
    -6
      src/main/java/com/ffii/fpsms/m18/web/M18TestController.kt
  5. +5
    -0
      src/main/java/com/ffii/fpsms/m18/web/models/M18TestRequest.kt
  6. +5
    -2
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderLine.kt
  7. +2
    -0
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/entity/DeliveryOrderLineRepository.kt
  8. +7
    -0
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/enums/DeliveryOrderLineEnum.kt
  9. +18
    -0
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/enums/DeliveryOrderLineEnumConverter.kt
  10. +64
    -0
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/service/DeliveryOrderLineService.kt
  11. +14
    -0
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/SaveDeliveryOrderLineRequest.kt
  12. +11
    -0
      src/main/java/com/ffii/fpsms/modules/deliveryOrder/web/models/SaveDeliveryOrderLineResponse.kt
  13. +2
    -0
      src/main/java/com/ffii/fpsms/modules/master/entity/ItemUomRespository.kt
  14. +4
    -0
      src/main/java/com/ffii/fpsms/modules/master/service/ItemUomService.kt

+ 412
- 0
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<M18PurchaseOrderListResponse, M18PurchaseOrderListRequest>(
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<M18PurchaseOrderResponse, M18PurchaseOrderRequest>(
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<Long>()
val successDetailList = mutableListOf<Long>()
val failList = mutableListOf<Long>()
val failDetailList = mutableListOf<Long>()
val failItemDetailList = mutableListOf<Long>()

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--------------------------------------------")
}
}

+ 77
- 0
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.model.*
import com.ffii.fpsms.m18.utils.CommonUtils import com.ffii.fpsms.m18.utils.CommonUtils
import com.ffii.fpsms.m18.web.models.M18TestMasterDateRequest 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.entity.UomConversion
import com.ffii.fpsms.modules.master.enums.ShopType import com.ffii.fpsms.modules.master.enums.ShopType
import com.ffii.fpsms.modules.master.service.* 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) { open fun saveProducts(request: M18TestMasterDateRequest) {
logger.info("--------------------------------------------Start - Saving M18 Products / Materials--------------------------------------------") logger.info("--------------------------------------------Start - Saving M18 Products / Materials--------------------------------------------")
val items = getProducts(request) val items = getProducts(request)


+ 17
- 6
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.model.*
import com.ffii.fpsms.m18.utils.CommonUtils import com.ffii.fpsms.m18.utils.CommonUtils
import com.ffii.fpsms.m18.web.models.M18TestPoRequest 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.ItemUomService
import com.ffii.fpsms.modules.master.service.ItemsService import com.ffii.fpsms.modules.master.service.ItemsService
import com.ffii.fpsms.modules.master.service.ShopService import com.ffii.fpsms.modules.master.service.ShopService
@@ -30,9 +32,12 @@ open class M18PurchaseOrderService(
val m18DataLogService: M18DataLogService, val m18DataLogService: M18DataLogService,
val purchaseOrderService: PurchaseOrderService, val purchaseOrderService: PurchaseOrderService,
val purchaseOrderLineService: PurchaseOrderLineService, val purchaseOrderLineService: PurchaseOrderLineService,
val deliveryOrderService: DeliveryOrderService,
val deliveryOrderLineService: DeliveryOrderLineService,
val itemsService: ItemsService, val itemsService: ItemsService,
val shopService: ShopService, val shopService: ShopService,
val itemUomService: ItemUomService, val itemUomService: ItemUomService,
val m18MasterDataService: M18MasterDataService
) { ) {
val commonUtils = CommonUtils() val commonUtils = CommonUtils()
val logger: Logger = LoggerFactory.getLogger(JwtTokenUtil::class.java) 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_LOAD_PURCHASE_ORDER_API = "/root/api/read/po"
val M18_FETCH_PURCHASE_ORDER_LIST_API = "/search/search" 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? { open fun getPurchaseOrdersWithType(request: M18TestPoRequest): M18PurchaseOrderListResponseWithType? {
val purchaseOrders = M18PurchaseOrderListResponseWithType(mutableListOf()) val purchaseOrders = M18PurchaseOrderListResponseWithType(mutableListOf())
val lastModifyDateConds = val lastModifyDateConds =
@@ -83,7 +88,7 @@ open class M18PurchaseOrderService(
} }


// Shop PO // 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( val shopPoSupplier = commonUtils.listToString(
shopService.findM18VendorIdsByCodeRegexp(m18Config.SHOP_PO_SUPPLIER), shopService.findM18VendorIdsByCodeRegexp(m18Config.SHOP_PO_SUPPLIER),
"venId=equal=", "venId=equal=",
@@ -106,7 +111,7 @@ open class M18PurchaseOrderService(
} catch (e: Exception) { } catch (e: Exception) {
logger.error("(Getting Shop Po list) Error on Function - ${e.stackTrace}") logger.error("(Getting Shop Po list) Error on Function - ${e.stackTrace}")
logger.error(e.message) logger.error(e.message)
}
} */


// OEM PO // OEM PO
/* val oemPoBuyers = commonUtils.listToString(listOf(m18Config.BEID_PF, m18Config.BEID_PP), "beId=equal=", "=or=") /* 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}: Saved M18 Data Log. ID: ${saveM18PurchaseOrderLineLog.id}")
logger.info("${poLineRefType}: Finding item...") logger.info("${poLineRefType}: Finding item...")
val item = itemsService.findByM18Id(line.proId) 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 { try {
// Find the purchase_order_line if exist // Find the purchase_order_line if exist
@@ -322,10 +333,10 @@ open class M18PurchaseOrderService(


// Save to purchase_order_line table // Save to purchase_order_line table
logger.info("${poLineRefType}: Saving purchase order line...") 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( val savePurchaseOrderLineRequest = SavePurchaseOrderLineRequest(
id = existingPurchaseOrderLine?.id, id = existingPurchaseOrderLine?.id,
itemId = item?.id,
itemId = itemId,
uomId = itemUom?.uom?.id, uomId = itemUom?.uom?.id,
purchaseOrderId = purchaseOrderId, purchaseOrderId = purchaseOrderId,
qty = line.qty, qty = line.qty,


+ 17
- 6
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.core.utils.JwtTokenUtil
import com.ffii.fpsms.m18.M18Config 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.M18MasterDataService
import com.ffii.fpsms.m18.service.M18PurchaseOrderService import com.ffii.fpsms.m18.service.M18PurchaseOrderService
import com.ffii.fpsms.m18.service.M18PurchaseQuotationService 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.M18TestMasterDateRequest
import com.ffii.fpsms.m18.web.models.M18TestPoRequest import com.ffii.fpsms.m18.web.models.M18TestPoRequest
import com.ffii.fpsms.m18.web.models.M18TestPqRequest 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 jakarta.validation.Valid
import org.slf4j.Logger import org.slf4j.Logger
import org.slf4j.LoggerFactory 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 @RestController
@@ -37,6 +34,7 @@ class M18TestController (
private val m18Config: M18Config, private val m18Config: M18Config,
private val itemUomService: ItemUomService, private val itemUomService: ItemUomService,
private val m18PurchaseQuotationService: M18PurchaseQuotationService, private val m18PurchaseQuotationService: M18PurchaseQuotationService,
private val m18DeliveryOrderService: M18DeliveryOrderService,
) { ) {
var logger: Logger = LoggerFactory.getLogger(JwtTokenUtil::class.java) var logger: Logger = LoggerFactory.getLogger(JwtTokenUtil::class.java)


@@ -95,6 +93,12 @@ class M18TestController (
m18MasterDataService.saveProducts(request) m18MasterDataService.saveProducts(request)
} }


@GetMapping("/product/{id}")
fun m18Product(@PathVariable id: Long) {
logger.info("Access token: ${m18Config.ACCESS_TOKEN}")
m18MasterDataService.saveProduct(id)
}

@PostMapping("/vendor") @PostMapping("/vendor")
fun m18Vendor(@Valid @RequestBody request: M18TestMasterDateRequest) { fun m18Vendor(@Valid @RequestBody request: M18TestMasterDateRequest) {
logger.info("Access token: ${m18Config.ACCESS_TOKEN}") logger.info("Access token: ${m18Config.ACCESS_TOKEN}")
@@ -132,6 +136,13 @@ class M18TestController (
m18PurchaseOrderService.savePurchaseOrders(request) 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 --------------------------------------------- /// // --------------------------------------------- Purchase Quotation --------------------------------------------- ///
@PostMapping("/pq") @PostMapping("/pq")
fun m18PQ(@Valid @RequestBody request: M18TestPqRequest) { fun m18PQ(@Valid @RequestBody request: M18TestPqRequest) {


+ 5
- 0
src/main/java/com/ffii/fpsms/m18/web/models/M18TestRequest.kt 查看文件

@@ -5,6 +5,11 @@ data class M18TestPoRequest(
val modifiedDateTo: String?, val modifiedDateTo: String?,
) )


data class M18TestDoRequest(
val modifiedDateFrom: String?,
val modifiedDateTo: String?,
)

data class M18TestPqRequest( data class M18TestPqRequest(
val modifiedDateFrom: String? = null, val modifiedDateFrom: String? = null,
val modifiedDateTo: String? = null, val modifiedDateTo: String? = null,


+ 5
- 2
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.fasterxml.jackson.annotation.JsonBackReference
import com.ffii.core.entity.BaseEntity import com.ffii.core.entity.BaseEntity
import com.ffii.fpsms.m18.entity.M18DataLog 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.Items
import com.ffii.fpsms.modules.master.entity.UomConversion import com.ffii.fpsms.modules.master.entity.UomConversion
import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrderLine import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrderLine
@@ -35,10 +38,10 @@ open class DeliveryOrderLine: BaseEntity<Long>() {
@Column(name = "price", precision = 14, scale = 2) @Column(name = "price", precision = 14, scale = 2)
open var price: BigDecimal? = null open var price: BigDecimal? = null


@Size(max = 30)
@NotNull @NotNull
@Column(name = "status", nullable = false, length = 30) @Column(name = "status", nullable = false, length = 30)
open var status: String? = null
@Convert(converter = DeliveryOrderLineStatusConverter::class)
open var status: DeliveryOrderLineStatus? = null


@NotNull @NotNull
@ManyToOne @ManyToOne


+ 2
- 0
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 com.ffii.core.support.AbstractRepository
import org.springframework.stereotype.Repository import org.springframework.stereotype.Repository
import java.io.Serializable


@Repository @Repository
interface DeliveryOrderLineRepository : AbstractRepository<DeliveryOrderLine, Long> { interface DeliveryOrderLineRepository : AbstractRepository<DeliveryOrderLine, Long> {
fun findByM18DataLogIdAndDeletedIsFalse(m18datalogId: Serializable): DeliveryOrderLine?
} }

+ 7
- 0
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");
}

+ 18
- 0
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<DeliveryOrderLineStatus, String>{
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 }
}
}
}

+ 64
- 0
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
}
}

+ 14
- 0
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?,
)

+ 11
- 0
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?,
)

+ 2
- 0
src/main/java/com/ffii/fpsms/modules/master/entity/ItemUomRespository.kt 查看文件

@@ -17,6 +17,8 @@ interface ItemUomRespository : AbstractRepository<ItemUom, Long> {


fun findByItemIdAndPurchaseUnitIsTrueAndDeletedIsFalse(itemId: Serializable): ItemUom? fun findByItemIdAndPurchaseUnitIsTrueAndDeletedIsFalse(itemId: Serializable): ItemUom?


fun findByItemIdAndSalesUnitIsTrueAndDeletedIsFalse(itemId: Serializable): ItemUom?

fun findByItemM18IdAndPurchaseUnitIsTrueAndDeletedIsFalse(itemM18Id: Long): ItemUom? fun findByItemM18IdAndPurchaseUnitIsTrueAndDeletedIsFalse(itemM18Id: Long): ItemUom?
fun findBaseUnitByItemIdAndBaseUnitIsTrueAndDeletedIsFalse(itemId: Long): ItemUom? fun findBaseUnitByItemIdAndBaseUnitIsTrueAndDeletedIsFalse(itemId: Long): ItemUom?
} }

+ 4
- 0
src/main/java/com/ffii/fpsms/modules/master/service/ItemUomService.kt 查看文件

@@ -31,6 +31,10 @@ open class ItemUomService(
return itemUomRespository.findByItemIdAndPurchaseUnitIsTrueAndDeletedIsFalse(itemId) return itemUomRespository.findByItemIdAndPurchaseUnitIsTrueAndDeletedIsFalse(itemId)
} }


open fun findSalesUnitByItemId(itemId: Long): ItemUom? {
return itemUomRespository.findByItemIdAndSalesUnitIsTrueAndDeletedIsFalse(itemId)
}

open fun findPurchaseUnitByM18ItemId(m18ItemId: Long): ItemUom? { open fun findPurchaseUnitByM18ItemId(m18ItemId: Long): ItemUom? {
return itemUomRespository.findByItemM18IdAndPurchaseUnitIsTrueAndDeletedIsFalse(m18ItemId) return itemUomRespository.findByItemM18IdAndPurchaseUnitIsTrueAndDeletedIsFalse(m18ItemId)
} }


正在加载...
取消
保存