فهرست منبع

工作报告bug修复

fuyuchuan 8 ماه پیش
والد
کامیت
c357e799cc

+ 1 - 1
service-iot/service-iot-api/src/main/java/com/usky/iot/factory/RemotePmFactory.java

@@ -26,7 +26,7 @@ public class RemotePmFactory implements FallbackFactory<RemotePmService>
         {
             @Override
             public void executeTimedSending() {
-                throw new FeignBadRequestException(500,"公告报告定时发送异常"+throwable.getMessage());
+                throw new FeignBadRequestException(500,"工作报告定时发送异常"+throwable.getMessage());
             }
 
         };

+ 2 - 0
service-iot/service-iot-biz/src/main/java/com/usky/iot/controller/api/PmTimedSendingApi.java

@@ -12,6 +12,7 @@ import java.time.LocalDateTime;
  *  数据统一查询 前端控制器
  * </p>
  *
+ * @author f
  */
 @RestController
 public class PmTimedSendingApi implements RemotePmService {
@@ -24,4 +25,5 @@ public class PmTimedSendingApi implements RemotePmService {
         LocalDateTime now = LocalDateTime.now();
         pmWorkReportService.timedSending(now);
     }
+
 }

+ 11 - 2
service-iot/service-iot-biz/src/main/java/com/usky/iot/controller/web/PmWorkContentController.java

@@ -47,7 +47,16 @@ public class PmWorkContentController {
         return ApiResult.success(pmWorkContentService.projectQuery(startDate, endDate, projectName, projectAscription, reportId));
     }
 
-
+    /**
+     * 报告记录
+     *
+     * @param startDate
+     * @param endDate
+     * @param projectName
+     * @param reportId
+     * @param projectAscription
+     * @return
+     */
     @GetMapping("/reportRecord")
     public ApiResult<List<PmWorkReport>> reportRecord(@RequestParam(value = "startDate", required = false) String startDate,
                                                       @RequestParam(value = "endDate", required = false) String endDate,
@@ -62,7 +71,7 @@ public class PmWorkContentController {
     }
 
     /**
-     * APP报告详情分页列表
+     * 报告详情分页列表
      *
      * @param projectAscription 1:我负责;2:我收到;3:我发出
      * @param pageNum           页数

+ 0 - 4
service-iot/service-iot-biz/src/main/java/com/usky/iot/controller/web/PmWorkReportController.java

@@ -4,7 +4,6 @@ package com.usky.iot.controller.web;
 import com.aliyuncs.exceptions.ClientException;
 import com.usky.common.core.bean.ApiResult;
 import com.usky.iot.domain.PmWorkReport;
-import com.usky.iot.service.PmProjectService;
 import com.usky.iot.service.PmWorkReportService;
 import com.usky.iot.service.vo.PmProjectTotalWorkTimeVo;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -28,9 +27,6 @@ public class PmWorkReportController {
     @Autowired
     private PmWorkReportService pmWorkReportService;
 
-    @Autowired
-    private PmProjectService pmProjectService;
-
     /**
      * 周工作报告查询
      *

+ 23 - 8
service-iot/service-iot-biz/src/main/java/com/usky/iot/domain/PmWorkReport.java

@@ -1,20 +1,19 @@
 package com.usky.iot.domain;
 
-import java.math.BigDecimal;
-
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.usky.iot.service.vo.PmReportReadersVO;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
 
+import java.io.Serializable;
+import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
-import java.io.Serializable;
 import java.util.List;
 
-import com.fasterxml.jackson.annotation.JsonFormat;
-import lombok.*;
-import org.springframework.data.annotation.Transient;
-
 /**
  * <p>
  * 工作报告表
@@ -48,6 +47,7 @@ public class PmWorkReport implements Serializable {
     /**
      * 提交时间
      */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime submitDate;
 
     /**
@@ -78,6 +78,7 @@ public class PmWorkReport implements Serializable {
     /**
      * 创建时间
      */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
     /**
@@ -88,6 +89,7 @@ public class PmWorkReport implements Serializable {
     /**
      * 更新时间
      */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime updateTime;
 
     /**
@@ -120,7 +122,7 @@ public class PmWorkReport implements Serializable {
     /**
      * 定时时间
      */
-    //@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime timingTime;
 
     /**
@@ -132,4 +134,17 @@ public class PmWorkReport implements Serializable {
      * 是否定时(默认0:否,1:是)
      */
     private Integer isRegularlySend;
+
+    /**
+     * 已读,未读人员
+     */
+    @TableField(exist = false)
+    private PmReportReadersVO pmReportReaders;
+
+    /**
+     * 头像
+     */
+    @TableField(exist = false)
+    private String avatar;
+
 }

+ 1 - 0
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/PmWorkReportService.java

@@ -46,4 +46,5 @@ public interface PmWorkReportService extends CrudService<PmWorkReport> {
      * 定时发送
      */
     void timedSending(LocalDateTime time);
+
 }

+ 3 - 0
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/impl/PmProjectServiceImpl.java

@@ -312,4 +312,7 @@ public class PmProjectServiceImpl extends AbstractCrudService<PmProjectMapper, P
         pmProjectMapper.updateById(project);
     }
 
+
+
+
 }

+ 104 - 36
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/impl/PmWorkContentServiceImpl.java

@@ -15,10 +15,7 @@ import com.usky.iot.domain.PmWorkReport;
 import com.usky.iot.mapper.*;
 import com.usky.iot.service.PmProjectService;
 import com.usky.iot.service.PmWorkContentService;
-import com.usky.iot.service.vo.ProjectWorkTimeVO;
-import com.usky.iot.service.vo.UserWorkTimeVO;
-import com.usky.iot.service.vo.WorkHoursStatisticsVO;
-import com.usky.iot.service.vo.WorkTimeExportVO;
+import com.usky.iot.service.vo.*;
 import com.usky.system.domain.SysUser;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -120,7 +117,7 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
         }
         return rIds;
     }
