caozixuan 10 mesi fa
parent
commit
c57a642a5b

+ 29 - 6
sop-api/src/main/java/com/qmth/sop/server/api/TBDingController.java

@@ -4,12 +4,12 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.qmth.boot.api.constant.ApiConstant;
-import com.qmth.sop.business.entity.*;
-import com.qmth.sop.common.annotation.OperationLog;
 import com.qmth.sop.business.bean.params.DingSaveParam;
 import com.qmth.sop.business.bean.result.*;
+import com.qmth.sop.business.entity.*;
 import com.qmth.sop.business.service.*;
 import com.qmth.sop.business.templete.execute.AsyncDingCountExportService;
+import com.qmth.sop.common.annotation.OperationLog;
 import com.qmth.sop.common.contant.SystemConstant;
 import com.qmth.sop.common.enums.*;
 import com.qmth.sop.common.util.Result;
@@ -66,6 +66,9 @@ public class TBDingController {
     @Resource
     TBCrmDetailService tbCrmDetailService;
 
+    @Resource
+    TBUserArchivesService tbUserArchivesService;
+
     @ApiOperation(value = "考勤明细")
     @RequestMapping(value = "/detail", method = RequestMethod.POST)
     @ApiResponses({ @ApiResponse(code = 200, message = "查询成功", response = TBDing.class) })
@@ -194,17 +197,18 @@ public class TBDingController {
     @ApiOperation(value = "考勤打卡信息")
     @RequestMapping(value = "/ding_info", method = RequestMethod.POST)
     @ApiResponses({ @ApiResponse(code = 200, message = "查询成功", response = DingElementResult.class) })
-    public Result findDingInfo(@ApiParam(value = "sop单号", required = true) @RequestParam String sopNo) {
+    public Result findDingInfo(@ApiParam(value = "服务单元id", required = true) @RequestParam Long serviceId,
+            @ApiParam(value = "sop单号") @RequestParam(required = false) String sopNo) {
         SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
-        return ResultUtil.ok(tBDingService.findDingElements(sopNo, requestUser.getId()));
+        return ResultUtil.ok(tBDingService.findDingElements(serviceId, sopNo, requestUser.getId()));
     }
 
     @ApiOperation(value = "考勤结果统计")
     @RequestMapping(value = "/ding_statistic", method = RequestMethod.POST)
     @ApiResponses({ @ApiResponse(code = 200, message = "查询成功", response = DingStatisticResult.class) })
-    public Result findDingStatistic(@ApiParam(value = "sop单号", required = true) @RequestParam String sopNo,
+    public Result findDingStatistic(@ApiParam(value = "服务单元id", required = true) @RequestParam Long serviceId, @ApiParam(value = "sop单号") @RequestParam(required = false) String sopNo,
             @ApiParam(value = "打卡人id", required = true) @RequestParam String userId) {
-        return ResultUtil.ok(tBDingService.findDingStatistic(sopNo, SystemConstant.convertIdToLong(userId)));
+        return ResultUtil.ok(tBDingService.findDingStatistic(serviceId, sopNo, SystemConstant.convertIdToLong(userId)));
     }
 
     @ApiOperation(value = "考勤打卡保存")
@@ -227,6 +231,8 @@ public class TBDingController {
         List<DingSopInfo> resultList = new ArrayList<>();
         SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
         Long requestUserId = requestUser.getId();
+        // 判断是否包含区域协调人身份
+        boolean isCoordinator = tbUserArchivesService.containsRegionCoordinator(requestUserId);
 
         List<TBCrm> tbCrmList = tbCrmService.findAllCrm(requestUserId, null);
         if (CollectionUtils.isNotEmpty(tbCrmList)) {
@@ -241,6 +247,12 @@ public class TBDingController {
                 }
                 cell.setServiceUnitId(serviceUnitId);
                 cell.setServiceUnitName(service.getName());
+
+                if (isCoordinator) {
+                    // 包含区域协调人角色 - 打卡不选择sop
+                    resultList.add(cell);
+                    continue;
+                }
                 List<TBCrm> crmInServiceList = tbCrmList.stream().filter(e -> serviceUnitId.equals(e.getServiceId()))
                         .distinct().collect(Collectors.toList());
                 List<SopInfoResult> sopInfo = new ArrayList<>();
@@ -280,9 +292,14 @@ public class TBDingController {
     @RequestMapping(value = "/ding_find_all_sop", method = RequestMethod.POST)
     @ApiResponses({ @ApiResponse(code = 200, message = "查询成功", response = DingElementResult.class) })
     public Result findDingAllSop() {
+        SysUser requestUser = (SysUser) ServletUtil.getRequestUser();
+        Long requestUserId = requestUser.getId();
+        boolean isCoordinator = tbUserArchivesService.containsRegionCoordinator(requestUserId);
+
         List<DingSopInfo> resultList = new ArrayList<>();
         List<SopInfoResult> list = tbSopInfoService.findFlowByServiceId(null);
         List<Long> serviceUnitIdList = list.stream().map(SopInfoResult::getServiceId).distinct().collect(Collectors.toList());
+
         for (Long serviceUnitId : serviceUnitIdList) {
             DingSopInfo cell = new DingSopInfo();
             TBService service = tbServiceService.getById(serviceUnitId);
@@ -292,6 +309,12 @@ public class TBDingController {
 
             cell.setServiceUnitId(serviceUnitId);
             cell.setServiceUnitName(service.getName());
+            if (isCoordinator) {
+                // 区协打卡不选择sop
+                resultList.add(cell);
+                continue;
+            }
+
             List<SopInfoResult> sopInServiceList = list.stream().filter(e -> serviceUnitId.equals(e.getServiceId()))
                     .distinct().collect(Collectors.toList());
             cell.setSopInfo(sopInServiceList);

+ 36 - 0
sop-business/src/main/java/com/qmth/sop/business/bean/dto/RegionCoordinatorDingTimeDto.java

@@ -0,0 +1,36 @@
+package com.qmth.sop.business.bean.dto;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * @Description: 区协打卡时间段
+ * @Author: CaoZixuan
+ * @Date: 2024-09-04
+ */
+public class RegionCoordinatorDingTimeDto {
+    @ApiModelProperty("开始时间")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long startTime;
+
+    @ApiModelProperty("结束时间")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long endTime;
+
+    public Long getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(Long startTime) {
+        this.startTime = startTime;
+    }
+
+    public Long getEndTime() {
+        return endTime;
+    }
+
+    public void setEndTime(Long endTime) {
+        this.endTime = endTime;
+    }
+}

+ 17 - 2
sop-business/src/main/java/com/qmth/sop/business/bean/params/DingSaveParam.java

@@ -1,5 +1,7 @@
 package com.qmth.sop.business.bean.params;
 
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
 import com.qmth.sop.common.enums.InOutTypeEnum;
 import io.swagger.annotations.ApiModelProperty;
 import org.hibernate.validator.constraints.Range;
@@ -13,9 +15,14 @@ import javax.validation.constraints.NotNull;
  * @Date: 2023-09-05
  */
 public class DingSaveParam {
+
+    @ApiModelProperty("服务单元id")
+    @NotNull(message = "缺少服务单元")
+    @Range(min = 1L, message = "缺少服务单元")
+    @JsonSerialize(using = ToStringSerializer.class)
+    private Long serviceId;
+
     @ApiModelProperty("sop号")
-    @NotNull(message = "缺少sop号")
-    @NotBlank(message = "缺少sop号")
     private String sopNo;
 
     @ApiModelProperty("签到时间")
@@ -45,6 +52,14 @@ public class DingSaveParam {
     @NotBlank(message = "缺少y坐标")
     private String axisY;
 
+    public Long getServiceId() {
+        return serviceId;
+    }
+
+    public void setServiceId(Long serviceId) {
+        this.serviceId = serviceId;
+    }
+
     public String getSopNo() {
         return sopNo;
     }

+ 0 - 1
sop-business/src/main/java/com/qmth/sop/business/bean/result/SysDingGroupResult.java

@@ -6,7 +6,6 @@ import com.qmth.sop.business.entity.SysDingGroup;
 import com.qmth.sop.common.enums.ServiceStatusEnum;
 import io.swagger.annotations.ApiModelProperty;
 
-import javax.validation.constraints.NotEmpty;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.List;

+ 24 - 4
sop-business/src/main/java/com/qmth/sop/business/service/TBDingService.java

@@ -3,6 +3,7 @@ package com.qmth.sop.business.service;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.qmth.sop.business.bean.dto.DateFormDto;
+import com.qmth.sop.business.bean.dto.RegionCoordinatorDingTimeDto;
 import com.qmth.sop.business.bean.params.DingSaveParam;
 import com.qmth.sop.business.bean.result.*;
 import com.qmth.sop.business.entity.SysUser;
@@ -30,20 +31,22 @@ public interface TBDingService extends IService<TBDing> {
     /**
      * 根据sop查询打卡界面元素
      *
-     * @param sopNo  sop编号
-     * @param userId 用户id
+     * @param serviceId 服务单元id
+     * @param sopNo     sop编号
+     * @param userId    用户id
      * @return 打卡元素
      */
-    DingElementResult findDingElements(String sopNo, Long userId);
+    DingElementResult findDingElements(Long serviceId, String sopNo, Long userId);
 
     /**
      * 考勤结果统计
      *
+     * @param serviceId 服务单元id
      * @param sopNo  sop单号
      * @param userId 用户id
      * @return 考勤结果统计
      */
-    DingStatisticResult findDingStatistic(String sopNo, Long userId);
+    DingStatisticResult findDingStatistic(Long serviceId, String sopNo, Long userId);
 
     /**
      * 保存打卡记录
@@ -89,6 +92,15 @@ public interface TBDingService extends IService<TBDing> {
      */
     DingElementResult findDingRule(Long userId, String sopNo);
 
+    /**
+     * 查询考勤组规则(只查询工程师的考勤规则)
+     *
+     * @param userId        用户id
+     * @param serviceUnitId 服务单元id
+     * @return 规则
+     */
+    DingElementResult findDingRule(Long userId, Long serviceUnitId);
+
     /**
      * 查询剩余补卡天数
      *
@@ -123,8 +135,16 @@ public interface TBDingService extends IService<TBDing> {
 
     /**
      * 根据sopNo查询状态
+     *
      * @param sopNo sopNo
      * @return 审批
      */
     TFFlowApprove findFlowApproveBySopNo(String sopNo);
+
+    /**
+     * 获取区协打卡时间段
+     *
+     * @return 区协打卡时间段
+     */
+    RegionCoordinatorDingTimeDto findRegionCoordinatorDingTime();
 }

+ 8 - 0
sop-business/src/main/java/com/qmth/sop/business/service/TBUserArchivesService.java

@@ -135,4 +135,12 @@ public interface TBUserArchivesService extends IService<TBUserArchives> {
     List<ArchivesSourceResult> findArchivesSourceByType(Set<RoleTypeEnum> roleTypes);
 
     List<Map<String, Object>> findTempEmp();
+
+    /**
+     * 查询是否包含区域协调人
+     *
+     * @param userId 用户id
+     * @return true是,false否
+     */
+    boolean containsRegionCoordinator(Long userId);
 }

+ 16 - 2
sop-business/src/main/java/com/qmth/sop/business/service/impl/SysDingObjServiceImpl.java

@@ -1,13 +1,16 @@
 package com.qmth.sop.business.service.impl;
 
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.sop.business.bean.result.SysDingGroupRoleResult;
 import com.qmth.sop.business.entity.SysDingObj;
 import com.qmth.sop.business.mapper.SysDingObjMapper;
 import com.qmth.sop.business.service.SysDingObjService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.qmth.sop.common.contant.SystemConstant;
+import com.qmth.sop.common.enums.SopRoleTypeEnum;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
+import java.util.Objects;
 
 /**
  * <p>
@@ -22,6 +25,17 @@ public class SysDingObjServiceImpl extends ServiceImpl<SysDingObjMapper, SysDing
 
     @Override
     public List<SysDingGroupRoleResult> getList(long id) {
-        return this.baseMapper.getList(id);
+        List<SysDingGroupRoleResult> result = this.baseMapper.getList(id);
+        for (SysDingGroupRoleResult sysDingGroupRoleResult : result) {
+            Long roleId = sysDingGroupRoleResult.getRoleId();
+            if (!SystemConstant.longNotNull(roleId)) {
+                // 打卡类型 名称根据sop_role_type来
+                SopRoleTypeEnum sopRoleType = sysDingGroupRoleResult.getSopRoleType();
+                if (Objects.nonNull(sopRoleType)) {
+                    sysDingGroupRoleResult.setRoleName(sopRoleType.getTitle());
+                }
+            }
+        }
+        return result;
     }
 }

+ 95 - 44
sop-business/src/main/java/com/qmth/sop/business/service/impl/TBDingServiceImpl.java

@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.qmth.sop.business.bean.dto.DataPermissionDto;
 import com.qmth.sop.business.bean.dto.DateFormDto;
+import com.qmth.sop.business.bean.dto.RegionCoordinatorDingTimeDto;
 import com.qmth.sop.business.bean.dto.SopCrmInfo;
 import com.qmth.sop.business.bean.params.DingSaveParam;
 import com.qmth.sop.business.bean.result.*;
@@ -90,18 +91,25 @@ public class TBDingServiceImpl extends ServiceImpl<TBDingMapper, TBDing> impleme
     private TBCrmDetailService tbCrmDetailService;
 
     @Override
-    public DingElementResult findDingElements(String sopNo, Long userId) {
-
-        SopCrmInfo sopCrmInfo = tbCrmService.findSopCrmInfoBySop(sopNo);
-        if (Objects.isNull(sopCrmInfo)) {
-            throw ExceptionResultEnum.ERROR.exception(String.format("未找到sop单号为[%s]的派单信息", sopNo));
+    public DingElementResult findDingElements(Long serviceId, String sopNo, Long userId) {
+        if (SystemConstant.strNotNull(sopNo)) {
+            SopCrmInfo sopCrmInfo = tbCrmService.findSopCrmInfoBySop(sopNo);
+            if (Objects.isNull(sopCrmInfo)) {
+                throw ExceptionResultEnum.ERROR.exception(String.format("未找到sop单号为[%s]的派单信息", sopNo));
+            }
         }
-        DingElementResult dingElementResult = this.findDingRule(userId, sopNo);
+
+        DingElementResult dingElementResult = this.findDingRule(userId, serviceId);
         if (Objects.nonNull(dingElementResult)) {
             Long userArchivesId = dingElementResult.getUserArchivesId();
             String currentDayStr = DateFormatUtils.format(System.currentTimeMillis(), SystemConstant.DEFAULT_DATE_DAY_PATTERN);
-            List<TBDing> tbDingList = this.list(new QueryWrapper<TBDing>().lambda().eq(TBDing::getSopNo, sopNo)
-                    .eq(TBDing::getUserArchivesId, userArchivesId).eq(TBDing::getSignDate, currentDayStr));
+            QueryWrapper<TBDing> queryWrapper = new QueryWrapper<>();
+            queryWrapper.lambda().eq(TBDing::getServiceId, serviceId).eq(TBDing::getUserArchivesId, userArchivesId).eq(TBDing::getSignDate, currentDayStr);
+            if (SystemConstant.strNotNull(sopNo)) {
+                queryWrapper.lambda().eq(TBDing::getSopNo, sopNo);
+            }
+
+            List<TBDing> tbDingList = this.list(queryWrapper);
             if (CollectionUtils.isNotEmpty(tbDingList)) {
                 // 有考勤记录
                 if (tbDingList.size() > 1) {
@@ -124,7 +132,7 @@ public class TBDingServiceImpl extends ServiceImpl<TBDingMapper, TBDing> impleme
     }
 
     @Override
-    public DingStatisticResult findDingStatistic(String sopNo, Long userId) {
+    public DingStatisticResult findDingStatistic(Long serviceId, String sopNo, Long userId) {
         // 截取年分割截止
         final int yearEnd = 4;
         // 截取日分割开始
@@ -138,9 +146,13 @@ public class TBDingServiceImpl extends ServiceImpl<TBDingMapper, TBDing> impleme
         int exceptionCount = 0;
         List<DingFormResult> formList = new ArrayList<>();
         if (CollectionUtils.isNotEmpty(dateFormList)) {
+            QueryWrapper<TBDing> dingQueryWrapper = new QueryWrapper<>();
+            dingQueryWrapper.lambda().eq(TBDing::getServiceId, serviceId).eq(TBDing::getUserId, userId).orderByAsc(TBDing::getId);
+            if (SystemConstant.strNotNull(sopNo)) {
+                dingQueryWrapper.lambda().eq(TBDing::getSopNo, sopNo);
+            }
 
-            List<TBDing> tbDingList = this.list(
-                    new QueryWrapper<TBDing>().lambda().eq(TBDing::getSopNo, sopNo).eq(TBDing::getUserId, userId).orderByAsc(TBDing::getId));
+            List<TBDing> tbDingList = this.list(dingQueryWrapper);
 
             // 签到表
             List<DingFormResult> formDingList = new ArrayList<>();
@@ -158,7 +170,7 @@ public class TBDingServiceImpl extends ServiceImpl<TBDingMapper, TBDing> impleme
                 if (signInTime == null || signInTime == 0) {
                     signInInfo.setStatus(DingStatusEnum.NO_SIGN);
                 } else {
-                    if (sopNo.equals(dingSopNo)) {
+                    if (Objects.equals(sopNo, dingSopNo)) {
                         signInInfo.setStatus(DingStatusEnum.SIGN);
                     } else {
                         signInInfo.setStatus(DingStatusEnum.OTHER);
@@ -179,7 +191,7 @@ public class TBDingServiceImpl extends ServiceImpl<TBDingMapper, TBDing> impleme
                 if (signOutTime == null || signOutTime == 0) {
                     signOutInfo.setStatus(DingStatusEnum.NO_SIGN);
                 } else {
-                    if (sopNo.equals(dingSopNo)) {
+                    if (Objects.equals(sopNo, dingSopNo)) {
                         signOutInfo.setStatus(DingStatusEnum.SIGN);
                     } else {
                         signOutInfo.setStatus(DingStatusEnum.OTHER);
@@ -202,6 +214,7 @@ public class TBDingServiceImpl extends ServiceImpl<TBDingMapper, TBDing> impleme
             String endDate = dateFormDto.getEndDate();
             endDate = endDate.substring(dayStart);
 
+            // TODO: 2024/9/4 更改补卡记录
             // 查询正在补卡中的记录
             List<TBDingApply> resigningList = tbDingApplyService.list(
                     new QueryWrapper<TBDingApply>().lambda().select(TBDingApply::getType, TBDingApply::getApplyTime).eq(TBDingApply::getSopNo, sopNo).eq(TBDingApply::getCreateId, userId)
@@ -288,23 +301,46 @@ public class TBDingServiceImpl extends ServiceImpl<TBDingMapper, TBDing> impleme
 
     @Override
     public void dingSave(DingSaveParam dingSaveParam, Long userId) throws IOException {
+        boolean isCoordinator = tbUserArchivesService.containsRegionCoordinator(userId);
+        Long serviceId = dingSaveParam.getServiceId();
         String sopNo = dingSaveParam.getSopNo();
-        SopCrmInfo sopCrmInfo = tbCrmService.findSopCrmInfoBySop(sopNo);
-        if (Objects.isNull(sopCrmInfo)) {
-            throw ExceptionResultEnum.ERROR.exception(String.format("未找到sop单号为[%s]的派单信息", sopNo));
+        String crmNo = null;
+        Long flowId = null;
+        List<SopRoleTypeEnum> roleType = new ArrayList<>();
+        if (SystemConstant.strNotNull(sopNo)) {
+            SopCrmInfo sopCrmInfo = tbCrmService.findSopCrmInfoBySop(sopNo);
+            if (Objects.isNull(sopCrmInfo)) {
+                throw ExceptionResultEnum.ERROR.exception(String.format("未找到sop单号为[%s]的派单信息", sopNo));
+            }
+            crmNo = sopCrmInfo.getCrmNo();
+            flowId = sopCrmInfo.getFlowId();
+            roleType = tbUserArchivesAllocationService.findSopRoleTypeByUserSopNo(userId, sopNo);
+            if (CollectionUtils.isEmpty(roleType)) {
+                throw ExceptionResultEnum.ERROR.exception("未找到用户在当前sop的身份信息");
+            }
+        } else {
+            if (!isCoordinator) {
+                throw ExceptionResultEnum.ERROR.exception("非区域协调人,必须选择sop");
+            }
+            roleType.add(SopRoleTypeEnum.REGION_COORDINATOR);
         }
 
-        DingElementResult dingElementResult = this.findDingRule(userId, sopNo);
+        DingElementResult dingElementResult = this.findDingRule(userId, serviceId);
         if (Objects.isNull(dingElementResult)) {
             throw ExceptionResultEnum.ERROR.exception("未能获取考勤相关规则");
         }
 
         Long signTime = dingSaveParam.getSignTime();
-        TBCrmDetail tbCrmDetail = tbCrmDetailService.findBySopNo(sopNo);
-        Long scanStartTime = tbCrmDetail.getScanStartTime();
-        Long scanEndTime = tbCrmDetail.getScanEndTime();
-        Long markPaperStartTime = tbCrmDetail.getMarkPaperStartTime();
-        Long markPaperEndTime = tbCrmDetail.getMarkPaperEndTime();
+        if (isCoordinator) {
+            RegionCoordinatorDingTimeDto dingTimeDto = this.findRegionCoordinatorDingTime();
+            Long startTime = dingTimeDto.getStartTime();
+            Long endTime = dingTimeDto.getEndTime();
+            if (signTime < startTime || signTime > endTime) {
+                throw ExceptionResultEnum.ERROR.exception(
+                        String.format("区域协调人请在%s - %s打卡", DateFormatUtils.format(startTime, "yyyy/MM/dd"),
+                                DateFormatUtils.format(endTime, "yyyy/MM/dd")));
+            }
+        }
 
         DingDateTypeEnum dateType = sysDingDateService.getDingDateType(DateDisposeUtils.timestampToLocalDate(signTime));
 
@@ -345,13 +381,6 @@ public class TBDingServiceImpl extends ServiceImpl<TBDingMapper, TBDing> impleme
             facePass = score.compareTo(limit) > -1;
         }
 
-        String crmNo = sopCrmInfo.getCrmNo();
-        Long serviceId = sopCrmInfo.getServiceUnitId();
-        Long flowId = sopCrmInfo.getFlowId();
-        List<SopRoleTypeEnum> roleType = tbUserArchivesAllocationService.findSopRoleTypeByUserSopNo(userId, sopNo);
-        if (CollectionUtils.isEmpty(roleType)) {
-            throw ExceptionResultEnum.ERROR.exception("未找到用户在当前sop的身份信息");
-        }
         String signDate = DateFormatUtils.format(signTime, SystemConstant.DEFAULT_DATE_DAY_PATTERN);
         String signYear = DateFormatUtils.format(signTime, SystemConstant.DEFAULT_DATE_YEAR_PATTERN);
         String currentDayStr = DateFormatUtils.format(System.currentTimeMillis(), SystemConstant.DEFAULT_DATE_DAY_PATTERN);
@@ -362,7 +391,13 @@ public class TBDingServiceImpl extends ServiceImpl<TBDingMapper, TBDing> impleme
         List<TBDing> todayDingList = this.list(
                 new QueryWrapper<TBDing>().lambda().eq(TBDing::getUserId, userId).eq(TBDing::getSignYear, signYear).eq(TBDing::getSignDate, signDate));
         // 该用户在其他sop的当天打卡记录
-        List<TBDing> otherSopDingList = todayDingList.stream().filter(e -> !e.getSopNo().equals(sopNo)).collect(Collectors.toList());
+        List<TBDing> otherSopDingList;
+        if (isCoordinator) {
+            otherSopDingList = todayDingList.stream().filter(e -> !e.getServiceId().equals(serviceId)).collect(Collectors.toList());
+        } else {
+            otherSopDingList = todayDingList.stream().filter(e -> !e.getSopNo().equals(sopNo)).collect(Collectors.toList());
+        }
+
         if (CollectionUtils.isNotEmpty(otherSopDingList)) {
             List<TBDing> unFinishDingList = otherSopDingList.stream()
                     .filter(e -> !SystemConstant.longNotNull(e.getSignInTime()) || !SystemConstant.longNotNull(e.getSignOutTime())).collect(Collectors.toList());
@@ -392,8 +427,12 @@ public class TBDingServiceImpl extends ServiceImpl<TBDingMapper, TBDing> impleme
             log.error("人脸识别不通过,score :" + score);
             throw ExceptionResultEnum.ERROR.exception("人脸识别不通过!");
         }
-
-        List<TBDing> tbDingList = todayDingList.stream().filter(e -> e.getSopNo().equals(sopNo)).collect(Collectors.toList());
+        List<TBDing> tbDingList;
+        if (isCoordinator) {
+            tbDingList = todayDingList.stream().filter(e -> e.getServiceId().equals(serviceId)).collect(Collectors.toList());
+        } else {
+            tbDingList = todayDingList.stream().filter(e -> e.getSopNo().equals(sopNo)).collect(Collectors.toList());
+        }
         if (CollectionUtils.isEmpty(tbDingList)) {
             // 没有这天的打卡记录 - 新增打卡记录
             TBDing tbDing = new TBDing();
@@ -447,16 +486,6 @@ public class TBDingServiceImpl extends ServiceImpl<TBDingMapper, TBDing> impleme
                 tbDing.setFaceOutPass(facePass);
                 break;
             }
-            Long signInTime = tbDing.getSignInTime();
-            Long signOutTime = tbDing.getSignOutTime();
-            if (signInTime != null && signInTime > 0 && signOutTime != null && signOutTime > 0) {
-                // 打卡异常 (两个打卡时间均不在时间点 -> 异常)
-                boolean signInException = !((scanStartTime <= signInTime && signInTime <= scanEndTime) || (
-                        markPaperStartTime <= signInTime && signInTime <= markPaperEndTime));
-                boolean signOutException = !((scanStartTime <= signOutTime && signOutTime <= scanEndTime) || (
-                        markPaperStartTime <= signOutTime && signOutTime <= markPaperEndTime));
-                tbDing.setDingException(signInException && signOutException);
-            }
             this.updateById(tbDing);
         }
     }
@@ -566,11 +595,11 @@ public class TBDingServiceImpl extends ServiceImpl<TBDingMapper, TBDing> impleme
     public DateFormDto buildSignDateFormBySop(String sopNo) {
         DateFormDto result = new DateFormDto();
         List<String> dateList = new ArrayList<>();
+        long currentTime = System.currentTimeMillis();
         if (sopNo != null && sopNo.length() > 0) {
             TFFlowApprove tfFlowApprove = this.findFlowApproveBySopNo(sopNo);
             FlowStatusEnum flowStatusEnum = tfFlowApprove.getStatus();
             Long updateTime = tfFlowApprove.getUpdateTime();
-            Long currentTime = System.currentTimeMillis();
 
             TBCrmDetail tbCrmDetail = tbCrmDetailService.findBySopNo(sopNo);
             if (Objects.isNull(tbCrmDetail)) {
@@ -587,7 +616,16 @@ public class TBDingServiceImpl extends ServiceImpl<TBDingMapper, TBDing> impleme
             }
             dateList.sort(Collections.reverseOrder());
             result.setDateFormList(dateList);
-
+        } else {
+            // 区协固定打卡时间
+            RegionCoordinatorDingTimeDto dingTimeDto = this.findRegionCoordinatorDingTime();
+            Long startTime = dingTimeDto.getStartTime();
+            if (currentTime < startTime) {
+                return result;
+            }
+            Long endTime = dingTimeDto.getEndTime();
+            result.setDateFormList(DateDisposeUtils.getDaysBetween(startTime, Math.min(currentTime, endTime),
+                    SystemConstant.DEFAULT_DATE_YMD_S_PATTERN));
         }
         if (CollectionUtils.isNotEmpty(dateList)) {
             result.setEndDate(dateList.get(0));
@@ -599,7 +637,11 @@ public class TBDingServiceImpl extends ServiceImpl<TBDingMapper, TBDing> impleme
     public DingElementResult findDingRule(Long userId, String sopNo) {
         SopCrmInfo sopCrmInfo = tbCrmService.findSopCrmInfoBySop(sopNo);
         Long serviceUnitId = sopCrmInfo.getServiceUnitId();
+        return this.findDingRule(userId, serviceUnitId);
+    }
 
+    @Override
+    public DingElementResult findDingRule(Long userId, Long serviceUnitId) {
         List<DingElementResult> dingElementResultList = this.baseMapper.findDingResultByUserId(userId, serviceUnitId);
         List<Long> dingGroupIds = dingElementResultList.stream().map(DingElementResult::getDingGroupId).distinct().collect(Collectors.toList());
 
@@ -756,4 +798,13 @@ public class TBDingServiceImpl extends ServiceImpl<TBDingMapper, TBDing> impleme
         }
         return tfFlowApproves.get(0);
     }
+
+    @Override
+    public RegionCoordinatorDingTimeDto findRegionCoordinatorDingTime() {
+        SysConfig sysConfig = sysConfigService.findByConfigKey(SystemConstant.REGION_COORDINATOR_DING_TIME);
+        if (Objects.isNull(sysConfig)) {
+            throw ExceptionResultEnum.ERROR.exception("缺少区域协调人打卡时间段");
+        }
+        return JSON.parseObject(sysConfig.getConfigValue(), RegionCoordinatorDingTimeDto.class);
+    }
 }

+ 8 - 26
sop-business/src/main/java/com/qmth/sop/business/service/impl/TBUserArchivesAllocationServiceImpl.java

@@ -533,23 +533,13 @@ public class TBUserArchivesAllocationServiceImpl
         switch (sopRoleTypeEnum) {
         case ENGINEER:
         case PROJECT_MANAGER:
-            switch (productTypeEnum) {
-            case OFFICE:
-                datasource = tbUserArchivesService.list().stream().map(TBUserArchives::getId).distinct()
-                        .collect(Collectors.toList());
-                break;
-            case CLOUD_MARK:
-                datasource = tbUserArchivesService.findArchivesSourceByType(
-                                new HashSet<>(Arrays.asList(RoleTypeEnum.EFFECT_ENGINEER, RoleTypeEnum.ASSISTANT_ENGINEER)))
-                        .stream().map(ArchivesSourceResult::getArchivesId).distinct().collect(Collectors.toList());
-                break;
-            default:
-                break;
-            }
+            datasource = tbUserArchivesService.findArchivesSourceByType(
+                            new HashSet<>(Arrays.asList(RoleTypeEnum.EFFECT_ENGINEER, RoleTypeEnum.ASSISTANT_ENGINEER)))
+                    .stream().map(ArchivesSourceResult::getArchivesId).distinct().collect(Collectors.toList());
             break;
         case REGION_COORDINATOR:
             datasource = tbUserArchivesService.findArchivesSourceByType(
-                            new HashSet<>(Arrays.asList(RoleTypeEnum.REGION_COORDINATOR))).stream()
+                            new HashSet<>(Collections.singletonList(RoleTypeEnum.REGION_COORDINATOR))).stream()
                     .map(ArchivesSourceResult::getArchivesId).distinct().collect(Collectors.toList());
             break;
         }
@@ -597,21 +587,13 @@ public class TBUserArchivesAllocationServiceImpl
             switch (sopRoleTypeCompositeEnum) {
             case ENGINEER:
             case PROJECT_MANAGER:
-                switch (productTypeEnum) {
-                case OFFICE:
-                    datasource = tbUserArchivesService.list().stream().map(TBUserArchives::getId).distinct()
-                            .collect(Collectors.toList());
-                    break;
-                case CLOUD_MARK:
-                    datasource = tbUserArchivesService.findArchivesSourceByType(
-                                    new HashSet<>(Arrays.asList(RoleTypeEnum.EFFECT_ENGINEER, RoleTypeEnum.ASSISTANT_ENGINEER)))
-                            .stream().map(ArchivesSourceResult::getArchivesId).distinct().collect(Collectors.toList());
-                    break;
-                }
+                datasource = tbUserArchivesService.findArchivesSourceByType(
+                                new HashSet<>(Arrays.asList(RoleTypeEnum.EFFECT_ENGINEER, RoleTypeEnum.ASSISTANT_ENGINEER)))
+                        .stream().map(ArchivesSourceResult::getArchivesId).distinct().collect(Collectors.toList());
                 break;
             case REGION_COORDINATOR:
                 datasource = tbUserArchivesService.findArchivesSourceByType(
-                                new HashSet<>(Arrays.asList(RoleTypeEnum.REGION_COORDINATOR))).stream()
+                                new HashSet<>(Collections.singletonList(RoleTypeEnum.REGION_COORDINATOR))).stream()
                         .map(ArchivesSourceResult::getArchivesId).distinct().collect(Collectors.toList());
                 break;
             }

+ 9 - 0
sop-business/src/main/java/com/qmth/sop/business/service/impl/TBUserArchivesServiceImpl.java

@@ -615,4 +615,13 @@ public class TBUserArchivesServiceImpl extends ServiceImpl<TBUserArchivesMapper,
     public List<Map<String, Object>> findTempEmp() {
         return this.baseMapper.findTempEmp();
     }
+
+    @Override
+    public boolean containsRegionCoordinator(Long userId) {
+        UserArchivesResult userArchivesResult = tbUserArchivesService.findUserArchivesByArchivesIdORUserId(null,
+                userId);
+        List<RoleResult> roleInfoList = userArchivesResult.getRoleInfoList();
+        // 判断是否包含区域协调人身份
+        return roleInfoList.stream().anyMatch(e -> RoleTypeEnum.REGION_COORDINATOR.name().equals(e.getRoleType()));
+    }
 }

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

@@ -175,3 +175,10 @@ ALTER TABLE t_b_ding_submit
     ADD COLUMN user_id BIGINT NOT NULL COMMENT '人员id' AFTER crm_no,
     DROP INDEX t_b_ding_submit_un ,
     ADD UNIQUE INDEX t_b_ding_submit_un USING BTREE (sop_no, user_id);
+
+-- 2024-09-04
+ALTER TABLE t_b_ding
+    CHANGE COLUMN sop_no sop_no VARCHAR(100) CHARACTER SET 'utf8mb4' NULL COMMENT 'sop单号' ,
+    CHANGE COLUMN ding_sop_no ding_sop_no VARCHAR(100) CHARACTER SET 'utf8mb4' NULL COMMENT '实际打卡对应的sop单号' ;
+
+INSERT INTO sys_config (id, config_key, config_name, config_value, enable, sort, create_id) VALUES ('41', 'region.coordinator.ding.time', '区域协调人打卡时间段', '{\"startTime\": 1725292800000,\"endTime\": 1725897600000}', '1', '1', '1');

+ 1 - 1
sop-business/src/main/resources/mapper/SysDingObjMapper.xml

@@ -2,7 +2,7 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.qmth.sop.business.mapper.SysDingObjMapper">
     <select id="getList" resultType="com.qmth.sop.business.bean.result.SysDingGroupRoleResult">
-        select a.*,ifnull(r.name,'工程师') role_name from sys_ding_obj a
+        select a.*,r.name AS role_name from sys_ding_obj a
         left join sys_role r on r.id=a.role_id
         <where>
             <if test="id != null and id != ''">

+ 2 - 2
sop-business/src/main/resources/mapper/TBSopInfoMapper.xml

@@ -252,7 +252,7 @@
             <if test="userId != null and userId != ''">
                 and tbuaa.user_id = #{userId}
             </if>
-            and tbuaa.sop_role_type in ('ENGINEER','PROJECT_MANAGER')
+            and tbuaa.sop_role_type in ('ENGINEER','PROJECT_MANAGER','REGION_COORDINATOR')
             and tffa.status not in('END')
         </where>
         union
@@ -286,7 +286,7 @@
             <if test="userId != null and userId != ''">
                 and tbuaa.user_id = #{userId}
             </if>
-            and tbuaa.sop_role_type in ('ENGINEER','PROJECT_MANAGER')
+            and tbuaa.sop_role_type in ('ENGINEER','PROJECT_MANAGER','REGION_COORDINATOR')
             and tffa.status not in('END')
             and tbuaal.crm_detail_id = tbuaa.crm_detail_id
         </where>

+ 1 - 0
sop-common/src/main/java/com/qmth/sop/common/contant/SystemConstant.java

@@ -224,6 +224,7 @@ public class SystemConstant {
     public static final String FXXK_CUSTOM_QUERY_URL = "fxxk.custom.query.url";
     public static final String FXXK_USER_QUERY_URL = "fxxk.user.query.url";
     public static final String RTZF_OSS_LOGIN_URL = "rtzf.oss.login.url";
+    public static final String REGION_COORDINATOR_DING_TIME = "region.coordinator.ding.time";
 
     /**
      * api前缀

+ 1 - 2
sop-common/src/main/java/com/qmth/sop/common/enums/SopRoleTypeEnum.java

@@ -6,8 +6,7 @@ package com.qmth.sop.common.enums;
  * @Date: 2024-05-14
  */
 public enum SopRoleTypeEnum {
-    REGION_COORDINATOR("区域协调人", new RoleTypeEnum[] { RoleTypeEnum.REGION_MANAGER, RoleTypeEnum.REGION_COORDINATOR,
-            RoleTypeEnum.EFFECT_ENGINEER, RoleTypeEnum.ASSISTANT_ENGINEER }),
+    REGION_COORDINATOR("区域协调人", new RoleTypeEnum[] {RoleTypeEnum.REGION_COORDINATOR}),
     PROJECT_MANAGER("项目经理", new RoleTypeEnum[] { RoleTypeEnum.REGION_MANAGER, RoleTypeEnum.REGION_COORDINATOR,
             RoleTypeEnum.EFFECT_ENGINEER, RoleTypeEnum.ASSISTANT_ENGINEER }),
     ENGINEER("工程师", new RoleTypeEnum[] { RoleTypeEnum.REGION_MANAGER, RoleTypeEnum.REGION_COORDINATOR,