QuYueTing 2 дней назад
Родитель
Сommit
8de1e136b0
13 измененных файлов с 425 добавлено и 165 удалено
  1. 128 151
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectApprovalController.java
  2. 4 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java
  3. 5 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserDingdingTimeController.java
  4. 6 4
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java
  5. 173 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WxCorpInfoController.java
  6. 3 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/UserDingdingTime.java
  7. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/WxCorpInfoService.java
  8. 1 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DingDingServiceImpl.java
  9. 41 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectApprovalServiceImpl.java
  10. 3 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  11. 52 5
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java
  12. 5 2
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/application.yml
  13. 2 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserDingdingTimeMapper.xml

+ 128 - 151
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectApprovalController.java

@@ -5,14 +5,18 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.google.gson.JsonObject;
 import com.management.platform.entity.*;
+import com.management.platform.mapper.InformationMapper;
+import com.management.platform.mapper.ProjectLevelMapper;
 import com.management.platform.mapper.ProjectMapper;
 import com.management.platform.mapper.UserMapper;
 import com.management.platform.service.*;
 import com.management.platform.service.impl.WxCorpInfoServiceImpl;
 import com.management.platform.util.HttpRespMsg;
 import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.RequestBody;
@@ -66,6 +70,10 @@ public class ProjectApprovalController {
     private WxCorpInfoService wxCorpInfoService;
     @Resource
     private WxCorpTemplateService wxCorpTemplateService;
+    @Autowired
+    private ProjectLevelMapper projectLevelMapper;
+    @Resource
+    private InformationMapper informationMapper;
 
     /**
      * 分页获取项目列表
@@ -82,9 +90,10 @@ public class ProjectApprovalController {
     @Transactional(rollbackFor = Exception.class)
     public HttpRespMsg editProjectApproval(@RequestBody ProjectApproval projectApproval) throws Exception {
         HttpRespMsg msg=new HttpRespMsg();
-        String[] arr=new String[]{"正常","紧急","重要","重要且紧急","低风险","中风险","高风险"};
+//        String[] arr=new String[]{"正常","紧急","重要","重要且紧急","低风险","中风险","高风险"};
         User user = userMapper.selectById(request.getHeader("token"));
         Integer companyId = user.getCompanyId();
+        List<ProjectLevel> levelList = projectLevelMapper.selectList(new QueryWrapper<ProjectLevel>().eq("company_id", companyId));
         WxCorpInfo wxCorpInfo = wxCorpInfoService.getOne(new LambdaQueryWrapper<WxCorpInfo>().eq(WxCorpInfo::getCompanyId, companyId));
         List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
         List<ProjectCategory> categoryList = projectCategoryService.list(new LambdaQueryWrapper<ProjectCategory>().eq(ProjectCategory::getCompanyId, companyId));
@@ -198,84 +207,107 @@ public class ProjectApprovalController {
         }
         if(projectApproval.getStatus()!=1){
             if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
-                //更新审核人 发送到企业微信完成审核动作
-                String detail = wxCorpInfoService.getTemplateDetail(companyId);
-                if(detail!=null&&!StringUtils.isEmpty(detail)){
-                    DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
-                    JSONObject resultOb = JSONObject.parseObject(detail);
-                    JSONObject template_content = resultOb.getJSONObject("template_content");
-                    JSONArray controls = template_content.getJSONArray("controls");
-                    Map<String,Object> templateMap=new HashMap<>();
-                    WxCorpTemplate template = wxCorpTemplateService.getById(companyId);
-                    JSONObject requestData=new JSONObject();
-                    requestData.put("template_id",template.getTemplateId());
-                    requestData.put("creator_userid",user.getCorpwxUserid());
-                    //审核模式  0-通过接口指定审批人、抄送人(此时approver、notifyer等参数可用);1-使用此模板在管理后台设置的审批流程(需要保证审批流程中没有“申请人自选”节点),支持条件审批
-                    requestData.put("use_template_approver",1);
-                    JSONObject apply_data=new JSONObject();
-                    JSONArray contents=new JSONArray();
-                    for (int i = 0; i < controls.size(); i++) {
-                        JSONObject item = controls.getJSONObject(i);
-                        JSONObject property = item.getJSONObject("property");
-                        //控件id指定到指定控件
-                        String templateId = property.getString("id");
-                        //控件名称 这里为了统一工时管家格式 限制企业需要用到我们提供的名称(项目编号 项目名称 项目分类 项目类型 项目经理 级别 合同金额 计划开始日期 计划结束日期)
-                        JSONArray titleArray = property.getJSONArray("title");
-                        //控件类型 在这里统一用Text  Text-文本;Textarea-多行文本;Number-数字;Money-金额;Date-日期/日期+时间;Selector-单选/多选;Contact-成员/部门;Tips-说明文字;File-附件;Table-明细;Attendance-假勤控件;Vacation-请假控件;Location-位置;RelatedApproval-关联审批单;Formula-公式;DateRange-时长;BankAccount-收款账户
-                        String control = property.getString("control");
-                        //是否必填
-                        String require = property.getString("require");
-                        //是否打印
-                        String un_print = property.getString("un_print");
-                        JSONObject content=new JSONObject();
-                        content.put("control",control);
-                        content.put("id",templateId);
-                        JSONObject value=new JSONObject();
-                        JSONObject titleOb = titleArray.getJSONObject(0);
-                        switch (titleOb.getString("text")){
-                            case "项目编号":
-                                value.put("text",projectApproval.getProjectCode()==null?"":projectApproval.getProjectCode());
-                                break;
-                            case "项目名称":
-                                value.put("text",projectApproval.getProjectName());
-                                break;
-                            case "项目分类":
-                                value.put("text",projectApproval.getCategoryName()==null?"":projectApproval.getCategoryName());
-                                break;
-                            case "项目类型":
-                                value.put("text",projectApproval.getIsPublic()==0?"正式项目":"非项目");
-                                break;
-                            case "项目经理":
-                                value.put("text",projectApproval.getInchargerName()==null?"":("$userName="+projectApproval.getInchargerName()+"$"));
-                                break;
-                            case "级别":
-                                value.put("text",arr[projectApproval.getLevel()-1]);
-                                break;
-                            case "合同金额":
-                                value.put("text",projectApproval.getContractAmount()==null?String.valueOf(0):String.valueOf(projectApproval.getContractAmount()));
-                                break;
-                            case "计划开始日期":
-                                value.put("text",projectApproval.getPlanStartDate()==null?"":df.format(projectApproval.getPlanStartDate()));
-                                break;
-                            case "计划结束日期":
-                                value.put("text",projectApproval.getPlanEndDate()==null?"":df.format(projectApproval.getPlanEndDate()));
-                                break;
+                //发送企业微信通知消息
+                if (projectApproval.getProjectApprovalCheckList().size() > 0) {
+                    //取第一个审核人,发送消息通知
+                    String checkerId = projectApproval.getProjectApprovalCheckList().get(0).getUserId();
+                    User checker = userMapper.selectById(checkerId);
+                    if (checker != null) {
+                        StringBuilder sb=new StringBuilder();
+                        sb.append("立项审批,项目["+projectApproval.getProjectName()+"]待您审核");
+                        String corpwxUserid = checker.getCorpwxUserid();
+                        if (corpwxUserid != null) {
+                            wxCorpInfoService.sendWXCorpMsg(wxCorpInfo, corpwxUserid,sb.toString(), "projectApproval", WxCorpInfoServiceImpl.TEXT_CARD_MSG_PROJECT_CREATE);
                         }
-                        content.put("value",value);
-                        contents.add(content);
+                        //系统消息
+                        Information information=new Information();
+                        information.setType(12);
+                        information.setUserId(checkerId);
+                        information.setTime(LocalDateTime.now());
+                        information.setContent("projectApproval");
+                        information.setMsg("立项审批,项目["+projectApproval.getProjectName()+"]待您审核");
+                        informationMapper.insert(information);
                     }
-                    apply_data.put("contents",contents);
-                    requestData.put("apply_data",apply_data);
-                    requestData.put("approver",new JSONArray());
-                    requestData.put("summary_list",new JSONArray());
-                    System.out.println("===============>发送到企业微信的数据"+requestData);
-                    //发送到企业微信
-                    String sp_no = wxCorpInfoService.applyEvent(request, requestData);
-                    projectApproval.setWxCorpSpNo(sp_no);
-                    projectApprovalService.updateById(projectApproval);
-                }else {
-                    throw  new Exception("企业暂未同步服务商审批模板,推送企业微信审批失败,请联系服务商!");
                 }
+
+                //更新审核人 发送到企业微信完成审核动作
+//                String detail = wxCorpInfoService.getTemplateDetail(companyId);
+//                if(detail!=null&&!StringUtils.isEmpty(detail)){
+//                    DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
+//                    JSONObject resultOb = JSONObject.parseObject(detail);
+//                    JSONObject template_content = resultOb.getJSONObject("template_content");
+//                    JSONArray controls = template_content.getJSONArray("controls");
+//                    Map<String,Object> templateMap=new HashMap<>();
+//                    WxCorpTemplate template = wxCorpTemplateService.getById(companyId);
+//                    JSONObject requestData=new JSONObject();
+//                    requestData.put("template_id",template.getTemplateId());
+//                    requestData.put("creator_userid",user.getCorpwxUserid());
+//                    //审核模式  0-通过接口指定审批人、抄送人(此时approver、notifyer等参数可用);1-使用此模板在管理后台设置的审批流程(需要保证审批流程中没有“申请人自选”节点),支持条件审批
+//                    requestData.put("use_template_approver",1);
+//                    JSONObject apply_data=new JSONObject();
+//                    JSONArray contents=new JSONArray();
+//                    for (int i = 0; i < controls.size(); i++) {
+//                        JSONObject item = controls.getJSONObject(i);
+//                        JSONObject property = item.getJSONObject("property");
+//                        //控件id指定到指定控件
+//                        String templateId = property.getString("id");
+//                        //控件名称 这里为了统一工时管家格式 限制企业需要用到我们提供的名称(项目编号 项目名称 项目分类 项目类型 项目经理 级别 合同金额 计划开始日期 计划结束日期)
+//                        JSONArray titleArray = property.getJSONArray("title");
+//                        //控件类型 在这里统一用Text  Text-文本;Textarea-多行文本;Number-数字;Money-金额;Date-日期/日期+时间;Selector-单选/多选;Contact-成员/部门;Tips-说明文字;File-附件;Table-明细;Attendance-假勤控件;Vacation-请假控件;Location-位置;RelatedApproval-关联审批单;Formula-公式;DateRange-时长;BankAccount-收款账户
+//                        String control = property.getString("control");
+//                        //是否必填
+//                        String require = property.getString("require");
+//                        //是否打印
+//                        String un_print = property.getString("un_print");
+//                        JSONObject content=new JSONObject();
+//                        content.put("control",control);
+//                        content.put("id",templateId);
+//                        JSONObject value=new JSONObject();
+//                        JSONObject titleOb = titleArray.getJSONObject(0);
+//                        switch (titleOb.getString("text")){
+//                            case "项目编号":
+//                                value.put("text",projectApproval.getProjectCode()==null?"":projectApproval.getProjectCode());
+//                                break;
+//                            case "项目名称":
+//                                value.put("text",projectApproval.getProjectName());
+//                                break;
+//                            case "项目分类":
+//                                value.put("text",projectApproval.getCategoryName()==null?"":projectApproval.getCategoryName());
+//                                break;
+//                            case "项目类型":
+//                                value.put("text",projectApproval.getIsPublic()==0?"正式项目":"非项目");
+//                                break;
+//                            case "项目经理":
+//                                value.put("text",projectApproval.getInchargerName()==null?"":("$userName="+projectApproval.getInchargerName()+"$"));
+//                                break;
+//                            case "级别":
+//                                value.put("text",levelList.stream().filter(p->p.getId().equals(projectApproval.getLevel())).findFirst().get().getProjectLevelName());
+//                                break;
+//                            case "合同金额":
+//                                value.put("text",projectApproval.getContractAmount()==null?String.valueOf(0):String.valueOf(projectApproval.getContractAmount()));
+//                                break;
+//                            case "计划开始日期":
+//                                value.put("text",projectApproval.getPlanStartDate()==null?"":df.format(projectApproval.getPlanStartDate()));
+//                                break;
+//                            case "计划结束日期":
+//                                value.put("text",projectApproval.getPlanEndDate()==null?"":df.format(projectApproval.getPlanEndDate()));
+//                                break;
+//                        }
+//                        content.put("value",value);
+//                        contents.add(content);
+//                    }
+//                    apply_data.put("contents",contents);
+//                    requestData.put("apply_data",apply_data);
+//                    requestData.put("approver",new JSONArray());
+//                    requestData.put("summary_list",new JSONArray());
+//                    System.out.println("===============>发送到企业微信的数据"+requestData);
+//                    //发送到企业微信
+//                    String sp_no = wxCorpInfoService.applyEvent(request, requestData);
+//                    projectApproval.setWxCorpSpNo(sp_no);
+//                    projectApprovalService.updateById(projectApproval);
+//                }else {
+//                    throw  new Exception("企业暂未同步服务商审批模板,推送企业微信审批失败,请联系服务商!");
+//                }
             }
         }
         return msg;
@@ -285,9 +317,10 @@ public class ProjectApprovalController {
     @Transactional(rollbackFor = Exception.class)
     public HttpRespMsg tempSave(@RequestBody ProjectApproval projectApproval) throws Exception{
         HttpRespMsg msg=new HttpRespMsg();
-        String[] arr=new String[]{"正常","紧急","重要","重要且紧急","低风险","中风险","高风险"};
+//        String[] arr=new String[]{"正常","紧急","重要","重要且紧急","低风险","中风险","高风险"};
         User user = userMapper.selectById(request.getHeader("token"));
         Integer companyId = user.getCompanyId();
+
         WxCorpInfo wxCorpInfo = wxCorpInfoService.getOne(new LambdaQueryWrapper<WxCorpInfo>().eq(WxCorpInfo::getCompanyId, companyId));
         List<User> userList = userMapper.selectList(new LambdaQueryWrapper<User>().eq(User::getCompanyId, companyId));
         List<ProjectCategory> categoryList = projectCategoryService.list(new LambdaQueryWrapper<ProjectCategory>().eq(ProjectCategory::getCompanyId, companyId));
@@ -401,82 +434,26 @@ public class ProjectApprovalController {
         if(projectApproval.getStatus()==-1){
             if(wxCorpInfo!=null&&wxCorpInfo.getSaasSyncContact()==1){
                 //更新审核人 发送到企业微信完成审核动作
-                String detail = wxCorpInfoService.getTemplateDetail(companyId);
-                if(detail!=null&&!StringUtils.isEmpty(detail)){
-                    DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
-                    JSONObject resultOb = JSONObject.parseObject(detail);
-                    JSONObject template_content = resultOb.getJSONObject("template_content");
-                    JSONArray controls = template_content.getJSONArray("controls");
-                    Map<String,Object> templateMap=new HashMap<>();
-                    WxCorpTemplate template = wxCorpTemplateService.getById(companyId);
-                    JSONObject requestData=new JSONObject();
-                    requestData.put("template_id",template.getTemplateId());
-                    requestData.put("creator_userid",user.getCorpwxUserid());
-                    //审核模式  0-通过接口指定审批人、抄送人(此时approver、notifyer等参数可用);1-使用此模板在管理后台设置的审批流程(需要保证审批流程中没有“申请人自选”节点),支持条件审批
-                    requestData.put("use_template_approver",1);
-                    JSONObject apply_data=new JSONObject();
-                    JSONArray contents=new JSONArray();
-                    for (int i = 0; i < controls.size(); i++) {
-                        JSONObject item = controls.getJSONObject(i);
-                        JSONObject property = item.getJSONObject("property");
-                        //控件id指定到指定控件
-                        String templateId = property.getString("id");
-                        //控件名称 这里为了统一工时管家格式 限制企业需要用到我们提供的名称(项目编号 项目名称 项目分类 项目类型 项目经理 级别 合同金额 计划开始日期 计划结束日期)
-                        JSONArray titleArray = property.getJSONArray("title");
-                        //控件类型 在这里统一用Text  Text-文本;Textarea-多行文本;Number-数字;Money-金额;Date-日期/日期+时间;Selector-单选/多选;Contact-成员/部门;Tips-说明文字;File-附件;Table-明细;Attendance-假勤控件;Vacation-请假控件;Location-位置;RelatedApproval-关联审批单;Formula-公式;DateRange-时长;BankAccount-收款账户
-                        String control = property.getString("control");
-                        //是否必填
-                        String require = property.getString("require");
-                        //是否打印
-                        String un_print = property.getString("un_print");
-                        JSONObject content=new JSONObject();
-                        content.put("control",control);
-                        content.put("id",templateId);
-                        JSONObject value=new JSONObject();
-                        JSONObject titleOb = titleArray.getJSONObject(0);
-                        switch (titleOb.getString("text")){
-                            case "项目编号":
-                                value.put("text",projectApproval.getProjectCode()==null?"":projectApproval.getProjectCode());
-                                break;
-                            case "项目名称":
-                                value.put("text",projectApproval.getProjectName());
-                                break;
-                            case "项目分类":
-                                value.put("text",projectApproval.getCategoryName()==null?"":projectApproval.getCategoryName());
-                                break;
-                            case "项目类型":
-                                value.put("text",projectApproval.getIsPublic()==0?"正式项目":"非项目");
-                                break;
-                            case "项目经理":
-                                value.put("text",projectApproval.getInchargerName()==null?"":("$userName="+projectApproval.getInchargerName()+"$"));
-                                break;
-                            case "级别":
-                                value.put("text",arr[projectApproval.getLevel()-1]);
-                                break;
-                            case "合同金额":
-                                value.put("text",projectApproval.getContractAmount()==null?String.valueOf(0):String.valueOf(projectApproval.getContractAmount()));
-                                break;
-                            case "计划开始日期":
-                                value.put("text",projectApproval.getPlanStartDate()==null?"":df.format(projectApproval.getPlanStartDate()));
-                                break;
-                            case "计划结束日期":
-                                value.put("text",projectApproval.getPlanEndDate()==null?"":df.format(projectApproval.getPlanEndDate()));
-                                break;
+                if (projectApproval.getProjectApprovalCheckList().size() > 0) {
+                    //取第一个审核人,发送消息通知
+                    String checkerId = projectApproval.getProjectApprovalCheckList().get(0).getUserId();
+                    User checker = userMapper.selectById(checkerId);
+                    if (checker != null) {
+                        StringBuilder sb=new StringBuilder();
+                        sb.append("立项审批,项目["+projectApproval.getProjectName()+"]待您审核");
+                        String corpwxUserid = checker.getCorpwxUserid();
+                        if (corpwxUserid != null) {
+                            wxCorpInfoService.sendWXCorpMsg(wxCorpInfo, corpwxUserid,sb.toString(), "projectApproval", WxCorpInfoServiceImpl.TEXT_CARD_MSG_PROJECT_CREATE);
                         }
-                        content.put("value",value);
-                        contents.add(content);
+                        //系统消息
+                        Information information=new Information();
+                        information.setType(12);
+                        information.setUserId(checkerId);
+                        information.setTime(LocalDateTime.now());
+                        information.setContent("projectApproval");
+                        information.setMsg("立项审批,项目["+projectApproval.getProjectName()+"]待您审核");
+                        informationMapper.insert(information);
                     }
-                    apply_data.put("contents",contents);
-                    requestData.put("apply_data",apply_data);
-                    requestData.put("approver",new JSONArray());
-                    requestData.put("summary_list",new JSONArray());
-                    System.out.println("===============>发送到企业微信的数据"+requestData);
-                    //发送到企业微信
-                    String sp_no = wxCorpInfoService.applyEvent(request, requestData);
-                    projectApproval.setWxCorpSpNo(sp_no);
-                    projectApprovalService.updateById(projectApproval);
-                }else {
-                    throw  new Exception("企业暂未同步服务商审批模板,推送企业微信审批失败,请联系服务商!");
                 }
             }
         }

+ 4 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java

@@ -938,7 +938,10 @@ public class ReportController {
                 boolean isForbidden = false;
                 boolean isLastMonthFail = false;
                 //获取设置的当月几号作为填报的截止日期
-                LocalDate curMonthDeadline = LocalDate.now().withDayOfMonth(compTimeType.getFillMonthOnDay());
+                LocalDate deadline = LocalDate.now();
+                //获取当月的最后一天
+                int lastDay = compTimeType.getFillMonthOnDay() > deadline.lengthOfMonth() ? deadline.lengthOfMonth() : compTimeType.getFillMonthOnDay();
+                LocalDate curMonthDeadline = LocalDate.now().withDayOfMonth(lastDay);
                 if (createDate.length > 0) {
                     String createDateOne = createDate[0];
                     if (fillMonths == 2) {

+ 5 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/UserDingdingTimeController.java

@@ -4,12 +4,15 @@ package com.management.platform.controller;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.management.platform.entity.CompanyDingding;
+import com.management.platform.entity.LeaveSheet;
 import com.management.platform.entity.User;
 import com.management.platform.entity.UserDingdingTime;
 import com.management.platform.mapper.CompanyDingdingMapper;
+import com.management.platform.mapper.LeaveSheetMapper;
 import com.management.platform.mapper.UserDingdingTimeMapper;
 import com.management.platform.mapper.UserMapper;
 import com.management.platform.util.HttpRespMsg;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.RequestMapping;
 
 import org.springframework.web.bind.annotation.RequestParam;
@@ -36,6 +39,8 @@ public class UserDingdingTimeController {
     private UserMapper userMapper;
     @Resource
     private CompanyDingdingMapper companyDingdingMapper;
+    @Autowired
+    private LeaveSheetMapper leaveSheetMapper;
 
     @RequestMapping("/getUserCardTime")
     public HttpRespMsg getUserCardTime(String userId, String date) {

+ 6 - 4
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java

@@ -4094,18 +4094,20 @@ public class WeiXinCorpController {
 
 
     @RequestMapping("/testGetApprovalList")
-    public HttpRespMsg testGetApprovalList(String startDate,String endDate) throws Exception {
+    public HttpRespMsg testGetApprovalList(Integer companyId, String startDate,String endDate) throws Exception {
         HttpRespMsg msg=new HttpRespMsg();
         JSONArray jsonArrayFilter = new JSONArray();
         JSONObject filter1 = new JSONObject();
         filter1.put("key","record_type");
-        filter1.put("value",1);
+        filter1.put("value",5);
         jsonArrayFilter.add(filter1);
         JSONObject filter2 = new JSONObject();
-        filter2.put("key","sp_status ");
+        filter2.put("key","sp_status");
         filter2.put("value",2);
         jsonArrayFilter.add(filter2);
-        JSONArray approvalInfo = wxCorpInfoService.getApprovalInfo(7, startDate, endDate, "", jsonArrayFilter);
+        JSONArray approvalInfo = wxCorpInfoService.getApprovalInfo(companyId, startDate, endDate, "", jsonArrayFilter);
+        //TODO: 获取审批单详情
+
         msg.setData(approvalInfo.toArray());
         return msg;
     }

+ 173 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WxCorpInfoController.java

@@ -19,6 +19,10 @@ import org.springframework.web.bind.annotation.RestController;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
 import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -97,5 +101,174 @@ public class WxCorpInfoController {
     public HttpRespMsg batchTransferLicense(HttpServletRequest request,String handoverId,String takeoverId) throws Exception {
         return wxCorpInfoService.batchTransferLicense(request,handoverId,takeoverId);
     }
+
+    /**
+     * 获取加班审批单号列表及详情
+     * 参考getUserCheckInData接口实现
+     * 根据企业微信官方文档:
+     * - 获取审批单号:https://developer.work.weixin.qq.com/document/path/94603
+     * - 获取审批详情:https://developer.work.weixin.qq.com/document/path/92634
+     * record_type=5 表示加班审批
+     */
+    @RequestMapping("/getOvertimeApprovalList")
+    public HttpRespMsg getOvertimeApprovalList(int companyId, String startDate, String endDate) {
+        HttpRespMsg msg = new HttpRespMsg();
+        try {
+            // 构建过滤条件:record_type=5 表示加班审批
+            JSONArray filterArray = new JSONArray();
+            JSONObject filter = new JSONObject();
+            filter.put("key", "record_type");
+            filter.put("value", "5");
+            filterArray.add(filter);
+            
+            // 调用service层方法获取审批单号列表
+            JSONArray approvalList = wxCorpInfoService.getApprovalInfo(companyId, startDate, endDate, "", filterArray);
+            
+            if (approvalList != null && approvalList.size() > 0) {
+                // TODO: 获取审批单详情
+                JSONArray detailList = new JSONArray();
+                
+                for (int i = 0; i < approvalList.size(); i++) {
+                    String spNo = approvalList.getString(i);
+                    try {
+                        // 获取审批单详情
+                        JSONObject detail = wxCorpInfoService.getApprovalDetail(companyId, spNo);
+                        
+                        if (detail != null) {
+                            // 解析需要的字段
+                            JSONObject result = new JSONObject();
+                            result.put("sp_no", spNo);
+                            
+                            // 提交人信息
+                            JSONObject applyer = detail.getJSONObject("applyer");
+                            if (applyer != null) {
+                                result.put("applyer_userid", applyer.getString("userid"));
+                                result.put("applyer_name", applyer.getString("partyname"));
+                            }
+                            
+                            // 审批申请数据
+                            JSONObject applyData = detail.getJSONObject("apply_data");
+                            if (applyData != null) {
+                                JSONArray contents = applyData.getJSONArray("contents");
+                                if (contents != null) {
+                                    for (int j = 0; j < contents.size(); j++) {
+                                        JSONObject content = contents.getJSONObject(j);
+                                        String controlName = content.getString("control");
+                                        System.out.println("content=" + content);
+                                        JSONArray array = content.getJSONArray("title");
+                                        String title = null;
+                                        for (int k = 0; k < array.size(); k++) {
+                                            JSONObject item = array.getJSONObject(k);
+                                            if (item.getString("lang").equals("zh_CN")) {
+                                                title = item.getString("text");
+                                                break;
+                                            }
+                                        }
+                                        // 加班时间信息 - 从Attendance控件中解析
+                                        if ("Attendance".equals(controlName)) {
+                                            JSONObject value = content.getJSONObject("value");
+                                            if (value != null) {
+                                                JSONObject attendance = value.getJSONObject("attendance");
+                                                if (attendance != null) {
+                                                    // 解析date_range
+                                                    JSONObject dateRange = attendance.getJSONObject("date_range");
+                                                    if (dateRange != null) {
+                                                        // 时间格式化器
+                                                        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+                                                        
+                                                        // 加班开始时间(时间戳转换为格式化字符串)
+                                                        Long startTimestamp = dateRange.getLong("new_begin");
+                                                        LocalDateTime startDateTime = LocalDateTime.ofInstant(
+                                                            Instant.ofEpochSecond(startTimestamp), 
+                                                            ZoneId.systemDefault()
+                                                        );
+                                                        result.put("start_time", startDateTime.format(formatter));
+                                                        
+                                                        // 加班结束时间(时间戳转换为格式化字符串)
+                                                        Long endTimestamp = dateRange.getLong("new_end");
+                                                        LocalDateTime endDateTime = LocalDateTime.ofInstant(
+                                                            Instant.ofEpochSecond(endTimestamp), 
+                                                            ZoneId.systemDefault()
+                                                        );
+                                                        result.put("end_time", endDateTime.format(formatter));
+                                                        
+                                                        // 加班时长(秒)
+                                                        result.put("duration", dateRange.getLong("new_duration"));
+                                                        // 时长类型
+                                                        result.put("duration_type", dateRange.getString("type"));
+                                                    }
+                                                    
+//                                                    // 解析slice_info中的duration
+//                                                    JSONObject sliceInfo = attendance.getJSONObject("slice_info");
+//                                                    if (sliceInfo != null) {
+//                                                        result.put("slice_duration", sliceInfo.getLong("duration"));
+//                                                        result.put("slice_state", sliceInfo.getInteger("state"));
+//                                                    }
+                                                    
+                                                    // 加班类型(5表示加班)
+                                                    result.put("attendance_type", attendance.getInteger("type"));
+                                                }
+                                            }
+                                        } else if ("是否夜班".equals(title)){
+                                            // 是否夜班字段 - 从Selector控件中解析
+                                            JSONObject value = content.getJSONObject("value");
+                                            if (value != null) {
+                                                JSONObject selector = value.getJSONObject("selector");
+                                                if (selector != null) {
+                                                    JSONArray options = selector.getJSONArray("options");
+                                                    if (options != null && options.size() > 0) {
+                                                        JSONObject option = options.getJSONObject(0);
+                                                        JSONArray valueArray = option.getJSONArray("value");
+                                                        if (valueArray != null) {
+                                                            for (int k = 0; k < valueArray.size(); k++) {
+                                                                JSONObject valueItem = valueArray.getJSONObject(k);
+                                                                if ("zh_CN".equals(valueItem.getString("lang"))) {
+                                                                    String nightShiftText = valueItem.getString("text");
+                                                                    // "是"表示是夜班,"否"表示不是夜班
+                                                                    result.put("is_night_shift", "是".equals(nightShiftText));
+                                                                    break;
+                                                                }
+                                                            }
+                                                        }
+                                                    }
+                                                }
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                            
+                            // 打印详情
+                            System.out.println("=== 加班审批单详情 ===");
+                            System.out.println("审批单号: " + result.getString("sp_no"));
+                            System.out.println("提交人ID: " + result.getString("applyer_userid"));
+                            System.out.println("提交人姓名: " + result.getString("applyer_name"));
+                            System.out.println("开始时间: " + result.getString("start_time"));
+                            System.out.println("结束时间: " + result.getString("end_time"));
+                            System.out.println("加班时长(秒): " + result.getLong("duration"));
+                            System.out.println("时长类型: " + result.getString("duration_type"));
+                            System.out.println("考勤类型: " + result.getInteger("attendance_type"));
+                            System.out.println("=====================");
+                            
+                            detailList.add(result);
+                        }
+                    } catch (Exception e) {
+                        System.err.println("获取审批单 " + spNo + " 详情失败: " + e.getMessage());
+                        e.printStackTrace();
+                    }
+                }
+                
+                msg.data = detailList;
+                msg.msg = "成功获取" + detailList.size() + "条加班审批详情";
+            } else {
+                msg.data = new JSONArray();
+                msg.msg = "未查询到加班审批单号";
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            msg.setError("获取加班审批单号失败:" + e.getMessage());
+        }
+        return msg;
+    }
 }
 

+ 3 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/UserDingdingTime.java

@@ -66,6 +66,9 @@ public class UserDingdingTime extends Model<UserDingdingTime> {
     @TableField("work_hours")
     private Float workHours;
 
+    @TableField("ask_leave_time")
+    private Float askLeaveTime;
+
 
     /**
      * 是否是出差

+ 2 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/WxCorpInfoService.java

@@ -86,6 +86,8 @@ public interface WxCorpInfoService extends IService<WxCorpInfo> {
 
     JSONArray getApprovalInfo(Integer companyId, String startDate, String endDate, String newCursor, JSONArray filterArray) throws Exception;
 
+    JSONObject getApprovalDetail(Integer companyId, String spNo) throws Exception;
+
     public String applyEvent(HttpServletRequest request, JSONObject data) throws Exception;
 
     String getAsyncJobResult(String tmpFileJobId,WxCorpInfo wxCorpInfo)  throws Exception;

+ 1 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DingDingServiceImpl.java

@@ -2565,6 +2565,7 @@ public class DingDingServiceImpl implements DingDingService {
         }
     }
 
+    //获取钉钉排班记录,如果有加班,出差,请假的申请单,也会在这个结果中返回。 但是如果员工没有排班,是无法获取到审批单的记录的。
     private String listUserScheduleByDay(CompanyDingding dingding, String userDingdingId, String accessToken, long dateTime) throws ApiException {
         DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/attendance/schedule/listbyday");
         OapiAttendanceScheduleListbydayRequest req = new OapiAttendanceScheduleListbydayRequest();

+ 41 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectApprovalServiceImpl.java

@@ -66,6 +66,8 @@ public class ProjectApprovalServiceImpl extends ServiceImpl<ProjectApprovalMappe
     @Resource
     private CompanyMapper companyMapper;
     @Resource
+    private InformationMapper informationMapper;
+    @Resource
     private HttpServletRequest request;
     @Resource
     private ProjectCategoryMapper projectCategoryMapper;
@@ -814,6 +816,7 @@ public class ProjectApprovalServiceImpl extends ServiceImpl<ProjectApprovalMappe
         HttpRespMsg msg=new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("token"));
         ProjectApproval projectApproval = getById(id);
+        Integer companyId = projectApproval.getCompanyId();
         List<ProjectApprovalCheck> projectApprovalChecks = projectApprovalCheckService.list(new LambdaQueryWrapper<ProjectApprovalCheck>().eq(ProjectApprovalCheck::getProjectApprovalId, id).orderByAsc(ProjectApprovalCheck::getSeq));
         if (null==projectApprovalChecks||projectApprovalChecks.isEmpty()){
             msg.setError("该项目未设置审核人");
@@ -888,6 +891,25 @@ public class ProjectApprovalServiceImpl extends ServiceImpl<ProjectApprovalMappe
                     if (first.get().getSeq()==projectApprovalChecks.size()){
                         projectApproval.setStatus(1);
                         projectApprovalService.updateById(projectApproval);
+                        String creatorId = projectApproval.getCreatorId();
+                        User notifyUser = userMapper.selectById(creatorId);
+                        if (notifyUser != null) {
+                            StringBuilder sb=new StringBuilder();
+                            sb.append("您的立项审批已通过");
+                            String corpwxUserid = user.getCorpwxUserid();
+                            if (corpwxUserid != null) {
+                                WxCorpInfo wxCorpInfo = wxCorpInfoService.getOne(new LambdaQueryWrapper<WxCorpInfo>().eq(WxCorpInfo::getCompanyId, companyId));
+                                wxCorpInfoService.sendWXCorpMsg(wxCorpInfo, corpwxUserid,sb.toString(), "projectApproval", WxCorpInfoServiceImpl.TEXT_CARD_MSG_PROJECT_APPROVED);
+                            }
+                            //系统消息
+                            Information information=new Information();
+                            information.setType(12);
+                            information.setUserId(creatorId);
+                            information.setTime(LocalDateTime.now());
+                            information.setContent("projectApproval");
+                            information.setMsg("您的立项审批已通过");
+                            informationMapper.insert(information);
+                        }
                     }
                 }
                 break;
@@ -905,6 +927,25 @@ public class ProjectApprovalServiceImpl extends ServiceImpl<ProjectApprovalMappe
                 //驳回
                 projectApprovalLog.setType(3);
                 projectApprovalLogService.save(projectApprovalLog);
+                String creatorId = projectApproval.getCreatorId();
+                User notifyUser = userMapper.selectById(creatorId);
+                if (notifyUser != null) {
+                    StringBuilder sb=new StringBuilder();
+                    sb.append("您的立项审批被驳回");
+                    String corpwxUserid = user.getCorpwxUserid();
+                    if (corpwxUserid != null) {
+                        WxCorpInfo wxCorpInfo = wxCorpInfoService.getOne(new LambdaQueryWrapper<WxCorpInfo>().eq(WxCorpInfo::getCompanyId, companyId));
+                        wxCorpInfoService.sendWXCorpMsg(wxCorpInfo, corpwxUserid,sb.toString(), "projectApproval", WxCorpInfoServiceImpl.TEXT_CARD_MSG_PROJECT_REJECTED);
+                    }
+                    //系统消息
+                    Information information=new Information();
+                    information.setType(12);
+                    information.setUserId(creatorId);
+                    information.setTime(LocalDateTime.now());
+                    information.setContent("projectApproval");
+                    information.setMsg("您的立项审批被驳回");
+                    informationMapper.insert(information);
+                }
                 break;
             /*撤销*/
             case 3:

+ 3 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -10496,7 +10496,9 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
             result.add(start);
             start=start.plusDays(1);
         }
-        result.add(start);
+        if (start != null) {
+            result.add(start);
+        }
         return result;
     }
 

+ 52 - 5
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/WxCorpInfoServiceImpl.java

@@ -121,7 +121,9 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
     public static final int TEXT_CARD_MSG_TASK_FILE_CHECK = 28;//任务文件驳回
 
     public static final int TEXT_CARD_MSG_TASK_PLAN_NEED_CHECK = 29;//工作计划待审核
-
+    public static final int TEXT_CARD_MSG_PROJECT_CREATE = 30;//立项待审核
+    public static final int TEXT_CARD_MSG_PROJECT_REJECTED = 31;
+    public static final int TEXT_CARD_MSG_PROJECT_APPROVED = 32;
     private static Object userLock = new Object();
 
     @Value("${suitId}")
@@ -414,6 +416,15 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
                 else if (pageRouter.contains("projectInside")) {
                     //预估工时审核
                     title = "预估工时审核通知";
+                } else if (pageRouter.equals("projectApproval")) {
+                    // 项目立项审批
+                    if (msgType.equals(TEXT_CARD_MSG_PROJECT_CREATE)) {
+                        title = "项目立项待审核";
+                    } else if (msgType.equals(TEXT_CARD_MSG_PROJECT_APPROVED)) {
+                        title = "项目立项审核通过";
+                    } else if (msgType.equals(TEXT_CARD_MSG_PROJECT_REJECTED)) {
+                        title = "项目立项审批驳回";
+                    }
                 }
             }
             cardJson.put("title", title);
@@ -2779,6 +2790,40 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
         return null;
     }
 
+    /**
+     * 获取审批申请详情
+     * 参考文档:https://developer.work.weixin.qq.com/document/path/92634
+     * @param companyId 公司ID
+     * @param spNo 审批单号
+     * @return 审批详情JSON对象
+     */
+    @Override
+    public JSONObject getApprovalDetail(Integer companyId, String spNo) throws Exception {
+        WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id", companyId));
+        String url = GET_APPROVAL_DETAIL.replace("ACCESS_TOKEN", getCorpAccessToken(wxCorpInfo));
+        
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_JSON);
+        
+        JSONObject requestMap = new JSONObject();
+        requestMap.put("sp_no", spNo);
+        
+        HttpEntity<String> requestEntity = new HttpEntity<>(requestMap.toJSONString(), headers);
+        ResponseEntity<String> responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
+        
+        if (responseEntity.getStatusCode() == HttpStatus.OK) {
+            String resp = responseEntity.getBody();
+            JSONObject jsonObject = JSONObject.parseObject(resp);
+            
+            if (jsonObject.getIntValue("errcode") == 0) {
+                return jsonObject.getJSONObject("info");
+            } else {
+                throw new Exception("获取审批详情失败:" + jsonObject.toJSONString());
+            }
+        }
+        return null;
+    }
+
     /**
      * 批量获取审批单号
      * PS:Integer recordType 1-请假;2-打卡补卡;3-出差;4-外出;5-加班; 6- 调班;7-会议室预定;8-退款审批;9-红包报销审批
@@ -2789,10 +2834,8 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
         DateTimeFormatter df=DateTimeFormatter.ofPattern("yyyy-MM-dd");
         LocalDateTime startDateTime = LocalDate.parse(startDate, df).atTime(LocalTime.MIN);
         LocalDateTime endDateTime = LocalDate.parse(endDate, df).atTime(LocalTime.MAX);
-        long startTime = startDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli() -
-                LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
-        long endTime = endDateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli() -
-                LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli();
+        long startTime = startDateTime.toEpochSecond(ZoneOffset.of("+8"));
+        long endTime = endDateTime.toEpochSecond(ZoneOffset.of("+8"));
         WxCorpInfo wxCorpInfo = wxCorpInfoMapper.selectOne(new QueryWrapper<WxCorpInfo>().eq("company_id",companyId));
         String url=BATCH_GET_APPROVAL_INFO.replace("ACCESS_TOKEN",getCorpAccessToken(wxCorpInfo));
         HttpHeaders headers = new HttpHeaders();
@@ -2811,6 +2854,7 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
         if (ResponseEntity.getStatusCode() == HttpStatus.OK) {
             JSONArray jsonArray=new JSONArray();
             String resp = ResponseEntity.getBody();
+            System.out.println("返回加班审批单号==+ resp==" + resp);
             JSONObject jsonObject = JSONObject.parseObject(resp);
             JSONArray sp_no_list = jsonObject.getJSONArray("sp_no_list");
             jsonArray.addAll(sp_no_list);
@@ -2838,11 +2882,14 @@ public class WxCorpInfoServiceImpl extends ServiceImpl<WxCorpInfoMapper, WxCorpI
         headers.setContentType(type);
         headers.add("Accept", MediaType.APPLICATION_JSON.toString());
         HttpEntity<JSONObject> entity = new HttpEntity<>(data, headers);
+        System.out.println("发送通知消息, applyEvent ,url=" + url);
         ResponseEntity<String> ResponseEntity = restTemplate.postForEntity(url, entity, String.class);
         if (ResponseEntity.getStatusCode() == HttpStatus.OK) {
             String resp = ResponseEntity.getBody();
             JSONObject object = JSONObject.parseObject(resp);
             return object.getString("sp_no");
+        } else {
+            System.err.println("报错了:"+ResponseEntity.getStatusCode() + ", " + ResponseEntity.getBody());
         }
         return "";
     }

Разница между файлами не показана из-за своего большого размера
+ 5 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/resources/application.yml


+ 2 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserDingdingTimeMapper.xml

@@ -17,11 +17,12 @@
         <result column="work_hours" property="workHours" />
         <result column="is_offi_business" property="isOffiBusiness" />
         <result column="modified_by_admin" property="modifiedByAdmin" />
+        <result column="ask_leave_time" property="askLeaveTime" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, work_date, dingding_userid, user_id, dingding_corpid, company_id, start_time, end_time, week_day, week_day_txt, work_hours, is_offi_business,modified_by_admin
+        id, work_date, dingding_userid, user_id, dingding_corpid, company_id, start_time, end_time, week_day, week_day_txt, work_hours, is_offi_business,modified_by_admin, ask_leave_time
     </sql>
 
 </mapper>