-    
+
     /**
      * @description: 负责人项目id查询
      * @author: fu
@@ -171,12 +168,12 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
         List<Integer> receiveList = receive();
         List<Integer> sentOutList = sentOut();
         List<Integer> headProjects = head();
-        //LocalDate start = LocalDate.parse(startDate);
-        //LocalDate end = LocalDate.parse(endDate);
-        //String subQueryReports = "SELECT id FROM pm_work_report WHERE report_date BETWEEN '" + start + "' AND '" + end + "' AND tenant_id = " + SecurityUtils.getTenantId();
-        //String subQueryReport = "SELECT id FROM pm_work_report WHERE FIND_IN_SET('" + SecurityUtils.getUserId() + "', cc_to) > 0 AND tenant_id = " + SecurityUtils.getTenantId();
-        //String sentOut = "SELECT id FROM pm_work_report WHERE create_by = '" + SecurityUtils.getUsername() + "' AND tenant_id = " + SecurityUtils.getTenantId();
-        //String subQueryProjects = "SELECT id FROM pm_project WHERE project_head = '" + SecurityUtils.getUserId() + "' AND tenant_id = " + SecurityUtils.getTenantId();
+        // LocalDate start = LocalDate.parse(startDate);
+        // LocalDate end = LocalDate.parse(endDate);
+        // String subQueryReports = "SELECT id FROM pm_work_report WHERE report_date BETWEEN '" + start + "' AND '" + end + "' AND tenant_id = " + SecurityUtils.getTenantId();
+        // String subQueryReport = "SELECT id FROM pm_work_report WHERE FIND_IN_SET('" + SecurityUtils.getUserId() + "', cc_to) > 0 AND tenant_id = " + SecurityUtils.getTenantId();
+        // String sentOut = "SELECT id FROM pm_work_report WHERE create_by = '" + SecurityUtils.getUsername() + "' AND tenant_id = " + SecurityUtils.getTenantId();
+        // String subQueryProjects = "SELECT id FROM pm_project WHERE project_head = '" + SecurityUtils.getUserId() + "' AND tenant_id = " + SecurityUtils.getTenantId();
         LambdaQueryWrapper<PmWorkContent> contentLambdaQuery = Wrappers.lambdaQuery();
         contentLambdaQuery.select(PmWorkContent::getProjectId, PmWorkContent::getProjectName);
         if (!reportIds.isEmpty()) {
@@ -191,15 +188,15 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
                 return new ArrayList<PmWorkContent>();
             }
             contentLambdaQuery.in(PmWorkContent::getProjectId, headProjects);
-            //contentLambdaQuery.inSql(PmWorkContent::getProjectId, subQueryProjects);
+            // contentLambdaQuery.inSql(PmWorkContent::getProjectId, subQueryProjects);
         } else if (projectAscription == 2) {
-            //contentLambdaQuery.inSql(PmWorkContent::getReportId, subQueryReport);
+            // contentLambdaQuery.inSql(PmWorkContent::getReportId, subQueryReport);
             if (receiveList.isEmpty()) {
                 return new ArrayList<PmWorkContent>();
             }
             contentLambdaQuery.in(PmWorkContent::getReportId, receiveList);
         } else if (projectAscription == 3) {
-            //contentLambdaQuery.in(PmWorkContent::getReportId, sentOutList);
+            // contentLambdaQuery.in(PmWorkContent::getReportId, sentOutList);
             if (sentOutList.isEmpty()) {
                 return new ArrayList<PmWorkContent>();
             }
@@ -218,7 +215,7 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
         if (reportId != null && reportId != 0) {
             LambdaQueryWrapper<PmWorkReport> reportQuery = Wrappers.lambdaQuery();
             reportQuery.select(PmWorkReport::getId, PmWorkReport::getCoordinateWork, PmWorkReport::getTomorrowPlan, PmWorkReport::getCcTo, PmWorkReport::getSubmitterId,
-                    PmWorkReport::getCreateTime, PmWorkReport::getReportDate)
+                            PmWorkReport::getCreateTime, PmWorkReport::getReportDate)
                     .eq(PmWorkReport::getId, reportId);
             PmWorkReport report = pmWorkReportMapper.selectOne(reportQuery);
             LambdaQueryWrapper<PmWorkContent> contentQuery = Wrappers.lambdaQuery();
@@ -234,11 +231,11 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
             List<Integer> receiveList2 = receive();
             List<Integer> sentOutList = sentOut();
             List<Integer> headProjects = head();
-            //String subQueryReports = "SELECT id FROM pm_work_report WHERE report_date BETWEEN '" + start + "' AND '" + end + "' AND tenant_id = " + SecurityUtils.getTenantId();
-            //String subQueryReport = "SELECT id FROM pm_work_report WHERE FIND_IN_SET('" + SecurityUtils.getUserId() + "', cc_to) > 0 AND tenant_id = " + SecurityUtils.getTenantId();
-            //String subQueryProjects = "SELECT id FROM pm_project WHERE project_head = '" + SecurityUtils.getUserId() + "' AND tenant_id = " + SecurityUtils.getTenantId();
-            //String sentOut = "SELECT id FROM pm_work_report WHERE create_by = '" + SecurityUtils.getUsername() + "' AND tenant_id = " + SecurityUtils.getTenantId();
-            //String reportIdList = "SELECT report_id FROM pm_work_content WHERE project_name = '" + projectName + "' AND tenant_id = " + SecurityUtils.getTenantId();
+            // String subQueryReports = "SELECT id FROM pm_work_report WHERE report_date BETWEEN '" + start + "' AND '" + end + "' AND tenant_id = " + SecurityUtils.getTenantId();
+            // String subQueryReport = "SELECT id FROM pm_work_report WHERE FIND_IN_SET('" + SecurityUtils.getUserId() + "', cc_to) > 0 AND tenant_id = " + SecurityUtils.getTenantId();
+            // String subQueryProjects = "SELECT id FROM pm_project WHERE project_head = '" + SecurityUtils.getUserId() + "' AND tenant_id = " + SecurityUtils.getTenantId();
+            // String sentOut = "SELECT id FROM pm_work_report WHERE create_by = '" + SecurityUtils.getUsername() + "' AND tenant_id = " + SecurityUtils.getTenantId();
+            // String reportIdList = "SELECT report_id FROM pm_work_content WHERE project_name = '" + projectName + "' AND tenant_id = " + SecurityUtils.getTenantId();
             LambdaQueryWrapper<PmWorkContent> contentLambdaQuery = Wrappers.lambdaQuery();
             contentLambdaQuery.select(PmWorkContent::getReportId, PmWorkContent::getWorkContent, PmWorkContent::getWorkTime, PmWorkContent::getProjectName);
             if (StringUtils.isNotBlank(startDate) && StringUtils.isNotBlank(endDate)) {
@@ -253,10 +250,10 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
                 //.inSql(PmWorkContent::getReportId, subQueryReports);
                 contentLambdaQuery.in(PmWorkContent::getProjectId, headProjects);
             } else if (projectAscription == 2) {
-                //contentLambdaQuery.inSql(PmWorkContent::getReportId, subQueryReport);
+                // contentLambdaQuery.inSql(PmWorkContent::getReportId, subQueryReport);
                 contentLambdaQuery.in(PmWorkContent::getReportId, receiveList2);
             } else if (projectAscription == 3) {
-                //contentLambdaQuery.inSql(PmWorkContent::getReportId, sentOut);
+                // contentLambdaQuery.inSql(PmWorkContent::getReportId, sentOut);
                 contentLambdaQuery.in(PmWorkContent::getReportId, sentOutList);
             }
 //            if (StringUtils.isNotBlank(projectName)) {
@@ -276,7 +273,7 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
             }
             LambdaQueryWrapper<PmWorkReport> reportQuery = Wrappers.lambdaQuery();
             reportQuery.select(PmWorkReport::getId, PmWorkReport::getCoordinateWork, PmWorkReport::getTomorrowPlan, PmWorkReport::getCcTo, PmWorkReport::getSubmitterId,
-                    PmWorkReport::getCreateTime, PmWorkReport::getReportDate)
+                            PmWorkReport::getCreateTime, PmWorkReport::getReportDate)
                     .in(PmWorkReport::getId, reportIds)
                     .orderByDesc(PmWorkReport::getCreateTime);
             reportList = pmWorkReportMapper.selectList(reportQuery);
@@ -353,7 +350,8 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
     @Override
     public List<SysUser> nickNames(List<Long> userIds) {
         LambdaQueryWrapper<SysUser> usersQuery = Wrappers.lambdaQuery();
-        usersQuery.select(SysUser::getUserId, SysUser::getNickName, SysUser::getUserName)
+        usersQuery.select(SysUser::getUserId, SysUser::getNickName, SysUser::getUserName, SysUser::getPhonenumber, SysUser::getAvatar,
+                        SysUser::getSex, SysUser::getDeptId)
                 .eq(SysUser::getTenantId, SecurityUtils.getTenantId())
                 .eq(SysUser::getDelFlag, 0)
                 .in(SysUser::getUserId, userIds);
@@ -377,11 +375,11 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
         String userName = SecurityUtils.getUsername();
         Long deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId();
         List<Integer> headProjects = head();
-        if (projectAscription == 1 && headProjects.isEmpty()){
+        if (projectAscription == 1 && headProjects.isEmpty()) {
             return returnPage;
         }
         List<Integer> receiveList2 = receive();
-        if (projectAscription == 2 && receiveList2.isEmpty()){
+        if (projectAscription == 2 && receiveList2.isEmpty()) {
             return returnPage;
         }
         List<Long> userIds = new ArrayList<>();
@@ -430,7 +428,7 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
                     .orderByDesc(PmWorkReport::getCreateTime);
         }
         IPage<PmWorkReport> reportPage = pmWorkReportMapper.selectPage(new Page<>(pageNum, pageSize), reportQuery);
-        if (reportPage.getRecords() == null || reportPage.getRecords().isEmpty()){
+        if (reportPage.getRecords() == null || reportPage.getRecords().isEmpty()) {
             return returnPage;
         }
         List<PmWorkReport> reportList = reportPage.getRecords();
@@ -465,13 +463,81 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
             reportList.forEach(report -> {
                 report.setCreateBy(userNicknameMap.get(report.getSubmitterId()));
             });
-        }else {
+        }
+
+        // 已读未读查询
+        List<Integer> reportIdList = new ArrayList<>(reportIds);
+        List<PmReceive> receives = receives(reportIdList);
+
+        List<Long> uId = new ArrayList<>();
+        for (PmReceive pmReceive : receives) {
+            Long receiverId = pmReceive.getReceiverId();
+            uId.add(receiverId);
+        }
 
+        List<Long> userIdList = new ArrayList<>();
+        for (PmWorkReport report : reportList) {
+            userIdList.add(report.getSubmitterId());
+        }
+        List<SysUser> sysUsers = nickNames(userIdList);
+
+        Map<Integer, List<PmReceive>> reportReceivesMap = receives.stream()
+                .collect(Collectors.groupingBy(PmReceive::getReportId));
+
+        if (sysUsers != null) {
+            for (PmWorkReport report : reportList) {
+                List<Long> readAlready = new ArrayList<>();
+                List<Long> readNotAlready = new ArrayList<>();
+                int readCount = 0;
+                int unreadCount = 0;
+                List<PmReceive> reportReceives = reportReceivesMap.getOrDefault(report.getId(), Collections.emptyList());
+                for (PmReceive pmReceive : reportReceives) {
+                    if (pmReceive.getReadFlag() == 1) {
+                        readCount++;
+                        readAlready.add(pmReceive.getReceiverId());
+                    } else {
+                        unreadCount++;
+                        readNotAlready.add(pmReceive.getReceiverId());
+                    }
+                }
+
+                PmReportReadersVO readUnreadVO = new PmReportReadersVO(readAlready, readNotAlready, readCount, unreadCount);
+                report.setPmReportReaders(readUnreadVO);
+
+                // 头像
+                for (SysUser sysUser : sysUsers) {
+                    if (sysUser.getUserId().equals(report.getSubmitterId())) {
+                        report.setAvatar(sysUser.getAvatar());
+                        break;
+                    }
+                }
+            }
         }
 
         return new CommonPage<>(reportList, reportPage.getTotal(), pageSize, pageNum);
     }
 
+    /**
+     * @description: 获取报告接收人
+     * @author: fu
+     * @date: 2024/8/8 19:22
+     * @param: [report]
+     * @return: java.util.List<com.usky.iot.domain.PmReceive>
+     **/
+    private List<PmReceive> receives(List<Integer> reports) {
+        LambdaQueryWrapper<PmReceive> queryWrapper = Wrappers.lambdaQuery();
+        queryWrapper.select(PmReceive::getReportId, PmReceive::getReadFlag, PmReceive::getReceiverId)
+                .in(PmReceive::getReportId, reports);
+        return pmReceiveMapper.selectList(queryWrapper);
+    }
+
+    /**
+     * @description: 获取报告列表
+     * @author: fu
+     * @date: 2024/8/8 19:22
+     * @param: [startDate, endDate]
+     * @return: java.util.List<java.lang.Integer>
+     **/
     private List<Integer> reports(LocalDate startDate, LocalDate endDate) {
         LambdaQueryWrapper<PmWorkReport> reportsQuery = Wrappers.lambdaQuery();
         reportsQuery.select(PmWorkReport::getId)
@@ -500,8 +566,10 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
         Integer tenantId = SecurityUtils.getTenantId();
         Long deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId();
         LambdaQueryWrapper<SysUser> userNameQuery = Wrappers.lambdaQuery();
-        userNameQuery.select(SysUser::getUserId, SysUser::getNickName);
-        userNameQuery.eq(SysUser::getDelFlag, 0).eq(SysUser::getStatus, 0);
+        userNameQuery.select(SysUser::getUserId, SysUser::getNickName, SysUser::getUserName, SysUser::getPhonenumber, SysUser::getAvatar,
+                        SysUser::getSex, SysUser::getDeptId)
+                .eq(SysUser::getDelFlag, 0)
+                .eq(SysUser::getStatus, 0);
         if (userId != null && userId != 0) {
             userNameQuery.eq(SysUser::getUserId, userId);
             return sysUserMapper.selectList(userNameQuery);
@@ -575,7 +643,7 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
             nickName.add(user.getNickName());
         }
 
-        //统计userId每个项目所需工时
+        // 统计userId每个项目所需工时
         List<WorkHoursStatisticsVO> userAndProject = new ArrayList<>();
         List<PmWorkContent> pmWorkContentList = workTimeCount(userIds, pmProjectId, startDate, endDate);
         for (PmWorkContent content : pmWorkContentList) {
@@ -602,12 +670,12 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
         }
         List<WorkHoursStatisticsVO> userAndProjectD = userAndProject;
 
-        //userAndProject = baseMapper.workHoursStatistics(start, end, userId, tenantId);
-        //Long deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId();
-        //List<WorkHoursStatisticsVO> userAndProjectD = baseMapper.statisticsDept(start, end, userId, tenantId, deptId);
+        // userAndProject = baseMapper.workHoursStatistics(start, end, userId, tenantId);
+        // Long deptId = SecurityUtils.getLoginUser().getSysUser().getDeptId();
+        // List<WorkHoursStatisticsVO> userAndProjectD = baseMapper.statisticsDept(start, end, userId, tenantId, deptId);
         if (workerOrProject != 1) {
             returnList.add(nickName);
-            //重组返回数据结构
+            // 重组返回数据结构
             for (String name : pmProjectName) {
                 ProjectWorkTimeVO projectWorkTimeVO = new ProjectWorkTimeVO();
                 projectWorkTimeVO.setProjectOrPerson(name);
@@ -640,7 +708,7 @@ public class PmWorkContentServiceImpl extends AbstractCrudService<PmWorkContentM
             returnList.add(projectWorkTime);
         } else {
             returnList.add(pmProjectName);
-            //重组返回数据结构
+            // 重组返回数据结构
             for (String uName : nickName) {
                 String name = uName;
                 UserWorkTimeVO userWorkTimeVO2 = new UserWorkTimeVO();

+ 105 - 138
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/impl/PmWorkReportServiceImpl.java

@@ -4,13 +4,18 @@ import com.aliyuncs.exceptions.ClientException;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.usky.common.core.exception.BusinessException;
+import com.usky.common.mybatis.core.AbstractCrudService;
 import com.usky.common.security.utils.SecurityUtils;
-import com.usky.iot.domain.*;
-import com.usky.iot.mapper.*;
+import com.usky.iot.domain.PmProject;
+import com.usky.iot.domain.PmReceive;
+import com.usky.iot.domain.PmWorkContent;
+import com.usky.iot.domain.PmWorkReport;
+import com.usky.iot.mapper.PmReceiveMapper;
+import com.usky.iot.mapper.PmWorkContentMapper;
+import com.usky.iot.mapper.PmWorkReportMapper;
 import com.usky.iot.service.PmProjectService;
 import com.usky.iot.service.PmWorkContentService;
 import com.usky.iot.service.PmWorkReportService;
-import com.usky.common.mybatis.core.AbstractCrudService;
 import com.usky.iot.service.config.DingTalkAndMessage;
 import com.usky.iot.service.vo.PmProjectTotalWorkTimeVo;
 import com.usky.iot.service.vo.PmProjectWorkTimeVo;
@@ -92,7 +97,7 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
             dates.add(tempDate);
             tempDate = tempDate.plusDays(1);
         }
-        //返回最新的一条数据给前端填充
+        // 返回最新的一条数据给前端填充
         LambdaQueryWrapper<PmWorkReport> wrapper2 = Wrappers.lambdaQuery();
         wrapper2.eq(PmWorkReport::getSubmitterId, SecurityUtils.getUserId())
                 .orderByDesc(PmWorkReport::getSubmitDate)
@@ -105,7 +110,7 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
             List<PmWorkContent> contents1 = pmWorkContentMapper.selectList(wrapper);
             report.get(0).setWorkContents(contents1);
         }
-        //固定返回七条数据,没有内容也要设置时间给前端渲染
+        // 固定返回七条数据,没有内容也要设置时间给前端渲染
         LambdaQueryWrapper<PmWorkReport> queryWrapperR = Wrappers.lambdaQuery();
         queryWrapperR.eq(PmWorkReport::getSubmitterId, SecurityUtils.getUserId())
                 .between(PmWorkReport::getReportDate, startDate1, endDate1)
@@ -133,7 +138,7 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
         }
         LambdaQueryWrapper<PmWorkContent> queryWrapperC = Wrappers.lambdaQuery();
         queryWrapperC.select(PmWorkContent::getId, PmWorkContent::getWorkContent, PmWorkContent::getWorkTime, PmWorkContent::getProjectId,
-                PmWorkContent::getProjectName, PmWorkContent::getReportId, PmWorkContent::getCreateTime, PmWorkContent::getUpdateTime)
+                        PmWorkContent::getProjectName, PmWorkContent::getReportId, PmWorkContent::getCreateTime, PmWorkContent::getUpdateTime)
                 .in(PmWorkContent::getReportId, ids)
                 .orderByDesc(PmWorkContent::getWorkTime);
         List<PmWorkContent> contents = pmWorkContentMapper.selectList(queryWrapperC);
