فهرست منبع

Merge remote-tracking branch 'origin/master'

liuyc 2 سال پیش
والد
کامیت
e6460c34ee
25فایلهای تغییر یافته به همراه577 افزوده شده و 199 حذف شده
  1. 3 0
      blade-service-api/blade-control-api/src/main/java/org/springblade/control/entity/EmployeeTaskInfo.java
  2. 1 0
      blade-service/blade-control/src/main/java/org/springblade/control/controller/AnnualBudgetController.java
  3. 14 0
      blade-service/blade-control/src/main/java/org/springblade/control/mapper/EmployeeTaskInfoMapper.java
  4. 18 0
      blade-service/blade-control/src/main/java/org/springblade/control/mapper/EmployeeTaskInfoMapper.xml
  5. 3 0
      blade-service/blade-control/src/main/java/org/springblade/control/mapper/PlanInformMapper.java
  6. 3 0
      blade-service/blade-control/src/main/java/org/springblade/control/mapper/PlanInformMapper.xml
  7. 1 0
      blade-service/blade-control/src/main/java/org/springblade/control/mapper/ProjectCostBudgetMapper.xml
  8. 1 0
      blade-service/blade-control/src/main/java/org/springblade/control/mapper/ProjectInfoMapper.java
  9. 3 0
      blade-service/blade-control/src/main/java/org/springblade/control/mapper/ProjectInfoMapper.xml
  10. 37 0
      blade-service/blade-control/src/main/java/org/springblade/control/service/IEmployeeTaskInfoService.java
  11. 3 0
      blade-service/blade-control/src/main/java/org/springblade/control/service/IPlanInformService.java
  12. 3 0
      blade-service/blade-control/src/main/java/org/springblade/control/service/IProjectCostBudgetService.java
  13. 71 157
      blade-service/blade-control/src/main/java/org/springblade/control/service/impl/AnnualBudgetServiceImpl.java
  14. 2 0
      blade-service/blade-control/src/main/java/org/springblade/control/service/impl/DepartmentPlanLogImpl.java
  15. 170 0
      blade-service/blade-control/src/main/java/org/springblade/control/service/impl/EmployeeTaskInfoServiceImpl.java
  16. 27 0
      blade-service/blade-control/src/main/java/org/springblade/control/service/impl/PlanInformServiceImpl.java
  17. 103 16
      blade-service/blade-control/src/main/java/org/springblade/control/service/impl/ProjectCostBudgetServiceImpl.java
  18. 5 0
      blade-service/blade-control/src/main/java/org/springblade/control/service/impl/ProjectInfoServiceImpl.java
  19. 21 8
      blade-service/blade-control/src/main/java/org/springblade/control/service/impl/TaskProcessServiceImpl.java
  20. 1 1
      blade-service/blade-manager/src/main/java/com/mixsmart/utils/CustomFunction.java
  21. 38 6
      blade-service/blade-manager/src/main/java/com/mixsmart/utils/FormulaUtils.java
  22. 44 8
      blade-service/blade-manager/src/main/java/com/mixsmart/utils/StringUtils.java
  23. 2 1
      blade-service/blade-manager/src/main/java/org/springblade/manager/controller/FormulaController.java
  24. 1 0
      blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/FormulaTurnPoint.java
  25. 2 2
      blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

+ 3 - 0
blade-service-api/blade-control-api/src/main/java/org/springblade/control/entity/EmployeeTaskInfo.java

