已添加8个文件
已修改21个文件
654 ■■■■■ 文件已修改
doc/20260306_create_purchase_return_orders.sql 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/projectManagement/controller/InfoController.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/projectManagement/controller/RolesController.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/projectManagement/dto/InfoStageDto.java 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/projectManagement/dto/PlanStageDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/projectManagement/mapper/InfoStageMapper.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/projectManagement/pojo/InfoStage.java 141 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/projectManagement/service/RolesService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/projectManagement/service/impl/RolesServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/projectManagement/service/impl/handle/InfoHandleService.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/projectManagement/service/impl/handle/InfoStageHandleService.java 161 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/projectManagement/vo/InfoStageVo.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/projectManagement/vo/InfoVo.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/projectManagement/vo/ListInfoVo.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/projectManagement/vo/SaveInfoStageVo.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/projectManagement/vo/SimpleRoleVo.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrderProductsController.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrdersController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/mapper/PurchaseReturnOrderProductsMapper.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/pojo/PurchaseReturnOrderProducts.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/pojo/PurchaseReturnOrders.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/PurchaseReturnOrderProductsService.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/impl/PurchaseReturnOrderProductsServiceImpl.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/ruoyi/purchase/service/impl/PurchaseReturnOrdersServiceImpl.java 4 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/procurementrecord/ReturnManagementMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/projectManagement/InfoMapper.xml 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/projectManagement/InfoStageMapper.xml 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/purchase/PurchaseReturnOrderProductsMapper.xml 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/mapper/safe/SafeTrainingMapper.xml 21 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
doc/20260306_create_purchase_return_orders.sql
@@ -30,6 +30,7 @@
    id                       bigint auto_increment primary key,
    purchase_return_order_id bigint not null default 0 comment '退货单id',
    sales_ledger_product_id  bigint not null default 0 comment '采购产品id',
    return_quantity          decimal(16, 4)  not null default 0 comment '退货数量',
    create_time              datetime null comment '录入时间',
    update_time              datetime null comment '更新时间',
    index                    idx_purchase_return_order_id (purchase_return_order_id),
