浏览代码

update

master
CANCERYS\kw093 3 周前
父节点
当前提交
211992525f
共有 2 个文件被更改,包括 53 次插入49 次删除
  1. +51
    -48
      src/main/java/com/ffii/fpsms/modules/master/service/WarehouseService.kt
  2. +2
    -1
      src/main/java/com/ffii/fpsms/modules/master/web/models/SaveWarehouseRequest.kt

+ 51
- 48
src/main/java/com/ffii/fpsms/modules/master/service/WarehouseService.kt 查看文件

@@ -120,6 +120,7 @@ open class WarehouseService(
val sheet: Sheet = workbook.getSheetAt(0);
// Columns
val COLUMN_REF_INDEX = 0;
val COLUMN_WAREHOSE_INDEX = 1;
val COLUMN_ZONE_INDEX = 2;
val COLUMN_SLOT_INDEX = 3;
@@ -131,12 +132,13 @@ open class WarehouseService(
val START_ROW_INDEX = 5;
// 第一步:收集所有 Excel 数据(包含行索引,用于调试)
// first step: collect all Excel data (contains row index, for debugging)
data class ExcelWarehouseDataWithRow(
val rowIndex: Int,
val warehouse: String,
val area: String,
val slot: String
val slot: String,
val ref: String?
)
val excelDataList = mutableListOf<ExcelWarehouseDataWithRow>()
@@ -150,6 +152,7 @@ open class WarehouseService(
}
try {
val ref = ExcelUtils.getStringValue(row.getCell(COLUMN_REF_INDEX))?.trim()
val warehouse = ExcelUtils.getStringValue(row.getCell(COLUMN_WAREHOSE_INDEX))?.trim()
val area = ExcelUtils.getStringValue(row.getCell(COLUMN_ZONE_INDEX))?.trim()
val slot = ExcelUtils.getStringValue(row.getCell(COLUMN_SLOT_INDEX))?.trim()
@@ -159,7 +162,7 @@ open class WarehouseService(
continue
}
excelDataList.add(ExcelWarehouseDataWithRow(i, warehouse, area, slot))
excelDataList.add(ExcelWarehouseDataWithRow(i, warehouse, area, slot,ref))
} catch (e: Exception) {
logger.error("Read Error (Row ${i + 1}): ${e.message}")
skippedRows++
@@ -168,25 +171,26 @@ open class WarehouseService(
logger.info("Total rows in Excel: ${sheet.lastRowNum - START_ROW_INDEX + 1}, Valid rows collected: ${excelDataList.size}, Skipped: $skippedRows")
// 第二步:计算 order 映射(使用 ExcelWarehouseData)
val excelDataForOrder = excelDataList.map {
ExcelWarehouseData(it.warehouse, it.area, it.slot)
// second step: calculate order map (using ExcelWarehouseData)
val excelDataForOrder = excelDataList.map {
ExcelWarehouseData(it.warehouse, it.area, it.slot, it.ref ?: "${it.rowIndex}") // 如果 ref 为空,使用 rowIndex
}
val orderMap = calculateOrderMap(excelDataForOrder)
logger.info("Order map size: ${orderMap.size}")
// 第三步:在循环中使用 orderMap 匹配
// third step: use orderMap to match in the loop
var updateCount = 0
var createCount = 0
var skippedInSecondLoop = 0
val processedKeys = mutableSetOf<String>()
// val processedKeys = mutableSetOf<String>()
for (i in START_ROW_INDEX..<sheet.lastRowNum) {
val row = sheet.getRow(i)
if (row == null) continue
try {
val ref = ExcelUtils.getStringValue(row.getCell(COLUMN_REF_INDEX))?.trim()
val warehouse = ExcelUtils.getStringValue(row.getCell(COLUMN_WAREHOSE_INDEX))?.trim()
val area = ExcelUtils.getStringValue(row.getCell(COLUMN_ZONE_INDEX))?.trim()
val slot = ExcelUtils.getStringValue(row.getCell(COLUMN_SLOT_INDEX))?.trim()
@@ -200,12 +204,12 @@ open class WarehouseService(
continue
}
// 使用唯一标识从 orderMap 获取 order
val uniqueKey = "$warehouse-$area-$slot"
val order = orderMap[uniqueKey]
// use unique identifier from orderMap to get order
val refKey = ref ?: "${i + 1}"
val order = orderMap[refKey]
if (order == null) {
logger.warn("Order not found for key: $uniqueKey at row ${i + 1}")
logger.warn("Order not found for key: ${refKey}Key at row ${i + 1}")
skippedInSecondLoop++
continue
}
@@ -215,28 +219,22 @@ open class WarehouseService(
val name = "$store_id-$storeLocation"
val description = "$store_id-$storeLocation"
// 检查是否已经处理过这个 uniqueKey(避免重复处理)
if (processedKeys.contains(uniqueKey)) {
logger.warn("Duplicate key found: $uniqueKey at row ${i + 1}, skipping")
skippedInSecondLoop++
continue
}
processedKeys.add(uniqueKey)
// 查找现有仓库
val existingWarehouse = warehouseRepository.findAll()
.firstOrNull {
it.code == code && it.deleted == false
} ?: warehouseRepository.findAll()
.firstOrNull {
it.warehouse == warehouse &&
it.area == area &&
it.slot == slot &&
it.deleted == false
// check if the warehouse exists
val existingWarehouse = if (!ref.isNullOrBlank()) {
try {
val refId = ref.toLong()
warehouseRepository.findById(refId).orElse(null)?.takeIf { !it.deleted }
} catch (e: NumberFormatException) {
logger.warn("Invalid ref format: $ref at row ${i + 1}, treating as new record")
null
}
} else {
null
}
if (existingWarehouse != null) {
// 更新
// update the warehouse
existingWarehouse.apply {
this.code = code
this.name = name
@@ -253,7 +251,7 @@ open class WarehouseService(
warehouseRepository.save(existingWarehouse)
updateCount++
} else {
// 创建
// create the warehouse
val newWarehouse = Warehouse().apply {
this.code = code
this.name = name
@@ -281,40 +279,45 @@ open class WarehouseService(
return "Import Excel success - Created: $createCount, Updated: $updateCount, Skipped: $skippedInSecondLoop";
}

// 计算 order 映射:接收 Excel 数据列表,返回 Map<唯一标识, order>
// calculate order map: receive Excel data list, return Map<unique identifier, order>
private fun calculateOrderMap(excelDataList: List<ExcelWarehouseData>): Map<String, Int> {
data class WarehouseWithSort(
val data: ExcelWarehouseData,
val sortValue: Long,
val uniqueKey: String
val ref: String, // ref as unique identifier
val warehouse: String,
val area: String,
val slot: String,
val sortValue: Long
)

val sortedWarehouses = excelDataList.map { data ->
val slot = data.slot.toIntOrNull() ?: 0
val sortValue = calculateSortValue(data.warehouse, data.area, slot)
val uniqueKey = "${data.warehouse}-${data.area}-${data.slot}"
WarehouseWithSort(data, sortValue, uniqueKey)
}.sortedBy { it.sortValue }

// 分配连续的 order(1, 2, 3...),类似 ROW_NUMBER()
// use ref as unique identifier (ref is stored in rowIndex field)
val ref = data.rowIndex
WarehouseWithSort(ref, data.warehouse, data.area, data.slot, sortValue)
}.sortedBy { it.sortValue } // sort by sortValue
// assign consecutive order (1, 2, 3...), return Map<ref, order>
return sortedWarehouses.mapIndexed { index, warehouseWithSort ->
warehouseWithSort.uniqueKey to (index + 1) // 唯一标识 -> order
warehouseWithSort.ref to (index + 1) // ref -> order
}.toMap()
}
// 计算单个仓库的排序值(与 MySQL 逻辑一致)
// calculate sort value for a single warehouse (consistent with MySQL logic)
private fun calculateSortValue(warehouseStr: String, areaStr: String, slot: Int): Long {
// 提取楼层号
// extract floor number
val floorNumber = if (warehouseStr.length >= 2) {
warehouseStr.substring(1, 2).toIntOrNull() ?: 99
} else 99
// 提取字母部分
// extract letter part
val letterPart = if (areaStr.startsWith("#") && areaStr.length >= 2) {
areaStr.substring(1, 2)
} else null
// 计算楼层排序值
// calculate floor sort value
val floorOrder = when (floorNumber) {
2 -> 1
3 -> 2
@@ -322,7 +325,7 @@ open class WarehouseService(
else -> 99
}
// 计算字母排序值(与 MySQL 逻辑一致)
// calculate letter sort value (consistent with MySQL logic)
val letterOrder = when {
letterPart == null -> 9999
letterPart in listOf("C", "B", "A", "E", "F", "G", "H", "I", "N", "M", "L", "P", "Q", "R", "S", "Y", "O", "K", "D") -> {
@@ -336,7 +339,7 @@ open class WarehouseService(
else -> 1000 + letterPart[0].code
}
// 计算总排序值:楼层 * 10000 + 字母 * 100 + slot
// calculate total sort value: floor * 10000 + letter * 100 + slot
return floorOrder * 10000L + letterOrder * 100L + slot
}
}

+ 2
- 1
src/main/java/com/ffii/fpsms/modules/master/web/models/SaveWarehouseRequest.kt 查看文件

@@ -28,5 +28,6 @@ data class NewWarehouseRequest(
data class ExcelWarehouseData(
val warehouse: String,
val area: String,
val slot: String
val slot: String,
val rowIndex: String
)

正在加载...
取消
保存