@@ -65,6 +65,9 @@ public class EmployeeTaskInfo extends BaseEntity {
     @ApiModelProperty(value = "员工当天工资")
     private BigDecimal employeeSalary;
 
+    @ApiModelProperty(value = "测算其他支出均摊到天")
+    private BigDecimal avgOtherCost;
+
     @DateTimeFormat(
             pattern = "yyyy-MM-dd"
     )

+ 1 - 0
blade-service/blade-control/src/main/java/org/springblade/control/controller/AnnualBudgetController.java

@@ -8,6 +8,7 @@ import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParams;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
+import org.apache.poi.ss.usermodel.Workbook;
 import org.springblade.control.dto.AnnualBudgetDTO;
 import org.springblade.control.dto.ControlProjectInfoDTO;
 import org.springblade.control.entity.AnnualBudget;

+ 14 - 0
blade-service/blade-control/src/main/java/org/springblade/control/mapper/EmployeeTaskInfoMapper.java

@@ -27,4 +27,18 @@ public interface EmployeeTaskInfoMapper extends BaseMapper<EmployeeTaskInfo> {
     void deleteByBudgetParentId(@Param("ids") List<Long> ids,@Param("parentId") Long parentId);
 
     void deleteByBudgetIdAndParentId(@Param("id") Long id);
+
+    BigDecimal getAllEmployeeSalaryByYear(@Param("year") int y);
+
+    List<EmployeeTaskInfo> getAllEmployeeSalaryByYear2(@Param("year") int y);
+
+    List<EmployeeTaskInfo> getAllEmployeeSalaryByProject(@Param("projectId") Long projectId);
+
+    //根据项目获取所有预算工作日
+    List<EmployeeTaskInfo> getAllBudgetSalaryByProject(@Param("projectId") Long projectId);
+
+    //根据年获取所有预算工作日
+    List<EmployeeTaskInfo> getAllBudgetSalaryByYear(@Param("year") int y);
+
+    void setAvgOtherCostByParentId(@Param("id") Long id,@Param("avg") BigDecimal avg);
 }

+ 18 - 0
blade-service/blade-control/src/main/java/org/springblade/control/mapper/EmployeeTaskInfoMapper.xml

@@ -1,6 +1,9 @@
 <?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="org.springblade.control.mapper.EmployeeTaskInfoMapper">
+    <update id="setAvgOtherCostByParentId">
+        update c_employee_task_info set avg_other_cost = #{avg} where budget_parent_id = #{id}
+    </update>
 
 
     <delete id="deleteByBudgetId">
@@ -21,4 +24,19 @@
         delete from c_employee_task_info
         where (budget_id = #{id} or budget_parent_id = #{id}) and work_type = 0
     </delete>
+    <select id="getAllEmployeeSalaryByYear" resultType="java.math.BigDecimal">
+        select SUM(employee_salary) from c_employee_task_info WHERE work_type = 1 and DATE_FORMAT(one_day, '%Y') = #{year}
+    </select>
+    <select id="getAllEmployeeSalaryByYear2" resultType="org.springblade.control.entity.EmployeeTaskInfo">
+        select * from c_employee_task_info WHERE work_type = 1 and DATE_FORMAT(one_day, '%Y') = #{year}
+    </select>
+    <select id="getAllEmployeeSalaryByProject" resultType="org.springblade.control.entity.EmployeeTaskInfo">
+        select * from c_employee_task_info WHERE work_type = 1 and project_id = #{projectId}
+    </select>
+    <select id="getAllBudgetSalaryByProject" resultType="org.springblade.control.entity.EmployeeTaskInfo">
+        select * from c_employee_task_info WHERE work_type = 0 and project_id = #{projectId}
+    </select>
+    <select id="getAllBudgetSalaryByYear" resultType="org.springblade.control.entity.EmployeeTaskInfo">
+        select * from c_employee_task_info WHERE work_type = 0 and DATE_FORMAT(one_day, '%Y') = #{year}
+    </select>
 </mapper>

+ 3 - 0
blade-service/blade-control/src/main/java/org/springblade/control/mapper/PlanInformMapper.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Param;
 import org.springblade.control.entity.AnnualBudgetDisburse;
 import org.springblade.control.entity.PlanInform;
+import org.springblade.system.user.entity.User;
 
 import java.util.List;
 
@@ -16,4 +17,6 @@ public interface PlanInformMapper extends BaseMapper<PlanInform> {
 
 
     List<PlanInform> getUserInform(@Param("userId") Long userId);
+
+    User getUserById(@Param("id") Long taskUser);
 }

+ 3 - 0
blade-service/blade-control/src/main/java/org/springblade/control/mapper/PlanInformMapper.xml

@@ -8,4 +8,7 @@
         order by inform_date desc
         limit 5
     </select>
+    <select id="getUserById" resultType="org.springblade.system.user.entity.User">
+        SELECT id,name FROM blade_user WHERE id = #{id}
+    </select>
 </mapper>

+ 1 - 0
blade-service/blade-control/src/main/java/org/springblade/control/mapper/ProjectCostBudgetMapper.xml

@@ -46,6 +46,7 @@
         <if test="budget.unitType != null and budget.unitType != ''">
             and pcb.unit_type = #{budget.unitType}
         </if>
+        ORDER BY pcb.sort
     </select>
     <select id="getBudgetTotalByProjectId" resultType="org.springblade.control.entity.ProjectCostBudgetStats">
         select

+ 1 - 0
blade-service/blade-control/src/main/java/org/springblade/control/mapper/ProjectInfoMapper.java

@@ -57,4 +57,5 @@ public interface ProjectInfoMapper extends BaseMapper<ControlProjectInfo> {
     //返回指定项目,指定费用分类对应的进程
     List<ProjectReimburseVO> getProjectReimburse3(@Param("projectId") Long projectId,@Param("costType") Integer costType);
 
+    String getProjectNameByBudgetId(@Param("id") Long id);
 }

+ 3 - 0
blade-service/blade-control/src/main/java/org/springblade/control/mapper/ProjectInfoMapper.xml

@@ -128,5 +128,8 @@
         WHERE fri.is_deleted = 0 and fri.status = 2
             and #{year} = DATE_FORMAT(fri.fr_date ,'%Y')
     </select>
+    <select id="getProjectNameByBudgetId" resultType="java.lang.String">
+        select cpi.name  from c_control_project_info cpi WHERE id = (SELECT pcb.project_id from c_project_cost_budget pcb WHERE pcb.id = #{id})
+    </select>
 
 </mapper>

+ 37 - 0
blade-service/blade-control/src/main/java/org/springblade/control/service/IEmployeeTaskInfoService.java

@@ -12,6 +12,7 @@ import org.springblade.core.mp.support.Query;
 
 import java.math.BigDecimal;
 import java.time.LocalDate;
+import java.time.Year;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -31,4 +32,40 @@ public interface IEmployeeTaskInfoService extends BaseService<EmployeeTaskInfo>
 
     //根据父预算id删除工作信息,并且排除到正在进行中的计划
     void deleteByBudgetParentId(List<Long> ids,Long parentId);
+
+    //根据父预算id修改所有日期的,其他平均预算
+    void setAvgOtherCostByParentId(Long id,BigDecimal avg);
+
+
+    /**
+     *  实际支出相关接口
+     */
+    //根据年查询当年所有的人工支出
+    BigDecimal getAllEmployeeSalaryByYear(int y);
+
+    //根据年查询当年所有的人工支出,并按照项目分组,组里的数据是每个月的支出,如果该项目没有支出将不会插入
+    Map<Long,Map<Integer, BigDecimal>> getAllEmployeeSalaryByYear2(int y);
+
+    //根据年查询当年所有的人工支出,并按照项目分组,组里的数据是项目年支出,如果该项目没有支出将不会插入
+    Map<Long,BigDecimal> getAllEmployeeSalaryByYear3(int y);
+
+    //获取项目的所有支出,按环节分组,如果该环节没有支出,将不会插入
+    Map<Long,BigDecimal> getAllEmployeeSalaryByProject(Long projectId);
+
+    //根据年查询所有人工支出,按月分组,当月没有支出将不会插入
+    Map<Integer, BigDecimal> getAllEmployeeSalaryByYear4(int y);
+
+    //根据年查询除所有人工支出,按部门分组,再按月统计
+    Map<Long,Map<Integer, BigDecimal>> getAllEmployeeSalaryByYear5(int y);
+
+
+
+    /**
+     *  预算支出相关接口
+     */
+    //根据项目id,获取项目所有的预算支出,按照环节分组,如果该环节没有支出,将不会插入
+    Map<Long,BigDecimal> getAllBudgetSalaryByProject(Long projectId);
+
+    //根据年查询所有预算支出,按月分组,当月没有支出将不会插入
+    Map<Integer, BigDecimal> getAllBudgetSalaryByYear(int y);
 }

+ 3 - 0
blade-service/blade-control/src/main/java/org/springblade/control/service/IPlanInformService.java

@@ -18,4 +18,7 @@ public interface IPlanInformService extends BaseService<PlanInform> {
     //任务完成,传入任务名称.任务人和审批人
     void taskFinishedInform(String taskName,Long taskUser,String appUser,Integer status);
     void taskFinishedInform2(String taskName,String taskUser,String appUser,Integer status);
+
+    //任务转移审批通过,通知
+    void taskChangedInform(Long taskUser,Long changedUser,String appUserName,String planDesc);
 }

+ 3 - 0
blade-service/blade-control/src/main/java/org/springblade/control/service/IProjectCostBudgetService.java

@@ -92,6 +92,9 @@ public interface IProjectCostBudgetService extends BaseService<ProjectCostBudget
     //任务审批完成闭环时,计算当前任务的实际用时和人工成本,传入任务id和任务实际完成时间
     void taskFinishedStats(Long PlanId,LocalDate practicalFinishTime);
 
+    //任务转移审批通过时,计算上一个任务人工作量,并清空workDate
+    void taskChangeStats(Long PlanId,Long taskUser);
+
     //获取所有项目截至当年的维护支出
     BigDecimal getAllMaintainCost(int year);
 

+ 71 - 157
blade-service/blade-control/src/main/java/org/springblade/control/service/impl/AnnualBudgetServiceImpl.java

@@ -52,6 +52,8 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
 
     private final WorkDateInfoMapper dateInfoMapper;
 
+    private final IEmployeeTaskInfoService employeeTaskInfoService;
+
     /**
      * 新增年度经营预算
      * @param dto
@@ -420,7 +422,7 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
 
         //统计今年的已盈利:已收入-支出 ,目前已支出只统计闭环的计划
         //获取今年人工支出
-        BigDecimal yearStaffDisburse = budgetService.getYearStaffDisburse(year);
+        BigDecimal yearStaffDisburse = employeeTaskInfoService.getAllEmployeeSalaryByYear(year);
         //获取今年维护支出
         BigDecimal cost = budgetService.getAllMaintainCost(LocalDate.now().getYear());
         //获取今年报销支出
@@ -493,8 +495,9 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
         //总实际收入:当年所有回款
         BigDecimal yearReturned = returnedInfoService.getYearReturned(y);
         map.put("yearReturned",yearReturned);
-        //总实际支出:当年所有报销支出,和人工支出
-        BigDecimal yearStaffDisburse = budgetService.getYearStaffDisburse(y);
+        //总实际支出=报销支出+人工支出+维护支出
+        //人工支出
+        BigDecimal yearStaffDisburse = employeeTaskInfoService.getAllEmployeeSalaryByYear(y);
         //维护支出
         BigDecimal cost;
         if (y == 0){
@@ -557,9 +560,11 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
         List<AnnualProjectCostVO> mapList = new ArrayList<>();
         //按年查询所有支出,按照项目分组,然后再按照月份分组统计
         //查询人工支出
-        List<ProjectCostBudget> budgetByYear = budgetService.getBudgetByYear(y);
-        Map<Long, List<ProjectCostBudget>> map = budgetByYear.parallelStream()
-                .collect(Collectors.groupingBy(ProjectCostBudget::getProjectId));
+        Map<Long, Map<Integer, BigDecimal>> mapMap = employeeTaskInfoService.getAllEmployeeSalaryByYear2(y);
+        Boolean isCost = true;
+        if (mapMap == null || mapMap.size() <= 0){
+            isCost = false;
+        }
         //维护支出
         Map<Long, List<BigDecimal>> listMap = budgetService.getAllMaintainCost3(y);
         Boolean isMaintain = true;
@@ -575,50 +580,13 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
         for (ControlProjectInfo project : list) {
             AnnualProjectCostVO vo = new AnnualProjectCostVO();
             List<Integer> integerList = new ArrayList<>();
-            List<ProjectCostBudget> budgets = map.get(project.getId());
             for (int i = 1; i <= 12; i++) {
                 BigDecimal big = new BigDecimal(0);
-                if (budgets != null && budgets.size() > 0) {
-                    for (ProjectCostBudget budget : budgets) {
-                        //计算人工支出
-                        if (budget.getRealPlanStartTime().getYear() != y || budget.getPracticalFinishTime().getYear() != y){
-                            if (budget.getIsTwoMonth() != 1){
-                                throw new ServiceException("计划年份异常2");
-                            }
-                            if (budget.getPracticalFinishTime().getYear() != y){
-                                //如果结束时间不是今年,则开始月大于等于当前月才计算
-                                if (budget.getRealPlanStartTime().getMonthValue() == i) {
-                                    big = big.add(budget.getPracticalStartMoney());
-                                }
-                            }else {
-                                if (budget.getPracticalFinishTime().getMonthValue() == i) {
-                                    big = big.add(budget.getPracticalEndMoney());
-                                }
-                            }
-                        }else {
-                            //开始和结束时间没有跨年,但是需要判断是否跨月,如果没有跨月,则判断是否是当前月完成
-                            if (budget.getIsTwoMonth() == 0) {
-                                if (budget.getPracticalFinishTime().getMonthValue() == i) {
-                                    big = big.add(budget.getActualTotalMoney());
-                                }
-                            }else {
-                                //如果跨月则判断是否包含当前月
-                                LocalDate startTime = budget.getRealPlanStartTime();
-                                LocalDate endTime = budget.getPracticalFinishTime();
-                                if (startTime.getMonthValue() <= i && endTime.getMonthValue() >= i){
-                                    if (startTime.getMonthValue() == i){
-                                        //开始时间是当月,获取当月工作日,除以总工作日,乘以总工资
-
-                                    }else if (endTime.getMonthValue() == i){
-                                        //开始时间是当月,获取当月工作日,除以总工作日,乘以总工资
-                                    }else {
-                                        //判断此月之前的工作日,如果此工作日已经大于总工作日,那么此月不算支出
-
-                                        //获取此月整月工作日,用总工作日,减去此月之前的工作日,如果此月工作日大于结果工作日,则使用结果工作日
-                                    }
-                                }
-                            }
-                        }
+                //计算人工支出
+                if (isCost && mapMap.get(project.getId()) != null){
+                    Map<Integer, BigDecimal> map = mapMap.get(project.getId());
+                    if (map.get(i) != null) {
+                        big = big.add(map.get(i));
                     }
                 }
                 //计算维护
@@ -781,9 +749,6 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
     @Override
     public List<ProjectIncomeCostRatioVO> portalProjectCostRatio(String date) {
         int y = Integer.parseInt(date.substring(0,4));
-//        if ("汇总所有".equals(date)){
-//            date = "";
-//        }
         //获取项目列表
         List<ControlProjectInfo> list = projectInfoService.listByYear(Integer.parseInt(date.substring(0,4)));
         if (list == null || list.size() <= 0){
@@ -802,9 +767,9 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
             isReimburse = false;
         }
         List<ProjectIncomeCostRatioVO> vos = new ArrayList<>();
-        //按年获取闭环任务,根据项目分组
-        List<ProjectCostBudget> costByMonth = budgetService.getBudgetByYear(y);
-        if (costByMonth == null || costByMonth.size() <= 0){
+        //获取全年人工支出,如果为null,则直接返回
+        Map<Long, BigDecimal> costMap = employeeTaskInfoService.getAllEmployeeSalaryByYear3(y);
+        if (costMap == null || costMap.size() <= 0){
             //没有闭环任务,为每个项目设置为0
             for (ControlProjectInfo info : list) {
                 ProjectIncomeCostRatioVO vo = new ProjectIncomeCostRatioVO();
@@ -820,33 +785,14 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
             }
             return vos;
         }
-        Map<Long, List<ProjectCostBudget>> map = costByMonth.parallelStream()
-                .collect(Collectors.groupingBy(ProjectCostBudget::getProjectId));
         //为每个项目设置支出
         for (ControlProjectInfo info : list) {
             ProjectIncomeCostRatioVO vo = new ProjectIncomeCostRatioVO();
             vo.setProjectName(info.getName());
             BigDecimal big = new BigDecimal(0);
             //获取人工支出
-            List<ProjectCostBudget> budgets = map.get(info.getId());
-            if (budgets != null && budgets.size() > 0){
-                for (ProjectCostBudget budget : budgets) {
-//                    big = big.add(budget.getActualTotalMoney());
-                    if (budget.getRealPlanStartTime().getYear() != y || budget.getPracticalFinishTime().getYear() != y){
-                        if (budget.getIsTwoMonth() != 1){
-                            throw new ServiceException("计划年份异常3");
-                        }
-                        if (budget.getPracticalFinishTime().getYear() != y){
-                            //如果结束时间不是今年,则使用开始金额
-                            big = big.add(budget.getPracticalStartMoney());
-                        }else {
-                            big = big.add(budget.getPracticalEndMoney());
-                        }
-                    }else {
-                        big = big.add(budget.getActualTotalMoney());
-                    }
-
-                }
+            if (costMap.get(info.getId()) != null){
+                big = big.add(costMap.get(info.getId()));
             }
             //维护支出
             if (isMaintain){
@@ -927,16 +873,10 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
         }else {
             isPlan2 = false;
         }
-        //获取项目所有已经闭环的固定计划
-        List<ProjectCostBudget> finishedTask = budgetService.getProjectAllFinishedTask(projectId, null);
-        Map<Long, List<ProjectCostBudget>> collect = new HashMap<>();
-        boolean isPlan = true ;
-        if (finishedTask != null && finishedTask.size() > 0){
-            collect = finishedTask.parallelStream()
-                    .collect(Collectors.groupingBy(ProjectCostBudget::getProjectProcess));
-        }else {
-            isPlan = false;
-        }
+        //获取项目的所有支出,按环节分组
+        Map<Long, BigDecimal> budgetMap = employeeTaskInfoService.getAllBudgetSalaryByProject(projectId);
+        //获取项目的所有支出,按环节分组
+        Map<Long, BigDecimal> costMap = employeeTaskInfoService.getAllEmployeeSalaryByProject(projectId);
         //项目每个进程的维护支出
         Map<Long, BigDecimal> maintainMap = budgetService.getAllMaintainCost8(projectId);
         Boolean isMaintain = true;
@@ -990,68 +930,24 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
                 vo.setProcessProgressBar(0);
             }
             //设置进程支出金额,统计人工支出,维护支出,报销支出
-            if (!isPlan){
-                //没有完成的任务就不用设置人工支出
-                //报销支出
-                if (isReimburse){
-                    if (reimburseMap.get(process.getId()) != null){
-                        vo.setProcessCostCount(reimburseMap.get(process.getId()));
-                    }
-                }else {
-                    vo.setProcessCostCount(new BigDecimal(0));
-                }
-
-                //维护支出
-                if (isMaintain && maintainMap.get(process.getId()) != null){
-                    if (vo.getProcessCostCount() == null) {
-                        vo.setProcessCostCount(maintainMap.get(process.getId()));
-                    }else {
-                        vo.setProcessCostCount(vo.getProcessCostCount().add(maintainMap.get(process.getId())));
-                    }
-                }
-            }else {
-                //有完成的任务,设置人工支出
-                List<ProjectCostBudget> budgets = collect.get(process.getId());
-                if (budgets != null && budgets.size() > 0){
-                    //计算所有任务支出总和
-                    BigDecimal big = new BigDecimal(0);
-                    for (ProjectCostBudget budget : budgets) {
-                        big = big.add(budget.getActualTotalMoney());
-                    }
-                    //设置报销支出
-                    if (isReimburse){
-                        if (reimburseMap.get(process.getId()) != null){
-                            big = big.add(reimburseMap.get(process.getId()));
-                        }
-                    }
-                    //设置维护支出
-                    if (isMaintain && maintainMap.get(process.getId()) != null){
-                           big = big.add(maintainMap.get(process.getId()));
-                    }
-                    vo.setProcessCostCount(big);
-                }else {
-                    //没有人工支出
-                    //设置报销支出
-                    if (isReimburse){
-                        if (reimburseMap.get(process.getId()) != null){
-                            vo.setProcessCostCount(reimburseMap.get(process.getId()));
-                        }
-                    }else {
-                        vo.setProcessCostCount(new BigDecimal(0));
-                    }
-
-                    //维护支出
-                    if (isMaintain && maintainMap.get(process.getId()) != null){
-                        if (vo.getProcessCostCount() == null) {
-                            vo.setProcessCostCount(maintainMap.get(process.getId()));
-                        }else {
-                            vo.setProcessCostCount(vo.getProcessCostCount().add(maintainMap.get(process.getId())));
-                        }
-                    }
+            //设置人工支出
+            BigDecimal big = new BigDecimal(0);
+            if (costMap != null && costMap.get(process.getId()) != null){
+                big = big.add(costMap.get(process.getId()));
+            }
+            //设置报销支出
+            if (isReimburse){
+                if (reimburseMap.get(process.getId()) != null){
+                    big = big.add(reimburseMap.get(process.getId()));
                 }
             }
+            //设置维护支出
+            if (isMaintain && maintainMap.get(process.getId()) != null){
+                   big = big.add(maintainMap.get(process.getId()));
+            }
+            vo.setProcessCostCount(big);
             //设置进程支出金额百分比,统计实际支出和预算的百分比
-            if (isPlan2){
+            if (budgetMap != null){
                 List<ProjectCostBudget> budgets = collect2.get(process.getId());
                 if (budgets != null && budgets.size() > 0) {
                     BigDecimal allMoney = new BigDecimal(0);
@@ -1061,13 +957,9 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
                             budget.setBudgetCountMoney(new BigDecimal(0));
                         }
                         allMoney = allMoney.add(budget.getBudgetCountMoney());
-//                        //统计人工支出
-//                        if (budget.getTaskApprove() == 1) {
-//                            costMoney = costMoney.add(budget.getActualTotalMoney());
-//                        }
                     }
-                    //统计报销支出
-                    if (vo.getProcessCostCount() != null && allMoney.intValue() != 0){
+                    //统计占比
+                    if (vo.getProcessCostCount().intValue() != 0 && allMoney.intValue() != 0){
                         vo.setProcessCostProgressBar(vo.getProcessCostCount().divide(allMoney, 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).intValue());
                     }else {
                         vo.setProcessProgressBar(0);
@@ -1110,7 +1002,8 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
         //获取所有项目当年每月的实际回款
         List<BigDecimal> returned2 = returnedInfoService.getAllMonthReturnedByYear(y,2);
         //获取每月实际的人工支出
-        List<BigDecimal> staffCost = budgetService.getAllMonthStaffCostByYear(y);
+//        List<BigDecimal> staffCost = budgetService.getAllMonthStaffCostByYear(y);
+        Map<Integer, BigDecimal> costMap = employeeTaskInfoService.getAllEmployeeSalaryByYear4(y);
         //获取每月实际的维护支出
         List<BigDecimal> maintainCost = budgetService.getAllMonthMaintainCostByYear(y);
         //获取每月实际的报销支出
@@ -1156,8 +1049,12 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
             vo1.setIncome3(returned2.get(i-1));
             c5 = c5.add(returned2.get(i-1));
             //实际每月支出
-            vo1.setDisburse3(staffCost.get(i-1).add(maintainCost.get(i-1).add(reimburse.get(i-1))));
-            c6 = c6.add(staffCost.get(i-1).add(maintainCost.get(i-1).add(reimburse.get(i-1))));
+            BigDecimal big = new BigDecimal(0);
+            if (costMap != null && costMap.get(i) != null){
+                big = costMap.get(i);
+            }
+            vo1.setDisburse3(big.add(maintainCost.get(i-1).add(reimburse.get(i-1))));
+            c6 = c6.add(big.add(maintainCost.get(i-1).add(reimburse.get(i-1))));
 
         list.add(vo1);
         }
@@ -1173,6 +1070,19 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
         return list;
     }
 
+
+    /**
+     * 预算与实际统计-部门支出统计
+     */
+    public List<BudgetAndPracticalByDeptVO> budgetAndPracticalByDept2(String year) {
+        int y = Integer.parseInt(year.substring(0, 4));
+        //结果集
+        List<BudgetAndPracticalByDeptVO> list = new ArrayList<>();
+        List<String> months = Arrays.asList("一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月");
+        //
+        return null;
+    }
+
     /**
      * 预算与实际统计-部门支出统计
      */
@@ -1980,7 +1890,7 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
         vo.setPracticalInput(yearReturned);
         //获取当年所有实际支出: 人工支出+维护支出+报销支出
         //人工支出
-        BigDecimal disburse = budgetService.getYearStaffDisburse(y);
+        BigDecimal disburse = employeeTaskInfoService.getAllEmployeeSalaryByYear(y);
         //维护支出
         BigDecimal maintainCost = budgetService.getAllMaintainCost(y);
         //报销支出
@@ -2009,7 +1919,7 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
         }
         List<BigDecimal> costList = disburseService.budgetCostByYear(annualId);
         //一年的实际人工支出,按月返回指定年的
-        List<BigDecimal> staffCostList = budgetService.getAllMonthStaffCostByYear2(y);
+        Map<Integer, BigDecimal> costMap = employeeTaskInfoService.getAllBudgetSalaryByYear(y);
         //管理成本预算支出  = 年度经营的非人工成本,按月返回指定年的
         List<BigDecimal> notCostList = disburseService.budgetNotCostByYear(annualId);
         //管理成本实际支出 = 指定年的每个月报销,按月返回
@@ -2026,8 +1936,12 @@ public class AnnualBudgetServiceImpl extends BaseServiceImpl<AnnualBudgetMapper,
             vo.setDisburse1(costList.get(i));
             b1 = b1.add(costList.get(i));
             //设置人工成本实际支出
-            vo.setDisburse2(staffCostList.get(i));
-            b2 = b2.add(staffCostList.get(i));
+            BigDecimal big = new BigDecimal(0);
+            if (costMap != null && costMap.get(i+1) != null){
+                big = costMap.get(i+1);
+            }
+            vo.setDisburse2(big);
+            b2 = b2.add(big);
             //设置管理成本预算支出
             vo.setDisburse3(notCostList.get(i));
             b3 = b3.add(notCostList.get(i));

+ 2 - 0
blade-service/blade-control/src/main/java/org/springblade/control/service/impl/DepartmentPlanLogImpl.java

@@ -113,6 +113,8 @@ public class DepartmentPlanLogImpl extends BaseServiceImpl<DepartmentPlanLogMapp
                         str.append(localDate.toString() + ",");
                     }
                     log.setWorkDate(str.toString());
