yys
1.产品导入新增excel错误提示
2.bom导入新增excel错误提示
3.仓储物流增加库位字段
4.修改发货出库-新增库位
5.修改采购入库审核-新增库位
6.生产入库-新增库位,审核
已添加2个文件
已修改43个文件
530 ■■■■ 文件已修改
src/main/java/com/ruoyi/approve/controller/ApproveNodeController.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/IApproveNodeService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/controller/ProductController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/dto/ProductModelExcelCopyErrorDto.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/pojo/ProductModel.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/IProductModelService.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/impl/ReturnManagementServiceImpl.java 14 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProductBomController.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/BomImportErrorDto.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductOrder.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductionProductInput.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/ProductBomService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductBomServiceImpl.java 45 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductStructureRecordServiceImpl.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductionProductInputServiceImpl.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/ShipmentApprovalController.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/dto/ShippingInfoDto.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/ShippingInfoDetail.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/ShippingInfoDetailServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/controller/StockInRecordController.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/controller/StockInventoryController.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/dto/StockInRecordDto.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/execl/StockInventoryExportData.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/pojo/StockInRecord.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/pojo/StockInventory.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/pojo/StockUninventory.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/StockInRecordService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/StockInventoryService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java 38 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/ShippingInfoMapper.xml 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/stock/StockInRecordMapper.xml 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/stock/StockInventoryMapper.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/stock/StockUninventoryMapper.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/approve/controller/ApproveNodeController.java
@@ -1,8 +1,12 @@
package com.ruoyi.approve.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.approve.pojo.ApproveNode;
import com.ruoyi.approve.service.IApproveNodeService;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.purchase.pojo.PurchaseLedger;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
@@ -10,6 +14,7 @@
import org.springframework.web.bind.annotation.*;
import java.io.IOException;
import java.util.List;
@Api(tags = "审批记录")
@RestController
@@ -42,6 +47,15 @@
        return AjaxResult.success();
    }
    @ApiOperation(value = "采购审核填写库位入库")
    @PostMapping("/purchaseApprove")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult purchaseApprove(@RequestBody List<SalesLedgerProduct> salesLedgerProducts) {
        approveNodeService.purchaseApprove(salesLedgerProducts);
        return AjaxResult.success();
    }
    /**
     * åˆå§‹åŒ–审批节点
     * @param id
src/main/java/com/ruoyi/approve/service/IApproveNodeService.java
@@ -2,6 +2,7 @@
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.approve.pojo.ApproveNode;
import com.ruoyi.sales.pojo.SalesLedgerProduct;
import java.io.IOException;
import java.util.List;
@@ -18,4 +19,6 @@
    void updateApproveNode(ApproveNode approveNode) throws IOException;
    void delApproveNodeByApproveId(String id);
    void purchaseApprove(List<SalesLedgerProduct> salesLedgerProducts);
}
src/main/java/com/ruoyi/approve/service/impl/ApproveNodeServiceImpl.java
@@ -202,9 +202,6 @@
                        // è´¨æ£€
                        if (salesLedgerProduct.getIsChecked()) {
                            purchaseLedgerServiceImpl.addQualityInspect(purchaseLedger, salesLedgerProduct);
                        }else {
                            //直接入库
                            stockUtils.addStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockInQualifiedRecordTypeEnum.PURCHASE_STOCK_IN.getCode(), purchaseLedger.getId());
                        }
                    }
                } else if (status.equals(3)) {
@@ -306,6 +303,18 @@
        }
    }
    @Override
    public void purchaseApprove(List<SalesLedgerProduct> salesLedgerProducts) {
        for (SalesLedgerProduct salesLedgerProduct : salesLedgerProducts) {
            stockUtils.addStock(salesLedgerProduct.getProductModelId(),
                    salesLedgerProduct.getQuantity(),
                    StockInQualifiedRecordTypeEnum.PURCHASE_STOCK_IN.getCode(),
                    salesLedgerProduct.getId(),
                    salesLedgerProduct.getStockLocation(),
                    2);
        }
    }
    //审批类型获取(与前端页面对应)
    private String approveProcessType(Integer approveType){
        switch (approveType){
src/main/java/com/ruoyi/basic/controller/ProductController.java
@@ -139,8 +139,8 @@
     */
    @Log(title = "导入产品",businessType = BusinessType.IMPORT)
    @PostMapping("import")
    public AjaxResult importProduct(MultipartFile file) {
        return AjaxResult.success(productModelService.importProduct(file));
    public void importProduct(HttpServletResponse response,MultipartFile file) {
        productModelService.importProduct(file,response);
    }
    /**
src/main/java/com/ruoyi/basic/dto/ProductModelExcelCopyErrorDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,13 @@
package com.ruoyi.basic.dto;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import lombok.Data;
import org.apache.poi.ss.usermodel.IndexedColors;
@Data
public class ProductModelExcelCopyErrorDto extends ProductModelExcelCopyDto{
    @Excel(name = "错误信息",sort = 1,color = IndexedColors.RED)
    private String errorMsg;
}
src/main/java/com/ruoyi/basic/pojo/ProductModel.java
@@ -16,6 +16,10 @@
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "错误信息")
    @TableField(exist = false)
    private String errorMsg;
    @TableField(exist = false)
    private List<CommonFile> SalesLedgerFiles;
src/main/java/com/ruoyi/basic/service/IProductModelService.java
@@ -8,6 +8,7 @@
import com.ruoyi.basic.pojo.ProductModel;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@@ -34,5 +35,5 @@
     */
    IPage<ProductModel> modelListPage(Page page , ProductDto productDto);
    Boolean importProduct(MultipartFile file);
    void importProduct(MultipartFile file, HttpServletResponse response);
}
src/main/java/com/ruoyi/basic/service/impl/ProductModelServiceImpl.java
@@ -32,6 +32,7 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
@@ -130,46 +131,52 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean importProduct(MultipartFile file) {
    public void importProduct(MultipartFile file, HttpServletResponse response) {
        ExcelUtil<ProductModelExcelCopyDto> productModelExcelUtil = new ExcelUtil<>(ProductModelExcelCopyDto.class);
        List<ProductModelExcelCopyDto> productModelList = null;
        try {
            ExcelUtil<ProductModelExcelCopyDto> productModelExcelUtil = new ExcelUtil<>(ProductModelExcelCopyDto.class);
            List<ProductModelExcelCopyDto> productModelList = productModelExcelUtil.importExcel(file.getInputStream());
            if(CollectionUtils.isNotEmpty(productModelList)){
                // 2. æŒ‰äº§å“åç§°,图纸编号分组
                Map<Map.Entry<String, String>, List<ProductModelExcelCopyDto>> groupedByProductNameAndDrawingNumber =
                        productModelList.stream()
                                .collect(Collectors.groupingBy(
                                        dto -> new AbstractMap.SimpleEntry<>(
                                                dto.getProductName(),
                                                dto.getModel()
                                        )
                                ));
                // 2. éåŽ†åˆ†ç»„ç»“æžœå¤„ç†æ•°æ®
                for (Map.Entry<Map.Entry<String, String>, List<ProductModelExcelCopyDto>> entry : groupedByProductNameAndDrawingNumber.entrySet()) {
                    Map.Entry<String, String> groupKey = entry.getKey();
                    String productName = groupKey.getKey(); // äº§å“åç§°
                    String drawingNumber = groupKey.getValue(); // å›¾çº¸ç¼–号
                    List<ProductModelExcelCopyDto> dtoList = entry.getValue();
                    // ç©ºåˆ—表跳过,避免后续NPE
                    if (CollectionUtils.isEmpty(dtoList)) {
                        continue;
                    }
                    ProductModelExcelCopyDto firstDto = dtoList.get(0);
                    String model = firstDto.getModel();
                    // 3. æŸ¥è¯¢/新增产品(按产品名称+图纸编号,更精准)
                    Product product = getOrCreateProduct(productName, drawingNumber);
                    // 4. æ‰¹é‡å¤„理产品型号(按图纸编号+型号)
                    processProductModel(dtoList, product.getId(), model, drawingNumber);
                }
            }
            return true;
            productModelList = productModelExcelUtil.importExcel(file.getInputStream());
        }catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("文件解析失败");
        }
        return false;
        if(CollectionUtils.isNotEmpty(productModelList)){
            // 2. æŒ‰äº§å“åç§°,图纸编号分组
            Map<Map.Entry<String, String>, List<ProductModelExcelCopyDto>> groupedByProductNameAndDrawingNumber =
                    productModelList.stream()
                            .collect(Collectors.groupingBy(
                                    dto -> new AbstractMap.SimpleEntry<>(
                                            dto.getProductName(),
                                            dto.getModel()
                                    )
                            ));
            List<ProductModelExcelCopyErrorDto> errorList = new ArrayList<>();
            // 2. éåŽ†åˆ†ç»„ç»“æžœå¤„ç†æ•°æ®
            for (Map.Entry<Map.Entry<String, String>, List<ProductModelExcelCopyDto>> entry : groupedByProductNameAndDrawingNumber.entrySet()) {
                Map.Entry<String, String> groupKey = entry.getKey();
                String productName = groupKey.getKey(); // äº§å“åç§°
                String drawingNumber = groupKey.getValue(); // å›¾çº¸ç¼–号
                List<ProductModelExcelCopyDto> dtoList = entry.getValue();
                // ç©ºåˆ—表跳过,避免后续NPE
                if (CollectionUtils.isEmpty(dtoList)) {
                    continue;
                }
                ProductModelExcelCopyDto firstDto = dtoList.get(0);
                String model = firstDto.getModel();
                // 3. æŸ¥è¯¢/新增产品(按产品名称+图纸编号,更精准)
                Product product = getOrCreateProduct(productName, drawingNumber);
                // 4. æ‰¹é‡å¤„理产品型号(按图纸编号+型号)
                processProductModel(dtoList, product.getId(), model, drawingNumber,errorList);
            }
            if(CollectionUtils.isNotEmpty(errorList)){
                // 5. æ‰¹é‡å¤„理错误数据
                ExcelUtil<ProductModelExcelCopyErrorDto> errorExcelUtil = new ExcelUtil<>(ProductModelExcelCopyErrorDto.class);
                errorExcelUtil.exportExcel(response,errorList, "错误数据");
            }
        }
    }
    /**
@@ -196,11 +203,14 @@
     * æŠ½å–通用方法:处理产品型号(新增/更新)
     */
    private void processProductModel(List<ProductModelExcelCopyDto> dtoList,
                                     Long productId, String model, String drawingNumber) {
                                     Long productId,
                                     String model,
                                     String drawingNumber,
                                     List<ProductModelExcelCopyErrorDto> errorList) {
        // æŸ¥è¯¢æ‰€æœ‰å·¥è‰ºè·¯çº¿
        List<ProductProcess> productRoutes = productProcessMapper.selectList(new QueryWrapper<ProductProcess>());
        if(CollectionUtils.isEmpty(productRoutes)){
            throw new ServiceException("请先创建产品工艺路线");
            productRoutes = new ArrayList<>();
        }
        for (ProductModelExcelCopyDto dto : dtoList) {
            // æŸ¥è¯¢æ¡ä»¶ï¼šåž‹å·+图纸编号(更精准,符合分组逻辑)
src/main/java/com/ruoyi/procurementrecord/service/impl/ReturnManagementServiceImpl.java
@@ -139,13 +139,13 @@
        for (ReturnSaleProductDto returnSaleProduct : list) {
            bigDecimal = bigDecimal.add(returnSaleProduct.getPrice());
            // æ˜¯å¦æœ‰è´¨é‡é—®é¢˜
            if (returnSaleProduct.getIsQuality() == 1) {
                // æœ‰è´¨é‡é—®é¢˜ï¼Œå…¥ä¸åˆæ ¼åº“
                stockUtils.addUnStock(returnSaleProduct.getProductModelId(),returnSaleProduct.getNum(), StockInUnQualifiedRecordTypeEnum.RETURN_UNSTOCK_IN.getCode(),returnSaleProduct.getId());
            }else{
                // æ— è´¨é‡é—®é¢˜ï¼Œå…¥åˆæ ¼åº“
                stockUtils.addStock(returnSaleProduct.getProductModelId(),returnSaleProduct.getNum(), StockInQualifiedRecordTypeEnum.RETURN_HE_IN.getCode(),returnSaleProduct.getId());
            }
//            if (returnSaleProduct.getIsQuality() == 1) {
//                // æœ‰è´¨é‡é—®é¢˜ï¼Œå…¥ä¸åˆæ ¼åº“
//                stockUtils.addUnStock(returnSaleProduct.getProductModelId(),returnSaleProduct.getNum(), StockInUnQualifiedRecordTypeEnum.RETURN_UNSTOCK_IN.getCode(),returnSaleProduct.getId());
//            }else{
//                // æ— è´¨é‡é—®é¢˜ï¼Œå…¥åˆæ ¼åº“
//                stockUtils.addStock(returnSaleProduct.getProductModelId(),returnSaleProduct.getNum(), StockInQualifiedRecordTypeEnum.RETURN_HE_IN.getCode(),returnSaleProduct.getId());
//            }
            returnSaleProduct.setStatus(1);
            returnSaleProductService.updateById(returnSaleProduct);
        }
src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
@@ -49,6 +49,7 @@
        stockUninventoryDto.setRecordType(String.valueOf(recordType));
        stockUninventoryDto.setQualitity(quantity);
        stockUninventoryDto.setProductModelId(productModelId);
        stockUninventoryDto.setStockLocation("不合格库位");
        stockUninventoryService.addStockUninventory(stockUninventoryDto);
    }
@@ -65,6 +66,7 @@
        stockUninventoryDto.setRecordType(String.valueOf(recordType));
        stockUninventoryDto.setQualitity(quantity);
        stockUninventoryDto.setProductModelId(productModelId);
        stockUninventoryDto.setStockLocation("不合格库位");
        stockUninventoryService.subtractStockUninventory(stockUninventoryDto);
    }
