2026-04-17 ac11e0a1320b469a2a111ba3d6a4a54f424845b7
Merge remote-tracking branch 'origin/dev_New' into dev_New
已添加7个文件
已修改10个文件
459 ■■■■■ 文件已修改
src/main/java/com/ruoyi/production/controller/ProcessRouteItemController.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProductOrderController.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProductOrderMaterialController.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/dto/ProductOrderMaterialDto.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/mapper/ProductOrderMaterialMapper.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/mapper/ProductStructureMapper.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductOrder.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductOrderMaterial.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/pojo/ProductProcess.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/ProductOrderMaterialService.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/service/impl/ProductOrderMaterialServiceImpl.java 66 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/sales/pojo/SalesLedger.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProcessRouteItemMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductOrderMaterialMapper.xml 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductProcessRouteItemMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/production/ProductWorkOrderMapper.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/sales/SalesLedgerMapper.xml 46 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/production/controller/ProcessRouteItemController.java
@@ -1,27 +1,19 @@
package com.ruoyi.production.controller;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
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.production.dto.ProcessRouteItemDto;
import com.ruoyi.production.pojo.ProcessRoute;
import com.ruoyi.production.pojo.ProcessRouteItem;
import com.ruoyi.production.service.ProcessRouteItemService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;
import java.util.Arrays;
import java.util.List;
@RestController
@RequestMapping("processRouteItem")
@RequestMapping("/processRouteItem")
@Api(tags = "工艺路线明细")
public class ProcessRouteItemController {
    @Autowired
src/main/java/com/ruoyi/production/controller/ProductOrderController.java
@@ -1,13 +1,11 @@
package com.ruoyi.production.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.basic.pojo.Customer;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.framework.aspectj.lang.annotation.Log;
import com.ruoyi.framework.aspectj.lang.enums.BusinessType;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.production.dto.ProductOrderDto;
import com.ruoyi.production.pojo.ProcessRoute;
import com.ruoyi.production.pojo.ProductOrder;
import com.ruoyi.production.service.ProductOrderService;
import io.swagger.annotations.Api;
@@ -16,7 +14,6 @@
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.List;
@RequestMapping("productOrder")
src/main/java/com/ruoyi/production/controller/ProductOrderMaterialController.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,50 @@
package com.ruoyi.production.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.framework.web.domain.R;
import com.ruoyi.production.dto.ProductOrderMaterialDto;
import com.ruoyi.production.pojo.ProductOrderMaterial;
import com.ruoyi.production.service.ProductOrderMaterialService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@AllArgsConstructor
@RequestMapping("/productOrderMaterial")
@Api(value = "ProductOrderMaterial", tags = "生产订单物料表")
public class ProductOrderMaterialController {
    private ProductOrderMaterialService productOrderMaterialservice;
    @GetMapping("/detailList")
    @ApiOperation("分页查询所有生产订单物料表")
    public R listPage(Page<ProductOrderMaterial> page, ProductOrderMaterial productOrderMaterial) {
        IPage<ProductOrderMaterial> listPage = productOrderMaterialservice.listPage(page, productOrderMaterial);
        return R.ok(listPage);
    }
    @PostMapping("/add")
    @ApiOperation("新增生产订单物料表")
    public R add(@RequestBody ProductOrderMaterial productOrderMaterial) {
        return R.ok(productOrderMaterialservice.save(productOrderMaterial));
    }
    @PostMapping("/update")
    @ApiOperation("修改生产订单物料表")
    public R update(@RequestBody ProductOrderMaterial productOrderMaterial) {
        return R.ok(productOrderMaterialservice.updateById(productOrderMaterial));
    }
    @GetMapping("/list")
    @ApiOperation("领料台账列表")
    public R list(ProductOrderMaterialDto productOrderMaterialDto) {
        List<ProductOrderMaterialDto> productOrderMaterialDtos = productOrderMaterialservice.pickMaterial(productOrderMaterialDto);
        return R.ok(productOrderMaterialDtos);
    }
}
src/main/java/com/ruoyi/production/dto/ProductOrderMaterialDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,11 @@
package com.ruoyi.production.dto;
import com.ruoyi.production.pojo.ProductOrderMaterial;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class ProductOrderMaterialDto extends ProductOrderMaterial {
}
src/main/java/com/ruoyi/production/mapper/ProductOrderMaterialMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,21 @@
package com.ruoyi.production.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ruoyi.production.dto.ProductOrderMaterialDto;
import com.ruoyi.production.dto.ProductStructureDto;
import com.ruoyi.production.pojo.ProductOrderMaterial;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface ProductOrderMaterialMapper extends BaseMapper<ProductOrderMaterial> {
    IPage<ProductOrderMaterial> pickMaterial(@Param("id") Long ProductOrderId);
    List<ProductStructureDto> selectLeafNode(@Param("bomId") Long bomId);
    List<ProductOrderMaterialDto> selectByProductModelIds(@Param("ids") List<Long> productModelIds);
}
src/main/java/com/ruoyi/production/mapper/ProductStructureMapper.java
@@ -1,8 +1,6 @@
package com.ruoyi.production.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.production.dto.ProductStructureDto;
import com.ruoyi.production.pojo.ProductStructure;
import org.apache.ibatis.annotations.Mapper;
@@ -16,4 +14,6 @@
    List<ProductStructureDto> listBybomId(@Param("bomId") Integer bomId);
    List<ProductStructureDto> listBybomAndProcess(@Param("bomId") Integer bomId, @Param("processId") Long processId);
    List<ProductStructureDto> selectLeafNode(@Param("bomId") Integer bomId);
}
src/main/java/com/ruoyi/production/pojo/ProductOrder.java
@@ -3,7 +3,6 @@
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.framework.aspectj.lang.annotation.Excel;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
src/main/java/com/ruoyi/production/pojo/ProductOrderMaterial.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,96 @@
package com.ruoyi.production.pojo;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@TableName("product_order_material")
@ApiModel(description="生产订单物料表")
public class ProductOrderMaterial implements Serializable {
    private static final long serialVersionUID = 1L;
    /**
    * ä¸»é”®ID
    */
    @ApiModelProperty(value="主键ID")
    private Long id;
    /**
    * ç”Ÿäº§è®¢å•ID
    */
    @ApiModelProperty(value="生产订单ID")
    private Long productOrderId;
    /**
    * å·¥åºåç§°
    */
    @ApiModelProperty(value="工序名称")
    private String processName;
    /**
    * åŽŸæ–™åç§°
    */
    @ApiModelProperty(value="原料名称")
    private String materialName;
    /**
    * åŽŸæ–™åž‹å·
    */
    @ApiModelProperty(value="原料型号")
    private String materialModel;
    /**
    * éœ€æ±‚数量
    */
    @ApiModelProperty(value="需求数量")
    private BigDecimal requiredQty;
    /**
    * è®¡é‡å•位
    */
    @ApiModelProperty(value="计量单位")
    private String unit;
    /**
    * é¢†ç”¨æ•°é‡
    */
    @ApiModelProperty(value="领用数量")
    private BigDecimal pickQty;
    /**
    * è¡¥æ–™æ•°é‡
    */
    @ApiModelProperty(value="补料数量")
    private BigDecimal supplementQty;
    /**
    * é€€æ–™æ•°é‡
    */
    @ApiModelProperty(value="退料数量")
    private BigDecimal returnQty;
    /**
    * å®žé™…数量
    */
    @ApiModelProperty(value="实际数量")
    private BigDecimal actualQty;
    @ApiModelProperty(value = "租户ID")
    @TableField(fill = FieldFill.INSERT)
    private Long tenantId;
    @ApiModelProperty(value = "创建时间")
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
    @ApiModelProperty(value = "创建用户")
    @TableField(fill = FieldFill.INSERT)
    private Long createUser;
    @ApiModelProperty(value = "修改时间")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
    @ApiModelProperty(value = "修改用户")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private Long updateUser;
}
src/main/java/com/ruoyi/production/pojo/ProductProcess.java
@@ -86,4 +86,12 @@
    @TableField(fill = FieldFill.INSERT)
    private Long deptId;
    @ApiModelProperty(value ="是否入库")
    @TableField("is_inbound")
    private Boolean inbound;
    @ApiModelProperty(value ="是否报工")
    @TableField("is_report_work")
    private Boolean reportWork;
}
src/main/java/com/ruoyi/production/service/ProductOrderMaterialService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,15 @@
package com.ruoyi.production.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.production.dto.ProductOrderMaterialDto;
import com.ruoyi.production.pojo.ProductOrderMaterial;
import java.util.List;
public interface ProductOrderMaterialService extends IService<ProductOrderMaterial> {
    IPage<ProductOrderMaterial> listPage(Page<ProductOrderMaterial> page, ProductOrderMaterial productOrderMaterial);
    List<ProductOrderMaterialDto> pickMaterial(ProductOrderMaterialDto productOrderMaterialDto);
}
src/main/java/com/ruoyi/production/service/impl/ProductOrderMaterialServiceImpl.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,66 @@
package com.ruoyi.production.service.impl;
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.production.dto.ProductOrderMaterialDto;
import com.ruoyi.production.dto.ProductStructureDto;
import com.ruoyi.production.mapper.ProcessRouteMapper;
import com.ruoyi.production.mapper.ProductOrderMapper;
import com.ruoyi.production.mapper.ProductOrderMaterialMapper;
import com.ruoyi.production.pojo.ProcessRoute;
import com.ruoyi.production.pojo.ProductOrder;
import com.ruoyi.production.pojo.ProductOrderMaterial;
import com.ruoyi.production.service.ProductOrderMaterialService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class ProductOrderMaterialServiceImpl extends ServiceImpl<ProductOrderMaterialMapper, ProductOrderMaterial> implements ProductOrderMaterialService {
    private final ProductOrderMaterialMapper productOrderMaterialmapper;
    private final ProductOrderMapper productOrderMapper;
    private final ProcessRouteMapper processRouteMapper;
    @Override
    public IPage<ProductOrderMaterial> listPage(Page<ProductOrderMaterial> page, ProductOrderMaterial productOrderMaterial) {
        return productOrderMaterialmapper.selectPage(page, null);
    }
    @Override
    public List<ProductOrderMaterialDto> pickMaterial(ProductOrderMaterialDto productOrderMaterialDto) {
        Long productOrderId = productOrderMaterialDto.getProductOrderId();
        ProductOrder productOrder = productOrderMapper.selectById(productOrderId);
        BigDecimal quantity = productOrder.getQuantity();
        ProcessRoute processRoute = processRouteMapper.selectById(productOrder.getRouteId());
        //查询叶子节点
        List<ProductStructureDto> productStructureDtoList = productOrderMaterialmapper.selectLeafNode(Long.valueOf(processRoute.getBomId()));
        List<Long> productModelIds = productStructureDtoList.stream()
                .map(ProductStructureDto::getProductModelId)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        if (!productModelIds.isEmpty()) {
            List<ProductOrderMaterialDto> productOrderMaterialDtos = productOrderMaterialmapper.selectByProductModelIds(productModelIds);
            if (!productOrderMaterialDtos.isEmpty()) {
                return productOrderMaterialDtos;
            }else {
                throw new RuntimeException("库存没有对应产品");
            }
        }else {
            throw new RuntimeException("请先维护BOM");
        }
    }
}
src/main/java/com/ruoyi/sales/pojo/SalesLedger.java
@@ -154,5 +154,9 @@
    @TableField(fill = FieldFill.INSERT)
    private Long deptId;
    @ApiModelProperty(value = "是否有生产记录")
    @TableField(exist = false)
    private Boolean hasProductionRecord;
}
src/main/resources/mapper/production/ProcessRouteItemMapper.xml
@@ -17,6 +17,8 @@
        select pri.*,
               pr.description ,
               pp.name as process_name,
               pp.is_inbound as inbound,
               pp.is_report_work as reportWork,
               pm.speculative_trading_name,
               pm.product_id,
               pm.model,
