fix(仓储物流): ①出库新增临时跳过租户插件修复 SetOperationList 解析异常 ②库存预警查询补 warningLevel/warningStatus/warningTime/expectedShortageTime/suggestionType/suggestionContent 字段 ③currentStock 别名
已修改4个文件
50 ■■■■■ 文件已修改
src/main/java/com/ruoyi/common/handler/CustomTenantLineHandler.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/pojo/CustomStorage.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordOutServiceImpl.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/CustomStorageWarningRecordMapper.xml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/handler/CustomTenantLineHandler.java
@@ -26,8 +26,18 @@
        }
    }
    /**
     * 线程级临时忽略开关:某些 insert 场景下 jsqlparser 解析会抛
     * ClassCastException: SetOperationList cannot be cast to PlainSelect,
     * 可在该线程内临时跳过租户插件(tenant_id 由 MybatisHandler 自动填充保证)。
     */
    public static final ThreadLocal<Boolean> TEMP_IGNORE = new ThreadLocal<>();
    @Override
    public boolean ignoreTable(String tableName) {
        if (Boolean.TRUE.equals(TEMP_IGNORE.get())) {
            return true;
        }
        // 指定不需要添加过滤条件的表
        Set<String> ignoreTables = IgnoreTableConfig.IGNORE_TABLES;
        return ignoreTables.contains(tableName);
src/main/java/com/ruoyi/procurementrecord/pojo/CustomStorage.java
@@ -42,6 +42,29 @@
    @TableField(exist = false)
    private String timeStr;
    // ===== 库存预警相关展示字段(来自 custom_storage_warning_record,非本表字段)=====
    /** 当前库存(页面列 currentStock,SQL 里由 availableStock 别名而来) */
    @TableField(exist = false)
    private BigDecimal currentStock;
    /** 预警级别 */
    @TableField(exist = false)
    private String warningLevel;
    /** 预警状态 */
    @TableField(exist = false)
    private String warningStatus;
    /** 预警时间 */
    @TableField(exist = false)
    private LocalDateTime warningTime;
    /** 预计缺货时间 */
    @TableField(exist = false)
    private LocalDateTime expectedShortageTime;
    /** 建议类型 */
    @TableField(exist = false)
    private String suggestionType;
    /** 建议内容 */
    @TableField(exist = false)
    private String suggestionContent;
    /**
     * 待出库数量
     */
src/main/java/com/ruoyi/procurementrecord/service/impl/ProcurementRecordOutServiceImpl.java
@@ -4,6 +4,7 @@
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.handler.CustomTenantLineHandler;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.procurementrecord.dto.ProcurementRecordOutAdd;
import com.ruoyi.procurementrecord.dto.ProcurementRecordOutPageDto;
@@ -81,6 +82,11 @@
                .updateUser(Long.valueOf(procurementRecordOutAdd.getUserId()))
                .updateTime(LocalDateTime.now());
        ProcurementRecordOut saved = procurementRecordOut.build();
        // 出库写入时临时跳过租户插件,避免 jsqlparser 解析异常
        // (ClassCastException: SetOperationList cannot be cast to PlainSelect)
        // tenant_id 由 MybatisHandler 的 strictInsertFill 自动填充,不会丢
        CustomTenantLineHandler.TEMP_IGNORE.set(Boolean.TRUE);
        try {
        this.save(saved);
        if (StringUtils.isNotEmpty(procurementRecordOutAdd.getRequisitionNum()) && saved.getId() != null) {
            ProcurementRecordOut upd = ProcurementRecordOut.builder()
@@ -89,6 +95,9 @@
                    .build();
            procurementRecordOutMapper.updateById(upd);
        }
        } finally {
            CustomTenantLineHandler.TEMP_IGNORE.remove();
        }
        return 0;
    }
src/main/resources/mapper/CustomStorageWarningRecordMapper.xml
@@ -22,7 +22,13 @@
        sum(t1.tax_inclusive_total_price) as totalPrice,
        sum(t1.inbound_num) as inboundNum,
        sum(t1.inbound_num) as inboundNum0,
        SUM(t1.inbound_num) - COALESCE(SUM(t2.inbound_num), 0) AS availableStock
        SUM(t1.inbound_num) - COALESCE(SUM(t2.inbound_num), 0) AS currentStock,
        ANY_VALUE(cswr.warning_level)        AS warningLevel,
        ANY_VALUE(cswr.warning_status)       AS warningStatus,
        ANY_VALUE(cswr.warning_time)         AS warningTime,
        ANY_VALUE(cswr.expectedShortageTime) AS expectedShortageTime,
        ANY_VALUE(cswr.suggestion_type)      AS suggestionType,
        ANY_VALUE(cswr.suggestion_content)   AS suggestionContent
        from custom_storage t1
        left join procurement_record_out t2 on t1.id = t2.procurement_record_storage_id and t2.type = 3
        inner join custom_storage_warning_record cswr on t1.id = cswr.custom_storage_id