Преглед изворни кода

Merge branch 'master' of http://47.100.37.243:10191/wutt/manHourHousekeeper

Min пре 1 година
родитељ
комит
4078ead741
33 измењених фајлова са 2519 додато и 1815 уклоњено
  1. 55 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/EstimateTimeSettingController.java
  2. 4 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ProjectController.java
  3. 57 3
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/ReportController.java
  4. 12 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java
  5. 68 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/EstimateTimeSetting.java
  6. 9 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Project.java
  7. 22 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/LaborHourRateVo.java
  8. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/EstimateTimeSettingMapper.java
  9. 3 2
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ProjectMapper.java
  10. 3 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ReportMapper.java
  11. 5 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/UserMapper.java
  12. 16 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/EstimateTimeSettingService.java
  13. 2 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/ProjectService.java
  14. 20 0
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/EstimateTimeSettingServiceImpl.java
  15. 145 9
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ProjectServiceImpl.java
  16. 11 7
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java
  17. 21 19
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java
  18. 5 10
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/DateTimeUtil.java
  19. 23 1
      fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/WorkDayCalculateUtils.java
  20. 1 1
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/application.yml
  21. 20 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/EstimateTimeSettingMapper.xml
  22. 89 71
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml
  23. 12 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportMapper.xml
  24. 29 0
      fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserMapper.xml
  25. 1 0
      fhKeeper/formulahousekeeper/ops-platform/src/main/java/com/management/platform/mapper/CompanyMapper.java
  26. 8 1
      fhKeeper/formulahousekeeper/timesheet-workshop-h5/src/views/index/index.vue
  27. 4 0
      fhKeeper/formulahousekeeper/timesheet-workshop-h5/src/views/login/index.vue
  28. 5 78
      fhKeeper/formulahousekeeper/timesheet-workshop-h5/src/views/my/children/center.vue
  29. 3 2
      fhKeeper/formulahousekeeper/timesheet-workshop/src/views/plan/planComponent.vue
  30. 1 1
      fhKeeper/formulahousekeeper/timesheet-workshop/src/views/statistic/index.vue
  31. 1739 1596
      fhKeeper/formulahousekeeper/timesheet/src/views/expense/expense.vue
  32. 107 8
      fhKeeper/formulahousekeeper/timesheet/src/views/project/list.vue
  33. 3 3
      fhKeeper/formulahousekeeper/timesheet_h5/src/views/index/index.vue

+ 55 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/EstimateTimeSettingController.java

@@ -0,0 +1,55 @@
+package com.management.platform.controller;
+
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.management.platform.entity.*;
+import com.management.platform.mapper.EstimateTimeSettingMapper;
+import com.management.platform.util.HttpRespMsg;
+import com.management.platform.util.MessageUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author Seyason
+ * @since 2023-11-19
+ */
+@RestController
+@RequestMapping("/estimate-time-setting")
+public class EstimateTimeSettingController {
+
+    @Resource
+    private EstimateTimeSettingMapper estimateTimeSettingMapper;
+
+    @RequestMapping("/get")
+    public HttpRespMsg get(Integer companyId) {
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        EstimateTimeSetting estimateTimeSetting = estimateTimeSettingMapper.selectById(companyId);
+        if (estimateTimeSetting == null) {
+            estimateTimeSetting = new EstimateTimeSetting();
+            estimateTimeSetting.setCompanyId(companyId);
+            estimateTimeSettingMapper.insert(estimateTimeSetting);
+            estimateTimeSetting = estimateTimeSettingMapper.selectById(companyId);
+        }
+        httpRespMsg.data = estimateTimeSetting;
+        return httpRespMsg;
+    }
+
+    @RequestMapping("/save")
+    public HttpRespMsg save(EstimateTimeSetting record) {
+        Boolean success = estimateTimeSettingMapper.updateById(record) > 0;
+        HttpRespMsg httpRespMsg = new HttpRespMsg();
+        if (!success) {
+            httpRespMsg.setError(MessageUtils.message("other.saveError"));
+        }
+        return httpRespMsg;
+    }
+}
+

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

@@ -1414,6 +1414,10 @@ public class ProjectController {
         return projectService.syncProjectWithSap(startDate,endDate);
     }
 
+    @RequestMapping("/getEffectiveLaborHourRate")
+    public HttpRespMsg getEffectiveLaborHourRate(String startDate,String endDate){
+        return projectService.getEffectiveLaborHourRate(startDate,endDate);
+    }
 
 
 }

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

