| @@ -137,7 +137,7 @@ open class M18DeliveryOrderService( | |||||
| // Process for Delivery Order (mainpo) | // Process for Delivery Order (mainpo) | ||||
| // Assume only one DO in the DO (search by DO ID) | // Assume only one DO in the DO (search by DO ID) | ||||
| val mainpo = deliveryOrderDetail?.data?.mainpo?.get(0) | val mainpo = deliveryOrderDetail?.data?.mainpo?.get(0) | ||||
| logger.info("deliveryOrderDetail: data is null? ${deliveryOrderDetail?.data == null} | mainpo is null? ${deliveryOrderDetail?.data?.mainpo == null} | get(0) is null? ${deliveryOrderDetail?.data?.mainpo?.get(0) == null}") | |||||
| // logger.info("deliveryOrderDetail: data is null? ${deliveryOrderDetail?.data == null} | mainpo is null? ${deliveryOrderDetail?.data?.mainpo == null} | get(0) is null? ${deliveryOrderDetail?.data?.mainpo?.get(0) == null}") | |||||
| val pot = deliveryOrderDetail?.data?.pot | val pot = deliveryOrderDetail?.data?.pot | ||||
| val deliveryOrderLineMessage = deliveryOrderDetail?.messages | val deliveryOrderLineMessage = deliveryOrderDetail?.messages | ||||
| @@ -4,7 +4,7 @@ import java.time.LocalDate | |||||
| import java.time.format.DateTimeFormatter | import java.time.format.DateTimeFormatter | ||||
| object CodeGenerator { | object CodeGenerator { | ||||
| // Default Value for Lot No | |||||
| // Old Function | |||||
| private var dateFormat = DateTimeFormatter.ofPattern("yyMMdd") | private var dateFormat = DateTimeFormatter.ofPattern("yyMMdd") | ||||
| fun generateCode(prefix: String, itemId: Long, count: Int): String { | fun generateCode(prefix: String, itemId: Long, count: Int): String { | ||||
| // prefix = "ITEM" || "LOT" | // prefix = "ITEM" || "LOT" | ||||
| @@ -15,12 +15,12 @@ object CodeGenerator { | |||||
| return "$prefix-$todayStr$itemStr$countStr" | return "$prefix-$todayStr$itemStr$countStr" | ||||
| } | } | ||||
| // Default Value for Order No | |||||
| val DEFAULT_SUFFIX_FORMAT = "%03d"; | |||||
| // Default Value for Order No & Lot No. | |||||
| val DEFAULT_SUFFIX_FORMAT = "%04d"; | |||||
| val DEFAULT_PATTERN = "yyyyMMdd"; | val DEFAULT_PATTERN = "yyyyMMdd"; | ||||
| val DEFAULT_FORMATTER = DateTimeFormatter.ofPattern(DEFAULT_PATTERN) | val DEFAULT_FORMATTER = DateTimeFormatter.ofPattern(DEFAULT_PATTERN) | ||||
| val DEFAULT_MIDFIX = LocalDate.now().format(DEFAULT_FORMATTER) | val DEFAULT_MIDFIX = LocalDate.now().format(DEFAULT_FORMATTER) | ||||
| fun generateOrderNo( | |||||
| fun generateNo( | |||||
| suffixFormat: String? = null, | suffixFormat: String? = null, | ||||
| pattern: String? = null, | pattern: String? = null, | ||||
| prefix: String, | prefix: String, | ||||
| @@ -74,7 +74,7 @@ open class SchedulerService( | |||||
| // Init Scheduler | // Init Scheduler | ||||
| // @PostConstruct | // @PostConstruct | ||||
| fun init() { | fun init() { | ||||
| scheduleM18PoTask(); | |||||
| // scheduleM18PoTask(); | |||||
| scheduleM18MasterData(); | scheduleM18MasterData(); | ||||
| scheduleRoughProd(); | scheduleRoughProd(); | ||||
| scheduleDetailedProd(); | scheduleDetailedProd(); | ||||
| @@ -160,8 +160,8 @@ open class SchedulerService( | |||||
| ) | ) | ||||
| m18PurchaseOrderService.savePurchaseOrders(request); | m18PurchaseOrderService.savePurchaseOrders(request); | ||||
| m18DeliveryOrderService.saveDeliveryOrders(request); | m18DeliveryOrderService.saveDeliveryOrders(request); | ||||
| logger.info("today: ${today.format(dataStringFormat)}") | |||||
| logger.info("yesterday: ${yesterday.format(dataStringFormat)}") | |||||
| // logger.info("today: ${today.format(dataStringFormat)}") | |||||
| // logger.info("yesterday: ${yesterday.format(dataStringFormat)}") | |||||
| } | } | ||||
| open fun getM18MasterData() { | open fun getM18MasterData() { | ||||
| @@ -179,7 +179,7 @@ open class SchedulerService( | |||||
| m18MasterDataService.saveVendors(request) | m18MasterDataService.saveVendors(request) | ||||
| m18MasterDataService.saveBusinessUnits(request) | m18MasterDataService.saveBusinessUnits(request) | ||||
| m18MasterDataService.saveCurrencies(request) | m18MasterDataService.saveCurrencies(request) | ||||
| logger.info("today: ${today.format(dataStringFormat)}") | |||||
| logger.info("yesterday: ${yesterday.format(dataStringFormat)}") | |||||
| // logger.info("today: ${today.format(dataStringFormat)}") | |||||
| // logger.info("yesterday: ${yesterday.format(dataStringFormat)}") | |||||
| } | } | ||||
| } | } | ||||
| @@ -2,6 +2,8 @@ package com.ffii.fpsms.modules.master.service | |||||
| import com.ffii.core.support.AbstractBaseEntityService | import com.ffii.core.support.AbstractBaseEntityService | ||||
| import com.ffii.core.support.JdbcDao | import com.ffii.core.support.JdbcDao | ||||
| import com.ffii.core.utils.ExcelUtils | |||||
| import com.ffii.core.utils.JwtTokenUtil | |||||
| import com.ffii.fpsms.modules.master.entity.ItemsRepository | import com.ffii.fpsms.modules.master.entity.ItemsRepository | ||||
| import com.ffii.fpsms.modules.master.entity.Warehouse | import com.ffii.fpsms.modules.master.entity.Warehouse | ||||
| import com.ffii.fpsms.modules.master.entity.WarehouseRepository | import com.ffii.fpsms.modules.master.entity.WarehouseRepository | ||||
| @@ -14,15 +16,19 @@ import com.ffii.fpsms.modules.stock.entity.StockInLineRepository | |||||
| import com.ffii.fpsms.modules.stock.entity.StockInRepository | import com.ffii.fpsms.modules.stock.entity.StockInRepository | ||||
| import com.ffii.fpsms.modules.stock.service.InventoryLotService | import com.ffii.fpsms.modules.stock.service.InventoryLotService | ||||
| import com.ffii.fpsms.modules.stock.service.StockInService | import com.ffii.fpsms.modules.stock.service.StockInService | ||||
| import org.apache.poi.ss.usermodel.Sheet | |||||
| import org.apache.poi.ss.usermodel.Workbook | |||||
| import org.slf4j.Logger | |||||
| import org.slf4j.LoggerFactory | |||||
| import org.springframework.stereotype.Service | import org.springframework.stereotype.Service | ||||
| import java.math.BigDecimal | |||||
| import kotlin.jvm.optionals.getOrNull | import kotlin.jvm.optionals.getOrNull | ||||
| @Service | @Service | ||||
| open class WarehouseService( | open class WarehouseService( | ||||
| private val jdbcDao: JdbcDao, | private val jdbcDao: JdbcDao, | ||||
| private val warehouseRepository: WarehouseRepository, | private val warehouseRepository: WarehouseRepository, | ||||
| ): AbstractBaseEntityService<Warehouse, Long, WarehouseRepository>(jdbcDao, warehouseRepository) { | |||||
| ) : AbstractBaseEntityService<Warehouse, Long, WarehouseRepository>(jdbcDao, warehouseRepository) { | |||||
| open fun getWarehouses(): List<Warehouse> { | open fun getWarehouses(): List<Warehouse> { | ||||
| return warehouseRepository.findAll().filter { it.deleted == false } | return warehouseRepository.findAll().filter { it.deleted == false } | ||||
| } | } | ||||
| @@ -51,4 +57,56 @@ open class WarehouseService( | |||||
| return warehouseRepository.save(warehouse); | return warehouseRepository.save(warehouse); | ||||
| } | } | ||||
| open fun importExcel(workbook: Workbook?): String { | |||||
| logger.info("--------- Start - Import Warehouse Excel -------"); | |||||
| if (workbook == null) { | |||||
| logger.error("No Excel Import"); | |||||
| return "Import Excel failure"; | |||||
| } | |||||
| val sheet: Sheet = workbook.getSheetAt(0); | |||||
| // Columns | |||||
| val COLUMN_WAREHOSE_INDEX = 1; | |||||
| val COLUMN_ZONE_INDEX = 2; | |||||
| val COLUMN_SLOT_INDEX = 3; | |||||
| val COLUMN_FLOOR_INDEX = 4; | |||||
| val COLUMN_PLACE_INDEX = 5; | |||||
| val START_ROW_INDEX = 2; | |||||
| // Start Import | |||||
| for (i in START_ROW_INDEX..<sheet.lastRowNum) { | |||||
| val row = sheet.getRow(i) | |||||
| try { | |||||
| val floor = ExcelUtils.getStringValue(row.getCell(COLUMN_FLOOR_INDEX)).trim() | |||||
| val place = ExcelUtils.getStringValue(row.getCell(COLUMN_PLACE_INDEX)).trim() | |||||
| val code = ExcelUtils.getStringValue(row.getCell(COLUMN_WAREHOSE_INDEX)).trim() | |||||
| val zone = ExcelUtils.getStringValue(row.getCell(COLUMN_ZONE_INDEX)).trim() | |||||
| val slot = ExcelUtils.getStringValue(row.getCell(COLUMN_SLOT_INDEX)).trim() | |||||
| // logger.info("Warehouse code - zone - slot: ${row.getCell(COLUMN_WAREHOSE_INDEX).cellType} - ${row.getCell(COLUMN_ZONE_INDEX).cellType} - ${row.getCell(COLUMN_SLOT_INDEX).cellType}") | |||||
| val defaultCapacity = BigDecimal(10000) | |||||
| val warehouseCode = "$code-$zone-$slot" | |||||
| val warehouseName = "$floor-$place" | |||||
| val existingWarehouse = findByCode(warehouseCode) | |||||
| if (existingWarehouse == null) { | |||||
| val warehouseRequest = SaveWarehouseRequest( | |||||
| code = warehouseCode, | |||||
| name = warehouseName, | |||||
| description = warehouseName, | |||||
| capacity = defaultCapacity | |||||
| ) | |||||
| saveWarehouse(warehouseRequest) | |||||
| } | |||||
| } catch (e: Exception) { | |||||
| logger.error("Import Error (Warehouse Error): ${e.message}") | |||||
| } | |||||
| } | |||||
| logger.info("--------- End - Import Warehouse Excel -------") | |||||
| return "Import Excel success"; | |||||
| } | |||||
| } | } | ||||
| @@ -3,9 +3,16 @@ package com.ffii.fpsms.modules.master.web | |||||
| import com.ffii.fpsms.modules.master.entity.Warehouse | import com.ffii.fpsms.modules.master.entity.Warehouse | ||||
| import com.ffii.fpsms.modules.master.entity.projections.WarehouseCombo | import com.ffii.fpsms.modules.master.entity.projections.WarehouseCombo | ||||
| import com.ffii.fpsms.modules.master.service.WarehouseService | import com.ffii.fpsms.modules.master.service.WarehouseService | ||||
| import jakarta.servlet.http.HttpServletRequest | |||||
| import org.apache.poi.ss.usermodel.Workbook | |||||
| import org.apache.poi.xssf.usermodel.XSSFWorkbook | |||||
| import org.springframework.http.ResponseEntity | |||||
| import org.springframework.web.bind.ServletRequestBindingException | |||||
| import org.springframework.web.bind.annotation.GetMapping | import org.springframework.web.bind.annotation.GetMapping | ||||
| import org.springframework.web.bind.annotation.PostMapping | |||||
| import org.springframework.web.bind.annotation.RequestMapping | import org.springframework.web.bind.annotation.RequestMapping | ||||
| import org.springframework.web.bind.annotation.RestController | import org.springframework.web.bind.annotation.RestController | ||||
| import org.springframework.web.multipart.MultipartHttpServletRequest | |||||
| @RestController | @RestController | ||||
| @RequestMapping("/warehouse") | @RequestMapping("/warehouse") | ||||
| @@ -21,4 +28,19 @@ class WarehouseController( | |||||
| fun findCombo(): List<WarehouseCombo> { | fun findCombo(): List<WarehouseCombo> { | ||||
| return warehouseService.findCombo() | return warehouseService.findCombo() | ||||
| } | } | ||||
| @PostMapping("/import") | |||||
| @Throws(ServletRequestBindingException::class) | |||||
| fun importExcel(request: HttpServletRequest): ResponseEntity<*> { | |||||
| var workbook: Workbook? = null; | |||||
| try { | |||||
| val multipartFile = (request as MultipartHttpServletRequest).getFile("multipartFileList") | |||||
| workbook = XSSFWorkbook(multipartFile?.inputStream) | |||||
| } catch (e: Exception) { | |||||
| println(e) | |||||
| } | |||||
| return ResponseEntity.ok(warehouseService.importExcel(workbook)) | |||||
| } | |||||
| } | } | ||||
| @@ -1,6 +1,7 @@ | |||||
| package com.ffii.fpsms.modules.stock.entity | package com.ffii.fpsms.modules.stock.entity | ||||
| import com.ffii.core.support.AbstractRepository | import com.ffii.core.support.AbstractRepository | ||||
| import org.springframework.data.jpa.repository.Query | |||||
| import org.springframework.stereotype.Repository | import org.springframework.stereotype.Repository | ||||
| import java.io.Serializable | import java.io.Serializable | ||||
| @@ -10,4 +11,8 @@ interface InventoryLotRepository: AbstractRepository<InventoryLot, Long> { | |||||
| fun findByItemIdAndDeletedFalse(itemId: Long): List<InventoryLot> | fun findByItemIdAndDeletedFalse(itemId: Long): List<InventoryLot> | ||||
| @Query(""" | |||||
| select il.lotNo from InventoryLot il where il.lotNo like :prefix% order by il.lotNo desc limit 1 | |||||
| """) | |||||
| fun findLatestLotNoByPrefix(prefix: String): String? | |||||
| } | } | ||||
| @@ -81,6 +81,13 @@ open class InventoryService( | |||||
| return inventoryRepository.findInventoryInfoByItemIdInAndDeletedIsFalse(itemIds); | return inventoryRepository.findInventoryInfoByItemIdInAndDeletedIsFalse(itemIds); | ||||
| } | } | ||||
| open fun assignLotNo(): String { | |||||
| val prefix = "LT" | |||||
| val midfix = CodeGenerator.DEFAULT_MIDFIX | |||||
| val latestCode = inventoryLotRepository.findLatestLotNoByPrefix("${prefix}-${midfix}") | |||||
| return CodeGenerator.generateNo(prefix = prefix, latestCode = latestCode) | |||||
| } | |||||
| fun save_po(): PurchaseOrder { | fun save_po(): PurchaseOrder { | ||||
| val poCode = "MANUAL-IMPORT ${LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE)}" | val poCode = "MANUAL-IMPORT ${LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE)}" | ||||
| val po = PurchaseOrder().apply { | val po = PurchaseOrder().apply { | ||||
| @@ -269,11 +276,12 @@ open class InventoryService( | |||||
| // stock in line | // stock in line | ||||
| val oneYearExpiry = 1L | val oneYearExpiry = 1L | ||||
| val stockInLineEntries = polList.map { pol -> | val stockInLineEntries = polList.map { pol -> | ||||
| val newLotNo = CodeGenerator.generateCode( | |||||
| prefix = "MPO", | |||||
| itemId = pol.item!!.id!!, | |||||
| count = pol.id!!.toInt() | |||||
| ) | |||||
| // val newLotNo = CodeGenerator.generateCode( | |||||
| // prefix = "MPO", | |||||
| // itemId = pol.item!!.id!!, | |||||
| // count = pol.id!!.toInt() | |||||
| // ) | |||||
| val newLotNo = assignLotNo() | |||||
| StockInLine().apply { | StockInLine().apply { | ||||
| this.purchaseOrder = po | this.purchaseOrder = po | ||||
| this.purchaseOrderLine = pol | this.purchaseOrderLine = pol | ||||
| @@ -79,6 +79,14 @@ open class StockInLineService( | |||||
| open fun getReceivedStockInLineInfo(stockInLineId: Long): StockInLineInfo { | open fun getReceivedStockInLineInfo(stockInLineId: Long): StockInLineInfo { | ||||
| return stockInLineRepository.findStockInLineInfoByIdAndStatusAndDeletedFalse(id = stockInLineId, status = StockInLineStatus.RECEIVED.status).orElseThrow() | return stockInLineRepository.findStockInLineInfoByIdAndStatusAndDeletedFalse(id = stockInLineId, status = StockInLineStatus.RECEIVED.status).orElseThrow() | ||||
| } | } | ||||
| open fun assignLotNo(): String { | |||||
| val prefix = "LT" | |||||
| val midfix = CodeGenerator.DEFAULT_MIDFIX | |||||
| val latestCode = inventoryLotRepository.findLatestLotNoByPrefix("${prefix}-${midfix}") | |||||
| return CodeGenerator.generateNo(prefix = prefix, latestCode = latestCode) | |||||
| } | |||||
| @Throws(IOException::class) | @Throws(IOException::class) | ||||
| @Transactional | @Transactional | ||||
| open fun create(request: SaveStockInLineRequest): MessageResponse { | open fun create(request: SaveStockInLineRequest): MessageResponse { | ||||
| @@ -179,7 +187,8 @@ open class StockInLineService( | |||||
| "itemId" to stockInLine.item!!.id | "itemId" to stockInLine.item!!.id | ||||
| ) | ) | ||||
| val inventoryCount = jdbcDao.queryForInt(INVENTORY_COUNT.toString(), args) | val inventoryCount = jdbcDao.queryForInt(INVENTORY_COUNT.toString(), args) | ||||
| val newLotNo = CodeGenerator.generateCode(prefix = "MPO", itemId = stockInLine.item!!.id!!, count = inventoryCount) | |||||
| // val newLotNo = CodeGenerator.generateCode(prefix = "MPO", itemId = stockInLine.item!!.id!!, count = inventoryCount) | |||||
| val newLotNo = assignLotNo() | |||||
| inventoryLot.apply { | inventoryLot.apply { | ||||
| this.item = stockInLine.item | this.item = stockInLine.item | ||||
| this.stockInLine = stockInLine | this.stockInLine = stockInLine | ||||
| @@ -21,7 +21,6 @@ import org.slf4j.Logger | |||||
| import org.slf4j.LoggerFactory | import org.slf4j.LoggerFactory | ||||
| import org.springframework.stereotype.Service | import org.springframework.stereotype.Service | ||||
| import java.math.BigDecimal | import java.math.BigDecimal | ||||
| import java.time.LocalDate | |||||
| import java.time.LocalDateTime | import java.time.LocalDateTime | ||||
| @Service | @Service | ||||
| @@ -42,7 +41,7 @@ class StockTakeService( | |||||
| val prefix = "ST" | val prefix = "ST" | ||||
| val midfix = CodeGenerator.DEFAULT_MIDFIX | val midfix = CodeGenerator.DEFAULT_MIDFIX | ||||
| val latestCode = stockTakeRepository.findLatestCodeByPrefix("${prefix}-${midfix}") | val latestCode = stockTakeRepository.findLatestCodeByPrefix("${prefix}-${midfix}") | ||||
| return CodeGenerator.generateOrderNo(prefix = prefix, latestCode = latestCode) | |||||
| return CodeGenerator.generateNo(prefix = prefix, latestCode = latestCode) | |||||
| } | } | ||||
| fun saveStockTake(request: SaveStockTakeRequest): StockTake { | fun saveStockTake(request: SaveStockTakeRequest): StockTake { | ||||