Browse Source

Merge remote-tracking branch 'origin/dev' into dev

dzx 1 year ago
parent
commit
1f5299347b

+ 109 - 0
src/main/java/com/xjrsoft/module/job/ProcessNotProcessingAlertTask.java

@@ -0,0 +1,109 @@
+package com.xjrsoft.module.job;
+
+import cn.hutool.db.Db;
+import cn.hutool.db.Entity;
+import com.xjrsoft.common.constant.GlobalConstant;
+import com.xjrsoft.common.utils.DatasourceUtil;
+import com.xjrsoft.common.utils.DateUtils;
+import com.xjrsoft.module.evaluate.entity.EvaluateManage;
+import com.xjrsoft.module.oa.utils.SendMessageUtil;
+import com.xjrsoft.module.workflow.entity.WorkflowExtra;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import javax.sql.DataSource;
+import java.time.Duration;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
+
+/**
+ * 流程未处理提醒
+ */
+@Component
+@Slf4j
+public class ProcessNotProcessingAlertTask {
+    /**
+     * 流程未处理提醒
+     */
+    @Scheduled(cron = "0 0 14 * * ?")
+    public void alertProcessNotProcessing() {
+        System.out.printf("定时提醒流程未处理:%s", DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN));
+        DataSource datasource = DatasourceUtil.getDataSource(GlobalConstant.DEFAULT_DATASOURCE_KEY);
+        try {
+            Db use = Db.use(datasource);
+
+            //获取未结束流程的流程id
+            String listUncloseProcessIdSql = "SELECT DISTINCT process_id " +
+                    "FROM xjr_workflow_record w1 " +
+                    "WHERE NOT EXISTS ( " +
+                    "        SELECT 1 " +
+                    "        FROM xjr_workflow_record w2 " +
+                    "        WHERE w2.node_id = 'Event_140v10k' " +
+                    "          AND w1.process_id = w2.process_id " +
+                    "    );";
+            List<Entity> listUncloseProcessId = use.query(listUncloseProcessIdSql);
+
+            if(!listUncloseProcessId.isEmpty()){
+                //获取所有未完成流程的所有节点
+                String uncloseProcessIdStr = listUncloseProcessId.stream()
+                        .map(entity -> "'" + entity.getStr("process_id") + "'")
+                        .collect(Collectors.joining(","));
+                String listWorkflowExtraSql = "select * " +
+                        "from xjr_workflow_extra "
+                        + "where process_id in (" + uncloseProcessIdStr + ");";;
+                List<WorkflowExtra> workflowExtraList = use.query(listWorkflowExtraSql, WorkflowExtra.class);
+
+                List<String> uncloseProcessIdList = listUncloseProcessId.stream()
+                        .map(entity -> entity.getStr("process_id"))
+                        .collect(Collectors.toList());
+
+                //筛选出每个流程的最后一个节点的记录,需要的是有任务节点id的记录
+                List<WorkflowExtra> workflowExtraLastNodeList = new ArrayList<>();
+                LocalDateTime now = LocalDateTime.now();
+                for(String processId : uncloseProcessIdList){
+                    workflowExtraList.stream()
+                            .filter(e -> e.getProcessId().equals(processId))
+                            .max(Comparator.comparing(WorkflowExtra::getStartTime))
+                            .ifPresent(e -> {
+                                if((e.getEndTime() == null || e.getEndTime().toString().equals("")) && e.getApproveUserIds() != null && !e.getApproveUserIds().equals("")){
+                                    // 计算两个时间之间的差值
+                                    Duration duration = Duration.between(e.getStartTime(), now);
+                                    if (duration.toHours() > 24) {
+                                        //System.out.println("时间差大于24小时");
+                                        workflowExtraLastNodeList.add(e);
+                                    }
+                                }
+                            });
+                }
+
+                //对未结束的流程节点进行处理,通知下一个节点需要处理的人
+                Map<String, StringBuilder> message = new HashMap<>();
+                for (WorkflowExtra w : workflowExtraLastNodeList){
+                    String approveUserIds = w.getApproveUserIds();
+                    String[] aapproveUserIdArray = approveUserIds.trim().split(",");
+                    for (String str : aapproveUserIdArray){
+                        if(message.containsKey(str)){
+                            message.get(str).append(",").append(w.getProcessName());
+                        }else {
+                            message.put(str, new StringBuilder(w.getProcessName()));
+                        }
+                    }
+                }
+
+//                SendMessageUtil.sendWorkflowUnapprovedWx(message);
+
+                CompletableFuture.runAsync(() -> {
+                    SendMessageUtil.sendWorkflowUnapprovedWx(message);
+                });
+
+//                System.err.println(workflowExtraLastNodeList.size());
+//                System.err.println(workflowExtraLastNodeList.get(0));
+            }
+        } catch (Exception e) {
+            log.error(e.getMessage(), "定时提醒流程未处理");
+        }
+    }
+}

