diff --git a/src/main/java/com/gaotao/modules/warehouse/service/impl/IfsInventoryInitServiceImpl.java b/src/main/java/com/gaotao/modules/warehouse/service/impl/IfsInventoryInitServiceImpl.java
index 4e025f00..95b5c043 100644
--- a/src/main/java/com/gaotao/modules/warehouse/service/impl/IfsInventoryInitServiceImpl.java
+++ b/src/main/java/com/gaotao/modules/warehouse/service/impl/IfsInventoryInitServiceImpl.java
@@ -758,8 +758,8 @@ public class IfsInventoryInitServiceImpl implements IfsInventoryInitService {
*
注意:
*
* - inventory_stock_ifs表:只插入不更新,记录已存在则报错
- * - part_attribute表:记录已存在则跳过,不报错;插入异常则整批失败
- * - 任一行校验或写入失败:一行都不保留,已写入的数据随事务回滚
+ * - part_attribute表:已存在则跳过;写入失败只记日志,不回滚、不返回给前端
+ * - 库存行校验或写入失败:一行都不保留,已写入的数据随事务回滚
*
*
* @param file Excel文件
@@ -953,33 +953,41 @@ public class IfsInventoryInitServiceImpl implements IfsInventoryInitService {
int partAttributeSkipped = 0;
int partAttributeSaved = 0;
+ int partAttributeFailed = 0;
for (Map rowData : successList) {
int rowNumber = (int) rowData.get("rowNumber");
try {
- // 1. 插入inventory_stock_ifs表(已存在则抛错)
+ // 库存写入失败仍整批回滚;料件属性不放在这个 try 里,避免主键冲突中断导入
insertOrUpdateIfsInventory(rowData);
+ } catch (Exception e) {
+ log.error("第{}行数据插入失败: {}", rowNumber, e.getMessage(), e);
+ errorMessages.add("第" + rowNumber + "行: 数据库插入失败 - " + e.getMessage());
+ // 前面的行已在同一事务里写入;正常返回会提交,必须显式标记回滚才能一行都不留
+ TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
+ log.warn("=== IFS库存Excel写入失败,已标记整批回滚 === 失败行: {}", rowNumber);
+ return buildImportAbortResult(errorMessages);
+ }
- // 2. 插入part_attribute表(已存在则跳过,插入异常向上抛出)
- PartAttribute partAttribute = (PartAttribute) rowData.get("part_attribute");
- if (partAttribute != null) {
+ PartAttribute partAttribute = (PartAttribute) rowData.get("part_attribute");
+ if (partAttribute != null) {
+ try {
boolean saved = insertPartAttributeIfNotExists(partAttribute);
if (saved) {
partAttributeSaved++;
} else {
partAttributeSkipped++;
}
+ } catch (Exception e) {
+ // 属性失败不能进入错误结果:前端会据此提示“未写入任何数据”,库存事务也不能因此回滚
+ partAttributeFailed++;
+ log.error("第{}行料件属性写入失败,已忽略,不影响库存导入: site={}, partNo={}, 原因: {}",
+ rowNumber, partAttribute.getSite(), partAttribute.getPartNo(), e.getMessage(), e);
}
- } catch (Exception e) {
- log.error("第{}行数据插入失败: {}", rowNumber, e.getMessage(), e);
- errorMessages.add("第" + rowNumber + "行: 数据库插入失败 - " + e.getMessage());
- // 前面的行已在同一事务里写入;正常返回会提交,必须显式标记回滚才能一行都不留
- TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
- log.warn("=== IFS库存Excel写入失败,已标记整批回滚 === 失败行: {}", rowNumber);
- return buildImportAbortResult(errorMessages);
}
}
- log.info("=== part_attribute表处理统计 === 新增: {}, 跳过: {}", partAttributeSaved, partAttributeSkipped);
+ log.info("=== part_attribute表处理统计 === 新增: {}, 跳过: {}, 失败已忽略: {}",
+ partAttributeSaved, partAttributeSkipped, partAttributeFailed);
log.info("=== IFS库存Excel导入完成 === 成功: {}, 失败: 0", successList.size());
Map result = new HashMap<>();
@@ -1037,8 +1045,8 @@ public class IfsInventoryInitServiceImpl implements IfsInventoryInitService {
}
/**
- * 插入part_attribute记录(如果不存在)
- * 已存在视为跳过,不报错;插入失败必须抛出,否则库存行会在属性写入失败时被单独提交。
+ * 插入part_attribute记录(如果不存在)。
+ * 已存在则跳过。插入失败先回滚到保存点再抛出,由调用方记日志后继续,不能把库存导入事务标成回滚。
*
* @param partAttribute 料件属性对象
* @return true=成功插入,false=已存在跳过
@@ -1053,7 +1061,24 @@ public class IfsInventoryInitServiceImpl implements IfsInventoryInitService {
return false;
}
- partAttributeMapper.insert(partAttribute);
+ // SQL Server 主键冲突只中止当前语句,但连接上的事务可能无法再提交。
+ // 保存点把失败限制在这次属性插入,回滚后库存导入仍可继续。
+ Object savepoint = TransactionAspectSupport.currentTransactionStatus().createSavepoint();
+ try {
+ partAttributeMapper.insert(partAttribute);
+ } catch (Exception e) {
+ try {
+ TransactionAspectSupport.currentTransactionStatus().rollbackToSavepoint(savepoint);
+ } catch (Exception rollbackEx) {
+ log.error("料件属性保存点回滚失败: site={}, partNo={}",
+ partAttribute.getSite(), partAttribute.getPartNo(), rollbackEx);
+ }
+ if (e instanceof RuntimeException) {
+ throw (RuntimeException) e;
+ }
+ throw new RuntimeException(e);
+ }
+ TransactionAspectSupport.currentTransactionStatus().releaseSavepoint(savepoint);
log.debug("料件属性新增成功: site={}, partNo={}",
partAttribute.getSite(), partAttribute.getPartNo());
return true;