fix: 1.已发货的销售台账对应的出入库记录做限制不能删除;2.销售台账入库操作后,点击删除,对应的销售入库记录未一并删除;3.销售台账入库状态新增部分入库
已添加1个文件
已修改19个文件
287 ■■■■■ 文件已修改
doc/河南鹤壁天沐钢化玻璃厂.sql 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/controller/ShipmentApprovalController.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/dto/SalesProductStockDto.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/SalesLedger.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java 66 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/pojo/StockInRecord.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/SalesLedgerMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/stock/StockInventoryMapper.xml 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mybatis/mybatis-config.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
doc/ºÓÄϺױÚÌìãå¸Ö»¯²£Á§³§.sql
@@ -109,3 +109,17 @@
                                                                    `user_id` int NULL DEFAULT NULL COMMENT '用户id',
                                                                    PRIMARY KEY (`id`)
    );
ALTER TABLE `product-inventory-management-hbtmblc`.`stock_in_record`
    ADD COLUMN `sales_ledger_id`         bigint NULL COMMENT '销售台账ID' AFTER `weighing_date`,
    ADD COLUMN `sales_ledger_product_id` bigint NULL COMMENT '销售台账产品ID' AFTER `sales_ledger_id`;
ALTER TABLE `product-inventory-management-hbtmblc`.`sales_ledger_product`
    ADD COLUMN `product_stock_status` int NULL COMMENT '产品入库状态' AFTER `floor_code`;
ALTER TABLE `product-inventory-management-hbtmblc`.`stock_out_record`
    MODIFY COLUMN `outbound_batches` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '出库批次' AFTER `id`,
    MODIFY COLUMN `stock_out_num` decimal(16, 4) NULL DEFAULT NULL COMMENT '出库数量' AFTER `outbound_batches`,
    MODIFY COLUMN `record_id` int NULL DEFAULT NULL COMMENT '出库来源id' AFTER `stock_out_num`,
    ADD COLUMN `sales_ledger_id`         bigint NULL COMMENT '销售订单ID' AFTER `type`,
    ADD COLUMN `sales_ledger_product_id` bigint NULL COMMENT '销售订单产品ID' AFTER `sales_ledger_id`;
src/main/java/com/ruoyi/common/enums/StockInQualifiedRecordTypeEnum.java
@@ -12,7 +12,7 @@
    QUALITYINSPECT_STOCK_IN("6", "质检-合格入库"),
    DEFECTIVE_PASS("11", "不合格-让步放行"),
    RETURN_HE_IN("14", "销售退货-合格入库"),
    SALE_STOCK_IN("15", "销售-合格入库");
    SALE_STOCK_IN("15", "销售订单-合格入库");
    private final String code;
