ソースを参照

钉钉的考勤,请假,出差同步

seyason 3 年 前
コミット
88dae61470
31 ファイル変更599 行追加138 行削除
  1. 3 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/constant/Constant.java
  2. 6 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/BusinessTripController.java
  3. 18 11
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/DingDingController.java
  4. 23 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/FinanceController.java
  5. 2 5
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/LeaveSheetController.java
  6. 3 3
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java
  7. 11 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java
  8. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/LeaveSheet.java
  9. 3 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Report.java
  10. 19 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/TimeType.java
  11. 4 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/UserDingdingTime.java
  12. 2 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProjectMapper.java
  13. 1 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/UserMapper.java
  14. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/BusinessTripService.java
  15. 5 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/DingDingService.java
  16. 4 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/FinanceService.java
  17. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/LeaveSheetService.java
  18. 3 3
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectService.java
  19. 9 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/BusinessTripServiceImpl.java
  20. 366 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DingDingServiceImpl.java
  21. 16 37
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FinanceServiceImpl.java
  22. 35 40
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/LeaveSheetServiceImpl.java
  23. 3 3
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java
  24. 20 14
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  25. 6 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/application.yml
  26. 5 4
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml
  27. 4 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/TimeTypeMapper.xml
  28. 2 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserDingdingTimeMapper.xml
  29. 12 2
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserMapper.xml
  30. 1 3
      fhKeeper/formulahousekeeper/timesheet/src/main.js
  31. 8 1
      fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue

+ 3 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/constant/Constant.java

@@ -34,5 +34,7 @@ public class Constant {
 
     public static final String ROLE_SUPER_MANAGER = "超级管理员";
 
-    public static String[] DEFAULT_BASE_COST_ITEMS = {"人工成本","一般费用","外包费用","其他"};
+    public static final String[] DEFAULT_BASE_COST_ITEMS = {"人工成本","一般费用","外包费用","其他"};
+
+    public static final String[] LEAVE_TYPES = {"事假","病假","年假","产假","婚假","丧假","调休假","陪产假","其他"};
 }

+ 6 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/BusinessTripController.java

@@ -46,6 +46,12 @@ public class BusinessTripController {
 
     }
 
+    @RequestMapping("/modifyProject")
+    public HttpRespMsg modifyProject(BusinessTrip sheet) {
+        return businessTripService.modifyProject(sheet);
+
+    }
+
     @RequestMapping("/delete")
     public HttpRespMsg delete(Integer id) {
         return businessTripService.delete(id);

+ 18 - 11
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/DingDingController.java

@@ -4,14 +4,7 @@ import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.dingtalk.api.DefaultDingTalkClient;
-import com.dingtalk.api.DingTalkClient;
-import com.dingtalk.api.request.OapiServiceGetSuiteTokenRequest;
-import com.dingtalk.api.request.OapiServiceGetUnactiveCorpRequest;
-import com.dingtalk.api.response.OapiServiceGetSuiteTokenResponse;
-import com.dingtalk.api.response.OapiServiceGetUnactiveCorpResponse;
 import com.management.platform.entity.CompanyDingding;
-import com.management.platform.entity.SysConfig;
 import com.management.platform.entity.User;
 import com.management.platform.mapper.UserMapper;
 import com.management.platform.service.CompanyDingdingService;
@@ -20,8 +13,6 @@ import com.management.platform.util.*;
 import com.taobao.api.ApiException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.springframework.format.annotation.DateTimeFormat;
-import org.springframework.http.*;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
@@ -275,9 +266,25 @@ public class DingDingController {
         User user = userMapper.selectById(userId);
         System.out.println("测试发送审批给=="+user.getName());
         CompanyDingding dingding = companyDingdingService.getOne(new QueryWrapper<CompanyDingding>().eq("company_id", user.getCompanyId()));
-
         companyDingdingService.sendLeaveApplyAlertMsg(dingding.getCompanyId(), dingding.getAgentId(), "", user.getDingdingUserid());
-
         return msg;
     }
+
+    @RequestMapping("/syncCardTime")
+    public HttpRespMsg syncCardTime(Integer companyId, String userId, String startDate, String endDate) {
+        dingDingService.syncCardTime(companyId, userId, startDate, endDate);
+        return new HttpRespMsg();
+    }
+
+    @RequestMapping("/syncLeaveTime")
+    public HttpRespMsg syncLeaveTime(Integer companyId, String userId, String startDate, String endDate) {
+        dingDingService.syncLeaveTime(companyId, userId, startDate, endDate);
+        return new HttpRespMsg();
+    }
+
+    @RequestMapping("/syncUserWorkData")
+    public HttpRespMsg syncUserWorkData(Integer companyId, String workDate) {
+        dingDingService.syncUserWorkData(companyId, workDate);
+        return new HttpRespMsg();
+    }
 }

+ 23 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/FinanceController.java

@@ -11,6 +11,8 @@ import com.management.platform.service.FinanceFixedcolnameService;
 import com.management.platform.service.FinanceService;
 import com.management.platform.util.ExcelUtil;
 import com.management.platform.util.HttpRespMsg;
+import com.management.platform.util.UserNotFoundException;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.bind.annotation.RequestMapping;
 
