From 96474569bdebbfc6a05328f9709fc7d2082615b0 Mon Sep 17 00:00:00 2001 From: "cyril.tsui" Date: Tue, 13 May 2025 16:35:50 +0800 Subject: [PATCH] [Update M18 API Related + Purchase Order + Currency + Item UoM + Shop + Qc Item] --- .../fpsms/api/service/ApiCallerService.kt | 5 +- src/main/java/com/ffii/fpsms/m18/M18Config.kt | 69 +-- .../fpsms/m18/model/M18MasterDataRequest.kt | 44 +- .../fpsms/m18/model/M18MasterDataResponse.kt | 91 +++- .../m18/model/M18PurchaseOrderResponse.kt | 21 +- .../fpsms/m18/service/M18MasterDataService.kt | 403 ++++++++++++----- .../m18/service/M18PurchaseOrderService.kt | 413 +++++++++++------- .../ffii/fpsms/m18/service/M18TokenService.kt | 2 +- .../com/ffii/fpsms/m18/utils/CommonUtils.kt | 4 +- .../ffii/fpsms/m18/web/M18TestController.kt | 36 +- .../fpsms/modules/master/entity/Currency.kt | 34 ++ .../master/entity/CurrencyRepository.kt | 11 + .../fpsms/modules/master/entity/ItemUom.kt | 55 +++ .../master/entity/ItemUomRespository.kt | 18 + .../ffii/fpsms/modules/master/entity/Items.kt | 4 +- .../modules/master/entity/ShopRepository.kt | 13 + .../master/entity/UomConversionRepository.kt | 3 + .../master/entity/projections/SearchId.kt | 5 + .../modules/master/service/CurrencyService.kt | 33 ++ .../modules/master/service/ItemUomService.kt | 57 +++ .../modules/master/service/ShopService.kt | 11 + .../master/service/UomConversionService.kt | 6 +- .../modules/master/web/QcItemController.kt | 43 +- .../master/web/models/CurrencyRequest.kt | 12 + .../master/web/models/ItemUomRequest.kt | 27 ++ .../purchaseOrder/entity/PurchaseOrder.kt | 8 +- .../purchaseOrder/entity/PurchaseOrderLine.kt | 13 +- ...aseOrderStatus.kt => PurchaseOrderEnum.kt} | 6 + ...erter.kt => PurchaseOrderEnumConverter.kt} | 15 + ...LineStatus.kt => PurchaseOrderLineEnum.kt} | 2 - ...r.kt => PurchaseOrderLineEnumConverter.kt} | 0 .../service/PurchaseOrderLineService.kt | 13 +- .../service/PurchaseOrderService.kt | 3 + .../web/model/SavePurchaseOrderLineRequest.kt | 4 +- .../model/SavePurchaseOrderLineResponse.kt | 3 +- .../web/model/SavePurchaseOrderRequest.kt | 1 + src/main/resources/application.yml | 5 + .../01_create_currency_table.sql | 19 + .../02_create_item_uom_table.sql | 28 ++ .../03_update_purchase_order_line.sql | 8 + .../04_update_purchase_order.sql | 6 + 41 files changed, 1147 insertions(+), 407 deletions(-) create mode 100644 src/main/java/com/ffii/fpsms/modules/master/entity/Currency.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/master/entity/CurrencyRepository.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/master/entity/ItemUom.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/master/entity/ItemUomRespository.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/master/entity/projections/SearchId.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/master/service/CurrencyService.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/master/service/ItemUomService.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/master/web/models/CurrencyRequest.kt create mode 100644 src/main/java/com/ffii/fpsms/modules/master/web/models/ItemUomRequest.kt rename src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/{PurchaseOrderStatus.kt => PurchaseOrderEnum.kt} (80%) rename src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/{PurchaseOrderStatusConverter.kt => PurchaseOrderEnumConverter.kt} (54%) rename src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/{PurchaseOrderLineStatus.kt => PurchaseOrderLineEnum.kt} (77%) rename src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/{PurchaseOrderLineStatusConverter.kt => PurchaseOrderLineEnumConverter.kt} (100%) create mode 100644 src/main/resources/db/changelog/changes/20250512_01_cyril/01_create_currency_table.sql create mode 100644 src/main/resources/db/changelog/changes/20250512_01_cyril/02_create_item_uom_table.sql create mode 100644 src/main/resources/db/changelog/changes/20250512_01_cyril/03_update_purchase_order_line.sql create mode 100644 src/main/resources/db/changelog/changes/20250512_01_cyril/04_update_purchase_order.sql diff --git a/src/main/java/com/ffii/fpsms/api/service/ApiCallerService.kt b/src/main/java/com/ffii/fpsms/api/service/ApiCallerService.kt index f42f7a2..f59ed5d 100644 --- a/src/main/java/com/ffii/fpsms/api/service/ApiCallerService.kt +++ b/src/main/java/com/ffii/fpsms/api/service/ApiCallerService.kt @@ -22,13 +22,12 @@ import org.springframework.web.reactive.function.client.awaitBody @Service open class ApiCallerService( - @Value("\${m18.config.base-url}") private val baseUrl: String, - open val m18Config: M18Config + val m18Config: M18Config ) { val logger: Logger = LoggerFactory.getLogger(JwtTokenUtil::class.java) val webClient: WebClient = WebClient.builder() - .baseUrl(baseUrl) + .baseUrl(m18Config.BASE_URL) .defaultHeaders { headers -> headers.set(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) // headers.set(HttpHeaders.AUTHORIZATION, "Bearer ${m18Config.ACCESS_TOKEN}") diff --git a/src/main/java/com/ffii/fpsms/m18/M18Config.kt b/src/main/java/com/ffii/fpsms/m18/M18Config.kt index dedcb89..d24d977 100644 --- a/src/main/java/com/ffii/fpsms/m18/M18Config.kt +++ b/src/main/java/com/ffii/fpsms/m18/M18Config.kt @@ -10,48 +10,61 @@ import org.springframework.context.annotation.Configuration open class M18Config { // Account - @Value("\${m18.config.grant-type}") - lateinit var GRANT_TYPE: String; +// @Value("\${m18.config.grant-type}") + var GRANT_TYPE: String = "password"; - @Value("\${m18.config.client-id}") - lateinit var CLIENT_ID: String; +// @Value("\${m18.config.client-id}") + var CLIENT_ID: String = "M2Y1OGYxMmQtZDRiOS00OTA4LTgyNTktZDRkNzEzNWVkMzRm"; - @Value("\${m18.config.client-secret}") - lateinit var CLIENT_SECRET: String; +// @Value("\${m18.config.client-secret}") + var CLIENT_SECRET: String = "M2Y2YjQzYzQtZTc2Mi00OTFhLTkwYmItYmJhMzFjZjEyYmY5"; - @Value("\${m18.config.username}") - lateinit var USERNAME: String; +// @Value("\${m18.config.username}") + var USERNAME: String = "testingMTMS"; - @Value("\${m18.config.password}") - lateinit var PASSWORD: String; +// @Value("\${m18.config.password}") + var PASSWORD: String = "db25f2fc14cd2d2b1e7af307241f548fb03c312a"; + + var BASE_URL: String = "http://16.162.251.126/jsf/rfws" + + // Supplier +// @Value("\${m18.config.supplier-not.material-po}") + var MATERIAL_PO_SUPPLIER_NOT: List = listOf("P06", "P07"); + +// @Value("\${m18.config.supplier.shop-po}") + var SHOP_PO_SUPPLIER: List = listOf("P06", "P07"); + +// @Value("\${m18.config.supplier.oem-po}") + var OEM_PO_SUPPLIER: List = listOf("T62"); // Series - @Value("\${m18.config.seriesId.pp}") - var SERIESID_PP: Long? = null; +// @Value("\${m18.config.seriesId.pp}") + var SERIESID_PP: Long = 26; + +// @Value("\${m18.config.seriesId.pf}") + var SERIESID_PF: Long = 33; - @Value("\${m18.config.seriesId.pf}") - var SERIESID_PF: Long? = null; +// @Value("\${m18.config.seriesId.sc}") + var SERIESID_SC: Long = 27; - @Value("\${m18.config.seriesId.sc}") - var SERIESID_SC: Long? = null; +// @Value("\${m18.config.seriesId.se}") + var SERIESID_SE: Long = 28; - @Value("\${m18.config.seriesId.se}") - var SERIESID_SE: Long? = null; +// @Value("\${m18.config.seriesId.sf}") + var SERIESID_SF: Long = 70; - @Value("\${m18.config.seriesId.sf}") - var SERIESID_SF: Long? = null; +// @Value("\${m18.config.seriesId.sr}") + var SERIESID_SR: Long = 29; - @Value("\${m18.config.seriesId.sr}") - var SERIESID_SR: Long? = null; // BE - @Value("\${m18.config.beId.pp}") - var BEID_PP: Long? = null; +// @Value("\${m18.config.beId.pp}") + var BEID_PP: Long = 27; - @Value("\${m18.config.beId.pf}") - var BEID_PF: Long? = null; +// @Value("\${m18.config.beId.pf}") + var BEID_PF: Long = 1; - @Value("\${m18.config.beId.toa}") - var BEID_TOA: Long? = null; +// @Value("\${m18.config.beId.toa}") + var BEID_TOA: Long = 29; // Fetch var ACCESS_TOKEN: String? = null; diff --git a/src/main/java/com/ffii/fpsms/m18/model/M18MasterDataRequest.kt b/src/main/java/com/ffii/fpsms/m18/model/M18MasterDataRequest.kt index 288eeaa..ebe7a2d 100644 --- a/src/main/java/com/ffii/fpsms/m18/model/M18MasterDataRequest.kt +++ b/src/main/java/com/ffii/fpsms/m18/model/M18MasterDataRequest.kt @@ -1,40 +1,22 @@ package com.ffii.fpsms.m18.model -/** Product / Material Request */ -data class M18ItemRequest ( - val id: Long, - val params: String? = null, -) - -/** Product / Material List Request */ -data class M18ItemListRequest ( - val stSearch: String = "pro", - val params: String? = null, - val conds: String? = null, -) - -/** Vendor Request */ -data class M18VendorRequest ( - val id: Long, - val params: String? = null, -) +/** StSearch Type */ +enum class StSearchType(val value: String) { + PRODUCT("pro"), + VENDOR("ven"), + CUSTOMER("cus"), + UNIT("unit"), + CURRENCY("cur"), +} -/** Vendor List Request */ -data class M18VendorListRequest ( - val stSearch: String = "ven", +/** M18 Common Master Data Request */ +data class M18CommonListRequest ( + val stSearch: String? = null, val params: String? = null, val conds: String? = null, ) -/** Customer Request */ -data class M18CustomerRequest ( +data class M18CommonLineRequest ( val id: Long, val params: String? = null, -) - -/** Customer List Request */ -data class M18CustomerListRequest ( - val stSearch: String = "cus", - val params: String? = null, - val conds: String? = null, -) +) \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/m18/model/M18MasterDataResponse.kt b/src/main/java/com/ffii/fpsms/m18/model/M18MasterDataResponse.kt index c8d293f..ba4e46a 100644 --- a/src/main/java/com/ffii/fpsms/m18/model/M18MasterDataResponse.kt +++ b/src/main/java/com/ffii/fpsms/m18/model/M18MasterDataResponse.kt @@ -10,16 +10,17 @@ data class M18ErrorMessages ( ) /** Product / Material Response */ -data class M18ItemResponse ( - val data: M18ItemData?, +data class M18ProductResponse ( + val data: M18ProductData?, val messages: List? ) -data class M18ItemData ( - val pro: List? +data class M18ProductData ( + val pro: List?, + val price: List? ) -data class M18ItemPro ( +data class M18ProductPro ( val id: Long, val code: String, val desc: String, @@ -28,12 +29,23 @@ data class M18ItemPro ( val lastModifyDate: Long, ) +data class M18ProductPrice ( + val id: Long, + val hId: Long, + val unitId: Long, + val basicUnit: Boolean, + val saleUnit: Boolean, + val stkUnit: Boolean, + val purUnit: Boolean, + val pickUnit: Boolean, +) + /** Product / Material List Response */ -data class M18ItemListResponse ( - val values: List?, +data class M18ProductListResponse ( + val values: List?, ) -data class M18ItemListValue ( +data class M18ProductListValue ( val id: Long, val lastModifyDate: String?, ) @@ -72,4 +84,67 @@ data class M18VendorListResponse ( data class M18VendorListValue ( val id: Long, val lastModifyDate: String?, +) + +/** Unit List Response */ +data class M18UnitListResponse ( + val values: List?, +) + +data class M18UnitListValue ( + val id: Long, + val lastModifyDate: String?, + val code: String, + val udfudesc: String, +) + +/** Unit Response */ +data class M18UnitResponse ( + val data: List +) + +data class M18UnitData ( + val unit: List +) + +data class M18UnitUnit ( + val id: Long, + val expiredDate: Long, + val lastModifyDate: Long, + val code: String, + val udfShortDesc: String, + val udfudesc: String, + val status: String, +) + +/** Currency List Response */ +data class M18CurrencyListResponse ( + val values: List?, +) + +data class M18CurrencyListValue ( + val id: Long, + val lastModifyDate: String?, + val code: String, + val sym: String, + val curDesc: String, +) + +/** Currency Response */ +data class M18CurrencyResponse ( + val data: List +) + +data class M18CurrencyData ( + val cur: List +) + +data class M18CurrencyCur ( + val id: Long, + val expiredDate: Long, + val lastModifyDate: Long, + val code: String, + val sym: String, + val desc: String, + val status: String, ) \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/m18/model/M18PurchaseOrderResponse.kt b/src/main/java/com/ffii/fpsms/m18/model/M18PurchaseOrderResponse.kt index 87a9f57..e669732 100644 --- a/src/main/java/com/ffii/fpsms/m18/model/M18PurchaseOrderResponse.kt +++ b/src/main/java/com/ffii/fpsms/m18/model/M18PurchaseOrderResponse.kt @@ -1,5 +1,6 @@ package com.ffii.fpsms.m18.model +import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderType import java.math.BigDecimal import java.time.Instant import java.time.LocalDateTime @@ -10,7 +11,7 @@ data class M18PurchaseOrderResponse ( ) data class M18PurchaseOrderData ( - val mainPo: List, + val mainpo: List, val pot: List ) @@ -27,23 +28,35 @@ data class M18PurchaseOrderMainPo ( ) data class M18PurchaseOrderPot ( + // Purchase Order Line ID val id: Long, + // Purchase Order ID val hId: Long, + // product ID + val proId: Long, val code: String, - val desc: String, + val bDesc: String, val unitId: Long, - val seriesId: Long, +// val seriesId: Long?, val qty: BigDecimal, val amt: BigDecimal, + val curId: Long, ) /** Purchase Order List Response */ +data class M18PurchaseOrderListResponseWithType ( + var valuesWithType: MutableList?>> +) + data class M18PurchaseOrderListResponse ( - val values: List + var values: List ) data class M18PurchaseOrderListValue ( val id: Long, val code: String, val lastModifyDate: String, + + // Defined by FP-MTMS + val type: PurchaseOrderType?, ) \ 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 d6dd603..c01dd9f 100644 --- a/src/main/java/com/ffii/fpsms/m18/service/M18MasterDataService.kt +++ b/src/main/java/com/ffii/fpsms/m18/service/M18MasterDataService.kt @@ -5,16 +5,15 @@ 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.entity.UomConversion import com.ffii.fpsms.modules.master.enums.ShopType -import com.ffii.fpsms.modules.master.service.ItemsService -import com.ffii.fpsms.modules.master.service.ShopService -import com.ffii.fpsms.modules.master.web.models.ItemType -import com.ffii.fpsms.modules.master.web.models.NewItemRequest -import com.ffii.fpsms.modules.master.web.models.SaveShopRequest +import com.ffii.fpsms.modules.master.service.* +import com.ffii.fpsms.modules.master.web.models.* import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.stereotype.Service import java.time.LocalDate +import java.time.LocalDateTime import java.time.format.DateTimeFormatter @Service @@ -23,87 +22,129 @@ open class M18MasterDataService( val apiCallerService: ApiCallerService, val itemsService: ItemsService, val shopService: ShopService, + val uomConversionService: UomConversionService, + val currencyService: CurrencyService, + val itemUomService: ItemUomService, ) { val commonUtils = CommonUtils() val logger: Logger = LoggerFactory.getLogger(JwtTokenUtil::class.java) + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") - // Everyday update the master data + // M18 Conditions val lastModifyDate = LocalDate.now().minusDays(1) val lastModifyDateConds = "lastModifyDate=largerThan=$lastModifyDate" val seriesIdList = listOf(m18Config.SERIESID_SC, m18Config.SERIESID_SE, m18Config.SERIESID_SF, m18Config.SERIESID_SR) - val seriesIdConds = "(" + commonUtils.ListToString(seriesIdList.filterNotNull(), "seriesId=unequal=", "=or=") + ")" + val seriesIdConds = + "(" + commonUtils.ListToString(seriesIdList.filterNotNull(), "seriesId=unequal=", "=or=") + ")" val beIdList = listOf(m18Config.BEID_PF, m18Config.BEID_PP, m18Config.BEID_TOA) val beIdConds = "(" + commonUtils.ListToString(beIdList.filterNotNull(), "beId=equal=", "=or=") + ")" -// val commonConds =seriesIdConds + beIdConds -// "(beId=equal=${m18Config.BEID_PF}=or=beId=equal=${m18Config.BEID_PP}=or=beId=equal=${m18Config.BEID_TOA})" - val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss") - // M18 API - val M18_LOAD_ITEM_API = "/root/api/read/pro" - val M18_FETCH_ITEM_LIST_API = "/search/search" - val M18_LOAD_VENDOR_API = "/root/api/read/ven" - val M18_FETCH_VENDOR_LIST_API = "/search/search" - - // --------------------------------------------- Item --------------------------------------------- /// - open fun getItems(): M18ItemListResponse? { - // seems no beId - val itemsParams = M18ItemListRequest( - params = null, - conds=seriesIdConds -// conds=commonConds -// conds = "lastModifyDate=largerThan=$lastModifyDate" + val M18_COMMON_FETCH_LIST_API = "/search/search" + val M18_COMMON_LOAD_LINE_API = "/root/api/read" + + val M18_LOAD_PRODUCT_API = "${M18_COMMON_LOAD_LINE_API}/${StSearchType.PRODUCT.value}" + val M18_LOAD_VENDOR_API = "${M18_COMMON_LOAD_LINE_API}/${StSearchType.VENDOR.value}" + val M18_LOAD_UNIT_API = "${M18_COMMON_LOAD_LINE_API}/${StSearchType.UNIT.value}" + val M18_LOAD_CURRENCY_API = "${M18_COMMON_LOAD_LINE_API}/${StSearchType.CURRENCY.value}" + + // --------------------------------------------- Common Function --------------------------------------------- /// + private inline fun getList( + stSearch: String?, + params: String? = null, + conds: String? = null, + ): T? { + val request = M18CommonListRequest( + stSearch = stSearch, + params = params, + conds = conds ) - val items = apiCallerService.get( - M18_FETCH_ITEM_LIST_API, - itemsParams + val response = apiCallerService.get( + M18_COMMON_FETCH_LIST_API, + request ).block() - return items + return response } - open fun getItem(id: Long): M18ItemResponse? { - logger.info("M18 Item ID: $id") - - val itemParams = M18ItemRequest( + private inline fun getLine( + id: Long, + params: String?, + api: String, + ): T? { + val request = M18CommonLineRequest( id = id, - params = null, + params = params, ) - val item = apiCallerService.get( - M18_LOAD_ITEM_API, - itemParams + val response = apiCallerService.get( + api, + request ).block() - return item + return response + } + + // --------------------------------------------- Product --------------------------------------------- /// + open fun getProducts(): M18ProductListResponse? { + // seems no beId + return getList( + stSearch = StSearchType.PRODUCT.value, + params = null, + conds = seriesIdConds + ) +// val itemsParams = M18CommonListRequest( +// stSearch = StSearchType.PRODUCT.value, +// params = null, +// conds = seriesIdConds +// ) +// +// val items = apiCallerService.get( +// M18_COMMON_FETCH_LIST_API, +// itemsParams +// ).block() +// +// return items } - open fun saveItems() { + open fun getProduct(id: Long): M18ProductResponse? { + logger.info("M18 Product ID: $id") + return getLine( + id = id, + params = null, + api = M18_LOAD_PRODUCT_API + ) + } - val items = getItems() - val exampleItems = listOf(10946L, 3825L) + open fun saveProducts() { + logger.info("--------------------------------------------Start - Saving M18 Products / Materials--------------------------------------------") + val items = getProducts() + val exampleProducts = listOf(10946L, 3825L) val successList = mutableListOf() val failList = mutableListOf() - if (items?.values != null) { - items.values.forEach { item -> -// if (item.id in exampleItems) { + val values = items?.values?.sortedBy { it.id } + if (values != null) { + values.forEach { item -> +// if (item.id in exampleProducts) { try { - val itemDetail = getItem(item.id) - if (itemDetail != null && itemDetail.data?.pro != null) { - val pro = itemDetail.data.pro[0] + val itemDetail = getProduct(item.id) + val pro = itemDetail?.data?.pro?.get(0) + val price = itemDetail?.data?.price + if (itemDetail != null && pro != null) { + val existingItem = itemsService.findByM18Id(item.id) val saveItemRequest = NewItemRequest( code = pro.code, name = pro.desc, -// type = if (pro.seriesId == m18Config.SERIESID_PF) ItemType.MATERIAL +// type = if (pro.seriesId == m18Config.SERIESID_PF) ProductType.MATERIAL // else ItemType.PRODUCT, type = ItemType.MATERIAL, - id = null, + id = existingItem?.id, description = pro.desc, remarks = null, shelfLife = null, @@ -113,108 +154,95 @@ open class M18MasterDataService( m18LastModifyDate = commonUtils.InstantToLocalDateTime(pro.lastModifyDate) ) - itemsService.saveItem(saveItemRequest) + 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...") + existingItemUoms?.filter { deleteItemUom -> + m18ItemUomIds.any { it != deleteItemUom.m18Id } + }?.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.InstantToLocalDateTime(pro.lastModifyDate) + ) + + logger.info("saved item id: ${savedItem.id}") + itemUomService.saveItemUom(itemUomRequest) + } + successList.add(item.id) logger.info("Success Count ${successList.size}: ${item.id} | ${pro.code} | ${pro.desc}") } else { failList.add(item.id) logger.error("Fail Message: ${itemDetail?.messages?.get(0)?.msgDetail}") - logger.error("Fail Count ${failList.size}: Item ID ${item.id} Not Found") + logger.error("Fail Count ${failList.size}: Item ID - ${item.id} Not Found") } } catch (e: Exception) { failList.add(item.id) - logger.error("M18 Item Data: ${e.message}") - logger.error("Fail Count ${failList.size}: Item ID ${item.id} Not Found") + logger.error("Exception") + logger.error("Fail Message: ${e.message}") + logger.error("Fail Count ${failList.size}: Item ID - ${item.id}") } -// val itemParams = M18ItemRequest( -// id = item.id, -// params = null -// ) - -// apiCallerService.get( -// M18_LOAD_ITEM_API, -// itemParams -// ).subscribe( -// { response -> -// val pro = response.data.pro[0] -//// when (pro.seriesId) { -//// m18Config.SERIESID_PF, m18Config.SERIESID_PP -> { -// val saveItemRequest = NewItemRequest( -// code = pro.code, -// name = pro.desc, -// type = if (pro.seriesId == m18Config.SERIESID_PF) ItemType.MATERIAL -// else ItemType.PRODUCT, -// id = null, -// description = null, -// remarks = null, -// shelfLife = null, -// countryOfOrigin = null, -// maxQty = null, -// m18Id = pro.id -// ) -// -// itemsService.saveItem(saveItemRequest) -//// } -//// } -// -// logger.info("Count ${++count}: ${pro.id} | ${pro.code} | ${pro.desc}") -// }, -// { error -> logger.error("WebClient Error: ${error.message}") } -// ) -// } } } else { logger.error("Items List is null. May occur errors.") } - logger.info("Total Success (${successList.size}): $successList") + logger.info("Total Success (${successList.size})") if (failList.size > 0) { logger.error("Total Fail (${failList.size}): $failList") } + + logger.info("--------------------------------------------End - Saving M18 Products / Materials--------------------------------------------") } // --------------------------------------------- Vendor --------------------------------------------- /// open fun getVendors(): M18VendorListResponse? { - val vendorsParams = M18VendorListRequest( + return getList( + stSearch = StSearchType.VENDOR.value, params = null, conds = beIdConds -// conds = "lastModifyDate=largerThan=$lastModifyDate" ) - - val vendors = apiCallerService.get( - M18_FETCH_VENDOR_LIST_API, - vendorsParams - ).block() - - return vendors } open fun getVendor(id: Long): M18VendorResponse? { logger.info("M18 Vendor ID: $id") - - val vendorParams = M18VendorRequest( + return getLine( id = id, params = null, + api = M18_LOAD_VENDOR_API ) - - val vendor = apiCallerService.get( - M18_LOAD_VENDOR_API, - vendorParams - ).block() - - return vendor } open fun saveVendors() { + logger.info("--------------------------------------------Start - Saving M18 Vendors--------------------------------------------") val vendors = getVendors() val exampleVendors = listOf(191L) val successList = mutableListOf() val failList = mutableListOf() + val values = vendors?.values?.sortedBy { it.id } - if (vendors?.values != null) { - vendors.values.forEach { vendor -> + if (values != null) { + values.forEach { vendor -> // if (vendor.id in exampleVendors) { try { val vendorDetail = getVendor(vendor.id) @@ -246,23 +274,170 @@ open class M18MasterDataService( } else { failList.add(vendor.id) logger.error("Fail Message: ${vendorDetail?.messages?.get(0)?.msgDetail}") - logger.error("Fail Count ${failList.size}: Vendor ID ${vendor.id} Not Found") + logger.error("Fail Count ${failList.size}: Vendor ID - ${vendor.id} Not Found") } } catch (e: Exception) { failList.add(vendor.id) - logger.error("M18 Vendor Data: ${e.message}") - logger.error("Fail Count ${failList.size}: Vendor ID ${vendor.id} Not Found") + logger.error("Exception") + logger.error("Fail Message: ${e.message}") + logger.error("Fail Count ${failList.size}: Vendor ID - ${vendor.id}") } // } } } else { - logger.error("Items List is null. May occur errors.") + logger.error("Vendor List is null. May occur errors.") } - logger.info("Total Success (${successList.size}): $successList") + logger.info("Total Success (${successList.size})") if (failList.size > 0) { logger.error("Total Fail (${failList.size}): $failList") } + logger.info("--------------------------------------------End - Saving M18 Vendors--------------------------------------------") + } + + // --------------------------------------------- Unit --------------------------------------------- /// + open fun getUnits(): M18UnitListResponse? { + // seems no beId + return getList( + stSearch = StSearchType.UNIT.value, + params = null, + conds = null + ) + } + + open fun getUnit(id: Long): M18UnitResponse? { + logger.info("M18 Unit ID: $id") + return getLine( + id = id, + params = null, + api = M18_LOAD_UNIT_API + ) + } + + open fun saveUnits() { + logger.info("--------------------------------------------Start - Saving M18 Units--------------------------------------------") + val units = getUnits() + + val successTransformList = mutableListOf() + val successSaveList = mutableListOf() + val failTransformList = mutableListOf() + val failSaveList = mutableListOf() + + val values = units?.values?.sortedBy { it.id } + if (values != null) { + val finalUnitList = arrayListOf() + + // transform unit + values.forEach { unit -> + try { + val tempObject = UomConversionService.BomObject().apply { + code = unit.code + udfudesc = unit.udfudesc + lastModifyDate = unit.lastModifyDate + id = unit.id + } + finalUnitList += uomConversionService.transformItem(tempObject) + successTransformList += unit.id + logger.info("Transform Success (M18): ${unit.id}") + } catch (e: Exception) { + failTransformList.add(unit.id) + logger.error("Transform Exception") + logger.error("Transform Fail Message: ${e.message}") + logger.error("Transform Fail Count ${failTransformList.size}: Unit ID - ${unit.id}") + } + } + + uomConversionService.calculateSizeInGram(finalUnitList) + + finalUnitList.forEach { + try { + uomConversionService.saveUomConversion(it) + successSaveList += it.m18Id + logger.info("Save Success (M18): ${it.m18Id}") + } catch (e: Exception) { + failSaveList.add(it.m18Id) + logger.error("Save Exception") + logger.error("Save Fail Message: ${e.message}") + logger.error("Save Fail Count ${failTransformList.size}: Unit ID - ${it.m18Id}") + } + } + } else { + logger.error("Unit List is null. May occur errors.") + } + + logger.info("Total Transform Success (${successTransformList.size})") + logger.info("Total Save Success (${successSaveList.size})") + + if (failTransformList.size > 0) { + logger.error("Total Transform Fail (${failTransformList.size}): $failTransformList") + } + + if (failSaveList.size > 0) { + logger.error("Total Save Fail (${failSaveList.size}): $failSaveList") + } + logger.info("--------------------------------------------End - Saving M18 Units--------------------------------------------") + } + + // --------------------------------------------- Currency --------------------------------------------- /// + open fun getCurrencies(): M18CurrencyListResponse? { + return getList( + stSearch = StSearchType.CURRENCY.value, + params = null, + conds = null + ) + } + + open fun getCurrency(id: Long): M18CurrencyResponse? { + logger.info("M18 Currency ID: $id") + return getLine( + id = id, + params = null, + api = M18_LOAD_CURRENCY_API + ) + } + + open fun saveCurrencies() { + logger.info("--------------------------------------------Start - Saving M18 Currencies--------------------------------------------") + val currencies = getCurrencies() + + val successList = mutableListOf() + val failList = mutableListOf() + + val values = currencies?.values?.sortedBy { it.id } + if (values != null) { + // save currency + values.forEach { currency -> + try { + val currencyRequest = CurrencyRequest( + id = null, + code = currency.code, + name = currency.sym, + description = currency.curDesc, + m18Id = currency.id, + m18LastModifyDate = LocalDateTime.parse(currency.lastModifyDate, formatter) + ) + + currencyService.saveCurrency(currencyRequest) + successList += currency.id + logger.info("Save Success (M18): ${currency.id}") + } catch (e: Exception) { + failList += currency.id + logger.error("Exception") + logger.error("Fail Message: ${e.message}") + logger.error("Fail Count ${failList.size}: Unit ID - ${currency.id}") + } + } + } else { + logger.error("Currency List is null. May occur errors.") + } + + logger.info("Total Save Success (${successList.size})") + + if (failList.size > 0) { + logger.error("Total Fail (${failList.size}): $failList") + } + + logger.info("--------------------------------------------End - Saving Currencies--------------------------------------------") } } \ No newline at end of file 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 1ab8f6c..3067a5b 100644 --- a/src/main/java/com/ffii/fpsms/m18/service/M18PurchaseOrderService.kt +++ b/src/main/java/com/ffii/fpsms/m18/service/M18PurchaseOrderService.kt @@ -9,6 +9,7 @@ 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 @@ -16,7 +17,6 @@ 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.LocalDate import java.time.LocalDateTime import kotlin.reflect.full.memberProperties @@ -30,28 +30,81 @@ open class M18PurchaseOrderService( val itemsService: ItemsService, val shopService: ShopService, ) { - val dateTimeConverter = CommonUtils() + val commonUtils = CommonUtils() val logger: Logger = LoggerFactory.getLogger(JwtTokenUtil::class.java) - val lastModifyDate = LocalDate.now().minusDays(1) - val commonConds="(beId=equal=${m18Config.BEID_PF}=or=beId=equal=${m18Config.BEID_PP}=or=beId=equal=${m18Config.BEID_TOA})=and=lastModifyDate=largerOrEqual=${lastModifyDate}" + 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" - open fun getPurchaseOrders(): M18PurchaseOrderListResponse? { - val purchaseOrdersParams = M18PurchaseOrderListRequest( + // 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 = commonConds + conds = materialPoConds ) - var purchaseOrders: M18PurchaseOrderListResponse? = null try { - purchaseOrders = apiCallerService.get( - M18_FETCH_PURCHASE_ORDER_LIST_API, - purchaseOrdersParams - ).block() + 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) @@ -81,7 +134,8 @@ open class M18PurchaseOrderService( } open fun savePurchaseOrders() { - val purchaseOrders = getPurchaseOrders() + logger.info("--------------------------------------------Start - Saving M18 Purchase Order--------------------------------------------") + val purchaseOrdersWithType = getPurchaseOrdersWithType() val examplePurchaseOrders = listOf(4764034L) val successList = mutableListOf() @@ -89,180 +143,235 @@ open class M18PurchaseOrderService( val failList = mutableListOf() val failDetailList = mutableListOf() - if (purchaseOrders != null) { + val poRefType = "Purchase Order" + val poLineRefType = "Purchase Order Line" + + if (purchaseOrdersWithType != null) { // Loop for Purchase Orders (values) - purchaseOrders.values.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) { - val poRefType = "Purchase Order" - - // Find the latest m18 data log by m18 id & type - val latestM18DataLog = m18DataLogService.findLatestM18DataLog(purchaseOrder.id, poRefType) - - // Save to m18_data_log table - 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 = dateTimeConverter.InstantToLocalDateTime(mainPo.lastModifyDate), - dataLog = mainPoJson, - status = true - ) - - val saveM18PurchaseOrderLog = m18DataLogService.saveM18DataLog(saveM18PurchaseOrderLogRequest) - - try { - // Find the purchase_order if exist - val existingPurchaseOrder = latestM18DataLog?.id?.let { purchaseOrderService.findPurchaseOrderByM18Id(it) } - - // Save to purchase_order table - val supplierId = shopService.findByM18Id(mainPo.venId)?.id - val savePurchaseOrderRequest = SavePurchaseOrderRequest( - id = existingPurchaseOrder?.id, - code = mainPo.code, - supplierId = supplierId, - orderDate = dateTimeConverter.InstantToLocalDateTime(mainPo.tDate), - estimatedArrivalDate = dateTimeConverter.InstantToLocalDateTime(mainPo.dDate), - completeDate = null, - status = PurchaseOrderStatus.PENDING.value, - m18DataLogId = saveM18PurchaseOrderLog.id, - ) - - val savePurchaseOrderResponse = purchaseOrderService.savePurchaseOrder(savePurchaseOrderRequest) - purchaseOrderId = savePurchaseOrderResponse.id - - successList.add(purchaseOrder.id) - } catch (e: Exception) { - failList.add(purchaseOrder.id) - logger.error("Error on Function - ${e.stackTrace} | Type: Purchase Order | M18 ID: ${purchaseOrder.id} | Different? ${mainPo.id}") - logger.error(e.message) - - val errorSaveM18PurchaseOrderLogRequest = SaveM18DataLogRequest( - id = saveM18PurchaseOrderLogRequest.id, - refType = "Purchase Order", - m18Id = purchaseOrder.id, - m18LastModifyDate = dateTimeConverter.InstantToLocalDateTime(mainPo.lastModifyDate), - dataLog = mainPoJson, - status = false - ) - - m18DataLogService.saveM18DataLog(errorSaveM18PurchaseOrderLogRequest) - } + purchaseOrdersWithType.valuesWithType.forEach { purchaseOrderWithType -> + val type = purchaseOrderWithType.first + val purchaseOrders = purchaseOrderWithType.second + + if (purchaseOrders != null) { + purchaseOrders.forEach { purchaseOrder -> + val purchaseOrderDetail = getPurchaseOrder(purchaseOrder.id) - // purchase_order_line + m18_data_log - if (pot != null) { - // Loop for Purchase Order Lines (pot) - pot.forEach { line -> - val poLineRefType = "Purchase Order Line" + 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 - val latestM18DataLog = m18DataLogService.findLatestM18DataLog(line.id, poLineRefType) + 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 - val lineJson = - line::class.memberProperties.associate { prop -> prop.name to prop.getter.call(line) } + logger.info("${poRefType}: Saving for M18 Data Log...") + val mainpoJson = + mainpo::class.memberProperties.associate { prop -> prop.name to prop.getter.call(mainpo) } .toMutableMap() - val saveM18PurchaseOrderLineLogRequest = SaveM18DataLogRequest( + + val saveM18PurchaseOrderLogRequest = SaveM18DataLogRequest( id = null, - refType = poLineRefType, - m18Id = line.id, - m18LastModifyDate = dateTimeConverter.InstantToLocalDateTime(mainPo.lastModifyDate), - dataLog = lineJson, + refType = poRefType, + m18Id = purchaseOrder.id, + m18LastModifyDate = commonUtils.InstantToLocalDateTime(mainpo.lastModifyDate), + dataLog = mainpoJson, status = true ) - val saveM18PurchaseOrderLineLog = m18DataLogService.saveM18DataLog(saveM18PurchaseOrderLineLogRequest) - - val item = itemsService.findByM18Id(line.id) - logger.info("Item ID: ${item?.id}") + val saveM18PurchaseOrderLog = + m18DataLogService.saveM18DataLog(saveM18PurchaseOrderLogRequest) +// logger.info("${poRefType}: Saved M18 Data Log. ID: ${saveM18PurchaseOrderLog.id}") try { - // Find the purchase_order_line if exist - val existingPurchaseOrderLine = latestM18DataLog?.id?.let { purchaseOrderLineService.findPurchaseOrderLineByM18Id(it) } - - // Save to purchase_order_line table - val savePurchaseOrderLineRequest = SavePurchaseOrderLineRequest( - id = existingPurchaseOrderLine?.id, - itemId = item?.id, - uomId = null, - purchaseOrderId = purchaseOrderId, - qty = line.qty, - price = line.amt, - priceUnit = null, - status = existingPurchaseOrderLine?.status?.value ?: PurchaseOrderLineStatus.PENDING.value, - m18DataLogId = saveM18PurchaseOrderLineLog.id, + // 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, ) - purchaseOrderLineService.savePurchaseOrderLine(savePurchaseOrderLineRequest) + 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) { - failDetailList.add(line.id) - logger.error("Error on Function - ${e.stackTrace} | Type: Purchase Order Line | M18 ID: ${line.id}") + 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 errorSaveM18PurchaseOrderLineLogRequest = SaveM18DataLogRequest( - id = saveM18PurchaseOrderLineLog.id, - refType = "Purchase Order", - m18Id = line.id, - m18LastModifyDate = dateTimeConverter.InstantToLocalDateTime(mainPo.lastModifyDate), - dataLog = lineJson, + val errorSaveM18PurchaseOrderLogRequest = SaveM18DataLogRequest( + id = saveM18PurchaseOrderLogRequest.id, + refType = poRefType, + m18Id = purchaseOrder.id, + m18LastModifyDate = commonUtils.InstantToLocalDateTime(mainpo.lastModifyDate), + dataLog = mainpoJson, status = false ) - m18DataLogService.saveM18DataLog(errorSaveM18PurchaseOrderLineLogRequest) + 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 { - val saveM18PurchaseOrderLineLogRequest = SaveM18DataLogRequest( - id = null, - refType = "Purchase Order Line", - m18Id = purchaseOrder.id, - m18LastModifyDate = dateTimeConverter.InstantToLocalDateTime(mainPo.lastModifyDate), - dataLog = mutableMapOf(Pair("Error Message", "Purchase Order Line is null")), - status = false - ) - - m18DataLogService.saveM18DataLog(saveM18PurchaseOrderLineLogRequest) } } else { - val saveM18DataLogRequest = SaveM18DataLogRequest( - id = null, - refType = "Purchase Order", - m18Id = purchaseOrder.id, -// m18LastModifyDate = if(mainPo?.lastModifyDate != null) dateTimeConverter.InstantToLocalDateTime(mainPo.lastModifyDate) else LocalDateTime.now(), - m18LastModifyDate = LocalDateTime.now(), - dataLog = mutableMapOf(Pair("Error Message", "Purchase Order is null")), - status = false - ) - - m18DataLogService.saveM18DataLog(saveM18DataLogRequest) + logger.error("${poRefType} List is null. May occur errors.") } } } else { - logger.error("Purchase Order List is null. May occur errors.") + logger.error("${poRefType} List is null. May occur errors.") } // End of save. Check result - logger.info("Total Success (Purchase Order) (${successList.size}): $successList") + logger.info("Total Success (${poRefType}) (${successList.size}): $successList") if (failList.size > 0) { - logger.error("Total Fail (Purchase Order) (${failList.size}): $failList") + logger.error("Total Fail (${poRefType}) (${failList.size}): $failList") } - logger.info("Total Success (Purchase Order Line) (${successDetailList.size}): $successDetailList") + logger.info("Total Success (${poLineRefType}) (${successDetailList.size}): $successDetailList") if (failDetailList.size > 0) { - logger.error("Total Fail (Purchase Order Line) (${failDetailList.size}): $failDetailList") + logger.error("Total Fail (${poLineRefType}) (${failDetailList.size}): $failDetailList") } + logger.info("--------------------------------------------End - Saving M18 Purchase Order--------------------------------------------") } } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/m18/service/M18TokenService.kt b/src/main/java/com/ffii/fpsms/m18/service/M18TokenService.kt index 8983339..8f62914 100644 --- a/src/main/java/com/ffii/fpsms/m18/service/M18TokenService.kt +++ b/src/main/java/com/ffii/fpsms/m18/service/M18TokenService.kt @@ -15,7 +15,7 @@ open class M18TokenService( private val m18Config: M18Config ) { - @Bean +// @Bean fun run() { // val params: MutableMap = mutableMapOf( // "grant_type" to m18Config.GRANT_TYPE, diff --git a/src/main/java/com/ffii/fpsms/m18/utils/CommonUtils.kt b/src/main/java/com/ffii/fpsms/m18/utils/CommonUtils.kt index dd49b1d..060042c 100644 --- a/src/main/java/com/ffii/fpsms/m18/utils/CommonUtils.kt +++ b/src/main/java/com/ffii/fpsms/m18/utils/CommonUtils.kt @@ -7,8 +7,8 @@ import java.time.ZoneId open class CommonUtils() { open fun InstantToLocalDateTime(timestamp: Long):LocalDateTime { val localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.of("Asia/Hong_Kong")) - println("ZoneId: ${ZoneId.systemDefault()}") - println("ZoneId: ${ZoneId.of("Asia/Hong_Kong")}") +// println("ZoneId: ${ZoneId.systemDefault()}") +// println("ZoneId: ${ZoneId.of("Asia/Hong_Kong")}") println("Timestamp: $timestamp") println("Local Date Time: $localDateTime") return localDateTime 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 69c9532..8cd2e36 100644 --- a/src/main/java/com/ffii/fpsms/m18/web/M18TestController.kt +++ b/src/main/java/com/ffii/fpsms/m18/web/M18TestController.kt @@ -4,27 +4,45 @@ import com.ffii.core.utils.JwtTokenUtil import com.ffii.fpsms.m18.M18Config import com.ffii.fpsms.m18.service.M18MasterDataService import com.ffii.fpsms.m18.service.M18PurchaseOrderService +import com.ffii.fpsms.modules.master.entity.Shop +import com.ffii.fpsms.modules.master.entity.ShopRepository +import com.ffii.fpsms.modules.master.entity.projections.SearchId +import com.ffii.fpsms.modules.master.enums.ShopType +import com.ffii.fpsms.modules.master.service.ShopService import org.slf4j.Logger import org.slf4j.LoggerFactory import org.springframework.web.bind.annotation.GetMapping import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam import org.springframework.web.bind.annotation.RestController @RestController @RequestMapping("/m18") class M18TestController ( + private val shopRepository: ShopRepository, + private val shopService: ShopService, private val m18MasterDataService: M18MasterDataService, private val m18PurchaseOrderService: M18PurchaseOrderService, private val m18Config: M18Config, ) { var logger: Logger = LoggerFactory.getLogger(JwtTokenUtil::class.java) + @GetMapping("/test1") + fun test1(): List? { + return shopService.findVendorIdsByCodeRegexp(listOf("P06", "P07")) + } + + @GetMapping("/test2") + fun test2(): List? { + return shopRepository.findIdsByCodeRegexpAndTypeAndDeletedIsFalse("P06|P07", ShopType.SUPPLIER.value) + } + // --------------------------------------------- Master Data --------------------------------------------- /// - @GetMapping("/item") - fun m18Items() { + @GetMapping("/product") + fun m18Products() { logger.info("Access token: ${m18Config.ACCESS_TOKEN}") - m18MasterDataService.saveItems() + m18MasterDataService.saveProducts() } @GetMapping("/vendor") @@ -33,6 +51,18 @@ class M18TestController ( m18MasterDataService.saveVendors() } + @GetMapping("/unit") + fun m18Unit() { + logger.info("Access token: ${m18Config.ACCESS_TOKEN}") + m18MasterDataService.saveUnits() + } + + @GetMapping("/currency") + fun m18Currency() { + logger.info("Access token: ${m18Config.ACCESS_TOKEN}") + m18MasterDataService.saveCurrencies() + } + // --------------------------------------------- Purchase Order --------------------------------------------- /// @GetMapping("/po") fun m18PO() { diff --git a/src/main/java/com/ffii/fpsms/modules/master/entity/Currency.kt b/src/main/java/com/ffii/fpsms/modules/master/entity/Currency.kt new file mode 100644 index 0000000..62bfcb0 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/master/entity/Currency.kt @@ -0,0 +1,34 @@ +package com.ffii.fpsms.modules.master.entity + +import com.ffii.core.entity.BaseEntity +import jakarta.persistence.Column +import jakarta.persistence.Entity +import jakarta.persistence.Table +import jakarta.validation.constraints.NotNull +import jakarta.validation.constraints.Size +import java.time.LocalDateTime + +@Entity +@Table(name = "currency") +open class Currency : BaseEntity() { + @Size(max = 30) + @NotNull + @Column(name = "code", nullable = false, length = 30) + open var code: String? = null + + @Size(max = 30) + @NotNull + @Column(name = "name", nullable = false, length = 30) + open var name: String? = null + + @Size(max = 100) + @NotNull + @Column(name = "description", nullable = false, length = 100) + open var description: String? = null + + @Column(name = "m18Id") + open var m18Id: Long? = null + + @Column(name = "m18LastModifyDate") + open var m18LastModifyDate: LocalDateTime? = null +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/entity/CurrencyRepository.kt b/src/main/java/com/ffii/fpsms/modules/master/entity/CurrencyRepository.kt new file mode 100644 index 0000000..8542dd2 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/master/entity/CurrencyRepository.kt @@ -0,0 +1,11 @@ +package com.ffii.fpsms.modules.master.entity + +import com.ffii.core.support.AbstractRepository +import org.springframework.stereotype.Repository + +@Repository +interface CurrencyRepository: AbstractRepository { + fun findByIdAndDeletedIsFalse (id: Long): Currency? + + fun findByM18IdAndDeletedIsFalse (m18Id: Long): Currency? +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/entity/ItemUom.kt b/src/main/java/com/ffii/fpsms/modules/master/entity/ItemUom.kt new file mode 100644 index 0000000..0e3d801 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/master/entity/ItemUom.kt @@ -0,0 +1,55 @@ +package com.ffii.fpsms.modules.master.entity + +import com.ffii.core.entity.BaseEntity +import jakarta.persistence.* +import jakarta.validation.constraints.NotNull +import java.math.BigDecimal +import java.time.LocalDateTime + +@Entity +@Table(name = "item_uom") +open class ItemUom : BaseEntity() { + @NotNull + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "uomId", nullable = false) + open var uom: UomConversion? = null + + @NotNull + @ManyToOne(fetch = FetchType.LAZY, optional = false) + @JoinColumn(name = "itemId", nullable = false) + open var item: Items? = null + + @NotNull + @Column(name = "baseUnit", nullable = false) + open var baseUnit: Boolean? = null + + @NotNull + @Column(name = "stockUnit", nullable = false) + open var stockUnit: Boolean? = null + + @NotNull + @Column(name = "pickingUnit", nullable = false) + open var pickingUnit: Boolean? = null + + @NotNull + @Column(name = "salesUnit", nullable = false) + open var salesUnit: Boolean? = null + + @NotNull + @Column(name = "purchaseUnit", nullable = false) + open var purchaseUnit: Boolean? = null + + @Column(name = "price", precision = 14, scale = 2) + open var price: BigDecimal? = null + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "currencyId") + open var currency: Currency? = null + + @NotNull + @Column(name = "m18Id", nullable = false) + open var m18Id: Long? = null + + @Column(name = "m18LastModifyDate") + open var m18LastModifyDate: LocalDateTime? = null +} \ No newline at end of file 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 new file mode 100644 index 0000000..e3848c5 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/master/entity/ItemUomRespository.kt @@ -0,0 +1,18 @@ +package com.ffii.fpsms.modules.master.entity + +import com.ffii.core.support.AbstractRepository +import org.springframework.stereotype.Repository +import java.io.Serializable + +@Repository +interface ItemUomRespository : AbstractRepository { + fun findAllByItemIdAndDeletedIsFalse(itemId: Serializable): List + + fun findByIdAndDeletedIsFalse(id: Serializable): ItemUom? + + fun findByM18IdAndDeletedIsFalse(m18Id: Serializable): ItemUom? + + fun deleteAllByIdIn(id: List) + + fun findByItemIdAndPurchaseUnitIsTrueAndDeletedIsFalse(itemId: Serializable): ItemUom? +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/entity/Items.kt b/src/main/java/com/ffii/fpsms/modules/master/entity/Items.kt index 0db4657..33891fb 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/entity/Items.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/entity/Items.kt @@ -1,7 +1,6 @@ package com.ffii.fpsms.modules.master.entity import com.ffii.core.entity.BaseEntity -import com.ffii.fpsms.modules.master.web.models.ItemType import jakarta.persistence.* import jakarta.validation.constraints.NotNull import java.time.LocalDateTime @@ -41,4 +40,7 @@ open class Items : BaseEntity() { @Column(name = "m18LastModifyDate") open var m18LastModifyDate: LocalDateTime? = null + + @OneToMany(mappedBy = "item", cascade = [CascadeType.ALL], orphanRemoval = true) + open var itemUoms: MutableSet = mutableSetOf() } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/entity/ShopRepository.kt b/src/main/java/com/ffii/fpsms/modules/master/entity/ShopRepository.kt index ab87775..8cffaef 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/entity/ShopRepository.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/entity/ShopRepository.kt @@ -1,6 +1,9 @@ package com.ffii.fpsms.modules.master.entity import com.ffii.core.support.AbstractRepository +import com.ffii.fpsms.modules.master.entity.projections.SearchId +import com.ffii.fpsms.modules.master.enums.ShopType +import org.springframework.data.jpa.repository.Query import org.springframework.stereotype.Repository @Repository @@ -10,4 +13,14 @@ interface ShopRepository : AbstractRepository { fun findByIdAndDeletedIsFalse(id: Long): Shop? fun findByM18IdAndDeletedIsFalse(m18Id: Long): Shop? + + @Query( + nativeQuery = true, + value = "select s.id from Shop s where s.code regexp ?1 and s.type = ?2 and s.deleted = false") + fun findIdsByCodeRegexpAndTypeAndDeletedIsFalse(codeRegexp: String, type: String): List? + + @Query( + nativeQuery = true, + value = "select s.id from Shop s where s.code not regexp ?1 and s.type = ?2 and s.deleted = false") + fun findIdsByCodeNotRegexpAndTypeAndDeletedIsFalse(codeNotRegexp: String, type: String): List? } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/entity/UomConversionRepository.kt b/src/main/java/com/ffii/fpsms/modules/master/entity/UomConversionRepository.kt index 0b20142..e12317d 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/entity/UomConversionRepository.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/entity/UomConversionRepository.kt @@ -8,5 +8,8 @@ import java.time.LocalDateTime interface UomConversionRepository : AbstractRepository { //fun importFromM18(): ArrayList; fun findByIdAndDeletedFalse(id: Long): UomConversion; + + fun findByM18IdAndDeletedFalse(m18Id: Long): UomConversion?; + fun findByLastModifyDateAndM18IdAndDeletedFalse(lastModifyDate: LocalDateTime, m18Id: Long): UomConversion?; } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/entity/projections/SearchId.kt b/src/main/java/com/ffii/fpsms/modules/master/entity/projections/SearchId.kt new file mode 100644 index 0000000..1e69cdb --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/master/entity/projections/SearchId.kt @@ -0,0 +1,5 @@ +package com.ffii.fpsms.modules.master.entity.projections + +interface SearchId { + val id: Long +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/service/CurrencyService.kt b/src/main/java/com/ffii/fpsms/modules/master/service/CurrencyService.kt new file mode 100644 index 0000000..69d6c91 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/master/service/CurrencyService.kt @@ -0,0 +1,33 @@ +package com.ffii.fpsms.modules.master.service + +import com.ffii.fpsms.modules.master.entity.Currency +import com.ffii.fpsms.modules.master.entity.CurrencyRepository +import com.ffii.fpsms.modules.master.web.models.CurrencyRequest +import org.springframework.stereotype.Service + +@Service +open class CurrencyService( + val currencyRepository: CurrencyRepository, +) { + open fun findById(id: Long): Currency? { + return currencyRepository.findByIdAndDeletedIsFalse(id); + } + + open fun findByM18Id(m18Id: Long): Currency? { + return currencyRepository.findByM18IdAndDeletedIsFalse(m18Id); + } + + open fun saveCurrency(request: CurrencyRequest): Currency { + val currency = request.m18Id?.let { findByM18Id(it) } ?: request.id?.let { findById(it) } ?: Currency() + + currency.apply { + code = request.code + name = request.name + description = request.description + m18Id = request.m18Id + m18LastModifyDate = request.m18LastModifyDate + } + + return currencyRepository.saveAndFlush(currency) + } +} \ 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 new file mode 100644 index 0000000..9562cb8 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/master/service/ItemUomService.kt @@ -0,0 +1,57 @@ +package com.ffii.fpsms.modules.master.service + +import com.ffii.fpsms.modules.master.entity.ItemUom +import com.ffii.fpsms.modules.master.entity.ItemUomRespository +import com.ffii.fpsms.modules.master.web.models.ItemUomRequest +import org.springframework.stereotype.Service +import kotlin.jvm.optionals.getOrNull + +@Service +open class ItemUomService( + val itemsService: ItemsService, + val uomConversionService: UomConversionService, + val itemUomRespository: ItemUomRespository, + val currencyService: CurrencyService +) { + open fun findAllByItemsId(itemId: Long): List { + return itemUomRespository.findAllByItemIdAndDeletedIsFalse(itemId); + } + + open fun findById(id: Long): ItemUom? { + return itemUomRespository.findByIdAndDeletedIsFalse(id); + } + + open fun findByM18Id(m18Id: Long): ItemUom? { + return itemUomRespository.findByM18IdAndDeletedIsFalse(m18Id); + } + + // See if need to update the response + open fun saveItemUom(request: ItemUomRequest): ItemUom { + val itemUom = request.m18Id?.let { findByM18Id(it) } ?: request.id?.let { findById(it) } ?: ItemUom() + val item = request.itemId?.let { itemsService.find(it).getOrNull() } + val uom = request.m18UomId?.let { uomConversionService.findByM18Id(it) } ?: request.uomId?.let { uomConversionService.find(it).getOrNull() } + val currency = request.currencyId?.let { currencyService.findById(it) } + + itemUom.apply { + this.uom = uom + this.item = item + this.currency = currency + baseUnit = request.baseUnit + stockUnit = request.stockUnit + pickingUnit = request.pickingUnit + salesUnit = request.salesUnit + purchaseUnit = request.purchaseUnit + price = request.price + m18Id = request.m18Id + m18LastModifyDate = request.m18LastModifyDate + } + + val savedItemUom = itemUomRespository.saveAndFlush(itemUom) + + return savedItemUom + } + + open fun deleteItemUoms(deleteIds: List) { + itemUomRespository.deleteAllByIdIn(deleteIds) + } +} \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/service/ShopService.kt b/src/main/java/com/ffii/fpsms/modules/master/service/ShopService.kt index 9a9cf24..dad4c85 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/service/ShopService.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/service/ShopService.kt @@ -2,6 +2,7 @@ package com.ffii.fpsms.modules.master.service import com.ffii.fpsms.modules.master.entity.Shop import com.ffii.fpsms.modules.master.entity.ShopRepository +import com.ffii.fpsms.modules.master.entity.projections.SearchId import com.ffii.fpsms.modules.master.enums.ShopType import com.ffii.fpsms.modules.master.web.models.SaveShopRequest import com.ffii.fpsms.modules.master.web.models.SaveShopResponse @@ -24,6 +25,16 @@ open class ShopService( return shopRepository.findByM18IdAndDeletedIsFalse(m18Id) } + open fun findVendorIdsByCodeRegexp(code: List): List? { + val codeRegexp = code.joinToString("|") + return shopRepository.findIdsByCodeRegexpAndTypeAndDeletedIsFalse(codeRegexp, type = ShopType.SUPPLIER.value) + } + + open fun findVendorIdsByCodeNotRegexp(code: List): List? { + val codeRegexp = code.joinToString("|") + return shopRepository.findIdsByCodeNotRegexpAndTypeAndDeletedIsFalse(codeRegexp, type = ShopType.SUPPLIER.value) + } + open fun saveShop(request: SaveShopRequest): SaveShopResponse { val shop = if (request.m18Id != null) { findByM18Id(request.m18Id) ?: Shop() diff --git a/src/main/java/com/ffii/fpsms/modules/master/service/UomConversionService.kt b/src/main/java/com/ffii/fpsms/modules/master/service/UomConversionService.kt index 5f9d8ef..26c3635 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/service/UomConversionService.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/service/UomConversionService.kt @@ -196,6 +196,9 @@ open class UomConversionService( } } + open fun findByM18Id(m18Id: Long) : UomConversion? { + return uomConversionRepository.findByM18IdAndDeletedFalse(m18Id) + } @Throws(IOException::class) @Transactional open fun saveUomConversion(newUomConversion: UomConversion): MessageResponse { @@ -211,7 +214,8 @@ open class UomConversionService( ) } - val uomConversion = if (newUomConversion.id != null && newUomConversion.id > 0) + val uomConversion = findByM18Id(newUomConversion.m18Id) ?: + if (newUomConversion.id != null && newUomConversion.id > 0) uomConversionRepository.findByIdAndDeletedFalse(newUomConversion.id) else UomConversion() diff --git a/src/main/java/com/ffii/fpsms/modules/master/web/QcItemController.kt b/src/main/java/com/ffii/fpsms/modules/master/web/QcItemController.kt index 5bed80d..02bd270 100644 --- a/src/main/java/com/ffii/fpsms/modules/master/web/QcItemController.kt +++ b/src/main/java/com/ffii/fpsms/modules/master/web/QcItemController.kt @@ -39,47 +39,6 @@ class QcItemController( @PostMapping("/save") fun saveQcItem(@Valid @RequestBody request: SaveQcItemRequest): SaveQcItemResponse { - -// val qcItemProperties = QcItem::class.members.filterIsInstance>() - val errors = mutableMapOf() - val id = request.id - val qcItem = if (id != null) qcItemRepository.findById(id).orElseThrow() else QcItem() - - // check duplicated code - val duplicateQcItem = qcItemService.findQcItemByCode(request.code) - if (duplicateQcItem != null && duplicateQcItem.id != qcItem.id) { - errors["code"] = "Code is duplicated" - } - - if (errors.isNotEmpty()) { - request.let { - SaveQcItemResponse( - id = it.id, - code = it.code, - name = it.name, - description = it.description, - errors = errors - ) - } - } - - // Save Qc Item - qcItem.apply { - code = request.code - name = request.name - description = request.description - } - - val savedQcItem = qcItemRepository.save(qcItem) - - return savedQcItem.let { - SaveQcItemResponse( - id = it.id, - code = it.code, - name = it.name, - description = it.description, - errors = null - ) - } + return qcItemService.saveQcItem(request) } } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/web/models/CurrencyRequest.kt b/src/main/java/com/ffii/fpsms/modules/master/web/models/CurrencyRequest.kt new file mode 100644 index 0000000..40c3548 --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/master/web/models/CurrencyRequest.kt @@ -0,0 +1,12 @@ +package com.ffii.fpsms.modules.master.web.models + +import java.time.LocalDateTime + +data class CurrencyRequest ( + val id: Long?, + val code: String?, + val name: String?, + val description: String?, + val m18Id: Long?, + val m18LastModifyDate: LocalDateTime?, +) \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/master/web/models/ItemUomRequest.kt b/src/main/java/com/ffii/fpsms/modules/master/web/models/ItemUomRequest.kt new file mode 100644 index 0000000..ad7674e --- /dev/null +++ b/src/main/java/com/ffii/fpsms/modules/master/web/models/ItemUomRequest.kt @@ -0,0 +1,27 @@ +package com.ffii.fpsms.modules.master.web.models + +import java.math.BigDecimal +import java.time.LocalDateTime + +data class DeleteItemUomRequest( + val id: Long? = null, + val m18Id: Long? = null +) + +data class ItemUomRequest( + val id: Long? = null, + val uomId: Long? = null, + val m18UomId: Long? = null, + val itemId: Long? = null, + val m18ItemId: Long? = null, + val baseUnit: Boolean?, + val stockUnit: Boolean?, + val pickingUnit: Boolean?, + val salesUnit: Boolean?, + val purchaseUnit: Boolean?, + val price: BigDecimal?, + val currencyId: Long? = null, + val m18CurrencyId: Long? = null, + val m18Id: Long?, + val m18LastModifyDate: LocalDateTime?, +) \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/entity/PurchaseOrder.kt b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/entity/PurchaseOrder.kt index 2f7972f..99dbe1b 100644 --- a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/entity/PurchaseOrder.kt +++ b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/entity/PurchaseOrder.kt @@ -5,10 +5,11 @@ import com.ffii.fpsms.modules.master.entity.Shop import com.ffii.fpsms.m18.entity.M18DataLog import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderStatus import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderStatusConverter +import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderType +import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderTypeConverter import jakarta.persistence.* import jakarta.validation.constraints.NotNull import jakarta.validation.constraints.Size -import java.time.LocalDate import java.time.LocalDateTime @Entity @@ -37,6 +38,11 @@ open class PurchaseOrder : BaseEntity() { @Convert(converter = PurchaseOrderStatusConverter::class) open var status: PurchaseOrderStatus? = null + @NotNull + @Column(name = "type", nullable = true, length = 20) + @Convert(converter = PurchaseOrderTypeConverter::class) + open var type: PurchaseOrderType? = null + @NotNull @ManyToOne @JoinColumn(name = "m18DataLogId", nullable = false) diff --git a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/entity/PurchaseOrderLine.kt b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/entity/PurchaseOrderLine.kt index edb6cfa..f113f7a 100644 --- a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/entity/PurchaseOrderLine.kt +++ b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/entity/PurchaseOrderLine.kt @@ -3,7 +3,7 @@ package com.ffii.fpsms.modules.purchaseOrder.entity import com.ffii.core.entity.BaseEntity import com.ffii.fpsms.modules.master.entity.Items import com.ffii.fpsms.m18.entity.M18DataLog -import com.ffii.fpsms.modules.master.enums.ShopTypeConverter +import com.ffii.fpsms.modules.master.entity.Currency import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderLineStatus import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderLineStatusConverter import jakarta.persistence.* @@ -40,10 +40,6 @@ open class PurchaseOrderLine : BaseEntity(){ @Column(name = "price", precision = 14, scale = 2) open var price: BigDecimal? = null - @Size(max = 5) - @Column(name = "priceUnit", length = 5) - open var priceUnit: String? = null - @Convert(converter = PurchaseOrderLineStatusConverter::class) @NotNull @Column(name = "status", nullable = false, length = 10) @@ -53,4 +49,11 @@ open class PurchaseOrderLine : BaseEntity(){ @ManyToOne @JoinColumn(name = "m18DataLogId", nullable = false) open var m18DataLog: M18DataLog? = null + + @Column(name = "uomId") + open var uomId: Long? = null + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "currencyId") + open var currency: Currency? = null } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderStatus.kt b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderEnum.kt similarity index 80% rename from src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderStatus.kt rename to src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderEnum.kt index c0d4b6d..2e32efa 100644 --- a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderStatus.kt +++ b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderEnum.kt @@ -13,4 +13,10 @@ enum class PurchaseOrderStatus(val value: String) { ?: throw IllegalArgumentException("No enum constant with value: $value") } } +} + +enum class PurchaseOrderType(val value: String) { + MATERIAL ("material"), + SHOP ("shop"), + OEM ("oem") } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderStatusConverter.kt b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderEnumConverter.kt similarity index 54% rename from src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderStatusConverter.kt rename to src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderEnumConverter.kt index 5507231..1f9891f 100644 --- a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderStatusConverter.kt +++ b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderEnumConverter.kt @@ -3,6 +3,7 @@ package com.ffii.fpsms.modules.purchaseOrder.enums import jakarta.persistence.AttributeConverter import jakarta.persistence.Converter +// Purchase Order Status @Converter(autoApply = true) class PurchaseOrderStatusConverter : AttributeConverter{ override fun convertToDatabaseColumn(status: PurchaseOrderStatus?): String? { @@ -14,4 +15,18 @@ class PurchaseOrderStatusConverter : AttributeConverter{ + override fun convertToDatabaseColumn(status: PurchaseOrderType?): String? { + return status?.value + } + + override fun convertToEntityAttribute(value: String?): PurchaseOrderType? { + return value?.let { v -> + PurchaseOrderType.entries.find { it.value == v } + } + } } \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderLineStatus.kt b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderLineEnum.kt similarity index 77% rename from src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderLineStatus.kt rename to src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderLineEnum.kt index c7371a1..614b6f1 100644 --- a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderLineStatus.kt +++ b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderLineEnum.kt @@ -1,7 +1,5 @@ package com.ffii.fpsms.modules.purchaseOrder.enums -import com.ffii.fpsms.modules.master.enums.ShopType - enum class PurchaseOrderLineStatus(val value: String) { PENDING("pending"), PICKING("picking"), diff --git a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderLineStatusConverter.kt b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderLineEnumConverter.kt similarity index 100% rename from src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderLineStatusConverter.kt rename to src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderLineEnumConverter.kt diff --git a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/service/PurchaseOrderLineService.kt b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/service/PurchaseOrderLineService.kt index 6f2ad54..f385e60 100644 --- a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/service/PurchaseOrderLineService.kt +++ b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/service/PurchaseOrderLineService.kt @@ -2,8 +2,8 @@ package com.ffii.fpsms.modules.purchaseOrder.service import com.ffii.fpsms.m18.entity.M18DataLogRepository import com.ffii.fpsms.modules.master.entity.ItemsRepository +import com.ffii.fpsms.modules.master.service.CurrencyService import com.ffii.fpsms.modules.master.service.ItemsService -import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrder import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrderLine import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrderLineRepository import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrderRepository @@ -12,7 +12,6 @@ import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderLineStatus import com.ffii.fpsms.modules.purchaseOrder.web.model.SavePurchaseOrderLineRequest import com.ffii.fpsms.modules.purchaseOrder.web.model.SavePurchaseOrderLineResponse import org.springframework.stereotype.Service -import java.math.BigDecimal import kotlin.jvm.optionals.getOrDefault import kotlin.jvm.optionals.getOrNull @@ -22,7 +21,8 @@ open class PurchaseOrderLineService( private val itemsService: ItemsService, private val itemsRepository: ItemsRepository, private val purchaseOrderRepository: PurchaseOrderRepository, - private val m18DataLogRepository: M18DataLogRepository + private val m18DataLogRepository: M18DataLogRepository, + private val currencyService: CurrencyService, ) { open fun allPurchaseOrderLine(): List { return purchaseOrderLineRepository.findAll() @@ -31,6 +31,7 @@ open class PurchaseOrderLineService( open fun findPurchaseOrderLineByM18Id(m18DataLogId: Long): PurchaseOrderLine? { return purchaseOrderLineRepository.findByM18DataLogIdAndDeletedIsFalse(m18DataLogId) } + open fun findAllPoLineInfoByPoId(poId: Long): List { return purchaseOrderLineRepository.findAllPurchaseOrderLineInfoByPurchaseOrderIdAndDeletedIsFalse(poId) } @@ -43,6 +44,8 @@ open class PurchaseOrderLineService( val purchaseOrder = request.purchaseOrderId?.let { purchaseOrderRepository.findById(it).getOrNull() } val status = request.status?.let { status -> PurchaseOrderLineStatus.entries.find { it.value == status } } val m18DataLog = request.m18DataLogId?.let { m18DataLogRepository.findById(it).getOrNull() } + val currency = request.m18CurrencyId?.let { currencyService.findByM18Id(it) } + ?: request.currencyId?.let { currencyService.findById(it) } purchaseOrderLine.apply { this.item = item @@ -50,7 +53,7 @@ open class PurchaseOrderLineService( this.purchaseOrder = purchaseOrder qty = request.qty price = request.price - priceUnit = request.priceUnit + this.currency = currency this.status = status this.m18DataLog = m18DataLog ?: this.m18DataLog } @@ -61,7 +64,7 @@ open class PurchaseOrderLineService( itemNo = it.itemNo, qty = it.qty, price = it.price, - priceUnit = it.priceUnit, + currency = currency?.name, status = it.status?.value ) } diff --git a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/service/PurchaseOrderService.kt b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/service/PurchaseOrderService.kt index b381b93..d05f85c 100644 --- a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/service/PurchaseOrderService.kt +++ b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/service/PurchaseOrderService.kt @@ -10,6 +10,7 @@ import com.ffii.fpsms.modules.purchaseOrder.entity.PurchaseOrderRepository import com.ffii.fpsms.modules.purchaseOrder.entity.projections.PoLineWithStockInLine import com.ffii.fpsms.modules.purchaseOrder.entity.projections.PurchaseOrderInfo import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderStatus +import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderType import com.ffii.fpsms.modules.purchaseOrder.web.model.SavePurchaseOrderRequest import com.ffii.fpsms.modules.purchaseOrder.web.model.SavePurchaseOrderResponse import com.ffii.fpsms.modules.stock.entity.StockInLine @@ -77,6 +78,7 @@ open class PurchaseOrderService( request.id?.let { purchaseOrderRepository.findById(it).getOrDefault(PurchaseOrder()) } ?: PurchaseOrder() val supplier = request.supplierId?.let { shopRepository.findById(it).getOrNull() } val status = request.status?.let { status -> PurchaseOrderStatus.entries.find { it.value == status } } + val type = request.type?.let { type -> PurchaseOrderType.entries.find { it.value == type } } val m18DataLog = request.m18DataLogId?.let { m18DataLogRepository.findById(it).getOrNull() } //Need check duplicate? @@ -88,6 +90,7 @@ open class PurchaseOrderService( estimatedArrivalDate = request.estimatedArrivalDate completeDate = request.completeDate this.status = status + this.type = type this.m18DataLog = m18DataLog } diff --git a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/web/model/SavePurchaseOrderLineRequest.kt b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/web/model/SavePurchaseOrderLineRequest.kt index 0a01644..e935acb 100644 --- a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/web/model/SavePurchaseOrderLineRequest.kt +++ b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/web/model/SavePurchaseOrderLineRequest.kt @@ -1,6 +1,5 @@ package com.ffii.fpsms.modules.purchaseOrder.web.model -import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderLineStatus import java.math.BigDecimal data class SavePurchaseOrderLineRequest( @@ -10,7 +9,8 @@ data class SavePurchaseOrderLineRequest( val purchaseOrderId: Long?, val qty: BigDecimal?, val price: BigDecimal?, - val priceUnit: String?, + val currencyId: Long? = null, + val m18CurrencyId: Long? = null, val status: String?, val m18DataLogId: Long?, ) \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/web/model/SavePurchaseOrderLineResponse.kt b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/web/model/SavePurchaseOrderLineResponse.kt index d198d95..5b4c2e1 100644 --- a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/web/model/SavePurchaseOrderLineResponse.kt +++ b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/web/model/SavePurchaseOrderLineResponse.kt @@ -1,6 +1,5 @@ package com.ffii.fpsms.modules.purchaseOrder.web.model -import com.ffii.fpsms.modules.purchaseOrder.enums.PurchaseOrderLineStatus import java.math.BigDecimal data class SavePurchaseOrderLineResponse ( @@ -8,6 +7,6 @@ data class SavePurchaseOrderLineResponse ( val itemNo: String?, val qty: BigDecimal?, val price: BigDecimal?, - val priceUnit: String?, + val currency: String?, val status: String?, ) \ No newline at end of file diff --git a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/web/model/SavePurchaseOrderRequest.kt b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/web/model/SavePurchaseOrderRequest.kt index 60043bf..0c993fc 100644 --- a/src/main/java/com/ffii/fpsms/modules/purchaseOrder/web/model/SavePurchaseOrderRequest.kt +++ b/src/main/java/com/ffii/fpsms/modules/purchaseOrder/web/model/SavePurchaseOrderRequest.kt @@ -12,5 +12,6 @@ data class SavePurchaseOrderRequest ( val estimatedArrivalDate: LocalDateTime?, val completeDate: LocalDateTime?, val status: String?, + val type: String?, val m18DataLogId: Long? ) \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index cd993a8..b6a038f 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -36,6 +36,11 @@ m18: password: db25f2fc14cd2d2b1e7af307241f548fb03c312a base-url: http://16.162.251.126/jsf/rfws base-password: qwer1234 + supplier: + shop-po: P06, P07 + oem-po: T62 + supplier-not: + material-po: P06, P07 beId: toa: 29 pp: 27 diff --git a/src/main/resources/db/changelog/changes/20250512_01_cyril/01_create_currency_table.sql b/src/main/resources/db/changelog/changes/20250512_01_cyril/01_create_currency_table.sql new file mode 100644 index 0000000..9497fbb --- /dev/null +++ b/src/main/resources/db/changelog/changes/20250512_01_cyril/01_create_currency_table.sql @@ -0,0 +1,19 @@ +--liquibase formatted sql + +--changeset cyril:create currency table +CREATE TABLE `currency` +( + `id` INT NOT NULL AUTO_INCREMENT, + `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` VARCHAR(30) NULL DEFAULT NULL, + `version` INT NOT NULL DEFAULT '0', + `modified` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `modifiedBy` VARCHAR(30) NULL DEFAULT NULL, + `deleted` TINYINT(1) NOT NULL DEFAULT '0', + `code` VARCHAR(30) NOT NULL, + `name` VARCHAR(30) NOT NULL, + `description` VARCHAR(100) NOT NULL DEFAULT '0', + `m18Id` INT NULL, + `m18LastModifyDate` DATETIME NULL, + CONSTRAINT pk_currency PRIMARY KEY (id) +); \ No newline at end of file diff --git a/src/main/resources/db/changelog/changes/20250512_01_cyril/02_create_item_uom_table.sql b/src/main/resources/db/changelog/changes/20250512_01_cyril/02_create_item_uom_table.sql new file mode 100644 index 0000000..a4dd3d6 --- /dev/null +++ b/src/main/resources/db/changelog/changes/20250512_01_cyril/02_create_item_uom_table.sql @@ -0,0 +1,28 @@ +--liquibase formatted sql + +--changeset cyril:create item_uom table +CREATE TABLE `item_uom` +( + `id` INT NOT NULL AUTO_INCREMENT, + `created` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `createdBy` VARCHAR(30) NULL DEFAULT NULL, + `version` INT NOT NULL DEFAULT '0', + `modified` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + `modifiedBy` VARCHAR(30) NULL DEFAULT NULL, + `deleted` TINYINT(1) NOT NULL DEFAULT '0', + `uomId` INT NOT NULL, + `itemId` INT NOT NULL, + `baseUnit` TINYINT NOT NULL DEFAULT '0', + `stockUnit` TINYINT NOT NULL DEFAULT '0', + `pickingUnit` TINYINT NOT NULL DEFAULT '0', + `salesUnit` TINYINT NOT NULL DEFAULT '0', + `purchaseUnit` TINYINT NOT NULL DEFAULT '0', + `price` DECIMAL(14, 2) NULL, + `currencyId` INT NULL, + `m18Id` INT NOT NULL, + `m18LastModifyDate` DATETIME NULL, + CONSTRAINT pk_item_uom PRIMARY KEY (id), + CONSTRAINT FK_ITEM_UOM_ON_UOMID FOREIGN KEY (uomId) REFERENCES uom_conversion (id), + CONSTRAINT FK_ITEM_UOM_ON_ITEMID FOREIGN KEY (itemId) REFERENCES items (id), + CONSTRAINT FK_ITEM_UOM_ON_CURRENCYID FOREIGN KEY (currencyId) REFERENCES currency (id) +); \ No newline at end of file diff --git a/src/main/resources/db/changelog/changes/20250512_01_cyril/03_update_purchase_order_line.sql b/src/main/resources/db/changelog/changes/20250512_01_cyril/03_update_purchase_order_line.sql new file mode 100644 index 0000000..f2031e9 --- /dev/null +++ b/src/main/resources/db/changelog/changes/20250512_01_cyril/03_update_purchase_order_line.sql @@ -0,0 +1,8 @@ +--liquibase formatted sql + +--changeset cyril:update purchase order line + +ALTER TABLE `purchase_order_line` + CHANGE COLUMN `priceUnit` `currencyId` INT NULL DEFAULT NULL, + ADD CONSTRAINT `FK_PURCHASE_ORDER_LINE_ON_UOMID` FOREIGN KEY (`uomId`) REFERENCES `uom_conversion` (`id`), + ADD CONSTRAINT `FK_PURCHASE_ORDER_LINE_ON_CURRENCYID` FOREIGN KEY (`currencyId`) REFERENCES `currency` (`id`); \ No newline at end of file diff --git a/src/main/resources/db/changelog/changes/20250512_01_cyril/04_update_purchase_order.sql b/src/main/resources/db/changelog/changes/20250512_01_cyril/04_update_purchase_order.sql new file mode 100644 index 0000000..20b7c31 --- /dev/null +++ b/src/main/resources/db/changelog/changes/20250512_01_cyril/04_update_purchase_order.sql @@ -0,0 +1,6 @@ +--liquibase formatted sql + +--changeset cyril:update purchase order + +ALTER TABLE `purchase_order` + ADD COLUMN `type` VARCHAR(20) NULL AFTER `status`; \ No newline at end of file