Sfoglia il codice sorgente

import bom excel

production_process
MSI\derek 2 mesi fa
parent
commit
fc9b340f44
13 ha cambiato i file con 272 aggiunte e 7 eliminazioni
  1. +1
    -1
      src/main/java/com/ffii/fpsms/modules/master/entity/Bom.kt
  2. +2
    -2
      src/main/java/com/ffii/fpsms/modules/master/entity/BomMaterial.kt
  3. +3
    -0
      src/main/java/com/ffii/fpsms/modules/master/entity/ItemsRepository.kt
  4. +223
    -4
      src/main/java/com/ffii/fpsms/modules/master/service/BomService.kt
  5. +6
    -0
      src/main/java/com/ffii/fpsms/modules/master/web/BomController.kt
  6. +28
    -0
      src/main/java/com/ffii/fpsms/modules/master/web/models/SaveBomRequest.kt
  7. BIN
      src/main/resources/bomImport/006 PP1080 咖喱汁 Pings BOM Template v3.xlsx
  8. BIN
      src/main/resources/bomImport/200 PP - PP1193 蔥油(1磅) Pings BOM Template.xlsx
  9. BIN
      src/main/resources/bomImport/201 PP - PP1188 咖喱膽 Pings BOM Template.xlsx
  10. BIN
      src/main/resources/bomImport/202 PP - PP1096 白麵撈(1磅) Pings BOM Template.xlsx
  11. BIN
      src/main/resources/bomImport/801 PP1080 咖哩汁箱料粉 Pings BOM Template v3.xlsx
  12. +5
    -0
      src/main/resources/db/changelog/changes/20250611_01_derek/01_update_bom_material_col.sql
  13. +4
    -0
      src/main/resources/db/changelog/changes/20250611_01_derek/02_update_bom_score_col.sql

+ 1
- 1
src/main/java/com/ffii/fpsms/modules/master/entity/Bom.kt Vedi File