+ 66 - 0
src/main/java/com/xjrsoft/module/oa/utils/SendMessageUtil.java

@@ -25,6 +25,7 @@ import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
 
 /**
@@ -125,6 +126,71 @@ public class SendMessageUtil {
         }
     }
 
+    /**
+     * 发送工作流未审批微信消息
+     */
+    public static void sendWorkflowUnapprovedWx(Map<String, StringBuilder> message) {
+        IUserService userService = SpringUtil.getBean(IUserService.class);
+        RedisUtil redisUtil = SpringUtil.getBean(RedisUtil.class);
+
+        WeChatUtil weChatUtil = SpringUtil.getBean(WeChatUtil.class);
+
+        CommonPropertiesConfig cpConfig = SpringUtil.getBean(CommonPropertiesConfig.class);
+
+        //获取用户相关信息
+        List<User> userList = redisUtil.get(GlobalConstant.USER_CACHE_KEY, new TypeReference<List<User>>() {
+        });
+        //如果缓存中不存在用户信息,就直接去数据库查询,并保存到缓存中去
+        if (userList.size() == 0) {
+            userList = userService.list();
+            redisUtil.set(GlobalConstant.USER_CACHE_KEY, userList);
+        }
+
+        for (Map.Entry<String, StringBuilder> entry : message.entrySet()) {
+            String key = entry.getKey();
+            StringBuilder value = entry.getValue();
+//            System.out.println(key + "--" + value);
+            // 处理每个用户
+            User user = userList.stream().filter(u -> key.equals(u.getId())).findFirst().orElse(new User());
+            String openId = user.getOpenId();
+//            System.err.println(openId);
+            if (StrUtil.isEmpty(openId)) {
+                continue;
+            }
+
+            JSONObject data = new JSONObject();
+            // 任务名称
+            data.put("thing8", new JSONObject() {{
+                put("value", value.toString());
+            }});
+            // 事项名称
+            data.put("thing2", new JSONObject() {{
+                put("value", value.toString());
+            }});
+            // 申请人
+            data.put("thing6", new JSONObject() {{
+                put("value", "");
+            }});
+            // 时间
+            data.put("time3", new JSONObject() {{
+                put("value", LocalDateTimeUtil.format(LocalDateTime.now(), LocalDateTimeUtil.LOCAL_DATE_TIME_FORMAT));
+            }});
+
+            JSONObject object = new JSONObject();
+            object.put("touser", openId);
+            object.put("template_id", "sHsmz7LRj7HLd7GSTS3r2jCLvK-4Wp19iGzEvYK8n_I");
+//                object.put("miniprogram", new JSONObject() {{
+//                    put("appid", weChatUtil.getAppletAppKey());
+//                    put("pagepath", StrUtil.format("{}/xjrsoft/pages/workflow/approval?taskId={}&processId={}&type=todo",cpConfig.getDomainApp(), param.getTaskId(), param.getProcessId()));
+//                }});
+            object.put("url", StrUtil.format("{}/xjrsoft/pages/home/home",cpConfig.getDomainApp()));
+//            object.put("client_msg_id", param.getTaskId());
+            object.put("data", data);
+            Boolean isSuccess = weChatUtil.sendTemplateMessage(object);
+            //System.err.println(isSuccess);
+        }
+    }
+
     /**
      * 添加工作流审批消息
      */