src/main/java/com/ruoyi/procurementrecord/utils/StockUtils.java
@@ -35,6 +35,7 @@
    /**
     * ä¸åˆæ ¼å…¥åº“
     *
     * @param productModelId
     * @param quantity
     * @param recordType
@@ -51,6 +52,7 @@
    /**
     * ä¸åˆæ ¼å‡ºåº“
     *
     * @param productModelId
     * @param quantity
     * @param recordType
@@ -67,22 +69,39 @@
    /**
     * åˆæ ¼å…¥åº“
     *
     * @param productModelId
     * @param quantity
     * @param recordType
     * @param recordId
     */
    public void addStock(Long productModelId, BigDecimal quantity, String recordType,Long recordId) {
        addStock(null, null, productModelId, quantity, recordType, recordId);
    }
    /**
     * åˆæ ¼å…¥åº“
     *
     * @param productModelId
     * @param quantity
     * @param recordType
     * @param recordId
     */
    public void addStock(Long salesLedgerId, Long salesLedgerProductId, Long productModelId, BigDecimal quantity, String recordType, Long recordId) {
        StockInventoryDto stockInventoryDto = new StockInventoryDto();
        stockInventoryDto.setRecordId(recordId);
        stockInventoryDto.setRecordType(String.valueOf(recordType));
        stockInventoryDto.setQualitity(quantity);
        stockInventoryDto.setProductModelId(productModelId);
        stockInventoryDto.setSalesLedgerId(salesLedgerId);
        stockInventoryDto.setSalesLedgerProductId(salesLedgerProductId);
        stockInventoryService.addstockInventory(stockInventoryDto);
    }
    /**
     * åˆæ ¼å‡ºåº“
     *
     * @param productModelId
     * @param quantity
     * @param recordType
@@ -97,6 +116,25 @@
        stockInventoryService.subtractStockInventory(stockInventoryDto);
    }
    /**
     * åˆæ ¼å‡ºåº“
     *
     * @param productModelId
     * @param quantity
     * @param recordType
     * @param recordId
     */
    public void substractStock(Long salesId, Long salseProductId, Long productModelId, BigDecimal quantity, String recordType, Long recordId) {
        StockInventoryDto stockInventoryDto = new StockInventoryDto();
        stockInventoryDto.setRecordId(recordId);
        stockInventoryDto.setRecordType(String.valueOf(recordType));
        stockInventoryDto.setQualitity(quantity);
        stockInventoryDto.setProductModelId(productModelId);
        stockInventoryDto.setSalesLedgerId(salesId);
        stockInventoryDto.setSalesLedgerProductId(salseProductId);
        stockInventoryService.subtractStockInventory(stockInventoryDto);
    }
    //不合格库存删除
    public void deleteStockInRecord(Long recordId, String recordType) {
        StockInRecord one = stockInRecordService.getOne(new QueryWrapper<StockInRecord>()
@@ -106,6 +144,7 @@
            stockInRecordService.batchDelete(Collections.singletonList(one.getId()));
        }
    }
    public void deleteStockOutRecord(Long recordId, String recordType) {
        StockOutRecord one = stockOutRecordService.getOne(new QueryWrapper<StockOutRecord>()
                .lambda().eq(StockOutRecord::getRecordId, recordId)
src/main/java/com/ruoyi/sales/controller/SalesLedgerController.java
@@ -397,8 +397,8 @@
    @PostMapping("/salesStock")
    @ApiOperation("销售台账产品入库")
    public AjaxResult salesStock(@RequestBody SalesLedger salesLedger) {
        salesLedgerService.salesStock(salesLedger);
    public AjaxResult salesStock(@RequestBody SalesProductStockDto dto) {
        salesLedgerService.salesStock(dto);
        return AjaxResult.success();
    }
src/main/java/com/ruoyi/sales/controller/ShipmentApprovalController.java
@@ -87,12 +87,11 @@
            //出库
            stockUtils.addStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId());
            stockUtils.addStock(salesLedgerProduct.getSalesLedgerId(), salesLedgerProduct.getId(), salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId());
        }
        return AjaxResult.success();
    }
    /**
src/main/java/com/ruoyi/sales/dto/SalesProductStockDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
package com.ruoyi.sales.dto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.List;
/**
 * <br>
 * é”€å”®è®¢å•产品入库Dto
 * </br>
 *
 * @author deslrey
 * @version 1.0
 * @since 2026/4/17 13:53
 */
@Data
@ApiModel(value = "SalesProductStockDto", description = "销售订单产品入库Dto")
public class SalesProductStockDto {
    @ApiModelProperty("销售订单Id")
    private Long salesLedgerId;
    @ApiModelProperty("销售订单产品Id")
    private List<Long> salesLedgerProducts;
}
src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
@@ -149,9 +149,9 @@
    private Integer deliveryStatus;
    /**
     * å…¥åº“状态:0-未入库,1-已入库
     * å…¥åº“状态:0-未入库,1-部分入库,2-已入库
     */
    @ApiModelProperty("入库状态:0-未入库,1-已入库")
    @ApiModelProperty("入库状态:0-未入库,1-部分入库,2-已入库")
    private Integer stockStatus;
    @TableField(exist = false)