+                }else {
+                    throw new ServiceException("任务日期错误,请联系管理员");
                 }
             }
         }else {

+ 170 - 0
blade-service/blade-control/src/main/java/org/springblade/control/service/impl/EmployeeTaskInfoServiceImpl.java

@@ -68,4 +68,174 @@ public class EmployeeTaskInfoServiceImpl extends BaseServiceImpl<EmployeeTaskInf
     public void deleteByBudgetParentId(List<Long> ids, Long parentId) {
         baseMapper.deleteByBudgetParentId(ids,parentId);
     }
+
+    /**
+     * 根据父预算id修改所有日期的,其他平均预算
+     * @param id
+     * @param avg
+     */
+    @Override
+    public void setAvgOtherCostByParentId(Long id, BigDecimal avg) {
+        baseMapper.setAvgOtherCostByParentId(id,avg);
+    }
+
+    /**
+     * 根据年查询当年所有的人工支出
+     * @param y
+     * @return
+     */
+    @Override
+    public BigDecimal getAllEmployeeSalaryByYear(int y) {
+        BigDecimal decimal = baseMapper.getAllEmployeeSalaryByYear(y);
+        if (decimal == null){
+            return new BigDecimal(0);
+        }
+        return decimal;
+    }
+
+    /**
+     * 根据年查询当年所有的人工支出,并按照项目分组,组里的数据是每个月的支出,如果该项目没有支出将不会插入
+     * @param y
+     * @return
+     */
+    @Override
+    public Map<Long, Map<Integer, BigDecimal>> getAllEmployeeSalaryByYear2(int y) {
+        List<EmployeeTaskInfo> list = baseMapper.getAllEmployeeSalaryByYear2(y);
+        if (list != null && list.size() > 0){
+            Map<Long, Map<Integer, BigDecimal>> map = new HashMap<>();
+            Map<Long, List<EmployeeTaskInfo>> listMap = list.parallelStream()
+                    .collect(Collectors.groupingBy(EmployeeTaskInfo::getProjectId));
+            for (Long aLong : listMap.keySet()) {
+                //该项目所有支出
+                List<EmployeeTaskInfo> infoList = listMap.get(aLong);
+                //按月份分组
+                Map<Integer, BigDecimal> monthMap = infoList.stream().collect(
+                        Collectors.groupingBy(
+                                o -> o.getOneDay().getMonthValue(),
+                                Collectors.mapping(EmployeeTaskInfo::getEmployeeSalary, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))
+                        ));
+                map.put(aLong,monthMap);
+            }
+            return map;
+        }
+        return null;
+    }
+
+    /**
+     * 根据年查询当年所有的人工支出,并按照项目分组,组里的数据是项目年支出,如果该项目没有支出将不会插入
+     * @param y
+     * @return
+     */
+    @Override
+    public Map<Long, BigDecimal> getAllEmployeeSalaryByYear3(int y) {
+        List<EmployeeTaskInfo> list = baseMapper.getAllEmployeeSalaryByYear2(y);
+        if (list != null && list.size() > 0){
+            //按项目分组
+            Map<Long, BigDecimal> monthMap = list.stream().collect(
+                    Collectors.groupingBy(
+                            o -> o.getProjectId(),
+                            Collectors.mapping(EmployeeTaskInfo::getEmployeeSalary, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))
+                    ));
+            return monthMap;
+        }
+        return null;
+    }
+
+    /**
+     * 获取项目的所有支出,按环节分组
+     * @param projectId
+     * @return
+     */
+    @Override
+    public Map<Long, BigDecimal> getAllEmployeeSalaryByProject(Long projectId) {
+        List<EmployeeTaskInfo> list = baseMapper.getAllEmployeeSalaryByProject(projectId);
+        if (list != null && list.size() > 0){
+            //按项目分组
+            Map<Long, BigDecimal> monthMap = list.stream().collect(
+                    Collectors.groupingBy(
+                            o -> o.getProjectProcess(),
+                            Collectors.mapping(EmployeeTaskInfo::getEmployeeSalary, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))
+                    ));
+            return monthMap;
+        }
+        return null;
+    }
+
+    /**
+     * 根据年查询所有人工支出,按月分组,当月没有支出将不会插入
+     * @param y
+     * @return
+     */
+    @Override
+    public Map<Integer, BigDecimal> getAllEmployeeSalaryByYear4(int y) {
+        List<EmployeeTaskInfo> list = baseMapper.getAllEmployeeSalaryByYear2(y);
+        if (list != null && list.size() > 0){
+            //按项目分组
+            Map<Integer, BigDecimal> monthMap = list.stream().collect(
+                    Collectors.groupingBy(
+                            o -> o.getOneDay().getMonthValue(),
+                            Collectors.mapping(EmployeeTaskInfo::getEmployeeSalary, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))
+                    ));
+            return monthMap;
+        }
+        return null;
+    }
+
+    /**
+     * 根据年查询除所有人工支出,按部门分组,再按月统计
+     * @param y
+     * @return
+     */
+    @Override
+    public Map<Long, Map<Integer, BigDecimal>> getAllEmployeeSalaryByYear5(int y) {
+        List<EmployeeTaskInfo> list = baseMapper.getAllEmployeeSalaryByYear2(y);
+        if (list != null && list.size() > 0){
+            Map<Long, Map<Integer, BigDecimal>> map = new HashMap<>();
+            Map<Long, List<EmployeeTaskInfo>> listMap = list.parallelStream()
+                    .collect(Collectors.groupingBy(EmployeeTaskInfo::getDeptId));
+            for (Long aLong : listMap.keySet()) {
+                //该项目所有支出
+                List<EmployeeTaskInfo> infoList = listMap.get(aLong);
+                //按月份分组
+                Map<Integer, BigDecimal> monthMap = infoList.stream().collect(
+                        Collectors.groupingBy(
+                                o -> o.getOneDay().getMonthValue(),
+                                Collectors.mapping(EmployeeTaskInfo::getEmployeeSalary, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))
+                        ));
+                map.put(aLong,monthMap);
+            }
+            return map;
+        }
+        return null;
+    }
+
+    @Override
+    public Map<Long, BigDecimal> getAllBudgetSalaryByProject(Long projectId) {
+        List<EmployeeTaskInfo> list = baseMapper.getAllBudgetSalaryByProject(projectId);
+        if (list != null && list.size() > 0){
+            //按项目分组
+            Map<Long, BigDecimal> monthMap = list.stream().collect(
+                    Collectors.groupingBy(
+                            o -> o.getProjectProcess(),
+                            Collectors.mapping(EmployeeTaskInfo::getEmployeeSalary, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))
+                    ));
+            return monthMap;
+        }
+        return null;
+    }
+
+    @Override
+    public Map<Integer, BigDecimal> getAllBudgetSalaryByYear(int y) {
+        List<EmployeeTaskInfo> list = baseMapper.getAllBudgetSalaryByYear(y);
+        if (list != null && list.size() > 0){
+            //按项目分组
+            Map<Integer, BigDecimal> monthMap = list.stream().collect(
+                    Collectors.groupingBy(
+                            o -> o.getOneDay().getMonthValue(),
+                            Collectors.mapping(EmployeeTaskInfo::getEmployeeSalary, Collectors.reducing(BigDecimal.ZERO, BigDecimal::add))
+                    ));
+            return monthMap;
+        }
+        return null;
+    }
 }

