| @@ -137,7 +137,7 @@ open class M18DeliveryOrderService( | |||
| // Process for Delivery Order (mainpo) | |||
| // Assume only one DO in the DO (search by DO ID) | |||
| 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 deliveryOrderLineMessage = deliveryOrderDetail?.messages | |||
| @@ -4,7 +4,7 @@ import java.time.LocalDate | |||
| import java.time.format.DateTimeFormatter | |||
| object CodeGenerator { | |||
| // Default Value for Lot No | |||
| // Old Function | |||
| private var dateFormat = DateTimeFormatter.ofPattern("yyMMdd") | |||
| fun generateCode(prefix: String, itemId: Long, count: Int): String { | |||
| // prefix = "ITEM" || "LOT" | |||
| @@ -15,12 +15,12 @@ object CodeGenerator { | |||
| 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_FORMATTER = DateTimeFormatter.ofPattern(DEFAULT_PATTERN) | |||
| val DEFAULT_MIDFIX = LocalDate.now().format(DEFAULT_FORMATTER) | |||
| fun generateOrderNo( | |||
| fun generateNo( | |||
| suffixFormat: String? = null, | |||
| pattern: String? = null, | |||
| prefix: String, | |||
| @@ -74,7 +74,7 @@ open class SchedulerService( | |||
| // Init Scheduler | |||
| // @PostConstruct | |||
| fun init() { | |||
| scheduleM18PoTask(); | |||
| // scheduleM18PoTask(); | |||
| scheduleM18MasterData(); | |||
| scheduleRoughProd(); | |||
| scheduleDetailedProd(); | |||
| @@ -160,8 +160,8 @@ open class SchedulerService( | |||
| ) | |||
| m18PurchaseOrderService.savePurchaseOrders(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() { | |||
| @@ -179,7 +179,7 @@ open class SchedulerService( | |||
| m18MasterDataService.saveVendors(request) | |||
| m18MasterDataService.saveBusinessUnits(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.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.Warehouse | |||
| 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.service.InventoryLotService | |||
| 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 java.math.BigDecimal | |||
| import kotlin.jvm.optionals.getOrNull | |||
| @Service | |||
| open class WarehouseService( | |||
| private val jdbcDao: JdbcDao, | |||
| private val warehouseRepository: WarehouseRepository, | |||
| ): AbstractBaseEntityService<Warehouse, Long, WarehouseRepository>(jdbcDao, warehouseRepository) { | |||
| ) : AbstractBaseEntityService<Warehouse, Long, WarehouseRepository>(jdbcDao, warehouseRepository) { | |||
| open fun getWarehouses(): List<Warehouse> { | |||
| return warehouseRepository.findAll().filter { it.deleted == false } | |||
| } | |||
| @@ -51,4 +57,56 @@ open class WarehouseService( | |||
| 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.projections.WarehouseCombo | |||
| 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.PostMapping | |||
| import org.springframework.web.bind.annotation.RequestMapping | |||
| import org.springframework.web.bind.annotation.RestController | |||
| import org.springframework.web.multipart.MultipartHttpServletRequest | |||
| @RestController | |||
| @RequestMapping("/warehouse") | |||
| @@ -21,4 +28,19 @@ class WarehouseController( | |||
| fun findCombo(): List<WarehouseCombo> { | |||
| 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 | |||
| import com.ffii.core.support.AbstractRepository | |||
| import org.springframework.data.jpa.repository.Query | |||
| import org.springframework.stereotype.Repository | |||
| import java.io.Serializable | |||
| @@ -10,4 +11,8 @@ interface InventoryLotRepository: AbstractRepository<InventoryLot, Long> { | |||
| 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); | |||
| } | |||
| 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 { | |||
| val poCode = "MANUAL-IMPORT ${LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE)}" | |||
| val po = PurchaseOrder().apply { | |||
| @@ -269,11 +276,12 @@ open class InventoryService( | |||
| // stock in line | |||
| val oneYearExpiry = 1L | |||
| 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 { | |||
| this.purchaseOrder = po | |||
| this.purchaseOrderLine = pol | |||
| @@ -79,6 +79,14 @@ open class StockInLineService( | |||
| open fun getReceivedStockInLineInfo(stockInLineId: Long): StockInLineInfo { | |||
| 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) | |||
| @Transactional | |||
| open fun create(request: SaveStockInLineRequest): MessageResponse { | |||
| @@ -179,7 +187,8 @@ open class StockInLineService( | |||
| "itemId" to stockInLine.item!!.id | |||
| ) | |||
| 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 { | |||
| this.item = stockInLine.item | |||
| this.stockInLine = stockInLine | |||
| @@ -21,7 +21,6 @@ import org.slf4j.Logger | |||
| import org.slf4j.LoggerFactory | |||
| import org.springframework.stereotype.Service | |||
| import java.math.BigDecimal | |||
| import java.time.LocalDate | |||
| import java.time.LocalDateTime | |||
| @Service | |||
| @@ -42,7 +41,7 @@ class StockTakeService( | |||
| val prefix = "ST" | |||
| val midfix = CodeGenerator.DEFAULT_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 { | |||