src/main/java/com/ruoyi/sales/pojo/SalesLedgerProduct.java
@@ -292,6 +292,12 @@
    @ApiModelProperty("楼层编号")
    private String floorCode;
    /**
     * äº§å“å…¥åº“状态   0-未入库,1-已入库
     */
    @ApiModelProperty("产品入库状态")
    private Integer productStockStatus;
    @TableField(exist = false)
    @ApiModelProperty("销售产品额外加工")
    private List<SalesLedgerProductProcess> salesProductProcessList;
src/main/java/com/ruoyi/sales/service/ISalesLedgerService.java
@@ -67,5 +67,5 @@
    List<SalesLabelDto> salesLabel(Long salesLedgerId);
    void salesStock(SalesLedger salesLedger);
    void salesStock(SalesProductStockDto dto);
}
src/main/java/com/ruoyi/sales/service/impl/SalesLedgerServiceImpl.java
@@ -49,7 +49,13 @@
import com.ruoyi.sales.service.ISalesLedgerProductProcessService;
import com.ruoyi.sales.service.ISalesLedgerService;
import com.ruoyi.stock.dto.StockInventoryDto;
import com.ruoyi.stock.mapper.StockInRecordMapper;
import com.ruoyi.stock.mapper.StockOutRecordMapper;
import com.ruoyi.stock.pojo.StockInRecord;
import com.ruoyi.stock.pojo.StockOutRecord;
import com.ruoyi.stock.service.StockInRecordService;
import com.ruoyi.stock.service.StockInventoryService;
import com.ruoyi.stock.service.StockOutRecordService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
@@ -130,6 +136,10 @@
    private final ISalesLedgerProcessRouteService salesLedgerProcessRouteService;
    private final StockInventoryService stockInventoryService;
    private final StockInRecordMapper stockInRecordMapper;
    private final StockOutRecordMapper stockOutRecordMapper;
    private final StockInRecordService stockInRecordService;
    private final StockOutRecordService stockOutRecordService;
    @Autowired
    private SysDeptMapper sysDeptMapper;
@@ -703,6 +713,25 @@
        if (CollectionUtils.isNotEmpty(shippingInfos)) {
            shippingInfoServiceImpl.delete(shippingInfos.stream().map(ShippingInfo::getId).collect(Collectors.toList()));
        }
        // åˆ é™¤å…³è”的入库/出库记录(走服务层删除,触发库存数量回退)
        List<Long> stockInRecordIds = stockInRecordMapper.selectList(new LambdaQueryWrapper<StockInRecord>()
                        .in(StockInRecord::getSalesLedgerId, idList)
                        .select(StockInRecord::getId))
                .stream()
                .map(StockInRecord::getId)
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(stockInRecordIds)) {
            stockInRecordService.batchDelete(stockInRecordIds);
        }
        List<Long> stockOutRecordIds = stockOutRecordMapper.selectList(new LambdaQueryWrapper<StockOutRecord>()
                        .in(StockOutRecord::getSalesLedgerId, idList)
                        .select(StockOutRecord::getId))
                .stream()
                .map(StockOutRecord::getId)
                .collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(stockOutRecordIds)) {
            stockOutRecordService.batchDelete(stockOutRecordIds);
        }
        // åˆ é™¤é™„件表
        commonFileService.deleteByBusinessIds(idList, FileNameType.SALE.getValue());