+ 27 - 0
blade-service/blade-control/src/main/java/org/springblade/control/service/impl/PlanInformServiceImpl.java

@@ -21,6 +21,7 @@ import org.springblade.core.log.exception.ServiceException;
 import org.springblade.core.mp.base.BaseServiceImpl;
 import org.springblade.core.mp.support.Query;
 import org.springblade.core.secure.utils.SecureUtil;
+import org.springblade.system.user.entity.User;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -99,4 +100,30 @@ public class PlanInformServiceImpl extends BaseServiceImpl<PlanInformMapper, Pla
         this.saveBatch(list);
     }
 
+    /**
+     * 任务转移审批通过,通知
+     * @param taskUser
+     * @param changedUser
+     */
+    @Override
+    public void taskChangedInform(Long taskUser, Long changedUser, String appUserName,String planDesc) {
+        List<PlanInform> list = new ArrayList<>();
+        //获取任务人
+        User u1 = baseMapper.getUserById(taskUser);
+        //通知任务人
+        PlanInform inform1 = new PlanInform();
+        inform1.setInformDetails("《任务转移》" + "已被" + "【" + appUserName + "】" + "审批通过");
+        inform1.setInformUser(taskUser);
+        inform1.setInformDate(LocalDateTime.now());
+        list.add(inform1);
+        //获取转移人
+        PlanInform inform2 = new PlanInform();
+        inform2.setInformDetails("【" + u1.getName() + "】" + "向您转移了任务" + "《" + planDesc + "》");
+        inform2.setInformUser(changedUser);
+        inform2.setInformDate(LocalDateTime.now());
+        list.add(inform2);
+        //通知转移人
+        this.saveBatch(list);
+    }
+
 }

