huminmin
2026-04-23 52d98d59dfa75bd18187e99e1e550701a1b27191
Merge branch 'dev_衡阳_鹏创电子' of http://114.132.189.42:9002/r/product-inventory-management-after into dev_衡阳_鹏创电子
已添加1个文件
已修改11个文件
421 ■■■■■ 文件已修改
src/main/java/com/ruoyi/common/utils/BigDecimalUtils.java 180 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProductBomController.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductBomDto.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/mapper/ProductStructureMapper.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductionProductInput.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/ProductBomService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductBomServiceImpl.java 111 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductStructureMapper.xml 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductionProductInputMapper.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/common/utils/BigDecimalUtils.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,180 @@
package com.ruoyi.common.utils;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.Collection;
import java.util.Optional;
/**
 * @author yuan
 * @date 2026-04-23 13:10
 * @description BigDecimal工具类
 */
public class BigDecimalUtils {
    public static BigDecimal getBigDecimalValue(BigDecimal val) {
        return Optional.ofNullable(val).orElse(BigDecimal.ZERO);
    }
    public static BigDecimal of(Object val) {
        if (val == null) {
            return null;
        }
        try {
            if (val instanceof Double || val instanceof Float) {
                return BigDecimal.valueOf(((Number) val).doubleValue());
            }
            if (val instanceof Number) {
                return new BigDecimal(val.toString());
            }
            return new BigDecimal(val.toString().trim());
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("无法转换 " + val + " ä¸º BigDecimal类型 ", e);
        }
    }
    /**
     * å®‰å…¨è½¬æ¢æ–¹æ³•,将对象转为BigDecimal,null视为0
     * @param number å¯ä»¥æ˜¯Number、String或BigDecimal
     * @return å¯¹åº”çš„BigDecimal,null转为0
     */
    public static BigDecimal safe(Object number) {
        if (number == null) return BigDecimal.ZERO;
        if (number instanceof BigDecimal) return (BigDecimal) number;
        if (number instanceof Number) return BigDecimal.valueOf(((Number) number).doubleValue());
        try {
            return new BigDecimal(number.toString());
        } catch (NumberFormatException e) {
            return BigDecimal.ZERO;
        }
    }
    /**
     * åŠ æ³•è¿ç®—ï¼ˆè‡ªåŠ¨å¤„ç†null值)
     * @param values å¤šä¸ªåŠ æ•°
     * @return å’Œ
     */
    public static BigDecimal add(Object... values) {
        return Arrays.stream(values)
                .map(BigDecimalUtils::safe)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
    /**
     * å‡æ³•运算(自动处理null值)
     * @param minuend è¢«å‡æ•°
     * @param subtrahends å‡æ•°
     * @return å·®
     */
    public static BigDecimal subtract(Object minuend, Object... subtrahends) {
        BigDecimal result = safe(minuend);
        for (Object subtrahend : subtrahends) {
            result = result.subtract(safe(subtrahend));
        }
        return result;
    }
    /**
     * ä¹˜æ³•运算(自动处理null值,任何参数为null则返回0)
     * @param values å¤šä¸ªä¹˜æ•°
     * @return ç§¯
     */
    public static BigDecimal multiply(Object... values) {
        if (values == null || values.length == 0) {
            return BigDecimal.ZERO;
        }
        BigDecimal result = Arrays.stream(values)
                .map(BigDecimalUtils::safe)
                .reduce(BigDecimal.ONE, BigDecimal::multiply);
        // æ ‡å‡†åŒ–结果:如果是0,去除所有小数位;否则保留原有小数位
        return stripTrailingZeros(result);
    }
    /**
     * é™¤æ³•运算(自动处理null值)
     * @param dividend è¢«é™¤æ•°
     * @param divisor é™¤æ•°
     * @param scale å°æ•°ä½æ•°
     * @param roundingMode èˆå…¥æ¨¡å¼
     * @return å•†
     */
    public static BigDecimal divide(Object dividend, Object divisor,
                                    int scale, RoundingMode roundingMode) {
        BigDecimal d1 = safe(dividend);
        BigDecimal d2 = safe(divisor);
        if (d2.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }
        return    stripTrailingZeros(d1.divide(d2, scale, roundingMode));
    }
    /**
     * é™¤æ³•运算(自动处理null值)
     * @param dividend è¢«é™¤æ•°
     * @param divisor é™¤æ•°
     * @param scale å°æ•°ä½æ•°
     * @param roundingMode èˆå…¥æ¨¡å¼
     * @return å•†
     */
    public static BigDecimal dividePercentage(Object dividend, Object divisor,
                                              int scale, RoundingMode roundingMode) {
        BigDecimal d1 = safe(dividend);
        BigDecimal d2 = safe(divisor);
        if (d2.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }
        BigDecimal multiplied = d1.multiply(new BigDecimal("100"));
        BigDecimal result = multiplied.divide(d2, scale, roundingMode);
        return stripTrailingZeros(result);
    }
    /**
     * æ¯”较两个数的大小(自动处理null值,null视为0)
     * @param num1 ç¬¬ä¸€ä¸ªæ•°
     * @param num2 ç¬¬äºŒä¸ªæ•°
     * @return 1: num1 > num2; 0: num1 = num2; -1: num1 < num2
     */
    public static int compare(Object num1, Object num2) {
        return safe(num1).compareTo(safe(num2));
    }
    /**
     * å››èˆäº”入(自动处理null值)
     * @param value åŽŸå§‹å€¼
     * @param scale ä¿ç•™å°æ•°ä½æ•°
     * @return å››èˆäº”入后的值
     */
    public static BigDecimal round(Object value, int scale) {
        return safe(value).setScale(scale, RoundingMode.HALF_UP);
    }
    /**
     * æ±‚和(流式处理版)
     * @param numbers æ•°å­—集合
     * @return å’Œ
     */
    public static BigDecimal sum(Collection<?> numbers) {
        return numbers.stream()
                .map(BigDecimalUtils::safe)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
    }
    /**
     * æ ‡å‡†åŒ–BigDecimal结果
     * 1. å¦‚果是0,去除所有小数位
     * 2. å¦‚果不是0,去除末尾无意义的0
     */
    public static BigDecimal stripTrailingZeros(BigDecimal value) {
        if (value.compareTo(BigDecimal.ZERO) == 0) {
            return BigDecimal.ZERO;
        }
        return new BigDecimal(value.stripTrailingZeros().toPlainString());
    }
}
src/main/java/com/ruoyi/production/controller/ProductBomController.java
@@ -69,6 +69,13 @@
        return productBomService.add(productBom);
    }
    @ApiModelProperty("复制BOM")
    @PostMapping("/copy")
    @Log(title = "复制BOM", businessType = BusinessType.INSERT)
    public AjaxResult copy(@RequestBody ProductBomDto productBom) {
        return productBomService.copy(productBom);
    }
    @ApiOperation("更新BOM")
    @Log(title = "修改", businessType = BusinessType.UPDATE)
    @PutMapping("/update")
