fix(approve): 修复审批实例查询条件及流程控制问题
- 修复ApprovalInstanceMapper.xml中的business_type字段查询条件格式
- 将审批实例创建时间查询改为apply_time字段并调整日期范围查询逻辑
- 添加申请人姓名查询条件到审批实例查询
- 在审批实例更新前检查是否存在进行中的审批任务并抛出异常
- 在企业新闻服务中添加审批实例服务依赖注入
- 实现企业新闻编辑时重置审批流程功能
- 修复财务报销查询中的申请人代码查询条件
- 优化报销服务中的审批流程重置逻辑,仅在必要时删除审批实例
- 修复在职员工台账查询接口参数类型从实体类改为DTO
- 扩展员工台账查询支持部门ID筛选和合同开始时间筛选
- 在员工入职和更新时同步教育信息到员工基本信息
- 添加应急联系人信息查询到员工台账列表返回结果中
| | |
| | | import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeDept; |
| | | import com.ruoyi.collaborativeApproval.pojo.EnterpriseNewsScopeUser; |
| | | import com.ruoyi.common.enums.*; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.utils.OrderUtils; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.framework.security.LoginUser; |
| | |
| | | if (approvalInstanceDto == null || approvalInstanceDto.getId() == null) { |
| | | return false; |
| | | } |
| | | // 判断是否有正在进行的审批任务,有则不允许修改 |
| | | long pendingTaskCount = approvalTaskService.count( |
| | | Wrappers.<ApprovalTask>lambdaQuery() |
| | | .eq(ApprovalTask::getInstanceId, approvalInstanceDto.getId()) |
| | | .eq(ApprovalTask::getTaskStatus, "PENDING") |
| | | .eq(ApprovalTask::getDeleted, 0) |
| | | ); |
| | | if (pendingTaskCount > 0) { |
| | | throw new ServiceException("该审批单有正在进行的审批任务,不允许修改"); |
| | | } |
| | | boolean updated = this.updateById(approvalInstanceDto); |
| | | if (!updated) { |
| | | return false; |
| | |
| | | } |
| | | } |
| | | |
| | | resetApprovalFlow(existing.getApprovalInstanceId(), reimbursementId); |
| | | resetApprovalFlow(existing, reimbursementId); |
| | | if (BILL_STATUS_IN_APPROVAL.equals(billStatus)) { |
| | | reimbursement.setApprovalInstanceId(null); |
| | | startApproval(reimbursement, finReimbursementDto); |
| | |
| | | sysNoticeService.simpleNoticeByUser(title, message, approverIds, jumpPath); |
| | | } |
| | | |
| | | private void resetApprovalFlow(Long approvalInstanceId, Long reimbursementId) { |
| | | if (approvalInstanceId == null) { |
| | | private void resetApprovalFlow(FinReimbursement existing, Long reimbursementId) { |
| | | if (existing == null || existing.getApprovalInstanceId() == null) { |
| | | return; |
| | | } |
| | | Long approvalInstanceId = existing.getApprovalInstanceId(); |
| | | if (!"REJECTED".equals(existing.getBillStatus())) { |
| | | approvalInstanceService.delete(Collections.singletonList(approvalInstanceId)); |
| | | } |
| | | clearApprovalBinding(reimbursementId); |
| | | } |
| | | |
| | | private void clearApprovalBinding(Long reimbursementId) { |
| | | int rows = finReimbursementMapper.update( |
| | | null, |
| | | Wrappers.<FinReimbursement>lambdaUpdate() |
| | |
| | | import com.ruoyi.approve.pojo.ApprovalInstance; |
| | | import com.ruoyi.approve.pojo.ApprovalTask; |
| | | import com.ruoyi.approve.pojo.ApprovalTemplate; |
| | | import com.ruoyi.approve.service.ApprovalInstanceService; |
| | | import com.ruoyi.approve.utils.ApproveProcessConfigNodeUtils; |
| | | import com.ruoyi.basic.enums.ApplicationTypeEnum; |
| | | import com.ruoyi.basic.enums.RecordTypeEnum; |
| | |
| | | private final SysDeptMapper sysDeptMapper; |
| | | private final SysUserDeptMapper sysUserDeptMapper; |
| | | private final ApprovalInstanceMapper approvalInstanceMapper; |
| | | private final ApprovalInstanceService approvalInstanceService; |
| | | private final ApprovalTemplateMapper approvalTemplateMapper; |
| | | private final ApproveProcessConfigNodeUtils approveProcessConfigNodeUtils; |
| | | private final ISysNoticeService sysNoticeService; |
| | |
| | | saveReadScopeRelations(enterpriseNews.getId(), readScope, deptIds, userIds); |
| | | fileUtil.saveStorageAttachment(ApplicationTypeEnum.FILE, RecordTypeEnum.ENTERPRISE_NEWS, enterpriseNews.getId(), enterpriseNewsDto.getStorageBlobDTOs()); |
| | | if (STATUS_PENDING.equals(enterpriseNews.getStatus())) { |
| | | resetEnterpriseNewsApprovalFlow(oldEnterpriseNews); |
| | | startEnterpriseNewsApproval(enterpriseNews, enterpriseNewsDto); |
| | | } |
| | | return true; |
| | |
| | | .eq(EnterpriseNewsScopeUser::getNewsId, newsId)); |
| | | } |
| | | |
| | | private void resetEnterpriseNewsApprovalFlow(EnterpriseNews oldEnterpriseNews) { |
| | | if (oldEnterpriseNews == null || !STATUS_DRAFT.equals(oldEnterpriseNews.getStatus())) { |
| | | return; |
| | | } |
| | | List<Long> approvalInstanceIds = approvalInstanceMapper.selectList(new LambdaQueryWrapper<ApprovalInstance>() |
| | | .eq(ApprovalInstance::getBusinessId, oldEnterpriseNews.getId()) |
| | | .eq(ApprovalInstance::getBusinessType, TypeEnums.ENTERPRISE_NEWS_APPROVAL.getCode()) |
| | | .eq(ApprovalInstance::getDeleted, (byte) 0)) |
| | | .stream() |
| | | .map(ApprovalInstance::getId) |
| | | .filter(id -> id != null && id > 0) |
| | | .collect(Collectors.toList()); |
| | | if (StringUtils.isEmpty(approvalInstanceIds)) { |
| | | return; |
| | | } |
| | | approvalInstanceService.delete(approvalInstanceIds); |
| | | } |
| | | |
| | | private List<Long> distinctIds(List<Long> ids) { |
| | | if (StringUtils.isEmpty(ids)) { |
| | | return new ArrayList<>(); |
| | |
| | | * @return |
| | | */ |
| | | @GetMapping("/listPage") |
| | | public AjaxResult staffOnJobListPage(Page page, StaffOnJob staffOnJob) { |
| | | public AjaxResult staffOnJobListPage(Page page, StaffOnJobDto staffOnJob) { |
| | | return AjaxResult.success(staffOnJobService.staffOnJobListPage(page, staffOnJob)); |
| | | } |
| | | |
| | |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd") |
| | | private Date contractEndTime; |
| | | |
| | | private Long sysDeptId; |
| | | } |
| | |
| | | @Mapper |
| | | public interface StaffOnJobMapper extends BaseMapper<StaffOnJob> { |
| | | |
| | | IPage<StaffOnJobDto> staffOnJobListPage(Page page, @Param("staffOnJob") StaffOnJob staffOnJob); |
| | | IPage<StaffOnJobDto> staffOnJobListPage(Page page, @Param("staffOnJob") StaffOnJobDto staffOnJob); |
| | | |
| | | List<StaffOnJobDto> staffOnJobList(@Param("staffOnJob") StaffOnJob staffOnJob); |
| | | |
| | |
| | | public interface IStaffOnJobService extends IService<StaffOnJob> { |
| | | |
| | | |
| | | IPage<StaffOnJobDto> staffOnJobListPage(Page page, StaffOnJob staffOnJob); |
| | | IPage<StaffOnJobDto> staffOnJobListPage(Page page, StaffOnJobDto staffOnJob); |
| | | |
| | | StaffOnJobDto staffOnJobDetail(Long id); |
| | | |
| | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.common.exception.base.BaseException; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.dto.WordDateDto; |
| | | import com.ruoyi.project.system.domain.SysDept; |
| | |
| | | |
| | | //在职员工台账分页查询 |
| | | @Override |
| | | public IPage<StaffOnJobDto> staffOnJobListPage(Page page, StaffOnJob staffOnJob) { |
| | | return staffOnJobMapper.staffOnJobListPage(page,staffOnJob); |
| | | public IPage<StaffOnJobDto> staffOnJobListPage(Page page, StaffOnJobDto staffOnJob) { |
| | | IPage<StaffOnJobDto> staffOnJobDtoIPage = staffOnJobMapper.staffOnJobListPage(page, staffOnJob); |
| | | return staffOnJobDtoIPage; |
| | | } |
| | | |
| | | //新增入职 |
| | |
| | | } |
| | | |
| | | // 创建入职数据 |
| | | syncStudyInfoFromEducation(staffOnJobPrams); |
| | | staffOnJobPrams.setContractExpireTime(staffOnJobPrams.getContractEndTime()); |
| | | staffOnJobPrams.setStaffState(1); |
| | | staffOnJobMapper.insert(staffOnJobPrams); |
| | |
| | | // 绑定子表数据 |
| | | bingingStaffOnJobExtra(id,staffOnJobParams); |
| | | // 更新员工数据 |
| | | syncStudyInfoFromEducation(staffOnJobParams); |
| | | staffOnJobParams.setContractExpireTime(staffOnJobParams.getContractEndTime()); |
| | | return staffOnJobMapper.updateById(staffOnJobParams); |
| | | } |
| | |
| | | .forEach(staff -> staff.setStaffOnJobId(id)); // 赋值 |
| | | staffEducationService.saveBatch(staffOnJobPrams.getStaffEducationList()); |
| | | } |
| | | |
| | | // 新增工作经历 |
| | | if(CollectionUtils.isNotEmpty(staffOnJobPrams.getStaffWorkExperienceList())){ |
| | | staffOnJobPrams.getStaffWorkExperienceList().stream() |
| | |
| | | } |
| | | } |
| | | |
| | | private void syncStudyInfoFromEducation(StaffOnJob staffOnJobPrams) { |
| | | if (staffOnJobPrams == null || CollectionUtils.isEmpty(staffOnJobPrams.getStaffEducationList())) { |
| | | if (staffOnJobPrams != null) { |
| | | staffOnJobPrams.setFirstStudy("/"); |
| | | staffOnJobPrams.setProfession("/"); |
| | | } |
| | | return; |
| | | } |
| | | Optional<StaffEducation> matchedEducation = staffOnJobPrams.getStaffEducationList().stream() |
| | | .filter(Objects::nonNull) |
| | | .filter(education -> StringUtils.isNotEmpty(education.getMajor())) |
| | | .findFirst(); |
| | | if (matchedEducation.isPresent()) { |
| | | StaffEducation education = matchedEducation.get(); |
| | | staffOnJobPrams.setFirstStudy(education.getEducation()); |
| | | staffOnJobPrams.setProfession(education.getMajor()); |
| | | return; |
| | | } |
| | | staffOnJobPrams.setFirstStudy("/"); |
| | | staffOnJobPrams.setProfession("/"); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 通过员工id删除教育经历,工作经历,紧急联系人 |
| | |
| | | <if test="ew.businessType != null "> |
| | | and ai. business_type = #{ew.businessType} |
| | | </if> |
| | | <if test="ew.createTime != null"> |
| | | and ai.create_time between to_date(#{ew.createTimeStart}) and to_date(#{ew.createTimeEnd}) |
| | | <if test="ew.createTimeStart != null and ew.createTimeEnd != null"> |
| | | and ai.apply_time >= #{ew.createTimeStart} |
| | | and ai.apply_time <= #{ew.createTimeEnd} |
| | | </if> |
| | | <if test="ew.status != null"> |
| | | and ai.status = #{ew.status} |
| | | </if> |
| | | <if test="ew.applicantName != null and ew.applicantName !=''"> |
| | | and ai.applicant_name = #{ew.applicantName} |
| | | </if> |
| | | </where> |
| | | order by ai.id desc |
| | | </select> |
| | |
| | | <if test="ew.applicantName != null and ew.applicantName != ''"> |
| | | and applicant_name like concat('%',#{ew.applicantName},'%') |
| | | </if> |
| | | <if test="ew.createTimeStart != null and ew.createTimeStart !=''"> |
| | | and create_time between to_date(#{ew.createTimeStart}) and to_date(#{ew.createTimeEnd}) |
| | | <if test="ew.applicantCode != null and ew.applicantCode != ''"> |
| | | and applicant_code like concat('%',#{ew.applicantCode},'%') |
| | | </if> |
| | | <if test="ew.createTimeStart != null and ew.createTimeStart !='' and ew.createTimeEnd != null and ew.createTimeEnd != ''"> |
| | | and create_time >= #{ew.createTimeStart} |
| | | and create_time <= #{ew.createTimeEnd} |
| | | </if> |
| | | </where> |
| | | </select> |
| | |
| | | <mapper namespace="com.ruoyi.staff.mapper.StaffOnJobMapper"> |
| | | <select id="staffOnJobListPage" resultType="com.ruoyi.staff.dto.StaffOnJobDto"> |
| | | SELECT |
| | | staff_on_job.*, |
| | | sp.post_name as postName, |
| | | sd.dept_name as deptName, |
| | | MIN(t1.contract_start_time) as contract_start_time, -- 取最早合同开始时间 |
| | | MAX(t1.contract_end_time) as contract_end_time |
| | | staff_on_job.id, |
| | | staff_on_job.staff_state, |
| | | staff_on_job.staff_no, |
| | | staff_on_job.staff_name, |
| | | staff_on_job.sex, |
| | | staff_on_job.native_place, |
| | | staff_on_job.sys_post_id, |
| | | staff_on_job.sys_dept_id, |
| | | staff_on_job.role_id, |
| | | staff_on_job.adress, |
| | | staff_on_job.first_study, |
| | | staff_on_job.profession, |
| | | staff_on_job.identity_card, |
| | | staff_on_job.age, |
| | | staff_on_job.phone, |
| | | staff_on_job.contract_term, |
| | | staff_on_job.contract_expire_time, |
| | | staff_on_job.trial_end_date, |
| | | staff_on_job.trial_start_date, |
| | | staff_on_job.sign_date, |
| | | staff_on_job.salary_select, |
| | | staff_on_job.pro_salary, |
| | | staff_on_job.date_select, |
| | | staff_on_job.remark, |
| | | staff_on_job.create_time, |
| | | staff_on_job.create_user, |
| | | staff_on_job.update_time, |
| | | staff_on_job.update_user, |
| | | staff_on_job.tenant_id, |
| | | staff_on_job.alias, |
| | | staff_on_job.birth_date, |
| | | staff_on_job.nation, |
| | | staff_on_job.marital_status, |
| | | staff_on_job.pro_term, |
| | | staff_on_job.positive_date, |
| | | staff_on_job.basic_salary, |
| | | staff_on_job.dept_id, |
| | | sp.post_name AS post_name, |
| | | sd.dept_name AS dept_name, |
| | | MIN(t1.contract_start_time) AS contract_start_time, |
| | | MAX(t1.contract_end_time) AS contract_end_time, |
| | | ( |
| | | SELECT GROUP_CONCAT(sec.contact_name SEPARATOR ',') |
| | | FROM staff_emergency_contact sec |
| | | WHERE sec.staff_on_job_id = staff_on_job.id |
| | | ) AS emergency_contact, |
| | | ( |
| | | SELECT GROUP_CONCAT(sec.contact_phone SEPARATOR ',') |
| | | FROM staff_emergency_contact sec |
| | | WHERE sec.staff_on_job_id = staff_on_job.id |
| | | ) AS emergency_contact_phone |
| | | FROM staff_on_job |
| | | LEFT JOIN sys_post sp ON sp.post_id = staff_on_job.sys_post_id |
| | | LEFT JOIN sys_dept sd ON sd.dept_id = staff_on_job.sys_dept_id |
| | | LEFT JOIN staff_contract as t1 ON t1.staff_on_job_id = staff_on_job.id |
| | | WHERE 1=1 |
| | | LEFT JOIN staff_contract AS t1 ON t1.staff_on_job_id = staff_on_job.id |
| | | <where> |
| | | <if test="staffOnJob.staffState != null"> |
| | | AND staff_state = #{staffOnJob.staffState} |
| | | AND staff_on_job.staff_state = #{staffOnJob.staffState} |
| | | </if> |
| | | <if test="staffOnJob.staffName != null and staffOnJob.staffName != '' "> |
| | | AND staff_name LIKE CONCAT('%',#{staffOnJob.staffName},'%') |
| | | AND staff_on_job.staff_name LIKE CONCAT('%',#{staffOnJob.staffName},'%') |
| | | </if> |
| | | <if test="staffOnJob.entryDateStart != null and staffOnJob.entryDateStart != '' "> |
| | | AND contract_expire_time >= DATE_FORMAT(#{staffOnJob.entryDateStart},'%Y-%m-%d') |
| | | AND staff_on_job.contract_expire_time >= DATE_FORMAT(#{staffOnJob.entryDateStart},'%Y-%m-%d') |
| | | </if> |
| | | <if test="staffOnJob.entryDateEnd != null and staffOnJob.entryDateEnd != '' "> |
| | | AND contract_expire_time <= DATE_FORMAT(#{staffOnJob.entryDateEnd},'%Y-%m-%d') |
| | | AND staff_on_job.contract_expire_time <= DATE_FORMAT(#{staffOnJob.entryDateEnd},'%Y-%m-%d') |
| | | </if> |
| | | <if test="staffOnJob.sysDeptId != null"> |
| | | AND staff_on_job.sys_dept_id = #{staffOnJob.sysDeptId} |
| | | </if> |
| | | </where> |
| | | GROUP BY staff_on_job.id |
| | | <if test="staffOnJob.contractStartTime != null"> |
| | | HAVING MIN(t1.contract_start_time) = #{staffOnJob.contractStartTime} |
| | | </if> |
| | | </select> |
| | | <select id="staffOnJobList" resultType="com.ruoyi.staff.dto.StaffOnJobDto"> |
| | | SELECT |