@@ -16,7 +16,7 @@ open class Bom : BaseEntity<Long>() {
open var isDark: Int? = null

@Column
open var isFloat: Boolean? = null
open var isFloat: Int? = null

@Column
open var isDense: Int? = null


+ 2
- 2
src/main/java/com/ffii/fpsms/modules/master/entity/BomMaterial.kt Vedi File

@@ -42,11 +42,11 @@ open class BomMaterial : BaseEntity<Long>() {
@JsonBackReference
open var bom: Bom? = null

@NotNull
// @NotNull
@Column(name = "m18Id", nullable = false)
open var m18Id: Long? = null

@NotNull
// @NotNull
@Column(name = "m18LastModifyDate", nullable = false)
open var m18LastModifyDate: LocalDateTime? = null



+ 3
- 0
src/main/java/com/ffii/fpsms/modules/master/entity/ItemsRepository.kt Vedi File

@@ -5,6 +5,7 @@ import com.ffii.fpsms.modules.master.web.models.ItemType
import org.springframework.data.jpa.repository.Query
import org.springframework.stereotype.Repository
import java.io.Serializable
import java.util.Optional

@Repository
interface ItemsRepository : AbstractRepository<Items, Long> {
@@ -13,6 +14,8 @@ interface ItemsRepository : AbstractRepository<Items, Long> {
fun findByIdAndDeletedFalse(id: Long): Items?;

fun findByCodeAndTypeAndDeletedFalse(code: String, type: String): Items?;
fun findByCodeAndDeletedFalse(code: String): Items?;
fun findByNameAndDeletedFalse(name: String): Items?;

fun findByM18IdAndDeletedIsFalse(m18Id: Long): Items?;



+ 223
- 4
src/main/java/com/ffii/fpsms/modules/master/service/BomService.kt Vedi File

@@ -1,18 +1,32 @@
package com.ffii.fpsms.modules.master.service

import com.ffii.fpsms.modules.master.entity.Bom
import com.ffii.fpsms.modules.master.entity.BomRepository
import com.ffii.fpsms.modules.master.entity.*
import com.ffii.fpsms.modules.master.web.models.ImportBomMatRequest
import com.ffii.fpsms.modules.master.web.models.ImportBomRequest
import com.ffii.fpsms.modules.master.web.models.SaveBomRequest
import com.ffii.fpsms.modules.master.web.models.SaveBomResponse
import org.apache.poi.ss.usermodel.CellType
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.ClassPathResource
import org.springframework.core.io.support.PathMatchingResourcePatternResolver
import org.springframework.stereotype.Service
import kotlin.jvm.optionals.getOrNull
import java.io.File


@Service
open class BomService(
val bomRepository: BomRepository,
val bomMaterialRepository: BomMaterialRepository,
val itemsService: ItemsService,
val uomConversionService: UomConversionService
val itemsRepository: ItemsRepository,
val uomConversionService: UomConversionService,
val uomConversionRepository: UomConversionRepository
) {
private val COMPLETION_PROJECT = "templates/report/AR05_Project Completion Report.xlsx"
private val EXCEL_PATH = "bomImport/006 PP1080 咖喱汁 Pings BOM Template v3.xlsx"
// private val EXCEL_PATH = "C:\\Users\\2Fi\\Documents\\MTMS\\Ping's Production MTMS Project Folder\\模組2_生產規劃 (Production Planning)\\PP1080 咖哩汁 Bom\\006 PP1080 咖喱汁 Pings BOM Template v3.xlsx"

open fun findAll(): List<Bom> {
return bomRepository.findAll()
@@ -65,4 +79,209 @@ open class BomService(

return response
}

//////// -------------------------------- for excel import ------------------------------- /////////
fun saveBomEntity(req: ImportBomRequest): Bom {
val item = if (req.itemId != null) itemsRepository.findById(req.itemId).orElseThrow() else null
val uom = if (req.uomId != null) uomConversionRepository.findById(req.uomId).orElseThrow() else null
val bom = Bom().apply {
this.isDark = req.isDark
this.isFloat = req.isFloat
this.isDense = req.isDense
this.code = req.code
this.name = req.name
this.description = req.description
this.item = item
this.outputQty = req.outputQty
this.outputQtyUom = req.outputQtyUom
this.yield = req.yield
this.uom = uom
// this.excelUom = req.excelUom
}
val savedBom = bomRepository.saveAndFlush(bom)
// println("saved: ${savedBom.id}")
return savedBom
}

fun saveBomMaterial(req: ImportBomMatRequest): BomMaterial {
val bomMaterial = BomMaterial().apply {
this.item = req.item
this.itemName = req.item!!.name
this.isConsumable = req.isConsumable
this.qty = req.qty
this.uomName = req.uomName
this.bom = req.bom

}
return bomMaterialRepository.saveAndFlush(bomMaterial)
}
fun importExcelBomMaterial(bom: Bom, sheet: Sheet) {
var request = ImportBomMatRequest(
bom = bom
)
var startRowIndex = 10
val endRowIndex = 30
var startColumnIndex = 0
val endColumnIndex = 9
while (startRowIndex < endRowIndex) {
val tempRow = sheet.getRow(startRowIndex)
val tempCell = tempRow.getCell(startColumnIndex)
if (tempCell != null && tempCell.cellType == CellType.STRING && tempCell.stringCellValue.trim() == "材料編號") {
println("last: $startRowIndex")
startRowIndex++
break
}
startRowIndex++
}
while (startRowIndex != endRowIndex || startColumnIndex != endColumnIndex) {
val tempRow = sheet.getRow(startRowIndex)
val tempCell = tempRow.getCell(startColumnIndex)
if (tempCell == null || tempCell.cellType == CellType.BLANK) {
break
} else {
try {
when (startColumnIndex) {
0 -> {
// println("start")
val nameRow = sheet.getRow(startRowIndex)
val nameCell = nameRow.getCell(1)
val item = itemsRepository.findByCodeAndDeletedFalse(tempCell.stringCellValue.trim())
?: itemsRepository.findByNameAndDeletedFalse(nameCell.stringCellValue.trim())
// println(item)
request.apply {
this.item = item
}
}
2 -> {
request.apply {
this.qty = tempCell.numericCellValue.toBigDecimal()
}
}
3 -> {
request.apply {
this.uomName = tempCell.stringCellValue.trim()
}
}
}
} catch(e: Error) {
println(startColumnIndex)
println(startRowIndex)
println(tempCell.stringCellValue.trim())
}
}
if (startColumnIndex < endColumnIndex) {
startColumnIndex++
} else if (startRowIndex < endRowIndex) {
startRowIndex++
// do save
saveBomMaterial(request)
startColumnIndex = 0
}
}

}

fun importExcelBomBasicInfo(sheet: Sheet): Bom {
var request = ImportBomRequest(
code = "",
name = "",
description = "",
)
var startRowIndex = 0
val endRowIndex = 15
var startColumnIndex = 0
val endColumnIndex = 15
while (startRowIndex != endRowIndex || startColumnIndex != endColumnIndex) {
val tempRow = sheet.getRow(startRowIndex)
val tempCell = tempRow.getCell(startColumnIndex)
if (tempCell != null && tempCell.cellType == CellType.STRING) {
val tempCellVal = tempCell.stringCellValue.trim()
// --------------------- assigning value that is under a header to request ------------------------ //
val topTargetValueRow = sheet.getRow(startRowIndex + 1)
val topTargetValueCell = topTargetValueRow.getCell(startColumnIndex)
when (tempCellVal) {
"編號" -> {
println(topTargetValueCell.stringCellValue.trim())
request.apply {
code = topTargetValueCell.stringCellValue.trim()
}
}
"產品名稱" -> request.apply {
name = topTargetValueCell.stringCellValue.trim()
}
"種類" -> request.apply {
description = topTargetValueCell.stringCellValue.trim()
}
"份量 (Qty)" -> request.apply {
outputQty = topTargetValueCell.numericCellValue.toBigDecimal()
}
"單位" -> request.apply {
outputQtyUom = topTargetValueCell.stringCellValue.trim()
}
}
// ----------------------------------------------------------------------------------------------- //
// --------------------- assigning value that is next to a header to request ------------------------ //
fun calculateColourScore(value: String): Int {
var score = -1
when (value) {
"淺" -> score = 0
"深" -> score = 1
}
return score
}
fun calculateFloatScore(value: String): Int {
var score = -1
when (value) {
"沉" -> score = 0
"浮" -> score = 1
}
return score
}
val leftTargetValueRow = sheet.getRow(startRowIndex)
val leftTargetValueCell = leftTargetValueRow.getCell(startColumnIndex + 1)
if (tempCellVal == "顔色深淺度") println("顔色深淺度")
when (tempCellVal) {
"顔色深淺度" -> request.apply {
isDark = calculateColourScore(leftTargetValueCell.stringCellValue.trim())
}
"浮沉" -> request.apply {
isFloat = calculateFloatScore(leftTargetValueCell.stringCellValue.trim())
}
"濃淡程度" -> request.apply {
isDense = if (leftTargetValueCell.cellType == CellType.NUMERIC) leftTargetValueCell.numericCellValue.toInt() else 0
}
}
}
if (startRowIndex < endRowIndex) {
startRowIndex++
} else if (startColumnIndex < endColumnIndex) {
startColumnIndex++
startRowIndex = 0
}
}
return saveBomEntity(request)
}
open fun importBOM() {
// val folderPath = "bomImport"
// val folder = File(folderPath)
val resolver = PathMatchingResourcePatternResolver()
val excels = resolver.getResources("bomImport/*.xlsx")

for (resource in excels) {
//get sheet
println(resource.filename)
val templateInputStream = resource.inputStream
val workbook: Workbook = XSSFWorkbook(templateInputStream)
val sheet: Sheet = workbook.getSheetAt(0)
// val rowIndex = 1
// val columnIndex = 0
// val tempRow = sheet.getRow(rowIndex)
// val tempCell = tempRow.getCell(columnIndex)
// println(tempCell.cellType)
// println(tempCell.toString())
val bom = importExcelBomBasicInfo(sheet) // updating bom table
val bomMaterial = importExcelBomMaterial(bom, sheet)
// break
}
}
}

+ 6
- 0
src/main/java/com/ffii/fpsms/modules/master/web/BomController.kt Vedi File

@@ -3,6 +3,7 @@ package com.ffii.fpsms.modules.master.web
import com.ffii.fpsms.modules.master.entity.Bom
import com.ffii.fpsms.modules.master.service.BomService
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

@@ -15,4 +16,9 @@ class BomController (
fun getBoms(): List<Bom> {
return bomService.findAll()
}

@PostMapping("/import-bom")
fun importBom() {
return bomService.importBOM()
}
}

+ 28
- 0
src/main/java/com/ffii/fpsms/modules/master/web/models/SaveBomRequest.kt Vedi File

@@ -1,5 +1,7 @@
package com.ffii.fpsms.modules.master.web.models

import com.ffii.fpsms.modules.master.entity.Bom
import com.ffii.fpsms.modules.master.entity.Items
import jakarta.validation.constraints.NotBlank
import java.math.BigDecimal
import java.time.LocalDateTime
@@ -20,4 +22,30 @@ data class SaveBomRequest (
val m18UomId: Long? = null,
val m18Id: Long? = null,
val m18LastModifyDate: LocalDateTime? = null
)
data class ImportBomRequest (
@field:NotBlank(message = "bom code cannot be empty")
var code: String,
@field:NotBlank(message = "bom name cannot be empty")
var name: String,
@field:NotBlank(message = "bom description cannot be empty")
var description: String,
var itemId: Long? = null,
var outputQty: BigDecimal? = null,
var outputQtyUom: String? = null,
var yield: BigDecimal? = null,
var uomId: Long? = null,
var isDark: Int? = null,
var isFloat: Int? = null,
var isDense: Int? = null,
// var excelUom: String? = null
)

data class ImportBomMatRequest (
var item: Items? = null,
var isConsumable: Boolean? = false,
var qty: BigDecimal? = null,
var uomId: Long? = null,
var uomName: String? = null,
var bom: Bom? = null,
)

BIN
src/main/resources/bomImport/006 PP1080 咖喱汁 Pings BOM Template v3.xlsx Vedi File


BIN
src/main/resources/bomImport/200 PP - PP1193 蔥油(1磅) Pings BOM Template.xlsx Vedi File


BIN
src/main/resources/bomImport/201 PP - PP1188 咖喱膽 Pings BOM Template.xlsx Vedi File


BIN
src/main/resources/bomImport/202 PP - PP1096 白麵撈(1磅) Pings BOM Template.xlsx Vedi File


BIN
src/main/resources/bomImport/801 PP1080 咖哩汁箱料粉 Pings BOM Template v3.xlsx Vedi File


+ 5
- 0
src/main/resources/db/changelog/changes/20250611_01_derek/01_update_bom_material_col.sql Vedi File

@@ -0,0 +1,5 @@
-- liquibase formatted sql
-- changeset derek:modify bom material m18 related column
ALTER TABLE `bom_material`
MODIFY COLUMN `m18Id` INT(11) NULL,
MODIFY COLUMN `m18LastModifyDate` DATETIME NULL;

+ 4
- 0
src/main/resources/db/changelog/changes/20250611_01_derek/02_update_bom_score_col.sql Vedi File

@@ -0,0 +1,4 @@
-- liquibase formatted sql
-- changeset derek:update_bom_score_col
ALTER TABLE `bom`
MODIFY COLUMN `isFloat` INT(11) NULL;

Caricamento…
Annulla
Salva