@@ -20,6 +22,7 @@ import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -62,7 +65,26 @@ public class FinanceController {
     public HttpRespMsg importData(Integer companyId, String yearMonth,
                                   Boolean syncUserCost, Boolean syncHistoryReport,
                                   MultipartFile file, HttpServletRequest request) {
-        return financeService.importData(companyId, yearMonth, syncUserCost, syncHistoryReport, file, request);
+        HttpRespMsg msg = new HttpRespMsg();
+        try {
+            return financeService.importData(companyId, yearMonth, syncUserCost, syncHistoryReport, file, request);
+        } catch (IOException e) {
+            e.printStackTrace();
+            msg.setError("文件处理出错");
+            return msg;
+        } catch (UserNotFoundException e) {
+            e.printStackTrace();
+            msg.setError(e.getMessage());
+            return msg;
+        } catch (NullPointerException e) {
+            e.printStackTrace();
+            msg.setError("数据格式有误或存在空数据 导入失败");
+            return msg;
+        } catch (Exception e) {
+            e.printStackTrace();
+            msg.setError("发生其他错误");
+            return msg;
+        }
     }
 
     @RequestMapping("/exportData")

+ 2 - 5
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/LeaveSheetController.java

@@ -45,13 +45,12 @@ public class LeaveSheetController {
     /**
      *
      * @param sheet 请假单封装数据
-     * @param projectAuditorJson 项目审核人ids
      * @return
      */
     @RequestMapping("/add")
-    public HttpRespMsg add(LeaveSheet sheet, String projectAuditorJson) {
+    public HttpRespMsg add(LeaveSheet sheet) {
         String userId = request.getHeader("Token");
-        return leaveSheetService.add(sheet, userId, projectAuditorJson);
+        return leaveSheetService.add(sheet, userId);
 
     }
 
@@ -76,9 +75,7 @@ public class LeaveSheetController {
 
     @RequestMapping("/approve")
     public HttpRespMsg approve(Integer id) {
-
         return leaveSheetService.approve(id);
-
     }
     @RequestMapping("/deny")
     public HttpRespMsg deny(Integer id) {

+ 3 - 3
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java

@@ -328,7 +328,7 @@ public class ProjectController {
      * @return
      */
     @RequestMapping("/getOvertimeList")
-    public HttpRespMsg getOvertimeList(Integer userId, Integer projectId, String startDate, String endDate) {
+    public HttpRespMsg getOvertimeList(String userId, Integer projectId, String startDate, String endDate) {
         return projectService.getOvertimeList(userId, projectId, startDate, endDate, request);
     }
 
@@ -341,7 +341,7 @@ public class ProjectController {
      * @return
      */
     @RequestMapping("/getOvertimeDetail")
-    public HttpRespMsg getOvertimeDetail(Integer userId, Integer projectId, String startDate, String endDate) {
+    public HttpRespMsg getOvertimeDetail(String userId, Integer projectId, String startDate, String endDate) {
         return projectService.getOvertimeDetail(userId, projectId, startDate, endDate, request);
     }
 
@@ -354,7 +354,7 @@ public class ProjectController {
      * @return
      */
     @RequestMapping("/exportOvertimeList")
-    public HttpRespMsg exportOvertimeList(Integer userId, Integer projectId, String startDate, String endDate) {
+    public HttpRespMsg exportOvertimeList(String userId, Integer projectId, String startDate, String endDate) {
         return projectService.exportOvertimeList(userId, projectId, startDate, endDate, request);
     }
 

+ 11 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java

@@ -138,6 +138,7 @@ public class ReportController {
                                   Integer[] reportTimeType,
                                   String[] createDate,
                                   Integer[] taskId,
+                                  Integer[] taskFinish,
                                   Integer[] isOvertime,
                                   Integer[] progress,
                                   String[] targetUids,
@@ -212,6 +213,12 @@ public class ReportController {
                 overtimeHours[i] = null;
             }
         }
+        if (taskFinish == null) {
+            taskFinish = new Integer[projectId.length];
+            for(int i=0;i<taskFinish.length; i++) {
+                taskFinish[i] = 0;
+            }
+        }
 
         //检查项目是否截止
         List<Integer> integers = Arrays.asList(projectId);
@@ -447,6 +454,7 @@ public class ReportController {
                             report.setDeptId(user.getDepartmentId());
                             report.setProjectAuditState(0);
                             report.setProjectAuditorId(projectAuditorId[i]);
+                            report.setTaskFinish(taskFinish[i]);
 
                             if (auditWorkflowList.size() == 0) {
                                 //没有自定义审核流,默认的直接是项目负责人审核
@@ -503,6 +511,7 @@ public class ReportController {
                                         .setDeptId(subsUser.getDepartmentId())
                                         .setProjectAuditorId(projectAuditorId[i]);
                                 report.setProjectAuditState(0);
+                                report.setTaskFinish(taskFinish[i]);
                                 if (auditWorkflowList.size() == 0) {
                                     //没有自定义审核流,默认的直接是项目负责人审核
                                     report.setIsDeptAudit(0);
@@ -558,6 +567,7 @@ public class ReportController {
                         report.setDeptId(user.getDepartmentId());
                         report.setProjectAuditState(0);
                         report.setProjectAuditorId(projectAuditorId[i]);
+                        report.setTaskFinish(taskFinish[i]);
                         if (auditWorkflowList.size() == 0) {
                             //没有自定义审核流,默认的直接是项目负责人审核
                             report.setIsDeptAudit(0);
@@ -618,6 +628,7 @@ public class ReportController {
                                     .setProjectAuditorId(projectAuditorId[i])
                                     .setFillUserid(token);
                             report.setProjectAuditState(1);
+                            report.setTaskFinish(taskFinish[i]);
                             if (auditWorkflowList.size() == 0) {
                                 //没有自定义审核流,直接代填的,就算审核通过
                                 report.setIsDeptAudit(0);

+ 2 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/LeaveSheet.java

@@ -150,6 +150,8 @@ public class LeaveSheet extends Model<LeaveSheet> {
     @TableField("auditor_type")
     private Integer auditorType;
 
+    @TableField(exist = false)
+    private String dept;
 
     @Override
     protected Serializable pkVal() {

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

@@ -305,6 +305,9 @@ public class Report extends Model<Report> {
     private BigDecimal overtimeCost;
 
 
+    @TableField(exist = false)
+    private Integer taskFinish;
+
     @Override
     protected Serializable pkVal() {
         return this.id;

+ 19 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/TimeType.java

@@ -15,7 +15,7 @@ import lombok.experimental.Accessors;
  * </p>
  *
  * @author Seyason
- * @since 2022-04-19
+ * @since 2022-04-24
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -156,6 +156,24 @@ public class TimeType extends Model<TimeType> {
     @TableField("overtime_ratio")
     private Double overtimeRatio;
 
+    /**
+     * 是否同步钉钉考勤打卡和出差
+     */
+    @TableField("sync_dingding")
+    private Integer syncDingding;
+
+    /**
+     * 是否是药研行业
+     */
+    @TableField("is_cro")
+    private Integer isCro;
+
+    /**
+     * 只使用导入功能,不要项目审核
+     */
+    @TableField("only_importreport")
+    private Integer onlyImportreport;
+
 
     @Override
     protected Serializable pkVal() {

+ 4 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/UserDingdingTime.java

@@ -16,7 +16,7 @@ import lombok.experimental.Accessors;
  * </p>
  *
  * @author Seyason
- * @since 2022-04-25
+ * @since 2022-04-26
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -58,6 +58,9 @@ public class UserDingdingTime extends Model<UserDingdingTime> {
     @TableField("week_day_txt")
     private String weekDayTxt;
 
+    @TableField("work_hours")
+    private Float workHours;
+
 
     @Override
     protected Serializable pkVal() {

+ 2 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProjectMapper.java

@@ -67,12 +67,12 @@ public interface ProjectMapper extends BaseMapper<Project> {
 
     List<Map<String, Object>> getUserMonthTimeCost(@Param("companyId") Integer companyId, @Param("startDate") String startDate, @Param("endDate") String endDate);
 
-    List<Map<String, Object>> getOvertimeList(Integer userId, Integer companyId, String startDate, String endDate, Integer projectId);
+    List<Map<String, Object>> getOvertimeList(String userId, Integer companyId, String startDate, String endDate, Integer projectId);
 
     List<Map<String, Object>> getDegreeCost(@Param("startDate") String startDate, @Param("endDate") String endDate, @Param("projectId") Integer projectId, @Param("companyId") Integer companyId);
 
     //获取导出的项目数据
     List<HashMap<String, Object>> getExportData(Integer companyId, String userId);
 
-    List<Map<String, Object>> getOvertimeDetail(Integer userId, Integer companyId, String startDate, String endDate, Integer projectId);
+    List<Map<String, Object>> getOvertimeDetail(String userId, Integer companyId, String startDate, String endDate, Integer projectId);
 }

+ 1 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/UserMapper.java

@@ -35,4 +35,5 @@ public interface UserMapper extends BaseMapper<User> {
 
     List<Map<String, Object>> getSimpleNameList(@Param(Constants.WRAPPER) QueryWrapper<User> queryWrapper);
 
+    List<User> getUserWithDept(@Param(Constants.WRAPPER) QueryWrapper<User> queryWrapper);
 }

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

@@ -26,4 +26,6 @@ public interface BusinessTripService extends IService<BusinessTrip> {
     HttpRespMsg delete(Integer id);
 
     HttpRespMsg add(BusinessTrip sheet);
+
+    HttpRespMsg modifyProject(BusinessTrip sheet);
 }

+ 5 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/DingDingService.java

@@ -24,4 +24,9 @@ public interface DingDingService {
     HttpRespMsg reAuthCorp(String corpid);
 
 
+    public void syncCardTime(Integer companyId, String userId, String startDate, String endDate);
+
+    void syncLeaveTime(Integer companyId, String userId, String startDate, String endDate);
+
+    void syncUserWorkData(Integer companyId, String workDate);
 }

+ 4 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/FinanceService.java

@@ -3,9 +3,12 @@ package com.management.platform.service;
 import com.management.platform.entity.Finance;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.management.platform.util.HttpRespMsg;
+import com.management.platform.util.UserNotFoundException;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 import org.springframework.web.multipart.MultipartFile;
 
 import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
 
 /**
  * <p>
@@ -19,7 +22,7 @@ public interface FinanceService extends IService<Finance> {
 
     HttpRespMsg getByMonth(Integer companyId, String yearMonth);
 
-    HttpRespMsg importData(Integer companyId, String yearMonth, Boolean syncUserCost, Boolean syncHistoryReport, MultipartFile multipartFile, HttpServletRequest request);
+    HttpRespMsg importData(Integer companyId, String yearMonth, Boolean syncUserCost, Boolean syncHistoryReport, MultipartFile multipartFile, HttpServletRequest request) throws IOException, InvalidFormatException, UserNotFoundException;
 
     HttpRespMsg exportData(Integer groupByCategory, String date, Boolean assignNoProUser, HttpServletRequest request);
 

+ 1 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/LeaveSheetService.java

@@ -15,7 +15,7 @@ import com.management.platform.util.HttpRespMsg;
  */
 public interface LeaveSheetService extends IService<LeaveSheet> {
 
-    HttpRespMsg add(LeaveSheet sheet, String userId, String projectAuditorJson);
+    HttpRespMsg add(LeaveSheet sheet, String userId);
 
     HttpRespMsg delete(Integer id);
 

+ 3 - 3
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectService.java

@@ -94,9 +94,9 @@ public interface ProjectService extends IService<Project> {
 
     HttpRespMsg exportProjectStagesCost( HttpServletRequest request);
 
-    HttpRespMsg getOvertimeList(Integer userId, Integer projectId, String startDate, String endDate, HttpServletRequest request);
+    HttpRespMsg getOvertimeList(String userId, Integer projectId, String startDate, String endDate, HttpServletRequest request);
 
-    HttpRespMsg exportOvertimeList(Integer userId, Integer projectId, String startDate, String endDate, HttpServletRequest request);
+    HttpRespMsg exportOvertimeList(String userId, Integer projectId, String startDate, String endDate, HttpServletRequest request);
 
     HttpRespMsg getDegreeCost(String startDate, String endDate, Integer projectId, HttpServletRequest request);
 
@@ -110,5 +110,5 @@ public interface ProjectService extends IService<Project> {
 
     HttpRespMsg getMyParticiPMList(HttpServletRequest request);
 
-    HttpRespMsg getOvertimeDetail(Integer userId, Integer projectId, String startDate, String endDate, HttpServletRequest request);
+    HttpRespMsg getOvertimeDetail(String userId, Integer projectId, String startDate, String endDate, HttpServletRequest request);
 }

+ 9 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/BusinessTripServiceImpl.java

@@ -39,6 +39,14 @@ public class BusinessTripServiceImpl extends ServiceImpl<BusinessTripMapper, Bus
     @Resource
     private ProjectMapper projectMapper;
 
+
+    @Override
+    public HttpRespMsg modifyProject(BusinessTrip sheet) {
+        HttpRespMsg msg = new HttpRespMsg();
+        businessTripMapper.updateById(sheet);
+        return msg;
+    }
+
     @Override
     public HttpRespMsg add(BusinessTrip sheet) {
         HttpRespMsg msg = new HttpRespMsg();
@@ -94,7 +102,7 @@ public class BusinessTripServiceImpl extends ServiceImpl<BusinessTripMapper, Bus
             queryWrapper.eq("way", sheet.getWay());
         }
         if (sheet.getStartDate() != null && sheet.getEndDate() != null) {
-            queryWrapper.le("start_date", sheet.getEndDate()).gt("end_date", sheet.getStartDate());
+            queryWrapper.le("start_date", sheet.getEndDate()).ge("end_date", sheet.getStartDate());
         }
         IPage<BusinessTrip> listIPager = businessTripMapper.selectPage(new Page<>(pageIndex, pageSize),
                 queryWrapper);

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

@@ -1,5 +1,6 @@
 package com.management.platform.service.impl;
 
+import ch.qos.logback.core.util.StringCollectionUtil;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.aliyun.dingtalkcontact_1_0.models.GetUserHeaders;
@@ -17,19 +18,24 @@ import com.management.platform.entity.vo.UserVO;
 import com.management.platform.mapper.*;
 import com.management.platform.service.*;
 import com.management.platform.util.ColorUtil;
+import com.management.platform.util.DateTimeUtil;
 import com.management.platform.util.HttpRespMsg;
 import com.management.platform.util.SnowFlake;
 import com.taobao.api.ApiException;
+import com.taobao.api.internal.util.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -93,7 +99,21 @@ public class DingDingServiceImpl implements DingDingService {
     private ProjectMapper projectMapper;
     @Resource
     private ProjectBasecostSettingMapper projectBasecostSettingMapper;
-
+    @Resource
+    private UserDingdingTimeService userDingdingTimeService;
+    @Resource
+    private UserDingdingTimeMapper userDingdingTimeMapper;
+    @Resource
+    private LeaveSheetMapper leaveSheetMapper;
+    @Resource
+    private LeaveSheetService leaveSheetService;
+    //企业内部应用参数
+    @Value("${dingding.appkey}")
+    private String appkey;
+    @Value("${dingding.appsecret}")
+    private String appsecret;
+    @Value("${configEnv.isPrivateDeploy}")
+    private boolean isPrivateDeploy;//企业内部应用,私有化部署的情况
     @Override
     @Async
     public void corpAuth(String corpid, String corpName, String authUserId, Long agentId) throws ApiException {
@@ -310,6 +330,49 @@ public class DingDingServiceImpl implements DingDingService {
         return execute;
     }
 
+    private String getCorpAccessToken(CompanyDingding dingding) {
+        String accessToken = null;
+        if (dingding.getExpireTime().isBefore(LocalDateTime.now())) {
+            SysConfig config = sysConfigMapper.selectOne(new QueryWrapper<SysConfig>().eq("param_key", "dingding_suite_ticket"));
+            OapiServiceGetCorpTokenResponse result = null;
+            try {
+                result = getAuthCorpAccessToken(dingding.getCorpid(), config.getParamValue());
+                if (result != null) {
+                    if (result.getErrcode() == 0L) {
+                        //返回成功
+                        dingding.setAccessToken(result.getAccessToken());
+                        LocalDateTime time = LocalDateTime.now();
+                        time = time.plusSeconds(result.getExpiresIn());//设置token过期时间
+                        dingding.setExpireTime(time);
+                        companyDingdingMapper.updateById(dingding);
+
+                        accessToken = dingding.getAccessToken();
+                    } else {
+                        System.out.println(result.getBody());
+                    }
+                }
+            } catch (ApiException e) {
+                e.printStackTrace();
+            }
+        } else {
+            accessToken = dingding.getAccessToken();
+        }
+        return accessToken;
+    }
+
+    /**
+     * 获取钉钉内部企业的token
+     */
+    private OapiGettokenResponse getInnerCorpToken() throws ApiException {
+        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
+        OapiGettokenRequest request = new OapiGettokenRequest();
+        request.setAppkey(appkey);
+        request.setAppsecret(appsecret);
+        request.setHttpMethod("GET");
+        OapiGettokenResponse response = client.execute(request);
+        System.out.println(response.getBody());
+        return response;
+    }
 
     /**
      * 使用 Token 初始化账号Client
@@ -990,6 +1053,308 @@ public class DingDingServiceImpl implements DingDingService {
     }
 
 
+    @Override
+    public void syncLeaveTime(Integer companyId, String userId, String startDate, String endDate) {
+        //获取从开始日期到结束日期期间内的每一天的请假时长
+        if (companyId != null) {
+            //指定的某个公司
+            CompanyDingding dingding = companyDingdingMapper.selectOne(new QueryWrapper<CompanyDingding>().eq("company_id", companyId));
+            syncOneCompLeave(dingding, userId, startDate, endDate);
+        } else {
+            //全部的
+            List<TimeType> timeTypes = timeTypeMapper.selectList(new QueryWrapper<TimeType>().eq("sync_dingding", 1));
+            List<Integer> companyIds = timeTypes.stream().map(TimeType::getCompanyId).collect(Collectors.toList());
+            List<CompanyDingding> dingdingList = companyDingdingMapper.selectList(new QueryWrapper<CompanyDingding>().in("company_id", companyIds));
+            for (CompanyDingding dingding : dingdingList) {
+                syncOneCompLeave(dingding, userId, startDate, endDate);
+            }
+        }
+    }
+
+    //获取当天的员工考勤数据,包括打卡,请假/出差申请单; 仅企业内部应用有权限
+    @Override
+    public void syncUserWorkData(Integer companyId, String workDate) {
+        if (companyId != null) {
+            //指定的某个公司
+            CompanyDingding dingding = companyDingdingMapper.selectOne(new QueryWrapper<CompanyDingding>().eq("company_id", companyId));
+            syncOneCompWorkData(dingding, workDate);
+        } else {
+            //全部的
+            List<TimeType> timeTypes = timeTypeMapper.selectList(new QueryWrapper<TimeType>().eq("sync_dingding", 1));
+            List<Integer> companyIds = timeTypes.stream().map(TimeType::getCompanyId).collect(Collectors.toList());
+            List<CompanyDingding> dingdingList = companyDingdingMapper.selectList(new QueryWrapper<CompanyDingding>().in("company_id", companyIds));
+            for (CompanyDingding dingding : dingdingList) {
+                syncOneCompWorkData(dingding, workDate);
+            }
+        }
+    }
+
+
+    private void syncOneCompLeave(CompanyDingding dingding, String targetUserId, String startDate, String endDate) {
+        List<User> userList = new ArrayList<>();
+        TimeType timeType = timeTypeMapper.selectById(dingding.getCompanyId());
+        if (!StringUtils.isEmpty(targetUserId)) {
+            userList.add(userMapper.selectById(targetUserId));
+        } else {
+            userList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", dingding.getCompanyId()).eq("is_active", 1));
+        }
+        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        String accessToken = getCorpAccessToken(dingding);
+        List<LeaveSheet> sheetList = new ArrayList<>();
+        for (User u : userList) {
+            String type = "";
+            List<String> typeList = new ArrayList<>();
+            //最后一个其他不要
+            for (int i=0;i<Constant.LEAVE_TYPES.length-1; i++) {
+                type += Constant.LEAVE_TYPES[i];
+                if (i < Constant.LEAVE_TYPES.length -2) {
+                    type += ",";
+                }
+                if (type.length() > 15 || i == Constant.LEAVE_TYPES.length -2) {
+                    if (type.endsWith(",")) {
+                        type = type.substring(0, type.length()-1);
+                    }
+                    typeList.add(type);
+                    type = "";
+                }
+            }
+            for (String t : typeList) {
+                DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/attendance/getleavetimebynames");
+                OapiAttendanceGetleavetimebynamesRequest req = new OapiAttendanceGetleavetimebynamesRequest();
+                req.setUserid(u.getDingdingUserid());
+                req.setLeaveNames(t);
+                req.setFromDate(StringUtils.parseDateTime(startDate + " 00:00:00"));
+                req.setToDate(StringUtils.parseDateTime(endDate + " 23:59:59"));
+                OapiAttendanceGetleavetimebynamesResponse rsp = null;
+                try {
+                    rsp = client.execute(req, accessToken);
+                    System.out.println(rsp.getBody());
+//                    JSONArray array = JSONObject.parseObject(rsp.getBody()).getJSONObject("result").getJSONArray("columns");
+//                    for (int i=0;i<array.size(); i++) {
+//                        JSONObject item = array.getJSONObject(i);
+//                        String leaveTypeName = item.getJSONObject("columnvo").getString("name");
+//                        int typeIndex = 0;
+//                        for (int index=0;index < Constant.LEAVE_TYPES.length; index++) {
+//                            if (Constant.LEAVE_TYPES[index].equals(leaveTypeName)) {
+//                                typeIndex = index;
+//                                break;
+//                            }
+//                        }
+//                        //获取请假的数据
+//                        JSONArray valArray = item.getJSONArray("columnvals");
+//                        for (int j=0;j<valArray.size(); j++) {
+//                            Float val = valArray.getJSONObject(j).getFloat("value");
+//                            String date = valArray.getJSONObject(j).getString("date");
+//                            LocalDate localDate = LocalDateTime.parse(date, dtf).toLocalDate();
+//                            if (val != null && val > 0.0) {
+//                                //存在请假时长
+//                                LeaveSheet sheet = new LeaveSheet();
+//                                sheet.setCompanyId(dingding.getCompanyId());
+//                                sheet.setOwnerId(u.getId());
+//                                sheet.setOwnerName(u.getName());
+//                                sheet.setLeaveType(typeIndex);
+//                                sheet.setTimeHours(val);
+//                                sheet.setStartDate(localDate);
+//                                sheet.setEndDate(localDate);
+//                                if (val >= timeType.getAllday()) {
+//                                    sheet.setTimeType(0);
+//                                    sheet.setTimeDays(1.0f);
+//                                } else {
+//                                    sheet.setTimeType(1);//按小时
+//                                }
+//                                sheetList.add(sheet);
+//                            }
+//                        }
+//                    }
+                } catch (ApiException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        if (sheetList.size() > 0) {
+            //添加或更新请假数据
+            List<LeaveSheet> oldList = leaveSheetMapper.selectList(new QueryWrapper<LeaveSheet>()
+                    .eq("company_id", dingding.getCompanyId()).between("start_date", startDate, endDate)
+                    .between("end_date", startDate, endDate));
+            for (LeaveSheet newSheet : sheetList) {
+                Optional<LeaveSheet> find = oldList.stream()
+                        .filter(old->old.getStartDate().isEqual(newSheet.getStartDate()) && old.getOwnerId().equals(newSheet.getOwnerId())
+                                && old.getLeaveType().equals(newSheet.getLeaveType())).findFirst();
+                if (find.isPresent()) {
+                    newSheet.setId(find.get().getId());
+                }
+            }
+            leaveSheetService.saveOrUpdateBatch(sheetList);
+        }
+    }
+
+
+    @Override
+    public void syncCardTime(Integer companyId,String userId, String startDate, String endDate) {
+        if (companyId != null) {
+            //指定的某个公司
+            CompanyDingding dingding = companyDingdingMapper.selectOne(new QueryWrapper<CompanyDingding>().eq("company_id", companyId));
+            syncOneComp(dingding, userId, startDate, endDate);
+        } else {
+            //全部的
+            List<TimeType> timeTypes = timeTypeMapper.selectList(new QueryWrapper<TimeType>().eq("sync_dingding", 1));
+            List<Integer> companyIds = timeTypes.stream().map(TimeType::getCompanyId).collect(Collectors.toList());
+            List<CompanyDingding> dingdingList = companyDingdingMapper.selectList(new QueryWrapper<CompanyDingding>().in("company_id", companyIds));
+            for (CompanyDingding dingding : dingdingList) {
+                syncOneComp(dingding, userId, startDate, endDate);
+            }
+        }
+    }
+
+    private void syncOneCompWorkData(CompanyDingding dingding, String workDate) {
+        List<User> userList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", dingding.getCompanyId()));
+        String accessToken = null;
+        try {
+            accessToken = getInnerCorpToken().getAccessToken();
+        } catch (ApiException e) {
+            e.printStackTrace();
+        }
+        for (User user : userList) {
+            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/attendance/getupdatedata");
+            OapiAttendanceGetupdatedataRequest req = new OapiAttendanceGetupdatedataRequest();
+            req.setUserid(user.getDingdingUserid());
+            req.setWorkDate(StringUtils.parseDateTime(workDate + " 00:00:00"));
+            OapiAttendanceGetupdatedataResponse rsp = null;
+            try {
+                rsp = client.execute(req, accessToken);
+                System.out.println(rsp.getBody());
+            } catch (ApiException e) {
+                e.printStackTrace();
+            }
+
+        }
+    }
+
+
+    private void syncOneComp(CompanyDingding dingding, String targetUserId, String startDate, String endDate) {
+        List<User> userList = new ArrayList<>();
+        if (!StringUtils.isEmpty(targetUserId)) {
+            userList.add(userMapper.selectById(targetUserId));
+        } else {
+            userList = userMapper.selectList(new QueryWrapper<User>().eq("company_id", dingding.getCompanyId()).eq("is_active", 1));
+        }
+        String accessToken = getCorpAccessToken(dingding);
+        if (userList.size() > 50) {
+            int batchSize = userList.size()/50+userList.size()%50==0?0:1;
+            for (int i=0; i<batchSize; i++) {
+                int endIndex = (i+1)*50;
+                if (endIndex > userList.size()) {
+                    endIndex = userList.size();
+                }
+                syncCardDetailList(dingding, startDate, endDate, accessToken, userList.subList(i*50,endIndex));
+            }
+        } else {
+            syncCardDetailList(dingding, startDate, endDate, accessToken,  userList);
+        }
+    }
+
+    private void syncCardDetailList(CompanyDingding dingding, String startDate, String endDate, String accessToken, List<User> userList) {
+        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/attendance/listRecord");
+        OapiAttendanceListRecordRequest req = new OapiAttendanceListRecordRequest();
+        List<String> ddIds = userList.stream().map(User::getDingdingUserid).collect(Collectors.toList());
+        req.setUserIds(ddIds);
+        req.setCheckDateFrom(startDate+ " 08:00:00");
+        req.setCheckDateTo(endDate+ " 23:59:59");
+        req.setIsI18n(false);
+        OapiAttendanceListRecordResponse rsp = null;
+        try {
+            rsp = client.execute(req, accessToken);
+            System.out.println(rsp);
+            if (rsp.getErrcode() == 0) {
+                //正常
+                JSONArray array = JSONObject.parseObject(rsp.getBody()).getJSONArray("recordresult");
+                List<DdingCardTimeItem> list = new ArrayList<DdingCardTimeItem>();
+                for (int i=0;i<array.size(); i++) {
+                    list.add(JSONObject.toJavaObject(array.getJSONObject(i), DdingCardTimeItem.class));
+                }
+                //获取数据库中已有的数据,做比对
+                List<String> ids = userList.stream().map(User::getId).collect(Collectors.toList());
+
+                List<UserDingdingTime> oldList = userDingdingTimeMapper.selectList(new QueryWrapper<UserDingdingTime>().between("work_date", startDate, endDate).in("user_id", ids));
+                System.out.println("历史数据size===="+oldList.size());
+                List<UserDingdingTime> cardRecordList = new ArrayList<>();
+                //按人员进行分组
+                Map<String, List<DdingCardTimeItem>> map = list.stream().collect(Collectors.groupingBy(DdingCardTimeItem::getUserId));
+                Iterator<String> it = map.keySet().iterator();
+                DateTimeFormatter hmFormat = DateTimeFormatter.ofPattern("HH:mm");
+                while(it.hasNext()) {
+                    String key = it.next();
+                    //取这个人员的所有考勤记录,再按天进行分组
+                    List<DdingCardTimeItem> ddTimes = map.get(key);
+                    String uid = userList.stream().filter(u->u.getDingdingUserid().equals(key)).findFirst().get().getId();
+                    Map<Long, List<DdingCardTimeItem>> dailyMap = ddTimes.stream().collect(Collectors.groupingBy(DdingCardTimeItem::getWorkDate));
+                    Iterator<Long> dayIter = dailyMap.keySet().iterator();
+                    while (dayIter.hasNext()) {
+                        Long d = dayIter.next();
+                        LocalDate workDate =  LocalDateTime.ofEpochSecond(d/1000, 0, ZoneOffset.ofHours(8)).toLocalDate();
+                        UserDingdingTime timeItem = new UserDingdingTime();
+                        timeItem.setWorkDate(workDate);
+                        System.out.println("workDate====="+workDate);
+                        List<DdingCardTimeItem> oneDayTimes = dailyMap.get(d);
+
+                        DdingCardTimeItem onDutyEarleast = null;
+                        DdingCardTimeItem offDutyLatest = null;
+                        Comparator<DdingCardTimeItem> comparator = Comparator.comparing(DdingCardTimeItem::getUserCheckTime);
+                        Optional<DdingCardTimeItem> find = oneDayTimes.stream().filter(p->"OnDuty".equals(p.getCheckType())).min(comparator);
+                        if (find.isPresent()) {
+                            onDutyEarleast = find.get();
+                        }
+                        Optional<DdingCardTimeItem> findOff = oneDayTimes.stream().filter(p->"OffDuty".equals(p.getCheckType())).max(comparator);
+                        if (findOff.isPresent()) {
+                            offDutyLatest = findOff.get();
+                        }
+                        if (onDutyEarleast != null) {
+                            System.out.println("最早打卡时间"+onDutyEarleast.getUserCheckTime());
+                            timeItem.setDingdingCorpid(onDutyEarleast.getCorpId());
+                            timeItem.setDingdingUserid(onDutyEarleast.getUserId());
+                            timeItem.setUserId(uid);
+                            LocalDateTime sLt = LocalDateTime.ofEpochSecond(onDutyEarleast.getUserCheckTime()/1000, 0, ZoneOffset.ofHours(8));
+                            timeItem.setStartTime(hmFormat.format(sLt));
+                            //计算周几
+                            timeItem.setWeekDay(workDate.getDayOfWeek().getValue());
+                            timeItem.setWeekDayTxt(DateTimeUtil.getWeekDayTxt(timeItem.getWeekDay()));
+                        }
+                        if (offDutyLatest != null) {
+                            System.out.println("最晚打卡时间"+offDutyLatest.getUserCheckTime());
+                            LocalDateTime oLt = LocalDateTime.ofEpochSecond(offDutyLatest.getUserCheckTime()/1000, 0, ZoneOffset.ofHours(8));
+                            timeItem.setEndTime(hmFormat.format(oLt));
+                        }
+                        timeItem.setCompanyId(dingding.getCompanyId());
+                        if (onDutyEarleast != null && offDutyLatest != null) {
+                            long seconds = (offDutyLatest.getUserCheckTime() - onDutyEarleast.getUserCheckTime())/1000;
+                            float hours = seconds*1.0f/3600;
+                            timeItem.setWorkHours(hours);
+                            //对比,看看之前是否已经存了
+                            Optional<UserDingdingTime> findOld = oldList.stream().filter(old->old.getUserId().equals(timeItem.getUserId()) && old.getWorkDate().isEqual(timeItem.getWorkDate())).findFirst();
+                            if (findOld.isPresent()) {
+                                timeItem.setId(findOld.get().getId());
+                            }
+                            cardRecordList.add(timeItem);
+                        }
+                    }
+                }
+                //保存数据
+                if (cardRecordList.size() > 0) {
+                    System.out.println("插入数据size=="+cardRecordList.size());
+                    userDingdingTimeService.saveOrUpdateBatch(cardRecordList);
+                }
+            } else {
+                //报错了
+                System.err.println("同步钉钉考勤报错 "+rsp.getErrcode()+":"+rsp.getErrmsg());
+                System.err.println("同步钉钉考勤报错 "+rsp.getErrcode()+":"+rsp.getErrmsg());
+            }
+        } catch (ApiException e) {
+            e.printStackTrace();
+        }
+        System.out.println(rsp.getBody());
+    }
+
+
     public void activateSuite(String authCorpid, String tmpAuthCode) throws ApiException {
         DingTalkClient client= new DefaultDingTalkClient("https://oapi.dingtalk.com/service/activate_suite?suite_access_token=" + getDDSuiteAccessToken());
         OapiServiceActivateSuiteRequest req= new OapiServiceActivateSuiteRequest();

+ 16 - 37
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FinanceServiceImpl.java

@@ -16,6 +16,7 @@ import org.apache.commons.io.FileUtils;
 import org.apache.log4j.LogManager;
 import org.apache.log4j.Logger;
 import org.apache.poi.hssf.usermodel.*;
+import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
 import org.apache.poi.ss.usermodel.*;
 import org.apache.poi.xssf.usermodel.XSSFCell;
 import org.apache.poi.xssf.usermodel.XSSFRow;
@@ -115,7 +116,7 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
     }
 
     @Override
-    public HttpRespMsg importData(Integer companyId, String yearMonth, Boolean syncUserCost, Boolean syncHistoryReport, MultipartFile multipartFile, HttpServletRequest request) {
+    public HttpRespMsg importData(Integer companyId, String yearMonth, Boolean syncUserCost, Boolean syncHistoryReport, MultipartFile multipartFile, HttpServletRequest request) throws IOException, InvalidFormatException, UserNotFoundException {
         HttpRespMsg msg = new HttpRespMsg();
         User user = userMapper.selectById(request.getHeader("TOKEN"));
         //然后处理文件
@@ -327,6 +328,8 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                 msg.setError("请填写数据再上传");
                 return msg;
             }
+
+
             //批量插入
             financeService.saveOrUpdateBatch(financeList);
             if (syncUserCost) {
@@ -388,42 +391,18 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                 dir.mkdir();
             }
             File destFile = new File(dir, destFileName);
-            try {
-//            multipartFile.transferTo(destFile);
-                FileUtils.copyFile(file, destFile);
-                FinanceImport log = new FinanceImport();
-                log.setCompanyId(companyId);
-                log.setFileName(originName);
-                log.setServerName(financeFolder+"/"+destFileName);
-                log.setUserId(user.getId());
-                log.setUserName(user.getName());
-                log.setYmonth(yearMonth);
-                log.setRecoverMonthcost(syncUserCost?1:0);
-                log.setRecoverReport(syncHistoryReport?1:0);
-                log.setState(1);//默认审核通过
-                financeImportMapper.insert(log);
-            } catch (IOException e) {
-                e.printStackTrace();
-                msg.setError(e.getMessage());
-            } finally {
-                System.out.println("删除临时文件:"+file.delete());
-            }
-        } catch (IOException e) {
-            e.printStackTrace();
-            msg.setError("文件处理出错");
-            return msg;
-        } catch (UserNotFoundException e) {
-            e.printStackTrace();
-            msg.setError(e.getMessage());
-            return msg;
-        } catch (NullPointerException e) {
-            e.printStackTrace();
-            msg.setError("数据格式有误或存在空数据 导入失败");
-            return msg;
-        } catch (Exception e) {
-            e.printStackTrace();
-            msg.setError("发生其他错误");
-            return msg;
+            FileUtils.copyFile(file, destFile);
+            FinanceImport log = new FinanceImport();
+            log.setCompanyId(companyId);
+            log.setFileName(originName);
+            log.setServerName(financeFolder+"/"+destFileName);
+            log.setUserId(user.getId());
+            log.setUserName(user.getName());
+            log.setYmonth(yearMonth);
+            log.setRecoverMonthcost(syncUserCost?1:0);
+            log.setRecoverReport(syncHistoryReport?1:0);
+            log.setState(1);//默认审核通过
+            financeImportMapper.insert(log);
         } finally {
             //关闭流
             try {

+ 35 - 40
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/LeaveSheetServiceImpl.java

@@ -17,10 +17,8 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
 
 import javax.annotation.Resource;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -53,7 +51,7 @@ public class LeaveSheetServiceImpl extends ServiceImpl<LeaveSheetMapper, LeaveSh
 
 
     @Override
-    public HttpRespMsg add(LeaveSheet sheet, String userId, String projectAuditorJson) {
+    public HttpRespMsg add(LeaveSheet sheet, String userId) {
         HttpRespMsg msg = new HttpRespMsg();
         boolean isNew = false;
         if (sheet.getId() == null) {
@@ -80,41 +78,26 @@ public class LeaveSheetServiceImpl extends ServiceImpl<LeaveSheetMapper, LeaveSh
                 msg.setError("该时间段已有请假申请,不能重复请假");
             } else {
                 //校验当前的指定的项目审核人
-                if (StringUtils.isEmpty(projectAuditorJson)) {
-                    msg.setError("项目审核人不能为空");
-                } else {
-                    //获取第一个审批人
-                    User owner = userMapper.selectById(sheet.getOwnerId());
-                    AuditWorkflowSetting workflowNode = auditWorkflowSettingMapper.selectOne(new QueryWrapper<AuditWorkflowSetting>().eq("type", 0)
-                            .eq("dept_id", owner.getDepartmentId()).orderByAsc("seq").last("limit 1"));
-                    if (workflowNode != null) {
-                        if (workflowNode.getAuditorType() == 0) {
-                            //项目负责人审核, 创建时指定的项目审核人
-
-                        } else if (workflowNode.getAuditorType() == 1) {
-                            //部门负责人
-                            Department dept = departmentMapper.selectById(workflowNode.getAuditDeptId());
-                            sheet.setAuditorId(dept.getManagerId());
-
-                        } else {
-                            //指定一个人审批
-                            sheet.setAuditorId(workflowNode.getUserId());
-                            sheet.setAuditorName(workflowNode.getUserName());
-                        }
+                //获取第一个审批人
+                User owner = userMapper.selectById(sheet.getOwnerId());
+                AuditWorkflowSetting workflowNode = auditWorkflowSettingMapper.selectOne(new QueryWrapper<AuditWorkflowSetting>().eq("type", 0)
+                        .eq("dept_id", owner.getDepartmentId()).orderByAsc("seq").last("limit 1"));
+                if (workflowNode != null) {
+                    if (workflowNode.getAuditorType() == 0) {
+                        //项目负责人审核, 创建时指定的项目审核人
+
+                    } else if (workflowNode.getAuditorType() == 1) {
+                        //部门负责人
+                        Department dept = departmentMapper.selectById(workflowNode.getAuditDeptId());
+                        sheet.setAuditorId(dept.getManagerId());
+
+                    } else {
+                        //指定一个人审批
+                        sheet.setAuditorId(workflowNode.getUserId());
+                        sheet.setAuditorName(workflowNode.getUserName());
                     }
-                    leaveSheetMapper.insert(sheet);
-                    //设置项目的负责人审核
-                    List<String> userIds = JSONArray.parseArray(projectAuditorJson, String.class);
-                    List<LeavePmaudit> pmauditList = new ArrayList<>();
-                    for (String id : userIds) {
-                        LeavePmaudit leavePmaudit = new LeavePmaudit();
-                        leavePmaudit.setLeaveId(sheet.getId());
-                        leavePmaudit.setAuditorId(id);
-                        leavePmaudit.setStatus(0);
-                        pmauditList.add(leavePmaudit);
-                    }
-                    leavePmauditService.saveBatch(pmauditList);
                 }
+                leaveSheetMapper.insert(sheet);
             }
         } else {
             leaveSheetMapper.updateById(sheet);
@@ -145,13 +128,25 @@ public class LeaveSheetServiceImpl extends ServiceImpl<LeaveSheetMapper, LeaveSh
         if (sheet.getLeaveType() != null) {
             queryWrapper.eq("leave_type", sheet.getLeaveType());
         }
-        if (sheet.getStartDate() != null) {
-            queryWrapper.le("start_date", sheet.getStartDate()).gt("end_date", sheet.getEndDate());
+        if (sheet.getStartDate() != null && sheet.getEndDate() != null) {
+            queryWrapper.le("start_date", sheet.getEndDate()).ge("end_date", sheet.getStartDate());
         }
         IPage<LeaveSheet> listIPager = leaveSheetMapper.selectPage(new Page<>(pageIndex, pageSize),
                 queryWrapper);
         List<LeaveSheet> records = listIPager.getRecords();
+        List<String> userIds = records.stream().map(LeaveSheet::getOwnerId).collect(Collectors.toList());
+        if (userIds.size() > 0) {
+            List<User> userList = userMapper.getUserWithDept(new QueryWrapper<User>().in("id", userIds));
+            records.stream().forEach(r->{
+                Optional<User> find = userList.stream().filter(u->u.getId().equals(r.getOwnerId())).findFirst();
+                if (find.isPresent()) {
+                    r.setDept(find.get().getDepartmentName());
+                }
+            });
+        }
+
         Long total = listIPager.getTotal();
+
         Map<String, Object> map = new HashMap<>();
         map.put("records", records);
         map.put("total", total);

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

@@ -1576,7 +1576,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
     }
 
     @Override
-    public HttpRespMsg getOvertimeList(Integer userId, Integer projectId, String startDate, String endDate, HttpServletRequest request) {
+    public HttpRespMsg getOvertimeList(String userId, Integer projectId, String startDate, String endDate, HttpServletRequest request) {
         HttpRespMsg msg = new HttpRespMsg();
         String token = request.getHeader("TOKEN");
         User user = userMapper.selectById(token);
@@ -1585,7 +1585,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
     }
 
     @Override
-    public HttpRespMsg exportOvertimeList(Integer userId, Integer projectId, String startDate, String endDate, HttpServletRequest request) {
+    public HttpRespMsg exportOvertimeList(String userId, Integer projectId, String startDate, String endDate, HttpServletRequest request) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         try {
             String token = request.getHeader("TOKEN");
@@ -2070,7 +2070,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
     }
 
     @Override
-    public HttpRespMsg getOvertimeDetail(Integer userId, Integer projectId, String startDate, String endDate, HttpServletRequest request) {
+    public HttpRespMsg getOvertimeDetail(String userId, Integer projectId, String startDate, String endDate, HttpServletRequest request) {
         HttpRespMsg msg = new HttpRespMsg();
         String token = request.getHeader("TOKEN");
         User user = userMapper.selectById(token);

+ 20 - 14
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -84,6 +84,8 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
     @Resource
     private SysFunctionMapper sysFunctionMapper;
     @Resource
+    private UserDingdingTimeMapper userDingdingTimeMapper;
+    @Resource
     private ReportService reportService;
     @Resource
     ReportExtraDegreeMapper reportExtraDegreeMapper;
@@ -557,26 +559,23 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                 }
             });
             resultMap.put("report", reports);
-            //顺便再获取一下可分配时间
-            Integer totalWorkingTime = 0;
-            //以下区间被认为是工作时间
-            Integer[] workType = {-1, 0, 1, 2, 3, 4, 5};
-            //工作时间筛选
-            List<TimeCalculation> timeCalculations = timeCalculationMapper.selectList(new QueryWrapper<TimeCalculation>()
-                    .eq("date", LocalDate.parse(date, DateTimeFormatter.ofPattern("yyyy-MM-dd")))
-                    .eq("user_id", userId)
-                    .in("action_type", workType));
-            if (timeCalculations != null) {
-                for (TimeCalculation timeCalculation : timeCalculations) {
-                    totalWorkingTime += timeCalculation.getDuration();
+            TimeType timeType = timeTypeMapper.selectById(companyId);
+            System.out.println("getSyncDingding==="+timeType.getSyncDingding());
+            if (timeType.getSyncDingding() == 1) {
+                List<UserDingdingTime> dingdingTimes = userDingdingTimeMapper.selectList(new QueryWrapper<UserDingdingTime>()
+                        .eq("user_id", userId).eq("work_date", date));
+                if (dingdingTimes.size() > 0) {
+                    UserDingdingTime time = dingdingTimes.get(0);
+                    resultMap.put("time", time);
                 }
             }
+
             //把总秒数转为double后换算为小时并保留两位小数
-            resultMap.put("time", new DecimalFormat("0.00").format((double) totalWorkingTime / 3600));
+//            resultMap.put("time", new DecimalFormat("0.00").format((double) totalWorkingTime / 3600));
             //顺便返回该公司全部的项目
             resultMap.put("project", allProjectList);
             //顺便返回公司的工作时间设置
-            resultMap.put("timeType",timeTypeMapper.selectById(companyId));
+            resultMap.put("timeType",timeType);
 
             httpRespMsg.data = resultMap;
         } catch (NullPointerException e) {
@@ -640,6 +639,13 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
 
         //批量新增或更新
         reportService.saveOrUpdateBatch(reportList);
+        //更新任务完成状态
+        List<Integer> finishedTaskIds = reportList.stream().filter(r->r.getTaskId() != null && r.getTaskId() != 0 && r.getTaskFinish() == 1)
+                .map(Report::getTaskId).collect(Collectors.toList());
+        if (finishedTaskIds.size() > 0) {
+            Task fTask = new Task();
+            taskMapper.update(fTask.setTaskStatus(1), new QueryWrapper<Task>().in("id", finishedTaskIds));
+        }
 
         int enginerring = companyMapper.selectById(companyId).getPackageEngineering();
         if (enginerring == 1) {

+ 6 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/application.yml

@@ -129,8 +129,14 @@ corpId: wwf11426cf618e1703
 token: Mhi7ehNX61UN4MB7PHnC
 encodingAesKey: PHVMkME1XMrImmGJZ4OZJxSysI7hFEhtDDUQrlHAfIS
 
+#钉钉企业内部应用参数
+dingding:
+  appkey: dingspmh9hturxaqbauc
+  appsecret: ivx71XoC_WUCSYkihioa-O7SvOpwGz8oJnTQjOgsg-K6jI1FPHB5Q5L1CBaf1I6j
 
 configEnv:
   isDev: true
+  # 是否是私有化部署,企业内部应用
+  isPrivateDeploy: false
 
 

+ 5 - 4
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml

@@ -343,8 +343,8 @@
     <!--获取加班统计报表 -->
     <select id="getOvertimeList" resultType="java.util.Map">
         SELECT report.`creator_id` AS userId, user.`name` AS username, SUM(report.`working_time`) AS workingTime,
-        SUM(report.`overtime_hours`) AS overtimeHours,
-        SUM(report.overtime_cost) AS cost FROM report LEFT JOIN user ON user.id = report.`creator_id`
+        IFNULL(SUM(report.`overtime_hours`),0) AS overtimeHours,
+        IFNULL(SUM(report.overtime_cost), 0) AS cost FROM report LEFT JOIN user ON user.id = report.`creator_id`
         WHERE report.is_overtime = 1
         and report.`state` = 1
         AND report.`create_date` BETWEEN #{startDate} and #{endDate}
@@ -361,8 +361,8 @@
     <!-- 获取某个员工的某时间段内的加班详情 -->
     <select id="getOvertimeDetail" resultType="java.util.Map">
         SELECT date_format(report.`create_date`, '%Y-%m-%d') AS createDate, report.`creator_id` AS userId, user.`name` AS username, SUM(report.`working_time`) AS workingTime,
-        SUM(report.`overtime_hours`) AS overtimeHours,
-        SUM(report.overtime_cost) AS cost FROM report LEFT JOIN user ON user.id = report.`creator_id`
+        IFNULL(SUM(report.`overtime_hours`), 0) AS overtimeHours,
+        IFNULL(SUM(report.overtime_cost), 0) AS cost FROM report LEFT JOIN user ON user.id = report.`creator_id`
         WHERE report.is_overtime = 1
         and report.`state` = 1
         AND report.`create_date` BETWEEN #{startDate} and #{endDate}
@@ -373,6 +373,7 @@
         <if test="userId != null">
             AND report.`creator_id` = #{userId}
         </if>
+        group by report.create_date
     </select>
     <!--按照项目内的阶段名称分组统计工时-->
     <select id="getDegreeCost" resultType="java.util.Map">

+ 4 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/TimeTypeMapper.xml

@@ -26,11 +26,14 @@
         <result column="custom_data_name" property="customDataName" />
         <result column="finance_audit" property="financeAudit" />
         <result column="overtime_ratio" property="overtimeRatio" />
+        <result column="sync_dingding" property="syncDingding" />
+        <result column="is_cro" property="isCro" />
+        <result column="only_importreport" property="onlyImportreport" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        company_id, allday, am, pm, month_days, hour_cost_input_type, type, pay_overtime, alert_time, multi_worktime, fix_monthcost, fill_months, custom_degree_active, custom_degree_name, alert_msg, sync_corpwx_time, need_dept_audit, report_workflow, custom_data_active, custom_data_name, finance_audit, overtime_ratio
+        company_id, allday, am, pm, month_days, hour_cost_input_type, type, pay_overtime, alert_time, multi_worktime, fix_monthcost, fill_months, custom_degree_active, custom_degree_name, alert_msg, sync_corpwx_time, need_dept_audit, report_workflow, custom_data_active, custom_data_name, finance_audit, overtime_ratio, sync_dingding, is_cro, only_importreport
     </sql>
 
 </mapper>

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

@@ -14,11 +14,12 @@
         <result column="end_time" property="endTime" />
         <result column="week_day" property="weekDay" />
         <result column="week_day_txt" property="weekDayTxt" />
+        <result column="work_hours" property="workHours" />
     </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
+        id, work_date, dingding_userid, user_id, dingding_corpid, company_id, start_time, end_time, week_day, week_day_txt, work_hours
     </sql>
 
 </mapper>

+ 12 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserMapper.xml

@@ -30,7 +30,12 @@
         <result column="inactive_date" property="inactiveDate" />
         <result column="position" property="position" />
     </resultMap>
-
+    <resultMap id="BaseResultMap2" type="com.management.platform.entity.User">
+        <id column="id" property="id" />
+        <result column="name" property="name" />
+        <result column="department_id" property="departmentId" />
+        <result column="department_name" property="departmentName" />
+    </resultMap>
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
         id, name, phone, password, portrait_url, create_time, role, company_id, department_id, department_cascade, cost, month_cost, salary_type, manage_dept_id, color, is_active, wx_openid, role_id, role_name, cost_apply_date, dingding_userid, dingding_unionid, corpwx_userid, inactive_date, position
@@ -102,7 +107,7 @@
     <select id="getProjectPushUserList" resultType="java.util.Map">
         SELECT a.id, a.wx_openid as wxOpenid, a.corpwx_userid as corpwxUserid
         FROM user AS a
-        WHERE  a.wx_openid IS NOT NULL
+        WHERE a.wx_openid IS NOT NULL
         AND a.is_active = 1
         AND a.id in (select user_id from participation where project_id = #{projectId})
     </select>
@@ -110,4 +115,9 @@
         select id, name from user
         ${ew.customSqlSegment}
     </select>
+
+    <select id="getUserWithDept" resultMap="BaseResultMap2">
+        select user.id, name, department.department_name from user left join department on department.department_id = user.department_id
+        ${ew.customSqlSegment}
+    </select>
 </mapper>

+ 1 - 3
fhKeeper/formulahousekeeper/timesheet/src/main.js

@@ -184,7 +184,7 @@ router.beforeEach((to, from, next) => {
                     getRoutes = arr;
 
                     //同步企业微信考勤打卡的情况下,根据深圳赛元微电子的要求,屏蔽项目报告审核模块
-                    if (user.timeType.syncCorpwxTime == 1) {
+                    if (user.timeType.onlyImportreport == 1) {
                         getRoutes = getRoutes.filter(r=>{return r.name != '项目报告审核'});
                     }
                     //检查是否开启了自定义审批流
@@ -198,8 +198,6 @@ router.beforeEach((to, from, next) => {
                     router.options.routes = fixedRouter.concat(getRoutes);
                     router.push({ path: to.path })
                 }
-                
-                
             }
         }
         next()

+ 8 - 1
fhKeeper/formulahousekeeper/timesheet/src/views/workReport/daily.vue

@@ -245,6 +245,10 @@
                     <el-input-number :disabled="!canEdit" v-if="reportTimeType.type == 3" style="margin-left:10px;" @change="changeAllTime"
                         v-model="reportTimeType.allday" :precision="1" :step="0.5" :max="12" :min="0.5"></el-input-number>
                     <span v-if="reportTimeType.type == 3">小时</span>
+
+                    <span v-if="workForm.time">考勤打卡: {{workForm.time.startTime}}-{{workForm.time.endTime}}, {{workForm.time.workHours}}小时</span>
+                    <span v-if="user.timeType.syncDingding==1&&!workForm.time">暂无考勤记录</span>
+                    
                 </el-form-item>
                 
                 <div v-for="(domain, index) in workForm.domains" :key="domain.id" :style="index>0?'margin-top:10px;':''">
@@ -3258,17 +3262,19 @@
                                     auditUserList: list.report[i].auditUserList,
                                     projectAuditorId: list.report[i].projectAuditorId,
                                     projectAuditorName: list.report[i].projectAuditorName,
-                                    overtimeHours: list.report[i].overtimeHours
+                                    overtimeHours: list.report[i].overtimeHours,
                                 })
                                 if (list.report[i].state >= 2) {
                                     this.canEdit = true;
                                 }
                             }
+                            alert(list.time);
                             this.workForm = {
                                 createDate: this.workForm.createDate,
                                 domains: arr,
                                 userNames:null,
                                 userId:null,
+                                time: list.time
                             }
                         } else {
                             this.workForm = {
@@ -3286,6 +3292,7 @@
                                 }],
                                 userId:null,
                                 userNames:null,
+                                time: this.report.time
                             }
                             this.canEdit = true;
                         }