src/main/resources/mapper/production/ProductOrderMaterialMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,116 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.production.mapper.ProductOrderMaterialMapper">
    <resultMap id="BaseResultMap" type="com.ruoyi.production.pojo.ProductOrderMaterial">
        <id column="id" property="id" />
                <result column="tenant_id" property="tenantId" />
                <result column="process_name" property="processName" />
                <result column="material_name" property="materialName" />
                <result column="material_model" property="materialModel" />
                <result column="required_qty" property="requiredQty" />
                <result column="unit" property="unit" />
                <result column="pick_qty" property="pickQty" />
                <result column="supplement_qty" property="supplementQty" />
                <result column="return_qty" property="returnQty" />
                <result column="actual_qty" property="actualQty" />
                <result column="create_time" property="createTime" />
                <result column="update_time" property="updateTime" />
                <result column="create_user" property="createUser" />
                <result column="update_user" property="updateUser" />
    </resultMap>
        <select id="pickMaterial" resultType="com.ruoyi.production.pojo.ProductOrderMaterial">
            SELECT
            si.id,
            si.qualitity,
            COALESCE(si.locked_quantity, 0) AS locked_quantity,
            si.product_model_id,
            si.create_time,
            si.update_time,
            COALESCE(si.warn_num, 0) AS warn_num,
            si.version,
            (si.qualitity - COALESCE(si.locked_quantity, 0)) AS un_locked_quantity,
            pm.model,
            si.remark,
            pm.unit,
            pm.uid_no AS uidNo,
            p.product_name,
            p1.product_name AS parentName,
            si.batch_no,
            si.customer
            FROM
            stock_inventory si
            LEFT JOIN product_model pm ON si.product_model_id = pm.id
            LEFT JOIN product p ON pm.product_id = p.id
            LEFT JOIN product p1 ON p1.id = p.parent_id
        </select>
    <select id="selectLeafNode" resultType="com.ruoyi.production.dto.ProductStructureDto">
        SELECT
            ps.*,
            p.product_name,
            pp.NAME AS process_name,
            pm.product_id,
            pm.model
        FROM
            product_structure ps
                LEFT JOIN product_model pm ON ps.product_model_id = pm.id
                LEFT JOIN product p ON pm.product_id = p.id
                LEFT JOIN product_process pp ON ps.process_id = pp.id
        WHERE
            ps.bom_id = #{bomId}
          AND NOT EXISTS (SELECT 1 FROM product_structure ps_child WHERE ps_child.parent_id = ps.id AND ps_child.bom_id = 30)
        ORDER BY
            ps.id
    </select>
    <select id="selectByProductModelIds" resultType="com.ruoyi.production.dto.ProductOrderMaterialDto">
        SELECT
            si.id,
            si.qualitity,
            COALESCE(si.locked_quantity, 0) AS locked_quantity,
            si.product_model_id,
            si.create_time,
            si.update_time,
            COALESCE(si.warn_num, 0) AS warn_num,
            si.version,
            (si.qualitity - COALESCE(si.locked_quantity, 0)) AS un_locked_quantity,
            pm.model as materialModel,
            si.remark,
            pm.unit,
            pm.uid_no AS uidNo,
            p.product_name as materialName,
            p1.product_name AS parentName,
            leaf.process_name,
            leaf.id AS structure_id
            FROM stock_inventory si
            LEFT JOIN product_model pm ON si.product_model_id = pm.id
            LEFT JOIN product p ON pm.product_id = p.id
            LEFT JOIN product p1 ON p1.id = p.parent_id
            INNER JOIN (
            SELECT
            ps.product_model_id,
            pp.name AS process_name,
            ps.id
        FROM product_structure ps
        LEFT JOIN product_process pp ON ps.process_id = pp.id
        WHERE ps.product_model_id IN
        <foreach collection="ids" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
        AND ps.id NOT IN (
        SELECT DISTINCT parent_id
        FROM product_structure
        WHERE parent_id IS NOT NULL
        AND parent_id != 0
        AND product_model_id IN
        <foreach collection="ids" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
        ))
        leaf ON leaf.product_model_id = si.product_model_id
        ORDER BY si.id
    </select>