@@ -75,13 +77,19 @@
     * @param recordType
     * @param recordId
     */
    public void addStock(Long productModelId, BigDecimal quantity, String recordType,Long recordId) {
    public void addStock(Long productModelId,
                         BigDecimal quantity,
                         String recordType,
                         Long recordId,
                         String stockLocation,
                         Integer isProduction) {
        StockInventoryDto stockInventoryDto = new StockInventoryDto();
        stockInventoryDto.setRecordId(recordId);
        stockInventoryDto.setRecordType(String.valueOf(recordType));
        stockInventoryDto.setQualitity(quantity);
        stockInventoryDto.setProductModelId(productModelId);
        stockInventoryService.addstockInventory(stockInventoryDto);
        stockInventoryDto.setStockLocation(stockLocation);
        stockInventoryService.addstockInventory(stockInventoryDto,isProduction);
    }
    /**
@@ -91,12 +99,13 @@
     * @param recordType
     * @param recordId
     */
    public void substractStock(Long productModelId, BigDecimal quantity, String recordType,Long recordId) {
    public void substractStock(Long productModelId, BigDecimal quantity, String recordType,Long recordId,String stockLocation) {
        StockInventoryDto stockInventoryDto = new StockInventoryDto();
        stockInventoryDto.setRecordId(recordId);
        stockInventoryDto.setRecordType(String.valueOf(recordType));
        stockInventoryDto.setQualitity(quantity);
        stockInventoryDto.setProductModelId(productModelId);
        stockInventoryDto.setStockLocation(stockLocation);
        stockInventoryService.subtractStockInventory(stockInventoryDto);
    }
src/main/java/com/ruoyi/production/controller/ProductBomController.java
@@ -102,12 +102,11 @@
    }
    @PostMapping("uploadBom")
    @PreAuthorize("@ss.hasPermi('product:bom:import')")
    @PostMapping("/uploadBom")
    @Log(title = "根据Excel导入BOM", businessType = BusinessType.IMPORT)
    @ApiOperation("根据Excel导入BOM")
    public AjaxResult uploadBom(@RequestParam("file") MultipartFile file) {
        return productBomService.uploadBom(file);
    public void uploadBom(@RequestParam("file") MultipartFile file,HttpServletResponse response) {
        productBomService.uploadBom(file,response);
    }
    @PostMapping("exportBom")
src/main/java/com/ruoyi/production/dto/BomImportErrorDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
package com.ruoyi.production.dto;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.apache.poi.ss.usermodel.IndexedColors;
@Data
public class BomImportErrorDto extends BomImportDto{
    @ApiModelProperty(value = "错误信息")
    @Excel(name = "错误信息",sort = 1,color = IndexedColors.RED)
    private String errorMsg;
}
src/main/java/com/ruoyi/production/pojo/ProductOrder.java
@@ -64,6 +64,20 @@
    private String npsNo;
    /**
     * ä¸é€šè¿‡åŽŸå› 
     */
    @ApiModelProperty(value = "不通过原因")
    @Excel(name = "不通过原因")
    private String reason;
    /**
     * å®žé™…入库数量
     */
    @ApiModelProperty(value = "实际入库数量")
    @Excel(name = "实际入库数量")
    private BigDecimal actualStockInNum;
    /**
     * ç§Ÿæˆ·id
     */
    @ApiModelProperty(value = "租户id")
src/main/java/com/ruoyi/production/pojo/ProductionProductInput.java
@@ -36,4 +36,8 @@
    @ApiModelProperty(value = "租户ID")
    @TableField(fill = FieldFill.INSERT)
    private Long tenantId;
    @ApiModelProperty(value = "库位")
    @TableField(exist = false)
    private String stockLocation;
}
src/main/java/com/ruoyi/production/service/ProductBomService.java
@@ -24,7 +24,7 @@
    AjaxResult add(ProductBom productBom);
    AjaxResult uploadBom(MultipartFile file);
    void uploadBom(MultipartFile file,HttpServletResponse response);
    void exportBom(HttpServletResponse response, Integer bomId);
}
src/main/java/com/ruoyi/production/service/impl/ProductBomServiceImpl.java
@@ -14,6 +14,7 @@
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.production.dto.BomImportDto;
import com.ruoyi.production.dto.BomImportErrorDto;
import com.ruoyi.production.dto.ProductBomDto;
import com.ruoyi.production.dto.ProductStructureDto;
import com.ruoyi.production.mapper.ProductBomMapper;
@@ -23,6 +24,7 @@
import com.ruoyi.production.service.ProductBomService;
import com.ruoyi.production.service.ProductProcessService;
import com.ruoyi.production.service.ProductStructureService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -103,14 +105,17 @@
     * @param children å½“前父项的子项列表
     * @return ä¿å­˜åŽçš„父项产品ID
     */
    private void saveBomRecursive(List<BomImportDto> children,ProductBom bom,ProductModel rootModel,Map<String, Long> processMap) {
    private void saveBomRecursive(List<BomImportDto> children,
                                  ProductBom bom,ProductModel rootModel,
                                  Map<String, Long> processMap,
                                  List<BomImportErrorDto> errorList ) {
        // 1. èŽ·å–children中子项产品编号为空的数据
        List<BomImportDto> parentChildren = children
                .stream()
                .filter(child -> StringUtils.isEmpty(child.getChildCode()))
                .collect(Collectors.toList());
        if(CollectionUtils.isEmpty(parentChildren)){
            throw new ServiceException("请选择父项产品编号");
            return;
        }
        BomImportDto parentId = parentChildren.get(0); // çˆ¶çº§æ•°æ®
        ProductStructure rootNode = new ProductStructure();
@@ -129,7 +134,13 @@
            }
            //  èŽ·å–å­é¡¹æ¨¡åž‹ä¿¡æ¯
            ProductModel childModel = findModel(child.getChildName(), child.getChildSpec());
            if(childModel.getId() == null){
                BomImportErrorDto errorDto = new BomImportErrorDto();
                BeanUtils.copyProperties(child, errorDto);
                errorDto.setErrorMsg(childModel.getErrorMsg());
                errorList.add(errorDto);
                continue;
            }
            //  æ’入结构表
            ProductStructure node = new ProductStructure();
            node.setBomId(bom.getId());
@@ -147,16 +158,16 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult uploadBom(MultipartFile file) {
    public void uploadBom(MultipartFile file,HttpServletResponse response) {
        ExcelUtil<BomImportDto> util = new ExcelUtil<>(BomImportDto.class);
        List<BomImportDto> list;
        try {
            list = util.importExcel(file.getInputStream());
        } catch (Exception e) {
            return AjaxResult.error("Excel解析失败");
            throw new ServiceException("Excel解析失败");
        }
        if (list == null || list.isEmpty()) return AjaxResult.error("数据为空");
        if (list == null || list.isEmpty()) throw new ServiceException("文件为空");
        //  å¤„理工序
        list.forEach(dto -> {
@@ -172,11 +183,20 @@
        Map<String, List<BomImportDto>> parentMap = list.stream()
                .filter(bom -> StringUtils.isNotBlank(bom.getParentCode()))
                .collect(Collectors.groupingBy(BomImportDto::getParentCode));
        List<BomImportErrorDto> errorList = new ArrayList<>();
        // 2. éåŽ†æ‰€æœ‰çˆ¶é¡¹ï¼Œé€’å½’ä¿å­˜
        for (Map.Entry<String, List<BomImportDto>> entry : parentMap.entrySet()) {
            //  åˆ›å»º BOM æ•°æ®
            BomImportDto first = entry.getValue().get(0);
            ProductModel rootModel = findModel(first.getParentName(), first.getParentSpec());
            if(rootModel.getId() == null){
                BomImportErrorDto error = new BomImportErrorDto();
                BeanUtils.copyProperties(first, error);
                error.setErrorMsg(rootModel.getErrorMsg());
                errorList.add(error);
                continue;
            }
            ProductBom bom = new ProductBom();
            bom.setProductModelId(rootModel.getId());
            bom.setVersion("1.0");
@@ -185,9 +205,13 @@
            productBomMapper.updateById(bom);
            // å¤„理bom子表数据
            List<BomImportDto> children = entry.getValue();
            saveBomRecursive(children,bom,rootModel,processMap);
            saveBomRecursive(children,bom,rootModel,processMap,errorList);
        }
        return AjaxResult.success("BOM导入成功");
        // åˆ¤æ–­æ˜¯å¦æœ‰é”™è¯¯æ•°æ®ï¼Œæœ‰å°±å¯¼å‡º
        if(CollectionUtils.isNotEmpty(errorList)){
            ExcelUtil<BomImportErrorDto> utils = new ExcelUtil<>(BomImportErrorDto.class);
            utils.exportExcel(response,errorList, "BOM错误数据");
        }
    }
@@ -276,7 +300,10 @@
        ProductModel model = productModelService.getOne(new LambdaQueryWrapper<ProductModel>()
//                .eq(ProductModel::getProductId, product.getId())
                .eq(ProductModel::getModel, spec).last("limit 1"));
        if (model == null) throw new ServiceException("图纸编号未维护:" + name + "[" + spec + "]");
        if (model == null){
            model = new ProductModel();
            model.setErrorMsg("图纸编号未维护:" + "[" + spec + "]");
        }
        return model;
    }
src/main/java/com/ruoyi/production/service/impl/ProductStructureRecordServiceImpl.java
@@ -56,7 +56,11 @@
        }
        for (ProductionProductInput productionProductInput : productionProductInputs) {
            productionProductInputMapper.insert(productionProductInput);
            stockUtils.substractStock(productionProductInput.getProductModelId(), productionProductInput.getQuantity(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(), productionProductInput.getProductOrderId());
            stockUtils.substractStock(productionProductInput.getProductModelId(),
                    productionProductInput.getQuantity(),
                    StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(),
                    productionProductInput.getProductOrderId(),
                    productionProductInput.getStockLocation());
            // æ‰£é™¤ç‰©æ–™æ¸…单
            ProductStructureRecord productStructureRecord = productStructureRecordMapper.selectById(productionProductInput.getProductStructureRecordId());
            if(productStructureRecord != null){
src/main/java/com/ruoyi/production/service/impl/ProductionProductInputServiceImpl.java
@@ -49,7 +49,11 @@
            productionProductInput1.setReturnQuantity(qty.add(qty1));
            productionProductInputMapper.updateById(productionProductInput1);
            // é€€æ–™å…¥åº“
            stockUtils.addStock(input.getProductModelId(), input.getReturnQuantity(), StockInQualifiedRecordTypeEnum.RETURN_MATERIAL_IN.getCode(), input.getId());
            stockUtils.addStock(input.getProductModelId(),
                    input.getReturnQuantity(), StockInQualifiedRecordTypeEnum.RETURN_MATERIAL_IN.getCode(),
                    input.getId(),
                    input.getStockLocation(),
                    2);
            // å¢žåŠ ç‰©æ–™æ¸…å•
            ProductStructureRecord productStructureRecord = productStructureRecordMapper.selectById(input.getProductStructureRecordId());
            if(productStructureRecord != null){
src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -264,7 +264,12 @@
                productOrder.setEndTime(LocalDateTime.now());//结束时间
                productOrder.setStatus("已完成");
                // ç”Ÿäº§å®Œæˆå…¥åº“
                stockUtils.addStock(productProcessRouteItem.getProductModelId(), productOrder.getCompleteQuantity(), StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(), productionProductMain.getId());
                stockUtils.addStock(productProcessRouteItem.getProductModelId(),
                        productOrder.getCompleteQuantity(),
                        StockInQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_IN.getCode(),
                        productOrder.getId(),
                        "",
                        1);
            }
//            if (productWorkOrderList.stream().filter(item -> item.getStatus() == 3).count() == productProcessRouteItems.size() - 1) {
//
src/main/java/com/ruoyi/quality/service/impl/QualityInspectServiceImpl.java
@@ -94,7 +94,10 @@
            qualityUnqualifiedMapper.insert(qualityUnqualified);
        } else {
            //合格直接入库
            stockUtils.addStock(qualityInspect.getProductModelId(), qualityInspect.getQuantity(), StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode(), qualityInspect.getId());
            stockUtils.addStock(qualityInspect.getProductModelId(),
                    qualityInspect.getQuantity(),
                    StockInQualifiedRecordTypeEnum.QUALITYINSPECT_STOCK_IN.getCode(),
                    qualityInspect.getId(),"质检合格入库",2);
        }
        qualityInspect.setInspectState(1);//已提交
        return qualityInspectMapper.updateById(qualityInspect);
src/main/java/com/ruoyi/quality/service/impl/QualityUnqualifiedServiceImpl.java
@@ -131,7 +131,11 @@
                    break;
                case "让步放行":
                    //调用提交合格的接口
                    stockUtils.addStock(qualityInspect.getProductModelId(), unqualified.getQuantity(), StockInQualifiedRecordTypeEnum.DEFECTIVE_PASS.getCode(), unqualified.getId());
                    stockUtils.addStock(qualityInspect.getProductModelId(),
                            unqualified.getQuantity(),
                            StockInQualifiedRecordTypeEnum.DEFECTIVE_PASS.getCode(),
                            unqualified.getId(),
                            "让步放行",2);
                    qualityInspect.setCheckResult("合格");
                    qualityInspectService.submit(qualityInspect);
                    break;
src/main/java/com/ruoyi/sales/controller/ShipmentApprovalController.java
@@ -44,57 +44,6 @@
        return AjaxResult.success(listPage);
    }
    @PostMapping("/update")
    @ApiOperation("发货审批,更新发货审批状态")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult update(@RequestBody ShipmentApproval req) {
        //  æŸ¥è¯¢å‘货审批
        ShipmentApproval shipmentApproval = shipmentApprovalMapper.selectById(req.getId());
        if (shipmentApproval == null) {
            return AjaxResult.error("发货审批不存在");
        }
        //  æ›´æ–°å‘货审批状态
        shipmentApproval.setApproveStatus(req.getApproveStatus());
        boolean update = shipmentApprovalService.updateById(shipmentApproval);
        if (!update) {
            //  äº‹åŠ¡å›žæ»š
            throw new ServiceException("发货审批更新失败");
        }
        //  æŸ¥è¯¢å…³è”的销售台账产品
        SalesLedgerProduct salesLedgerProduct = salesLedgerProductService.getById(shipmentApproval.getSalesLedgerProductId());
        if (salesLedgerProduct == null) {
            //  æŠ›å¼‚常事务回滚
            throw new ServiceException("销售台账不存在,审批回滚");
        }
        //  åŒæ­¥æ›´æ–°é”€å”®å°è´¦äº§å“çš„审批状态
        salesLedgerProduct.setApproveStatus(req.getApproveStatus());
        salesLedgerProductService.updateById(salesLedgerProduct);
        //  å®¡æ‰¹é€šè¿‡
        if (req.getApproveStatus() == 3) {
//            // æŸ¥è¯¢é‡‡è´­å…¥åº“记录
//            LambdaQueryWrapper<ProcurementRecordStorage> lambdaQueryWrapper = new LambdaQueryWrapper<ProcurementRecordStorage>()
//                    .eq(ProcurementRecordStorage::getSalesLedgerProductId, req.getSalesLedgerProductId());
//            ProcurementRecordStorage procurementRecordStorage = procurementRecordStorageService.getOne(lambdaQueryWrapper);
//
//            if (procurementRecordStorage == null) {
//                // ä¿è¯å‰é¢çš„修改全部回滚
//                throw new ServiceException("采购记录不存在,审批回滚");
//            }
            //出库
            stockUtils.addStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId());
        }
        return AjaxResult.success();
    }
    /**
     * å¯¼å‡ºå‘货信息管理
     */
src/main/java/com/ruoyi/sales/dto/ShippingInfoDto.java
@@ -17,6 +17,10 @@
@Data
public class ShippingInfoDto extends ShippingInfo {
    @ApiModelProperty(value = "库位")
    @TableField(exist = false)
    private String stockLocation;
    /**
     * å®¡æ‰¹äººid列表
     */
@@ -45,4 +49,8 @@
     */
    private BigDecimal returnTotal = BigDecimal.ZERO;
    private String productCategory;
    private String specificationModel;
}
src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
@@ -23,8 +23,13 @@
@TableName("sales_ledger_product")
@Data
public class SalesLedgerProduct implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "库位")
    @TableField(exist = false)
    private String stockLocation;
    /**
     * äº§å“ä¿¡æ¯ä¸»é”®
     */
src/main/java/com/ruoyi/sales/pojo/ShippingInfoDetail.java
@@ -31,6 +31,9 @@
@ApiModel(value = "ShippingInfoDetail对象", description = "发货明细表")
public class ShippingInfoDetail implements Serializable {
    @ApiModelProperty(value = "库位")
    private String stockLocation;
    private static final long serialVersionUID = 1L;
    /**
src/main/java/com/ruoyi/sales/service/impl/ShippingInfoDetailServiceImpl.java
@@ -84,6 +84,7 @@
        }
        // æ‰£åº“å­˜
        shippingInfo.setShippingTotal(shippingInfoDetail.getShippingNum());
        shippingInfo.setStockLocation(shippingInfoDetail.getStockLocation());
        shippingInfoService.deductStock(shippingInfo);
        // è¿ç§»æ–‡ä»¶
        if(CollectionUtils.isNotEmpty(shippingInfoDetail.getTempFileIds())){
src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
@@ -166,7 +166,10 @@
        }
        //扣减库存
        SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(byId.getSalesLedgerProductId());
        stockUtils.substractStock(salesLedgerProduct.getProductModelId(), req.getShippingTotal(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId());
        stockUtils.substractStock(salesLedgerProduct.getProductModelId(),
                req.getShippingTotal(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(),
                req.getId(),
                req.getStockLocation());
        byId.setExpressNumber(req.getExpressNumber());
        byId.setExpressCompany(req.getExpressCompany());
        byId.setStatus(req.getStatus());
src/main/java/com/ruoyi/stock/controller/StockInRecordController.java
@@ -2,14 +2,18 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.stock.dto.StockInRecordDto;
import com.ruoyi.stock.dto.StockInventoryDto;
import com.ruoyi.stock.service.StockInRecordService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
@@ -42,6 +46,14 @@
        return AjaxResult.success(stockInRecordService.batchDelete(ids));
    }
    @ApiOperation("生产入库审核")
    @PostMapping("/productionApprove")
    @Transactional(rollbackFor = Exception.class)
    public R productionApprove(@RequestBody StockInRecordDto stockInRecordDto) {
        return R.ok(stockInRecordService.productionApprove(stockInRecordDto));
    }
    @PostMapping("/exportStockInRecord")
    @ApiOperation("导出入库记录")
    public void exportStockInRecord(HttpServletResponse response, StockInRecordDto stockInRecordDto) {
src/main/java/com/ruoyi/stock/controller/StockInventoryController.java
@@ -14,6 +14,7 @@
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
@@ -49,7 +50,7 @@
    public R addstockInventory(@RequestBody StockInventoryDto stockInventoryDto) {
        stockInventoryDto.setRecordType(String.valueOf(StockInQualifiedRecordTypeEnum.CUSTOMIZATION_STOCK_IN.getCode()));
        stockInventoryDto.setRecordId(0L);
        return R.ok(stockInventoryService.addstockInventory(stockInventoryDto));
        return R.ok(stockInventoryService.addstockInventory(stockInventoryDto,2));
    }
@@ -61,9 +62,9 @@
        return R.ok(stockInventoryService.subtractStockInventory(stockInventoryDto));
    }
    @PostMapping("importStockInventory")
    @ApiOperation("导入库存")
    @Transactional(rollbackFor = Exception.class)
    public R importStockInventory(MultipartFile file) {
        return stockInventoryService.importStockInventory(file);
    }
src/main/java/com/ruoyi/stock/dto/StockInRecordDto.java
@@ -3,6 +3,8 @@
import com.ruoyi.stock.pojo.StockInRecord;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class StockInRecordDto extends StockInRecord {
@@ -31,4 +33,16 @@
    //现存量
    private String currentStock;
    /**
     * ä¸é€šè¿‡åŽŸå› 
     */
    private String reason;
    /**
     * å®žé™…入库数量
     */
    private BigDecimal actualStockInNum;
}
src/main/java/com/ruoyi/stock/execl/StockInventoryExportData.java
@@ -30,6 +30,9 @@
    @Excel(name = "备注")
    private String remark;
    @Excel(name = "库位")
    private String stockLocation;
//
//    @Excel(name = "最新更新时间")
//    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
src/main/java/com/ruoyi/stock/pojo/StockInRecord.java
@@ -28,6 +28,9 @@
    @ApiModelProperty(value = "入库数量")
    private BigDecimal stockInNum;
    @ApiModelProperty(value = "待审核入库数量(生产)")
    private BigDecimal waitAuditNum;
    @ApiModelProperty(value = "记录类型  æžšä¸¾")
    private String recordType;
@@ -62,4 +65,10 @@
    @ApiModelProperty(value = "修改用户")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Integer updateUser;
    @ApiModelProperty(value = "库位")
    private String stockLocation;
    @ApiModelProperty(value = "状态(1 - å¾…审核  2-已入库)")
    private Integer status;
}
src/main/java/com/ruoyi/stock/pojo/StockInventory.java
@@ -63,4 +63,7 @@
    @ApiModelProperty("备注")
    private String remark;
    @ApiModelProperty(value = "库位")
    private String stockLocation;
}
src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java
@@ -71,4 +71,7 @@
    @ApiModelProperty(value = "类型  0合格入库 1不合格入库")
    private String type;
    @ApiModelProperty(value = "库位")
    private String stockLocation;
}
src/main/java/com/ruoyi/stock/pojo/StockUninventory.java
@@ -59,4 +59,7 @@
    @ApiModelProperty("被订单锁定数量")
    private BigDecimal lockedQuantity;
    @ApiModelProperty(value = "库位")
    private String stockLocation;
}
src/main/java/com/ruoyi/stock/service/StockInRecordService.java
@@ -19,4 +19,6 @@
    int batchDelete(List<Long> ids);
    void exportStockInRecord(HttpServletResponse response, StockInRecordDto stockInRecordDto);
    Object productionApprove(StockInRecordDto stockInRecordDto);
}
src/main/java/com/ruoyi/stock/service/StockInventoryService.java
@@ -23,7 +23,7 @@
    IPage<StockInventoryDto> pagestockInventory(Page page, StockInventoryDto stockInventoryDto);
    Boolean addstockInventory(StockInventoryDto stockInventoryDto);
    Boolean addstockInventory(StockInventoryDto stockInventoryDto,Integer isProduction);
    Boolean subtractStockInventory(StockInventoryDto stockInventoryDto);
