diff --git a/cf-module-prod-plan/cf-module-prod-plan-api/src/main/java/com/cf/imes/module/plan/enums/ErrorCodeConstants.java b/cf-module-prod-plan/cf-module-prod-plan-api/src/main/java/com/cf/imes/module/plan/enums/ErrorCodeConstants.java index 871d10e80..3028fc803 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-api/src/main/java/com/cf/imes/module/plan/enums/ErrorCodeConstants.java +++ b/cf-module-prod-plan/cf-module-prod-plan-api/src/main/java/com/cf/imes/module/plan/enums/ErrorCodeConstants.java @@ -18,4 +18,5 @@ public class ErrorCodeConstants { public static final ErrorCode WEBCAD_ORDER_IMPORT_FAILED = new ErrorCode(1_005_000_008, "导入失败:请检查拆单数据"); public static final ErrorCode WEBCAD_ORDER_IMPORT_PLATE_NOT_EXIST_ERROR = new ErrorCode(1_005_000_009, "导入失败:板材对应失败,板材库中不存在对应板材【{}】"); public static final ErrorCode WEBCAD_ORDER_IMPORT_SEAL_NOT_EXIST_ERROR = new ErrorCode(1_005_000_010, "导入失败:封边条对应失败,配件库中不存在对应封边条【{}】"); + public static final ErrorCode WEBCAD_ORDER_IMPORT_SAVEDATA_ERROR = new ErrorCode(1_005_000_011, "导入失败:数据保存异常,请检查拆单数据"); } diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/OrderImportController.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/OrderImportController.java index ddf55a0c9..402d0d170 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/OrderImportController.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/controller/admin/orderImport/OrderImportController.java @@ -31,7 +31,7 @@ public class OrderImportController { private WebCadOrderImportService webCadOrderImportService; @PostMapping("/webcad/import") - @Operation(summary = "生产单导入新增") + @Operation(summary = "webcad拆单导入生产单") @OperateLog(type = IMPORT) public CommonResult webCadOrderImport(@RequestBody WebCadDataReqVO webCadDataReqVO) { webCadOrderImportService.webCadOrderImport(webCadDataReqVO); diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/WebCadOrderImportServiceImpl.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/WebCadOrderImportServiceImpl.java index f62c40f27..07245b3cc 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/WebCadOrderImportServiceImpl.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/WebCadOrderImportServiceImpl.java @@ -25,7 +25,9 @@ import com.cf.imes.module.plan.service.order.OrderInputProcessor; import com.cf.imes.module.plan.service.orderImport.factory.WebCadOrderImportFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; @@ -91,7 +93,11 @@ public class WebCadOrderImportServiceImpl implements WebCadOrderImportService { @Resource private PlateGoodMapper plateGoodMapper; + @Resource + private DataSourceTransactionManager transactionManager; + @Override + @Transactional(rollbackFor = Exception.class) public void webCadOrderImport(WebCadDataReqVO webCadDataReqVO) { Long organId = OrganContextHolder.getOrganId(); String redisUniqueKey = "webcad"; @@ -106,7 +112,7 @@ public class WebCadOrderImportServiceImpl implements WebCadOrderImportService { throw new ServiceException(ORDER_IMPORT_ORGAN_LOCK_ERROR); } WebCadOrderImportFactory webCadOrderImportFactory = new WebCadOrderImportFactory(organId, orderMapper, snowFlakeGenerator, orderBodyMapper, plateMapper, orderItemMapper, orderGroupMapper, - idWorker, orderInputProcessor, partsMapper, orderPartsMapper, goodsMapper, rawGoodsMapper, plateGoodMapper, customPlateNoGenerateService); + idWorker, orderInputProcessor, partsMapper, orderPartsMapper, goodsMapper, rawGoodsMapper, plateGoodMapper, customPlateNoGenerateService, transactionManager); webCadOrderImportFactory.analyzeTempData(webCadDataReqVO); } catch (ServiceException se) { throw se; diff --git a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/WebCadOrderImportFactory.java b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/WebCadOrderImportFactory.java index 8f924450b..7c183d160 100644 --- a/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/WebCadOrderImportFactory.java +++ b/cf-module-prod-plan/cf-module-prod-plan-biz/src/main/java/com/cf/imes/module/plan/service/orderImport/factory/WebCadOrderImportFactory.java @@ -6,6 +6,7 @@ import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.ObjectUtil; import com.alibaba.excel.util.ListUtils; import com.alibaba.fastjson.JSON; +import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.cf.imes.framework.common.exception.ServiceException; import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil; @@ -48,6 +49,9 @@ import com.cf.imes.module.plan.service.customplateno.vo.CustomPlateNoGenerateCon import com.cf.imes.module.plan.service.order.OrderInputProcessor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; +import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.transaction.TransactionDefinition; +import org.springframework.transaction.TransactionStatus; import java.math.BigDecimal; import java.time.LocalDateTime; @@ -55,11 +59,16 @@ import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_IMPORT_MATERIALS_EMPTY_ERROR; import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_IMPORT_PLATE_NOT_EXIST_ERROR; import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_IMPORT_ROOMBODY_EMPTY_ERROR; +import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_IMPORT_SAVEDATA_ERROR; import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_IMPORT_SEAL_NOT_EXIST_ERROR; import static com.cf.imes.module.plan.enums.ErrorCodeConstants.WEBCAD_ORDER_NOT_EXISTS_ERROR; @@ -104,6 +113,8 @@ public class WebCadOrderImportFactory { private CustomPlateNoGenerateService customPlateNoGenerateService; + private DataSourceTransactionManager transactionManager; + private Long organId; private Long orderId; @@ -115,6 +126,10 @@ public class WebCadOrderImportFactory { private CustomPlateNoGenerateConfigVO plateNoGenerateConfigVO; + // 操作人 + private String operatorName; + + private LocalDateTime now; // 柜体成倍信息缓存:{ 房间名+柜体名:childrenDTO } private Map roomBodyMap = new HashMap<>(); @@ -153,7 +168,8 @@ public class WebCadOrderImportFactory { GoodsMapper goodsMapper, RawGoodsMapper rawGoodsMapper, PlateGoodMapper plateGoodMapper, - CustomPlateNoGenerateService customPlateNoGenerateService) { + CustomPlateNoGenerateService customPlateNoGenerateService, + DataSourceTransactionManager transactionManager) { this.organId = organId; this.orderMapper = orderMapper; this.snowFlakeGenerator = snowFlakeGenerator; @@ -169,6 +185,9 @@ public class WebCadOrderImportFactory { this.rawGoodsMapper = rawGoodsMapper; this.plateGoodMapper = plateGoodMapper; this.customPlateNoGenerateService = customPlateNoGenerateService; + this.transactionManager = transactionManager; + operatorName = SecurityFrameworkUtils.getLoginUser().getNickname(); + now = LocalDateTime.now(); } public void analyzeTempData(WebCadDataReqVO webCadDataReqVO) { @@ -419,6 +438,10 @@ public class WebCadOrderImportFactory { OrderBodyDO orderBodyDO = OrderBodyDO.builder().id(bodyId).orderId(orderId).organId(organId) .roomId(roomId).roomName(roomName).name(bodyName).width(0.0).height(0.0) .depth(0.0).multiNum(0).plateNum(0).unregularNum(0).filename("无").remark("无").deleted(false).build(); + orderBodyDO.setCreator(operatorName); + orderBodyDO.setUpdater(operatorName); + orderBodyDO.setCreateTime(now); + orderBodyDO.setUpdateTime(now); // 缓存成倍的柜体信息 bodyMap.put(roomBodyKey + i, orderBodyDO); @@ -454,6 +477,10 @@ public class WebCadOrderImportFactory { orderBodyDO = OrderBodyDO.builder().id(bodyId).orderId(orderId).organId(organId) .roomId(roomId).roomName(roomName).name(bodyName).width(0.0).height(0.0) .depth(0.0).multiNum(0).plateNum(0).unregularNum(0).filename("无").remark("无").deleted(false).build(); + orderBodyDO.setCreator(operatorName); + orderBodyDO.setUpdater(operatorName); + orderBodyDO.setCreateTime(now); + orderBodyDO.setUpdateTime(now); // 缓存成倍的柜体信息 bodyMap.put(roomBodyKey, orderBodyDO); @@ -533,10 +560,8 @@ public class WebCadOrderImportFactory { .deleted(false) .organId(organId) .build(); - String operatorName = SecurityFrameworkUtils.getLoginUser().getNickname(); plateDO.setCreator(operatorName); plateDO.setUpdater(operatorName); - LocalDateTime now = LocalDateTime.now(); plateDO.setCreateTime(now); plateDO.setUpdateTime(now); @@ -624,6 +649,11 @@ public class WebCadOrderImportFactory { .remark("无") .deleted(false) .build(); + orderGroupDO.setCreator(operatorName); + orderGroupDO.setUpdater(operatorName); + orderGroupDO.setCreateTime(now); + orderGroupDO.setUpdateTime(now); + orderGroupMap.put(groupMapKey, orderGroupDO); orderGroupDOS.add(orderGroupDO); } else { @@ -731,6 +761,10 @@ public class WebCadOrderImportFactory { orderBodyDO = OrderBodyDO.builder().id(bodyId).orderId(orderId).organId(organId) .roomId(roomId).roomName(roomName).name(bodyName).width(0.0).height(0.0) .depth(0.0).multiNum(0).plateNum(0).unregularNum(0).filename("无").remark("无").deleted(false).build(); + orderBodyDO.setCreator(operatorName); + orderBodyDO.setUpdater(operatorName); + orderBodyDO.setCreateTime(now); + orderBodyDO.setUpdateTime(now); // 缓存成倍的柜体信息 bodyMap.put(roomBodyKey, orderBodyDO); @@ -777,6 +811,11 @@ public class WebCadOrderImportFactory { .remark("无") .deleted(false) .build(); + orderGroupDO.setCreator(operatorName); + orderGroupDO.setUpdater(operatorName); + orderGroupDO.setCreateTime(now); + orderGroupDO.setUpdateTime(now); + orderGroupMap.put(groupMapKey, orderGroupDO); orderGroupDOS.add(orderGroupDO); } @@ -1045,15 +1084,94 @@ public class WebCadOrderImportFactory { } } +// /** +// * 数据保存入库 +// */ +// private void saveData() { +// orderInfoBatchInsertWithinThreshold(orderBodyMapper, bodyMap.values().stream().toList(), true); +// orderInfoBatchInsertWithinThreshold(orderItemMapper, orderItemDOS, true); +// orderInfoBatchInsertWithinThreshold(orderGroupMapper, orderGroupDOS, true); +// } + + /** * 数据保存入库 + * orderBody、orderItem、orderGroup */ private void saveData() { - orderInfoBatchInsertWithinThreshold(orderBodyMapper, bodyMap.values().stream().toList(), true); - orderInfoBatchInsertWithinThreshold(orderItemMapper, orderItemDOS, true); - orderInfoBatchInsertWithinThreshold(orderGroupMapper, orderGroupDOS, true); - } + TransactionStatus transactionStatus = transactionManager.getTransaction(TransactionDefinition.withDefaults()); + ExecutorService executorService = Executors.newFixedThreadPool(3); + AtomicBoolean hasError = new AtomicBoolean(false); + CountDownLatch latch = new CountDownLatch(3); + // 当前数据源data_code + String peek = DynamicDataSourceContextHolder.peek(); + Runnable bodyTask = () -> { + try { + // 子线程同步主线程的多数据源 + DynamicDataSourceContextHolder.push(peek); + orderInfoBatchInsertWithinThreshold(orderBodyMapper, bodyMap.values().stream().toList(), true); + } catch (Exception e) { + hasError.set(true); + log.error("Error saving order bodies", e); + } finally { + latch.countDown(); + } + }; + + Runnable itemTask = () -> { + try { + // 子线程同步主线程的多数据源 + DynamicDataSourceContextHolder.push(peek); + orderInfoBatchInsertWithinThreshold(orderItemMapper, orderItemDOS, true); + } catch (Exception e) { + hasError.set(true); + log.error("Error saving order items", e); + } finally { + latch.countDown(); + } + }; + + Runnable groupTask = () -> { + try { + // 子线程同步主线程的多数据源 + DynamicDataSourceContextHolder.push(peek); + orderInfoBatchInsertWithinThreshold(orderGroupMapper, orderGroupDOS, true); + } catch (Exception e) { + hasError.set(true); + log.error("Error saving order groups", e); + } finally { + latch.countDown(); + } + }; + + // 执行子线程 + executorService.submit(bodyTask); + executorService.submit(itemTask); + executorService.submit(groupTask); + + try { + // 等待所有任务完成 + latch.await(); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + hasError.set(true); + log.error("WEBCAD import saveData Thread interrupted", e); + } finally { + // 中止所有任务 + executorService.shutdown(); + } + + if (hasError.get()) { + // 所有任务事务提交 + transactionManager.rollback(transactionStatus); + // 抛出异常回滚主线程的数据 + throw new ServiceException(WEBCAD_ORDER_IMPORT_SAVEDATA_ERROR); + } else { + // 所有任务事务回滚 + transactionManager.commit(transactionStatus); + } + } /** * 清空所有列表