فهرست منبع

add: 考勤统计

caozixuan 1 سال پیش
والد
کامیت
ca9878107c

+ 0 - 34
sop-business/src/main/java/com/qmth/sop/business/entity/TBDingStatistic.java

@@ -68,16 +68,6 @@ public class TBDingStatistic extends BaseEntity {
     @ApiModelProperty(value = "违规天数(天)")
     private Integer violationDays;
 
-    @ApiModelProperty(value = "提交人id")
-    @JsonSerialize(using = ToStringSerializer.class)
-    private Long submitUserId;
-
-    @ApiModelProperty(value = "提交时间")
-    private Long submitTime;
-
-    @ApiModelProperty(value = "提交状态")
-    private String submitStatus;
-
     public Long getServiceId() {
         return serviceId;
     }
@@ -197,28 +187,4 @@ public class TBDingStatistic extends BaseEntity {
     public void setViolationDays(Integer violationDays) {
         this.violationDays = violationDays;
     }
-
-    public Long getSubmitUserId() {
-        return submitUserId;
-    }
-
-    public void setSubmitUserId(Long submitUserId) {
-        this.submitUserId = submitUserId;
-    }
-
-    public Long getSubmitTime() {
-        return submitTime;
-    }
-
-    public void setSubmitTime(Long submitTime) {
-        this.submitTime = submitTime;
-    }
-
-    public String getSubmitStatus() {
-        return submitStatus;
-    }
-
-    public void setSubmitStatus(String submitStatus) {
-        this.submitStatus = submitStatus;
-    }
 }

+ 22 - 1
sop-business/src/main/java/com/qmth/sop/business/service/TBDingStatisticService.java

@@ -1,7 +1,10 @@
 package com.qmth.sop.business.service;
 
-import com.qmth.sop.business.entity.TBDingStatistic;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.qmth.sop.business.entity.TBDing;
+import com.qmth.sop.business.entity.TBDingStatistic;
+
+import java.util.List;
 
 /**
  * <p>
@@ -13,6 +16,15 @@ import com.baomidou.mybatisplus.extension.service.IService;
  */
 public interface TBDingStatisticService extends IService<TBDingStatistic> {
 
+    /**
+     * 根据sopNo和用户档案id查询sop统计级路
+     *
+     * @param sopNo          sopNo
+     * @param userArchivesId 用户档案id
+     * @return 打卡统计记录
+     */
+    TBDingStatistic findBySopNoAndUserArchivesId(String sopNo, Long userArchivesId);
+
     /**
      * 构建考勤统计 (sop计划时间变更 -> 更新打卡统计时间)
      *
@@ -24,4 +36,13 @@ public interface TBDingStatisticService extends IService<TBDingStatistic> {
      * 构建考勤统计 (构建打卡统计信息)
      */
     void buildDingStatistic();
+
+    /**
+     * 构建考勤统计 (构建打卡统计信息)
+     *
+     * @param sopNo         sopNo
+     * @param datasource    数据源
+     * @param requestUserId 创建人
+     */
+    void buildDingStatisticBySop(String sopNo, List<TBDing> datasource, Long requestUserId);
 }

+ 3 - 1
sop-business/src/main/java/com/qmth/sop/business/service/impl/TBDingServiceImpl.java

@@ -90,7 +90,7 @@ public class TBDingServiceImpl extends ServiceImpl<TBDingMapper, TBDing> impleme
     private TBUserArchivesAllocationService tbUserArchivesAllocationService;
 
     @Resource
-    private TBCrmDetailService tbCrmDetailService;
+    private TBDingStatisticService tbDingStatisticService;
 
     @Override
     public DingElementResult findDingElements(String sopNo, Long userId) {
@@ -726,5 +726,7 @@ public class TBDingServiceImpl extends ServiceImpl<TBDingMapper, TBDing> impleme
             e.setDingException(dingException);
         });
         this.updateBatchById(tbDingList);
