|
|
|
@ -758,8 +758,8 @@ public class IfsInventoryInitServiceImpl implements IfsInventoryInitService { |
|
|
|
* <p><b>注意:</b></p> |
|
|
|
* <ul> |
|
|
|
* <li>inventory_stock_ifs表:只插入不更新,记录已存在则报错</li> |
|
|
|
* <li>part_attribute表:记录已存在则跳过,不报错;插入异常则整批失败</li> |
|
|
|
* <li>任一行校验或写入失败:一行都不保留,已写入的数据随事务回滚</li> |
|
|
|
* <li>part_attribute表:已存在则跳过;写入失败只记日志,不回滚、不返回给前端</li> |
|
|
|
* <li>库存行校验或写入失败:一行都不保留,已写入的数据随事务回滚</li> |
|
|
|
* </ul> |
|
|
|
* |
|
|
|
* @param file Excel文件 |
|
|
|
@ -953,33 +953,41 @@ public class IfsInventoryInitServiceImpl implements IfsInventoryInitService { |
|
|
|
|
|
|
|
int partAttributeSkipped = 0; |
|
|
|
int partAttributeSaved = 0; |
|
|
|
int partAttributeFailed = 0; |
|
|
|
for (Map<String, Object> 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<String, Object> 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; |
|
|
|
|