@@ -98,6 +98,8 @@ public class ReportController {
     private UserFvTimeService userFvTimeService;
     @Resource
     private LeaveSheetService leaveSheetService;
+    @Resource
+    private EstimateTimeSettingMapper estimateTimeSettingMapper;
 
     //获取任务相关的日报列表
     @RequestMapping("/getTaskReportList")
@@ -339,6 +341,19 @@ public class ReportController {
         User user = userService.getById(token);
         Company company = companyService.getById(user.getCompanyId());
         TimeType comTimeType = timeTypeMapper.selectById(user.getCompanyId());
+        if (company.getId() == 1336) {
+            //针对三友反馈的填写的日报内容,但是没有显示出来的问题,打印日志进行追踪
+            System.out.println("user: "+user.getId()+", 填写内容是:");
+            if (content != null) {
+                for (int i=0;i<projectId.length; i++) {
+                    if (i < content.length) {
+                        System.out.println("项目:"+i+", "+projectId[i]+", "+content[i]);
+                    } else {
+                        System.out.println("项目:"+i+", "+projectId[i]+", 内容为空");
+                    }
+                }
+            }
+        }
         if (comTimeType.getStopReport() == 1) {
             HttpRespMsg msg = new HttpRespMsg();
             msg.setError("系统已关闭日报填写功能,请联系管理员");
@@ -1118,12 +1133,23 @@ public class ReportController {
         }
 
         //如果开启了项目人天
+        String warningPercentProjects = "";
+        String warningLackProjects = "";
+        EstimateTimeSetting estimateTimeSetting = null;
         if(comTimeType.getProjectManDay()==1){
             Collection<Integer> projectIds = reportList.stream().map(Report::getProjectId).distinct().collect(Collectors.toList());
             List<Report> needCheckReportList = reportMapper.selectList(new QueryWrapper<Report>().in("project_id", projectIds).and(wrapper->wrapper.eq("state",0).or().eq("state",1).or().eq("state",3)));
             List<Project> targetProjectList = projectList.stream().filter(pl -> projectIds.contains(pl.getId())).collect(Collectors.toList());
+            estimateTimeSetting = estimateTimeSettingMapper.selectById(company.getId());
+            //如果没有设置过项目人天,就初始化一下
+            if (estimateTimeSetting == null) {
+                estimateTimeSetting = new EstimateTimeSetting();
+                estimateTimeSetting.setCompanyId(company.getId());
+                estimateTimeSettingMapper.insert(estimateTimeSetting);
+                estimateTimeSetting = estimateTimeSettingMapper.selectById(company.getId());
+            }
             for (Report report : reportList) {
-                    HttpRespMsg httpRespMsg = new HttpRespMsg();
+                HttpRespMsg httpRespMsg = new HttpRespMsg();
                 Optional<Project> first = targetProjectList.stream().filter(tl -> tl.getId().equals(report.getProjectId())).findFirst();
                 if(first.isPresent()){
                     double nowReport = reportList.stream().filter(rl -> rl.getCreateDate().equals(report.getCreateDate()) && rl.getCreatorId().equals(report.getCreatorId())).mapToDouble(Report::getWorkingTime).sum();
@@ -1138,12 +1164,24 @@ public class ReportController {
                         BigDecimal hasReport = new BigDecimal(sum).add(new BigDecimal(nowReport));
                         BigDecimal multiply = new BigDecimal(first.get().getManDay()).multiply(new BigDecimal(comTimeType.getAllday()));
                         if(hasReport.doubleValue()>multiply.doubleValue()){
-                            httpRespMsg.setError("超过当前项目["+first.get().getProjectName()+"]预算工时,无法继续提交工时");
-                            return httpRespMsg;
+                            if (estimateTimeSetting.getProjectFronzeOnLack() == 1) {
+                                httpRespMsg.setError("超过当前项目["+first.get().getProjectName()+"]预算工时,无法继续提交工时");
+                                return httpRespMsg;
+                            } else {
+                                //仅提醒
+                                warningLackProjects += first.get().getProjectName() + ",";
+                            }
+                        } else {
+                            //检查是否超过预设的提醒百分比;设置的数值是剩余的百分比
+                            if (hasReport.divide(multiply, 2, RoundingMode.HALF_UP).multiply(new BigDecimal(100)).compareTo(new BigDecimal(100-estimateTimeSetting.getProjectWarningPercent()))>0) {
+                                warningPercentProjects += first.get().getProjectName() + ",";
+                            }
                         }
                     }
                 }
             }
+
+
         }
 
         //如果锁定工作时长上限的话,需要校验每日的合计工作时长
@@ -1497,6 +1535,22 @@ public class ReportController {
                 approveReport(rIds, 0, request, null);
             }
         }
+
+        String estimateWarningMsg = "";
+        if (estimateTimeSetting != null) {
+            if (!StringUtils.isEmpty(warningLackProjects)) {
+                warningLackProjects = warningLackProjects.substring(0, warningLackProjects.length() -1);
+                estimateWarningMsg += "提交成功,项目["+warningLackProjects+"]预估工时不足,请联系项目经理。";
+            }
+            if (!StringUtils.isEmpty(warningPercentProjects)) {
+                warningPercentProjects = warningPercentProjects.substring(0, warningPercentProjects.length() -1);
+                estimateWarningMsg += "提交成功,项目["+warningPercentProjects+"]预估工时剩余小于"+estimateTimeSetting.getProjectWarningPercent()+"%,请联系项目经理。";
+            }
+            if (!StringUtils.isEmpty(estimateWarningMsg)) {
+                httpRespMsg.setMsg(estimateWarningMsg);
+            }
+        }
+
         return httpRespMsg;
     }
 

+ 12 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/controller/WeiXinCorpController.java

@@ -1714,7 +1714,8 @@ public class WeiXinCorpController {
 
     //获取部门详情
     private JSONObject getDeptDetail(String accessToken, int deptId) {
-        String url = GET_DEPARTMENT_DETAIL_URL.replace("ACCESS_TOKEN", accessToken).replace("ID", ""+deptId);
+        log.info("传参数accessToken="+accessToken+", deptId=="+deptId);
+        String url = GET_DEPARTMENT_DETAIL_URL.replace("ACCESS_TOKEN", accessToken).replace("id=ID", "id="+deptId);
         String result = restTemplate.getForObject(url, String.class);
         log.info("部门详情:"+result);
         JSONObject obj = JSONObject.parseObject(result);
@@ -2664,9 +2665,19 @@ public class WeiXinCorpController {
             } else {
                 //比较是否有更新
                 Department oldDept = first.get();
+                boolean hasUpdate = false;
                 if (oldDept.getCorpwxDeptpid() == null || !oldDept.getCorpwxDeptpid().equals(department.getCorpwxDeptpid())) {
                     //有父部门需要更新
                     oldDept.setCorpwxDeptpid(parentId);
+                    hasUpdate = true;
+                }
+                if ((StringUtils.isEmpty(oldDept.getDepartmentName()) && !StringUtils.isEmpty(department.getDepartmentName()))
+                    ||(!StringUtils.isEmpty(oldDept.getDepartmentName()) && !StringUtils.isEmpty(department.getDepartmentName()) && !oldDept.getDepartmentName().equals(department.getDepartmentName()))) {
+                    //有名称需要更新
+                    oldDept.setDepartmentName(department.getDepartmentName());
+                    hasUpdate = true;
+                }
+                if (hasUpdate) {
                     departmentMapper.updateById(oldDept);
                 }
                 department = oldDept;

+ 68 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/EstimateTimeSetting.java

@@ -0,0 +1,68 @@
+package com.management.platform.entity;
+
+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 2023-11-19
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class EstimateTimeSetting extends Model<EstimateTimeSetting> {
+
+    private static final long serialVersionUID=1L;
+
+    /**
+     * 公司id
+     */
+    @TableId("company_id")
+    private Integer companyId;
+
+    /**
+     * 项目人天填写要求:0-非必填,1-工时系统必填,同步的非必填,2-全部必填
+     */
+    @TableField("project_man_day_fill_mode")
+    private Integer projectManDayFillMode;
+
+    /**
+     * 项目剩余工时低于xx%时开始提示
+     */
+    @TableField("project_warning_percent")
+    private Integer projectWarningPercent;
+
+    /**
+     * 项目预估工时不足时是否禁止填报
+     */
+    @TableField("project_fronze_on_lack")
+    private Integer projectFronzeOnLack;
+
+    /**
+     * 分组剩余工时低于xx%时开始提示
+     */
+    @TableField("group_warning_percent")
+    private Integer groupWarningPercent;
+
+    /**
+     * 分组预估工时不足时是否禁止填报
+     */
+    @TableField("group_fronze_on_lack")
+    private Integer groupFronzeOnLack;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.companyId;
+    }
+
+}

+ 9 - 2
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/Project.java

@@ -25,7 +25,7 @@ import org.springframework.format.annotation.DateTimeFormat;
  * </p>
  *
  * @author Seyason
- * @since 2023-04-20
+ * @since 2023-11-19
  */
 @Data
 @EqualsAndHashCode(callSuper = false)
@@ -340,7 +340,7 @@ public class Project extends Model<Project> {
 
     @TableField(exist = false)
     List<TaskGroup> taskGroupList;
-    
+
     @TableField(exist = false)
     private String levelString;
 
@@ -452,6 +452,13 @@ public class Project extends Model<Project> {
     @TableField(exist = false)
     private List<SubProject> subProjectList;
 
+    /**
+     * 是否是从外部系统同步的项目
+     */
+    @TableField("from_outside")
+    private Integer fromOutside;
+
+
     @Override
     protected Serializable pkVal() {
         return this.id;

+ 22 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/entity/vo/LaborHourRateVo.java

@@ -0,0 +1,22 @@
+package com.management.platform.entity.vo;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+public class LaborHourRateVo {
+    private Integer root_id;//大区的id
+    private String department_name;//部门名称
+    private List<Integer> child_ids;//子孙的id列表
+    private Double working_time;//实报工时
+    private Integer count;//在职人数
+    private Integer date_count;//应报工时天数
+    private Integer day_time;//日标准工时
+    private Long total_time;//应报工时
+    private Double rate;//比率
+}

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

@@ -0,0 +1,16 @@
+package com.management.platform.mapper;
+
+import com.management.platform.entity.EstimateTimeSetting;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author Seyason
+ * @since 2023-11-19
+ */
+public interface EstimateTimeSettingMapper extends BaseMapper<EstimateTimeSetting> {
+
+}

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

@@ -29,7 +29,8 @@ public interface ProjectMapper extends BaseMapper<Project> {
 
     List<Map<String, Object>> getTimeCost(@Param("companyId") Integer companyId, @Param("startDate") String startDate, @Param("endDate") String endDate,
                                           @Param("projectId") Integer projectId, @Param("userIdList") List<String> userIdList,
-                                          @Param("deptIds")List<Integer> deptIds,@Param("filterDeptIds")List<Integer> filterDeptIds, @Param("deptRelatedProjectIds") List<Integer> deptRelatedProjectIds, @Param("projectIds") List<Integer> projectIds);
+                                          @Param("deptIds")List<Integer> deptIds,@Param("filterDeptIds")List<Integer> filterDeptIds, @Param("deptRelatedProjectIds") List<Integer> deptRelatedProjectIds,
+                                          @Param("projectIds") List<Integer> projectIds, @Param("inchargeUserIds") List<String> inchargeUserIds);
 
     List<Map<String, Object>> getCustomDataSum(@Param("companyId") Integer companyId, @Param("startDate") String startDate, @Param("endDate") String endDate,
                                           @Param("projectId") Integer projectId, @Param("userId") String userId);
@@ -120,7 +121,7 @@ public interface ProjectMapper extends BaseMapper<Project> {
 
     List<Map<String, Object>> getTimeCostByMainProject(Integer companyId, String startDate, String endDate, Integer projectId, String userId, List<Integer> deptIds);
 
-    List<Map<String, Object>> getCostByGroup(String startDate, String endDate, Integer projectId);
+    List<Map<String, Object>> getCostByGroup(String startDate, String endDate, Integer projectId, List<Integer> gpIds);
 
     List<Map<String, Object>> selectWithGroup(Integer companyId, String startDate, String endDate, Integer startIndex, Integer endIndex, Integer projectId, List<Integer> inchagerIds, Integer groupId, List<Integer> taskGroupIds);
 

+ 3 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/mapper/ReportMapper.java

@@ -7,6 +7,7 @@ import org.apache.ibatis.annotations.Select;
 import org.apache.ibatis.annotations.Update;
 
 import java.time.LocalDate;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -180,4 +181,6 @@ public interface ReportMapper extends BaseMapper<Report> {
     List<Map<String, Object>> getCcReportByDate(@Param("date") String date, @Param("id") String id, @Param("state") Integer state);
 
     List<Map<String, Object>> getPushProjectReportToSap(Integer companyId, String startDate, String endDate,String userId);
+
+    List<Report> getSumWorkingTime(ArrayList<Integer> deptIds, String startDate, String endDate);
 }

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

@@ -9,6 +9,7 @@ import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Update;
 
 import java.time.LocalDate;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
@@ -43,4 +44,8 @@ public interface UserMapper extends BaseMapper<User> {
     void setSuperiorNull(String userId);
 
     List<Map<String, Object>> getWeekPushUserList(Integer companyId, LocalDate startDate, LocalDate lastDay);
+
+    int getIsActiveCount(ArrayList<Integer> deptIds, String startDate, String endDate);
+
+    List<User> getInActiveList(ArrayList<Integer> deptIds, String startDate, String endDate);
 }

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

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

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

@@ -262,4 +262,6 @@ public interface ProjectService extends IService<Project> {
     HttpRespMsg getFunWorkContextList(Integer id);
 
     HttpRespMsg syncProjectWithSap(String startDate,String endDate);
+
+    HttpRespMsg getEffectiveLaborHourRate(String startDate, String endDate);
 }

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

@@ -0,0 +1,20 @@
+package com.management.platform.service.impl;
+
+import com.management.platform.entity.EstimateTimeSetting;
+import com.management.platform.mapper.EstimateTimeSettingMapper;
+import com.management.platform.service.EstimateTimeSettingService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author Seyason
+ * @since 2023-11-19
+ */
+@Service
+public class EstimateTimeSettingServiceImpl extends ServiceImpl<EstimateTimeSettingMapper, EstimateTimeSetting> implements EstimateTimeSettingService {
+
+}

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

@@ -3,12 +3,14 @@ package com.management.platform.service.impl;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.github.pagehelper.util.StringUtil;
 import com.management.platform.entity.*;
+import com.management.platform.entity.Task;
 import com.management.platform.entity.vo.*;
 import com.management.platform.mapper.*;
 import com.management.platform.service.*;
@@ -53,10 +55,7 @@ import java.math.RoundingMode;
 import java.sql.Array;
 import java.sql.Timestamp;
 import java.text.*;
-import java.time.Duration;
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.LocalTime;
+import java.time.*;
 import java.time.chrono.ChronoLocalDate;
 import java.time.format.DateTimeFormatter;
 import java.time.temporal.TemporalAdjusters;
@@ -1249,6 +1248,9 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
             List<SysRichFunction> functionCostList = sysFunctionMapper.getRoleFunctions(targetUser.getRoleId(), "查看成本统计");
             List<Integer> deptRelatedProjectIds = new ArrayList<>();
             List<Integer> projectIds = null;
+            //针对威派格,部门的主要和其他负责人需要查看部门下人员负责的项目或者项目下的任务分组的工时
+            boolean containDeptMembInchargeProjects = targetUser.getCompanyId() == 936;
+            List<String> inchargeUserIds = null;
             //判断查看权限
             if(functionAllList.size()==0){
                 deptIds=new ArrayList<>();
@@ -1272,6 +1274,9 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                     if(functionTimeList.size()>0||functionCostList.size()>0){
                         deptIds.addAll(allMyManagedDeptIds);
                     }
+                    if (containDeptMembInchargeProjects && deptIds.size() > 1) {
+                        inchargeUserIds = userMapper.selectList(new QueryWrapper<User>().select("id").in("department_id", deptIds)).stream().map(User::getId).collect(Collectors.toList());
+                    }
                 } else {
                     //担任项目经理的项目
                     List<Project> projectList = projectMapper.selectList(new QueryWrapper<Project>().select("id").eq("incharger_id", targetUser.getId()));
@@ -1289,7 +1294,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                 String[] split = userIds.split(",");
                 userIdList = Arrays.asList(split);
             }
-            List<Map<String, Object>> list = projectMapper.getTimeCost(companyId, startDate, endDate, projectId, userIdList,deptIds,null, deptRelatedProjectIds, projectIds);
+            List<Map<String, Object>> list = projectMapper.getTimeCost(companyId, startDate, endDate, projectId, userIdList,deptIds,null, deptRelatedProjectIds, projectIds, inchargeUserIds);
             BigDecimal totalMoneyCost = BigDecimal.valueOf(0);
             for (Map<String, Object> map : list) {
                 if (!map.containsKey("cost")) {
@@ -1355,6 +1360,9 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
             List<Integer> manProjectIds = null;
             //判断查看权限
             List<Integer> filterDeptIds=null;
+            //针对威派格,部门的主要和其他负责人需要查看部门下人员负责的项目或者项目下的任务分组的工时
+            boolean containDeptMembInchargeProjects = targetUser.getCompanyId() == 936;
+            List<String> inchargeUserIds = null;
             if(deptId!=null){
                 filterDeptIds= getBranchDepartment(deptId, allDepartmentList);
             }
@@ -1378,6 +1386,9 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                     if(functionTimeList.size()>0||functionCostList.size()>0){
                         deptIds.addAll(allMyManagedDeptIds);
                     }
+                    if (containDeptMembInchargeProjects && deptIds.size() > 1) {
+                        inchargeUserIds = userMapper.selectList(new QueryWrapper<User>().select("id").in("department_id", deptIds)).stream().map(User::getId).collect(Collectors.toList());
+                    }
                 } else {
                     //担任项目经理的项目
                     List<Project> projectList = projectMapper.selectList(new QueryWrapper<Project>().select("id").eq("incharger_id", targetUser.getId()));
@@ -1407,7 +1418,7 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
                 String[] split = userIds.split(",");
                 userIdList = Arrays.asList(split);
             }
-            List<Map<String, Object>> list = projectMapper.getTimeCost(companyId, startDate, endDate, projectId, userIdList,deptIds,filterDeptIds,deptRelatedProjectIds, manProjectIds);
+            List<Map<String, Object>> list = projectMapper.getTimeCost(companyId, startDate, endDate, projectId, userIdList,deptIds,filterDeptIds,deptRelatedProjectIds, manProjectIds, inchargeUserIds);
             BigDecimal totalMoneyCost = BigDecimal.valueOf(0);
             List<List<String>> allList=null ;
             List<String> sumRow = null;
@@ -8207,14 +8218,64 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
     public HttpRespMsg getCostByGroup(String startDate, String endDate, Integer projectId, HttpServletRequest request) {
         HttpRespMsg httpRespMsg = new HttpRespMsg();
         try {
-            Integer companyId = userMapper.selectById(request.getHeader("Token")).getCompanyId();
+            User targetUser = userMapper.selectById(request.getHeader("Token"));
+            Integer companyId = targetUser.getCompanyId();
             //首先查看有无浏览权限
-            if (!projectMapper.selectById(projectId).getCompanyId().equals(companyId)) {
+            Project project = projectMapper.selectById(projectId);
+            if (!project.getCompanyId().equals(companyId)) {
                 //httpRespMsg.setError("无权查看其他公司的项目详情");
                 httpRespMsg.setError(MessageUtils.message("access.otherCompanyProject"));
             } else {
                 Map<String, Object> resultMap = new HashMap<>();
-                List<Map<String, Object>> list = projectMapper.getCostByGroup(startDate, endDate, projectId);
+                List<Integer> gpIds = null;
+                if (companyId == 936) {
+                    //威派格的工时查看可能是看分组负责人的分组工时,需要过滤筛选
+                    //当前用户管理部门
+                    List<Integer> deptIds=null;
+                    List<Department> allDepartmentList = departmentMapper.selectList(new QueryWrapper<Department>().eq("company_id",companyId));
+                    List<Department> departmentList = departmentMapper.selectList(new QueryWrapper<Department>().eq("manager_id", targetUser.getId()).eq("company_id", companyId));
+                    List<DepartmentOtherManager> departmentOtherManagerList = departmentOtherManagerMapper.selectList(new QueryWrapper<DepartmentOtherManager>().eq("other_manager_id", targetUser.getId()));
+                    List<SysRichFunction> functionAllList = sysFunctionMapper.getRoleFunctions(targetUser.getRoleId(), "查看全公司");
+                    List<SysRichFunction> functionDpartList = sysFunctionMapper.getRoleFunctions(targetUser.getRoleId(), "查看负责部门");
+                    //无查看全公司的权限
+                    if (functionAllList.size() == 0) {
+                        deptIds = new ArrayList<>();
+                        deptIds.add(-1);
+                        //有查看负责部门的权限
+                        if (functionDpartList.size() > 0) {
+                            List<Integer> collect = departmentList.stream().map(dm -> dm.getDepartmentId()).distinct().collect(Collectors.toList());
+                            List<Integer> otherCollect = departmentOtherManagerList.stream().map(dom -> dom.getDepartmentId()).distinct().collect(Collectors.toList());
+                            collect.addAll(otherCollect);
+                            for (Integer integer : collect) {
+                                List<Integer> branchDepartment = getBranchDepartment(integer, allDepartmentList);
+                                deptIds.addAll(branchDepartment);
+                            }
+                            //查找当前项目的负责人
+                            if (project.getInchargerId() != null) {
+                                Integer departmentId = userMapper.selectById(project.getInchargerId()).getDepartmentId();
+                                if (deptIds.contains(departmentId)) {
+                                    //项目经理是管理的部门下面的人,查看全部分组
+                                } else {
+                                    //检查是否是分组负责人,查看部分分组
+                                    List<Integer> fDeptIds = deptIds;
+                                    List<TaskGroup> groupList = taskGroupMapper.selectList(new QueryWrapper<TaskGroup>().eq("project_id", project.getId()));
+                                    gpIds = new ArrayList<>();
+                                    gpIds.add(-1);
+                                    for (TaskGroup g : groupList) {
+                                        if (g.getInchargerId() != null) {
+                                            Integer departmentId1 = userMapper.selectById(g.getInchargerId()).getDepartmentId();
+                                            if (fDeptIds.contains(departmentId1)) {
+                                                //是分组负责人,查看全部
+                                                gpIds.add(g.getId());
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                List<Map<String, Object>> list = projectMapper.getCostByGroup(startDate, endDate, projectId, gpIds);
                 BigDecimal totalMoneyCost = BigDecimal.valueOf(0);
                 for (Map<String, Object> map : list) {
                     if (!map.containsKey("costMoney")) {
@@ -11199,6 +11260,81 @@ public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> impl
         return msg;
     }
 
+    @Override
+    public HttpRespMsg getEffectiveLaborHourRate(String startDate, String endDate) {
+        LambdaQueryWrapper<Department> lqw = new LambdaQueryWrapper<>();
+        lqw.in(Department::getDepartmentId,3759,3899,3900,3901,3902,3903,3904,3906,5719);
+        List<Department> departments = departmentMapper.selectList(lqw);
+
+        ArrayList<LaborHourRateVo> laborHourRateVos = new ArrayList<>();
+
+        int dayCount = WorkDayCalculateUtils.getWorkDaysCountInRange(startDate, endDate, 0);//应报工时天数
+
+        for (Department department : departments) {
+            LaborHourRateVo laborHourRateVo = new LaborHourRateVo();
+            laborHourRateVo.setRoot_id(department.getDepartmentId());
+            laborHourRateVo.setDepartment_name(department.getDepartmentName());
+            ArrayList<Integer> deptIds = new ArrayList<>();
+            setDeptIdList(department.getDepartmentId(),deptIds);
+            deptIds.add(department.getDepartmentId());
+            laborHourRateVo.setChild_ids(deptIds);
+            //查询该公司下某头部部门及子部门在四种项目下的工时之和,某个时间段内
+            List<Report> reportList= reportMapper.getSumWorkingTime(deptIds,startDate,endDate);
+            ArrayList<Report> reports = new ArrayList<>();//按时填报的report
+            for (Report report : reportList) {
+                LocalDate createDate = report.getCreateDate();
+                LocalDateTime createTime = report.getCreateTime();
+                LocalDate createTimeLocalDate = createTime.toLocalDate();
+                boolean b1 = WorkDayCalculateUtils.sameMonth(createDate, createTimeLocalDate);
+                boolean b2 = WorkDayCalculateUtils.sameWeek(createDate, createTimeLocalDate);
+                if (b1&&b2){
+                    reports.add(report);
+                }
+            }
+            double timeSum = reports.stream().mapToDouble(Report::getWorkingTime).sum();
+
+
+            int inActiveDays=0;
+            //查询  入职时间早于起始时间 但是员工在这段时间离职 的员工列表
+            List<User> inActiveList=userMapper.getInActiveList(deptIds,startDate,endDate);
+            //获取离职员工在此期间工作多少天
+            for (User user : inActiveList) {
+                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+                String inactiveDate = user.getInactiveDate().format(formatter);
+                inActiveDays+=WorkDayCalculateUtils.getWorkDaysCountInRange(startDate,inactiveDate,0);
+            }
+            //-- 查询 有多少个  入职时间早于起始时间 并且是在职的员工
+            int isActiveCount=userMapper.getIsActiveCount(deptIds,startDate,endDate);
+
+            laborHourRateVo.setWorking_time(timeSum);
+            laborHourRateVo.setDate_count(dayCount);
+            laborHourRateVo.setCount(isActiveCount);
+            laborHourRateVo.setTotal_time((long) (inActiveList.size()*8*inActiveDays+isActiveCount*8*dayCount));//应报工时还少了在职的加上可能辞职的
+            System.out.println("============="+inActiveDays);
+            System.out.println("============="+isActiveCount);
+            laborHourRateVo.setDay_time(8);
+            laborHourRateVos.add(laborHourRateVo);
+        }
+        HttpRespMsg msg = new HttpRespMsg();
+        msg.setData(laborHourRateVos);
+        return msg;
+    }
+
+
+    public void setDeptIdList(Integer departmentId,List<Integer> deptIds){
+        LambdaQueryWrapper<Department> lqw = new LambdaQueryWrapper<>();
+        lqw.eq(Department::getSuperiorId,departmentId);
+        List<Department> departmentList = departmentMapper.selectList(lqw);
+
+        if (departmentList!=null&&departmentList.size()>0){
+            List<Integer> collect = departmentList.stream().map(Department::getDepartmentId).collect(Collectors.toList());
+            deptIds.addAll(collect);
+            for (Integer id : collect) {
+                setDeptIdList(id,deptIds);
+            }
+        }
+    }
+
     //同步SAP项目服务数据到工时管家
     private void syncServiceData(String startDate, String endDate, Integer companyId) {
         List<ReportExtraDegree> extraDegrees = reportExtraDegreeService.list(new QueryWrapper<ReportExtraDegree>().eq("company_id", companyId));

+ 11 - 7
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/service/impl/ReportServiceImpl.java

@@ -5557,13 +5557,17 @@ public class ReportServiceImpl extends ServiceImpl<ReportMapper, Report> impleme
                     map.put("daysTxt", date.format(DateTimeFormatter.ofPattern("MM/dd")));
                     if (!noReportDataList.stream().anyMatch(noItem->noItem.get("corpwxUserid").equals(curUser.getCorpwxUserid()))) {
                         noReportDataList.add(map);
-                    }
-                } else {
-                    Map<String, Object> findUser = noReportDataList.stream().filter(data -> data.get("corpwxUserid").equals(curUser.getCorpwxUserid())).findFirst().get();
-                    Object days = findUser.get("days");
-                    findUser.put("days", (Integer)days + 1);
-                    if ((Integer)days + 1 < 4) {
-                        findUser.put("daysTxt", findUser.get("daysTxt") + "," + date.format(DateTimeFormatter.ofPattern("MM/dd")));
+                    } else {
+                        //已经添加过了,需要更新天数
+                        Optional<Map<String, Object>> optional = noReportDataList.stream().filter(data -> data.get("corpwxUserid").equals(curUser.getCorpwxUserid())).findFirst();
+                        if (optional.isPresent()) {
+                            Map<String, Object> findUser = optional.get();
+                            Object days = findUser.get("days");
+                            findUser.put("days", (Integer)days + 1);
+                            if ((Integer)days + 1 < 4) {
+                                findUser.put("daysTxt", findUser.get("daysTxt") + "," + date.format(DateTimeFormatter.ofPattern("MM/dd")));
+                            }
+                        }
                     }
                 }
             }

+ 21 - 19
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/task/TimingTask.java

@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.injector.methods.SelectById;
 import com.management.platform.controller.WeiXinCorpController;
 import com.management.platform.entity.*;
+import com.management.platform.entity.Task;
 import com.management.platform.entity.vo.TokenVo;
 import com.management.platform.mapper.*;
 import com.management.platform.service.*;
@@ -41,6 +42,7 @@ import java.sql.Time;
 import java.sql.Timestamp;
 import java.text.DecimalFormat;
 import java.time.*;
+import java.time.Period;
 import java.time.format.DateTimeFormatter;
 import java.time.temporal.TemporalAccessor;
 import java.time.temporal.TemporalAdjusters;
@@ -1285,9 +1287,8 @@ public class TimingTask {
                 }
                 //开通了OA功能,有请假模块的,需要把当前请假的排除掉
                 List<Map<String, Object>> userList = new ArrayList<>();
-                boolean recentlyNotFill;
+                boolean lastWeekNotFill = false;
                 if (t.getAlertType() == 0 || t.getAlertType() == 1) {
-                    recentlyNotFill = false;
                     if (company.getPackageOa() == 1) {
                         userList = userMapper.getPushUserList(t.getCompanyId(),t.getAlertType(), date);
                     } else {
@@ -1312,16 +1313,21 @@ public class TimingTask {
                         }
                         transfDay = transfDay.plusDays(1);
                     }
-                    //如果今天就是最后一个工作日
-                    if (lastWorkDay.isEqual(localDate)) {
-                        recentlyNotFill = false;
+                    //如果今天就是最后一个工作日;或者周六周日,需要提醒本周
+                    if (lastWorkDay.isEqual(localDate) || localDate.getDayOfWeek().getValue() == 6 || localDate.getDayOfWeek().getValue() == 7) {
                         LocalDate startDate = localDate.with(DayOfWeek.MONDAY);
                         userList = reportService.getNotFullReportUserList(company.getId(), startDate, lastDay);
                     } else {
-                        //检查之前10天是否存在未填的
-                        LocalDate startDate = localDate.minusDays(10);
-                        userList = reportService.getNotFullReportUserList(company.getId(), startDate, localDate.minusDays(1));
-                        recentlyNotFill = true;
+                        LocalDate startDate = localDate.minusDays(7);
+                        //从2023-11-10号以后开始算
+                        if (startDate.isAfter(LocalDate.parse("2023-11-05"))) {
+                            //检查上周日报是否漏填
+                            LocalDate lastSunday = localDate.with(DayOfWeek.SUNDAY).minusWeeks(1);
+                            LocalDate lastMonday = lastSunday.minusDays(6);
+                            userList = reportService.getNotFullReportUserList(company.getId(), lastMonday, lastSunday);
+//                            System.out.println("上周未填人员数量="+userList.size());
+                            lastWeekNotFill = true;
+                        }
                     }
                 } else if (t.getAlertType() == 3) {
                     //3--每月固定日期提醒上个月的
@@ -1335,19 +1341,16 @@ public class TimingTask {
                         LocalDate endDate = localDate.minusMonths(1).with(TemporalAdjusters.lastDayOfMonth());
                         userList = reportService.getNotFullReportUserList(company.getId(), startDate, endDate);
                     }
-                    recentlyNotFill = false;
-                } else {
-                    recentlyNotFill = false;
                 }
-
                 List<WxCorpInfo> cpList = wxCorpInfoMapper.selectList(new QueryWrapper<WxCorpInfo>().eq("company_id", t.getCompanyId()));
+                final boolean finalLastWeekNotFill = lastWeekNotFill;
                 userList.forEach(u->{
                     if (u.get("corpwxUserid") != null){
                         //推送到企业微信
                         String corpUid = (String) u.get("corpwxUserid");
                         JSONObject json=new JSONObject();
-                        JSONArray dataJson=new JSONArray();
-                        JSONObject jsonObj=new JSONObject();
+                        JSONArray dataJson = new JSONArray();
+                        JSONObject jsonObj = new JSONObject();
                         jsonObj.put("key", "提示");
                         if (t.getAlertType() == 3) {
                             //每月提醒上个月的
@@ -1357,14 +1360,12 @@ public class TimingTask {
                                 jsonObj.put("value", "您上个月有"+u.get("daysTxt")+"共"+(Integer)u.get("days")+"天未填写工时报告,请尽快填写");
                             }
                         } else {
-                            if (recentlyNotFill) {
-                                jsonObj.put("value", "您近期有"+(Integer)u.get("days")+"天未填写工时报告,请尽快填写");
+                            if (finalLastWeekNotFill) {
+                                jsonObj.put("value", "您上周有"+(Integer)u.get("days")+"天未填写工时报告,请尽快填写");
                             } else {
                                 jsonObj.put("value", StringUtils.isEmpty(t.getAlertMsg())?"":t.getAlertMsg());
                             }
                         }
-
-
                         dataJson.add(jsonObj);
                         if(isPrivateDeploy){
                             json.put("content",StringUtils.isEmpty(t.getAlertMsg())?"":t.getAlertMsg()+"\\n<a href=\\\"https://open.weixin.qq.com/connect/oauth2/authorize?appid="+suitId+"&redirect_uri="+pcUrl+"/api/corpInsideWXAuth&response_type=code&scope=snsapi_base&state=0#wechat_redirect\\\">去填写</a>");
@@ -1374,6 +1375,7 @@ public class TimingTask {
                             json.put("content_item",dataJson);
                         }
                         if (cpList.size() > 0) {
+//                            System.out.println("发送企业微信漏填提醒:" + LocalDateTime.now().toString() + ", corpUid=" + corpUid + ", json=" + json.toJSONString());
                             wxCorpInfoService.sendWXCorpTemplateMsg(cpList.get(0), corpUid, json);
                         }
                     } else if (u.get("wxOpenid") != null) {

+ 5 - 10
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/DateTimeUtil.java

@@ -70,15 +70,10 @@ public class DateTimeUtil {
     }
 
     public static void main(String[] args) {
-        double d = getHalfHoursFromDouble(0.26);
-        System.out.println(d);
-        d = getHalfHoursFromDouble(1.2);
-        System.out.println(d);
-        d = getHalfHoursFromDouble(1.24);
-        System.out.println(d);
-        d = getHalfHoursFromDouble(1.25);
-        System.out.println(d);
-        d = getHalfHoursFromDouble(1.26);
-        System.out.println(d);
+        LocalDate localDate = LocalDate.now();
+        System.out.println(localDate);
+        System.out.println(localDate.getDayOfWeek().getValue());
+        localDate = localDate.with(DayOfWeek.SUNDAY);
+        System.out.println(localDate);
     }
 }

+ 23 - 1
fhKeeper/formulahousekeeper/management-platform/src/main/java/com/management/platform/util/WorkDayCalculateUtils.java

@@ -7,6 +7,7 @@ import java.text.SimpleDateFormat;
 import java.time.DayOfWeek;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
+import java.time.temporal.WeekFields;
 import java.util.*;
 
 public class WorkDayCalculateUtils {
@@ -291,7 +292,28 @@ public class WorkDayCalculateUtils {
     }
 
 
+
+    //判断俩日期是否在同一周
+    public static boolean sameWeek(LocalDate date1, LocalDate date2) {
+        WeekFields weekFields = WeekFields.of(Locale.getDefault());
+        int week1 = date1.get(weekFields.weekOfWeekBasedYear());
+        System.out.println(week1);
+        int week2 = date2.get(weekFields.weekOfWeekBasedYear());
+        System.out.println(week2);
+        return week1 == week2;
+    }
+
+    //判断俩日期是否在月份
+    public static boolean sameMonth(LocalDate date1, LocalDate date2) {
+        return date1.getYear() == date2.getYear() && date1.getMonth() == date2.getMonth();
+    }
+
     public static void main(String[] args) {
-        System.out.println(getWorkDaysCountInRange("2022-08-06","2022-08-08", 1));
+        System.out.println(getWorkDaysCountInRange("2023-11-01","2023-11-04", 0));
+
+        LocalDate date1 = LocalDate.of(2023, 12, 1);
+        LocalDate date2 = LocalDate.of(2023, 11, 30);
+//        System.out.println(sameWeek(date1, date2));
+//        System.out.println(sameMonth(date1, date2));
     }
 }

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

@@ -15,7 +15,7 @@ spring:
       location: C:/upload/
   datasource:
     driver-class-name: com.mysql.cj.jdbc.Driver
-    url: jdbc:mysql://47.101.180.183:17089/man_mingyi?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&useSSL=false
+    url: jdbc:mysql://47.101.180.183:17089/man_dev?useUnicode=true&characterEncoding=utf8&serverTimezone=GMT%2B8&rewriteBatchedStatements=true&useSSL=false
     username: root
     password: P011430@Huoshi*
     

+ 20 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/EstimateTimeSettingMapper.xml

@@ -0,0 +1,20 @@
+<?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.EstimateTimeSettingMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.management.platform.entity.EstimateTimeSetting">
+        <id column="company_id" property="companyId" />
+        <result column="project_man_day_fill_mode" property="projectManDayFillMode" />
+        <result column="project_warning_percent" property="projectWarningPercent" />
+        <result column="project_fronze_on_lack" property="projectFronzeOnLack" />
+        <result column="group_warning_percent" property="groupWarningPercent" />
+        <result column="group_fronze_on_lack" property="groupFronzeOnLack" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        company_id, project_man_day_fill_mode, project_warning_percent, project_fronze_on_lack, group_warning_percent, group_fronze_on_lack
+    </sql>
+
+</mapper>

Разлика између датотеке није приказан због своје велике величине
+ 89 - 71
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ProjectMapper.xml


+ 12 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/ReportMapper.xml

@@ -967,4 +967,16 @@
             and r.creator_id=#{userId}
         </if>
     </select>
+
+    <select id="getSumWorkingTime" resultType="com.management.platform.entity.Report">
+        SELECT * FROM report r
+        LEFT JOIN project p
+        ON r.project_id=p.id
+        WHERE p.company_id=936 AND p.category IN(168,169,171,172)
+        AND r.dept_id IN
+        <foreach collection="deptIds" item="id" open="(" close=")" separator=",">
+            #{id}
+        </foreach>
+        AND r.create_date BETWEEN #{startDate} AND #{endDate}
+    </select>
 </mapper>

+ 29 - 0
fhKeeper/formulahousekeeper/management-platform/src/main/resources/mapper/UserMapper.xml

@@ -181,4 +181,33 @@
         select user.id, name, department.department_name from user left join department on department.department_id = user.department_id
             ${ew.customSqlSegment}
     </select>
+
+    <select id="getIsActiveCount" resultType="java.lang.Integer">
+        SELECT count(1) isActiveCount FROM user
+        WHERE id IN (SELECT DISTINCT r.creator_id  FROM report r
+        LEFT JOIN project p
+        ON r.project_id=p.id
+        WHERE p.company_id=936 AND p.category IN(168,169,171,172)
+        AND r.dept_id IN
+        <foreach collection="deptIds" item="id" open="(" close=")" separator=",">
+            #{id}
+        </foreach>
+        AND r.create_date BETWEEN #{startDate} AND #{endDate})
+        AND is_active=1 AND (inactive_date >= #{endDate} OR inactive_date is null) AND induction_date &lt;= #{startDate}
+    </select>
+
+    <select id="getInActiveList" resultType="com.management.platform.entity.User">
+        SELECT user.* FROM user
+        WHERE id in
+        (SELECT DISTINCT r.creator_id  FROM report r
+        LEFT JOIN project p
+        ON r.project_id=p.id
+        WHERE p.company_id=936 AND p.category IN(168,169,171,172)
+        AND r.dept_id IN
+        <foreach collection="deptIds" item="id" open="(" close=")" separator=",">
+            #{id}
+        </foreach>
+        AND r.create_date BETWEEN #{startDate} AND #{endDate})
+        AND inactive_date BETWEEN #{startDate} AND #{endDate} and induction_date &lt;= #{startDate}
+    </select>
 </mapper>

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

@@ -2,6 +2,7 @@ package com.management.platform.mapper;
 
 import com.management.platform.entity.Company;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Delete;
 
 /**
  * <p>

+ 8 - 1
fhKeeper/formulahousekeeper/timesheet-workshop-h5/src/views/index/index.vue

@@ -222,7 +222,14 @@ export default {
                 },
             ]
             console.log(routersList, modelNameList)
-            this.routers = routersList.filter(item => item.fixed || modelNameList.includes(item.moudelName))
+            this.routers = routersList.filter(item => item.fixed || modelNameList.includes(item.moudelName));
+            this.routers.push({
+                    name: '我的',
+                    moudelName: '我的',
+                    // url: '/workView',
+                    url: '/my',
+                    icon: 'balance-list-o'
+                });
         },
         // 获取企业微信参数
         agentConfig() {

+ 4 - 0
fhKeeper/formulahousekeeper/timesheet-workshop-h5/src/views/login/index.vue

@@ -196,6 +196,10 @@
                 this.isWX = true;
             }
             let href = window.location.href;
+            //如果是管理员退出后登录,则不自动登录
+            if (href.indexOf('loginAny') > 0) {
+                return;
+            }
             //优先处理企业微信工作台点击进入,后台已经处理过,有userId传过来了
             if (this.isCorpWX && href.indexOf("userId") > 0) {
                 //判断企业微信,是否存在授权

+ 5 - 78
fhKeeper/formulahousekeeper/timesheet-workshop-h5/src/views/my/children/center.vue

@@ -13,36 +13,25 @@
         <!-- 主体 -->
         <main class="mt-10">
             <div class="bg-fff">
-                <!-- <div v-if="userInfo.companyId == '7'"> -->
-
-                <van-cell title="当前版本" :title-style="'flex: 0.5;'" :value="version"></van-cell>
-
                 <div style="height: 20px;background: #f4f4f4"></div>
                 <!-- </div> -->
                 <van-cell title="账号" v-if="userInfo.userNameNeedTranslate != '1'" :title-style="'flex: 0.5;'" :value="userInfo.phone"></van-cell>
                 <van-cell title="工号" v-if="userInfo.jobNumber" :title-style="'flex: 0.5;'" :value="userInfo.jobNumber"></van-cell>
-
+                <van-cell title="角色" v-if="userInfo.roleName" :title-style="'flex: 0.5;'" :value="userInfo.roleName"></van-cell>
                 <div style="height: 20px;background: #f4f4f4"></div>
                 
                 <van-cell title="公司" :title-style="'flex: 0.5;'" :value="userInfo.companyName"></van-cell>
                 <van-cell title="有效日期" :title-style="'flex: 0.5;'" :value="expirationDate"></van-cell> 
 
                 <div style="height: 20px;background: #f4f4f4"></div>
-                <!-- <div v-if="userInfo.companyId == '7'"> -->
-                <van-cell title="使用说明" :title-style="'flex: 1;'" is-link @click="instructions()"></van-cell>
-                <van-cell title="在线客服" :title-style="'flex: 1;'" is-link @click="tokefu()"></van-cell>
-                <van-cell title="添加员工" :title-style="'flex: 1;'" is-link @click="addEmployee()" v-if="wxManager"></van-cell>
-                <!-- </div> -->
-                <!-- <van-cell title="修改密码" isLink to="/my/set"></van-cell> -->
             </div>
-            <van-cell :title="'绑定'+(isCorpWX?'企业':'')+'微信'" v-if="userInfo.userNameNeedTranslate != '1' && (isCorpWX || isWX)" @click="bindWeiXin" style="margin-top:10px;" :title-style="'flex: 2.5;'" label="绑定微信后可接收工时填报提醒">
+            <!-- <van-cell :title="'绑定'+(isCorpWX?'企业':'')+'微信'" v-if="userInfo.userNameNeedTranslate != '1' && (isCorpWX || isWX)" @click="bindWeiXin" style="margin-top:10px;" :title-style="'flex: 2.5;'" label="绑定微信后可接收工时填报提醒">
                 <template>
                     <span v-if="(isCorpWX && userInfo.corpwxUserid == null) || (isWX && userInfo.wxOpenid == null)" style="color:#ff0000;">未绑定</span>
                     <span v-if="(isCorpWX && userInfo.corpwxUserid != null) || (isWX && userInfo.wxOpenid != null)" style="color:#7CCD7C;">已绑定</span>
                 </template>
-            </van-cell>
-            <van-button class="logout" @click="logout" block round type="danger" v-if="!isCorpWX">退出登录</van-button>
-            <!-- <van-button class="logout" @click="logout" block round type="danger" >退出登录</van-button> -->
+            </van-cell> -->
+            <van-button class="logout" @click="logout" block round type="danger" v-if="userInfo.roleName=='超级管理员' || userInfo.roleName=='系统管理员'">退出登录</van-button>
         </main>
 
         <Footer page="my" />
@@ -78,7 +67,7 @@
             logout() {
                 this.$store.commit("updateLogin", false);
                 localStorage.removeItem("userInfo");
-                this.$router.push("/login");
+                this.$router.push({path:"/login", query: {loginAny: true}});
             },
             bindWeiXin(){
                 //企业微信
@@ -99,61 +88,6 @@
                 var weixinUrl="https://open.weixin.qq.com/connect/oauth2/authorize?appid="+appId+"&redirect_uri="+encodeURI(url)+"&response_type=code&scope=snsapi_base&state=0#wechat_redirect";
                 window.location.href = weixinUrl;
             },
-            // 使用说明
-            instructions() {
-                let url = 'http://celiang.oss-cn-hangzhou.aliyuncs.com/measurement/2022-01/18/75it6phpocqYFV1642488558220118.pdf'
-                let name = '使用说明书'
-                // 将要传过去的值
-                this.previewPDF(url, name)
-            },
-            // 预览pdf
-            previewPDF(url, name) {
-                this.$router.push({
-                    path:  '/pdf',
-                    query: {
-                        url: '',
-                        name: name
-                    }
-                })
-            },
-            // 添加员工
-            addEmployee() {
-                wx.invoke('openAppManage', {}, function(res){
-                    console.log(res, '你在看看')
-                    if(res.err_msg == "openAppManage:ok") {
-                        // 调用成功              
-                    }
-                    if(res.err_msg == "openAppManage:fail:no permission") {
-                        // 调用人身份不符合                 
-                        this.$message({message: '调用人身份不符合',type: "error"});
-                    }
-                    if(res.err_msg == "openAppManage:fail:unknown app") {
-                        // 应用信息获取失败
-                        this.$message({message: '应用信息获取失败',type: "error"});
-                    }
-                    if(res.err_msg == "openAppManage:fail:unsupported app type") {
-                        // 应用类型不符合要求
-                        this.$message({message: '应用类型不符合要求',type: "error"});
-                    }
-                    if(res.err_msg == "openAppManage:fail") {
-                        // 其它错误                  
-                        this.$message({message: '其它错误',type: "error"});
-                    }      
-                })
-            },
-            // 跳转客服
-            tokefu(){
-                wx.invoke('openThirdAppServiceChat', {
-                    }, function(res) {
-                        console.log('invoke',res);
-                        if (res.err_msg == "openThirdAppServiceChat:ok" || res.err_msg == "openThirdAppServiceChat:cancel") {
-                        }else{
-                            this.$toast.fail('请联系管理员添加客服');
-                        }
-                        
-                    }
-                );
-            },
             // 判断是否有添加员工的权限
             getWxManager() {
                 this.$axios.post("/user/isManager", {})
@@ -185,13 +119,6 @@
                 userss.company.expirationDate[2] >= 10 ? userss.company.expirationDate[2] : userss.company.expirationDate[1] = '0' + userss.company.expirationDate[2]
                 userss.company.expirationDate[1] >= 10 ? userss.company.expirationDate[1] : userss.company.expirationDate[1] = '0' + userss.company.expirationDate[1]
                 this.expirationDate = userss.company.expirationDate[0] + '-' + userss.company.expirationDate[1] + '-' + userss.company.expirationDate[2]
-
-                // 版本
-                userss.company.packageWorktime == 1 ? this.version = '基础版' : ''
-                userss.company.packageProject == 1 ? this.version = '专业版' : ''
-                userss.company.packageEngineering == 1 ? this.version = '建筑工程版' : ''
-                userss.company.packageOa == 1 ? this.version = '旗舰版' : ''
-
                 console.log(this.version)
             }
 

+ 3 - 2
fhKeeper/formulahousekeeper/timesheet-workshop/src/views/plan/planComponent.vue

@@ -95,7 +95,7 @@
     </div>
 
     <!-- 新增今日计划 -->
-    <el-dialog :title="titleName" :visible.sync="editPlanDiaLog" width="800px" top="190px" :before-close="handleClose">
+    <el-dialog :title="titleName" :visible.sync="editPlanDiaLog" width="800px" top="7.5vh" :before-close="handleClose">
       <div class="planDialog">
         <el-form ref="todayPlanForm" :rules="todayPlanFormrules" :model="todayPlanForm" label-width="120px">
           <el-form-item label="排产工单号" style="width: 100%" prop="productSchedulingNum">
@@ -1100,7 +1100,8 @@ export default {
 
   // 新增样式
   .planDialog {
-    max-height: 42vh;
+    // max-height: 42vh;
+    max-height: 62vh;
     overflow-y: auto;
     scrollbar-width: none;
     /* Firefox */

+ 1 - 1
fhKeeper/formulahousekeeper/timesheet-workshop/src/views/statistic/index.vue

@@ -1405,7 +1405,7 @@ export default {
 }
 // 新增样式
 .planDialog {
-    max-height: 42vh;
+    max-height: 62vh;
     overflow-y: auto;
     scrollbar-width: none;
     /* Firefox */

Разлика између датотеке није приказан због своје велике величине
+ 1739 - 1596
fhKeeper/formulahousekeeper/timesheet/src/views/expense/expense.vue


+ 107 - 8
fhKeeper/formulahousekeeper/timesheet/src/views/project/list.vue

@@ -72,14 +72,9 @@
                             <el-dropdown-item v-if="user.company.packageProject == 1 && permissions.projectCostOfItems">
                                 <el-link type="primary" :underline="false" @click="showBaseCostItemDialog">{{ $t('baselinecostitem') }}</el-link>
                             </el-dropdown-item>
-                            <!-- <el-dropdown-item v-if="user.company.packageProject == 1 && user.companyId == '936'"> -->
-                            <!-- <el-dropdown-item >
-                                <el-link type="primary" :underline="false" @click="keyNodesIsShow = true">关键节点项</el-link>
-                            </el-dropdown-item> -->
                             <el-dropdown-item v-if="permissions.projectClassification">
                                 <el-link type="primary" :underline="false" @click="showClfDialog = true">{{ $t('classificationmanagement') }}</el-link>
                             </el-dropdown-item>
-                            <!-- <el-dropdown-item v-if="user.timeType.mainProjectState == 1 && !permissions.projectClassification"> -->
                             <el-dropdown-item v-if="user.timeType.mainProjectState == 1">
                                 <el-link type="primary" :underline="false" @click="mainProjectDialog = true">{{ $t('masterprojectmanagement') }}</el-link>
                             </el-dropdown-item>
@@ -95,6 +90,9 @@
                             <el-dropdown-item v-if="user.companyId==3385 && permissions.projectClassification">
                                 <el-link type="primary" :underline="false" @click="functionalDivisionDig=true,getFunctionalList()">{{'职能分工设置'}}</el-link>
                             </el-dropdown-item>
+                            <el-dropdown-item v-if="user.timeType.projectManDay == 1 && permissions.projectClassification">
+                                <el-link type="primary" :underline="false" @click="projectManDaySettingDialog = true;getManDaySetting()">{{ '预估工时配置' }}</el-link>
+                            </el-dropdown-item>
                         </el-dropdown-menu>
                         </el-dropdown>
                 </el-form-item>
@@ -622,7 +620,8 @@
                     </el-form-item>
 
                     <!-- 增加项目人天字段 绎维固定字段 -->
-                    <el-form-item label="项目人天" v-if="user.timeType.projectManDay == 1">
+                    <el-form-item  v-if="user.timeType.projectManDay == 1">
+                        <template slot="label"><span v-if="manDaySetting.projectManDayFillMode == 2 || (manDaySetting.projectManDayFillMode == 1 && addForm.fromOutside == 0)" style="padding:5px;color:red;">*</span>项目人天</template>
                         <el-input v-model.number="addForm.manDay" :placeholder="$t('peaseenterthe')" @input="jisuanEstimatedWorkTime(addForm.manDay)"  style="width: 100px"></el-input><span style="margin-left:10px;position:absolute;">人天(预估工时:{{this.estimatedWorkTime}}h)</span>
                         <el-tooltip effect="dark" :content="$t('根据系统基础设置每日正常工作时长计算,1人天为一个每日正常工作时长')" placement="top-start" style="margin-left:180px">
                                         <i class="el-icon-question" style="color:#606266"></i>
@@ -1070,6 +1069,43 @@
             </div>
         </el-dialog>
 
+        
+        <el-dialog title="项目预估工时配置" show-header="false" v-if="projectManDaySettingDialog" :visible.sync="projectManDaySettingDialog" :close-on-click-modal="false" customClass="customWidth" width="600px">
+            <el-form label-width="200px" :form="manDaySetting">
+                <el-form-item :label="'预估工时是否必填'"  >
+                    <el-select v-model="manDaySetting.projectManDayFillMode" :placeholder="$t('defaultText.pleaseChoose')"  >
+                        <el-option label="非必填" :value="0"></el-option>
+                        <el-option label="工时系统创建的项目必填" :value="1"></el-option>
+                        <el-option label="工时系统和外部同步的项目都必填" :value="2"></el-option>
+                    </el-select>
+                </el-form-item>
+                <el-form-item :label="'项目工时提醒百分比'"  >
+                    <el-input v-model="manDaySetting.projectWarningPercent" type="number" style="width:200px;">
+                    </el-input>%
+                </el-form-item>
+                <el-form-item :label="'项目工时不足时'"  >
+                    <el-select v-model="manDaySetting.projectFronzeOnLack" :placeholder="$t('defaultText.pleaseChoose')"  >
+                        <el-option label="禁止填报" :value="1"></el-option>
+                        <el-option label="可以填报,仅提醒" :value="0"></el-option>
+                    </el-select>
+                </el-form-item>
+                <el-form-item :label="'分组工时提醒百分比'"  v-if="user.company.packageProject == 1">
+                    <el-input v-model="manDaySetting.groupWarningPercent" type="number" style="width:200px;">
+                    </el-input>%
+                </el-form-item>
+                <el-form-item :label="'分组工时不足时'"  v-if="user.company.packageProject == 1" >
+                    <el-select v-model="manDaySetting.groupFronzeOnLack" :placeholder="$t('defaultText.pleaseChoose')"  >
+                        <el-option label="禁止填报" :value="1"></el-option>
+                        <el-option label="可以填报,仅提醒" :value="0"></el-option>
+                    </el-select>
+                </el-form-item>
+            </el-form>
+            <div slot="footer" class="dialog-footer">
+                <el-button type="default" @click="projectManDaySettingDialog = false" >{{ $t('Shutdown') }}</el-button>
+                <el-button type="primary" @click="saveProjectManDaySetting()" >保存</el-button>
+            </div>
+        </el-dialog>
+
         <!-- 导出任务分组 -->
         <el-dialog :title="'导出任务分组'" show-header="false" v-if="groupTaskDialog" :visible.sync="groupTaskDialog" :close-on-click-modal="false" customClass="customWidth" width="600px">
             <el-form>
@@ -1629,6 +1665,8 @@ a {
         },
         data() {
             return {
+                manDaySetting:{},
+                projectManDaySettingDialog: false,
                 projectListPageComponentKey: 1,
                 isDeleting: false,
                 forSubProjectlist:[],
@@ -1924,6 +1962,47 @@ a {
             })
         },
         methods: {
+            saveProjectManDaySetting() {
+                this.http.post('/estimate-time-setting/save', this.manDaySetting,
+                res => {
+                    if (res.code == "ok") {
+                        this.projectManDaySettingDialog = false;
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
+            //获取项目预估工时配置数据
+            getManDaySetting() {
+                this.http.post('/estimate-time-setting/get', {
+                    companyId: this.user.companyId
+                },
+                res => {
+                    if (res.code == "ok") {
+                        this.manDaySetting = res.data;
+                    } else {
+                        this.$message({
+                            message: res.msg,
+                            type: "error"
+                        });
+                    }
+                },
+                error => {
+                    this.$message({
+                        message: error,
+                        type: "error"
+                    });
+                });
+            },
             submitCopySubProject() {
                 //获取选中的项目
                 if (this.checkedPForSubArr.length == 0) {
@@ -4397,7 +4476,8 @@ a {
                         projectMainId: '',
                         outputValue: '',
                         bu: [],
-                        manDay:0
+                        manDay:0,
+                        fromOutside: 0,
                         // deptId: []
                     }
                     this.estimatedWorkTime=''
@@ -4534,7 +4614,8 @@ a {
                         bu: buascaderList,
                         manDay:item.manDay==null?0:item.manDay,
                         manDayStartDate:item.manDayStartDate,
-                        manDayDisable:item.manDay
+                        manDayDisable:item.manDay,
+                        fromOutside:item.fromOutside
                     }
                     for(var i in this.dataList) {
                         var str = 'plate' + (+i + 1)
@@ -4634,6 +4715,9 @@ a {
                     // this.findUserInTree()
                 }
                 this.addFormVisible = true;
+                if (this.user.timeType.projectManDay == 1) {
+                    this.getManDaySetting();
+                }
                 if (this.user.company.packageEngineering == 1) {
                     if (this.professionList.length == 0) {
                         this.getProfessionList();
@@ -4874,6 +4958,7 @@ a {
                         if (this.user.timeType.outputValueStatus == 1){
                             formData.append("outputValue",this.addForm.outputValue ? this.addForm.outputValue : 0)
                         }
+                        
                         var listId = []
                         var listName = []
                         for(var i in this.auseList) {
@@ -4944,6 +5029,17 @@ a {
                         }
                         formData.append("buId", this.addForm.bu ? this.addForm.bu : '');
                         if(this.user.timeType.projectManDay){
+                            //检验预估人天的必填属性
+                            if (this.manDaySetting.projectManDayFillMode == 2 || (this.manDaySetting.projectManDayFillMode == 1 && this.addForm.fromOutside == 0)) {
+                                if (!this.addForm.manDay) {
+                                    this.$message({
+                                        message: '预估工时不能为0',
+                                        type: "error"
+                                    });
+                                    this.addLoading = false;
+                                    return;
+                                }
+                            }
                             formData.append("manDay", this.addForm.manDay ? this.addForm.manDay : '');
                             formData.append("manDayStartDate", this.addForm.manDayStartDate ? this.addForm.manDayStartDate : '');
                         }
@@ -5547,6 +5643,9 @@ a {
             if(this.user.companyId == '936') {
                 this.getkeyNodes()
             }
+            if (this.user.timeType.projectManDay == 1) {
+                this.getManDaySetting();
+            }
         }
     };
 </script>

+ 3 - 3
fhKeeper/formulahousekeeper/timesheet_h5/src/views/index/index.vue

@@ -187,10 +187,10 @@
                         this.routers.push({name: '查看日报',url: '/calendar',icon: 'description'})
                         if(this.user.companyId != '1071') { // 针对物奇公司去掉填写日报
                             this.routers.push({name: '填写日报',url: '/edit',icon: 'edit'})
-                        }
-                        // if (this.user.companyId == 817 || this.user.companyId == 7 || this.user.companyId == 10) {
+                            //物奇临时去掉按周填报
                             this.routers.push({name: '按周填报',url: '/weekEdit',icon: 'records'})
-                        // }
+                        }
+                        // this.routers.push({name: '按周填报',url: '/weekEdit',icon: 'records'})                        }
                     }
                     if(list[i].name == '待办任务') {
                         this.routers.push({