@@ -860,6 +889,7 @@
        if (!updateList.isEmpty()) {
            for (SalesLedgerProduct product : updateList) {
                product.setType(type.getCode());
                product.setProductStockStatus(0);
                salesLedgerProductMapper.updateById(product);
                //  æ¸…空销售产品绑定的加工
                salesLedgerProductProcessBindService.updateProductProcessBind(product.getSalesProductProcessList(), product.getId());
@@ -872,6 +902,7 @@
                salesLedgerProduct.setNoInvoiceNum(salesLedgerProduct.getQuantity());
                salesLedgerProduct.setNoInvoiceAmount(salesLedgerProduct.getTaxInclusiveTotalPrice());
                salesLedgerProduct.setPendingInvoiceTotal(salesLedgerProduct.getTaxInclusiveTotalPrice());
                salesLedgerProduct.setProductStockStatus(0);
                salesLedgerProductMapper.insert(salesLedgerProduct);
                //  ç»‘定产品额外加工
                //  æ¸…空销售产品绑定的加工
@@ -1509,23 +1540,27 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void salesStock(SalesLedger salesLedger) {
        if (salesLedger == null || salesLedger.getId() == null) {
    public void salesStock(SalesProductStockDto dto) {
        if (dto == null || dto.getSalesLedgerId() == null) {
            throw new NullPointerException("入库失败,请选择需要入库的销售订单");
        }
        //  æŸ¥è¯¢é”€å”®è®¢å•是否存在
        SalesLedger ledger = baseMapper.selectById(salesLedger.getId());
        SalesLedger ledger = baseMapper.selectById(dto.getSalesLedgerId());
        if (ledger == null) {
            throw new ServiceException("入库失败,销售订单不存在");
        }
        if (ledger.getStockStatus() == null) {
            throw new ServiceException("入库失败,销售订单入库状态异常");
        }
        if (ledger.getStockStatus() == 1) {
        if (ledger.getStockStatus() == 2) {
            throw new ServiceException("入库失败,该销售订单已入库,请勿重复入库");
        }
        List<Long> products = dto.getSalesLedgerProducts();
        if (products == null || products.isEmpty()) {
            throw new ServiceException("入库失败,入库产品不能为空");
        }
        //  æŸ¥è¯¢é”€å”®è®¢å•的产品
        List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(Wrappers.<SalesLedgerProduct>lambdaQuery().eq(SalesLedgerProduct::getSalesLedgerId, ledger.getId()));
        List<SalesLedgerProduct> salesLedgerProducts = salesLedgerProductMapper.selectList(Wrappers.<SalesLedgerProduct>lambdaQuery().in(SalesLedgerProduct::getId, products));
        if (salesLedgerProducts == null || salesLedgerProducts.isEmpty()) {
            throw new ServiceException("入库失败,未查询到该销售订单的销售产品");
        }
@@ -1533,15 +1568,20 @@
            if (product.getProductModelId() == null) {
                continue;
            }
            StockInventoryDto dto = new StockInventoryDto();
            dto.setRecordId(product.getId());
            dto.setRecordType(StockInQualifiedRecordTypeEnum.SALE_STOCK_IN.getCode());
            dto.setQualitity(product.getQuantity());
            dto.setProductModelId(product.getProductModelId());
            stockInventoryService.addstockInventory(dto);
            StockInventoryDto stockInventoryDto = new StockInventoryDto();
            stockInventoryDto.setRecordId(product.getId());
            stockInventoryDto.setRecordType(StockInQualifiedRecordTypeEnum.SALE_STOCK_IN.getCode());
            stockInventoryDto.setQualitity(product.getQuantity());
            stockInventoryDto.setProductModelId(product.getProductModelId());
            stockInventoryDto.setSalesLedgerId(ledger.getId());
            stockInventoryDto.setSalesLedgerProductId(product.getId());
            stockInventoryService.addstockInventory(stockInventoryDto);
        }
        //  æ›´æ–°é”€å”®è®¢å•入库状态
        ledger.setStockStatus(1);
        //  æŒ‰é”€å”®è®¢å•产品入库情况更新主单入库状态:1-部分入库,2-已入库
        List<SalesLedgerProduct> ledgerAllProducts = salesLedgerProductMapper.selectList(Wrappers.<SalesLedgerProduct>lambdaQuery().eq(SalesLedgerProduct::getSalesLedgerId, ledger.getId()));
        boolean hasStocked = CollectionUtils.isNotEmpty(ledgerAllProducts) && ledgerAllProducts.stream().anyMatch(item -> Objects.equals(item.getProductStockStatus(), 1));
        boolean allStocked = CollectionUtils.isNotEmpty(ledgerAllProducts) && ledgerAllProducts.stream().allMatch(item -> Objects.equals(item.getProductStockStatus(), 1));
        ledger.setStockStatus(allStocked ? 2 : (hasStocked ? 1 : 0));
        baseMapper.updateById(ledger);
    }
}
src/main/java/com/ruoyi/sales/service/impl/ShippingInfoServiceImpl.java
@@ -24,9 +24,11 @@
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -85,7 +87,7 @@
        if(!"已发货".equals(byId.getStatus())){
            SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(byId.getSalesLedgerProductId());
            if (salesLedgerProduct != null) {
                stockUtils.substractStock(salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId());
                stockUtils.substractStock(salesLedgerProduct.getSalesLedgerId(), salesLedgerProduct.getId(), salesLedgerProduct.getProductModelId(), salesLedgerProduct.getQuantity(), StockOutQualifiedRecordTypeEnum.SALE_SHIP_STOCK_OUT.getCode(), req.getId());
            }
        }
        byId.setExpressNumber(req.getExpressNumber());
src/main/java/com/ruoyi/stock/dto/StockInventoryDto.java
@@ -39,4 +39,8 @@
    private BigDecimal currentStock;
    private BigDecimal  unLockedQuantity;
    private Long salesLedgerId;
    private Long salesLedgerProductId;
}
src/main/java/com/ruoyi/stock/pojo/StockInRecord.java
@@ -62,4 +62,10 @@
    @ApiModelProperty(value = "修改用户")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Integer updateUser;
    @ApiModelProperty("销售订单ID")
    private Long salesLedgerId;
    @ApiModelProperty("销售订单产品ID")
    private Long salesLedgerProductId;
}
src/main/java/com/ruoyi/stock/pojo/StockOutRecord.java
@@ -71,4 +71,10 @@
    @ApiModelProperty(value = "类型  0合格入库 1不合格入库")
    private String type;
    @ApiModelProperty("销售订单ID")
    private Long salesLedgerId;
    @ApiModelProperty("销售订单产品ID")
    private Long salesLedgerProductId;
}
src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
@@ -2,6 +2,8 @@
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;
import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
@@ -11,6 +13,10 @@
import com.ruoyi.common.utils.OrderUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
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.stock.dto.StockInRecordDto;
import com.ruoyi.stock.dto.StockInventoryDto;
import com.ruoyi.stock.dto.StockUninventoryDto;
@@ -28,6 +34,7 @@
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Objects;
@Service
@AllArgsConstructor
@@ -36,6 +43,8 @@
    private StockInRecordMapper stockInRecordMapper;
    private StockInventoryMapper stockInventoryMapper;
    private StockUninventoryMapper stockUninventoryMapper;
    private SalesLedgerProductMapper salesLedgerProductMapper;
    private SalesLedgerMapper salesLedgerMapper;
    @Override
    public IPage<StockInRecordDto> listPage(Page page, StockInRecordDto stockInRecordDto) {
@@ -72,6 +81,7 @@
    public int batchDelete(List<Long> ids) {
        for (Long id : ids) {
            StockInRecord stockInRecord = stockInRecordMapper.selectById(id);
            validateCanDeleteBySalesLedger(stockInRecord);
            if (stockInRecord.getType().equals("0")) {
                StockInventory stockInventory = stockInventoryMapper.selectOne(new LambdaQueryWrapper<StockInventory>().eq(StockInventory::getProductModelId, stockInRecord.getProductModelId()));
                if (stockInventory == null) {
@@ -80,7 +90,12 @@
                    StockInventoryDto stockInRecordDto = new StockInventoryDto();
                    stockInRecordDto.setProductModelId(stockInventory.getProductModelId());
                    stockInRecordDto.setQualitity(stockInRecord.getStockInNum());
                    stockInventoryMapper.updateSubtractStockInventory(stockInRecordDto);
                    int affectRows = stockInventoryMapper.updateSubtractStockInventory(stockInRecordDto);
                    if (affectRows <= 0) {
                        throw new BaseException("库存回退失败,当前库存不足,无法删除该入库记录");
                    }
                    // é”€å”®å…¥åº“记录删除时,回退销售产品和销售订单入库状态
                    rollbackSalesStockStatus(stockInRecord);
                }
            }else if (stockInRecord.getType().equals("1")) {
                StockUninventory stockUninventory = stockUninventoryMapper.selectOne(new LambdaQueryWrapper<StockUninventory>().eq(StockUninventory::getProductModelId, stockInRecord.getProductModelId()));
@@ -90,13 +105,54 @@
                    StockUninventoryDto stockUninventoryDto = new StockUninventoryDto();
                    stockUninventoryDto.setProductModelId(stockUninventory.getProductModelId());
                    stockUninventoryDto.setQualitity(stockInRecord.getStockInNum());
                    stockUninventoryMapper.updateSubtractStockUnInventory(stockUninventoryDto);
                    int affectRows = stockUninventoryMapper.updateSubtractStockUnInventory(stockUninventoryDto);
                    if (affectRows <= 0) {
                        throw new BaseException("不合格库存回退失败,当前库存不足,无法删除该入库记录");
                    }
                }
            }
        }
        return stockInRecordMapper.deleteBatchIds(ids);
    }
    private void validateCanDeleteBySalesLedger(StockInRecord stockInRecord) {
        if (stockInRecord == null || stockInRecord.getSalesLedgerId() == null) {
            return;
        }
        SalesLedger salesLedger = salesLedgerMapper.selectById(stockInRecord.getSalesLedgerId());
        if (salesLedger != null && Objects.equals(salesLedger.getDeliveryStatus(), 5)) {
            throw new BaseException("销售订单已发货,对应入库记录不允许删除");
        }
    }
    private void rollbackSalesStockStatus(StockInRecord stockInRecord) {
        if (stockInRecord == null || stockInRecord.getSalesLedgerProductId() == null) {
            return;
        }
        SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(stockInRecord.getSalesLedgerProductId());
        if (salesLedgerProduct == null) {
            return;
        }
        salesLedgerProduct.setProductStockStatus(0);
        salesLedgerProductMapper.updateById(salesLedgerProduct);
        Long salesLedgerId = stockInRecord.getSalesLedgerId() != null ? stockInRecord.getSalesLedgerId() : salesLedgerProduct.getSalesLedgerId();
        if (salesLedgerId == null) {
            return;
        }
        SalesLedger salesLedger = salesLedgerMapper.selectById(salesLedgerId);
        if (salesLedger == null) {
            return;
        }
        List<SalesLedgerProduct> ledgerProducts = salesLedgerProductMapper.selectList(Wrappers.<SalesLedgerProduct>lambdaQuery().eq(SalesLedgerProduct::getSalesLedgerId, salesLedgerId));
        boolean hasStocked = CollectionUtils.isNotEmpty(ledgerProducts)
                && ledgerProducts.stream().anyMatch(item -> Objects.equals(item.getProductStockStatus(), 1));
        boolean allStocked = CollectionUtils.isNotEmpty(ledgerProducts)
                && ledgerProducts.stream().allMatch(item -> Objects.equals(item.getProductStockStatus(), 1));
        salesLedger.setStockStatus(allStocked ? 2 : (hasStocked ? 1 : 0));
        salesLedgerMapper.updateById(salesLedger);
    }
    @Override
    public void exportStockInRecord(HttpServletResponse response, StockInRecordDto stockInRecordDto) {
        List<StockInRecordExportData> list = stockInRecordMapper.listStockInRecordExportData(stockInRecordDto);
src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
@@ -7,6 +7,7 @@
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.sales.mapper.SalesLedgerProductMapper;
@@ -46,6 +47,7 @@
    private StockInRecordService stockInRecordService;
    private StockOutRecordService stockOutRecordService;
    private SalesLedgerProductMapper salesLedgerProductMapper;
    @Override
    public IPage<StockInventoryDto> pagestockInventory(Page page, StockInventoryDto stockInventoryDto) {
        return stockInventoryMapper.pagestockInventory(page, stockInventoryDto);
@@ -56,12 +58,22 @@
    @Transactional(rollbackFor = Exception.class)
    public Boolean addstockInventory(StockInventoryDto stockInventoryDto) {
        //新增入库记录再添加库存
        //  æ›´æ–°äº§å“å…¥åº“状态
        SalesLedgerProduct salesLedgerProduct = salesLedgerProductMapper.selectById(stockInventoryDto.getSalesLedgerProductId());
        if (salesLedgerProduct == null) {
            throw new ServiceException("入库失败,销售产品不存在");
        }
        salesLedgerProduct.setProductStockStatus(1);
        salesLedgerProductMapper.updateById(salesLedgerProduct);
        StockInRecordDto stockInRecordDto = new StockInRecordDto();
        stockInRecordDto.setRecordId(stockInventoryDto.getRecordId());
        stockInRecordDto.setRecordType(stockInventoryDto.getRecordType());
        stockInRecordDto.setStockInNum(stockInventoryDto.getQualitity());
        stockInRecordDto.setProductModelId(stockInventoryDto.getProductModelId());
        stockInRecordDto.setType("0");
        stockInRecordDto.setSalesLedgerId(stockInventoryDto.getSalesLedgerId());
        stockInRecordDto.setSalesLedgerProductId(stockInventoryDto.getSalesLedgerProductId());
        stockInRecordService.add(stockInRecordDto);
        //再进行新增库存数量库存
        //先查询库存表中的产品是否存在,不存在新增,存在更新
@@ -92,6 +104,8 @@
        stockOutRecordDto.setStockOutNum(stockInventoryDto.getQualitity());
        stockOutRecordDto.setProductModelId(stockInventoryDto.getProductModelId());
        stockOutRecordDto.setType("0");
        stockOutRecordDto.setSalesLedgerId(stockInventoryDto.getSalesLedgerId());
        stockOutRecordDto.setSalesLedgerProductId(stockInventoryDto.getSalesLedgerProductId());
        stockOutRecordService.add(stockOutRecordDto);
        StockInventory oldStockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>().lambda().eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId()));
        if (ObjectUtils.isEmpty(oldStockInventory)) {
src/main/java/com/ruoyi/stock/service/impl/StockOutRecordServiceImpl.java
@@ -11,6 +11,8 @@
import com.ruoyi.common.utils.OrderUtils;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.sales.mapper.SalesLedgerMapper;
import com.ruoyi.sales.pojo.SalesLedger;
import com.ruoyi.stock.dto.StockInventoryDto;
import com.ruoyi.stock.dto.StockOutRecordDto;
import com.ruoyi.stock.dto.StockUninventoryDto;
@@ -28,6 +30,7 @@
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Objects;
/**
 * <p>
@@ -43,6 +46,7 @@
    private StockOutRecordMapper stockOutRecordMapper;
    private StockInventoryMapper stockInventoryMapper;
    private StockUninventoryMapper stockUninventoryMapper;
    private SalesLedgerMapper salesLedgerMapper;
    @Override
    public IPage<StockOutRecordDto> listPage(Page page, StockOutRecordDto stockOutRecordDto) {
@@ -75,6 +79,7 @@
    public int batchDelete(List<Long> ids) {
        for (Long id : ids) {
            StockOutRecord stockOutRecord = stockOutRecordMapper.selectById(id);
            validateCanDeleteBySalesLedger(stockOutRecord);
            if (stockOutRecord.getType().equals("0")) {
                StockInventory stockInventory = stockInventoryMapper.selectOne(new LambdaQueryWrapper<StockInventory>().eq(StockInventory::getProductModelId, stockOutRecord.getProductModelId()));
                if (stockInventory == null) {
@@ -100,6 +105,16 @@
        return stockOutRecordMapper.deleteBatchIds(ids);
    }
    private void validateCanDeleteBySalesLedger(StockOutRecord stockOutRecord) {
        if (stockOutRecord == null || stockOutRecord.getSalesLedgerId() == null) {
            return;
        }
        SalesLedger salesLedger = salesLedgerMapper.selectById(stockOutRecord.getSalesLedgerId());
        if (salesLedger != null && Objects.equals(salesLedger.getDeliveryStatus(), 5)) {
            throw new BaseException("销售订单已发货,对应出库记录不允许删除");
        }
    }
    @Override
    public void exportStockOutRecord(HttpServletResponse response, StockOutRecordDto stockOutRecordDto) {
        List<StockOutRecordExportData> list = stockOutRecordMapper.listStockOutRecordExportData(stockOutRecordDto);
src/main/resources/mapper/sales/SalesLedgerMapper.xml
@@ -96,7 +96,7 @@
                AND T1.stock_status = #{salesLedgerDto.stockStatus}
            </if>
        </where>
        ORDER BY T1.entry_date DESC
        ORDER BY T1.entry_date DESC,T1.id DESC
    </select>
    <select id="selectIncomeStats" resultType="com.ruoyi.home.dto.IncomeExpenseAnalysisDto">
src/main/resources/mapper/stock/StockInventoryMapper.xml
@@ -51,6 +51,7 @@
        </set>
        where product_model_id = #{ew.productModelId} and qualitity >= #{ew.qualitity}
    </update>
    <select id="pagestockInventory" resultType="com.ruoyi.stock.dto.StockInventoryDto">
        select si.id,
        si.qualitity,
@@ -66,7 +67,7 @@
        pm.unit,
        p.product_name
        from stock_inventory si
        left join product_model pm on si. = pm.id
        left join product_model pm on si.product_model_id = pm.id
        left join product p on pm.product_id = p.id
        where 1 = 1
        <if test="ew.productName != null and ew.productName !=''">
@@ -76,6 +77,7 @@
            and si.product_model_id = #{ew.productModelId}
        </if>
    </select>
    <select id="listStockInventoryExportData" resultType="com.ruoyi.stock.execl.StockInventoryExportData">
        select si.qualitity,
        pm.model,
src/main/resources/mybatis/mybatis-config.xml
@@ -12,8 +12,8 @@
        <!-- é…ç½®é»˜è®¤çš„æ‰§è¡Œå™¨.SIMPLE就是普通执行器;REUSE执行器会重用预处理语句(prepared statements);BATCH执行器将重用语句并执行批量更新 -->
        <setting name="defaultExecutorType"      value="SIMPLE" />
        <!-- æŒ‡å®š MyBatis æ‰€ç”¨æ—¥å¿—的具体实现 -->
        <setting name="logImpl"                  value="SLF4J"  />
<!--        <setting name="logImpl"                  value="org.apache.ibatis.logging.stdout.StdOutImpl"  />-->
        <!--        <setting name="logImpl"                  value="SLF4J"  />-->
        <setting name="logImpl" value="org.apache.ibatis.logging.stdout.StdOutImpl"/>
        <!-- ä½¿ç”¨é©¼å³°å‘½åæ³•转换字段 -->
        <!-- <setting name="mapUnderscoreToCamelCase" value="true"/> -->
    </settings>