src/main/java/com/ruoyi/production/dto/ProductBomDto.java
@@ -17,4 +17,7 @@
    //物料编码
    private String materialCode;
    //物料编码
    private Long copyId;
}
src/main/java/com/ruoyi/production/mapper/ProductStructureMapper.java
@@ -8,7 +8,9 @@
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.Collection;
import java.util.List;
import java.util.Set;
@Mapper
public interface ProductStructureMapper  extends BaseMapper<ProductStructure> {
@@ -16,4 +18,6 @@
    List<ProductStructureDto> listBybomId(@Param("bomId") Integer bomId);
    List<ProductStructureDto> listBybomAndProcess(@Param("bomId") Integer bomId, @Param("processId") Long processId);
    List<ProductStructureDto> selectByIds(@Param("parentIds") Set<Long> parentIds);
}
src/main/java/com/ruoyi/production/pojo/ProductionProductInput.java
@@ -23,6 +23,9 @@
    @ApiModelProperty(value = "数量")
    private BigDecimal quantity;
    @ApiModelProperty(value = "batchNo")
    private String batchNo;
    @ApiModelProperty(value = "创建时间")
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
src/main/java/com/ruoyi/production/service/ProductBomService.java
@@ -29,4 +29,6 @@
    void exportBom(HttpServletResponse response, Integer bomId);
    AjaxResult update(ProductBom productBom);
    AjaxResult copy(ProductBomDto productBom);
}
src/main/java/com/ruoyi/production/service/impl/ProductBomServiceImpl.java
@@ -2,6 +2,7 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
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.basic.pojo.Product;
@@ -20,6 +21,7 @@
import com.ruoyi.production.service.ProductBomService;
import com.ruoyi.production.service.ProductProcessService;
import com.ruoyi.production.service.ProductStructureService;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -188,6 +190,115 @@
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult copy(ProductBomDto productBom) {
        Long copyId = productBom.getCopyId();
        if (copyId == null) {
            throw new ServiceException("复制源BOM ID不能为空");
        }
        ProductBom sourceBom = productBomMapper.selectById(copyId);
        if (sourceBom == null) {
            throw new ServiceException("复制源BOM不存在");
        }
        ProductBom newBom = getProductBom(productBom, sourceBom);
        productBomMapper.insert(newBom);
        newBom.setBomNo("BM." + String.format("%05d", newBom.getId()));
        productBomMapper.updateById(newBom);
        ProductModel productModel = productModelService.getById(newBom.getProductModelId());
        if (productModel == null) {
            throw new ServiceException("选择的产品模型不存在");
        }
        ProductStructure newRoot = getProductStructure(newBom, productModel);
        productStructureService.save(newRoot);
        List<ProductStructure> sourceStructures = productStructureMapper.selectList(
                        Wrappers.<ProductStructure>lambdaQuery()
                                .eq(ProductStructure::getBomId, copyId.intValue()));
        if (sourceStructures == null || sourceStructures.isEmpty()) {
            return AjaxResult.success();
        }
        ProductStructure oldRoot = sourceStructures.stream()
                .filter(s -> s.getParentId() == null)
                .findFirst().orElse(new ProductStructure());
        List<ProductStructure> children = sourceStructures
                .stream()
                .filter(s -> !s.getId().equals(oldRoot.getId()))
                .collect(Collectors.toList());
        Map<Long, Long> oldNewIdMap = new HashMap<>();
        oldNewIdMap.put(oldRoot.getId(), newRoot.getId());
        List<ProductStructure> insertList = children
                .stream()
                .map(item -> getProductStructures(item, newBom))
                .collect(Collectors.toList());
        productStructureService.saveBatch(insertList);
        for (int i = 0; i < children.size(); i++) {
            oldNewIdMap.put(
                    children.get(i).getId(),
                    insertList.get(i).getId()
            );
        }
        List<ProductStructure> updateList = new ArrayList<>();
        for (int i = 0; i < children.size(); i++) {
            ProductStructure source = children.get(i);
            ProductStructure inserted = insertList.get(i);
            Long newParentId = oldNewIdMap.get(source.getParentId());
            if (newParentId != null) {
                inserted.setParentId(newParentId);
                updateList.add(inserted);
            }
        }
        if (!updateList.isEmpty()) {
            productStructureService.updateBatchById(updateList);
        }
        return AjaxResult.success();
    }
    @NotNull
    private static ProductStructure getProductStructures(ProductStructure item, ProductBom newBom) {
        ProductStructure copy = new ProductStructure();
        copy.setProductModelId(item.getProductModelId());
        copy.setProcessId(item.getProcessId());
        copy.setUnitQuantity(item.getUnitQuantity());
        copy.setDemandedQuantity(item.getDemandedQuantity());
        copy.setUnit(item.getUnit());
        copy.setBomId(newBom.getId());
        return copy;
    }
    @NotNull
    private static ProductStructure getProductStructure(ProductBom newBom, ProductModel productModel) {
        ProductStructure newRoot = new ProductStructure();
        newRoot.setProductModelId(newBom.getProductModelId());
        newRoot.setUnitQuantity(BigDecimal.valueOf(1));
        newRoot.setUnit(productModel.getUnit());
        newRoot.setBomId(newBom.getId());
        return newRoot;
    }
    @NotNull
    private static ProductBom getProductBom(ProductBomDto productBom, ProductBom sourceBom) {
        ProductBom newBom = new ProductBom();
        newBom.setProductModelId(productBom.getProductModelId() != null ? productBom.getProductModelId() : sourceBom.getProductModelId());
        newBom.setRemark(productBom.getRemark());
        newBom.setVersion(productBom.getVersion() != null ? productBom.getVersion() : sourceBom.getVersion());
        return newBom;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult uploadBom(MultipartFile file) {
        ExcelUtil<BomImportDto> util = new ExcelUtil<>(BomImportDto.class);
        List<BomImportDto> list;
src/main/java/com/ruoyi/production/service/impl/ProductionProductMainServiceImpl.java
@@ -18,6 +18,7 @@
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.procurementrecord.utils.StockUtils;
import com.ruoyi.production.dto.ProductStructureDto;
import com.ruoyi.production.dto.ProductionProductMainDto;
import com.ruoyi.production.mapper.*;
import com.ruoyi.production.pojo.*;
@@ -33,12 +34,12 @@
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
@Service
@@ -175,23 +176,48 @@
        productionProductMain.setStatus(0);
        productionProductMainMapper.insert(productionProductMain);
        /*新增报工投入表*/
//        List<ProductStructureDto> productStructureDtos = productStructureMapper.listBybomAndProcess(productProcessRoute.getBomId(), productProcess.getId());
//        if (productStructureDtos.isEmpty()) {
//            //如果该工序没有产品结构的投入品,那这个投入品和产出品是同一个
//            ProductStructureDto productStructureDto = new ProductStructureDto();
//            productStructureDto.setProductModelId(productProcessRouteItem.getProductModelId());
//            productStructureDto.setUnitQuantity(BigDecimal.ONE);
//            productStructureDtos.add(productStructureDto);
//        }
//        for (ProductStructureDto productStructureDto : productStructureDtos) {
//            System.out.println(productStructureDto.getProductModelId());
//            ProductionProductInput productionProductInput = new ProductionProductInput();
//            productionProductInput.setProductModelId(productStructureDto.getProductModelId());
        List<ProductStructureDto> productStructureDtos = productStructureMapper.listBybomAndProcess(productProcessRoute.getBomId(), productProcess.getId());
        if (productStructureDtos.isEmpty()) {
            //如果该工序没有产品结构的投入品,那这个投入品和产出品是同一个
            ProductStructureDto productStructureDto = new ProductStructureDto();
            productStructureDto.setProductModelId(productProcessRouteItem.getProductModelId());
            productStructureDto.setUnitQuantity(BigDecimal.ONE);
            productStructureDtos.add(productStructureDto);
        }
        Set<Long> parentIds = productStructureDtos.stream()
                .map(ProductStructureDto::getParentId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        Map<Long, ProductStructureDto> parentMap =
                productStructureMapper.selectByIds(parentIds)
                        .stream()
                        .collect(Collectors.toMap(
                                ProductStructureDto::getId,
                                Function.identity()
                        ));
        for (ProductStructureDto productStructureDto : productStructureDtos) {
            ProductionProductInput productionProductInput = new ProductionProductInput();
            productionProductInput.setProductModelId(productStructureDto.getProductModelId());
//            productionProductInput.setQuantity(productStructureDto.getUnitQuantity().multiply(dto.getQuantity()));
//            productionProductInput.setProductMainId(productionProductMain.getId());
//            productionProductInputMapper.insert(productionProductInput);
//            stockUtils.substractStock(productStructureDto.getProductModelId(), productionProductInput.getQuantity(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(), productionProductMain.getId(),dto.getBatchNo());
//        }
            BigDecimal childQty = productStructureDto.getUnitQuantity();
            BigDecimal parentQty = BigDecimal.ONE;
            if (productStructureDto.getParentId() != null) {
                ProductStructureDto parent = parentMap.get(productStructureDto.getParentId());
                if (parent != null) {
                    parentQty = parent.getUnitQuantity();
                }
            }
            // æ ¸å¿ƒè®¡ç®—
            BigDecimal needQty = childQty.divide(parentQty, 6, RoundingMode.HALF_UP).multiply(dto.getQuantity());
            productionProductInput.setQuantity(needQty);
            productionProductInput.setProductMainId(productionProductMain.getId());
            productionProductInputMapper.insert(productionProductInput);
            stockUtils.substractStock(productStructureDto.getProductModelId(), productionProductInput.getQuantity(), StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode(), productionProductMain.getId(), null);
        }
        /*新增报工产出表*/
        ProductionProductOutput productionProductOutput = new ProductionProductOutput();
        productionProductOutput.setProductMainId(productionProductMain.getId());
@@ -448,4 +474,4 @@
        
        return productionProductMainDtos;
    }
}
}
src/main/java/com/ruoyi/stock/service/impl/StockInRecordServiceImpl.java
@@ -6,7 +6,6 @@
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum;
import com.ruoyi.common.enums.StockInUnQualifiedRecordTypeEnum;
import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.EnumUtil;
import com.ruoyi.common.utils.OrderUtils;
@@ -61,7 +60,7 @@
        int insertRows = stockInRecordMapper.insert(stockInRecord);
        Long insertId = stockInRecord.getId(); // æ›¿æ¢ä¸ºä½ çš„实际主键字段:getRecordId()/getInboundId() ç­‰
        Long insertId = stockInRecord.getId();
        return insertRows > 0 ? insertId : null;
    }
