From 7f832d819e5f21ed6b2008390ecc884ff64fe956 Mon Sep 17 00:00:00 2001 From: dk <1260500659@qq.com> Date: Thu, 2 Jul 2026 16:33:33 +0800 Subject: [PATCH] =?UTF-8?q?feat(workreport):=20=E6=B7=BB=E5=8A=A0=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=8A=A5=E5=91=8A=E5=BE=85=E6=8F=90=E4=BA=A4=E6=8F=90?= =?UTF-8?q?=E9=86=92=E5=8A=9F=E8=83=BD=20-=20=E6=96=B0=E5=A2=9E=20selectLi?= =?UTF-8?q?stByPendingSubmitReminder=20=E6=96=B9=E6=B3=95=E7=94=A8?= =?UTF-8?q?=E4=BA=8E=E6=9F=A5=E8=AF=A2=E5=BE=85=E6=8F=90=E4=BA=A4=E7=9A=84?= =?UTF-8?q?=E5=B7=A5=E4=BD=9C=E6=8A=A5=E5=91=8A=20-=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E9=80=9A=E7=9F=A5=E6=A8=A1=E6=9D=BF=E5=B8=B8=E9=87=8F=E7=94=A8?= =?UTF-8?q?=E4=BA=8E=E5=BE=85=E5=AE=A1=E6=89=B9=E9=80=9A=E7=9F=A5=E5=8A=9F?= =?UTF-8?q?=E8=83=BD=20-=20=E6=9B=BF=E6=8D=A2=20ChronoField=20=E4=B8=BA=20?= =?UTF-8?q?IsoFields=20=E4=BB=A5=E6=AD=A3=E7=A1=AE=E5=A4=84=E7=90=86?= =?UTF-8?q?=E5=9F=BA=E4=BA=8E=E5=91=A8=E7=9A=84=E5=B9=B4=E4=BB=BD=E8=AE=A1?= =?UTF-8?q?=E7=AE=97=20-=20=E5=AE=9E=E7=8E=B0=E4=B8=AA=E4=BA=BA=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=8A=A5=E5=91=8A=E5=BE=85=E7=9B=B4=E5=B1=9E=E4=B8=8A?= =?UTF-8?q?=E7=BA=A7=E5=AE=A1=E6=89=B9=E7=9A=84=E9=80=9A=E7=9F=A5=E5=8F=91?= =?UTF-8?q?=E5=B8=83=E9=80=BB=E8=BE=91=20-=20=E5=AE=9E=E7=8E=B0=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E6=8A=A5=E5=91=8A=E5=BE=85=E5=AE=A1=E6=89=B9=E9=80=9A?= =?UTF-8?q?=E7=9F=A5=E7=9A=84=E5=8F=91=E5=B8=83=E5=8A=9F=E8=83=BD=20-=20?= =?UTF-8?q?=E5=88=9B=E5=BB=BA=20WorkReportPendingSubmitRemindScheduler=20?= =?UTF-8?q?=E5=AE=9A=E6=97=B6=E4=BB=BB=E5=8A=A1=E7=B1=BB=20-=20=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=20WorkReportPendingSubmitRemindService=20=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E7=B1=BB=E5=A4=84=E7=90=86=E6=8F=90=E9=86=92=E9=80=BB?= =?UTF-8?q?=E8=BE=91=20-=20=E6=B7=BB=E5=8A=A0=E5=AE=9A=E6=97=B6=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E6=AF=8F=E6=99=9A=208=20=E7=82=B9=E6=A3=80=E6=9F=A5?= =?UTF-8?q?=E5=B9=B6=E6=8F=90=E9=86=92=E9=80=BE=E6=9C=9F=E6=9C=AA=E6=8F=90?= =?UTF-8?q?=E4=BA=A4=E7=9A=84=E6=8A=A5=E5=91=8A=20-=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=91=A8=E6=8A=A5=E3=80=81=E6=9C=88=E6=8A=A5=E5=92=8C=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E6=8A=A5=E5=91=8A=E4=B8=89=E7=A7=8D=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E7=9A=84=E5=BE=85=E6=8F=90=E4=BA=A4=E6=8F=90=E9=86=92=20-=20?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=9F=BA=E4=BA=8E=E6=88=AA=E6=AD=A2=E6=97=B6?= =?UTF-8?q?=E9=97=B4=E8=BF=87=E6=BB=A4=E5=B9=B6=E6=8C=89=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E6=97=B6=E9=97=B4=E6=8E=92=E5=BA=8F=E7=9A=84=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../monthly/MonthlyReportMapper.java | 12 ++ .../project/ProjectReportMapper.java | 12 ++ .../workreport/weekly/WeeklyReportMapper.java | 12 ++ .../notify/NotifyTemplateCodeConstants.java | 8 ++ .../common/WorkReportCommonService.java | 57 ++++++++ ...orkReportPendingSubmitRemindScheduler.java | 17 +++ .../WorkReportPendingSubmitRemindService.java | 125 ++++++++++++++++++ .../team/TeamWorkReportServiceImpl.java | 7 +- 8 files changed, 247 insertions(+), 3 deletions(-) create mode 100644 rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/workreport/remind/WorkReportPendingSubmitRemindScheduler.java create mode 100644 rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/workreport/remind/WorkReportPendingSubmitRemindService.java diff --git a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/dal/mysql/workreport/monthly/MonthlyReportMapper.java b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/dal/mysql/workreport/monthly/MonthlyReportMapper.java index d21dd0c..0a5d698 100644 --- a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/dal/mysql/workreport/monthly/MonthlyReportMapper.java +++ b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/dal/mysql/workreport/monthly/MonthlyReportMapper.java @@ -162,6 +162,18 @@ public interface MonthlyReportMapper extends BaseMapperX { .in(MonthlyReportDO::getStatusCode, statuses)); } + default List selectListByPendingSubmitReminder(LocalDateTime cutoffTime, + Collection statusCodes) { + if (cutoffTime == null || statusCodes == null || statusCodes.isEmpty()) { + return List.of(); + } + return selectList(new LambdaQueryWrapperX() + .in(MonthlyReportDO::getStatusCode, statusCodes) + .le(MonthlyReportDO::getCreateTime, cutoffTime) + .orderByAsc(MonthlyReportDO::getCreateTime) + .orderByAsc(MonthlyReportDO::getId)); + } + private LambdaQueryWrapperX buildPageQuery(MonthlyReportPageReqVO reqVO) { LambdaQueryWrapperX wrapper = new LambdaQueryWrapperX() .eqIfPresent(MonthlyReportDO::getStatusCode, reqVO.getStatusCode()) diff --git a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/dal/mysql/workreport/project/ProjectReportMapper.java b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/dal/mysql/workreport/project/ProjectReportMapper.java index 35b959d..30dc034 100644 --- a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/dal/mysql/workreport/project/ProjectReportMapper.java +++ b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/dal/mysql/workreport/project/ProjectReportMapper.java @@ -172,6 +172,18 @@ public interface ProjectReportMapper extends BaseMapperX { .in(ProjectReportDO::getStatusCode, statuses)); } + default List selectListByPendingSubmitReminder(LocalDateTime cutoffTime, + Collection statusCodes) { + if (cutoffTime == null || statusCodes == null || statusCodes.isEmpty()) { + return List.of(); + } + return selectList(new LambdaQueryWrapperX() + .in(ProjectReportDO::getStatusCode, statusCodes) + .le(ProjectReportDO::getCreateTime, cutoffTime) + .orderByAsc(ProjectReportDO::getCreateTime) + .orderByAsc(ProjectReportDO::getId)); + } + private LambdaQueryWrapperX buildPageQuery(ProjectReportPageReqVO reqVO) { LambdaQueryWrapperX wrapper = new LambdaQueryWrapperX() .eqIfPresent(ProjectReportDO::getProjectId, reqVO.getProjectId()) diff --git a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/dal/mysql/workreport/weekly/WeeklyReportMapper.java b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/dal/mysql/workreport/weekly/WeeklyReportMapper.java index 6b9f0bc..ac1a1f9 100644 --- a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/dal/mysql/workreport/weekly/WeeklyReportMapper.java +++ b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/dal/mysql/workreport/weekly/WeeklyReportMapper.java @@ -162,6 +162,18 @@ public interface WeeklyReportMapper extends BaseMapperX { .in(WeeklyReportDO::getStatusCode, statuses)); } + default List selectListByPendingSubmitReminder(LocalDateTime cutoffTime, + Collection statusCodes) { + if (cutoffTime == null || statusCodes == null || statusCodes.isEmpty()) { + return List.of(); + } + return selectList(new LambdaQueryWrapperX() + .in(WeeklyReportDO::getStatusCode, statusCodes) + .le(WeeklyReportDO::getCreateTime, cutoffTime) + .orderByAsc(WeeklyReportDO::getCreateTime) + .orderByAsc(WeeklyReportDO::getId)); + } + private LambdaQueryWrapperX buildPageQuery(WeeklyReportPageReqVO reqVO) { LambdaQueryWrapperX wrapper = new LambdaQueryWrapperX() .eqIfPresent(WeeklyReportDO::getStatusCode, reqVO.getStatusCode()) diff --git a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/framework/notify/NotifyTemplateCodeConstants.java b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/framework/notify/NotifyTemplateCodeConstants.java index 50f8a9b..b4eb879 100644 --- a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/framework/notify/NotifyTemplateCodeConstants.java +++ b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/framework/notify/NotifyTemplateCodeConstants.java @@ -32,6 +32,14 @@ public class NotifyTemplateCodeConstants { public static final String WORK_REPORT_PROJECT_HALF_MONTH_TEAM_REMIND = "work_report_project_half_month_team_remind"; + /** 工作报告待直属上级审批通知:周报/月报通用 */ + public static final String WORK_REPORT_PENDING_APPROVAL_NOTIFY = + "work_report_pending_approval_notify"; + + /** 项目半月报待直属上级审批通知 */ + public static final String WORK_REPORT_PROJECT_HALF_MONTH_PENDING_APPROVAL_NOTIFY = + "work_report_project_half_month_pending_approval_notify"; + /** 执行指派:创建执行后通知负责人 + 协办人 */ public static final String EXECUTION_ASSIGNED = "execution_assigned"; diff --git a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/workreport/common/WorkReportCommonService.java b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/workreport/common/WorkReportCommonService.java index acc99df..dc8a10d 100644 --- a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/workreport/common/WorkReportCommonService.java +++ b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/workreport/common/WorkReportCommonService.java @@ -7,6 +7,8 @@ import com.njcn.rdms.framework.common.util.object.BeanUtils; import com.njcn.rdms.framework.security.core.util.SecurityFrameworkUtils; import com.njcn.rdms.module.project.constant.ProjectObjectConstants; import com.njcn.rdms.module.project.constant.WorkReportConstants; +import com.njcn.rdms.module.project.framework.notify.NotifySendEvent; +import com.njcn.rdms.module.project.framework.notify.NotifyTemplateCodeConstants; import com.njcn.rdms.module.project.controller.admin.workreport.common.vo.*; import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.*; import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.*; @@ -58,7 +60,9 @@ import com.njcn.rdms.module.system.api.permission.dto.ObjectRoleRespDTO; import com.njcn.rdms.module.system.api.user.AdminUserApi; import com.njcn.rdms.module.system.api.user.UserManagementRelationApi; import com.njcn.rdms.module.system.api.user.dto.AdminUserRespDTO; +import com.njcn.rdms.module.system.enums.notify.NotifyMessageLevelConstants; import jakarta.annotation.Resource; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; @@ -66,6 +70,7 @@ import org.springframework.util.StringUtils; import java.math.BigDecimal; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.temporal.IsoFields; import java.util.*; import java.util.stream.Collectors; @@ -131,6 +136,8 @@ public class WorkReportCommonService { private UserObjectRoleMapper userObjectRoleMapper; @Resource private TeamDashboardAccessService teamDashboardAccessService; + @Resource + private ApplicationEventPublisher applicationEventPublisher; public List getStatusDict() { return objectStatusModelMapper.selectListByObjectTypeEnabled(WorkReportConstants.STATUS_OBJECT_TYPE).stream() @@ -282,6 +289,9 @@ public class WorkReportCommonService { transition.getToStatusCode(), null, buildWeeklyRemark(latest)); writeAuditLog(WorkReportConstants.BIZ_TYPE_WEEKLY, id, actionCode, current.getStatusCode(), transition.getToStatusCode(), null, buildWeeklyRemark(latest)); + publishPersonalReportPendingApprovalNotice(latest.getSupervisorUserId(), + NotifyTemplateCodeConstants.WORK_REPORT_PENDING_APPROVAL_NOTIFY, + "周报", latest.getReporterName(), formatWeeklyPeriodLabelForNotify(latest)); } @Transactional(rollbackFor = Exception.class) @@ -451,6 +461,9 @@ public class WorkReportCommonService { transition.getToStatusCode(), null, buildMonthlyRemark(latest)); writeAuditLog(WorkReportConstants.BIZ_TYPE_MONTHLY, id, actionCode, current.getStatusCode(), transition.getToStatusCode(), null, buildMonthlyRemark(latest)); + publishPersonalReportPendingApprovalNotice(latest.getSupervisorUserId(), + NotifyTemplateCodeConstants.WORK_REPORT_PENDING_APPROVAL_NOTIFY, + "月报", latest.getReporterName(), latest.getPeriodLabel()); } @Transactional(rollbackFor = Exception.class) @@ -649,6 +662,7 @@ public class WorkReportCommonService { transition.getToStatusCode(), null, buildProjectRemark(latest)); writeAuditLog(WorkReportConstants.BIZ_TYPE_PROJECT, id, actionCode, current.getStatusCode(), transition.getToStatusCode(), null, buildProjectRemark(latest)); + publishProjectReportPendingApprovalNotice(latest); } @Transactional(rollbackFor = Exception.class) @@ -879,6 +893,49 @@ public class WorkReportCommonService { return new ArrayList<>(merged); } + private void publishPersonalReportPendingApprovalNotice(Long supervisorUserId, String templateCode, + String reportTypeName, String reporterName, String periodLabel) { + if (supervisorUserId == null) { + return; + } + Map params = new LinkedHashMap<>(); + params.put("reportTypeName", reportTypeName); + params.put("reporterName", defaultText(reporterName)); + params.put("periodLabel", defaultText(periodLabel)); + applicationEventPublisher.publishEvent(NotifySendEvent.of( + List.of(supervisorUserId), templateCode, params, NotifyMessageLevelConstants.REMIND)); + } + + private void publishProjectReportPendingApprovalNotice(ProjectReportDO report) { + if (report == null || report.getSupervisorUserId() == null) { + return; + } + Map params = new LinkedHashMap<>(); + params.put("reporterName", defaultText(report.getProjectOwnerName())); + params.put("projectName", defaultText(report.getProjectName())); + params.put("periodLabel", defaultText(report.getPeriodLabel())); + applicationEventPublisher.publishEvent(NotifySendEvent.of( + List.of(report.getSupervisorUserId()), + NotifyTemplateCodeConstants.WORK_REPORT_PROJECT_HALF_MONTH_PENDING_APPROVAL_NOTIFY, + params, NotifyMessageLevelConstants.REMIND)); + } + + private String formatWeeklyPeriodLabelForNotify(WeeklyReportDO report) { + if (report == null || report.getPeriodStartDate() == null || report.getPeriodEndDate() == null) { + return defaultText(report == null ? null : report.getPeriodLabel()); + } + LocalDate startDate = report.getPeriodStartDate(); + LocalDate endDate = report.getPeriodEndDate(); + int weekBasedYear = startDate.get(IsoFields.WEEK_BASED_YEAR); + int weekOfYear = startDate.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR); + return weekBasedYear + "年" + weekOfYear + "周(" + formatMonthDayRange(startDate, endDate) + ")"; + } + + private String formatMonthDayRange(LocalDate startDate, LocalDate endDate) { + return startDate.getMonthValue() + "月" + startDate.getDayOfMonth() + + "日-" + endDate.getMonthValue() + "月" + endDate.getDayOfMonth() + "日"; + } + private ObjectStatusModelDO getInitialStatusModel() { ObjectStatusModelDO statusModel = objectStatusModelMapper .selectInitialByObjectTypeEnabled(WorkReportConstants.STATUS_OBJECT_TYPE); diff --git a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/workreport/remind/WorkReportPendingSubmitRemindScheduler.java b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/workreport/remind/WorkReportPendingSubmitRemindScheduler.java new file mode 100644 index 0000000..aa6954a --- /dev/null +++ b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/workreport/remind/WorkReportPendingSubmitRemindScheduler.java @@ -0,0 +1,17 @@ +package com.njcn.rdms.module.project.service.workreport.remind; + +import jakarta.annotation.Resource; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +@Component +public class WorkReportPendingSubmitRemindScheduler { + + @Resource + private WorkReportPendingSubmitRemindService workReportPendingSubmitRemindService; + + @Scheduled(cron = "0 0 20 * * ?", zone = "Asia/Shanghai") + public void remindPendingSubmitReports() { + workReportPendingSubmitRemindService.remindPendingSubmitReports(); + } +} diff --git a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/workreport/remind/WorkReportPendingSubmitRemindService.java b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/workreport/remind/WorkReportPendingSubmitRemindService.java new file mode 100644 index 0000000..ef5f16a --- /dev/null +++ b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/workreport/remind/WorkReportPendingSubmitRemindService.java @@ -0,0 +1,125 @@ +package com.njcn.rdms.module.project.service.workreport.remind; + +import com.njcn.rdms.module.project.constant.WorkReportConstants; +import com.njcn.rdms.module.project.dal.dataobject.workreport.monthly.MonthlyReportDO; +import com.njcn.rdms.module.project.dal.dataobject.workreport.project.ProjectReportDO; +import com.njcn.rdms.module.project.dal.dataobject.workreport.weekly.WeeklyReportDO; +import com.njcn.rdms.module.project.dal.mysql.workreport.monthly.MonthlyReportMapper; +import com.njcn.rdms.module.project.dal.mysql.workreport.project.ProjectReportMapper; +import com.njcn.rdms.module.project.dal.mysql.workreport.weekly.WeeklyReportMapper; +import com.njcn.rdms.module.project.framework.notify.NotifySendEvent; +import com.njcn.rdms.module.project.framework.notify.NotifyTemplateCodeConstants; +import com.njcn.rdms.module.system.enums.notify.NotifyMessageLevelConstants; +import jakarta.annotation.Resource; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.StringUtils; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.temporal.IsoFields; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class WorkReportPendingSubmitRemindService { + + private static final List REMIND_STATUS_CODES = List.of( + WorkReportConstants.STATUS_DRAFT, + WorkReportConstants.STATUS_REJECTED); + + @Resource + private WeeklyReportMapper weeklyReportMapper; + @Resource + private MonthlyReportMapper monthlyReportMapper; + @Resource + private ProjectReportMapper projectReportMapper; + @Resource + private ApplicationEventPublisher applicationEventPublisher; + + @Transactional(rollbackFor = Exception.class) + public void remindPendingSubmitReports() { + LocalDateTime cutoffTime = LocalDateTime.now().minusDays(2); + remindWeekly(cutoffTime); + remindMonthly(cutoffTime); + remindProject(cutoffTime); + } + + private void remindWeekly(LocalDateTime cutoffTime) { + List reports = weeklyReportMapper.selectListByPendingSubmitReminder(cutoffTime, REMIND_STATUS_CODES); + for (WeeklyReportDO report : reports) { + if (report == null || report.getReporterId() == null) { + continue; + } + Map params = new HashMap<>(); + params.put("reportTypeName", "周报"); + params.put("periodKey", formatWeeklyPeriod(report.getPeriodKey(), report.getPeriodStartDate(), report.getPeriodEndDate())); + params.put("managerName", defaultText(report.getSupervisorName(), "系统通知")); + applicationEventPublisher.publishEvent(NotifySendEvent.of( + List.of(report.getReporterId()), + NotifyTemplateCodeConstants.WORK_REPORT_TEAM_REMIND, + params, + NotifyMessageLevelConstants.REMIND)); + } + } + + private void remindMonthly(LocalDateTime cutoffTime) { + List reports = monthlyReportMapper.selectListByPendingSubmitReminder(cutoffTime, REMIND_STATUS_CODES); + for (MonthlyReportDO report : reports) { + if (report == null || report.getReporterId() == null) { + continue; + } + Map params = new HashMap<>(); + params.put("reportTypeName", "月报"); + params.put("periodKey", formatMonthlyPeriod(report.getPeriodKey(), report.getPeriodStartDate())); + params.put("managerName", defaultText(report.getSupervisorName(), "系统通知")); + applicationEventPublisher.publishEvent(NotifySendEvent.of( + List.of(report.getReporterId()), + NotifyTemplateCodeConstants.WORK_REPORT_TEAM_REMIND, + params, + NotifyMessageLevelConstants.REMIND)); + } + } + + private void remindProject(LocalDateTime cutoffTime) { + List reports = projectReportMapper.selectListByPendingSubmitReminder(cutoffTime, REMIND_STATUS_CODES); + for (ProjectReportDO report : reports) { + if (report == null || report.getProjectOwnerId() == null) { + continue; + } + Map params = new HashMap<>(); + params.put("projectName", defaultText(report.getProjectName(), "")); + params.put("periodLabel", defaultText(report.getPeriodLabel(), report.getPeriodKey())); + params.put("managerName", defaultText(report.getSupervisorName(), "系统通知")); + applicationEventPublisher.publishEvent(NotifySendEvent.of( + List.of(report.getProjectOwnerId()), + NotifyTemplateCodeConstants.WORK_REPORT_PROJECT_HALF_MONTH_TEAM_REMIND, + params, + NotifyMessageLevelConstants.REMIND)); + } + } + + private String formatWeeklyPeriod(String periodKey, LocalDate startDate, LocalDate endDate) { + if (startDate == null || endDate == null) { + return defaultText(periodKey, ""); + } + int weekBasedYear = startDate.get(IsoFields.WEEK_BASED_YEAR); + int weekOfYear = startDate.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR); + return weekBasedYear + "年" + weekOfYear + "周(" + + startDate.getMonthValue() + "月" + startDate.getDayOfMonth() + "日-" + + endDate.getMonthValue() + "月" + endDate.getDayOfMonth() + "日)"; + } + + private String formatMonthlyPeriod(String periodKey, LocalDate startDate) { + if (startDate == null) { + return defaultText(periodKey, ""); + } + return startDate.getYear() + "年" + startDate.getMonthValue() + "月"; + } + + private String defaultText(String text, String fallback) { + return StringUtils.hasText(text) ? text.trim() : fallback; + } +} diff --git a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/workreport/team/TeamWorkReportServiceImpl.java b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/workreport/team/TeamWorkReportServiceImpl.java index 9cd743b..828ca68 100644 --- a/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/workreport/team/TeamWorkReportServiceImpl.java +++ b/rdms-project/rdms-project-boot/src/main/java/com/njcn/rdms/module/project/service/workreport/team/TeamWorkReportServiceImpl.java @@ -31,7 +31,7 @@ import org.springframework.util.StringUtils; import java.time.DayOfWeek; import java.time.LocalDate; import java.time.format.DateTimeParseException; -import java.time.temporal.ChronoField; +import java.time.temporal.IsoFields; import java.time.temporal.TemporalAdjusters; import java.util.ArrayList; import java.util.Collection; @@ -576,8 +576,9 @@ public class TeamWorkReportServiceImpl implements TeamWorkReportService { } LocalDate startDate = parsePeriodDate(parts, 1); LocalDate endDate = parsePeriodDate(parts, 4); - int weekOfYear = startDate.get(ChronoField.ALIGNED_WEEK_OF_YEAR); - return startDate.getYear() + "年" + weekOfYear + "周(" + formatMonthDayRange(startDate, endDate) + ")"; + int weekBasedYear = startDate.get(IsoFields.WEEK_BASED_YEAR); + int weekOfYear = startDate.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR); + return weekBasedYear + "年" + weekOfYear + "周(" + formatMonthDayRange(startDate, endDate) + ")"; } private String formatMonthlyPeriodKey(String periodKey) {