+ 2 - 2
src/main/java/com/xjrsoft/module/personnel/controller/BasePersonnelLabourCapitalController.java

@@ -252,9 +252,9 @@ public class BasePersonnelLabourCapitalController {
     public ResponseEntity<byte[]> exportData(@Valid WeeklyDutySchedulePageDto dto, @RequestParam(defaultValue = "false") Boolean isTemplate) {
         List<BasePersonnelLabourCapital> list = basePersonnelLabourCapitalService.list();
         ByteArrayOutputStream bot = new ByteArrayOutputStream();
-        EasyExcel.write(bot, WeeklyDutyScheduleListVo.class).automaticMergeHead(false).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(list);
+        EasyExcel.write(bot, BasePersonnelLabourCapital.class).automaticMergeHead(false).excelType(ExcelTypeEnum.XLSX).sheet().doWrite(list);
 
-        return RT.fileStream(bot.toByteArray(), "WeeklyDutySchedule" + ExcelTypeEnum.XLSX.getValue());
+        return RT.fileStream(bot.toByteArray(), "BasePersonnelLabourCapital" + ExcelTypeEnum.XLSX.getValue());
     }
 
 }

+ 5 - 1
src/main/java/com/xjrsoft/module/student/controller/StudentManagerController.java

@@ -21,6 +21,7 @@ import com.xjrsoft.module.student.dto.AddBaseStudentUserDto;
 import com.xjrsoft.module.student.dto.BaseStudentUserPageDto;
 import com.xjrsoft.module.student.dto.UpdateBaseStudentUserDto;
 import com.xjrsoft.module.student.entity.BaseStudent;
+import com.xjrsoft.module.student.entity.BaseStudentFamilyMember;
 import com.xjrsoft.module.student.entity.BaseStudentSchoolRoll;
 import com.xjrsoft.module.student.entity.BaseStudentUser;
 import com.xjrsoft.module.student.service.IStudentManagerService;
@@ -80,7 +81,10 @@ public class StudentManagerController {
                         .leftJoin(BaseStudentSchoolRoll.class, BaseStudentSchoolRoll::getUserId, BaseStudentUser::getId)
                         .leftJoin("base_grade a on a.id = t2.grade_id")
                         .leftJoin("base_major_set b on b.id = t2.major_set_id")
-                        .leftJoin(BaseClass.class, BaseClass::getId, BaseStudentSchoolRoll::getClassId));
+                        .leftJoin(BaseClass.class, BaseClass::getId, BaseStudentSchoolRoll::getClassId)
+                        .select("c.`mobile` as guardianPhone")
+                        .select("c.`name` as guardianName")
+                        .leftJoin("base_student_family_member c on c.user_id = t2.user_id"));
         for (BaseStudentUserPageVo record : page.getRecords()) {
             record.setGenderCn(GenderDictionaryEnum.getValue(record.getGender()));
         }

+ 17 - 0
src/main/java/com/xjrsoft/module/student/vo/BaseStudentGraduatePageVo.java