src/main/java/com/ruoyi/projectManagement/controller/InfoController.java
@@ -1,8 +1,11 @@
package com.ruoyi.projectManagement.controller;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.projectManagement.dto.InfoStageDto;
import com.ruoyi.projectManagement.dto.UpdateStateInfo;
import com.ruoyi.projectManagement.service.InfoService;
import com.ruoyi.projectManagement.service.impl.handle.InfoStageHandleService;
import com.ruoyi.projectManagement.vo.SaveInfoStageVo;
import com.ruoyi.projectManagement.vo.SaveInfoVo;
import com.ruoyi.projectManagement.vo.SearchInfoVo;
import io.swagger.annotations.Api;
@@ -24,6 +27,7 @@
public class InfoController {
    private final InfoService infoService;
    private final InfoStageHandleService infoStageHandleService;
    @PostMapping("/save")
    @ApiOperation("保存")
@@ -59,5 +63,25 @@
        return AjaxResult.success(infoService.getInfoById(id));
    }
    @PostMapping("/saveStage")
    @ApiOperation("保存阶段")
    public AjaxResult saveStage(@RequestBody @Valid SaveInfoStageVo dto) {
        infoStageHandleService.save(dto);
        return AjaxResult.success();
    }
    @PostMapping("/listStage/{id}")
    @ApiOperation("列表阶段")
    public AjaxResult listStage(@PathVariable Long id) {
        return AjaxResult.success(infoStageHandleService.getListVoByInfoId(id));
    }
    @PostMapping("/deleteStage/{id}")
    @ApiOperation("删除阶段")
    public AjaxResult deleteStage(@PathVariable Long id) {
        infoStageHandleService.deleteById(id);
        return AjaxResult.success();
    }
}
src/main/java/com/ruoyi/projectManagement/controller/RolesController.java
@@ -52,4 +52,9 @@
        if (CollectionUtils.isEmpty(ids)) return AjaxResult.error("请传入要删除的ID");
        return AjaxResult.success(rolesservice.removeBatchByIds(ids));
    }
    @PostMapping("/listSimpleRole")
    public AjaxResult listSimpleRole() {
        return AjaxResult.success(rolesservice.listSimpleRole());
    }
}
src/main/java/com/ruoyi/projectManagement/dto/InfoStageDto.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
package com.ruoyi.projectManagement.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
 * @author buhuazhen
 * @date 2026/3/11
 * @email 3038525872@qq.com
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class InfoStageDto implements java.io.Serializable {
    private Long id;
    /**
     * å¯¹åº”计划节点id
     */
    @NotNull(message = "对应计划节点projectManagementPlanNodeId不能为空")
    private Long projectManagementPlanNodeId;
    /**
     * å¯¹åº”项目id
     */
    @NotNull(message = "对应项目projectManagementInfoId不能为空")
    private Long projectManagementInfoId;
    /**
     * æè¿°
     */
    private String description;
    /**
     * å®žé™…负责人id
     */
    private Long actualLeaderId;
    /**
     * å®žé™…负责人名称
     */
    private String actualLeaderName;
    /**
     * é¢„计工期
     */
    private Integer estimatedDuration;
    /**
     * è®¡åˆ’开始
     */
    @JsonFormat(pattern = "yyyy-MM-dd")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate planStartTime;
    /**
     * è¿›åº¦
     */
    private Integer progress;
    /**
     * å®žé™…开始时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate actualStartTime;
    /**
     * å®žé™…结束时间
     */
    @JsonFormat(pattern = "yyyy-MM-dd")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate actualEndTime;
    /**
     * åˆ›å»ºæ—¶é—´
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime createTime;
    private String attachment;
}
src/main/java/com/ruoyi/projectManagement/dto/PlanStageDto.java
@@ -19,4 +19,6 @@
    private Long id;
    private String name;
    private PlanStageEnum planStageEnum;
    private Integer sort;
    private Integer estimatedDuration; // é¢„计工期
}
src/main/java/com/ruoyi/projectManagement/mapper/InfoStageMapper.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,18 @@
package com.ruoyi.projectManagement.mapper;
import com.ruoyi.projectManagement.pojo.InfoStage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author buhuazhen
* @description é’ˆå¯¹è¡¨ã€project_management_info_stage(项目阶段)】的数据库操作Mapper
* @createDate 2026-03-11 10:28:27
* @Entity com.ruoyi.projectManagement.pojo.InfoStage
*/
public interface InfoStageMapper extends BaseMapper<InfoStage> {
}
src/main/java/com/ruoyi/projectManagement/pojo/InfoStage.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,141 @@
package com.ruoyi.projectManagement.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
import lombok.Data;
/**
 * é¡¹ç›®é˜¶æ®µ
 * @TableName project_management_info_stage
 */
@TableName(value ="project_management_info_stage")
@Data
public class InfoStage implements Serializable {
    /**
     *
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * å¯¹åº”计划节点id
     */
    @TableField(value = "project_management_plan_node_id")
    private Long projectManagementPlanNodeId;
    /**
     * å¯¹åº”项目id
     */
    @TableField(value = "project_management_info_id")
    private Long projectManagementInfoId;
    /**
     * æè¿°
     */
    @TableField(value = "description")
    private String description;
    /**
     * å®žé™…负责人id
     */
    @TableField(value = "actual_leader_id")
    private Long actualLeaderId;
    /**
     * å®žé™…负责人名称
     */
    @TableField(value = "actual_leader_name")
    private String actualLeaderName;
    /**
     * é¢„计工期
     */
    @TableField(value = "estimated_duration")
    private Integer estimatedDuration;
    /**
     * è®¡åˆ’开始
     */
    @TableField(value = "plan_start_time")
    private LocalDate planStartTime;
    /**
     * è®¡åˆ’结束
     */
    @TableField(value = "plan_end_time")
    private LocalDate planEndTime;
    /**
     * è¿›åº¦
     */
    @TableField(value = "progress")
    private Integer progress;
    /**
     * å®žé™…开始时间
     */
    @TableField(value = "actual_start_time")
    private LocalDate actualStartTime;
    /**
     * å®žé™…结束时间
     */
    @TableField(value = "actual_end_time")
    private LocalDate actualEndTime;
    /**
     * é™„ä»¶
     */
    @TableField(value = "attachment")
    private String attachment;
    /**
     *
     */
    @TableField(value = "create_time")
    private LocalDateTime createTime;
    /**
     *
     */
    @TableField(value = "update_time")
    private LocalDateTime updateTime;
    /**
     *
     */
    @TableField(value = "is_delete")
    private Integer isDelete;
    /**
     *
     */
    @TableField(value = "create_user")
    private Long createUser;
    /**
     *
     */
    @TableField(value = "update_user")
    private Long updateUser;
    /**
     *
     */
    @TableField(value = "create_user_name")
    private String createUserName;
    /**
     *
     */
    @TableField(value = "update_user_name")
    private String updateUserName;
    @TableField(exist = false)
    private static final long serialVersionUID = 1L;
}
src/main/java/com/ruoyi/projectManagement/service/RolesService.java
@@ -4,7 +4,12 @@
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.projectManagement.pojo.Roles;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.projectManagement.vo.SimpleRoleVo;
import java.util.List;
public interface RolesService extends IService<Roles> {
    IPage<Roles> listPage(Page<Roles> page, Roles roles);
    List<SimpleRoleVo> listSimpleRole();
}
src/main/java/com/ruoyi/projectManagement/service/impl/RolesServiceImpl.java
@@ -1,16 +1,21 @@
package com.ruoyi.projectManagement.service.impl;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.enums.IsDeleteEnum;
import com.ruoyi.projectManagement.mapper.RolesMapper;
import com.ruoyi.projectManagement.pojo.Roles;
import com.ruoyi.projectManagement.service.RolesService;
import com.ruoyi.projectManagement.vo.SimpleRoleVo;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@AllArgsConstructor
@Service
@@ -29,4 +34,11 @@
        }
        return rolesmapper.selectPage(page, queryWrapper);
    }
    @Override
    public List<SimpleRoleVo> listSimpleRole() {
        LambdaQueryWrapper<Roles> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Roles::getStatus, 1);
        return BeanUtil.copyToList(rolesmapper.selectList(queryWrapper), SimpleRoleVo.class);
    }
}
src/main/java/com/ruoyi/projectManagement/service/impl/handle/InfoHandleService.java
@@ -4,10 +4,12 @@
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.google.common.collect.Lists;
import com.ruoyi.basic.service.CustomerFollowUpFileService;
import com.ruoyi.common.enums.PlanStageEnum;
import com.ruoyi.common.enums.ReviewStatusEnum;
import com.ruoyi.projectManagement.dto.InfoStageDto;
import com.ruoyi.projectManagement.dto.PlanStageDto;
import com.ruoyi.projectManagement.dto.SaveInfoDto;
import com.ruoyi.projectManagement.mapper.InfoMapper;
@@ -68,6 +70,11 @@
        return info.getId();
    }
    @Transactional
    public void updateById(@NotNull Info info){
        infoMapper.updateById(info);
    }
    public SaveInfoDto getInfoById(@NotNull Long id) {
        Info info = infoMapper.selectById(id);
        return convert(info);
@@ -99,7 +106,7 @@
    private List<PlanStageDto> getPlanStageList(@NotNull Long planId) {
        List<PlanNode> planNodeByPlanId = planService.getPlanNodeByPlanId(planId);
        return planNodeByPlanId.stream().map(it -> new PlanStageDto(it.getId(), it.getName(), PlanStageEnum.TO_BEGIN)).collect(Collectors.toList());
        return planNodeByPlanId.stream().map(it -> new PlanStageDto(it.getId(), it.getName(), PlanStageEnum.TO_BEGIN, it.getSort(), it.getEstimatedDuration())).collect(Collectors.toList());
    }
src/main/java/com/ruoyi/projectManagement/service/impl/handle/InfoStageHandleService.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,161 @@
package com.ruoyi.projectManagement.service.impl.handle;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.ruoyi.basic.service.CustomerFollowUpFileService;
import com.ruoyi.common.enums.IsDeleteEnum;
import com.ruoyi.common.enums.PlanStageEnum;
import com.ruoyi.projectManagement.dto.InfoStageDto;
import com.ruoyi.projectManagement.dto.PlanStageDto;
import com.ruoyi.projectManagement.dto.SaveInfoDto;
import com.ruoyi.projectManagement.mapper.InfoStageMapper;
import com.ruoyi.projectManagement.pojo.Info;
import com.ruoyi.projectManagement.pojo.InfoStage;
import com.ruoyi.projectManagement.vo.InfoStageVo;
import com.ruoyi.projectManagement.vo.SaveInfoStageVo;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import javax.validation.constraints.NotNull;
import java.util.*;
import java.util.stream.Collectors;
/**
 * @author buhuazhen
 * @date 2026/3/11
 * @email 3038525872@qq.com
 */
@Component
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class, readOnly = true)
public class InfoStageHandleService {
    private final InfoStageMapper infoStageMapper;
    private final InfoHandleService infoHandleService;
    private final CustomerFollowUpFileService customerFollowUpFileService;
    @Autowired
    @Lazy
    private InfoStageHandleService infoStageHandleService;
    @Transactional
    public void save(@NotNull SaveInfoStageVo saveInfoStageVo) {
        InfoStage infoStage = BeanUtil.copyProperties(saveInfoStageVo, InfoStage.class);
        // é™„件处理
        String attachmentIds = StrUtil.join(",", Optional.ofNullable(saveInfoStageVo.getAttachmentIds()).orElse(Collections.emptyList()));
        infoStage.setAttachment(attachmentIds);
        if (infoStage.getId() == null) {
            infoStageMapper.insert(infoStage);
        } else {
            infoStageMapper.updateById(infoStage);
        }
        infoStageHandleService.syncInfoStage(infoStage.getProjectManagementInfoId());
    }
    /**
     * åŒæ­¥é¡¹ç›®é˜¶æ®µçŠ¶æ€
     *
     * @param infoId
     */
    @Transactional
    public void syncInfoStage(@NotNull Long infoId) {
        SaveInfoDto infoById = infoHandleService.getInfoById(infoId);
        List<PlanStageDto> planStage = infoById.getPlanStage();
        // èŽ·å–ä¾æ—§å­˜åœ¨çš„é˜¶æ®µä¿¡æ¯
        List<InfoStageDto> infoStageNow = getListDtoByInfoId(infoId);
        Map<Long, Integer> maxProgressMap =
                infoStageNow.stream()
                        .filter(e -> e.getProjectManagementPlanNodeId() != null)
                        .collect(Collectors.toMap(
                                InfoStageDto::getProjectManagementPlanNodeId,
                                e -> Optional.ofNullable(e.getProgress()).orElse(0),
                                Integer::max
                        ));
        for (PlanStageDto stage : planStage) {
            int progress = maxProgressMap.getOrDefault(stage.getId(), 0);
            stage.setPlanStageEnum(calcStage(progress));
        }
        // è¿›è¡Œè°ƒæ•´
        Info info = new Info();
        info.setId(infoId);
        info.setPlanStage(planStage);
        infoHandleService.updateById(info);
    }
    private PlanStageEnum calcStage(int progress) {
        if (progress <= 0) {
            return PlanStageEnum.TO_BEGIN;
        } else if (progress < 100) {
            return PlanStageEnum.ON_GOING;
        }
        return PlanStageEnum.ENDED;
    }
    @Transactional(rollbackFor = Exception.class)
    public void deleteById(@NotNull Long id) {
        InfoStage infoStage = infoStageMapper.selectById(id);
        if (infoStage == null) {
            return;
        }
        LambdaUpdateWrapper<InfoStage> updateWrapper = new LambdaUpdateWrapper<InfoStage>();
        updateWrapper.eq(InfoStage::getId, id);
        updateWrapper.set(InfoStage::getIsDelete, IsDeleteEnum.DELETED.getCode());
        infoStageMapper.update(null, updateWrapper);
        infoStageHandleService.syncInfoStage(infoStage.getProjectManagementInfoId());
    }
    public List<InfoStageDto> getListDtoByInfoId(@NotNull Long infoId) {
        LambdaQueryWrapper<InfoStage> queryWrapper = new LambdaQueryWrapper<InfoStage>();
        queryWrapper.eq(InfoStage::getProjectManagementInfoId, infoId);
        queryWrapper.eq(InfoStage::getIsDelete, IsDeleteEnum.NOT_DELETED.getCode());
        List<InfoStageDto> infoStageDtos = BeanUtil.copyToList(infoStageMapper.selectList(queryWrapper), InfoStageDto.class);
        /*
         * è¿›è¡ŒæŽ’序 å…ˆæŒ‰ç…§å¯¹åº”çš„sort进行排序,后按照创建时间排序
         * å¯èƒ½ä¼šå‡ºçŽ°åŽéƒ¨æƒ…å†µ æ¯”如
         * ç«‹é¡¹ 100%
         * ç«‹é¡¹ 50%   è¿™ç§æƒ…况,当然也支持修改操作
         */
        SaveInfoDto infoById = infoHandleService.getInfoById(infoId);
        List<PlanStageDto> planStage = infoById.getPlanStage();
        // æž„建 id -> sort æ˜ å°„
        Map<Long, Integer> stageSortMap = planStage.stream()
                .collect(Collectors.toMap(
                        PlanStageDto::getId,
                        PlanStageDto::getSort
                ));
        // æŽ’序
        infoStageDtos.sort(
                Comparator
                        // å…ˆæŒ‰é˜¶æ®µæŽ’序
                        .comparing((InfoStageDto dto) ->
                                stageSortMap.getOrDefault(dto.getProjectManagementPlanNodeId(), Integer.MAX_VALUE)
                        )
                        // å†æŒ‰åˆ›å»ºæ—¶é—´æŽ’序
                        .thenComparing(InfoStageDto::getCreateTime)
        );
        return infoStageDtos;
    }
    public List<InfoStageVo> getListVoByInfoId(@NotNull Long infoId) {
        List<InfoStageDto> listByInfoId = getListDtoByInfoId(infoId);
        List<InfoStageVo> infoStageVos = BeanUtil.copyToList(listByInfoId, InfoStageVo.class);
        // å¤„理附件
        customerFollowUpFileService.fillAttachment(infoStageVos, InfoStageVo::getAttachment, InfoStageVo::setAttachmentList);
        return infoStageVos;
    }
}
src/main/java/com/ruoyi/projectManagement/vo/InfoStageVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
package com.ruoyi.projectManagement.vo;
import com.ruoyi.common.vo.SimpleFileVo;
import com.ruoyi.projectManagement.dto.InfoStageDto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.util.List;
/**
 * @author buhuazhen
 * @date 2026/3/11
 * @email 3038525872@qq.com
 */
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class InfoStageVo extends InfoStageDto implements java.io.Serializable {
    private List<SimpleFileVo> attachmentList; // é™„件列表
}
src/main/java/com/ruoyi/projectManagement/vo/InfoVo.java
@@ -20,10 +20,6 @@
@NoArgsConstructor
public class InfoVo extends SaveInfoVo implements Serializable {
    // é¡¹ç›®é˜¶æ®µ
    private String xxx;
    // ä¸‹çº§é¡¹ç›®
    private List<SaveInfoDto> subordinateInfoList;
}
src/main/java/com/ruoyi/projectManagement/vo/ListInfoVo.java
@@ -1,6 +1,7 @@
package com.ruoyi.projectManagement.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.projectManagement.dto.PlanStageDto;
import com.ruoyi.projectManagement.dto.SaveInfoDto;
import lombok.AllArgsConstructor;
import lombok.Data;
@@ -10,6 +11,7 @@
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.List;
/**
 * é¡µé¢åˆ—表信息
@@ -39,4 +41,6 @@
    private String createUserName; // åˆ›å»ºäººåç§°
    private String updateUserName; // æ›´æ–°äººåç§°
    // å…¨éƒ¨é˜¶æ®µä¿¡æ¯
    private List<PlanStageDto> planStage;
}
src/main/java/com/ruoyi/projectManagement/vo/SaveInfoStageVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,28 @@
package com.ruoyi.projectManagement.vo;
import com.baomidou.mybatisplus.annotation.TableField;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.projectManagement.dto.InfoStageDto;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDate;
import java.util.List;
/**
 * @author buhuazhen
 * @date 2026/3/11
 * @email 3038525872@qq.com
 */
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SaveInfoStageVo extends InfoStageDto implements java.io.Serializable {
    private List<String> attachmentIds;
}
src/main/java/com/ruoyi/projectManagement/vo/SimpleRoleVo.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,21 @@
package com.ruoyi.projectManagement.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
 * @author buhuazhen
 * @date 2026/3/11
 * @email 3038525872@qq.com
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
public class SimpleRoleVo implements java.io.Serializable {
    private Long id;
    private String no;
    private String name;
}
src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrderProductsController.java
@@ -1,5 +1,6 @@
package com.ruoyi.purchase.controller;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -9,10 +10,11 @@
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-03-09 01:37:44
 * @since 2026-03-10 04:45:35
 */