@@ -201,10 +206,12 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
         String userName = SecurityUtils.getUsername();
         Long userId = SecurityUtils.getUserId();
         Integer tenantId = SecurityUtils.getTenantId();
-        BigDecimal totalWorkTime = BigDecimal.ZERO; //计算总工时
+        BigDecimal totalWorkTime = BigDecimal.ZERO; // 计算总工时
         LocalDateTime dateTime = LocalDateTime.now();
         LocalDateTime timingTime = pmWorkReport.getTimingTime();
         LocalDateTime currentTimePlusMinutes = dateTime.plusMinutes(5);
+        String ccTo = pmWorkReport.getCcTo();
+        Integer rid = pmWorkReport.getId();
 
         if (pmWorkReport.getWorkContents() == null) {
             throw new BusinessException("报告内容不能为空,请检查!");
@@ -218,7 +225,7 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
         for (PmWorkContent a : pmWorkReport.getWorkContents()) {
             totalWorkTime = totalWorkTime.add(a.getWorkTime());
         }
-        //判断总工时是否超过24h
+        // 判断总工时是否超过24h
         BigDecimal maxWorkTimePerDay = BigDecimal.valueOf(24);
         if (totalWorkTime.compareTo(maxWorkTimePerDay) >= 0) {
             throw new BusinessException("一天24小时都不够你用,请检查当日总工时!");
@@ -226,19 +233,14 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
         if (totalWorkTime.compareTo(BigDecimal.ZERO) <= 0) {
             throw new BusinessException("工时必须大于零!");
         }
-        LambdaQueryWrapper<PmWorkReport> reportWrapper = Wrappers.lambdaQuery();
-        reportWrapper.select(PmWorkReport::getId)
-                .eq(PmWorkReport::getReportDate, pmWorkReport.getReportDate())
-                .last("LIMIT 1");
-        List<PmWorkReport> repeat = this.list(reportWrapper);
-        //判断是否携带reportId,不写带则为新增报告,携带则为编辑(更新)项目
-        if (pmWorkReport.getId() == null) {
 
+        // 判断是否携带reportId,不写带则为新增报告,携带则为编辑(更新)项目
+        if (rid == null) {
             PmWorkReport newReport = new PmWorkReport();
             newReport.setReportDate(pmWorkReport.getReportDate());
             newReport.setSubmitterId(userId);
             newReport.setSubmitDate(LocalDateTime.now());
-            newReport.setCcTo(pmWorkReport.getCcTo());
+            newReport.setCcTo(ccTo);
             newReport.setCoordinateWork(pmWorkReport.getCoordinateWork());
             newReport.setTomorrowPlan(pmWorkReport.getTomorrowPlan());
             newReport.setCreateBy(userName);
@@ -253,7 +255,7 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
                     newReport.setTimingTime(timingTime);
                     newReport.setReportStatus(0);
                 } else {
-                    throw new BusinessException("定时时间需提前至少五分钟!");
+                    throw new BusinessException("定时发送支持选中5分钟后的时间,请重新选择时间!");
                 }
             }
             try {
@@ -264,18 +266,18 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
                 throw new BusinessException("已存在重复数据,一人一天一篇报告");
             }
 
-            //获取报告中所有项目id
+            // 获取报告中所有项目id
             List<Integer> projectIds = new ArrayList<>();
             for (PmWorkContent b1 : pmWorkReport.getWorkContents()) {
                 projectIds.add(b1.getProjectId());
             }
-            //查出所有项目id对应项目名
+            // 查出所有项目id对应项目名
             List<PmProject> project = pmProjectService.projectName(projectIds);
-            //将项目名重新赋值
+            // 将项目名重新赋值
             List<PmWorkContent> pmWorkContents = new ArrayList<>();
             for (PmWorkContent b : pmWorkReport.getWorkContents()) {
                 for (int c = 0; c < project.size(); c++) {
-                    if (b.getProjectId() == project.get(c).getId()) {
+                    if (b.getProjectId().equals(project.get(c).getId())) {
                         b.setProjectName(project.get(c).getProjectName());
                     }
                 }
@@ -294,58 +296,55 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
                 pmWorkContentMapper.insert(newContent);
                 pmWorkContents.add(newContent);
             }
-            if (timingTime == null) {
-                //推送消息中心
+
+            // 抄送人不为空、非定时发送
+            if (StringUtils.isNotEmpty(ccTo) && timingTime == null) {
+                // 推送消息中心
                 dingTalkAndMessage.sendAsyncMessage(newReport);
 
-                //是否同步钉钉
-                if (pmWorkReport.getSendDingTalk() == 1) {
+                // 是否同步钉钉
+                if (pmWorkReport.getSendDingTalk().equals(1)) {
                     dingTalkAndMessage.sendDingTalkDailyReport(newReport, pmWorkContents);
                 }
 
-                //存入报告消息表
-                List<Long> longList = Arrays.stream(pmWorkReport.getCcTo().split(","))
-                        .map(Long::parseLong)
-                        .collect(Collectors.toList());
-                receiveMessages(longList, newReport.getId());
-            }
-            //抄送人不为空,非定时发送
-            if (StringUtils.isNotEmpty(pmWorkReport.getCcTo())) {
+                // 存入报告消息表
+                receiveMessages(ccTo, newReport.getId());
             }
-        } else if (repeat.size() > 0) {
+        } else {
             PmWorkReport rp = new PmWorkReport();
-            rp.setId(pmWorkReport.getId());
-            //rp.setReportDate(pmWorkReport.getReportDate());
+            rp.setId(rid);
+            // rp.setReportDate(pmWorkReport.getReportDate());
             rp.setSubmitterId(pmWorkReport.getSubmitterId());
-            //rp.setSubmitDate(pmWorkReport.getSubmitDate());
-            rp.setCcTo(pmWorkReport.getCcTo());
+            // rp.setSubmitDate(pmWorkReport.getSubmitDate());
+            if (pmWorkReport.getReportStatus().equals(0)) {
+                rp.setCcTo(ccTo);
+            }
             rp.setCoordinateWork(pmWorkReport.getCoordinateWork());
             rp.setTomorrowPlan(pmWorkReport.getTomorrowPlan());
             rp.setCreateBy(pmWorkReport.getCreateBy());
-            //rp.setCreateTime(pmWorkReport.getCreateTime());
-            //rp.setDeptId(pmWorkReport.getDeptId());
-            //rp.setTenantId(pmWorkReport.getTenantId());
+            // rp.setCreateTime(pmWorkReport.getCreateTime());
+            // rp.setDeptId(pmWorkReport.getDeptId());
+            // rp.setTenantId(pmWorkReport.getTenantId());
             rp.setUpdateBy(userName);
             rp.setUpdateTime(dateTime);
             rp.setTotalHours(totalWorkTime);
-            if (pmWorkReport.getIsRegularlySend() == 1) {
-                if (timingTime != null && timingTime.isAfter(currentTimePlusMinutes)) {
-                    rp.setTimingTime(timingTime);
-                } else {
-                    throw new BusinessException("定时时间需大于五分钟!");
-                }
-            } else {
-                rp.setIsRegularlySend(0);
+            rp.setIsRegularlySend(pmWorkReport.getIsRegularlySend());
+            if (pmWorkReport.getReportStatus().equals(0) && pmWorkReport.getIsRegularlySend().equals(1)) {
+                    if (timingTime != null && timingTime.isAfter(currentTimePlusMinutes)) {
+                        rp.setTimingTime(timingTime);
+                    } else {
+                        throw new BusinessException("定时发送支持选中5分钟后的时间,请重新选择时间!");
+                    }
             }
-            //rp.setReportStatus(pmWorkReport.getReportStatus());
             rp.setSendDingTalk(pmWorkReport.getSendDingTalk());
             pmWorkReportMapper.updateById(rp);
+
             LambdaQueryWrapper<PmWorkContent> queryWrapper = Wrappers.lambdaQuery();
             queryWrapper.select(PmWorkContent::getReportId, PmWorkContent::getSubmitterId, PmWorkContent::getCreateBy, PmWorkContent::getCreateTime, PmWorkContent::getDeptId, PmWorkContent::getTenantId)
-                    .eq(PmWorkContent::getReportId, pmWorkReport.getId())
+                    .eq(PmWorkContent::getReportId, rid)
                     .last("LIMIT 1");
             PmWorkContent f = pmWorkContentMapper.selectOne(queryWrapper);
-            pmWorkContentService.deleteContent(pmWorkReport.getId());
+            pmWorkContentService.deleteContent(rid);
             List<PmWorkContent> contents = pmWorkReport.getWorkContents();
             List<PmWorkContent> contentsList = new ArrayList<>();
             for (PmWorkContent e : contents) {
@@ -360,18 +359,25 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
                 pmWorkContentMapper.insert(e);
                 contentsList.add(e);
             }
-            if (pmWorkReport.getSendDingTalk().equals(1)) {
+            if (pmWorkReport.getSendDingTalk() ==1 && pmWorkReport.getTimingTime() != null && pmWorkReport.getIsRegularlySend() == 1) {
                 dingTalkAndMessage.sendDingTalkDailyReport(rp, contentsList);
+            }
+            if (pmWorkReport.getIsRegularlySend() == 0){
+                receiveMessages(ccTo, rid);
+                rp.setTimingTime(null);
                 rp.setReportStatus(1);
                 pmWorkReportMapper.updateById(rp);
             }
         }
     }
 
-    private void receiveMessages(List<Long> ids, Integer reportId) {
-        List<SysUser> users = pmWorkContentService.nickNames(ids);
-        if (ids.size() > 0) {
-            for (Long id : ids) {
+    private void receiveMessages(String ids, Integer reportId) {
+        List<Long> longList = Arrays.stream(ids.split(","))
+                .map(Long::parseLong)
+                .collect(Collectors.toList());
+        List<SysUser> users = pmWorkContentService.nickNames(longList);
+        if (longList.size() > 0) {
+            for (Long id : longList) {
                 PmReceive pmReceive = new PmReceive();
                 pmReceive.setReceiverId(id);
                 pmReceive.setReportId(reportId);
@@ -394,101 +400,30 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
     public PmProjectTotalWorkTimeVo countTime(Integer dateType, Integer dateNum) {
         int scale = 4;
         RoundingMode roundingMode = RoundingMode.HALF_UP;
-//        List<Map<String, Object>> returnList = new ArrayList<>();
-//        Map<String, Object> weekTotalMap = new HashMap<>();
-//        Map<String, Object> monthTotalMap = new HashMap<>();
-//        Map<String, Object> weekMap = new HashMap<>();
-//        Map<String, Object> monthMap = new HashMap<>();
         PmProjectTotalWorkTimeVo projectTotalWorkTimeVo = new PmProjectTotalWorkTimeVo();
-        List<PmProjectWorkTimeVo> returnListW = new ArrayList<>();
-        //List<PmProjectWorkTimeVo> returnListM = new ArrayList<>();
-        //LocalDate today = LocalDate.now();
-
-//        LocalDate startOfWeek = today.with(TemporalAdjusters.previousOrSame(java.time.DayOfWeek.MONDAY));
-//        LocalDate endOfWeek = today.with(TemporalAdjusters.nextOrSame(java.time.DayOfWeek.SUNDAY));
-//        LocalDateTime startOfWeekDateTime = startOfWeek.atStartOfDay();
-//        LocalDateTime endOfWeekDateTime = endOfWeek.atTime(23, 59, 59);
         Map<String, LocalDateTime> stringLocalDateTimeMap = countWeekOrMonth(dateType, dateNum);
         LocalDateTime startTime = stringLocalDateTimeMap.get("start");
         LocalDateTime endTime = stringLocalDateTimeMap.get("end");
         BigDecimal totalWorkTime = BigDecimal.ZERO;
+
         List<PmProjectWorkTimeVo> week = pmWorkContentMapper.workTimeCount(startTime, endTime, SecurityUtils.getUserId());
         if (week.isEmpty()) {
             projectTotalWorkTimeVo.setTotalWorkTime(totalWorkTime);
             projectTotalWorkTimeVo.setProjectWorkTime(week);
             return projectTotalWorkTimeVo;
         }
-//        for (int i = 0; i < week.size(); i++) {
-//            weekTotal = weekTotal.add(week.get(i).getWorkTime());
-//        }
         totalWorkTime = week.stream()
                 .map(PmProjectWorkTimeVo::getWorkTime)
                 .reduce(BigDecimal.ZERO, BigDecimal::add);
 
-//        BigDecimal totalPercentageW = BigDecimal.ZERO;
-//        for (int a = 0; a < week.size(); a++) {
-//            PmProjectWorkTimeVo workTimeVo = new PmProjectWorkTimeVo();
-//            workTimeVo.setProjectName(week.get(a).getProjectName());
-//            workTimeVo.setWorkTime(week.get(a).getWorkTime());
-//            if (a != week.size() - 1) {
-//                BigDecimal percentage = week.get(a).getWorkTime().divide(weekTotal, scale, roundingMode);
-//                workTimeVo.setPercentage(percentage);
-//                totalPercentageW = totalPercentageW.add(percentage);
-//            } else {
-//                BigDecimal lastPercentage = BigDecimal.ONE.subtract(totalPercentageW);
-//                workTimeVo.setPercentage(lastPercentage);
-//            }
-//            workTimeVo.setPercentage(week.get(a).getWorkTime().divide(weekTotal, scale, roundingMode));
-//            returnListW.add(workTimeVo);
-//        }
-//        projectTotalWorkTimeVo.setProjectWorkTime(returnListW);
         List<PmProjectWorkTimeVo> projectWorkTimeWithPercentage = calculatePercentage(week, totalWorkTime, scale, roundingMode);
         projectTotalWorkTimeVo.setTotalWorkTime(totalWorkTime);
         projectTotalWorkTimeVo.setProjectWorkTime(projectWorkTimeWithPercentage);
-        return projectTotalWorkTimeVo;
 
-
-//        LocalDate startOfMonth = today.withDayOfMonth(1);
-//        LocalDate endOfMonth = today.withDayOfMonth(today.lengthOfMonth());
-//        LocalDateTime startOfMonthDateTime = startOfMonth.atStartOfDay();
-//        LocalDateTime endOfMonthDateTime = endOfMonth.atTime(23, 59, 59);
-//        BigDecimal monthTotal = BigDecimal.ZERO;
-//        List<PmProjectWorkTimeVo> month = pmWorkContentMapper.workTimeCount(startOfMonthDateTime, endOfMonthDateTime, SecurityUtils.getUserId());
-//        if (month.isEmpty()) {
-//            weekTotalMap.put("MonthWorkTimeTotal", 0);
-//            weekMap.put("MonthlyData", month);
-//        }
-//        for (int i = 0; i < month.size(); i++) {
-//            monthTotal = monthTotal.add(month.get(i).getWorkTime());
-//        }
-//        BigDecimal totalPercentageM = BigDecimal.ZERO;
-//        for (int b = 0; b < month.size(); b++) {
-//            PmProjectWorkTimeVo workTimeVo = new PmProjectWorkTimeVo();
-//            workTimeVo.setProjectName(month.get(b).getProjectName());
-//            workTimeVo.setWorkTime(month.get(b).getWorkTime());
-//            if (b != month.size() - 1) {
-//                BigDecimal percentage = month.get(b).getWorkTime().divide(monthTotal, scale, roundingMode);
-//                workTimeVo.setPercentage(percentage);
-//                totalPercentageM = totalPercentageM.add(percentage);
-//            } else {
-//                BigDecimal lastPercentage = BigDecimal.ONE.subtract(totalPercentageM);
-//                workTimeVo.setPercentage(lastPercentage);
-//            }
-//
-//            returnListM.add(workTimeVo);
-//        }
-
-//        weekTotalMap.put("WeekWorkTimeTotal", weekTotal);
-//        monthTotalMap.put("MonthWorkTimeTotal", monthTotal);
-//        weekMap.put("WeeklyData", returnListW);
-//        monthMap.put("MonthlyData", returnListM);
-//        returnList.add(weekTotalMap);
-//        returnList.add(monthTotalMap);
-//        returnList.add(weekMap);
-//        returnList.add(monthMap);
-        //return null;
+        return projectTotalWorkTimeVo;
     }
-    //计算百分比
+
+    // 计算百分比
     private List<PmProjectWorkTimeVo> calculatePercentage(List<PmProjectWorkTimeVo> workTimeList, BigDecimal totalWorkTime, int scale, RoundingMode roundingMode) {
         BigDecimal totalPercentage = BigDecimal.ZERO;
         List<PmProjectWorkTimeVo> projectWorkTimeWithPercentage = new ArrayList<>();
@@ -509,9 +444,13 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
         return projectWorkTimeWithPercentage;
     }
 
-
-
-    //计算周和月
+    /**
+     * @description: 计算周和月
+     * @author: fu
+     * @date: 2024/8/7 20:17
+     * @param: [dateType, dateNum]
+     * @return: java.util.Map<java.lang.String, java.time.LocalDateTime>
+     **/
     public Map<String, LocalDateTime> countWeekOrMonth(Integer dateType, Integer dateNum) {
         Map<String, LocalDateTime> timePeriod = new HashMap<>();
         LocalDate today = LocalDate.now();
@@ -552,10 +491,24 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
     }
 
 
+    /**
+     * @description: 工作报告定时发送
+     * @author: fu
+     * @date: 2024/8/7 20:17
+     * @param: [time] 开始时间
+     * @return: void
+     **/
     @Transactional
     @Override
     public void timedSending(LocalDateTime time) {
         log.info("定时报告任务开始---------------------------");
+        int messageCenterTotal = 0;
+        int messageCenterSuccess = 0;
+        int messageCenterFail = 0;
+
+        int dingTalkTotal = 0;
+        int dingTalkSuccess = 0;
+        int dingTalkFail = 0;
         LambdaQueryWrapper<PmWorkReport> reports = Wrappers.lambdaQuery();
         reports.eq(PmWorkReport::getReportStatus, 0)
                 .eq(PmWorkReport::getIsRegularlySend, 1)
@@ -570,7 +523,7 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
             LambdaQueryWrapper<PmWorkContent> reportContents = Wrappers.lambdaQuery();
             reportContents.in(PmWorkContent::getReportId, reportIds);
             List<PmWorkContent> pmWorkContentList = pmWorkContentMapper.selectList(reportContents);
-            for (PmWorkReport report : reportList) {
+/*            for (PmWorkReport report : reportList) {
                 Integer id = report.getId();
                 List<PmWorkContent> workContents = new ArrayList<>();
                 for (PmWorkContent content : pmWorkContentList) {
@@ -578,27 +531,41 @@ public class PmWorkReportServiceImpl extends AbstractCrudService<PmWorkReportMap
                     if (reportId.equals(id)) {
                         workContents.add(content);
                     }
-                }
+                }*/
+            for (PmWorkReport report : reportList) {
+                messageCenterTotal++;
+                Integer id = report.getId();
+                List<PmWorkContent> workContents = pmWorkContentList.stream()
+                        .filter(content -> content.getReportId().equals(id))
+                        .collect(Collectors.toList());
                 try {
                     dingTalkAndMessage.sendAsyncMessage(report);
+                    messageCenterSuccess++;
                 } catch (Exception e) {
                     log.error("定时报告" + report.getId() + "调用消息中心异常" + e);
+                    messageCenterFail++;
                 }
                 if (report.getSendDingTalk() == 1) {
+                    dingTalkTotal++;
                     try {
                         dingTalkAndMessage.sendDingTalkDailyReport(report, workContents);
+                        dingTalkSuccess++;
                     } catch (Exception e) {
                         log.error("定时报告" + report.getId() + "发送钉钉异常" + e);
+                        dingTalkFail++;
                     }
                 }
-
                 report.setReportStatus(1);
+                report.setSubmitDate(time);
                 pmWorkReportMapper.updateById(report);
+                receiveMessages(report.getCcTo(), report.getId());
             }
         } else {
             log.info("当前没有定时工作报告可发送");
         }
         log.info("定时报告任务结束---------------------------");
+        log.info("消息中心发送总数:{},成功:{},失败:{}", messageCenterTotal, messageCenterSuccess, messageCenterFail);
+        log.info("钉钉发送总数:{},成功:{},失败:{}", dingTalkTotal, dingTalkSuccess, dingTalkFail);
     }
 
 

+ 27 - 0
service-iot/service-iot-biz/src/main/java/com/usky/iot/service/vo/PmReportReadersVO.java

@@ -0,0 +1,27 @@
+package com.usky.iot.service.vo;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author fu
+ * @date 2024/8/8
+ */
+@Data
+public class PmReportReadersVO {
+    //已读
+    private List<Long> readAlready;
+    //未读
+    private List<Long> readNotAlready;
+    //已读数量
+    private Integer read;
+    //未读数量
+    private Integer unRead;
+
+    public PmReportReadersVO(List<Long> readAlready, List<Long> readNotAlready, Integer read, Integer unRead) {
+        this.readAlready = readAlready;
+        this.readNotAlready = readNotAlready;
+        this.read = read;
+        this.unRead = unRead;
+    }
+}