+ 103 - 16
blade-service/blade-control/src/main/java/org/springblade/control/service/impl/ProjectCostBudgetServiceImpl.java

@@ -486,9 +486,15 @@ public class ProjectCostBudgetServiceImpl extends BaseServiceImpl<ProjectCostBud
                 List<Long> ids = vo2ChildrenList.stream().filter(l -> l.getStatus() != null && l.getStatus() != 1).map(ProjectCostBudgetVO2::getId).collect(Collectors.toList());
                 //清空除进行中之外的子计划的 员工任务信息表
                 employeeTaskInfoService.deleteByBudgetParentId(ids,vo2.getId());
+                BigDecimal allTotal = new BigDecimal(0);
+                Boolean isTaskType = false;
                 for (ProjectCostBudget budget : vo2ChildrenList) {
                     //如果计划正在进行中或者已经完成,则跳过
                     if (budget.getStatus() != null && budget.getStatus() != 1){
+                        if (map2.get(budget.getPlanTaskType()).get(0).getDictValue() == 1) {
+                            isTaskType = true;
+                        }
+                        allTotal = allTotal.add(budget.getPlanDays());
                         continue;
                     }
                     //如果保存太快,没有生成planDays,就查询
@@ -512,6 +518,7 @@ public class ProjectCostBudgetServiceImpl extends BaseServiceImpl<ProjectCostBud
 
                     //只计算固定计划的人工成本
                     if (map2.get(budget.getPlanTaskType()).get(0).getDictValue() == 1) {
+                        isTaskType = true;
                         LocalDate startTime = budget.getPlanStartTime();
                         LocalDate endTime = budget.getPlanEndTime();
                         List<EmployeeTaskInfo> infoList = new ArrayList<>();
@@ -519,6 +526,7 @@ public class ProjectCostBudgetServiceImpl extends BaseServiceImpl<ProjectCostBud
                         BigDecimal postMoney = new BigDecimal(map.get(vo2.getPostType()).get(0).getDictValue());
                         //获取计划日期中的工作日
                         List<LocalDate> workDaysList = dateInfoMapper.getWorkDaysList(startTime, endTime);
+                        allTotal = allTotal.add(new BigDecimal(workDaysList.size()));
                         for (LocalDate today : workDaysList) {
                             //保存预算到任务计划表
                             EmployeeTaskInfo employeeTaskInfo = new EmployeeTaskInfo();
@@ -569,6 +577,16 @@ public class ProjectCostBudgetServiceImpl extends BaseServiceImpl<ProjectCostBud
                         }
                     }
                 }
