소스 검색

update with inventory import

master
MSI\derek 4 주 전
부모
커밋
aa4283c7ea
5개의 변경된 파일276개의 추가작업 그리고 9개의 파일을 삭제
  1. +3
    -3
      src/main/java/com/ffii/fpsms/modules/master/service/BomService.kt
  2. +0
    -1
      src/main/java/com/ffii/fpsms/modules/purchaseOrder/entity/PurchaseOrderLine.kt
  3. +1
    -0
      src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderEnum.kt
  4. +267
    -5
      src/main/java/com/ffii/fpsms/modules/stock/service/InventoryService.kt
  5. +5
    -0
      src/main/resources/db/changelog/changes/20250730_01_derek/01_update_pol_set_m18LogId_null.sql

+ 3
- 3
src/main/java/com/ffii/fpsms/modules/master/service/BomService.kt 파일 보기

@@ -187,12 +187,12 @@ open class BomService(
// println(item)
bomMatRequest.item = item
}
2 -> {
bomMatRequest.qty = tempCell.numericCellValue.toBigDecimal()
}
3 -> {
bomMatRequest.uomName = tempCell.stringCellValue.trim()
}
6 -> {
bomMatRequest.qty = tempCell.numericCellValue.toBigDecimal()
}
7 -> {
val salesUnit = uomConversionRepository.findByCodeAndDeletedFalse(tempCell.stringCellValue.trim())
bomMatRequest.salesUnit = salesUnit


+ 0
- 1
src/main/java/com/ffii/fpsms/modules/purchaseOrder/entity/PurchaseOrderLine.kt 파일 보기

@@ -44,7 +44,6 @@ open class PurchaseOrderLine : BaseEntity<Long>() {
@Column(name = "status", nullable = false, length = 10)
open var status: PurchaseOrderLineStatus? = null

@NotNull
@ManyToOne
@JoinColumn(name = "m18DataLogId", nullable = false)
open var m18DataLog: M18DataLog? = null


+ 1
- 0
src/main/java/com/ffii/fpsms/modules/purchaseOrder/enums/PurchaseOrderEnum.kt 파일 보기

@@ -16,6 +16,7 @@ enum class PurchaseOrderStatus(val value: String) {
}

enum class PurchaseOrderType(val value: String) {
IMPORT ("import"),
MATERIAL ("material"),
SHOP ("shop"),
OEM ("oem")

+ 267
- 5
src/main/java/com/ffii/fpsms/modules/stock/service/InventoryService.kt 파일 보기

@@ -3,17 +3,32 @@ package com.ffii.fpsms.modules.stock.service
import com.ffii.core.response.RecordsRes
import com.ffii.core.support.AbstractBaseEntityService
import com.ffii.core.support.JdbcDao
import com.ffii.fpsms.modules.master.entity.Items
import com.ffii.fpsms.modules.master.entity.ItemsRepository
import com.ffii.fpsms.modules.master.entity.UomConversionRepository
import com.ffii.fpsms.modules.common.CodeGenerator
import com.ffii.fpsms.modules.master.entity.*
import com.ffii.fpsms.modules.master.service.ItemUomService
import com.ffii.fpsms.modules.master.service.UomConversionService
import com.ffii.fpsms.modules.stock.entity.Inventory
import com.ffii.fpsms.modules.stock.entity.InventoryRepository
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
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.stock.entity.*
import com.ffii.fpsms.modules.stock.entity.enum.InventoryLotLineStatus
import com.ffii.fpsms.modules.stock.entity.projection.InventoryInfo
import com.ffii.fpsms.modules.stock.web.model.SearchInventoryRequest
import org.apache.poi.ss.usermodel.Sheet
import org.apache.poi.ss.usermodel.Workbook
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import org.springframework.core.io.support.PathMatchingResourcePatternResolver
import org.springframework.data.domain.PageRequest
import org.springframework.stereotype.Service
import java.math.BigDecimal
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter

@Service
open class InventoryService(
@@ -23,6 +38,14 @@ open class InventoryService(
private val uomConversionService: UomConversionService,
private val uomConversionRepository: UomConversionRepository,
private val itemUomService: ItemUomService,
private val purchaseOrderRepository: PurchaseOrderRepository,
private val purchaseOrderLineRepository: PurchaseOrderLineRepository,
private val currencyRepository: CurrencyRepository,
private val stockInRepository: StockInRepository,
private val stockInLineRepository: StockInLineRepository,
private val inventoryLotRepository: InventoryLotRepository,
private val inventoryLotLineRepository: InventoryLotLineRepository,
private val warehouseRepository: WarehouseRepository
): AbstractBaseEntityService<Inventory, Long, InventoryRepository>(jdbcDao, inventoryRepository) {
open fun allInventory(): List<Inventory> {
// TODO: Replace by actual logic
@@ -58,6 +81,245 @@ open class InventoryService(
return inventoryRepository.findInventoryInfoByItemIdInAndDeletedIsFalse(itemIds);
}

fun save_po(): PurchaseOrder {
val poCode = "MANUAL-IMPORT ${LocalDate.now().format(DateTimeFormatter.ISO_LOCAL_DATE)}"
val po = PurchaseOrder().apply {
this.code = poCode
this.currency = currencyRepository.findByIdAndDeletedIsFalse(1)
this.orderDate = LocalDate.now().atStartOfDay()
this.estimatedArrivalDate = LocalDate.now().atStartOfDay()
this.completeDate = LocalDate.now().atStartOfDay()
this.status = PurchaseOrderStatus.COMPLETED
this.type = PurchaseOrderType.IMPORT
// set m18Datalog to nullable
}
return purchaseOrderRepository.saveAndFlush(po)
}

data class InventoryImportExcelField(
val itemCode: String,
val expiryDate: LocalDate,
val qty: BigDecimal,
val warehouseCode: String,
)

fun save_stock_in(po: PurchaseOrder): StockIn {
val stockIn = StockIn().apply {
this.code = po.code
this.orderDate = po.orderDate
this.estimatedCompleteDate = LocalDate.now()
this.completeDate = LocalDateTime.now()
this.purchaseOrder = po
}
return stockInRepository.save(stockIn)
}
fun save_stock_in_line(po: PurchaseOrder, stockIn: StockIn, pol: MutableList<PurchaseOrderLine>) {
val entries = pol.map {
StockInLine()
}
}
fun batch_save(sheet: Sheet, po: PurchaseOrder) {
var START_ROW_INDEX = 1
var START_COLUMN_INDEX = 1
val checkColumnIndex = 1
val itemCodeColumnIndex = 1
val expiryDateColumnIndex = 2
val qtyColumnIndex = 3
val warehouseColumnIndex = 4
val columnList = listOf(
itemCodeColumnIndex,
expiryDateColumnIndex,
qtyColumnIndex,
warehouseColumnIndex,
)
var counter = 0
val BATCH_SIZE = 50
val entriesList = mutableListOf<PurchaseOrderLine>()
while (true) {
val currentRow = sheet.getRow(START_ROW_INDEX)
val itemCell = currentRow.getCell(itemCodeColumnIndex)
// do save while ch
if (entriesList.size == BATCH_SIZE || itemCell == null) {
if (entriesList.isEmpty()) break
val polEntries = purchaseOrderLineRepository.saveAllAndFlush(entriesList)
val stockIn = save_stock_in(po)
// do save sil
save_stock_in_line(
po = po,
stockIn = stockIn,
pol = polEntries
)
entriesList.clear()
if (itemCell == null) break
}
val expiryDateCell = currentRow.getCell(expiryDateColumnIndex)
val qtyCell = currentRow.getCell(qtyColumnIndex)
val warehouseCell = currentRow.getCell(warehouseColumnIndex)
val request = InventoryImportExcelField(
itemCode = itemCell.stringCellValue,
expiryDate = itemCell.dateCellValue
.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate(),
qty = qtyCell.numericCellValue.toBigDecimal(),
warehouseCode = warehouseCell.stringCellValue
)
val item = itemsRepository.findByCodeAndDeletedFalse(request.itemCode)
val salesUnit = itemUomService.findSalesUnitByItemId(itemId = item!!.id!!)!!.uom
val purchaseOrderLine = PurchaseOrderLine()
.apply {
this.item = item
this.itemNo = item.code
this.uom = salesUnit
this.purchaseOrder = po
this.price = BigDecimal.ZERO
this.status = PurchaseOrderLineStatus.COMPLETED
}
entriesList.add(purchaseOrderLine)


START_ROW_INDEX++
counter++
}
}
open fun importInventoryTestingMethod() {
val resolver = PathMatchingResourcePatternResolver()
val TARGET_LOCATION_FILE = "file:C:/Users/2Fi/Desktop/Fourth Wave of BOM Excel/*.xlsx" // CHANGE THIS FOR DIFFERENT FILE
val excel = resolver.getResource(TARGET_LOCATION_FILE)
val inputStream = excel.inputStream
val workbook: Workbook = XSSFWorkbook(inputStream)
val sheet: Sheet = workbook.getSheetAt(0)

val po = save_po()
// saving lines in batch
batch_save(sheet = sheet, po = po)
}

data class ExcelMap(
val itemCodeColumnIndex: Int,
val expiryDateColumnIndex: Int,
val qtyColumnIndex: Int,
val warehouseColumnIndex: Int,
)
open fun importInventoryExcel() {
val resolver = PathMatchingResourcePatternResolver()
val TARGET_LOCATION_FILE = "file:C:/Users/2Fi/Desktop/Fourth Wave of BOM Excel/*.xlsx" // CHANGE THIS FOR DIFFERENT FILE
val excel = resolver.getResource(TARGET_LOCATION_FILE)
val inputStream = excel.inputStream
val workbook: Workbook = XSSFWorkbook(inputStream)
val sheet: Sheet = workbook.getSheetAt(0)

var START_ROW_INDEX = 1
var START_COLUMN_INDEX = 1
val columnMap = ExcelMap(
1,
2,
3,
4
)
val checkingRow = sheet.getRow(START_ROW_INDEX)
val checkingFirstCell = checkingRow.getCell(columnMap.itemCodeColumnIndex)
val purchaseOrderLineList = mutableListOf<PurchaseOrderLine>()
val requestList = mutableListOf<InventoryImportExcelField>()
// purchase order
val po = save_po()
// purchase order mostly
try {
while (checkingFirstCell != null) {
val currentRow = sheet.getRow(START_ROW_INDEX)
val itemCell = currentRow.getCell(columnMap.itemCodeColumnIndex)
val expiryDateCell = currentRow.getCell(columnMap.expiryDateColumnIndex)
val qtyCell = currentRow.getCell(columnMap.qtyColumnIndex)
val warehouseCell = currentRow.getCell(columnMap.warehouseColumnIndex)
// info
val request = InventoryImportExcelField(
itemCode = itemCell.stringCellValue,
expiryDate = itemCell.dateCellValue
.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate(),
qty = qtyCell.numericCellValue.toBigDecimal(),
warehouseCode = warehouseCell.stringCellValue
)
requestList.add(request)
val item = itemsRepository.findByCodeAndDeletedFalse(request.itemCode)
val salesUnit = itemUomService.findSalesUnitByItemId(itemId = item!!.id!!)!!.uom
// purchase order line
val purchaseOrderLine = PurchaseOrderLine()
.apply {
this.item = item
this.itemNo = item.code
this.uom = salesUnit
this.purchaseOrder = po
this.price = BigDecimal.ZERO
this.status = PurchaseOrderLineStatus.COMPLETED
}
purchaseOrderLineList.add(purchaseOrderLine)
START_ROW_INDEX++
}
} catch (e:Error) {
// write log to pol excel
}

val polList = purchaseOrderLineRepository.saveAllAndFlush(purchaseOrderLineList)
// stock in
val stockIn = save_stock_in(po)
// stock in line
val oneYearExpiry = 1L
val stockInLineEntries = polList.map { pol ->
val newLotNo = CodeGenerator.generateCode(
prefix = "POLOT",
itemId = pol.item!!.id!!,
count = pol.id!!.toInt()
)
StockInLine().apply {
this.purchaseOrder = po
this.purchaseOrderLine = pol
this.item = pol.item
this.itemNo = pol.item!!.code
this.stockIn = stockIn
this.acceptedQty = pol.qty
this.receiptDate = LocalDateTime.now()
this.expiryDate = LocalDate.now().plusYears(oneYearExpiry) // default
this.lotNo = newLotNo
}
}
val savedStockInLineEntries = stockInLineRepository.saveAllAndFlush(stockInLineEntries)
// inventory lot
val inventoryLotEntries = savedStockInLineEntries.map { stockInLine ->
InventoryLot().apply {
this.item = stockInLine.item
this.stockInLine = stockInLine
this.stockInDate = LocalDateTime.now()
this.expiryDate = stockInLine.expiryDate
this.lotNo = stockInLine.lotNo
}
}
val savedInventoryLotEntries = inventoryLotRepository.saveAllAndFlush(inventoryLotEntries)
// inventory lot line
// val inventoryLotLIneEntries = inventoryLotEntries.map {inventoryLot ->
val inventoryLotLineEntries = requestList.mapIndexed { index, request ->
val inventoryLot = savedInventoryLotEntries[index]
val warehouse = warehouseRepository.findAll().find { it.code == request.warehouseCode }!!
val salesUnit = itemUomService.findSalesUnitByItemId(itemId = inventoryLot.item!!.id!!)
InventoryLotLine().apply {
this.inventoryLot = inventoryLot
this.warehouse = warehouse
this.inQty = request.qty
this.status = InventoryLotLineStatus.AVAILABLE
this.stockUom = salesUnit
}
}
val savedInventoryLotLine = inventoryLotLineRepository.saveAllAndFlush(inventoryLotLineEntries)
val updateStockInLineEntries = savedInventoryLotLine.mapIndexed { index, inventoryLotLine ->
savedStockInLineEntries[index].apply {
this.inventoryLotLine = inventoryLotLine
this.inventoryLot = inventoryLotLine.inventoryLot
}
}
val savedNewStockInLineEntries = stockInLineRepository.saveAllAndFlush(updateStockInLineEntries)

}

// @Throws(IOException::class)
// open fun updateInventory(request: SaveInventoryRequest): MessageResponse {


+ 5
- 0
src/main/resources/db/changelog/changes/20250730_01_derek/01_update_pol_set_m18LogId_null.sql 파일 보기

@@ -0,0 +1,5 @@
-- liquibase formatted sql
-- changeset derek:update_pol_set_m18LogId_null

ALTER TABLE `purchase_order_line`
MODIFY COLUMN `m18DataLogId` Int(11) NULL;

불러오는 중...
취소
저장