|
|
|
@ -22,8 +22,11 @@ import org.apache.commons.lang.StringUtils; |
|
|
|
import org.springframework.beans.factory.annotation.Autowired; |
|
|
|
import org.springframework.jdbc.core.JdbcTemplate; |
|
|
|
import org.springframework.stereotype.Service; |
|
|
|
import org.springframework.transaction.PlatformTransactionManager; |
|
|
|
import org.springframework.transaction.TransactionDefinition; |
|
|
|
import org.springframework.transaction.annotation.Transactional; |
|
|
|
import org.springframework.transaction.interceptor.TransactionAspectSupport; |
|
|
|
import org.springframework.transaction.support.TransactionTemplate; |
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
import org.springframework.web.multipart.MultipartFile; |
|
|
|
|
|
|
|
@ -60,6 +63,9 @@ public class IfsInventoryInitServiceImpl implements IfsInventoryInitService { |
|
|
|
@Autowired |
|
|
|
private PartAttributeMapper partAttributeMapper; |
|
|
|
|
|
|
|
@Autowired |
|
|
|
private PlatformTransactionManager transactionManager; |
|
|
|
|
|
|
|
@Override |
|
|
|
public PageUtils getInventoryStockList(InventoryStock data) { |
|
|
|
IPage<InventoryStock> ipage = warehouseMapper.getIfsInventoryStockList( |
|
|
|
@ -967,7 +973,11 @@ public class IfsInventoryInitServiceImpl implements IfsInventoryInitService { |
|
|
|
log.warn("=== IFS库存Excel写入失败,已标记整批回滚 === 失败行: {}", rowNumber); |
|
|
|
return buildImportAbortResult(errorMessages); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// 全部库存行写入成功后再补充属性,避免后续库存行失败时提前提交属性。 |
|
|
|
for (Map<String, Object> rowData : successList) { |
|
|
|
int rowNumber = (int) rowData.get("rowNumber"); |
|
|
|
PartAttribute partAttribute = (PartAttribute) rowData.get("part_attribute"); |
|
|
|
if (partAttribute != null) { |
|
|
|
try { |
|
|
|
@ -1046,42 +1056,30 @@ public class IfsInventoryInitServiceImpl implements IfsInventoryInitService { |
|
|
|
|
|
|
|
/** |
|
|
|
* 插入part_attribute记录(如果不存在)。 |
|
|
|
* 已存在则跳过。插入失败先回滚到保存点再抛出,由调用方记日志后继续,不能把库存导入事务标成回滚。 |
|
|
|
* 已存在则跳过。查询与插入使用独立事务,失败仅回滚属性事务,由调用方记日志后继续。 |
|
|
|
* |
|
|
|
* @param partAttribute 料件属性对象 |
|
|
|
* @return true=成功插入,false=已存在跳过 |
|
|
|
*/ |
|
|
|
private boolean insertPartAttributeIfNotExists(PartAttribute partAttribute) { |
|
|
|
PartAttribute existing = partAttributeMapper.getPartAttributeByHeight( |
|
|
|
partAttribute.getSite(), partAttribute.getPartNo(), partAttribute.getHeight()); |
|
|
|
|
|
|
|
if (existing != null) { |
|
|
|
log.debug("料件属性已存在,跳过: site={}, partNo={}", |
|
|
|
partAttribute.getSite(), partAttribute.getPartNo()); |
|
|
|
return false; |
|
|
|
} |
|
|
|
// JpaTransactionManager 不支持当前 JPA 方言的保存点,不能使用 NESTED/createSavepoint。 |
|
|
|
// REQUIRES_NEW 挂起库存事务,确保查询、插入及提交失败都不会污染库存事务。 |
|
|
|
TransactionTemplate attributeTransaction = new TransactionTemplate(transactionManager); |
|
|
|
attributeTransaction.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); |
|
|
|
return Boolean.TRUE.equals(attributeTransaction.execute(status -> { |
|
|
|
PartAttribute existing = partAttributeMapper.getPartAttributeByHeight( |
|
|
|
partAttribute.getSite(), partAttribute.getPartNo(), partAttribute.getHeight()); |
|
|
|
if (existing != null) { |
|
|
|
log.debug("料件属性已存在,跳过: site={}, partNo={}", |
|
|
|
partAttribute.getSite(), partAttribute.getPartNo()); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
// 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; |
|
|
|
log.debug("料件属性新增成功: site={}, partNo={}", |
|
|
|
partAttribute.getSite(), partAttribute.getPartNo()); |
|
|
|
return true; |
|
|
|
})); |
|
|
|
} |
|
|
|
|
|
|
|
/** |
|
|
|
|