src/main/java/com/ruoyi/stock/service/impl/StockInventoryServiceImpl.java
@@ -37,6 +37,7 @@
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
@@ -251,6 +252,38 @@
        stockOutRecordDto.setProductModelId(stockInventoryDto.getProductModelId());
        stockOutRecordDto.setType("0");
        stockOutRecordService.add(stockOutRecordDto);
        if (ObjectUtils.isEmpty(stockInventoryDto.getBatchNo())) {
            List<StockInventory> stockInventories = stockInventoryMapper.selectList(new QueryWrapper<StockInventory>().lambda()
                    .eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId())
                    .orderByAsc(StockInventory::getId));
            if (ObjectUtils.isEmpty(stockInventories)) {
                throw new RuntimeException("产品库存不存在");
            }
            BigDecimal remainingQty = stockInventoryDto.getQualitity();
            for (StockInventory stockInventory : stockInventories) {
                BigDecimal lockedQty = stockInventory.getLockedQuantity() == null ? BigDecimal.ZERO : stockInventory.getLockedQuantity();
                BigDecimal availableQty = stockInventory.getQualitity().subtract(lockedQty);
                if (availableQty.compareTo(BigDecimal.ZERO) <= 0) {
                    continue;
                }
                BigDecimal deductQty = remainingQty.min(availableQty);
                stockInventory.setQualitity(stockInventory.getQualitity().subtract(deductQty));
                stockInventory.setVersion(stockInventory.getVersion() == null ? 1 : stockInventory.getVersion() + 1);
                stockInventory.setUpdateTime(LocalDateTime.now());
                stockInventoryMapper.updateById(stockInventory);
                remainingQty = remainingQty.subtract(deductQty);
                if (remainingQty.compareTo(BigDecimal.ZERO) <= 0) {
                    return true;
                }
            }
            ProductModel productModel = productModelMapper.selectById(stockInventoryDto.getProductModelId());
            Product product = productMapper.selectById(productModel.getProductId());
            throw new RuntimeException(product.getProductName() + "/" + productModel.getModel() + "库存不足无法出库");
        }
        StockInventory oldStockInventory = stockInventoryMapper.selectOne(new QueryWrapper<StockInventory>().lambda().eq(StockInventory::getProductModelId, stockInventoryDto.getProductModelId())
                .eq(StockInventory::getBatchNo, stockInventoryDto.getBatchNo()));
        if (ObjectUtils.isEmpty(oldStockInventory)) {
src/main/resources/mapper/production/ProductStructureMapper.xml
@@ -41,4 +41,12 @@
        and ps.process_id=#{processId}
        order by ps.id
    </select>
    <select id="selectByIds" resultType="com.ruoyi.production.dto.ProductStructureDto">
        select *
        from product_structure
        where id in
        <foreach item="item" collection="parentIds" separator="," open="(" close=")" index="">
            #{item}
        </foreach>
    </select>
</mapper>
src/main/resources/mapper/production/ProductionProductInputMapper.xml
@@ -7,6 +7,7 @@
        <result property="productMainId" column="product_main_id"/>
        <result property="productModelId" column="product_model_id"/>
        <result property="quantity" column="quantity"/>
        <result property="batchNo" column="batch_no"/>
        <result property="tenantId" column="tenant_id"/>
        <result property="createTime" column="create_time"/>
    </resultMap>