src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
@@ -1,7 +1,9 @@
package com.ruoyi.stock.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
@@ -9,8 +11,11 @@
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.EnumUtil;
import com.ruoyi.common.utils.OrderUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.production.mapper.ProductOrderMapper;
import com.ruoyi.production.pojo.ProductOrder;
import com.ruoyi.stock.dto.StockInRecordDto;
import com.ruoyi.stock.dto.StockInventoryDto;
import com.ruoyi.stock.dto.StockUninventoryDto;
@@ -36,6 +41,8 @@
    private StockInRecordMapper stockInRecordMapper;
    private StockInventoryMapper stockInventoryMapper;
    private StockUninventoryMapper stockUninventoryMapper;
    private ProductOrderMapper productOrderMapper;
    @Override
    public IPage<StockInRecordDto> listPage(Page page, StockInRecordDto stockInRecordDto) {
@@ -90,6 +97,7 @@
                    StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
                    stockUninventoryDto.setProductModelId(stockUninventory.getProductModelId());
                    stockUninventoryDto.setQualitity(stockInRecord.getStockInNum());
                    stockUninventoryDto.setStockLocation(stockInRecord.getStockLocation());
                    stockUninventoryMapper.updateSubtractStockUnInventory(stockUninventoryDto);
                }
            }
