Bläddra i källkod

自定义薪资项

seyason 3 år sedan
förälder
incheckning
35abc22724
35 ändrade filer med 1185 tillägg och 135 borttagningar
  1. BIN
      fhKeeper/formulahousekeeper/inva_4_tivo/images/qr_dingding.png
  2. 6 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/DingDingController.java
  3. 52 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/FinanceController.java
  4. 91 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/FinanceTblcuscolController.java
  5. 4 4
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java
  6. 117 60
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java
  7. 101 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportExtraDegreeController.java
  8. 3 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java
  9. 19 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Finance.java
  10. 45 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/FinanceTblcuscol.java
  11. 5 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ProjectSumItem.java
  12. 48 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ReportExtraDegree.java
  13. 19 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/TimeType.java
  14. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/FinanceTblcuscolMapper.java
  15. 2 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProjectMapper.java
  16. 19 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ReportExtraDegreeMapper.java
  17. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/DingDingService.java
  18. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/FinanceTblcuscolService.java
  19. 2 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectService.java
  20. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ReportExtraDegreeService.java
  21. 73 22
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DingDingServiceImpl.java
  22. 105 4
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FinanceServiceImpl.java
  23. 20 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FinanceTblcuscolServiceImpl.java
  24. 11 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/LeaveSheetServiceImpl.java
  25. 17 13
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java
  26. 20 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportExtraDegreeServiceImpl.java
  27. 24 19
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/Tess4jDemo.java
  28. 181 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/WorkDayCalculateUtils.java
  29. 4 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/FinanceMapper.xml
  30. 17 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/FinanceTblcuscolMapper.xml
  31. 6 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml
  32. 21 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportExtraDegreeMapper.xml
  33. 4 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/TimeTypeMapper.xml
  34. 80 1
      fhKeeper/formulahousekeeper/timesheet/src/views/project/finance.vue
  35. 19 0
      fhKeeper/formulahousekeeper/timesheet/src/views/settings/timetype.vue

BIN
fhKeeper/formulahousekeeper/inva_4_tivo/images/qr_dingding.png


+ 6 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/DingDingController.java