@@ -46,6 +46,23 @@ public class BaseStudentGraduatePageVo {
     @ExcelProperty("学生姓名")
     @ApiModelProperty("学生姓名")
     private String name;
+
+    /**
+     * 性别
+     */
+    @ContentStyle(dataFormat = 49)
+    @ExcelProperty("性别")
+    @ApiModelProperty("性别")
+    private String gender;
+
+    /**
+     * 性别
+     */
+    @ContentStyle(dataFormat = 49)
+    @ExcelProperty("性别")
+    @ApiModelProperty("性别")
+    private String genderCn;
+
     /**
      * 联系方式
      */

+ 12 - 0
src/main/java/com/xjrsoft/module/student/vo/BaseStudentUserPageVo.java

@@ -108,4 +108,16 @@ public class BaseStudentUserPageVo {
      */
     @ApiModelProperty("学籍状态")
     private String archivesStatus;
+
+    /**
+     * 监护人姓名
+     */
+    @ApiModelProperty("监护人姓名")
+    private String guardianName;
+
+    /**
+     * 江湖人联系电话
+     */
+    @ApiModelProperty("监护人联系电话")
+    private String guardianPhone;
 }

+ 1 - 1
src/main/java/com/xjrsoft/module/textbook/service/impl/TextbookServiceImpl.java

@@ -709,7 +709,7 @@ public class TextbookServiceImpl extends MPJBaseServiceImpl<TextbookMapper, Text
                             subtotalColumn.add(rowIndex + vv.size() + 2, 1, 4);
                             BigDecimal subtotal = new BigDecimal("0");
                             for (TextbookClaimExportQueryVo tv : vv) {
-                                subtotal = subtotal.add(tv.getSubtotal());
+                                subtotal = subtotal.add(tv.getSubtotal()==null?new BigDecimal("0"):tv.getSubtotal());
                             }
                             BigDecimal finalSubtotal = subtotal;
                             vv.add(new TextbookClaimExportQueryVo(){{

+ 0 - 1
src/main/java/com/xjrsoft/module/workflow/controller/WorkflowExecuteController.java

@@ -51,7 +51,6 @@ public class WorkflowExecuteController {
         return R.ok(workflowExecuteService.getStartProcessInfo(schemaId));
     }
 
-
     @GetMapping("/approve-process-info")
     @ApiOperation(value = "审批流程所需要的信息")
     public R approveProcessInfo(@RequestParam String taskId) {

+ 1 - 0
src/main/resources/mapper/student/BaseStudentGraduateMapper.xml

@@ -53,6 +53,7 @@
         <if test="dto.status != null">
             and t5.status = #{dto.status}
         </if>
+
     </select>
 
     <select id="getInfoById" resultType="com.xjrsoft.module.student.vo.BaseStudentGraduateVo">

+ 2 - 1
src/main/resources/mapper/textbook/TextbookMapper.xml

@@ -268,9 +268,10 @@
                 sum(t2.stock) as num,
                 sum(t1.issue_number) as claimNum
             from wf_textbook_claim t
-                left join wf_textbook_claim_item t1 on t1.wf_textbook_claim_id = t.id
+                inner join wf_textbook_claim_item t1 on t1.wf_textbook_claim_id = t.id
                 left join textbook t2 on t2.id = t1.textbook_id
             where claim_type = 'claim_student'
+                AND t.status = 1
             <if test="dto.baseSemesterId != null and dto.baseSemesterId > 0">
                 and t.base_semester_id = #{dto.baseSemesterId}
             </if>

+ 107 - 0
src/test/java/com/xjrsoft/module/job/ProcessNotProcessingAlertTaskTest.java

@@ -0,0 +1,107 @@
+package com.xjrsoft.module.job;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.db.Db;
+import cn.hutool.db.Entity;
+import com.xjrsoft.common.constant.GlobalConstant;
+import com.xjrsoft.common.utils.DatasourceUtil;
+import com.xjrsoft.common.utils.DateUtils;
+import com.xjrsoft.module.oa.service.INewsService;
+import com.xjrsoft.module.oa.utils.SendMessageUtil;
+import com.xjrsoft.module.workflow.constant.WorkflowConstant;
+import com.xjrsoft.module.workflow.entity.WorkflowExtra;
+import com.xjrsoft.module.workflow.vo.MyProcessPageVo;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import javax.sql.DataSource;
+import java.time.Duration;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
+
+import static org.junit.jupiter.api.Assertions.*;
+@SpringBootTest
+class ProcessNotProcessingAlertTaskTest {
+
+    @Test
+    void alertProcessNotProcessing() {
+        DataSource datasource = DatasourceUtil.getDataSource(GlobalConstant.DEFAULT_DATASOURCE_KEY);
+        try {
+            Db use = Db.use(datasource);
+
+            //获取未结束流程的流程id
+            String listUncloseProcessIdSql = "SELECT DISTINCT process_id " +
+                    "FROM xjr_workflow_record w1 " +
+                    "WHERE NOT EXISTS ( " +
+                    "        SELECT 1 " +
+                    "        FROM xjr_workflow_record w2 " +
+                    "        WHERE w2.node_id = 'Event_140v10k' " +
+                    "          AND w1.process_id = w2.process_id " +
+                    "    );";
+            List<Entity> listUncloseProcessId = use.query(listUncloseProcessIdSql);
+
+            if(!listUncloseProcessId.isEmpty()){
+                //获取所有未完成流程的所有节点
+                String uncloseProcessIdStr = listUncloseProcessId.stream()
+                        .map(entity -> "'" + entity.getStr("process_id") + "'")
+                        .collect(Collectors.joining(","));
+                String listWorkflowExtraSql = "select * " +
+                        "from xjr_workflow_extra "
+                        + "where process_id in (" + uncloseProcessIdStr + ");";;
+                List<WorkflowExtra> workflowExtraList = use.query(listWorkflowExtraSql, WorkflowExtra.class);
+
+                List<String> uncloseProcessIdList = listUncloseProcessId.stream()
+                        .map(entity -> entity.getStr("process_id"))
+                        .collect(Collectors.toList());
+
+                //筛选出每个流程的最后一个节点的记录,需要的是有任务节点id的记录
+                List<WorkflowExtra> workflowExtraLastNodeList = new ArrayList<>();
+                LocalDateTime now = LocalDateTime.now();
+                for(String processId : uncloseProcessIdList){
+                    workflowExtraList.stream()
+                            .filter(e -> e.getProcessId().equals(processId))
+                            .max(Comparator.comparing(WorkflowExtra::getStartTime))
+                            .ifPresent(e -> {
+                                if((e.getEndTime() == null || e.getEndTime().toString().equals("")) && e.getApproveUserIds() != null && !e.getApproveUserIds().equals("")){
+                                    // 计算两个时间之间的差值
+                                    Duration duration = Duration.between(e.getStartTime(), now);
+                                    if (duration.toHours() > 24) {
+                                        System.out.println("时间差大于24小时");
+                                        workflowExtraLastNodeList.add(e);
+                                    }
+                                }
+                            });
+                }
+
+                //对未结束的流程节点进行处理,通知下一个节点需要处理的人
+                Map<String, StringBuilder> message = new HashMap<>();
+                for (WorkflowExtra w : workflowExtraLastNodeList){
+                    String approveUserIds = w.getApproveUserIds();
+                    String[] aapproveUserIdArray = approveUserIds.trim().split(",");
+                    for (String str : aapproveUserIdArray){
+                        System.err.println(str);
+                        if(message.containsKey(str)){
+                            message.get(str).append(",").append(w.getProcessName());
+                        }else {
+                            message.put(str, new StringBuilder(w.getProcessName()));
+                        }
+                    }
+                }
+
+//                SendMessageUtil.sendWorkflowUnapprovedWx(message);
+
+                CompletableFuture.runAsync(() -> {
+                    SendMessageUtil.sendWorkflowUnapprovedWx(message);
+                });
+
+//                System.err.println(workflowExtraLastNodeList.size());
+//                System.err.println(workflowExtraLastNodeList.get(0));
+            }
+        } catch (Exception e) {
+            System.err.println(e.getMessage()+"定时提醒流程未处理");
+        }
+    }
+}