@RestController
@RequestMapping("/purchaseReturnOrderProducts")
@Api(tags = "采购退货产品")
public class PurchaseReturnOrderProductsController {
}
src/main/java/com/ruoyi/purchase/controller/PurchaseReturnOrdersController.java
@@ -9,6 +9,7 @@
import com.ruoyi.purchase.dto.PurchaseReturnOrderDto;
import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper;
import com.ruoyi.purchase.service.PurchaseReturnOrdersService;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -22,6 +23,7 @@
 */
@RestController
@RequestMapping("/purchaseReturnOrders")
@Api(tags = "采购退货单")
public class PurchaseReturnOrdersController {
    @Autowired
    private PurchaseReturnOrdersService purchaseReturnOrdersService;
src/main/java/com/ruoyi/purchase/mapper/PurchaseReturnOrderProductsMapper.java
@@ -10,7 +10,7 @@
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-03-09 01:37:44
 * @since 2026-03-10 04:45:35
 */
@Mapper
public interface PurchaseReturnOrderProductsMapper extends BaseMapper<PurchaseReturnOrderProducts> {
src/main/java/com/ruoyi/purchase/pojo/PurchaseReturnOrderProducts.java
@@ -19,7 +19,7 @@
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-03-09 01:37:44
 * @since 2026-03-10 04:45:35
 */
@Getter
@Setter
@@ -38,6 +38,9 @@
    @ApiModelProperty("采购产品id")
    private Long salesLedgerProductId;
    @ApiModelProperty("退货数量")
    private BigDecimal returnQuantity;
    @ApiModelProperty("录入时间")
    @TableField(fill = FieldFill.INSERT)
    private LocalDateTime createTime;
@@ -45,7 +48,4 @@
    @ApiModelProperty("更新时间")
    @TableField(fill = FieldFill.INSERT_UPDATE)
    private LocalDateTime updateTime;
    @ApiModelProperty("退货数量")
    private BigDecimal num;
}
src/main/java/com/ruoyi/purchase/pojo/PurchaseReturnOrders.java
@@ -7,7 +7,10 @@
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
@@ -48,7 +51,8 @@
    private Integer projectPhase;
    @ApiModelProperty("制单日期")
    private LocalDateTime preparedAt;
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate preparedAt;
    @ApiModelProperty("制单人id")
    private Long preparedUserId;
src/main/java/com/ruoyi/purchase/service/PurchaseReturnOrderProductsService.java
@@ -9,7 +9,7 @@
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-03-09 01:37:44
 * @since 2026-03-10 04:45:35
 */
public interface PurchaseReturnOrderProductsService extends IService<PurchaseReturnOrderProducts> {
src/main/java/com/ruoyi/purchase/service/impl/PurchaseReturnOrderProductsServiceImpl.java
@@ -12,7 +12,7 @@
 * </p>
 *
 * @author èŠ¯å¯¼è½¯ä»¶ï¼ˆæ±Ÿè‹ï¼‰æœ‰é™å…¬å¸
 * @since 2026-03-09 01:37:44
 * @since 2026-03-10 04:45:35
 */
@Service
public class PurchaseReturnOrderProductsServiceImpl extends ServiceImpl<PurchaseReturnOrderProductsMapper, PurchaseReturnOrderProducts> implements PurchaseReturnOrderProductsService {
src/main/java/com/ruoyi/purchase/service/impl/PurchaseReturnOrdersServiceImpl.java
@@ -38,9 +38,11 @@
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(PurchaseReturnOrderDto purchaseReturnOrderDto) {
        this.save(purchaseReturnOrderDto);
        if (purchaseReturnOrderDto.getPurchaseReturnOrderProductsDtos().isEmpty()) {
        if (!purchaseReturnOrderDto.getPurchaseReturnOrderProductsDtos().isEmpty()) {
            for (PurchaseReturnOrderProductsDto purchaseReturnOrderProductsDto :purchaseReturnOrderDto.getPurchaseReturnOrderProductsDtos()) {
                purchaseReturnOrderProductsDto.setSalesLedgerProductId(purchaseReturnOrderProductsDto.getSalesLedgerProductId());
                purchaseReturnOrderProductsDto.setPurchaseReturnOrderId(purchaseReturnOrderDto.getId());
                purchaseReturnOrderProductsDto.setReturnQuantity(purchaseReturnOrderProductsDto.getReturnQuantity());
                purchaseReturnOrderProductsMapper.insert(purchaseReturnOrderProductsDto);
            }
        }
src/main/resources/mapper/procurementrecord/ReturnManagementMapper.xml
@@ -27,7 +27,7 @@
                and sl.salesman like concat('%',#{req.salesman},'%')
            </if>
            <if test="req.shippingNo != null and req.shippingNo != ''">
                and rm.shipping_no like concat('%',#{req.shippingNo},'%')
                and si.shipping_no like concat('%',#{req.shippingNo},'%')
            </if>
            <if test="req.projectStage != null and req.projectStage != ''">
                and rm.project_stage like concat('%',#{req.projectStage},'%')
src/main/resources/mapper/projectManagement/InfoMapper.xml
@@ -48,7 +48,14 @@
        department_name,order_date,order_amount,
        remark,attachment
    </sql>
    <select id="searchListInfo" resultType="com.ruoyi.projectManagement.vo.ListInfoVo">
    <resultMap id="ListInfoVoMap" type="com.ruoyi.projectManagement.vo.ListInfoVo">
        <result column="plan_stage"
                property="planStage"
                typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
    </resultMap>
    <select id="searchListInfo" resultMap="ListInfoVoMap">
        select t1.*, t2.name as project_management_plan_name,t3.title as projectManagementInfoParentName
        from project_management_info as t1
        left join project_management_plan as t2 on t1.project_management_plan_id = t2.id
src/main/resources/mapper/projectManagement/InfoStageMapper.xml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
<?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.projectManagement.mapper.InfoStageMapper">
    <resultMap id="BaseResultMap" type="com.ruoyi.projectManagement.pojo.InfoStage">
            <id property="id" column="id" jdbcType="BIGINT"/>
            <result property="projectManagementPlanNodeId" column="project_management_plan_node_id" jdbcType="BIGINT"/>
            <result property="projectManagementInfoId" column="project_management_info_id" jdbcType="BIGINT"/>
            <result property="description" column="description" jdbcType="VARCHAR"/>
            <result property="actualLeaderId" column="actually_leader_id" jdbcType="BIGINT"/>
            <result property="actualLeaderName" column="actually_leader_name" jdbcType="VARCHAR"/>
            <result property="estimatedDuration" column="estimated_duration" jdbcType="INTEGER"/>
            <result property="planStartTime" column="plan_start_time" jdbcType="DATE"/>
            <result property="planEndTime" column="plan_end_time" jdbcType="DATE"/>
            <result property="actualStartTime" column="actual_start_time" jdbcType="DATE"/>
            <result property="actualEndTime" column="actual_end_time" jdbcType="DATE"/>
            <result property="progress" column="progress" jdbcType="INTEGER"/>
            <result property="attachment" column="attachment" jdbcType="VARCHAR"/>
            <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
            <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
            <result property="isDelete" column="is_delete" jdbcType="INTEGER"/>
            <result property="createUser" column="create_user" jdbcType="BIGINT"/>
            <result property="updateUser" column="update_user" jdbcType="BIGINT"/>
            <result property="createUserName" column="create_user_name" jdbcType="VARCHAR"/>
            <result property="updateUserName" column="update_user_name" jdbcType="VARCHAR"/>
    </resultMap>
    <sql id="Base_Column_List">
        id,project_management_plan_node_id,project_management_info_id,
        description,actual_leader_id,actual_leader_name,
        estimated_duration,plan_start_time,plan_end_time,
        actual_start_time,actual_end_time,progress,attachment,
        create_time,update_time,is_delete,
        create_user,update_user,create_user_name,
        update_user_name
    </sql>
</mapper>
src/main/resources/mapper/purchase/PurchaseReturnOrderProductsMapper.xml
@@ -7,9 +7,9 @@
        <id column="id" property="id" />
        <result column="purchase_return_order_id" property="purchaseReturnOrderId" />
        <result column="sales_ledger_product_id" property="salesLedgerProductId" />
        <result column="return_quantity" property="returnQuantity" />
        <result column="create_time" property="createTime" />
        <result column="update_time" property="updateTime" />
        <result column="num" property="num" />
    </resultMap>
</mapper>
src/main/resources/mapper/safe/SafeTrainingMapper.xml
@@ -31,20 +31,21 @@
        <result column="tenant_id" property="tenantId" />
    </resultMap>
    <select id="pageSafeTraining" resultType="com.ruoyi.safe.dto.SafeTrainingDto">
        select st.*,
               su.nick_name assessmentUserName,
                count(std.id) nums
        from safe_training st
        left join safe_training_details std on std.safe_training_id = st.id
        left join sys_user su on st.assessment_user_id = su.user_id
        where  st.state = #{c.state}
        GROUP BY st.id
        SELECT
        st.*,
        su.nick_name AS assessmentUserName,
        COUNT(std.id) AS nums
        FROM safe_training st
        LEFT JOIN safe_training_details std ON std.safe_training_id = st.id
        LEFT JOIN sys_user su ON st.assessment_user_id = su.user_id
        WHERE st.state = #{c.state}
        <if test="c.placeTraining != null and c.placeTraining != ''">
            and st.place_training like concat('%', #{c.placeTraining}, '%')
            AND st.place_training LIKE CONCAT('%', #{c.placeTraining}, '%')
        </if>
        <if test="c.trainingDate != null ">
            and st.training_date = date_format(#{c.trainingDate},'%Y%m%d')
            AND DATE_FORMAT(st.training_date, '%Y%m%d') = DATE_FORMAT(#{c.trainingDate}, '%Y%m%d')
        </if>
        GROUP BY st.id, su.nick_name
    </select>
    <select id="getSafeTraining" resultType="com.ruoyi.safe.dto.SafeTrainingDto">
         select st.*,