+        // 重新统计该sop的考勤数据
+        tbDingStatisticService.buildDingStatistic(sopNo);
     }
 }

+ 157 - 80
sop-business/src/main/java/com/qmth/sop/business/service/impl/TBDingStatisticServiceImpl.java

@@ -2,7 +2,9 @@ package com.qmth.sop.business.service.impl;
 
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.sop.business.bean.dto.UserDto;
 import com.qmth.sop.business.entity.TBCrm;
 import com.qmth.sop.business.entity.TBCrmDetail;
 import com.qmth.sop.business.entity.TBDing;
@@ -12,15 +14,19 @@ import com.qmth.sop.business.service.*;
 import com.qmth.sop.common.contant.SystemConstant;
 import com.qmth.sop.common.enums.DingDateTypeEnum;
 import com.qmth.sop.common.enums.ExceptionResultEnum;
+import com.qmth.sop.common.enums.RoleTypeEnum;
 import com.qmth.sop.common.enums.SopRoleTypeEnum;
-import io.swagger.models.auth.In;
+import com.qmth.sop.common.util.DateDisposeUtils;
+import org.apache.commons.collections4.CollectionUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.util.ArrayList;
 import java.util.List;
 import java.util.Objects;
 import java.util.stream.Collectors;
@@ -35,6 +41,7 @@ import java.util.stream.Collectors;
  */
 @Service
 public class TBDingStatisticServiceImpl extends ServiceImpl<TBDingStatisticMapper, TBDingStatistic> implements TBDingStatisticService {
+
     private final static Logger log = LoggerFactory.getLogger(TBDingStatisticServiceImpl.class);
 
     @Resource
@@ -47,99 +54,169 @@ public class TBDingStatisticServiceImpl extends ServiceImpl<TBDingStatisticMappe
     private TBCrmService tbCrmService;
 
     @Resource
-    private SysUserService sysUserService;
+    private SysUserRoleService sysUserRoleService;
 
-    @Resource
-    private TBUserArchivesAllocationService tbUserArchivesAllocationService;
+    @Override
+    public TBDingStatistic findBySopNoAndUserArchivesId(String sopNo, Long userArchivesId) {
+        return this.getOne(new QueryWrapper<TBDingStatistic>().lambda().eq(TBDingStatistic::getSopNo, sopNo).eq(TBDingStatistic::getUserArchivesId, userArchivesId).last(SystemConstant.LIMIT1));
+    }
 
+    @Transactional
     @Override
     public void buildDingStatistic(String sopNo) {
-
+        List<RoleTypeEnum> roleTypeList = new ArrayList<>();
+        roleTypeList.add(RoleTypeEnum.ADMIN);
+        List<UserDto> userDtoList = sysUserRoleService.userListByRoleType(roleTypeList);
+        if (CollectionUtils.isEmpty(userDtoList)) {
+            throw ExceptionResultEnum.ERROR.exception("缺少系统管理员用户");
+        }
+        // 统计前一天的数据
+        Long currentEarliestTime = DateDisposeUtils.getEarliestTime(System.currentTimeMillis());
+        List<TBDing> datasource = tbDingService.list(new QueryWrapper<TBDing>().lambda().eq(TBDing::getSopNo, sopNo)).stream().filter(e -> {
+            if (Objects.nonNull(e.getSignInTime()) && Objects.nonNull(e.getSignOutTime())) {
+                return e.getSignInTime() < currentEarliestTime && e.getSignOutTime() < currentEarliestTime;
+            } else if (Objects.isNull(e.getSignInTime())) {
+                return e.getSignOutTime() < currentEarliestTime;
+            } else if (Objects.isNull(e.getSignOutTime())) {
+                return e.getSignInTime() < currentEarliestTime;
+            } else {
+                return true;
+            }
+        }).collect(Collectors.toList());
+        this.buildDingStatisticBySop(sopNo, datasource, userDtoList.get(0).getId());
     }
 
+    @Transactional
     @Override
     public void buildDingStatistic() {
-
-        List<TBDing> datasource = tbDingService.list();
+        Long currentEarliestTime = DateDisposeUtils.getEarliestTime(System.currentTimeMillis());
+
+        // 统计前一天的数据
+        List<TBDing> datasource = tbDingService.list().stream().filter(e -> {
+            if (Objects.nonNull(e.getSignInTime()) && Objects.nonNull(e.getSignOutTime())) {
+                return e.getSignInTime() < currentEarliestTime && e.getSignOutTime() < currentEarliestTime;
+            } else if (Objects.isNull(e.getSignInTime())) {
+                return e.getSignOutTime() < currentEarliestTime;
+            } else if (Objects.isNull(e.getSignOutTime())) {
+                return e.getSignInTime() < currentEarliestTime;
+            } else {
+                return true;
+            }
+        }).collect(Collectors.toList());
         List<String> sopNoList = datasource.stream().map(TBDing::getSopNo).distinct().collect(Collectors.toList());
-
+        List<RoleTypeEnum> roleTypeList = new ArrayList<>();
+        roleTypeList.add(RoleTypeEnum.ADMIN);
+        List<UserDto> userDtoList = sysUserRoleService.userListByRoleType(roleTypeList);
+        if (CollectionUtils.isEmpty(userDtoList)) {
+            throw ExceptionResultEnum.ERROR.exception("缺少系统管理员用户");
+        }
         for (String sopNo : sopNoList) {
-            TBCrmDetail tbCrmDetail = tbCrmDetailService.findBySopNo(sopNo);
-            if (Objects.isNull(tbCrmDetail)){
-                log.error(String.format("sopNo[%s]未找到派单详情信息",sopNo));
-                throw ExceptionResultEnum.ERROR.exception("未找到派单详情信息");
-            }
-            
-            String crmNo = tbCrmDetail.getCrmNo();
-            TBCrm tbCrm = tbCrmService.findByCrmNo(crmNo);
-            if (Objects.isNull(tbCrm)){
-                log.error(String.format("crmNo[%s]未找到派单信息",crmNo));
-                throw ExceptionResultEnum.ERROR.exception("未找到派单信息");
-            }
+            List<TBDing> sopDingInfo = datasource.stream().filter(e -> e.getSopNo().equals(sopNo)).collect(Collectors.toList());
+            this.buildDingStatisticBySop(sopNo, sopDingInfo, userDtoList.get(0).getId());
+        }
+    }
+
+    @Transactional
+    @Override
+    public void buildDingStatisticBySop(String sopNo, List<TBDing> datasource, Long requestUserId) {
+        List<TBDingStatistic> tbDingStatisticList = new ArrayList<>();
+        TBCrmDetail tbCrmDetail = tbCrmDetailService.findBySopNo(sopNo);
+        if (Objects.isNull(tbCrmDetail)) {
+            log.error(String.format("sopNo[%s]未找到派单详情信息", sopNo));
+            throw ExceptionResultEnum.ERROR.exception("未找到派单详情信息");
+        }
 
-            Long serviceUnitId = tbCrm.getServiceId();
-
-
-            Long scanStartTime = tbCrmDetail.getScanStartTime();
-            Long scanEndTime = tbCrmDetail.getScanEndTime();
-            Long markPaperStartTime = tbCrmDetail.getMarkPaperStartTime();
-            Long markPaperEndTime = tbCrmDetail.getMarkPaperEndTime();
-            // 该sop计划有效的日期
-            
-            
-            List<Long> userArchivesIdList = datasource.stream().filter(e -> Objects.equals(sopNo, e.getSopNo())).map(TBDing::getUserArchivesId).distinct().collect(Collectors.toList());
-
-            for (Long archivesId : userArchivesIdList) {
-                // 打卡数据集合
-                List<TBDing> dingList = datasource.stream()
-                        .filter(e -> Objects.equals(sopNo, e.getSopNo()) && Objects.equals(archivesId, e.getUserArchivesId())).collect(Collectors.toList());
-
-                // 非异常打卡(打卡时间在计划时间范围内 以及 缺少签到或签退的)
-                List<TBDing> effectDingList = dingList.stream().filter(e -> !e.getDingException()).collect(Collectors.toList());
-
-                List<SopRoleTypeEnum> sopRoleTypeList = dingList.stream().flatMap(e -> {
-                    String sopRoleTypeStr = e.getSopRoleType();
-                    List<SopRoleTypeEnum> list = JSONArray.parseArray(sopRoleTypeStr, SopRoleTypeEnum.class);
-                    return list.stream();
-                }).distinct().collect(Collectors.toList());
-                String sopRoleType = JSON.toJSONString(sopRoleTypeList);
-
-                // 根据非异常打卡数据统计
-                int actualDays = 0;
-                int weekDays = 0;
-                int weekends = 0;
-                int legalHolidays = 0;
-                BigDecimal workHours = BigDecimal.ZERO;
-                BigDecimal var = new BigDecimal(3600000);
-                for (TBDing effectDing : effectDingList) {
-                    if (!SystemConstant.isOneNull(effectDing.getSignInTime(), effectDing.getSignOutTime())){
-                        // 有效天数
-                        actualDays ++;
-                        DingDateTypeEnum dateType = effectDing.getDateType();
-                        switch (dateType){
-                            case WEEKEND:
-                                weekends ++;
-                                break;
-                            case LEGAL_HOLIDAYS:
-                                legalHolidays ++;
-                                break;
-                            default:
-                                weekDays ++;
-                                break;
-                        }
-                        // 累计工时
-                        workHours = workHours.add(new BigDecimal(effectDing.getSignOutTime() - effectDing.getSignInTime()).divide(var, 1,
-                                RoundingMode.HALF_UP));
+        String crmNo = tbCrmDetail.getCrmNo();
+        TBCrm tbCrm = tbCrmService.findByCrmNo(crmNo);
+        if (Objects.isNull(tbCrm)) {
+            log.error(String.format("crmNo[%s]未找到派单信息", crmNo));
+            throw ExceptionResultEnum.ERROR.exception("未找到派单信息");
+        }
+
+        Long serviceUnitId = tbCrm.getServiceId();
+
+        Long scanStartTime = tbCrmDetail.getScanStartTime();
+        Long scanEndTime = tbCrmDetail.getScanEndTime();
+        Long markPaperStartTime = tbCrmDetail.getMarkPaperStartTime();
+        Long markPaperEndTime = tbCrmDetail.getMarkPaperEndTime();
+        // 该sop计划有效的日期
+
+        List<Long> userArchivesIdList = datasource.stream().filter(e -> Objects.equals(sopNo, e.getSopNo())).map(TBDing::getUserArchivesId).distinct().collect(Collectors.toList());
+
+        for (Long userArchivesId : userArchivesIdList) {
+            // 打卡数据集合
+            List<TBDing> dingList = datasource.stream()
+                    .filter(e -> Objects.equals(sopNo, e.getSopNo()) && Objects.equals(userArchivesId, e.getUserArchivesId())).collect(Collectors.toList());
+
+            // 非异常打卡(打卡时间在计划时间范围内 以及 缺少签到或签退的)
+            List<TBDing> effectDingList = dingList.stream().filter(e -> !e.getDingException()).collect(Collectors.toList());
+
+            List<SopRoleTypeEnum> sopRoleTypeList = dingList.stream().flatMap(e -> {
+                String sopRoleTypeStr = e.getSopRoleType();
+                List<SopRoleTypeEnum> list = JSONArray.parseArray(sopRoleTypeStr, SopRoleTypeEnum.class);
+                return list.stream();
+            }).distinct().collect(Collectors.toList());
+            String sopRoleType = JSON.toJSONString(sopRoleTypeList);
+
+            // 根据非异常打卡数据统计
+            int actualDays = 0;
+            int weekDays = 0;
+            int weekends = 0;
+            int legalHolidays = 0;
+            BigDecimal workHours = BigDecimal.ZERO;
+            BigDecimal var = new BigDecimal(3600000);
+            for (TBDing effectDing : effectDingList) {
+                if (!SystemConstant.isOneNull(effectDing.getSignInTime(), effectDing.getSignOutTime())) {
+                    // 有效天数
+                    actualDays++;
+                    DingDateTypeEnum dateType = effectDing.getDateType();
+                    switch (dateType) {
+                    case WEEKEND:
+                        weekends++;
+                        break;
+                    case LEGAL_HOLIDAYS:
+                        legalHolidays++;
+                        break;
+                    default:
+                        weekDays++;
+                        break;
                     }
+                    // 累计工时
+                    workHours = workHours.add(
+                            new BigDecimal(effectDing.getSignOutTime() - effectDing.getSignInTime()).divide(var, 1,
+                                    RoundingMode.HALF_UP));
                 }
-                // 违规工时
-                int violationDays = Math.toIntExact(
-                        dingList.stream().filter(e -> SystemConstant.isOneNull(e.getSignInTime(), e.getSignOutTime()))
-                                .count());
-                
-                TBDingStatistic tbDingStatistic = new TBDingStatistic();
-                // TODO: 2024/5/23 新增实体对象-czx 
             }
+            // 违规工时
+            int violationDays = Math.toIntExact(
+                    dingList.stream().filter(e -> SystemConstant.isOneNull(e.getSignInTime(), e.getSignOutTime()))
+                            .count());
+
+            TBDingStatistic tbDingStatistic;
+            tbDingStatistic = this.findBySopNoAndUserArchivesId(sopNo, userArchivesId);
+            if (Objects.isNull(tbDingStatistic)) {
+                tbDingStatistic = new TBDingStatistic();
+                tbDingStatistic.insertInfo(requestUserId);
+            } else {
+                tbDingStatistic.updateInfo(requestUserId);
+            }
+            tbDingStatistic.setServiceId(serviceUnitId);
+            tbDingStatistic.setSopNo(sopNo);
+            tbDingStatistic.setCrmNo(crmNo);
+            tbDingStatistic.setUserArchivesId(userArchivesId);
+            tbDingStatistic.setScanStartTime(scanStartTime);
+            tbDingStatistic.setScanEndTime(scanEndTime);
+            tbDingStatistic.setMarkPaperStartTime(markPaperStartTime);
+            tbDingStatistic.setMarkPaperEndTime(markPaperEndTime);
+            tbDingStatistic.setSopRoleType(sopRoleType);
+            tbDingStatistic.setActualDays(actualDays);
+            tbDingStatistic.setWeekdays(weekDays);
+            tbDingStatistic.setWeekends(weekends);
+            tbDingStatistic.setLegalHolidays(legalHolidays);
+            tbDingStatistic.setWorkHours(workHours);
+            tbDingStatistic.setViolationDays(violationDays);
+            tbDingStatisticList.add(tbDingStatistic);
         }
+        this.saveOrUpdateBatch(tbDingStatisticList);
     }
 }

+ 7 - 0
sop-business/src/main/resources/db/log/caozixuan_update_log.sql

@@ -139,3 +139,10 @@ ALTER TABLE t_b_ding_submit
     CHANGE COLUMN violation_days violation_days INT NULL DEFAULT NULL COMMENT '违规天数(天)' ;
 ALTER TABLE t_b_ding_statistic
     CHANGE COLUMN violation_days violation_days INT NULL DEFAULT NULL COMMENT '违规天数(天)' ;
+
+-- 2024-05-24
+ALTER TABLE t_b_ding_statistic
+    DROP COLUMN submit_status,
+    DROP COLUMN submit_time,
+    DROP COLUMN submit_user_id;
+

+ 5 - 1
sop-common/src/main/java/com/qmth/sop/common/enums/JobEnum.java

@@ -35,7 +35,11 @@ public enum JobEnum {
 
     AUTO_ADD_DING_RECORD("自动打卡定时任务"),
 
-    AUTO_ADD_DING_RECORD_GROUP("自动打卡定时任务组");
+    AUTO_ADD_DING_RECORD_GROUP("自动打卡定时任务组"),
+
+    DING_STATISTIC("考勤统计定时任务"),
+
+    DING_STATISTIC_GROUP("考勤统计定时任务组");
 
     private String title;
 

+ 27 - 0
sop-task/src/main/java/com/qmth/sop/task/job/DingStatisticJob.java

@@ -0,0 +1,27 @@
+package com.qmth.sop.task.job;
+
+import com.qmth.sop.common.enums.ExceptionResultEnum;
+import com.qmth.sop.task.job.service.JobService;
+import org.quartz.JobExecutionContext;
+import org.springframework.scheduling.quartz.QuartzJobBean;
+
+import javax.annotation.Resource;
+
+/**
+ * @Description: 考勤统计定时任务
+ * @Author: CaoZixuan
+ * @Date: 2024-05-24
+ */
+public class DingStatisticJob extends QuartzJobBean {
+    @Resource
+    JobService jobService;
+
+    @Override
+    protected void executeInternal(JobExecutionContext context) {
+        try {
+            jobService.autoAddDingRecord();
+        } catch (Exception e) {
+            throw ExceptionResultEnum.ERROR.exception(e.getMessage());
+        }
+    }
+}

+ 5 - 0
sop-task/src/main/java/com/qmth/sop/task/job/service/JobService.java

@@ -55,4 +55,9 @@ public interface JobService {
      * 自动打卡定时任务
      */
     void autoAddDingRecord();
+
+    /**
+     * 考勤统计
+     */
+    void dingStatistic();
 }

+ 8 - 0
sop-task/src/main/java/com/qmth/sop/task/job/service/impl/JobServiceImpl.java

@@ -67,6 +67,9 @@ public class JobServiceImpl implements JobService {
     @Resource
     AsyncRtzfUserUpdateBatchService asyncRtzfUserUpdateBatchService;
 
+    @Resource
+    TBDingStatisticService tbDingStatisticService;
+
     /**
      * 流程任务提醒task
      */
@@ -301,4 +304,9 @@ public class JobServiceImpl implements JobService {
         String signDay = calendar.get(Calendar.MONTH) + 1 + "月" + calendar.get(Calendar.DATE) + "日";
         tbDingService.autoAddDingRecord(signYear, signDay);
     }
+
+    @Override
+    public void dingStatistic() {
+        tbDingStatisticService.buildDingStatistic();
+    }
 }

+ 7 - 0
sop-task/src/main/java/com/qmth/sop/task/start/StartRunning.java

@@ -86,6 +86,13 @@ public class StartRunning implements CommandLineRunner {
         quartzService.addJob(AutoAddDingRecordJob.class, JobEnum.AUTO_ADD_DING_RECORD.name(), JobEnum.AUTO_ADD_DING_RECORD_GROUP.name(), "0 30 23 * * ?", autoAddDingRecordMap);
         log.info("自动打卡定时任务 end");
 
+        log.info("考勤统计定时任务 start");
+        Map<Object,Object> dingStatisticMap = new HashMap<>();
+        dingStatisticMap.put(SystemConstant.NAME, DingStatisticJob.class.getName());
+        quartzService.deleteJob(JobEnum.DING_STATISTIC.name(), JobEnum.DING_STATISTIC_GROUP.name());
+        quartzService.addJob(DingStatisticJob.class, JobEnum.DING_STATISTIC.name(), JobEnum.DING_STATISTIC_GROUP.name(), "0 0 2 * * ?", dingStatisticMap);
+        log.info("考勤统计定时任务 end");
+
         log.info("服务器启动时执行 end");
     }
 }