src/main/java/com/ruoyi/basic/controller/ProductController.java
@@ -17,8 +17,6 @@ import com.ruoyi.framework.web.domain.AjaxResult; import com.ruoyi.sales.pojo.SalesLedgerProduct; import com.ruoyi.sales.service.ISalesLedgerProductService; import com.ruoyi.sales.service.ISalesLedgerService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.AllArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; @@ -143,4 +141,14 @@ ExcelUtil<ProductModelExportDto> excelUtil = new ExcelUtil<>(ProductModelExportDto.class); excelUtil.importTemplateExcel(response, "产品规格导入模板"); } /** * 向下复制型号等 */ @Log(title = "向下复制型号等", businessType = BusinessType.INSERT) @PostMapping("/downCopy") public AjaxResult downCopy(@RequestBody ProductModelDto productModelDto) { return toAjax(productModelService.downCopy(productModelDto)); } } src/main/java/com/ruoyi/basic/dto/ProductModelDto.java
@@ -9,4 +9,7 @@ @Data public class ProductModelDto extends ProductModel { private List<ProductStructureDto> productStructureList; //复制的目标产品id private Long targetProductId; } src/main/java/com/ruoyi/basic/service/IProductModelService.java
@@ -35,4 +35,6 @@ IPage<ProductModel> modelListPage(Page page , ProductDto productDto); AjaxResult importProductModel(MultipartFile file, Integer productId); int downCopy(ProductModelDto productModelDto); } src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java
@@ -155,4 +155,51 @@ throw new ServiceException("导入失败"); } } @Override @Transactional(rollbackFor = Exception.class) public int downCopy(ProductModelDto productModelDto) { if (productModelDto == null || productModelDto.getProductId() == null || productModelDto.getTargetProductId() == null) { throw new ServiceException("源产品ID和目标产品ID不能为空"); } Long sourceProductId = productModelDto.getProductId(); Long targetProductId = productModelDto.getTargetProductId(); if (sourceProductId.equals(targetProductId)) { throw new ServiceException("源产品和目标产品不能相同"); } Product sourceProduct = productMapper.selectById(sourceProductId); if (sourceProduct == null) { throw new ServiceException("源产品不存在"); } Product targetProduct = productMapper.selectById(targetProductId); if (targetProduct == null) { throw new ServiceException("目标产品不存在"); } List<ProductModel> sourceModels = productModelMapper.selectList( new LambdaQueryWrapper<ProductModel>() .eq(ProductModel::getProductId, sourceProductId) .orderByAsc(ProductModel::getId) ); if (CollectionUtils.isEmpty(sourceModels)) { throw new ServiceException("源产品下没有可复制的型号"); } List<ProductModel> copyList = new ArrayList<>(); for (ProductModel sourceModel : sourceModels) { ProductModel copy = new ProductModel(); BeanUtils.copyProperties(sourceModel, copy); copy.setId(null); copy.setProductId(targetProductId); copy.setTenantId(null); copyList.add(copy); } saveBatch(copyList); return copyList.size(); } } src/main/java/com/ruoyi/production/dto/ProductionProductMainDto.java
@@ -88,5 +88,5 @@ private String batchNo; @ApiModelProperty(value = "产品结构投入数量") private BigDecimal bomInputQty; private BigDecimal inputWeight; } src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -1,5 +1,8 @@ package com.ruoyi.production.service.impl; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; @@ -52,6 +55,8 @@ private static final String PROCESS_VOLTAGE_SORT = "电压分选"; private static final String PROCESS_OPTICAL_INSPECTION = "光检外观"; private static final String PROCESS_PACKAGING = "包装"; private static final String INPUT_WEIGHT_PARAMETER = "投入重量"; private static final String INPUT_WEIGHT_FIELD = "inputWeight"; private static final Object PRODUCT_MAIN_NO_LOCK = new Object(); private IQualityInspectService qualityInspectService; @@ -98,7 +103,10 @@ BigDecimal reportQty = dto.getQuantity(); BigDecimal scrapQty = dto.getScrapQty() == null ? BigDecimal.ZERO : dto.getScrapQty(); BigDecimal bomInputQty = dto.getBomInputQty(); BigDecimal bomInputQty = dto.getInputWeight(); if (bomInputQty == null) { bomInputQty = resolveInputWeight(dto.getOtherData()); } if (reportQty == null || reportQty.compareTo(BigDecimal.ZERO) <= 0) { throw new ServiceException("报工数量必须大于0"); } @@ -345,7 +353,7 @@ ProductionProductInput productionProductInput = new ProductionProductInput(); productionProductInput.setProductModelId(productStructureDto.getProductModelId()); productionProductInput.setQuantity(needQty); productionProductInput.setQuantity(needQty == null ? BigDecimal.ZERO : needQty); productionProductInput.setProductMainId(productionProductMain.getId()); productionProductInputMapper.insert(productionProductInput); @@ -761,4 +769,87 @@ return productionProductMainDtos; } private BigDecimal resolveInputWeight(String otherData) { if (StringUtils.isBlank(otherData)) { return null; } Object parsed; try { parsed = JSON.parse(otherData); } catch (Exception ex) { throw new ServiceException("报工参数格式错误,无法解析投入重量"); } String inputWeight = StringUtils.trim(findParameterValue(parsed, INPUT_WEIGHT_PARAMETER)); if (StringUtils.isBlank(inputWeight)) { inputWeight = StringUtils.trim(findFieldValue(parsed, INPUT_WEIGHT_FIELD)); } if (StringUtils.isBlank(inputWeight)) { return null; } try { return new BigDecimal(inputWeight); } catch (NumberFormatException ex) { throw new ServiceException("报工参数中的投入重量格式错误"); } } private String findParameterValue(Object node, String parameterItem) { if (node instanceof JSONArray) { JSONArray array = (JSONArray) node; for (Object item : array) { String value = findParameterValue(item, parameterItem); if (StringUtils.isNotBlank(value)) { return value; } } return null; } if (node instanceof JSONObject) { JSONObject object = (JSONObject) node; if (parameterItem.equals(StringUtils.trim(object.getString("parameterItem")))) { String value = StringUtils.trim(object.getString("value")); if (StringUtils.isNotBlank(value)) { return value; } } for (Object value : object.values()) { String matched = findParameterValue(value, parameterItem); if (StringUtils.isNotBlank(matched)) { return matched; } } } return null; } private String findFieldValue(Object node, String fieldName) { if (node instanceof JSONArray) { JSONArray array = (JSONArray) node; for (Object item : array) { String value = findFieldValue(item, fieldName); if (StringUtils.isNotBlank(value)) { return value; } } return null; } if (node instanceof JSONObject) { JSONObject object = (JSONObject) node; Object fieldValue = object.get(fieldName); if (fieldValue != null) { String value = StringUtils.trim(String.valueOf(fieldValue)); if (StringUtils.isNotBlank(value)) { return value; } } for (Object value : object.values()) { String matched = findFieldValue(value, fieldName); if (StringUtils.isNotBlank(matched)) { return matched; } } } return null; } } src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
@@ -298,7 +298,7 @@ throw new RuntimeException("产品库存不存在"); } BigDecimal remainingQty = stockInventoryDto.getQualitity(); BigDecimal remainingQty = stockInventoryDto.getQualitity() == null ? BigDecimal.ZERO : stockInventoryDto.getQualitity(); for (StockInventory stockInventory : stockInventories) { BigDecimal lockedQty = defaultDecimal(stockInventory.getLockedQuantity()); BigDecimal availableQty = defaultDecimal(stockInventory.getQualitity()).subtract(lockedQty); src/main/resources/mapper/production/SalesLedgerProductionAccountingMapper.xml
@@ -89,7 +89,7 @@ </if> </where> GROUP BY slpa.scheduling_user_name GROUP BY slpa.scheduling_user_id, slpa.scheduling_user_name </select>