+                //修改所有父id下的其他平均工资
+                if (isTaskType){
+                    BigDecimal otherCost = vo2.getBudgetCountMoney().subtract(vo2.getBudgetStaffCost());
+                    BigDecimal other = new BigDecimal(0);
+                    //查看成本测算中是否包含其他支出
+                    if (otherCost.intValue() != 0 ){
+                        other = otherCost.divide(allTotal,2, BigDecimal.ROUND_HALF_UP);
+                    }
+                    employeeTaskInfoService.setAvgOtherCostByParentId(vo2.getId(),other);
+                }
                 childrenList.addAll(vo2ChildrenList);
             }else {
                 //无子计划
@@ -585,7 +603,8 @@ public class ProjectCostBudgetServiceImpl extends BaseServiceImpl<ProjectCostBud
                     if (budget.getStatus() != null && budget.getStatus() != 1){
                         continue;
                     }
-                    employeeTaskInfoService.deleteByBudgetId(budget.getId());
+                    employeeTaskInfoService.deleteByBudgetIdAndParentId(budget.getId());
+//                    employeeTaskInfoService.deleteByBudgetId(budget.getId());
                     //存在数据,则判断是否是固定计划
                     if (map2.get(budget.getPlanTaskType()).get(0).getDictValue() == 1) {
                         LocalDate startTime = budget.getPlanStartTime();
@@ -595,6 +614,12 @@ public class ProjectCostBudgetServiceImpl extends BaseServiceImpl<ProjectCostBud
                         BigDecimal postMoney = new BigDecimal(map.get(vo2.getPostType()).get(0).getDictValue());
                         //获取计划日期中的工作日
                         List<LocalDate> workDaysList = dateInfoMapper.getWorkDaysList(startTime, endTime);
+                        BigDecimal otherCost = budget.getBudgetCountMoney().subtract(budget.getBudgetStaffCost());
+                        BigDecimal other = new BigDecimal(0);
+                        //查看成本测算中是否包含其他支出
+                        if (otherCost.intValue() != 0 ){
+                            other = otherCost.divide(new BigDecimal(workDaysList.size()),2, BigDecimal.ROUND_HALF_UP);
+                        }
                         for (LocalDate today : workDaysList) {
                             //保存预算到任务计划表
                             EmployeeTaskInfo employeeTaskInfo = new EmployeeTaskInfo();
@@ -611,6 +636,7 @@ public class ProjectCostBudgetServiceImpl extends BaseServiceImpl<ProjectCostBud
                             employeeTaskInfo.setWorkType(0);
                             employeeTaskInfo.setPostType(budget.getPostType());
                             employeeTaskInfo.setEmployeeSalary(postMoney);
+                            employeeTaskInfo.setAvgOtherCost(other);
                             infoList.add(employeeTaskInfo);
                         }
                         employeeTaskInfoService.saveBatch(infoList);
@@ -1039,7 +1065,7 @@ public class ProjectCostBudgetServiceImpl extends BaseServiceImpl<ProjectCostBud
                             big = big.add(budget.getActualTotalMoney());
                         }else {
                             if (budget.getPracticalTaskDays().intValue() != 0) {
-                                BigDecimal decimal = new BigDecimal(workDays).divide(budget.getPracticalTaskDays()).multiply(budget.getActualTotalMoney()).setScale(2, RoundingMode.HALF_UP);
+                                BigDecimal decimal = new BigDecimal(workDays).divide(budget.getPracticalTaskDays(),2, BigDecimal.ROUND_HALF_UP).multiply(budget.getActualTotalMoney()).setScale(2, RoundingMode.HALF_UP);
                                 big = big.add(decimal);
                             }
                         }
@@ -1050,7 +1076,7 @@ public class ProjectCostBudgetServiceImpl extends BaseServiceImpl<ProjectCostBud
                         Integer workDays = dateInfoMapper.getWorkDays(start, end);
                         //如果工作日大于等于实际完成工作日,则今年的支出就是0
                         if (workDays < budget.getPracticalTaskDays().intValue()){
-                            BigDecimal decimal = new BigDecimal(workDays).divide(budget.getPracticalTaskDays()).multiply(budget.getActualTotalMoney()).setScale(2, RoundingMode.HALF_UP);
+                            BigDecimal decimal = new BigDecimal(workDays).divide(budget.getPracticalTaskDays(),2, BigDecimal.ROUND_HALF_UP).multiply(budget.getActualTotalMoney()).setScale(2, RoundingMode.HALF_UP);
                             big = big.add(budget.getActualTotalMoney().subtract(decimal));
                         }
                     }