</mapper>
src/main/resources/mapper/production/ProductProcessRouteItemMapper.xml
@@ -13,6 +13,8 @@
    <select id="listItem" resultType="com.ruoyi.production.dto.ProductProcessRouteItemDto">
        select ppri.*,
               pp.name as process_name,
               pp.is_inbound as inbound,
               pp.is_report_work as reportWork,
               pm.model,
               pm.unit,
               p.product_name,
src/main/resources/mapper/production/ProductWorkOrderMapper.xml
@@ -45,8 +45,8 @@
            <if test="c.planStartTime != null and c.planEndTime != null">
                and DATE(pwo.create_time) between #{c.planStartTime} and #{c.planEndTime}
            </if>
            <if test="c.productOrderId != null and c.productOrderId != ''">
               and pwo.product_order_id = #{c.productOrderId}
            <if test="c.productOrderNpsNo != null and c.productOrderNpsNo != ''">
               and po.nps_no like concat('%',#{c.productOrderNpsNo},'%')
            </if>
    </select>
    <select id="getProductWorkOrderFlowCard" resultType="com.ruoyi.production.dto.ProductWorkOrderDto">
src/main/resources/mapper/sales/SalesLedgerMapper.xml
@@ -5,12 +5,12 @@
<mapper namespace="com.ruoyi.sales.mapper.SalesLedgerMapper">
    <select id="selectSequencesByDate" resultType="java.lang.Integer">
        SELECT CAST(SUBSTR(sales_contract_no,LENGTH(#{datePart})+1 , 3) AS SIGNED)
        SELECT CAST(SUBSTR(sales_contract_no, LENGTH(#{datePart}) + 1, 3) AS SIGNED)
        FROM sales_ledger
        WHERE sales_contract_no LIKE CONCAT('%',#{datePart},'%')
        WHERE sales_contract_no LIKE CONCAT('%', #{datePart}, '%')
    </select>
    <select id="getSalesNo" resultType="com.ruoyi.sales.pojo.SalesLedger">
    </select>
    <select id="selectSalesLedgerList" resultType="com.ruoyi.sales.pojo.SalesLedger">
@@ -56,47 +56,53 @@
        T1.attachment_materials,
        T1.tenant_id,
        T1.contract_amount,
        T1.contract_amount                    as noInvoiceAmountTotal,
        T1.contract_amount AS noInvoiceAmountTotal,
        T1.execution_date,
        T2.nick_name                          AS entry_person_name,
        T2.nick_name AS entry_person_name,
        T1.payment_method,
        T1.delivery_date,
        DATEDIFF(T1.delivery_date, CURDATE()) AS delivery_days_diff,
        CASE
        WHEN shipping_status_counts.total_count = 0 THEN false
        WHEN shipping_status_counts.unshipped_count = 0 THEN true
        ELSE false
        END AS is_fh
        IFNULL(shipping_status_counts.is_all_shipped, FALSE) AS is_fh,
        IFNULL(production_exists.has_production, FALSE) AS has_production_record
        FROM sales_ledger T1
        LEFT JOIN sys_user T2 ON T1.entry_person = T2.user_id
        LEFT JOIN (
        SELECT sales_ledger_id,
        COUNT(*) as total_count,
        SUM(CASE WHEN status != '已发货' THEN 1 ELSE 0 END) as unshipped_count
        CASE
        WHEN SUM(CASE WHEN status != '已发货' THEN 1 ELSE 0 END) = 0 THEN TRUE
        ELSE FALSE
        END AS is_all_shipped
        FROM shipping_info
        GROUP BY sales_ledger_id
        ) shipping_status_counts ON T1.id = shipping_status_counts.sales_ledger_id
        LEFT JOIN (
        SELECT DISTINCT po.sales_ledger_id,
        TRUE AS has_production
        FROM product_order po
        INNER JOIN product_work_order wo ON wo.product_order_id = po.id
        INNER JOIN production_product_main pm ON pm.work_order_id = wo.id
        ) production_exists ON T1.id = production_exists.sales_ledger_id
        <where>
            <if test="salesLedgerDto.customerName != null and salesLedgerDto.customerName != '' ">
                AND  T1.customer_name LIKE CONCAT('%',#{salesLedgerDto.customerName},'%')
                AND T1.customer_name LIKE CONCAT('%',#{salesLedgerDto.customerName},'%')
            </if>
            <if test="salesLedgerDto.customerContractNo != null and salesLedgerDto.customerContractNo !='' ">
                AND  T1.customer_contract_no LIKE CONCAT('%',#{salesLedgerDto.customerContractNo},'%')
                AND T1.customer_contract_no LIKE CONCAT('%',#{salesLedgerDto.customerContractNo},'%')
            </if>
            <if test="salesLedgerDto.salesContractNo != null and salesLedgerDto.salesContractNo != '' ">
                AND  T1.sales_contract_no LIKE CONCAT('%',#{salesLedgerDto.salesContractNo},'%')
                AND T1.sales_contract_no LIKE CONCAT('%',#{salesLedgerDto.salesContractNo},'%')
            </if>
            <if test="salesLedgerDto.projectName != null and salesLedgerDto.projectName != '' ">
                AND T1.project_name LIKE CONCAT('%',#{salesLedgerDto.projectName},'%')
            </if>
            <if test="salesLedgerDto.entryDateStart != null and salesLedgerDto.entryDateStart != '' ">
               AND T1.entry_date &gt;= DATE_FORMAT(#{salesLedgerDto.entryDateStart},'%Y-%m-%d')
                AND T1.entry_date &gt;= DATE_FORMAT(#{salesLedgerDto.entryDateStart},'%Y-%m-%d')
            </if>
            <if test="salesLedgerDto.entryDateEnd != null and salesLedgerDto.entryDateEnd != '' ">
                AND  T1.entry_date &lt;= DATE_FORMAT(#{salesLedgerDto.entryDateEnd},'%Y-%m-%d')
                AND T1.entry_date &lt;= DATE_FORMAT(#{salesLedgerDto.entryDateEnd},'%Y-%m-%d')
            </if>
        </where>
    order by T1.entry_date desc
        order by T1.entry_date desc
    </select>
    <select id="selectIncomeStats" resultType="com.ruoyi.home.dto.IncomeExpenseAnalysisDto">
@@ -117,9 +123,9 @@
        left join sales_ledger_product slp on sl.id = slp.sales_ledger_id
        left join shipping_info si on slp.id = si.sales_ledger_product_id
        where si.status = '已发货'
            <if test="ew.customerName != null and ew.customerName != '' ">
        <if test="ew.customerName != null and ew.customerName != '' ">
            and sl.customer_name like concat('%',#{ew.customerName},'%')
            </if>
        </if>
        order by sl.execution_date desc
    </select>