@@ -110,4 +118,41 @@
        ExcelUtil<StockInRecordExportData> util = new ExcelUtil<>(StockInRecordExportData.class);
        util.exportExcel(response,list, "入库记录信息");
    }
    @Override
    public Object productionApprove(StockInRecordDto stockInRecordDto) {
        //再进行新增库存数量库存
        //先查询库存表中的产品是否存在,不存在新增,存在更新
        StockInventory oldStockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>()
                .lambda()
                .eq(StockInventory::getProductModelId, stockInRecordDto.getProductModelId())
                .eq(StockInventory::getStockLocation, stockInRecordDto.getStockLocation()));
        StockInventory newStockInventory = new StockInventory();
        newStockInventory.setProductModelId(stockInRecordDto.getProductModelId());
        newStockInventory.setQualitity(stockInRecordDto.getActualStockInNum());
        newStockInventory.setVersion(1);
        newStockInventory.setRemark(stockInRecordDto.getRemark());
        newStockInventory.setStockLocation(stockInRecordDto.getStockLocation());
        if (ObjectUtils.isEmpty(oldStockInventory)) {
            stockInventoryMapper.insert(newStockInventory);
        }else {
            StockInventoryDto oldStockInventoryDto = new StockInventoryDto();
            BeanUtils.copyProperties(oldStockInventory, oldStockInventoryDto);
            stockInventoryMapper.updateAddStockInventory(oldStockInventoryDto);
        }
        stockInRecordDto.setStatus(2);
        stockInRecordDto.setStockInNum(stockInRecordDto.getActualStockInNum() == null ? stockInRecordDto.getWaitAuditNum() : stockInRecordDto.getActualStockInNum());
        stockInRecordMapper.updateById(stockInRecordDto);
        ProductOrder productOrder = productOrderMapper.selectById(stockInRecordDto.getRecordId());
        if(productOrder != null){
            if(StringUtils.isNotEmpty(stockInRecordDto.getReason())){
                productOrder.setReason(stockInRecordDto.getReason());
            }
            if(stockInRecordDto.getActualStockInNum() != null){
                productOrder.setActualStockInNum(stockInRecordDto.getActualStockInNum());
            }
            productOrderMapper.updateById(productOrder);
        }
        return true;
    }
}
src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
@@ -52,20 +52,39 @@
    }
    //入库调用
    /**
     *
     * @param stockInventoryDto
     * @param isProduction  æ˜¯å¦ç”Ÿäº§å…¥åº“ 1-是 2-否(生产需要审核才能入库)
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean addstockInventory(StockInventoryDto stockInventoryDto) {
    public Boolean addstockInventory(StockInventoryDto stockInventoryDto,Integer isProduction) {
        //新增入库记录再添加库存
        StockInRecordDto stockInRecordDto = new StockInRecordDto();
        stockInRecordDto.setRecordId(stockInventoryDto.getRecordId());
        stockInRecordDto.setRecordType(stockInventoryDto.getRecordType());
        stockInRecordDto.setStockInNum(stockInventoryDto.getQualitity());
        if(isProduction == 1){
            stockInRecordDto.setWaitAuditNum(stockInventoryDto.getQualitity());
        }else{
            stockInRecordDto.setStockInNum(stockInventoryDto.getQualitity());
        }
        stockInRecordDto.setProductModelId(stockInventoryDto.getProductModelId());
        stockInRecordDto.setType("0");
        stockInRecordDto.setStockLocation(stockInventoryDto.getStockLocation());
        stockInRecordDto.setStatus(isProduction);
        stockInRecordService.add(stockInRecordDto);
        if(isProduction == 1){
            return false;
        }
        //再进行新增库存数量库存
        //先查询库存表中的产品是否存在,不存在新增,存在更新
        StockInventory oldStockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>().lambda().eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId()));
        StockInventory oldStockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>()
                .lambda()
                .eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId())
                .eq(StockInventory::getStockLocation, stockInventoryDto.getStockLocation()));
        if (ObjectUtils.isEmpty(oldStockInventory)) {
            StockInventory newStockInventory = new StockInventory();
            newStockInventory.setProductModelId(stockInventoryDto.getProductModelId());
@@ -74,6 +93,7 @@
            newStockInventory.setRemark(stockInventoryDto.getRemark());
            newStockInventory.setLockedQuantity(stockInventoryDto.getLockedQuantity());
            newStockInventory.setWarnNum(stockInventoryDto.getWarnNum());
            newStockInventory.setStockLocation(stockInventoryDto.getStockLocation());
            stockInventoryMapper.insert(newStockInventory);
        }else {
             stockInventoryMapper.updateAddStockInventory(stockInventoryDto);
@@ -92,10 +112,14 @@
        stockOutRecordDto.setStockOutNum(stockInventoryDto.getQualitity());
        stockOutRecordDto.setProductModelId(stockInventoryDto.getProductModelId());
        stockOutRecordDto.setType("0");
        stockOutRecordDto.setStockLocation(stockInventoryDto.getStockLocation());
        stockOutRecordService.add(stockOutRecordDto);
        StockInventory oldStockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>().lambda().eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId()));
        StockInventory oldStockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>()
                .lambda()
                .eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId())
                .eq(StockInventory::getStockLocation, stockInventoryDto.getStockLocation()));
        if (ObjectUtils.isEmpty(oldStockInventory)) {
            throw new RuntimeException("产品库存不存在");
            throw new RuntimeException("库位【" + stockInventoryDto.getStockLocation() + "】产品库存不存在");
        }
        BigDecimal lockedQty = oldStockInventory.getLockedQuantity();
        if (lockedQty == null) {
@@ -104,7 +128,6 @@
        if (stockInventoryDto.getQualitity().compareTo(oldStockInventory.getQualitity().subtract(lockedQty)) > 0) {
            throw new RuntimeException("库存不足无法出库");
        }
        stockInventoryMapper.updateSubtractStockInventory(stockInventoryDto);
        return true;
    }
@@ -137,7 +160,8 @@
                        }
                        stockInventoryDto.setLockedQuantity(dto.getLockedQuantity());
                        stockInventoryDto.setProductModelId(item.getProductModelId());
                        this.addstockInventory(stockInventoryDto);
                        stockInventoryDto.setStockLocation(dto.getStockLocation());
                        this.addstockInventory(stockInventoryDto,2);
                        matched = true;
                        break; // æ‰¾åˆ°åŒ¹é…é¡¹åŽè·³å‡ºå¾ªçޝ
                    }
src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java
@@ -93,6 +93,7 @@
                    StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
                    stockUninventoryDto.setProductModelId(stockUninventory.getProductModelId());
                    stockUninventoryDto.setQualitity(stockOutRecord.getStockOutNum());
                    stockUninventoryDto.setStockLocation(stockOutRecord.getStockLocation());
                    stockUninventoryMapper.updateAddStockUnInventory(stockUninventoryDto);
                }
            }
src/main/java/com/ruoyi/stock/service/impl/StockUninventoryServiceImpl.java
@@ -54,16 +54,21 @@
        stockInRecordDto.setStockInNum(stockUninventoryDto.getQualitity());
        stockInRecordDto.setProductModelId(stockUninventoryDto.getProductModelId());
        stockInRecordDto.setType("1");
        stockInRecordDto.setStockLocation(stockUninventoryDto.getStockLocation());
        stockInRecordService.add(stockInRecordDto);
        //再进行新增库存数量库存
        //先查询库存表中的产品是否存在,不存在新增,存在更新
        StockUninventory oldStockUnInventory = stockUninventoryMapper.selectOne(new QueryWrapper<StockUninventory>().lambda().eq(StockUninventory::getProductModelId, stockUninventoryDto.getProductModelId()));
        StockUninventory oldStockUnInventory = stockUninventoryMapper.selectOne(new QueryWrapper<StockUninventory>()
                .lambda()
                .eq(StockUninventory::getProductModelId, stockUninventoryDto.getProductModelId())
                .eq(StockUninventory::getStockLocation, stockUninventoryDto.getStockLocation()));
        if (ObjectUtils.isEmpty(oldStockUnInventory)) {
            StockUninventory newStockUnInventory = new StockUninventory();
            newStockUnInventory.setProductModelId(stockUninventoryDto.getProductModelId());
            newStockUnInventory.setQualitity(stockUninventoryDto.getQualitity());
            newStockUnInventory.setVersion(1);
            newStockUnInventory.setRemark(stockUninventoryDto.getRemark());
            newStockUnInventory.setStockLocation(stockUninventoryDto.getStockLocation());
            stockUninventoryMapper.insert(newStockUnInventory);
        }else {
            stockUninventoryMapper.updateAddStockUnInventory(stockUninventoryDto);
@@ -81,11 +86,15 @@
        stockOutRecordDto.setRecordType(stockUninventoryDto.getRecordType());
        stockOutRecordDto.setStockOutNum(stockUninventoryDto.getQualitity());
        stockOutRecordDto.setProductModelId(stockUninventoryDto.getProductModelId());
        stockOutRecordDto.setStockLocation(stockUninventoryDto.getStockLocation());
        stockOutRecordDto.setType("1");
        stockOutRecordService.add(stockOutRecordDto);
        StockUninventory oldStockInventory = stockUninventoryMapper.selectOne(new QueryWrapper<StockUninventory>().lambda().eq(StockUninventory::getProductModelId, stockUninventoryDto.getProductModelId()));
        StockUninventory oldStockInventory = stockUninventoryMapper.selectOne(new QueryWrapper<StockUninventory>()
                .lambda()
                .eq(StockUninventory::getProductModelId, stockUninventoryDto.getProductModelId())
                .eq(StockUninventory::getStockLocation, stockUninventoryDto.getStockLocation()));
        if (ObjectUtils.isEmpty(oldStockInventory)) {
            throw new RuntimeException("产品库存不存在");
            throw new RuntimeException("库位【" + stockUninventoryDto.getStockLocation() + "】产品库存不存在");
        }else {
            stockUninventoryMapper.updateSubtractStockUnInventory(stockUninventoryDto);
        }
src/main/resources/mapper/sales/ShippingInfoMapper.xml
@@ -21,7 +21,9 @@
        sl.sales_contract_no,
        sl.customer_name,
        s.shipping_total AS shipping_total,
        slp.id as salesLedgerProductId
        slp.id as salesLedgerProductId,
        slp.product_category,
        slp.specification_model
        FROM shipping_info s
        LEFT JOIN sales_ledger sl ON s.sales_ledger_id = sl.id
        LEFT JOIN sales_ledger_product slp ON s.sales_ledger_product_id = slp.id and slp.type = 1
src/main/resources/mapper/stock/StockInRecordMapper.xml
@@ -15,6 +15,9 @@
        LEFT JOIN sys_user as u on sir.create_user = u.user_id
        <where>
            pm.product_type = #{params.productType}
            <if test="params.status != null">
                and sir.status = #{params.status}
            </if>
            <if test="params.timeStr != null and params.timeStr != ''">
                and sir.create_time like concat('%',#{params.timeStr},'%')
            </if>
src/main/resources/mapper/stock/StockInventoryMapper.xml
@@ -63,6 +63,7 @@
        (si.qualitity - COALESCE(si.locked_quantity, 0)) as un_locked_quantity,
        pm.model,
        si.remark,
        si.stock_location,
        pm.unit,
        p.product_name
        from stock_inventory si
src/main/resources/mapper/stock/StockUninventoryMapper.xml
@@ -25,7 +25,7 @@
            </if>
            update_time = now()
        </set>
        where product_model_id = #{ew.productModelId} and qualitity >= #{ew.qualitity}
        where product_model_id = #{ew.productModelId} and stock_location = #{ew.stockLocation} and qualitity >= #{ew.qualitity}
    </update>
    <update id="updateAddStockUnInventory">
        update stock_uninventory
@@ -41,7 +41,7 @@
            </if>
            update_time = now()
        </set>
        where product_model_id = #{ew.productModelId}
        where product_model_id = #{ew.productModelId} and stock_location = #{ew.stockLocation}
    </update>
    <select id="pageStockUninventory" resultType="com.ruoyi.stock.dto.StockUninventoryDto">
        select su.id,