@@ -1426,7 +1452,7 @@ public class ProjectCostBudgetServiceImpl extends BaseServiceImpl<ProjectCostBud
         int taskType = dictInfo.getDictValue().intValue();
         //计划为临时计划,则不计算金额直接闭环
         if (taskType == 2){
-            //为临时任务设置任务实际实际,方便统计
+            //为临时任务设置任务实际天数,方便统计
             budget.setPracticalTaskDays(new BigDecimal(1 + budget.getPracticalFinishTime().until(budget.getRealPlanStartTime(), ChronoUnit.DAYS)));
             this.updateById(budget);
         }else {
@@ -1438,24 +1464,29 @@ public class ProjectCostBudgetServiceImpl extends BaseServiceImpl<ProjectCostBud
             Double money = userInfo.getOneMoney();
             //为固定计划,则获取最后一条任务日志
             DepartmentPlanLog planLog = logMapper.getNewestPlanLog(PlanId);
-
             //为员工任务信息表插入实际工作时间
-            //获取计划日期中的工作日
+            String workDate = planLog.getWorkDate();
+            StringBuilder str = new StringBuilder();
             List<LocalDate> workDaysList = new ArrayList<>();
-            if (planLog.getSort() == 1){
-                workDaysList.addAll(dateInfoMapper.getWorkDaysList(budget.getRealPlanStartTime(), budget.getPracticalFinishTime()));
-            }else if (planLog.getSort() == 2){
-                workDaysList.addAll(dateInfoMapper.getWorkDaysList(budget.getRealPlanStartTime(), planLog.getPauseTime()));
-            }else {
-                //获取所有的计划日志,计算真实工作时间
-                List<DepartmentPlanLog> logList = logMapper.getAllLog(PlanId);
-                for (DepartmentPlanLog log : logList) {
-
+            //如果最后一条任务操作是暂停,则直接使用工作日集合
+            if (StringUtils.isNotBlank(workDate)){
+                String[] days = workDate.split(",");
+                if (days != null && days.length > 0){
+                    for (String day : days) {
+                        workDaysList.add(LocalDate.parse(day));
+                    }
+                }
+            }
+            //如果最后一条任务操作是开启,则+最后开启时间与提交日期之间的工作日
+            if (planLog.getStatus() == 1){
+                List<LocalDate> list = dateInfoMapper.getWorkDaysList(planLog.getOpenPlanStartTime(), practicalFinishTime);
+                if (list != null && list.size() > 0){
+                    workDaysList.addAll(list);
                 }
             }
             List<EmployeeTaskInfo> infoList = new ArrayList<>();
             for (LocalDate today : workDaysList) {
-                //保存预算到任务计划表
+                //保存实际执行任务时间-到任务计划表
                 EmployeeTaskInfo employeeTaskInfo = new EmployeeTaskInfo();
                 employeeTaskInfo.setBudgetId(budget.getId());
                 employeeTaskInfo.setProjectId(budget.getProjectId());
@@ -1523,6 +1554,62 @@ public class ProjectCostBudgetServiceImpl extends BaseServiceImpl<ProjectCostBud
         }
     }
 
+    /**
+     * 任务转移审批通过时,计算上一个任务人工作量,并清空workDate
+     * @param PlanId
+     */
+    @Override
+    public void taskChangeStats(Long PlanId,Long taskUser) {
+        ProjectCostBudget budget = this.getById(PlanId);
+        //如果为临时任务,则直接跳过
+        DictInfo dictInfo = baseMapper.getTaskType(budget.getPlanTaskType());
+        int taskType = dictInfo.getDictValue().intValue();
+        //计划为固定计划时,则插入工作量,清空workDate
+        if (taskType == 1){
+            //获取任务人工资
+            User userInfo = baseMapper.getUserInfo(taskUser);
+            if (userInfo.getOneMoney() == null){
+                throw new ServiceException("没有为任务人设置工资");
+            }
+            Double money = userInfo.getOneMoney();
+            DepartmentPlanLog planLog = logMapper.getNewestPlanLog(PlanId);
+            //为员工任务信息表插入实际工作时间
+            String workDate = planLog.getWorkDate();
+            List<LocalDate> workDaysList = new ArrayList<>();
+            //直接使用工作日集合
+            if (StringUtils.isNotBlank(workDate)){
+                String[] days = workDate.split(",");
+                if (days != null && days.length > 0){
+                    for (String day : days) {
+                        workDaysList.add(LocalDate.parse(day));
+                    }
+                    List<EmployeeTaskInfo> infoList = new ArrayList<>();
+                    for (LocalDate today : workDaysList) {
+                        //保存预算到任务计划表
+                        EmployeeTaskInfo employeeTaskInfo = new EmployeeTaskInfo();
+                        employeeTaskInfo.setBudgetId(budget.getId());
+                        employeeTaskInfo.setProjectId(budget.getProjectId());
+                        employeeTaskInfo.setBudgetParentId(budget.getParentId());
+                        employeeTaskInfo.setUnitType(budget.getUnitType());
+                        employeeTaskInfo.setDeptId(budget.getDeptId());
+                        employeeTaskInfo.setCostType(budget.getCostType());
+                        employeeTaskInfo.setTaskDetail(budget.getTaskDetail());
+                        employeeTaskInfo.setProjectProcess(budget.getProjectProcess());
+                        employeeTaskInfo.setBudgetType(budget.getBudgetType());
+                        employeeTaskInfo.setOneDay(today);
+                        employeeTaskInfo.setWorkType(1);
+                        employeeTaskInfo.setPostType(budget.getPostType());
+                        employeeTaskInfo.setEmployeeSalary(new BigDecimal(money));
+                        infoList.add(employeeTaskInfo);
+                    }
+                    employeeTaskInfoService.saveBatch(infoList);
+                    planLog.setWorkDate("");
+                    logMapper.updateById(planLog);
+                }
+            }
+        }
+    }
+
     /**
      * 根据年份获取所有项目的维护支出
      * @return

+ 5 - 0
blade-service/blade-control/src/main/java/org/springblade/control/service/impl/ProjectInfoServiceImpl.java

@@ -52,6 +52,11 @@ public class ProjectInfoServiceImpl extends BaseServiceImpl<ProjectInfoMapper, C
 
     private final JdbcTemplate jdbcTemplate;
 
+
+    public String getProjectNameByBudgetId(Long id){
+        return baseMapper.getProjectNameByBudgetId(id);
+    }
+
     /**
      * 自定义分页
      *

+ 21 - 8
blade-service/blade-control/src/main/java/org/springblade/control/service/impl/TaskProcessServiceImpl.java

@@ -890,6 +890,10 @@ public class TaskProcessServiceImpl extends BaseServiceImpl<TaskProcessMapper, T
                         planInformService.taskFinishedInform2("计划任务完成", taskProcessInfo.getAuditUserIds(), SecureUtil.getNickName(), taskProcessInfo.getStatus());
 
                     } else if (dto.getUpdateType().equals("2")) {
+                        //如果任务正在进行中,则提示要先暂停才能转移
+                        if (planTaskInfo.getStatus() != 3){
+                            throw new ServiceException("请先暂停任务,再转移");
+                        }
                         //任务转移
                         TaskProcessInfo taskProcessInfo = new TaskProcessInfo();
                         taskProcessInfo.setId(SnowFlakeUtil.getId());
@@ -1081,6 +1085,8 @@ public class TaskProcessServiceImpl extends BaseServiceImpl<TaskProcessMapper, T
 
                             //删除当前计划任务与日志关系信息(如果任务转移,那么就不属于该用户了,就应该在新用户写日志时,与新用户绑定)
                             jdbcTemplate.execute("delete from c_log_history_task_record where task_id = " + dataId);
+
+
                         }
 
                     } else if (taskStatus == 3) { //驳回审批
@@ -1190,18 +1196,24 @@ public class TaskProcessServiceImpl extends BaseServiceImpl<TaskProcessMapper, T
         switch (businessDataType) {
             case 1:
                 //计划任务
-                TaskProcessInfo taskProcessInfo1 = jdbcTemplate.query("select status from c_task_process_info where id = " + approveTaskId, new BeanPropertyRowMapper<>(TaskProcessInfo.class)).stream().findAny().orElse(null);
+                TaskProcessInfo taskProcessInfo1 = jdbcTemplate.query("select report_user_id,task_name,status from c_task_process_info where id = " + approveTaskId, new BeanPropertyRowMapper<>(TaskProcessInfo.class)).stream().findAny().orElse(null);
                 ProjectCostBudget projectCostBudget = jdbcTemplate.query("select plan_task_desc,task_user,id from c_project_cost_budget where id = " + dataId, new BeanPropertyRowMapper<>(ProjectCostBudget.class)).stream().findAny().orElse(null);
                 if (taskProcessInfo1 != null && projectCostBudget != null) {
                     //获取任务完成时间
                     TaskPlanUpdateStatusInfo taskPlanUpdateStatusInfo = jdbcTemplate.query("select completion_time from c_task_plan_update_status_info where update_type = 1 and approve_task_id = " + approveTaskId + " and plan_task_id = " + dataId, new BeanPropertyRowMapper<>(TaskPlanUpdateStatusInfo.class)).stream().findAny().orElse(null);
-                    if (taskPlanUpdateStatusInfo != null && taskProcessInfo1.getStatus().equals(2)) { //已完成的任务才推送
-                        //修改任务实际完成时间、金额
-                        LocalDate localDate = taskPlanUpdateStatusInfo.getCompletionTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
-                        projectCostBudgetService.taskFinishedStats(projectCostBudget.getId(), localDate);
+                    if (taskProcessInfo1.getTaskName().contains("完成任务")){
+                        if (taskPlanUpdateStatusInfo != null && taskProcessInfo1.getStatus().equals(2)) { //已完成的任务才推送
+                            //修改任务实际完成时间、金额
+                            LocalDate localDate = taskPlanUpdateStatusInfo.getCompletionTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+                            projectCostBudgetService.taskFinishedStats(projectCostBudget.getId(), localDate);
+                        }
+                        //日志操作信息
+                        planInformService.taskFinishedInform(projectCostBudget.getPlanTaskDesc(), projectCostBudget.getTaskUser(), SecureUtil.getUserName(), taskProcessInfo1.getStatus());
+                    }else if (taskProcessInfo1.getTaskName().contains("转移任务")){
+                        projectCostBudgetService.taskChangeStats(Long.parseLong(dataId),taskProcessInfo1.getReportUserId());
+                        //日志操作信息
+                        planInformService.taskChangedInform(taskPlanUpdateStatusInfo.getStartTransferObject(),taskPlanUpdateStatusInfo.getTransferObject(), SecureUtil.getUserName(),projectCostBudget.getPlanTaskDesc());
                     }
-                    //日志操作信息
-                    planInformService.taskFinishedInform(projectCostBudget.getPlanTaskDesc(), projectCostBudget.getTaskUser(), SecureUtil.getUserName(), taskProcessInfo1.getStatus());
                 }
 
                 break;
@@ -1307,8 +1319,9 @@ public class TaskProcessServiceImpl extends BaseServiceImpl<TaskProcessMapper, T
             case 10:
                 TaskProcessInfo taskProcessInfo10 = jdbcTemplate.query("select status,report_user_id from c_task_process_info where id = " + approveTaskId, new BeanPropertyRowMapper<>(TaskProcessInfo.class)).stream().findAny().orElse(null);
                 if (taskProcessInfo10 != null && taskProcessInfo10.getStatus().equals(2)) {
+                    String name = projectInfoServiceImpl.getProjectNameByBudgetId(Long.parseLong(dataId));
                     //日志操作信息
-                    planInformService.taskFinishedInform("成本测算申请", taskProcessInfo10.getReportUserId(), SecureUtil.getNickName(), taskProcessInfo10.getStatus());
+                    planInformService.taskFinishedInform(name +"-成本测算申请", taskProcessInfo10.getReportUserId(), SecureUtil.getNickName(), 4);
                 }
                 break;
         }

+ 1 - 1
blade-service/blade-manager/src/main/java/com/mixsmart/utils/CustomFunction.java

@@ -1327,7 +1327,7 @@ public class CustomFunction {
                     int _hz = Integer.parseInt(i < rateIn.length ? rateIn[i] : rateIn[rateIn.length - 1]);
                     String _deviation = i < deviationIn.length ? deviationIn[i] : deviationIn[deviationIn.length - 1];
                     String _pass = i < passIn.length ? passIn[i] : passIn[passIn.length - 1];
-                    int _scale = StringUtils.getScale(e, _deviation);
+                    int _scale = StringUtils.getScaleZero(e, _deviation);
                     String delimiter = StringUtils.handleNull(matcherFindGroup("[^0-9.]", e, 0, false));
                     if (StringUtils.isEmpty(delimiter)) {
                         delimiter = CONCAT;

+ 38 - 6
blade-service/blade-manager/src/main/java/com/mixsmart/utils/FormulaUtils.java

@@ -138,6 +138,21 @@ public class FormulaUtils {
         return result;
     }
 
+
+    public static void main(String[] args) {
+        FormData fd = new FormData();
+        fd.setEName("1111");
+        List<ElementData> list = new ArrayList<>();
+        list.add(new ElementData(1,1,1));
+        test(fd);
+        System.out.println(fd.getEName());
+    }
+    public static void  test(FormData fd){
+        fd.setEName("22222");
+        fd.getValues().add(new ElementData(2,2,2));
+    }
+
+
     public  static void write(FormData fd, Object data,Boolean nullOrBlank ){
         if(Func.isEmpty(fd.getValues())){
             /*无定位信息不写入*/
@@ -350,7 +365,7 @@ public class FormulaUtils {
         //huangjn 每份填报数据的id,目前日志专用
     }
 
-    /**从元素名称中解析项目名称*/
+    /**从元素名称中解析项目名称,细化项目匹配用*/
     public static  String parseItemName(String eName){
         if (StringUtils.isEmpty(eName)) {
             return eName;
@@ -369,6 +384,19 @@ public class FormulaUtils {
                 .collect(Collectors.joining());
     }
 
+    /*A15检查内容专用*/
+    public static  String checkItemName(String eName){
+        if (StringUtils.isEmpty(eName)) {
+            return eName;
+        }
+        /*分割字符串,选取第一个匹配的子串*/
+        String str = eName.replaceAll("\\s", "");
+        Pattern pattern = compile("[((_]");
+        String[] candidate = pattern.split(str);
+        String regex = "[^\\u4e00-\\u9fa5]+";
+        return Arrays.stream(candidate).map(s->s.replaceAll(regex,"")).distinct().filter(StringUtils::isNotEmpty).filter(s->!isContainKeywords2(s)).findFirst().orElse("");
+    }
+
     private static String filterString(String s, Pattern p) {
         s=s.replaceAll("【[^【】]+】","");
         Matcher matcher = p.matcher(s);
@@ -383,6 +411,10 @@ public class FormulaUtils {
         List<String> keywords = Arrays.asList( ":", "个","附录","抽查","测","求","小于","大于","检查","仪","按","不","各","记录","且","规定","值或实");
         return keywords.stream().anyMatch(s::contains);
     }
+    private static boolean isContainKeywords2(String s) {
+        List<String> keywords = Arrays.asList( "实测项目");
+        return keywords.stream().anyMatch(s::contains);
+    }
 
     public static List<String> itemNames =Arrays.asList(
             ""
@@ -422,13 +454,13 @@ public class FormulaUtils {
             ,"竖直度(mm)_挖孔桩_0.5%桩长,且≤200_铅锤线:每桩检测_实测值或实测偏差值"
             , "2△_压浆压力值 (Mpa)_满足施工技术 规范规定_查油压表读书;每管道检查_实测值或实测偏差值"
             , "基底承载力(KPa)_不小于设计_实测值或实测偏差值"
+            ,"1△_受力钢筋间距 (mm)_两排以上间距_±5_实测值或实测偏差值"
     );
 
-/*
-    public static void main(String[] args) {
-        itemNames.stream().map(FormulaUtils::parseItemName).forEach(System.out::println);
-    }
-*/
+/*    public static void main(String[] args) {
+     //   itemNames.stream().map(FormulaUtils::parseItemName).forEach(System.out::println);
+        itemNames.stream().map(FormulaUtils::checkItemName).forEach(System.out::println);
+    }*/
 
     /**
      * @Description 深度拷贝

+ 44 - 8
blade-service/blade-manager/src/main/java/com/mixsmart/utils/StringUtils.java

@@ -11,12 +11,14 @@ import java.io.UnsupportedEncodingException;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
 import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.text.DecimalFormat;
 import java.text.SimpleDateFormat;
 import java.util.*;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 
 /**
@@ -952,7 +954,7 @@ public class StringUtils {
         if (value instanceof Number) {
             return true;
         }
-        String pattern = "^[+-]?\\d+(\\.\\d+)?$";
+        String pattern = "^[+-]?\\d+(\\.[\\dEe]+)?$";
         Pattern r = Pattern.compile(pattern);
         Matcher m = r.matcher(String.valueOf(value));
         return m.matches();
@@ -1294,27 +1296,49 @@ public class StringUtils {
 
     /**
      * @return int
-     * @Description 获取最大小数位
+     * @Description 获取最大小数位,转String计算小数位格式,超长浮点数先转double,四舍五入取五位
      * @Param [number]
      * @Author yangyj
      * @Date 2021.12.23 15:08
      **/
+    /*去除有效数字后面的0*/
     public static Integer getScale(Object... number) {
         int max = 0;
         if (number != null) {
-            return getScale(Arrays.asList(number));
+            return getScale(scaleParam(number),1);
+        }
+        return max;
+    }
+    /*保留有效数字后面的0*/
+    public static Integer getScaleZero(Object... number){
+        int max = 0;
+        if (number != null) {
+            return getScale(scaleParam(number),0);
         }
         return max;
     }
 
-    private static Integer getScale(List<Object> number){
+    public static List<Object> scaleParam(Object ... number){
+        return Arrays.stream(number).filter(StringUtils::isNotEmpty).flatMap(e-> CustomFunction.obj2ListNe(e).stream()).distinct().filter(StringUtils::isNumber).map(e->{
+            /*0.3999999999999986 检测到超长小数位先转double处理,再还原回String*/
+            String tg=e.toString();
+            if(tg.length()-tg.indexOf(StringPool.DOT)>6||tg.contains("e")){
+                return BigDecimal.valueOf(Double.parseDouble(tg)).setScale(4, RoundingMode.HALF_UP).toString();
+            }else {
+                return e.toString();
+            }
+        }).collect(Collectors.toList());
+    }
+
+    public static final String[] SCALE_REG=new String[]{"(\\d)+.(\\d)*[0-9]","(\\d)+.(\\d)*[1-9]"};
+    private static Integer getScale(List<Object> number,Integer zero){
         int max=0;
         if(ListUtils.isNotEmpty(number)){
             for (Object n : number) {
                 if (StringUtils.isNotEmpty(n)) {
-                    String[] sa = n.toString().split(",");
+                    String[] sa = n.toString().split(StringPool.COMMA);
                     for (String s : sa) {
-                        Matcher m = RegexUtils.matcher("(\\d)+.(\\d)*[1-9]", s);
+                        Matcher m = RegexUtils.matcher(SCALE_REG[zero], s);
                         if (m.find()) {
                             int cp = new StringBuilder(m.group()).reverse().toString().indexOf(".");
                             if (cp < 5) {
@@ -1329,11 +1353,23 @@ public class StringUtils {
     }
 
 //    public static void main(String[] args) {
-//         List<Object> list = Arrays.asList("16.001",27.0,5,6);
+//        List<Double> list = new ArrayList<>();
+//        list.add(Double.parseDouble("0.3999999999999986"));
+//        list.add(Double.parseDouble("0.1999999999999996"));
+//        list.add(Double.parseDouble("-0.21"));
+//        list.add(Double.parseDouble("-1.2632e1"));
 //        System.out.println(getScale(list));
-//        System.out.println(getScale(16.00,17.00,10,8));
+//        System.out.println(getScaleZero(list));
 //    }
 
+/*    public static void main(String[] args) {
+         List<Object> list = Arrays.asList("16.001",27.0,5,6);
+        System.out.println(getScale(list));
+        System.out.println(getScaleZero(150.0));
+        System.out.println(getScale(150.0));
+
+    }*/
+
     /**
      * @return java.lang.String
      * @Description 公式脚本转义

+ 2 - 1
blade-service/blade-manager/src/main/java/org/springblade/manager/controller/FormulaController.java

@@ -500,7 +500,8 @@ public class FormulaController {
         List<Map<String, Object>> result = this.jdbcTemplate.queryForList(sql, tableName, "%" + search + "%");
         Map<String, Object> map = new HashMap<>();
         map.put("解析前", result.stream().map(e -> StringUtils.handleNull(e.get("en"))).collect(Collectors.toList()));
-        map.put("解析后", result.stream().map(e -> FormulaUtils.parseItemName(StringUtils.handleNull(e.get("en")))).collect(Collectors.toList()));
+        map.put("解析后A15", result.stream().map(e -> FormulaUtils.checkItemName(StringUtils.handleNull(e.get("en")))).collect(Collectors.toList()));
+        map.put("解析后通用数据", result.stream().map(e -> FormulaUtils.parseItemName(StringUtils.handleNull(e.get("en")))).collect(Collectors.toList()));
         return R.data(map);
     }
 

+ 1 - 0
blade-service/blade-manager/src/main/java/org/springblade/manager/formula/impl/FormulaTurnPoint.java

@@ -172,6 +172,7 @@ public class FormulaTurnPoint implements FormulaStrategy {
                 for(int i=0;i<fda.length;i++){
                     FormData fd= fda[i];
                     FormulaUtils.write(fd,group.get(i),true);
+                    fd.setUpdate(1);
                 }
             }
         });

+ 2 - 2
blade-service/blade-manager/src/main/java/org/springblade/manager/service/impl/FormulaServiceImpl.java

@@ -983,7 +983,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
         try{
             if(tec.summary.size()>0){
                 /**/
-                List<String> result=tec.checkItems.stream().filter(fdTmp->fdTmp.getValues().stream().map(ElementData::getValue).anyMatch(e->StringUtils.isNotEmpty(e)&&StringUtils.isNotEquals("/",e))).map(FormData::getEName).map(FormulaUtils::parseItemName).distinct().collect(Collectors.toList());
+                List<String> result=tec.checkItems.stream().filter(fdTmp->fdTmp.getValues().stream().map(ElementData::getValue).anyMatch(e->StringUtils.isNotEmpty(e)&&StringUtils.isNotEquals("/",e))).map(FormData::getEName).map(FormulaUtils::checkItemName).distinct().collect(Collectors.toList());
                 Optional<FormData> opk= tec.summary.stream().filter(FormData::executable).filter(f->StringUtils.isEquals(f.getFormula().getNumber(),CHECK_ITEMS)).findAny();
                 List<String> history=null;
                 if(opk.isPresent()&&!opk.get().empty()){
@@ -991,7 +991,7 @@ public class FormulaServiceImpl extends BaseServiceImpl<FormulaMapper, Formula>
                     history=  Arrays.asList(opk.get().getValues().get(0).stringValue().replaceAll("[\\s\\n]+","").split("[,、,]"));
                 }
                 if(history!=null&&history.size()>0){
-                    List<String> itemAll=tec.checkItems.stream().map(FormData::getEName).map(FormulaUtils::parseItemName).distinct().collect(Collectors.toList());
+                    List<String> itemAll=tec.checkItems.stream().map(FormData::getEName).map(FormulaUtils::checkItemName).distinct().collect(Collectors.toList());
                     List<String> customize=history.stream().filter(s->!itemAll.contains(s)).collect(Collectors.toList());
                     result.addAll(customize);
                 }