src/main/java/com/ruoyi/production/bean/dto/ProductionPlanDto.java
@@ -42,4 +42,14 @@ @Schema(description = "产品ID") private Long productId; @Schema(description = "筛选开始日期") @JsonFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd") private LocalDate requiredDateStart; @Schema(description = "筛选结束日期") @JsonFormat(pattern = "yyyy-MM-dd") @DateTimeFormat(pattern = "yyyy-MM-dd") private LocalDate requiredDateEnd; } src/main/java/com/ruoyi/production/bean/vo/ProductionPlanVo.java
@@ -21,4 +21,13 @@ @Schema(description = "产品ID") private Long productId; @Schema(description = "销售合同号") private String salesContractNo; @Schema(description = "客户名称") private String customerName; @Schema(description = "项目名称") private String projectName; } src/main/java/com/ruoyi/production/controller/ProductionOrderController.java
@@ -5,6 +5,7 @@ import com.ruoyi.framework.web.domain.R; import com.ruoyi.production.bean.dto.ProductionOrderDto; import com.ruoyi.production.bean.vo.ProductionOrderVo; import com.ruoyi.production.bean.vo.ProductionPlanVo; import com.ruoyi.production.pojo.ProductionOrder; import com.ruoyi.production.service.ProductionOrderService; import io.swagger.v3.oas.annotations.Operation; @@ -43,18 +44,11 @@ } @PostMapping("/addOrder") @Operation(summary = "新增生产订单", description = "新增下单只支持两种方式:1. 生产计划生成,传 productionPlanIds,系统自动汇总计划得到产品规格和数量;" + "2. 手动新增,必须传 productModelId 和 quantity。" @Operation(summary = "新增生产订单", description = "新增下单只支持1种方式:生产计划生成,传 productionPlanIds,系统自动汇总计划得到产品规格和数量;" + "technologyRoutingId 为空时会自动匹配该产品规格最新工艺路线,quantity 最终必须大于 0。") @io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, description = "前端友好提示:如果是生产计划生成,请传 productionPlanIds;" + "如果是手动新增,请至少填写 productModelId、quantity,且 quantity 必须大于 0。", content = @Content(schema = @Schema(implementation = ProductionOrder.class))) , content = @Content(schema = @Schema(implementation = ProductionOrder.class))) public R<Boolean> add(@RequestBody ProductionOrder productionOrder) { return R.ok(productionOrderService.saveProductionOrder(productionOrder)); } @PutMapping("/editOrder") @Operation(summary = "修改生产订单") public R<Boolean> edit(@RequestBody ProductionOrder productionOrder) { return R.ok(productionOrderService.saveProductionOrder(productionOrder)); } @@ -75,4 +69,10 @@ public R<Boolean> remove(@RequestBody List<Long> ids) { return R.ok(productionOrderService.removeProductionOrder(ids)); } @GetMapping("/source/{id}") @Operation(summary = "生产订单查询来源") public R<List<ProductionPlanVo>> getSource(@PathVariable Long id) { return R.ok(productionOrderService.getSource(id)); } } src/main/java/com/ruoyi/production/mapper/ProductionPlanMapper.java
@@ -27,4 +27,6 @@ List<ProductionPlanDto> selectWithMaterialByIds(@Param("ids") List<Long> ids); ProductionPlanDto selectProductionPlanDtoById(@Param("productionPlanId") Long productionPlanId); List<ProductionPlanVo> getSource(@Param("ids") List<Long> planIds); } src/main/java/com/ruoyi/production/pojo/ProductionOperationTask.java
@@ -73,4 +73,7 @@ @Schema(description = "部门ID") @TableField(fill = FieldFill.INSERT) private Long deptId; @Schema(description = "权限用户ID列表,格式:[1,2,3]。指定多个用户ID时,用逗号分隔。") private String userIds; } src/main/java/com/ruoyi/production/pojo/ProductionOrder.java
@@ -29,9 +29,6 @@ @TableId(value = "id", type = IdType.AUTO) private Long id; @Schema(description = "销售台账id。生产下单接口通常不需要前端手工填写,存在销售来源时由系统内部回填。") private Long salesLedgerId; @Schema(description = "生产计划ID列表,格式:[1,2,3]。如果按生产计划生成订单,新增时传这个字段即可,系统会自动汇总产品规格和数量。") private String productionPlanIds; @@ -63,9 +60,6 @@ @Schema(description = "结束日期") private LocalDateTime endTime; @Schema(description = "销售产品规格id。生产下单接口一般不作为前端必填项,存在销售来源时由系统内部关联。") private Integer salesLedgerProductId; @Schema(description = "创建人ID") @TableField(fill = FieldFill.INSERT) src/main/java/com/ruoyi/production/pojo/ProductionOrderBom.java
@@ -3,11 +3,8 @@ import com.baomidou.mybatisplus.annotation.*; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.Getter; import lombok.Setter; import java.io.Serializable; import java.math.BigDecimal; /** * <p> @@ -28,26 +25,20 @@ @TableId(value = "id", type = IdType.AUTO) private Long id; @Schema(description = "父节点ID") private Long parentId; @Schema(description = "生产订单id") private Long productionOrderId; @Schema(description = "产品规格id") private Long productModelId; @Schema(description = "工序id") private Long technologyOperationId; @Schema(description = "BOM编号") private String bomNo; @Schema(description = "单位产出需要数量") private BigDecimal unitQuantity; @Schema(description = "备注") private String remark; @Schema(description = "需求数量") private BigDecimal demandedQuantity; @Schema(description = "单位") private String unit; @Schema(description = "版本号") private String version; @Schema(description = "bom的id") private Long bomId; src/main/java/com/ruoyi/production/pojo/ProductionOrderPick.java
@@ -3,8 +3,6 @@ import com.baomidou.mybatisplus.annotation.*; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.Getter; import lombok.Setter; import java.io.Serializable; import java.math.BigDecimal; src/main/java/com/ruoyi/production/pojo/ProductionOrderRoutingOperation.java
@@ -31,8 +31,8 @@ @Schema(description = "工艺路线工序表id") private Long technologyRoutingOperationId; @Schema(description = "工艺路线id") private Long technologyRoutingId; @Schema(description = "生产订单工艺路线id") private Long orderRoutingId; @Schema(description = "产品规格id") private Long productModelId; src/main/java/com/ruoyi/production/pojo/ProductionPlan.java
@@ -74,14 +74,8 @@ @Schema(description = "已下发数量") private BigDecimal quantityIssued; @Schema(description = "是否下发制造订单") private Boolean issued; @Schema(description = "来源 销售/内部") private String source; @Schema(description = "审核状态") private String isAudit; @Schema(description = "承诺日期") private LocalDate promisedDeliveryDate; src/main/java/com/ruoyi/production/service/ProductionOrderService.java
@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.IService; import com.ruoyi.production.bean.dto.ProductionOrderDto; import com.ruoyi.production.bean.vo.ProductionOrderVo; import com.ruoyi.production.bean.vo.ProductionPlanVo; import com.ruoyi.production.pojo.ProductionOrder; import java.util.List; @@ -24,4 +25,6 @@ int syncProductionOrderSnapshot(Long productionOrderId); Object bindingRoute(ProductionOrderDto productionOrderDto); List<ProductionPlanVo> getSource(Long id); } src/main/java/com/ruoyi/production/service/impl/ProductionOrderRoutingOperationServiceImpl.java
@@ -91,7 +91,7 @@ Long routingId = null; ProductionOrderRoutingOperation deleteItem = productionOrderRoutingOperationMapper.selectById(id); if (deleteItem != null) { routingId = deleteItem.getTechnologyRoutingId(); routingId = deleteItem.getOrderRoutingId(); } productionOperationTaskMapper.delete(new LambdaQueryWrapper<ProductionOperationTask>() .eq(ProductionOperationTask::getTechnologyRoutingOperationId, id)); @@ -99,7 +99,7 @@ if (routingId != null) { List<ProductionOrderRoutingOperation> operationList = productionOrderRoutingOperationMapper.selectList( Wrappers.<ProductionOrderRoutingOperation>lambdaQuery() .eq(ProductionOrderRoutingOperation::getTechnologyRoutingId, routingId) .eq(ProductionOrderRoutingOperation::getOrderRoutingId, routingId) .eq(ProductionOrderRoutingOperation::getProductionOrderId, productionOrderId) .orderByAsc(ProductionOrderRoutingOperation::getDragSort)); for (int i = 0; i < operationList.size(); i++) { @@ -121,7 +121,7 @@ ProductionOrderRoutingOperation oldItem = productionOrderRoutingOperationMapper.selectById(productionOrderRoutingOperation.getId()); List<ProductionOrderRoutingOperation> operationList = productionOrderRoutingOperationMapper.selectList( Wrappers.<ProductionOrderRoutingOperation>lambdaQuery() .eq(ProductionOrderRoutingOperation::getTechnologyRoutingId, oldItem.getTechnologyRoutingId()) .eq(ProductionOrderRoutingOperation::getOrderRoutingId, oldItem.getOrderRoutingId()) .orderByAsc(ProductionOrderRoutingOperation::getDragSort)); Integer targetPosition = productionOrderRoutingOperation.getDragSort(); if (targetPosition != null && targetPosition >= 1) { src/main/java/com/ruoyi/production/service/impl/ProductionOrderServiceImpl.java
@@ -16,14 +16,13 @@ import com.ruoyi.common.exception.ServiceException; import com.ruoyi.production.bean.dto.ProductionOrderDto; import com.ruoyi.production.bean.vo.ProductionOrderVo; import com.ruoyi.production.bean.vo.ProductionPlanVo; import com.ruoyi.production.enums.ProductOrderStatusEnum; import com.ruoyi.production.mapper.*; import com.ruoyi.production.pojo.*; import com.ruoyi.production.service.ProductionOrderService; import com.ruoyi.sales.mapper.SalesLedgerMapper; import com.ruoyi.sales.mapper.SalesLedgerProductMapper; import com.ruoyi.sales.pojo.SalesLedger; import com.ruoyi.sales.pojo.SalesLedgerProduct; import com.ruoyi.technology.mapper.*; import com.ruoyi.technology.pojo.*; import lombok.RequiredArgsConstructor; @@ -105,7 +104,6 @@ if (!saved) { return false; } syncProductionPlanIssueStatus(oldOrder, productionOrder); boolean needSync = productionOrder.getTechnologyRoutingId() != null && (oldOrder == null || !Objects.equals(oldOrder.getTechnologyRoutingId(), productionOrder.getTechnologyRoutingId()) @@ -180,6 +178,16 @@ } @Override public List<ProductionPlanVo> getSource(Long id) { ProductionOrder productionOrder = baseMapper.selectById(id); if (productionOrder != null && productionOrder.getProductionPlanIds() != null) { List<Long> planIds = parsePlanIds(productionOrder.getProductionPlanIds()); return productionPlanMapper.getSource(planIds); } return null; } @Override public int syncProductionOrderSnapshot(Long productionOrderId) { ProductionOrder productionOrder = this.getById(productionOrderId); if (productionOrder == null) { @@ -224,7 +232,7 @@ ProductionOrderRoutingOperation targetOperation = new ProductionOrderRoutingOperation(); targetOperation.setProductionOrderId(productionOrder.getId()); targetOperation.setTechnologyRoutingOperationId(sourceOperation.getId()); targetOperation.setTechnologyRoutingId(orderRouting.getId()); targetOperation.setOrderRoutingId(orderRouting.getId()); targetOperation.setProductModelId(sourceOperation.getProductModelId()); targetOperation.setDragSort(sourceOperation.getDragSort()); targetOperation.setIsQuality(sourceOperation.getIsQuality()); @@ -289,10 +297,9 @@ orderBom.setProductionOrderId(productionOrder.getId()); orderBom.setBomId(Long.valueOf(technologyBom.getId())); orderBom.setProductModelId(root != null ? root.getProductModelId() : productionOrder.getProductModelId()); orderBom.setTechnologyOperationId(root == null ? null : root.getOperationId()); orderBom.setUnitQuantity(root != null && root.getUnitQuantity() != null ? root.getUnitQuantity() : BigDecimal.ONE); orderBom.setDemandedQuantity(orderQuantity); orderBom.setUnit(root == null ? null : root.getUnit()); orderBom.setRemark(technologyBom.getRemark()); orderBom.setBomNo(technologyBom.getBomNo()); orderBom.setVersion(technologyBom.getVersion()); productionOrderBomMapper.insert(orderBom); Map<Long, Long> idMap = new HashMap<>(); @@ -354,7 +361,6 @@ ProductionOrder query = dto == null ? new ProductionOrder() : dto; return Wrappers.<ProductionOrder>lambdaQuery() .eq(query.getId() != null, ProductionOrder::getId, query.getId()) .eq(query.getSalesLedgerId() != null, ProductionOrder::getSalesLedgerId, query.getSalesLedgerId()) .eq(query.getProductModelId() != null, ProductionOrder::getProductModelId, query.getProductModelId()) .eq(query.getTechnologyRoutingId() != null, ProductionOrder::getTechnologyRoutingId, query.getTechnologyRoutingId()) .like(query.getNpsNo() != null && !query.getNpsNo().trim().isEmpty(), ProductionOrder::getNpsNo, query.getNpsNo()) @@ -406,7 +412,6 @@ if (productionOrder == null) { throw new ServiceException("生产订单不能为空"); } fillFromSalesLedgerProduct(productionOrder); fillFromProductionPlans(productionOrder); if (productionOrder.getProductModelId() == null) { throw new ServiceException("产品规格ID不能为空"); @@ -414,54 +419,23 @@ if (defaultDecimal(productionOrder.getQuantity()).compareTo(BigDecimal.ZERO) <= 0) { throw new ServiceException("下单数量必须大于0"); } // if (productionOrder.getTechnologyRoutingId() == null) { // // 未显式指定工艺路线时,按产品规格选最新一条工艺作为默认路线。 // TechnologyRouting technologyRouting = technologyRoutingMapper.selectOne( // Wrappers.<TechnologyRouting>lambdaQuery() // .eq(TechnologyRouting::getProductModelId, productionOrder.getProductModelId()) // .orderByDesc(TechnologyRouting::getId) // .last("limit 1")); // if (technologyRouting == null) { // throw new ServiceException("未找到该产品规格对应的工艺路线"); // } // productionOrder.setTechnologyRoutingId(technologyRouting.getId()); // } if (productionOrder.getTechnologyRoutingId() == null) { // 未显式指定工艺路线时,按产品规格选最新一条工艺作为默认路线。 TechnologyRouting technologyRouting = technologyRoutingMapper.selectOne( Wrappers.<TechnologyRouting>lambdaQuery() .eq(TechnologyRouting::getProductModelId, productionOrder.getProductModelId()) .orderByDesc(TechnologyRouting::getId) .last("limit 1")); if (technologyRouting != null) { productionOrder.setTechnologyRoutingId(technologyRouting.getId()); } } if (oldOrder != null && ProductOrderStatusEnum.isStarted(oldOrder.getStatus())) { // 开工后只允许修正非核心字段,核心生产依据锁定。 if (!Objects.equals(oldOrder.getProductModelId(), productionOrder.getProductModelId()) || !Objects.equals(oldOrder.getTechnologyRoutingId(), productionOrder.getTechnologyRoutingId()) || compareDecimal(oldOrder.getQuantity(), productionOrder.getQuantity()) != 0) { throw new ServiceException("生产订单已开工,不能修改产品、工艺路线或数量"); } } } private void fillFromSalesLedgerProduct(ProductionOrder productionOrder) { if (productionOrder.getSalesLedgerProductId() == null) { return; } // 销售明细是订单来源时,以销售明细为准回填销售台账、产品规格和默认数量。 SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(productionOrder.getSalesLedgerProductId().longValue()); if (salesLedgerProduct == null) { throw new ServiceException("销售台账产品不存在"); } if (productionOrder.getSalesLedgerId() == null) { productionOrder.setSalesLedgerId(salesLedgerProduct.getSalesLedgerId()); } else if (!Objects.equals(productionOrder.getSalesLedgerId(), salesLedgerProduct.getSalesLedgerId())) { throw new ServiceException("销售台账ID与销售台账产品不一致"); } if (productionOrder.getProductModelId() == null) { productionOrder.setProductModelId(salesLedgerProduct.getProductModelId()); } else if (!Objects.equals(productionOrder.getProductModelId(), salesLedgerProduct.getProductModelId())) { throw new ServiceException("产品规格ID与销售台账产品不一致"); } if (productionOrder.getQuantity() == null || productionOrder.getQuantity().compareTo(BigDecimal.ZERO) <= 0) { productionOrder.setQuantity(salesLedgerProduct.getQuantity()); } if (productionOrder.getPlanCompleteTime() == null && productionOrder.getSalesLedgerId() != null) { SalesLedger salesLedger = salesLedgerMapper.selectById(productionOrder.getSalesLedgerId()); if (salesLedger != null && salesLedger.getDeliveryDate() != null) { productionOrder.setPlanCompleteTime(salesLedger.getDeliveryDate()); } } } @@ -507,43 +481,73 @@ productionOrder.setProductionPlanIds(formatPlanIds(planIds)); } private void syncProductionPlanIssueStatus(ProductionOrder oldOrder, ProductionOrder newOrder) { // 只处理本次增量变化,避免无关计划被重复写状态。 Set<Long> oldIds = new LinkedHashSet<>(parsePlanIds(oldOrder == null ? null : oldOrder.getProductionPlanIds())); Set<Long> newIds = new LinkedHashSet<>(parsePlanIds(newOrder == null ? null : newOrder.getProductionPlanIds())); Set<Long> toRelease = new LinkedHashSet<>(oldIds); toRelease.removeAll(newIds); Set<Long> toIssue = new LinkedHashSet<>(newIds); toIssue.removeAll(oldIds); if (!toRelease.isEmpty()) { updatePlanIssuedFlag(new ArrayList<>(toRelease), false); } if (!toIssue.isEmpty()) { updatePlanIssuedFlag(new ArrayList<>(toIssue), true); } } private void releaseProductionPlanIssueStatus(ProductionOrder productionOrder) { if (productionOrder == null) { return; } List<Long> planIds = parsePlanIds(productionOrder.getProductionPlanIds()); if (!planIds.isEmpty()) { updatePlanIssuedFlag(planIds, false); // 生产订单删除--对应的生产计划的已下发数量要减去 updatePlanIssuedFlag(planIds, productionOrder.getQuantity()); } } private void updatePlanIssuedFlag(List<Long> planIds, boolean issued) { //生产订单删除,生产计划的已下发数量对应变更 private void updatePlanIssuedFlag(List<Long> planIds, BigDecimal remainingAssignedQuantity) { if (planIds == null || planIds.isEmpty()) { return; } List<ProductionPlan> plans = productionPlanMapper.selectBatchIds(planIds); //下发数量减去 List<ProductionPlan> updates = new ArrayList<>(); for (ProductionPlan plan : plans) { BigDecimal requiredQuantity = Optional.ofNullable(plan.getQtyRequired()).orElse(BigDecimal.ZERO); if (requiredQuantity.compareTo(BigDecimal.ZERO) < 0) { requiredQuantity = BigDecimal.ZERO; } BigDecimal remainingQuantity = resolveRemainingQuantity(plan); BigDecimal historicalIssuedQuantity = requiredQuantity.subtract(remainingQuantity); BigDecimal issuedQuantity = remainingAssignedQuantity.min(historicalIssuedQuantity); remainingAssignedQuantity = remainingAssignedQuantity.subtract(issuedQuantity); BigDecimal totalIssuedQuantity = historicalIssuedQuantity.subtract(issuedQuantity); int planStatus = resolvePlanStatus(requiredQuantity, totalIssuedQuantity); ProductionPlan update = new ProductionPlan(); update.setId(plan.getId()); update.setIssued(issued); productionPlanMapper.updateById(update); update.setStatus(planStatus); update.setQuantityIssued(totalIssuedQuantity); updates.add(update); } if (!updates.isEmpty()) { productionPlanMapper.updateById(updates); } } private BigDecimal resolveRemainingQuantity(ProductionPlan plan) { if (plan == null) { return BigDecimal.ZERO; } BigDecimal requiredQuantity = Optional.ofNullable(plan.getQtyRequired()).orElse(BigDecimal.ZERO); if (requiredQuantity.compareTo(BigDecimal.ZERO) <= 0) { return BigDecimal.ZERO; } BigDecimal issuedQuantity = Optional.ofNullable(plan.getQuantityIssued()).orElse(BigDecimal.ZERO); if (issuedQuantity.compareTo(BigDecimal.ZERO) <= 0) { return requiredQuantity; } if (issuedQuantity.compareTo(requiredQuantity) >= 0) { return BigDecimal.ZERO; } return requiredQuantity.subtract(issuedQuantity); } private int resolvePlanStatus(BigDecimal requiredQuantity, BigDecimal issuedQuantity) { if (requiredQuantity == null || requiredQuantity.compareTo(BigDecimal.ZERO) <= 0) { return 0; } if (issuedQuantity == null || issuedQuantity.compareTo(BigDecimal.ZERO) <= 0) { return 0; } return issuedQuantity.compareTo(requiredQuantity) < 0 ? 1 : 2; } private void upsertOrderPick(ProductionOrder productionOrder) { src/main/java/com/ruoyi/production/service/impl/ProductionPlanServiceImpl.java
@@ -160,7 +160,6 @@ update.setId(plan.getId()); update.setStatus(planStatus); update.setQuantityIssued(totalIssuedQuantity); update.setIssued(planStatus == PLAN_STATUS_ISSUED); updates.add(update); } if (!updates.isEmpty()) { src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -169,7 +169,7 @@ List<ProductionOrderRoutingOperation> routingOperationList = productionOrderRoutingOperationMapper.selectList( Wrappers.<ProductionOrderRoutingOperation>lambdaQuery() .eq(ProductionOrderRoutingOperation::getTechnologyRoutingId, routingOperation.getTechnologyRoutingId()) .eq(ProductionOrderRoutingOperation::getOrderRoutingId, routingOperation.getOrderRoutingId()) .eq(ProductionOrderRoutingOperation::getProductionOrderId, routingOperation.getProductionOrderId())); boolean isLastOperation = routingOperation.getDragSort() != null && routingOperation.getDragSort().equals(routingOperationList.size()); if (productQty.compareTo(BigDecimal.ZERO) > 0) { @@ -245,8 +245,8 @@ } ProductionAccount productionAccount = new ProductionAccount(); productionAccount.setProductionProductMainId(productionProductMain.getId()); productionAccount.setSalesLedgerId(productionOrder.getSalesLedgerId()); productionAccount.setSalesLedgerProductId(productionOrder.getSalesLedgerProductId() == null ? null : productionOrder.getSalesLedgerProductId().longValue()); // productionAccount.setSalesLedgerId(productionOrder.getSalesLedgerId()); // productionAccount.setSalesLedgerProductId(productionOrder.getSalesLedgerProductId() == null ? null : productionOrder.getSalesLedgerProductId().longValue()); productionAccount.setSchedulingUserId(user == null ? null : user.getUserId()); productionAccount.setSchedulingUserName(user == null ? dto.getUserName() : user.getNickName()); productionAccount.setFinishedNum(productQty); @@ -301,7 +301,7 @@ // 只有最后一道工序的报工才会影响生产订单完工数量。 List<ProductionOrderRoutingOperation> routingOperationList = productionOrderRoutingOperationMapper.selectList( Wrappers.<ProductionOrderRoutingOperation>lambdaQuery() .eq(ProductionOrderRoutingOperation::getTechnologyRoutingId, routingOperation.getTechnologyRoutingId()) .eq(ProductionOrderRoutingOperation::getOrderRoutingId, routingOperation.getOrderRoutingId()) .eq(ProductionOrderRoutingOperation::getProductionOrderId, routingOperation.getProductionOrderId())); boolean isLastOperation = routingOperation.getDragSort() != null && routingOperation.getDragSort().equals(routingOperationList.size()); if (isLastOperation) { src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java
@@ -163,7 +163,7 @@ BeanUtils.copyProperties(sourceOperation, newOperation); newOperation.setId(null); newOperation.setProductionOrderId(newOrder.getId()); newOperation.setTechnologyRoutingId(routingIdMap.get(sourceOperation.getTechnologyRoutingId())); newOperation.setOrderRoutingId(routingIdMap.get(sourceOperation.getOrderRoutingId())); newOperation.setCreateTime(null); newOperation.setUpdateTime(null); productionOrderRoutingOperationMapper.insert(newOperation); src/main/java/com/ruoyi/sales/service/impl/SalesLedgerProductServiceImpl.java
@@ -253,6 +253,7 @@ if (!salesLedgerProduct.getIsProduction()) { return; } SalesLedger salesLedger = salesLedgerMapper.selectById(salesLedgerProduct.getSalesLedgerId()); ProductionPlan productionPlan = new ProductionPlan(); productionPlan.setSalesLedgerId(salesLedgerProduct.getSalesLedgerId()); productionPlan.setSalesLedgerProductId(salesLedgerProduct.getId()); @@ -261,6 +262,8 @@ productionPlan.setQtyRequired(salesLedgerProduct.getQuantity()); productionPlan.setSource("销售"); productionPlan.setStatus(0); productionPlan.setRequiredDate(salesLedger.getDeliveryDate());//需求日期=交货日期 productionPlan.setPromisedDeliveryDate(salesLedger.getDeliveryDate());//承诺日期=交货日期 productionPlanMapper.insert(productionPlan); } src/main/java/com/ruoyi/technology/controller/TechnologyRoutingOperationController.java
@@ -7,6 +7,7 @@ import com.ruoyi.technology.bean.vo.TechnologyRoutingOperationVo; import com.ruoyi.technology.pojo.TechnologyRoutingOperation; import com.ruoyi.technology.service.TechnologyRoutingOperationService; import io.swagger.annotations.ApiOperation; import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.Operation; import lombok.RequiredArgsConstructor; @@ -57,4 +58,10 @@ public R remove(@PathVariable("id") Long id) { return R.ok(technologyRoutingOperationService.removeTechnologyRoutingOperation(id)); } @PostMapping ("/sort") @Operation(summary = "排序工艺路线工序") public R sort(@RequestBody TechnologyRoutingOperation technologyRoutingOperation) { return R.ok(technologyRoutingOperationService.sort(technologyRoutingOperation)); } } src/main/java/com/ruoyi/technology/service/TechnologyRoutingOperationService.java
@@ -21,4 +21,6 @@ boolean saveTechnologyRoutingOperation(TechnologyRoutingOperation technologyRoutingOperation); boolean removeTechnologyRoutingOperation(Long id); int sort(TechnologyRoutingOperation technologyRoutingOperation); } src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingOperationParamServiceImpl.java
@@ -3,6 +3,7 @@ import cn.hutool.core.bean.BeanUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; @@ -90,23 +91,25 @@ ); } int successCount = 0; for (TechnologyOperationParam operationParam : operationParamList) { boolean exists = technologyRoutingOperationParamMapper.selectCount( Wrappers.<TechnologyRoutingOperationParam>lambdaQuery() .eq(TechnologyRoutingOperationParam::getTechnologyRoutingOperationId, routingOperation.getId()) .eq(TechnologyRoutingOperationParam::getTechnologyOperationParamId, operationParam.getId()) ) > 0; if (!replaceExisting && exists) { continue; if (CollectionUtils.isNotEmpty(operationParamList)) { for (TechnologyOperationParam operationParam : operationParamList) { boolean exists = technologyRoutingOperationParamMapper.selectCount( Wrappers.<TechnologyRoutingOperationParam>lambdaQuery() .eq(TechnologyRoutingOperationParam::getTechnologyRoutingOperationId, routingOperation.getId()) .eq(TechnologyRoutingOperationParam::getTechnologyOperationParamId, operationParam.getId()) ) > 0; if (!replaceExisting && exists) { continue; } TechnologyRoutingOperationParam snapshot = new TechnologyRoutingOperationParam(); snapshot.setTechnologyRoutingOperationId(routingOperation.getId()); snapshot.setTechnologyOperationParamId(operationParam.getId()); snapshot.setTechnologyOperationId(operationParam.getTechnologyOperationId()); snapshot.setStandardValue(operationParam.getStandardValue()); fillFromOperationParam(snapshot, routingOperation); technologyRoutingOperationParamMapper.insert(snapshot); successCount++; } TechnologyRoutingOperationParam snapshot = new TechnologyRoutingOperationParam(); snapshot.setTechnologyRoutingOperationId(routingOperation.getId()); snapshot.setTechnologyOperationParamId(operationParam.getId()); snapshot.setTechnologyOperationId(operationParam.getTechnologyOperationId()); snapshot.setStandardValue(operationParam.getStandardValue()); fillFromOperationParam(snapshot, routingOperation); technologyRoutingOperationParamMapper.insert(snapshot); successCount++; } return successCount; } src/main/java/com/ruoyi/technology/service/impl/TechnologyRoutingOperationServiceImpl.java
@@ -76,6 +76,40 @@ return removed; } @Override public int sort(TechnologyRoutingOperation technologyRoutingOperation) { //查询被改动的这条数据 TechnologyRoutingOperation oldtechnologyRoutingOperation = technologyRoutingOperationMapper.selectById(technologyRoutingOperation.getId()); //查询该工艺路线的所有工序并按照顺序排序 List<TechnologyRoutingOperation> technologyRouteOperations = technologyRoutingOperationMapper.selectList(Wrappers.<TechnologyRoutingOperation>lambdaQuery() .eq(TechnologyRoutingOperation::getTechnologyRoutingId, oldtechnologyRoutingOperation.getTechnologyRoutingId()) .orderByAsc(TechnologyRoutingOperation::getDragSort)); // 获取目标位置(移动到第几个之后) Integer targetPosition = technologyRoutingOperation.getDragSort(); if (targetPosition != null && targetPosition >= 0) { // 移动元素到新的位置 technologyRouteOperations.remove(oldtechnologyRoutingOperation); technologyRouteOperations.add(targetPosition-1, oldtechnologyRoutingOperation); // 更新所有受影响的排序字段 for (int i = 0; i < technologyRouteOperations.size(); i++) { TechnologyRoutingOperation item = technologyRouteOperations.get(i); if (!item.getId().equals(oldtechnologyRoutingOperation.getId())) { // 检查是否需要更新排序值 if (item.getDragSort() != i+1) { item.setDragSort(i+1); technologyRoutingOperationMapper.updateById(item); } } else { // 更新原记录的新排序位置 oldtechnologyRoutingOperation.setDragSort(targetPosition); technologyRoutingOperationMapper.updateById(oldtechnologyRoutingOperation); } } return 1; } return 0; } private Integer nextDragSort(Long technologyRoutingId) { TechnologyRoutingOperation lastOperation = technologyRoutingOperationMapper.selectOne( Wrappers.<TechnologyRoutingOperation>lambdaQuery() src/main/resources/mapper/production/ProductionOrderMapper.xml
@@ -5,7 +5,6 @@ <!-- 通用查询映射结果 --> <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductionOrder"> <id column="id" property="id" /> <result column="sales_ledger_id" property="salesLedgerId" /> <result column="production_plan_ids" property="productionPlanIds" /> <result column="product_model_id" property="productModelId" /> <result column="nps_no" property="npsNo" /> @@ -16,7 +15,6 @@ <result column="complete_quantity" property="completeQuantity" /> <result column="start_time" property="startTime" /> <result column="end_time" property="endTime" /> <result column="sales_ledger_product_id" property="salesLedgerProductId" /> <result column="create_user" property="createUser" /> <result column="dept_id" property="deptId" /> <result column="plan_complete_time" property="planCompleteTime" /> @@ -33,7 +31,6 @@ <sql id="ProductionOrderVoColumns"> po.id, po.sales_ledger_id, po.production_plan_ids, po.product_model_id, po.nps_no, @@ -44,13 +41,10 @@ po.complete_quantity, po.start_time, po.end_time, po.sales_ledger_product_id, po.create_user, po.dept_id, po.plan_complete_time, po.status, sl.sales_contract_no as salesContractNo, sl.customer_name as customerName, p.product_name as productName, pm.model as model, tr.process_route_code as processRouteCode, @@ -59,7 +53,6 @@ <sql id="ProductionOrderVoFrom"> from production_order po left join sales_ledger sl on po.sales_ledger_id = sl.id left join product_model pm on po.product_model_id = pm.id left join product p on pm.product_id = p.id left join technology_routing tr on po.technology_routing_id = tr.id @@ -72,17 +65,11 @@ <if test="c.id != null"> and po.id = #{c.id} </if> <if test="c.salesLedgerId != null"> and po.sales_ledger_id = #{c.salesLedgerId} </if> <if test="c.productModelId != null"> and po.product_model_id = #{c.productModelId} </if> <if test="c.technologyRoutingId != null"> and po.technology_routing_id = #{c.technologyRoutingId} </if> <if test="c.salesLedgerProductId != null"> and po.sales_ledger_product_id = #{c.salesLedgerProductId} </if> <if test="c.status != null"> and po.status = #{c.status} src/main/resources/mapper/production/ProductionPlanMapper.xml
@@ -16,7 +16,6 @@ <result column="qty_required" property="qtyRequired"/> <result column="issued" property="issued"/> <result column="source" property="source"/> <result column="is_audit" property="isAudit"/> <result column="promised_delivery_date" property="promisedDeliveryDate"/> </resultMap> @@ -26,10 +25,36 @@ pm.model, p.id as productId, p.product_name AS productName, pm.unit pm.unit, sl.sales_contract_no, sl.customer_name, sl.project_name FROM production_plan pp left join product_model pm on pp.product_model_id = pm.id left join product p on pm.product_id = p.id left join sales_ledger sl on pp.sales_ledger_id = sl.id <where> <if test="c != null"> <if test="c.id != null"> and pp.id = #{c.id} </if> <if test="c.productName != null and c.productName != ''"> and p.product_name like concat('%', #{c.productName}, '%') </if> <if test="c.model != null and c.model != ''"> and pm.model like concat('%', #{c.model}, '%') </if> <if test="c.status != null"> and pp.status = #{c.status} </if> <if test="c.mpsNo != null and c.mpsNo != ''"> and pp.mps_no like concat('%', #{c.mpsNo}, '%') </if> <if test="c.requiredDateStart != null and c.requiredDateEnd != null"> and pp.required_date between #{c.requiredDateStart} and #{c.requiredDateEnd} </if> </if> </where> ORDER BY COALESCE(pp.id) DESC </select> @@ -59,4 +84,23 @@ left join product p on pm.product_id = p.id WHERE pp.id = #{productionPlanId} </select> <select id="getSource" resultType="com.ruoyi.production.bean.vo.ProductionPlanVo"> SELECT pp.*, pm.model, p.product_name AS productName, pm.unit, sl.sales_contract_no, sl.customer_name, sl.project_name FROM production_plan pp LEFT JOIN product_model pm ON pp.product_model_id = pm.id LEFT JOIN product p ON pm.product_id = p.id left join sales_ledger sl on pp.sales_ledger_id = sl.id WHERE pp.id IN <foreach collection="ids" item="id" open="(" separator="," close=")"> #{id} </foreach> ORDER BY pp.id ASC </select> </mapper> src/main/resources/mapper/technology/TechnologyRoutingMapper.xml
@@ -39,6 +39,9 @@ <if test="c.productModelId != null"> and tr.product_model_id = #{c.productModelId} </if> <if test="c.model != null and c.model != ''"> and pm.model like concat('%', #{c.model}, '%') </if> <if test="c.bomId != null"> and tr.bom_id = #{c.bomId} </if>