@@ -152,7 +152,7 @@ public class DingDingController {
                                 if ("org_micro_app_scope_update".equals(syncAction)) {
                                     //授权范围变更,我们尝试重新获取组织结构
                                     String corpid = bizItem.getString("corp_id");
-                                    System.out.println("==Push 推送事件 使用范围变更===");
+                                    System.out.println("==Push 推送事件 使用范围变更=调用syncCorpMembs, corpid==="+corpid);
                                     try {
                                         dingDingService.syncCorpMembs(corpid);
                                     } catch (ApiException e) {
@@ -205,4 +205,9 @@ public class DingDingController {
         return msg;
     }
 
+    @RequestMapping("/syncCorpInfo")
+    public HttpRespMsg syncCorpInfo(String corpid) {
+        return dingDingService.syncCorpInfo(corpid);
+    }
+
 }

+ 52 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/FinanceController.java

@@ -1,8 +1,15 @@
 package com.management.platform.controller;
 
 
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.management.platform.entity.Company;
+import com.management.platform.entity.FinanceTblcuscol;
+import com.management.platform.mapper.CompanyMapper;
+import com.management.platform.mapper.FinanceTblcuscolMapper;
 import com.management.platform.service.FinanceService;
+import com.management.platform.util.ExcelUtil;
 import com.management.platform.util.HttpRespMsg;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.web.bind.annotation.RequestMapping;
 
 import org.springframework.web.bind.annotation.RequestParam;
@@ -11,6 +18,9 @@ import org.springframework.web.multipart.MultipartFile;
 
 import javax.annotation.Resource;
 import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -26,6 +36,13 @@ public class FinanceController {
 
     @Resource
     private FinanceService financeService;
+    @Resource
+    private FinanceTblcuscolMapper financeTblcuscolMapper;
+    @Resource
+    private CompanyMapper companyMapper;
+
+    @Value(value = "${upload.path}")
+    private String path;
 
     @RequestMapping("/getByMonth")
     public HttpRespMsg getByMonth(Integer companyId, String yearMonth) {
@@ -56,6 +73,41 @@ public class FinanceController {
     }
 
 
+    /**
+     * 获取财务报表模板
+     * @param companyId
+     * @return
+     */
+    @RequestMapping("/getTemplate")
+    public HttpRespMsg getTemplate(Integer companyId) {
+        List<FinanceTblcuscol> list = financeTblcuscolMapper.selectList(new QueryWrapper<FinanceTblcuscol>().eq("company_id", companyId));
+        HttpRespMsg msg = new HttpRespMsg();
+        if (list.size() == 0) {
+            //没有自定义的薪资项
+            msg.data = "/upload/财务人员成本模板.xlsx";
+        } else {
+            List<String> heads = new ArrayList<>();
+            Company company = companyMapper.selectById(companyId);
+            heads.add("姓名");
+            heads.add("工资");
+            heads.add("奖金");
+            heads.add("津贴");
+            heads.add("养老保险");
+            heads.add("医疗保险");
+            heads.add("失业保险");
+            heads.add("住房公积金");
+            heads.add("其他");
+            if (list.size() > 0) {
+                List<String> collect = list.stream().map(FinanceTblcuscol::getFieldName).collect(Collectors.toList());
+                heads.addAll(collect);
+            }
+            List<List<String>> allList = new ArrayList<>();
+            allList.add(heads);
+            String fileName = company.getCompanyName()+"_财务人员成本模板";
+            msg.data = ExcelUtil.exportGeneralExcelByTitleAndList(fileName, allList, path);
+        }
 
+        return msg;
+    }
 }
 

+ 91 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/FinanceTblcuscolController.java

@@ -0,0 +1,91 @@
+package com.management.platform.controller;
+
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.management.platform.entity.Finance;
+import com.management.platform.entity.FinanceTblcuscol;
+import com.management.platform.mapper.FinanceTblcuscolMapper;
+import com.management.platform.mapper.UserMapper;
+import com.management.platform.util.HttpRespMsg;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-12-17
+ */
+@RestController
+@RequestMapping("/finance-tblcuscol")
+public class FinanceTblcuscolController {
+
+    @Resource
+    private HttpServletRequest request;
+    @Resource
+    private FinanceTblcuscolMapper financeTblcuscolMapper;
+    @Resource
+    private UserMapper userMapper;
+
+    @RequestMapping("/get")
+    public HttpRespMsg get(Integer companyId) {
+
+        List<FinanceTblcuscol> list = financeTblcuscolMapper.selectList(new QueryWrapper<FinanceTblcuscol>().eq("company_id", companyId));
+        HttpRespMsg msg = new HttpRespMsg();
+        msg.data = list;
+        return msg;
+    }
+
+    @RequestMapping("/save")
+    public HttpRespMsg addOrMod(String field1, String field2, String field3) {
+        String token = request.getHeader("TOKEN");
+        int companyId = userMapper.selectById(token).getCompanyId();
+        financeTblcuscolMapper.delete(new QueryWrapper<FinanceTblcuscol>().eq("company_id", companyId));
+        if (!StringUtils.isEmpty(field1)) {
+            FinanceTblcuscol col = new FinanceTblcuscol();
+            col.setCompanyId(companyId);
+            col.setFieldName(field1);
+            financeTblcuscolMapper.insert(col);
+        }
+
+        if (!StringUtils.isEmpty(field2)) {
+            FinanceTblcuscol col = new FinanceTblcuscol();
+            col.setCompanyId(companyId);
+            col.setFieldName(field2);
+            financeTblcuscolMapper.insert(col);
+        }
+
+        if (!StringUtils.isEmpty(field3)) {
+            FinanceTblcuscol col = new FinanceTblcuscol();
+            col.setCompanyId(companyId);
+            col.setFieldName(field3);
+            financeTblcuscolMapper.insert(col);
+        }
+
+
+        return new HttpRespMsg();
+    }
+
+    @RequestMapping("/delete")
+    public HttpRespMsg delete(Integer id) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String token = request.getHeader("TOKEN");
+        int companyId = userMapper.selectById(token).getCompanyId();
+        FinanceTblcuscol financeTblcuscol = financeTblcuscolMapper.selectById(id);
+        if (financeTblcuscol.getCompanyId() == companyId) {
+            financeTblcuscolMapper.deleteById(id);
+        } else {
+            msg.setError("无权操作");
+        }
+        return msg;
+    }
+}
+

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

@@ -115,16 +115,16 @@ public class ProjectController {
      * 获取查询者所在公司每个项目的工时成本
      */
     @RequestMapping("/getTimeCost")
-    public HttpRespMsg getTimeCost(String startDate, String endDate) {
-        return projectService.getTimeCost(startDate, endDate, request);
+    public HttpRespMsg getTimeCost(String startDate, String endDate, String userId) {
+        return projectService.getTimeCost(startDate, endDate, userId, request);
     }
 
     /**
      * 导出查询者所在公司每个项目的工时成本
      */
     @RequestMapping("/exportTimeCost")
-    public HttpRespMsg exportTimeCost(String startDate, String endDate, Integer projectId) {
-        return projectService.exportTimeCost(startDate, endDate, projectId, request);
+    public HttpRespMsg exportTimeCost(String startDate, String endDate, Integer projectId, String userId) {
+        return projectService.exportTimeCost(startDate, endDate, projectId, userId, request);
     }
 
     /**

+ 117 - 60
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java

@@ -5,16 +5,15 @@ import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.github.pagehelper.util.StringUtil;
-import com.management.platform.entity.Report;
-import com.management.platform.entity.ReportProfessionProgress;
-import com.management.platform.entity.User;
-import com.management.platform.entity.UserSalary;
+import com.management.platform.entity.*;
 import com.management.platform.entity.vo.WorktimeItem;
+import com.management.platform.mapper.TimeTypeMapper;
 import com.management.platform.service.ReportService;
 import com.management.platform.service.UserSalaryService;
 import com.management.platform.service.UserService;
 import com.management.platform.util.HttpRespMsg;
 import com.management.platform.util.ListUtil;
+import com.management.platform.util.WorkDayCalculateUtils;
 import org.apache.log4j.helpers.DateTimeDateFormat;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -28,6 +27,7 @@ import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.time.DayOfWeek;
 import java.time.LocalDate;
+import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.ArrayList;
 import java.util.Date;
@@ -53,6 +53,9 @@ public class ReportController {
     private UserService userService;
     @Resource
     private UserSalaryService userSalaryService;
+    @Resource
+    private TimeTypeMapper timeTypeMapper;
+
 
     /**
      * 根据时间 按照人分类 获取报告信息
@@ -212,7 +215,44 @@ public class ReportController {
         }
 
         SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
-
+        //判断当前操作的人员,是不是系统管理员
+        if (user.getRole() != 1 && user.getRole() != 2) {
+            //非系统管理员,检查填报时间
+            TimeType compTimeType = timeTypeMapper.selectById(user.getCompanyId());
+            Integer fillMonths = compTimeType.getFillMonths();
+
+            if (fillMonths > 0) {
+                //有限制的情况
+                LocalDate curMonth = LocalDate.now();
+                LocalDate doorMonth = curMonth.minusMonths(fillMonths-1);
+                doorMonth = doorMonth.withDayOfMonth(1);//修改日期为1号
+                DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+                //检查填报日期,是否早于限制的日期
+                boolean isForbidden = false;
+                if (createDate.length > 0) {
+                    //日期都是一样的,取第一个就行了
+                    String createDateOne = createDate[0];
+                    if (createDateOne.contains("@")) {
+                        String[] dateArray = createDateOne.split("@");
+                        String startDate = dateArray[0];
+                        LocalDate localStartDate = LocalDate.parse(startDate, dateTimeFormatter);
+                        if (localStartDate.isBefore(doorMonth)) {
+                            isForbidden = true;
+                        }
+                    } else {
+                        //单日填报,检查日期是否早于限制时间
+                        if (LocalDate.parse(createDateOne, dateTimeFormatter).isBefore(doorMonth)) {
+                            isForbidden = true;
+                        }
+                    }
+                }
+                if (isForbidden) {
+                    HttpRespMsg msg = new HttpRespMsg();
+                    msg.setError("补填日报不可早于"+dateTimeFormatter.format(doorMonth)+",请联系系统管理员代填。");
+                    return msg;
+                }
+            }
+        }
         try {
             for (int i = 0; i < id.length; i++) {
                 System.out.println("==@@"+createDate[i]+", "+createDate[i].contains("@"));
@@ -239,14 +279,46 @@ public class ReportController {
                         return msg;
                     }
 
-                    LocalDate localStartDate = LocalDate.parse(startDate, ddtf);
-                    LocalDate localEndDate = LocalDate.parse(endDate, ddtf);
-                    int daysOffset = 0;
-                    while(true) {
-                        localStartDate = localStartDate.plusDays(daysOffset);
-                        //跳过周末
-                        if (localStartDate.getDayOfWeek() != DayOfWeek.SATURDAY && localStartDate.getDayOfWeek() != DayOfWeek.SUNDAY) {
-                            if (targetUserList == null) {
+//                    LocalDate localStartDate = LocalDate.parse(startDate, ddtf);
+//                    LocalDate localEndDate = LocalDate.parse(endDate, ddtf);
+                    List<LocalDate> workDaysListInRange = WorkDayCalculateUtils.getWorkDaysListInRange(startDate, endDate);
+                    for (LocalDate localStartDate : workDaysListInRange) {
+                        if (targetUserList == null) {
+                            Report report = new Report()
+                                    .setId(id[i] == -1 ? null : id[i])
+                                    .setProjectId(projectId[i])
+                                    .setSubProjectId(subProjectId[i] == 0?null:subProjectId[i])
+                                    .setReportTimeType(reportTimeType[i])
+                                    .setMultiWorktime(multiWorktime[i])
+                                    .setContent(content[i])
+                                    .setState(0)
+                                    .setPicAdd(pics!=null?pics[i]:null)
+                                    .setStage(stage != null && stage.length > 0 && !StringUtil.isEmpty(stage[i])?stage[i]:null)
+                                    .setCreateDate(localStartDate)
+                                    .setCreatorId(token);
+                            if (taskId != null && taskId[i] != null && taskId[i] != 0) {
+                                report.setTaskId(taskId[i]);
+                            }
+                            if (isOvertime != null && isOvertime[i] != null) {
+                                report.setIsOvertime(isOvertime[i]);
+                            }
+                            if (progress != null && progress[i] != null) {
+                                report.setProgress(progress[i]);
+                            }
+                            //计算工时和成本
+                            if (report.getMultiWorktime() == 0) {
+                                fillReportHours(report, hourCost, workingTime==null?null:workingTime[i], timeType==null?null:timeType[i], startTime==null?null:startTime[i], endTime==null?null:endTime[i],  sdf);
+                            } else {
+                                fillReportHours(report, hourCost, workingTime==null?null:workingTime[i], timeType==null?null:timeType[i], null, null, sdf);
+                            }
+
+
+                            //项目专业的进展
+                            fillReportProgress(report, professionProgress[i]);
+                            reportList.add(report);
+                        } else {
+                            //批量代填报的
+                            for (User subsUser : targetUserList) {
                                 Report report = new Report()
                                         .setId(id[i] == -1 ? null : id[i])
                                         .setProjectId(projectId[i])
@@ -254,11 +326,11 @@ public class ReportController {
                                         .setReportTimeType(reportTimeType[i])
                                         .setMultiWorktime(multiWorktime[i])
                                         .setContent(content[i])
-                                        .setState(0)
+                                        .setStage(stage!=null && stage.length > 0  && !StringUtil.isEmpty(stage[i])?stage[i]:null)
+                                        .setState(1)//代填,直接是审核通过状态
                                         .setPicAdd(pics!=null?pics[i]:null)
-                                        .setStage(stage != null && stage.length > 0 && !StringUtil.isEmpty(stage[i])?stage[i]:null)
                                         .setCreateDate(localStartDate)
-                                        .setCreatorId(token);
+                                        .setCreatorId(subsUser.getId());
                                 if (taskId != null && taskId[i] != null && taskId[i] != 0) {
                                     report.setTaskId(taskId[i]);
                                 }
@@ -275,55 +347,27 @@ public class ReportController {
                                     fillReportHours(report, hourCost, workingTime==null?null:workingTime[i], timeType==null?null:timeType[i], null, null, sdf);
                                 }
 
-
-                                //项目专业的进展
                                 fillReportProgress(report, professionProgress[i]);
                                 reportList.add(report);
-                            } else {
-                                //批量代填报的
-                                for (User subsUser : targetUserList) {
-                                    Report report = new Report()
-                                            .setId(id[i] == -1 ? null : id[i])
-                                            .setProjectId(projectId[i])
-                                            .setSubProjectId(subProjectId[i] == 0?null:subProjectId[i])
-                                            .setReportTimeType(reportTimeType[i])
-                                            .setMultiWorktime(multiWorktime[i])
-                                            .setContent(content[i])
-                                            .setStage(stage!=null && stage.length > 0  && !StringUtil.isEmpty(stage[i])?stage[i]:null)
-                                            .setState(1)//代填,直接是审核通过状态
-                                            .setPicAdd(pics!=null?pics[i]:null)
-                                            .setCreateDate(localStartDate)
-                                            .setCreatorId(subsUser.getId());
-                                    if (taskId != null && taskId[i] != null && taskId[i] != 0) {
-                                        report.setTaskId(taskId[i]);
-                                    }
-                                    if (isOvertime != null && isOvertime[i] != null) {
-                                        report.setIsOvertime(isOvertime[i]);
-                                    }
-                                    if (progress != null && progress[i] != null) {
-                                        report.setProgress(progress[i]);
-                                    }
-                                    //计算工时和成本
-                                    if (report.getMultiWorktime() == 0) {
-                                        fillReportHours(report, hourCost, workingTime==null?null:workingTime[i], timeType==null?null:timeType[i], startTime==null?null:startTime[i], endTime==null?null:endTime[i],  sdf);
-                                    } else {
-                                        fillReportHours(report, hourCost, workingTime==null?null:workingTime[i], timeType==null?null:timeType[i], null, null, sdf);
-                                    }
-
-                                    fillReportProgress(report, professionProgress[i]);
-                                    reportList.add(report);
-                                }
                             }
-
-
-                        }
-
-                        //结束条件
-                        if (localStartDate.isEqual(localEndDate)) {
-                            break;
                         }
-                        daysOffset = 1;
                     }
+//                    int daysOffset = 0;
+//                    while(true) {
+//                        localStartDate = localStartDate.plusDays(daysOffset);
+//                        //跳过周末
+//                        if (localStartDate.getDayOfWeek() != DayOfWeek.SATURDAY && localStartDate.getDayOfWeek() != DayOfWeek.SUNDAY) {
+//
+//
+//
+//                        }
+//
+//                        //结束条件
+//                        if (localStartDate.isEqual(localEndDate)) {
+//                            break;
+//                        }
+//                        daysOffset = 1;
+//                    }
                 } else {
                     if (targetUidList == null) {
                         Report report = new Report()
@@ -583,5 +627,18 @@ public class ReportController {
     public HttpRespMsg exportUserDailyWorkTime(HttpServletRequest request, String month) {
         return reportService.exportUserDailyWorkTime(request, month);
     }
+
+    /**
+     * 计算给定时间段内的工作日数量
+     * @param startDate 开始日期
+     * @param endDate 结束日期
+     * @return
+     */
+    @RequestMapping("/getWorkDays")
+    public HttpRespMsg getWorkDays(String startDate, String endDate) {
+        HttpRespMsg msg = new HttpRespMsg();
+        msg.data = WorkDayCalculateUtils.getWorkDaysCountInRange(startDate, endDate);
+        return msg;
+    }
 }
 

+ 101 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportExtraDegreeController.java

@@ -0,0 +1,101 @@
+package com.management.platform.controller;
+
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.management.platform.entity.CustomerInfo;
+import com.management.platform.entity.Project;
+import com.management.platform.entity.ReportExtraDegree;
+import com.management.platform.entity.User;
+import com.management.platform.mapper.CustomerInfoMapper;
+import com.management.platform.mapper.ProjectMapper;
+import com.management.platform.mapper.ReportExtraDegreeMapper;
+import com.management.platform.mapper.UserMapper;
+import com.management.platform.service.ReportExtraDegreeService;
+import com.management.platform.service.ReportService;
+import com.management.platform.util.HttpRespMsg;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletRequest;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-12-16
+ */
+@RestController
+@RequestMapping("/report-extra-degree")
+public class ReportExtraDegreeController {
+
+    @Resource
+    private HttpServletRequest request;
+    @Resource
+    UserMapper userMapper;
+    @Resource
+    ReportExtraDegreeMapper reportExtraDegreeMapper;
+
+    /**
+     * addOrMod添加或者修改
+     * @param info
+     * @return
+     */
+    @RequestMapping("/addOrMod")
+    public HttpRespMsg addOrMod(ReportExtraDegree info) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String token = request.getHeader("TOKEN");
+        User user = userMapper.selectById(token);
+        if (info.getId() == null) {
+            info.setCompanyId(user.getCompanyId());
+            reportExtraDegreeMapper.insert(info);
+        } else {
+            info.setCompanyId(user.getCompanyId());
+            reportExtraDegreeMapper.updateById(info);
+
+        }
+        return msg;
+    }
+
+    /**
+     * delete删除
+     * @param id
+     * @return
+     */
+    @RequestMapping("/delete")
+    public HttpRespMsg delete(Integer id) {
+        HttpRespMsg msg = new HttpRespMsg();
+        String token = request.getHeader("TOKEN");
+        User user = userMapper.selectById(token);
+        int r = reportExtraDegreeMapper.delete(new QueryWrapper<ReportExtraDegree>().eq("id", id).eq("company_id", user.getCompanyId()));
+        if (r <= 0) {
+            msg.setError("无权删除");
+        }
+        return msg;
+    }
+
+    /**
+     * 获取全部getAll
+     * @return
+     */
+    @RequestMapping("/getAll")
+    public HttpRespMsg getAll() {
+        HttpRespMsg msg = new HttpRespMsg();
+        String token = request.getHeader("TOKEN");
+        User user = userMapper.selectById(token);
+        List<ReportExtraDegree> all = reportExtraDegreeMapper.getAll(user.getCompanyId());
+        msg.data = all;
+        return msg;
+    }
+}
+

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

@@ -402,6 +402,9 @@ public class WeiXinCorpController {
                         //首先生成一个新公司,增加会员的试用一个月
                         company = new Company().setCompanyName(corpName)
                                 .setExpirationDate(LocalDateTime.now().plusMonths(1));
+                        company.setPackageProject(1);
+                        company.setPackageCustomer(1);
+                        company.setPackageExpense(1);
                         companyMapper.insert(company);
 
                         //生成项目的成本基线默认条目

+ 19 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Finance.java

@@ -16,7 +16,7 @@ import lombok.experimental.Accessors;
  * </p>
  *
  * @author Seyason
- * @since 2021-02-18
+ * @since 2021-12-17
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -115,10 +115,27 @@ public class Finance extends Model<Finance> {
     @TableField("ymonth")
     private String ymonth;
 
+    /**
+     * 自定义1
+     */
+    @TableField("custom_field1")
+    private BigDecimal customField1;
+
+    /**
+     * 自定义2
+     */
+    @TableField("custom_field2")
+    private BigDecimal customField2;
+
+    /**
+     * 自定义3
+     */
+    @TableField("custom_field3")
+    private BigDecimal customField3;
 
-    //时薪
     @TableField(exist = false)
     private BigDecimal hourCost;
+
     @Override
     protected Serializable pkVal() {
         return this.id;

+ 45 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/FinanceTblcuscol.java

@@ -0,0 +1,45 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-12-17
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class FinanceTblcuscol extends Model<FinanceTblcuscol> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @TableField("company_id")
+    private Integer companyId;
+
+    /**
+     * 自定义字段名称
+     */
+    @TableField("field_name")
+    private String fieldName;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 5 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ProjectSumItem.java

@@ -15,4 +15,9 @@ public class ProjectSumItem {
     public BigDecimal loseJob;
     public BigDecimal house;
     public BigDecimal other;
+
+    //自定义字段
+    public BigDecimal field1;
+    public BigDecimal field2;
+    public BigDecimal field3;
 }

+ 48 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/ReportExtraDegree.java

@@ -0,0 +1,48 @@
+package com.management.platform.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableField;
+import java.io.Serializable;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-12-16
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class ReportExtraDegree extends Model<ReportExtraDegree> {
+
+    private static final long serialVersionUID=1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 公司id
+     */
+    @TableField("company_id")
+    private Integer companyId;
+
+    /**
+     * 自定义数据内容
+     */
+    @TableField("name")
+    private String name;
+
+
+    @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 2021-11-24
+ * @since 2021-12-16
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -90,6 +90,24 @@ public class TimeType extends Model<TimeType> {
     @TableField("fix_monthcost")
     private Integer fixMonthcost;
 
+    /**
+     * 可补填几个月的, 0-不限制,1-本月,2-上个月,3-上上月
+     */
+    @TableField("fill_months")
+    private Integer fillMonths;
+
+    /**
+     * 工时填报自定义维度是否启用
+     */
+    @TableField("custom_degree_active")
+    private Integer customDegreeActive;
+
+    /**
+     * 工时填报自定义维度名称
+     */
+    @TableField("custom_degree_name")
+    private String customDegreeName;
+
 
     @Override
     protected Serializable pkVal() {

+ 16 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/FinanceTblcuscolMapper.java

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.FinanceTblcuscol;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-12-17
+ */
+public interface FinanceTblcuscolMapper extends BaseMapper<FinanceTblcuscol> {
+
+}

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

@@ -24,9 +24,9 @@ public interface ProjectMapper extends BaseMapper<Project> {
     List<Map<String, Object>> getParticipatedProject(@Param("userId") String userId, @Param("companyId") Integer companyId);
 
     List<Map<String, Object>> getTimeCost(@Param("companyId") Integer companyId, @Param("startDate") String startDate, @Param("endDate") String endDate,
-        @Param("projectId") Integer projectId);
+        @Param("projectId") Integer projectId, @Param("userId") String userId);
 
-    List<Map<String, Object>> getProjectCost(@Param("startDate") String startDate, @Param("endDate") String endDate, @Param("projectId") Integer projectId);
+    List<Map<String, Object>> getProjectCost(@Param("startDate") String startDate, @Param("endDate") String endDate, @Param("projectId") Integer projectId, @Param("userId") String userId);
     @Update("update project set status = 1, finish_date = null where id = #{id}")
     void restartProject(Integer id);
 

+ 19 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ReportExtraDegreeMapper.java

@@ -0,0 +1,19 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.ReportExtraDegree;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+import java.util.List;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-12-16
+ */
+public interface ReportExtraDegreeMapper extends BaseMapper<ReportExtraDegree> {
+
+    public List<ReportExtraDegree> getAll(Integer companyId);
+}

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

@@ -13,4 +13,6 @@ public interface DingDingService {
     HttpRespMsg getUserByCode(String code, String corpid);
 
     public HttpRespMsg testAsync();
+
+    HttpRespMsg syncCorpInfo(String corpid);
 }

+ 16 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/FinanceTblcuscolService.java

@@ -0,0 +1,16 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.FinanceTblcuscol;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-12-17
+ */
+public interface FinanceTblcuscolService extends IService<FinanceTblcuscol> {
+
+}

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

@@ -35,7 +35,7 @@ public interface ProjectService extends IService<Project> {
 
     HttpRespMsg deleteProject(Integer id);
 
-    HttpRespMsg getTimeCost(String startDate, String endDate, HttpServletRequest request);
+    HttpRespMsg getTimeCost(String startDate, String endDate, String userId, HttpServletRequest request);
 
     HttpRespMsg getProjectCost(String startDate, String endDate, Integer projectId, HttpServletRequest request);
 
@@ -43,7 +43,7 @@ public interface ProjectService extends IService<Project> {
 
     HttpRespMsg getAllMembCost(String startDate, String endDate, Integer projectId, HttpServletRequest request);
 
-    HttpRespMsg exportTimeCost(String startDate, String endDate, Integer projectId, HttpServletRequest request);
+    HttpRespMsg exportTimeCost(String startDate, String endDate, Integer projectId,String userId, HttpServletRequest request);
 
     HttpRespMsg updateProgress(Integer id, Integer progress, HttpServletRequest request);
 

+ 16 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ReportExtraDegreeService.java

@@ -0,0 +1,16 @@
+package com.management.platform.service;
+
+import com.management.platform.entity.ReportExtraDegree;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-12-16
+ */
+public interface ReportExtraDegreeService extends IService<ReportExtraDegree> {
+
+}

+ 73 - 22
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/DingDingServiceImpl.java

@@ -122,7 +122,9 @@ public class DingDingServiceImpl implements DingDingService {
         if (oldD == null) {
             //第一次,查询对方企业的accessToken
             SysConfig config = sysConfigMapper.selectOne(new QueryWrapper<SysConfig>().eq("param_key", "dingding_suite_ticket"));
-            OapiServiceGetCorpTokenResponse result = getAuthCorpAccessToken(corpid, config.getParamValue());
+            String suiteTicket = config.getParamValue();
+            System.out.println("查询到suiteTicket==" + suiteTicket);
+            OapiServiceGetCorpTokenResponse result = getAuthCorpAccessToken(corpid, suiteTicket);
             if (result != null) {
                 dingding.setAccessToken(result.getAccessToken());
                 LocalDateTime time = LocalDateTime.now();
@@ -161,23 +163,42 @@ public class DingDingServiceImpl implements DingDingService {
     @Override
     public String syncCorpMembs(String corpid) throws ApiException {
         CompanyDingding dingding = companyDingdingMapper.selectById(corpid);
+        String accessToken = null;
+        if (dingding == null) {
+            System.out.println("corpid不存在=="+corpid);
+            return "调用失败";
+        }
         if (dingding.getExpireTime().isBefore(LocalDateTime.now())) {
             SysConfig config = sysConfigMapper.selectOne(new QueryWrapper<SysConfig>().eq("param_key", "dingding_suite_ticket"));
             OapiServiceGetCorpTokenResponse result = getAuthCorpAccessToken(corpid, config.getParamValue());
             if (result != null) {
-                dingding.setAccessToken(result.getAccessToken());
-                LocalDateTime time = LocalDateTime.now();
-                time = time.plusSeconds(result.getExpiresIn());//设置token过期时间
-                dingding.setExpireTime(time);
-                companyDingdingMapper.updateById(dingding);
+                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());
+                }
             }
+        } else {
+            accessToken = dingding.getAccessToken();
+        }
+        if (accessToken == null) {
+            System.out.println("获取第三方企业accessToke失败");
+            return "调用失败";
+        } else {
+            System.out.println("syncCorpMembs 开始获取部门, accessToken="+accessToken);
+
+            //获取授权的部门
+            getAuthedDeptsAndUsers(dingding, accessToken);
+            return "调用成功";
         }
-        String accessToken = dingding.getAccessToken();
-        System.out.println("syncCorpMembs 开始获取部门, accessToken="+accessToken);
 
-        //获取授权的部门
-        getAuthedDeptsAndUsers(dingding, accessToken);
-        return "调用成功";
 
 //        String rest = getDepartmentList(dingding.getCompanyId(), corpid, accessToken, 1L, null);
 
@@ -247,17 +268,6 @@ public class DingDingServiceImpl implements DingDingService {
     }
 
 
-    public void getCorpAccessToken(String authCorpId) {
-        DefaultDingTalkClient client= new DefaultDingTalkClient("https://oapi.dingtalk.com/service/get_corp_token");
-        OapiServiceGetCorpTokenRequest req= new OapiServiceGetCorpTokenRequest();
-        req.setAuthCorpid(authCorpId);
-        try {
-            OapiServiceGetCorpTokenResponse execute= client.execute(req,suiteKey,suiteSecret,"suiteTicket");
-        } catch (ApiException e) {
-            e.printStackTrace();
-        }
-    }
-
     /**
      * 使用 Token 初始化账号Client
      * @return Client
@@ -369,6 +379,47 @@ public class DingDingServiceImpl implements DingDingService {
         return null;
     }
 
+    @Override
+    public HttpRespMsg syncCorpInfo(String corpid) {
+        //第一次,查询对方企业的accessToken
+        SysConfig config = sysConfigMapper.selectOne(new QueryWrapper<SysConfig>().eq("param_key", "dingding_suite_ticket"));
+        OapiServiceGetCorpTokenResponse result = null;
+        try {
+            String suiteTicket = config.getParamValue();
+            System.out.println("suiteTicket=="+suiteTicket);
+            result = getAuthCorpAccessToken(corpid, suiteTicket);
+            System.out.println("获取企业AccessToken=="+result.getBody());
+            if (result != null) {
+                System.out.println();
+//                CompanyDingding dingding = new CompanyDingding();
+//                dingding.setAccessToken(result.getAccessToken());
+//                LocalDateTime time = LocalDateTime.now();
+//                time = time.plusSeconds(result.getExpiresIn());//设置token过期时间
+//                dingding.setExpireTime(time);
+
+                //获取授权企业信息
+                DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/service/get_auth_info");
+                OapiServiceGetAuthInfoRequest req = new OapiServiceGetAuthInfoRequest();
+                req.setSuiteKey(suiteKey);
+                req.setAuthCorpid(corpid);
+                // 第三方企业应用的填写应用SuiteKey和SuiteSecret。
+                // 定制应用填写应用的CustomKey和CustomSecret。
+                OapiServiceGetAuthInfoResponse rsp = client.execute(req, suiteKey ,suiteSecret ,suiteTicket);
+                System.out.println("获取授权企业信息,名称=="+rsp.getAuthCorpInfo().getCorpName());
+//
+                OapiServiceGetAuthInfoResponse.AuthCorpInfo authCorpInfo = rsp.getAuthCorpInfo();
+                corpAuth(authCorpInfo.getCorpid(), authCorpInfo.getCorpName(), rsp.getAuthUserInfo().getUserId());
+            }
+
+
+        } catch (ApiException e) {
+            e.printStackTrace();
+        }
+
+
+        return null;
+    }
+
     private String getValidCorpAccessToken(String corpid) {
         CompanyDingding companyDingding = companyDingdingMapper.selectById(corpid);
         if (companyDingding.getExpireTime().isBefore(LocalDateTime.now())) {

+ 105 - 4
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FinanceServiceImpl.java

@@ -62,6 +62,9 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
     private ReportService reportService;
     @Resource
     private UserService userService;
+    @Resource
+    private FinanceTblcuscolMapper financeTblcuscolMapper;
+
     @Resource
     private ProjectMapper projectMapper;
     @Value(value = "${upload.path}")
@@ -124,6 +127,8 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                 userTimeList = reportMapper.getUserWorkingTimeByRange(companyId, startStr, endStr);
             }
 
+            List<FinanceTblcuscol> cusColList = financeTblcuscolMapper.selectList(new QueryWrapper<FinanceTblcuscol>().eq("company_id", companyId));
+
             //由于第一行需要指明列对应的标题
             int rowNum = sheet.getLastRowNum();
             for (int rowIndex = 0; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
@@ -135,7 +140,7 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                 if (ExcelUtil.isRowEmpty(row)) {
                     continue;
                 }
-                //姓名	工资	奖金	津贴	养老保险	医疗保险	失业保险	住房公积金	其他
+                //姓名	工资	奖金	津贴	养老保险	医疗保险	失业保险	住房公积金	其他; 可能有自定义的项
                 XSSFCell nameCell = row.getCell(0);
                 XSSFCell salaryCell = row.getCell(1);
                 XSSFCell bonusCell = row.getCell(2);
@@ -145,6 +150,9 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                 XSSFCell inJobCell = row.getCell(6);
                 XSSFCell houseFundCell = row.getCell(7);
                 XSSFCell otherCell = row.getCell(8);
+                XSSFCell field1 = cusColList.size() > 0?row.getCell(9):null;
+                XSSFCell field2 = cusColList.size() > 1?row.getCell(10):null;
+                XSSFCell field3 = cusColList.size() > 2?row.getCell(11):null;
 
 
                 nameCell.setCellType(CellType.STRING);
@@ -156,6 +164,9 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                 inJobCell.setCellType(CellType.STRING);
                 houseFundCell.setCellType(CellType.STRING);
                 if (otherCell != null)otherCell.setCellType(CellType.STRING);
+                if (field1 != null)field1.setCellType(CellType.STRING);
+                if (field2 != null)field2.setCellType(CellType.STRING);
+                if (field3 != null)field3.setCellType(CellType.STRING);
 
                 String name = nameCell.getStringCellValue().trim().replaceAll("\\u00a0", "");
                 Finance finance = new Finance();
@@ -234,6 +245,27 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                         finance.setOthers(value);
                         total = total.add(value);
                     }
+                    if (field1 != null) {
+                        field1.setCellType(CellType.STRING);
+                        String item = field1.getStringCellValue();
+                        BigDecimal value = item != null ? new BigDecimal(item.trim().replaceAll("\\u00a0", "")) : BigDecimal.valueOf(0);
+                        finance.setCustomField1(value);
+                        total = total.add(value);
+                    }
+                    if (field2 != null) {
+                        field2.setCellType(CellType.STRING);
+                        String item = field2.getStringCellValue();
+                        BigDecimal value = item != null ? new BigDecimal(item.trim().replaceAll("\\u00a0", "")) : BigDecimal.valueOf(0);
+                        finance.setCustomField2(value);
+                        total = total.add(value);
+                    }
+                    if (field3 != null) {
+                        field3.setCellType(CellType.STRING);
+                        String item = field3.getStringCellValue();
+                        BigDecimal value = item != null ? new BigDecimal(item.trim().replaceAll("\\u00a0", "")) : BigDecimal.valueOf(0);
+                        finance.setCustomField3(value);
+                        total = total.add(value);
+                    }
                     finance.setTotalCost(total);
 
                     //如果需要更新员工成本
@@ -339,6 +371,8 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         try {
             Integer companyId = userMapper.selectById(request.getHeader("Token")).getCompanyId();
+            final List<FinanceTblcuscol> cusColList = financeTblcuscolMapper.selectList(new QueryWrapper<FinanceTblcuscol>().eq("company_id", companyId));
+
             Map<String, Object> resultMap = new HashMap<>();
             double totalCostTime = 0;
             BigDecimal totalMoneyCost = BigDecimal.valueOf(0);
@@ -350,6 +384,9 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
             BigDecimal totalLoseJob = BigDecimal.valueOf(0);
             BigDecimal totalHouse = BigDecimal.valueOf(0);
             BigDecimal totalOther = BigDecimal.valueOf(0);
+            BigDecimal totalField1 = cusColList.size() > 0?BigDecimal.valueOf(0):null;
+            BigDecimal totalField2 = cusColList.size() > 1?BigDecimal.valueOf(0):null;
+            BigDecimal totalField3 = cusColList.size() > 2?BigDecimal.valueOf(0):null;
 
             List<String> headList = new ArrayList<String>();
             headList.add("项目");
@@ -363,6 +400,9 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
             headList.add("失业保险(元)");
             headList.add("住房公积金(元)");
             headList.add("其他(元)");
+            for (FinanceTblcuscol col : cusColList) {
+                headList.add(col.getFieldName());
+            }
             headList.add("总成本(元)");
             List<List<String>> allList = new ArrayList<List<String>>();
             allList.add(headList);
@@ -413,6 +453,9 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                 BigDecimal loseJob = new BigDecimal(0);
                 BigDecimal house = new BigDecimal(0);
                 BigDecimal other = new BigDecimal(0);
+                BigDecimal field1Item = new BigDecimal(0);
+                BigDecimal field2Item = new BigDecimal(0);
+                BigDecimal field3Item = new BigDecimal(0);
                 if (first.isPresent()) {
                     Finance userFinance = first.get();
                     cost = userFinance.getTotalCost().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
@@ -428,6 +471,15 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                     } else {
                         other = userFinance.getOthers().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
                     }
+                    if (userFinance.getCustomField1() != null) {
+                        field1Item = userFinance.getCustomField1().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
+                    }
+                    if (userFinance.getCustomField2() != null) {
+                        field2Item = userFinance.getCustomField2().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
+                    }
+                    if (userFinance.getCustomField3() != null) {
+                        field3Item = userFinance.getCustomField3().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
+                    }
                 } else {
                     System.out.println("财务数据中未找到用户:"+creatorId);
 
@@ -444,6 +496,9 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                     item.loseJob = item.loseJob.add(loseJob);
                     item.house = item.house.add(house);
                     item.other = item.other.add(other);
+                    item.field1 = item.field1.add(field1Item);
+                    item.field2 = item.field2.add(field2Item);
+                    item.field3 = item.field3.add(field3Item);
                 } else {
                     item = new ProjectSumItem();
                     pList.add(item);
@@ -458,6 +513,9 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                     item.loseJob = loseJob;
                     item.house = house;
                     item.other = other;
+                    item.field1 = field1Item;
+                    item.field2 = field2Item;
+                    item.field3 = field3Item;
                 }
                 totalMoneyCost = totalMoneyCost.add(cost);
                 totalSalary = totalSalary.add(salary);
@@ -468,6 +526,15 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                 totalLoseJob = totalLoseJob.add(loseJob);
                 totalHouse = totalHouse.add(house);
                 totalOther = totalOther.add(other);
+                if (totalField1 != null) {
+                    totalField1 = totalField1.add(field1Item);
+                }
+                if (totalField2 != null) {
+                    totalField2 = totalField2.add(field2Item);
+                }
+                if (totalField3 != null) {
+                    totalField3 = totalField3.add(field3Item);
+                }
             }
 
 
@@ -481,7 +548,15 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
             totalLoseJob = totalLoseJob.setScale(2, BigDecimal.ROUND_HALF_UP);
             totalHouse = totalHouse.setScale(2, BigDecimal.ROUND_HALF_UP);
             totalOther = totalOther.setScale(2, BigDecimal.ROUND_HALF_UP);
-
+            if (totalField1 != null) {
+                totalField1 = totalField1.setScale(2, BigDecimal.ROUND_HALF_UP);
+            }
+            if (totalField2 != null) {
+                totalField2 = totalField2.setScale(2, BigDecimal.ROUND_HALF_UP);
+            }
+            if (totalField3 != null) {
+                totalField3 = totalField3.setScale(2, BigDecimal.ROUND_HALF_UP);
+            }
             pList.forEach(p->{
                 p.cost = p.cost.setScale(2, BigDecimal.ROUND_HALF_UP);
                 p.salary = p.salary.setScale(2, BigDecimal.ROUND_HALF_UP);
@@ -492,6 +567,9 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                 p.loseJob = p.loseJob.setScale(2, BigDecimal.ROUND_HALF_UP);
                 p.house = p.house.setScale(2, BigDecimal.ROUND_HALF_UP);
                 p.other = p.other.setScale(2, BigDecimal.ROUND_HALF_UP);
+                p.field1 = p.field1.setScale(2, BigDecimal.ROUND_HALF_UP);
+                p.field2 = p.field2.setScale(2, BigDecimal.ROUND_HALF_UP);
+                p.field3 = p.field3.setScale(2, BigDecimal.ROUND_HALF_UP);
 
                 //组装写入excel文件的数据,从项目开始,项目下面挂成员
                 List<String> rowData = new ArrayList<String>();
@@ -506,6 +584,15 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                 rowData.add(p.loseJob.toPlainString());
                 rowData.add(p.house.toPlainString());
                 rowData.add(p.other.toPlainString());
+                if (cusColList.size() > 0) {
+                    rowData.add(p.field1.toPlainString());
+                }
+                if (cusColList.size() > 1) {
+                    rowData.add(p.field2.toPlainString());
+                }
+                if (cusColList.size() > 2) {
+                    rowData.add(p.field3.toPlainString());
+                }
                 rowData.add(p.cost.toPlainString());
                 allList.add(rowData);
 
@@ -534,7 +621,9 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                         BigDecimal loseJob = userFinance.getInsuranceLosejob().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
                         BigDecimal house = userFinance.getHouseFund().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
                         BigDecimal other = userFinance.getOthers() == null?new BigDecimal(0):userFinance.getOthers().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
-
+                        BigDecimal field1 = userFinance.getCustomField1() == null? new BigDecimal(0):userFinance.getCustomField1().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
+                        BigDecimal field2 = userFinance.getCustomField2() == null? new BigDecimal(0):userFinance.getCustomField2().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
+                        BigDecimal field3 = userFinance.getCustomField3() == null? new BigDecimal(0):userFinance.getCustomField3().multiply(new BigDecimal(workingTime)).divide(userTime.get(creatorId).workingTime, 4, BigDecimal.ROUND_HALF_UP);
                         membRowData.add(us.getName());
                         membRowData.add(workingTime+"");
                         membRowData.add(salary.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
@@ -545,6 +634,16 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
                         membRowData.add(loseJob.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
                         membRowData.add(house.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
                         membRowData.add(other.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
+                        //自定义字段
+                        if (cusColList.size() > 0) {
+                            membRowData.add(field1.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
+                        }
+                        if (cusColList.size() > 1) {
+                            membRowData.add(field2.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
+                        }
+                        if (cusColList.size() > 2) {
+                            membRowData.add(field3.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
+                        }
                         membRowData.add(cost.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString());
                         allList.add(membRowData);
                     }
@@ -566,7 +665,9 @@ public class FinanceServiceImpl extends ServiceImpl<FinanceMapper, Finance> impl
             sumRow.add(totalHouse.toString());
             sumRow.add(totalOther.toString());
             sumRow.add(totalMoneyCost.toString());
-
+            if (cusColList.size() > 0) sumRow.add(totalField1.toString());
+            if (cusColList.size() > 1) sumRow.add(totalField2.toString());
+            if (cusColList.size() > 2) sumRow.add(totalField3.toString());
             allList.add(sumRow);
             //生成excel文件导出
             String fileName = "财务人员成本_"+System.currentTimeMillis();

+ 20 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/FinanceTblcuscolServiceImpl.java

@@ -0,0 +1,20 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.FinanceTblcuscol;
+import com.management.platform.mapper.FinanceTblcuscolMapper;
+import com.management.platform.service.FinanceTblcuscolService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-12-17
+ */
+@Service
+public class FinanceTblcuscolServiceImpl extends ServiceImpl<FinanceTblcuscolMapper, FinanceTblcuscol> implements FinanceTblcuscolService {
+
+}

+ 11 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/LeaveSheetServiceImpl.java

@@ -35,7 +35,7 @@ public class LeaveSheetServiceImpl extends ServiceImpl<LeaveSheetMapper, LeaveSh
     @Resource
     private UserMapper userMapper;
     @Resource
-    private LeaveSheetMapper  leaveSheetMapper;
+    private LeaveSheetMapper leaveSheetMapper;
     @Resource
     private TimeTypeMapper timeTypeMapper;
 
@@ -53,12 +53,21 @@ public class LeaveSheetServiceImpl extends ServiceImpl<LeaveSheetMapper, LeaveSh
         sheet.setOwnerName(userMapper.selectById(sheet.getOwnerId()).getName());
         sheet.setCompanyId(user.getCompanyId());
         TimeType timeType = timeTypeMapper.selectById(user.getCompanyId());
-        if (sheet.getLeaveType() == 0) {
+        if (sheet.getTimeType() == 0) {
             //按天请假时,计算小时数
             float v = timeType.getAllday() * sheet.getTimeDays();
             sheet.setTimeHours(v);
         }
         if (isNew) {
+            //检查该时间段是否已经有按天请假
+            QueryWrapper<LeaveSheet> queryWrapper = new QueryWrapper<>();
+            queryWrapper.eq("owner_id", sheet.getOwnerId());
+            queryWrapper.nested(wrapper->wrapper.between("start_date", sheet.getStartDate(), sheet.getEndDate()).or().between("end_date", sheet.getStartDate(), sheet.getEndDate()));
+
+            int count = leaveSheetMapper.selectCount(queryWrapper);
+            if (count > 0) {
+                msg.setError("该时间段已有请假申请,不能重复请假");
+            }
             leaveSheetMapper.insert(sheet);
         } else {
             leaveSheetMapper.updateById(sheet);

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

@@ -417,7 +417,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
 
     //获取查询者所在公司每个项目的工时成本
     @Override
-    public HttpRespMsg getTimeCost(String startDate, String endDate, HttpServletRequest request) {
+    public HttpRespMsg getTimeCost(String startDate, String endDate, String userId, HttpServletRequest request) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         try {
             //根据系统配置的员工成本计算方式,按固定时薪还是固定月薪,分情况计算。
@@ -488,7 +488,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                 httpRespMsg.data = resultMap;
 
             } else {
-                List<Map<String, Object>> list = projectMapper.getTimeCost(companyId, startDate, endDate, null);
+                List<Map<String, Object>> list = projectMapper.getTimeCost(companyId, startDate, endDate, null, userId);
                 BigDecimal totalMoneyCost = BigDecimal.valueOf(0);
                 for (Map<String, Object> map : list) {
                     if (!map.containsKey("cost")) {
@@ -516,12 +516,12 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
 
     //导出查询者所在公司每个项目的工时成本,包括项目人员明细统计
     @Override
-    public HttpRespMsg exportTimeCost(String startDate, String endDate,Integer projectId, HttpServletRequest request) {
+    public HttpRespMsg exportTimeCost(String startDate, String endDate,Integer projectId, String userId, HttpServletRequest request) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         try {
             Integer companyId = userMapper.selectById(request.getHeader("Token")).getCompanyId();
             Map<String, Object> resultMap = new HashMap<>();
-            List<Map<String, Object>> list = projectMapper.getTimeCost(companyId, startDate, endDate, projectId);
+            List<Map<String, Object>> list = projectMapper.getTimeCost(companyId, startDate, endDate, projectId, userId);
             BigDecimal totalMoneyCost = BigDecimal.valueOf(0);
             List<String> headList = new ArrayList<String>();
             headList.add("项目");
@@ -549,7 +549,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                 allList.add(rowData);
                 //统计每个项目中的人员时间成本投入
                 int curProjectId = (Integer)map.get("id");
-                List<Map<String, Object>> membList = projectMapper.getProjectCost(startDate, endDate, curProjectId);
+                List<Map<String, Object>> membList = projectMapper.getProjectCost(startDate, endDate, curProjectId, userId);
                 map.put("membList", membList);
                 for (Map<String, Object> membMap : membList) {
                     List<String> membRowData = new ArrayList<String>();
@@ -727,7 +727,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                 TimeType timeType = timeTypeMapper.selectById(companyId);
                 if (timeType.getFixMonthcost() == 0) {
                     Map<String, Object> resultMap = new HashMap<>();
-                    List<Map<String, Object>> list = projectMapper.getProjectCost(startDate, endDate, projectId);
+                    List<Map<String, Object>> list = projectMapper.getProjectCost(startDate, endDate, projectId, null);
                     BigDecimal totalMoneyCost = BigDecimal.valueOf(0);
                     for (Map<String, Object> map : list) {
                         if (!map.containsKey("costMoney")) {
@@ -744,7 +744,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                     endDate = endDate + "-31";
                     List<Map<String, Object>> userMonthTimeCostList = projectMapper.getUserMonthTimeCost(companyId, startDate+"-01", endDate+"-31");
 
-                    List<Map<String, Object>> list = projectMapper.getProjectCost(startDate, endDate, projectId);
+                    List<Map<String, Object>> list = projectMapper.getProjectCost(startDate, endDate, projectId, null);
 
                     //检查财务表中是否已经导入成本
                     List<Finance> financeList = financeMapper.selectList(new QueryWrapper<Finance>().eq("ymonth", startDate).eq("company_id", companyId));
@@ -1281,15 +1281,19 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         HttpRespMsg msg = new HttpRespMsg();
         Integer total = projectMapper.selectCount(new QueryWrapper<Project>().eq("company_id", companyId));
         List<ProjectWithStage> record = projectMapper.selectWithStage(companyId, startIndex, endIndex);
-        //获取全部的列
-        List<Integer> collect = record.stream().map(ProjectWithStage::getId).collect(Collectors.toList());
-        List<Stages> stagesList = stagesMapper.selectList(new QueryWrapper<Stages>().in("project_id", collect));
-        List<String> stageList = stagesList.stream().map(Stages::getStagesName).distinct().collect(Collectors.toList());
-
         HashMap<String, Object> map = new HashMap<>();
         map.put("records", record);
         map.put("total", total);
-        map.put("stages", stageList);
+        //获取全部的列
+        if (record.size() > 0) {
+            List<Integer> collect = record.stream().map(ProjectWithStage::getId).collect(Collectors.toList());
+            List<Stages> stagesList = stagesMapper.selectList(new QueryWrapper<Stages>().in("project_id", collect));
+            List<String> stageList = stagesList.stream().map(Stages::getStagesName).distinct().collect(Collectors.toList());
+            map.put("stages", stageList);
+        } else {
+            map.put("stages", new ArrayList<>());
+        }
+
         msg.data = map;
         return msg;
     }

+ 20 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportExtraDegreeServiceImpl.java

@@ -0,0 +1,20 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.ReportExtraDegree;
+import com.management.platform.mapper.ReportExtraDegreeMapper;
+import com.management.platform.service.ReportExtraDegreeService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2021-12-16
+ */
+@Service
+public class ReportExtraDegreeServiceImpl extends ServiceImpl<ReportExtraDegreeMapper, ReportExtraDegree> implements ReportExtraDegreeService {
+
+}

+ 24 - 19
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/Tess4jDemo.java

@@ -1,6 +1,7 @@
 package com.management.platform.util;
 
 import java.io.File;
+import java.time.LocalDate;
 
 import net.sourceforge.tess4j.ITesseract;
 import net.sourceforge.tess4j.Tesseract;
@@ -12,26 +13,30 @@ import net.sourceforge.tess4j.TesseractException;
 
 public class Tess4jDemo {
     public static void main(String[] args) throws TesseractException {
+        LocalDate now = LocalDate.now();
+        now = now.minusMonths(2-1);
+        now = now.withDayOfMonth(1);
+        System.out.println(now.toString());
 
-        //创建ITesseract接口的实现实例对象
-        ITesseract iTesseract = new Tesseract();
-        //设置tessdata训练库语言包地址,项目根目录下为默认地址可不设置
-        //获取项目路径
-//        String projectPath = System.getProperty("user.dir");
-//        System.out.println(projectPath);
-//        iTesseract.setDatapath(projectPath+"\\src\\main\\java\\com.management.platform.tessdata");
-        //默认识别英文
-//                如果需要识别英文之外的语种,需要指定识别语种,并且需要将对应的语言包放进项目中
-        iTesseract.setLanguage("chi_sim");
-        // 指定本地图片
-        File img = new File("D:\\360MoveData\\Users\\Administrator\\Desktop\\book1.png");
-        //开始识别时间
-        long startTime = System.currentTimeMillis();
-        //识别结果
-        String ocrResult = iTesseract.doOCR(img);
-        // 输出识别结果
-        System.out.println("耗时:" + (System.currentTimeMillis() - startTime) + "ms");
-        System.out.println("识别结果: \n" + ocrResult);
+//        //创建ITesseract接口的实现实例对象
+//        ITesseract iTesseract = new Tesseract();
+//        //设置tessdata训练库语言包地址,项目根目录下为默认地址可不设置
+//        //获取项目路径
+////        String projectPath = System.getProperty("user.dir");
+////        System.out.println(projectPath);
+////        iTesseract.setDatapath(projectPath+"\\src\\main\\java\\com.management.platform.tessdata");
+//        //默认识别英文
+////                如果需要识别英文之外的语种,需要指定识别语种,并且需要将对应的语言包放进项目中
+//        iTesseract.setLanguage("chi_sim");
+//        // 指定本地图片
+//        File img = new File("D:\\360MoveData\\Users\\Administrator\\Desktop\\book1.png");
+//        //开始识别时间
+//        long startTime = System.currentTimeMillis();
+//        //识别结果
+//        String ocrResult = iTesseract.doOCR(img);
+//        // 输出识别结果
+//        System.out.println("耗时:" + (System.currentTimeMillis() - startTime) + "ms");
+//        System.out.println("识别结果: \n" + ocrResult);
 
     }
 }

+ 181 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/WorkDayCalculateUtils.java

@@ -0,0 +1,181 @@
+package com.management.platform.util;
+
+import org.apache.commons.lang3.time.DateFormatUtils;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+
+public class WorkDayCalculateUtils {
+    public static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
+    public static DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+    private static final String KEY_SPECIAL_WORK_DAYS = "work";
+    private static final String KEY_SPECIAL_REST_DAYS = "rest";
+
+    private static final HashMap<String, HashMap> YEAR_DEFINE = new HashMap<>();
+    static {
+        HashMap<String, String[]> map2019 = new HashMap<>();
+        //2019年的除了周末的特殊工作日
+        map2019.put(KEY_SPECIAL_WORK_DAYS, new String[]{"2019-02-02","2019-02-03","2019-04-28","2019-05-05"});
+        //2019年除了周末的特殊休息日,例如国庆中秋春节
+        map2019.put(KEY_SPECIAL_REST_DAYS, new String[]{"2019-01-01",//元旦
+                "2019-02-04", "2019-02-05", "2019-02-06", "2019-02-07", "2021-02-08",//春节
+                "2019-04-05",//清明节
+                "2019-05-01","2019-05-02","2019-05-03",//劳动节
+                "2019-06-07",//端午节
+                "2019-10-01", "2019-10-02","2019-10-03","2019-10-04","2019-10-05","2019-10-06","2019-10-07",//国庆节
+                 });
+        YEAR_DEFINE.put("2019", map2019);
+
+        HashMap<String, String[]> map2020 = new HashMap<>();
+        //2020年的除了周末的特殊工作日
+        map2020.put(KEY_SPECIAL_WORK_DAYS, new String[]{"2020-01-19","2020-04-26","2020-05-09","2020-06-28","2020-10-10"});
+        //2020年除了周末的特殊休息日,例如国庆中秋春节
+        map2020.put(KEY_SPECIAL_REST_DAYS, new String[]{"2020-01-01",//元旦
+                "2020-01-24", "2020-01-27", "2020-02-28", "2020-02-29", "2020-02-30","2020-02-31",//春节
+                "2020-04-04",//清明节
+                "2020-05-01","2020-05-02","2020-05-03","2020-05-04","2020-05-05",//劳动节
+                "2020-06-25","2020-06-26",//端午节
+                "2020-10-01", "2020-10-02","2020-10-03","2020-10-04","2020-10-05","2020-10-06","2020-10-07","2020-10-08",//国庆节
+        });
+        YEAR_DEFINE.put("2020", map2020);
+
+        HashMap<String, String[]> map2021 = new HashMap<>();
+        //除了周末的特殊工作日
+        map2021.put(KEY_SPECIAL_WORK_DAYS, new String[]{"2021-02-07","2021-02-20","2021-04-25","2021-05-08","2021-09-18","2021-09-26","2021-10-09"});
+        //除了周末的特殊休息日,例如国庆中秋春节
+        map2021.put(KEY_SPECIAL_REST_DAYS, new String[]{
+                "2021-01-01",//元旦
+                "2021-02-11", "2021-02-12", "2021-02-15", "2021-02-16", "2021-02-17",//春节
+                "2021-04-05",//清明节
+                "2021-05-03","2021-05-04","2021-05-05",//劳动节
+                "2021-06-14",//端午节
+                "2021-09-20","2021-09-21",//中秋节
+                "2021-10-01", "2021-10-02","2021-10-03","2021-10-04","2021-10-05","2021-10-06","2021-10-07",//国庆节
+        });
+        YEAR_DEFINE.put("2021", map2021);
+
+        HashMap<String, String[]> map2022 = new HashMap<>();
+        //除了周末的特殊工作日
+        map2022.put(KEY_SPECIAL_WORK_DAYS, new String[]{"2022-01-29","2022-01-30","2022-04-02","2022-04-24","2022-05-07","2022-10-08","2022-10-09",});
+        //除了周末的特殊休息日,例如国庆中秋春节
+        map2022.put(KEY_SPECIAL_REST_DAYS, new String[]{
+                "2022-01-03",//元旦
+                "2022-01-31", "2022-02-01", "2022-02-02", "2022-02-03", "2022-02-04",//春节
+                "2022-04-04","2022-04-05",//清明节
+                "2022-05-02","2022-05-03","2022-05-04",//劳动节
+                "2022-06-03",//端午节
+                "2022-09-20","2022-09-21",//中秋节
+                "2022-10-01", "2022-10-02","2022-10-03","2022-10-04","2022-10-05","2022-10-06","2022-10-07",//国庆节
+        });
+        YEAR_DEFINE.put("map2022", map2022);
+
+    }
+
+    /**
+     * 计算给定时间范围内的工作日列表
+     * @param startDate
+     * @param endDate
+     * @return
+     */
+    public static List<LocalDate> getWorkDaysListInRange(String startDate, String endDate) {
+        int daysOffset = 0;
+        LocalDate localStartDate = LocalDate.parse(startDate, dateTimeFormatter);
+        LocalDate localEndDate = LocalDate.parse(endDate, dateTimeFormatter);
+        List<LocalDate> list = new ArrayList<>();
+        while(true) {
+            localStartDate = localStartDate.plusDays(daysOffset);
+            if (isWorkDay(localStartDate)) {
+                list.add(localStartDate);
+            }
+            //到达结束日期,结束计算
+            if (localStartDate.isEqual(localEndDate)) {
+                break;
+            }
+            //每次加一天
+            if (daysOffset == 0) {
+                daysOffset = 1;
+            }
+        }
+        return list;
+    }
+
+    /**
+     * 计算给定时间范围内的工作日天数
+     * @param startDate
+     * @param endDate
+     * @return
+     */
+    public static int getWorkDaysCountInRange(String startDate, String endDate) {
+        int daysOffset = 0;
+        LocalDate localStartDate = LocalDate.parse(startDate, dateTimeFormatter);
+        LocalDate localEndDate = LocalDate.parse(endDate, dateTimeFormatter);
+        int count = 0;
+        while(true) {
+            localStartDate = localStartDate.plusDays(daysOffset);
+            if (isWorkDay(localStartDate)) {
+                count++;
+            }
+            //到达结束日期,结束计算
+            if (localStartDate.isEqual(localEndDate)) {
+                break;
+            }
+            //每次加一天
+            if (daysOffset == 0) {
+                daysOffset = 1;
+            }
+        }
+        return count;
+    }
+
+    private static boolean isInArray(String key, String[] array) {
+        for (int i=0;i<array.length; i++) {
+            if (array[i].equals(key)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public static boolean isWorkDay(LocalDate date) {
+        int year = date.getYear();
+        try {
+            String dateStr = dateTimeFormatter.format(date);
+            Date d = simpleDateFormat.parse(dateStr);
+            boolean isWeekend = date.getDayOfWeek() == DayOfWeek.SATURDAY || date.getDayOfWeek() == DayOfWeek.SUNDAY;
+            if (isWeekend) {
+                //判断周末是否是特殊工作日
+                HashMap<String, String[]> map = YEAR_DEFINE.get(year + "");
+                String[] list = map.get(KEY_SPECIAL_WORK_DAYS);
+                if (isInArray(dateStr, list)) {
+                    //存在特殊工作日
+                    return true;
+                } else {
+                    return false;
+                }
+            } else {
+                //判断常规周一到周五,是否是特殊节假日
+                HashMap<String, String[]> map = YEAR_DEFINE.get(year+"");
+                String[] list = map.get(KEY_SPECIAL_REST_DAYS);
+                if (isInArray(dateStr, list)) {
+                    return false;
+                } else {
+                    return true;
+                }
+            }
+        } catch (ParseException e) {
+            e.printStackTrace();
+            System.out.println(e.getMessage());
+        }
+        return true;
+    }
+
+
+    public static void main(String[] args) {
+        System.out.println(getWorkDaysCountInRange("2019-01-01","2019-12-31"));
+    }
+}

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

@@ -19,11 +19,14 @@
         <result column="others" property="others" />
         <result column="total_cost" property="totalCost" />
         <result column="ymonth" property="ymonth" />
+        <result column="custom_field1" property="customField1" />
+        <result column="custom_field2" property="customField2" />
+        <result column="custom_field3" property="customField3" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, user_id, name, company_id, dept_name, month_cost, bonus, allowance, insurance_old, insurance_medical, insurance_losejob, house_fund, others, total_cost, ymonth
+        id, user_id, name, company_id, dept_name, month_cost, bonus, allowance, insurance_old, insurance_medical, insurance_losejob, house_fund, others, total_cost, ymonth, custom_field1, custom_field2, custom_field3
     </sql>
 
 </mapper>

+ 17 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/FinanceTblcuscolMapper.xml

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.management.platform.mapper.FinanceTblcuscolMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.management.platform.entity.FinanceTblcuscol">
+        <id column="id" property="id" />
+        <result column="company_id" property="companyId" />
+        <result column="field_name" property="fieldName" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, company_id, field_name
+    </sql>
+
+</mapper>

+ 6 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml

@@ -95,6 +95,9 @@
         <if test="projectId != null">
             AND a.id = #{projectId}
         </if>
+        <if test="userId != null">
+            AND b.creator_id = #{userId}
+        </if>
         <if test="startDate != null and endDate != null">
             AND b.create_date between #{startDate} and #{endDate}
         </if>
@@ -141,6 +144,9 @@
         <if test="startDate != null and endDate != null">
             AND a.create_date between #{startDate} and #{endDate}
         </if>
+        <if test="userId != null">
+            AND a.creator_id = #{userId}
+        </if>
         GROUP BY b.id
         ORDER BY b.id ASC
     </select>

+ 21 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportExtraDegreeMapper.xml

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.management.platform.mapper.ReportExtraDegreeMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.management.platform.entity.ReportExtraDegree">
+        <id column="id" property="id" />
+        <result column="company_id" property="companyId" />
+        <result column="name" property="name" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, company_id, name
+    </sql>
+
+    <select id="getAll" resultMap="BaseResultMap">
+        select id, name from report_extra_degree where company_id = #{companyId}
+        ORDER BY id DESC
+    </select>
+</mapper>

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

@@ -15,11 +15,14 @@
         <result column="alert_time" property="alertTime" />
         <result column="multi_worktime" property="multiWorktime" />
         <result column="fix_monthcost" property="fixMonthcost" />
+        <result column="fill_months" property="fillMonths" />
+        <result column="custom_degree_active" property="customDegreeActive" />
+        <result column="custom_degree_name" property="customDegreeName" />
     </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
+        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
     </sql>
 
 </mapper>

+ 80 - 1
fhKeeper/formulahousekeeper/timesheet/src/views/project/finance.vue

@@ -7,7 +7,7 @@
                 <el-date-picker size="small" v-model="date" :editable="false" format="yyyy-MM" value-format="yyyy-MM" @change="changeMonth" :clearable="false" type="month" placeholder="选择月份"></el-date-picker>
             </el-form-item>
             <el-form-item style="float:right;">
-                <el-link type="primary" :underline="false" href="./upload/财务人员成本模板.xlsx" download="财务人员成本模板.xlsx">财务模板下载</el-link>
+                <el-link type="primary" :underline="false" @click="getTemplate()" download="财务人员成本模板.xlsx">财务模板下载</el-link>
             </el-form-item>
             <!-- <el-form-item style="float:right;">
                 <el-upload ref="upload" action="#" :limit="1" :http-request="importFinance" :show-file-list="false">
@@ -17,6 +17,9 @@
             <el-form-item style="float:right;">
                 <el-link type="primary" :underline="false" @click="importDialog = true;isUploading=false;">财务数据上传</el-link>
             </el-form-item>
+            <el-form-item style="float:right;">
+                <el-link type="primary" :underline="false" @click="showItemDialog">自定义薪资项</el-link>
+            </el-form-item>
             </el-form>
         </el-col>
         <!--列表-->
@@ -33,6 +36,11 @@
             <el-table-column prop="insuranceLosejob" label="失业保险" ></el-table-column>
             <el-table-column prop="houseFund" label="住房公积金" ></el-table-column>
             <el-table-column prop="others" label="其他" ></el-table-column>
+            <el-table-column :label="item.fieldName" v-for="(item, index) in customCols" :key="item.id">
+                <template slot-scope="scope">
+                    {{index==0?scope.customField1:(index==1?scope.customField2:(index==2?scope.customField3:''))}}
+                </template>
+            </el-table-column>
             <el-table-column prop="totalCost" label="总成本" ></el-table-column>
         </el-table>
         
@@ -130,6 +138,27 @@
                 <el-button type="primary" @click="showNPDialog = false" >关闭</el-button>
             </div>
         </el-dialog>
+
+        <el-dialog title="自定义薪资项" show-header="false" v-if="itemDialog" :visible.sync="itemDialog" :close-on-click-modal="false" customClass="customWidth" width="500px">
+            <div style="margin-left:30px;">
+            <span style="color:#999;">薪资表包含以下数据</span>
+            <p>工资</p>
+            <p>奖金</p>
+            <p>津贴</p>
+            <p>养老保险</p>
+            <p>医疗保险</p>
+            <p>失业保险</p>
+            <p>住房公积金</p>
+            <p>其他</p>
+            <p><el-input v-model="customFieldList.field1" placeholder="请输入自定义薪资项1名称" style="width:200px;" maxlength="8"></el-input></p>
+            <p><el-input v-model="customFieldList.field2" placeholder="请输入自定义薪资项2名称" style="width:200px;" maxlength="8"></el-input></p>
+            <p><el-input v-model="customFieldList.field3" placeholder="请输入自定义薪资项3名称" style="width:200px;" maxlength="8"></el-input></p>
+            </div>
+            <div slot="footer" class="dialog-footer">
+                <el-button type="primary" @click="itemDialog = false" >关闭</el-button>
+                <el-button type="primary" @click="saveItems()" >保存</el-button>
+            </div>
+        </el-dialog>
     </section>
 </template>
 <style scoped>
@@ -149,6 +178,9 @@
     export default {
         data() {
             return {
+                customFieldList:{field1:null, field2: null, field3: null},
+                itemDialog: false,
+                customCols:[],
                 showNPDialog: false,
                 npUserList:[],
                 hasNoProjectUsers: false,
@@ -170,6 +202,52 @@
             };
         },
         methods: {
+            downloadByA(row) {
+                const a = document.createElement('a'); // 创建a标签
+                a.setAttribute('download', row.name);// download属性
+                a.setAttribute('href', row.url);// href链接
+                a.click();// 自执行点击事件
+                a.remove();
+            },
+            getTemplate() {
+                this.http.post('/finance/getTemplate', {companyId: this.user.companyId},
+                    res => {
+                        if (res.code == "ok") {
+                            this.downloadByA({name:'财务成本报表.xlsx', url:res.data});
+                        }});
+               
+            },
+            saveItems() {
+                this.http.post('/finance-tblcuscol/save', this.customFieldList,
+                    res => {
+                        if (res.code == "ok") {
+                             this.itemDialog = false;
+                            this.getCustomColumn();
+                        }});
+               
+            },
+            showItemDialog() {
+                this.itemDialog = true;
+                this.customFieldList = {field1:null,field2:null, field3:null};
+                for (var i=0;i<this.customCols.length; i++) {
+                    if (i == 0) {
+                        this.customFieldList.field1 = this.customCols[i].fieldName;
+                    } else if (i == 1) {
+                        this.customFieldList.field2 = this.customCols[i].fieldName;
+                    } else if (i == 2) {
+                        this.customFieldList.field3 = this.customCols[i].fieldName;
+                    }
+                }
+                
+            },
+            //获取自定义的字段
+            getCustomColumn() {
+                this.http.post('/finance-tblcuscol/get', {companyId: this.user.companyId},
+                    res => {
+                        if (res.code == "ok") {
+                            this.customCols = res.data;
+                        }});
+            },
             showNoProjectUsers() {
                 this.showNPDialog = true;
                 this.http.post('/finance/getNoProjectUsers', {yearMonth: this.date},
@@ -434,6 +512,7 @@
                 that.tableHeight = window.innerHeight - 245;
             };
             this.getList();
+            this.getCustomColumn();
         },
         updated() {
             this.$nextTick(() => {

+ 19 - 0
fhKeeper/formulahousekeeper/timesheet/src/views/settings/timetype.vue

@@ -167,6 +167,24 @@
             </div>
         </el-col>
         </el-row>
+        <!-- 设置员工可补填的时间 -->
+        <p style="margin-left:10px;color:#666;">普通员工补填日报时间限制</p>
+        <el-row :gutter="20" style="padding-top:10px;width:100%;margin:0 auto;padding-left:10px;padding-right:10px;">
+        <el-col :span="24" >
+            <div class="panel" style="height:60px;">
+                <el-form :inline="true" :model="timeType"  style="margin-top:10px;">
+                 
+                <el-form-item label="补填时间" prop="fillMonths">
+                    <el-select v-model="timeType.fillMonths" >
+                        <el-option v-for="item in monthTimeList" :key="item.id" :label="item.name" :value="item.id">
+                        </el-option>
+                    </el-select>
+                    <span style="color:#666;margin-left:10px;">(说明:系统管理员为员工代填日报时不受补填时间的限制)</span>
+                </el-form-item>
+                </el-form>
+            </div>
+        </el-col>
+        </el-row>
         <div style="width:80px;margin:0 auto;padding:20px;">
             <el-button  type="primary" @click="submitInsert" :loading="addLoading">保存</el-button>
         </div>
@@ -179,6 +197,7 @@
     export default {
         data() {
             return {
+                monthTimeList:[{id:0, name:'不限制'},{id:1, name:'仅可补填当月'},{id:2, name:'可补填到上个月'},{id:3, name:'可补填到上上月'}],
                 progress:30,
                 startTime:null,
                 endTime:null,