feat(工作报告定时生成): 工作报告现在可以定时生成,并且可以刷新当前报告。
This commit is contained in:
@@ -2,11 +2,13 @@ package com.njcn.rdms.module.project;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
|
||||
/**
|
||||
* 项目交付域服务启动类
|
||||
*/
|
||||
@SpringBootApplication
|
||||
@EnableScheduling
|
||||
public class ProjectServerApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
@@ -14,6 +14,7 @@ import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.Month
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.MonthlyReportDefaultDraftReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.MonthlyReportExportVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.MonthlyReportPageReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.MonthlyReportRefreshDraftReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.MonthlyReportRespVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.MonthlyReportSaveReqVO;
|
||||
import com.njcn.rdms.module.project.service.workreport.export.WorkReportContentExportService;
|
||||
@@ -66,6 +67,13 @@ public class MonthlyReportController {
|
||||
return success(monthlyReportService.previewMonthlyDefaultDraft(reqVO));
|
||||
}
|
||||
|
||||
@PostMapping("/refresh-draft")
|
||||
@Operation(summary = "手动刷新月报默认稿")
|
||||
@PreAuthorize("@ss.hasPermission('" + WorkReportConstants.PERMISSION_CREATE + "')")
|
||||
public CommonResult<MonthlyReportRespVO> refreshMonthlyDraft(@Valid @RequestBody MonthlyReportRefreshDraftReqVO reqVO) {
|
||||
return success(monthlyReportService.refreshMonthlyDraft(reqVO));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "新建月报草稿")
|
||||
@PreAuthorize("@ss.hasPermission('" + WorkReportConstants.PERMISSION_CREATE + "')")
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo;
|
||||
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.common.vo.PersonalReportPlanItemReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.common.vo.PersonalReportReviewItemReqVO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
import static com.njcn.rdms.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
|
||||
|
||||
@Schema(description = "管理后台 - 月报手动刷新默认稿 Request VO")
|
||||
@Data
|
||||
public class MonthlyReportRefreshDraftReqVO {
|
||||
|
||||
@NotBlank(message = "周期编码不能为空")
|
||||
private String periodKey;
|
||||
|
||||
@NotBlank(message = "周期名称不能为空")
|
||||
private String periodLabel;
|
||||
|
||||
@NotNull(message = "周期开始日期不能为空")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate periodStartDate;
|
||||
|
||||
@NotNull(message = "周期结束日期不能为空")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate periodEndDate;
|
||||
|
||||
@Valid
|
||||
private List<PersonalReportReviewItemReqVO> reviewItems;
|
||||
|
||||
@Valid
|
||||
private List<PersonalReportPlanItemReqVO> planItems;
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.Proje
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.ProjectReportExportVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.ProjectReportOwnerProjectOptionRespVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.ProjectReportPageReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.ProjectReportRefreshDraftReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.ProjectReportRespVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.ProjectReportSaveReqVO;
|
||||
import com.njcn.rdms.module.project.service.workreport.export.WorkReportContentExportService;
|
||||
@@ -75,6 +76,14 @@ public class ProjectReportController {
|
||||
return success(projectReportService.previewProjectDefaultDraft(projectId, reqVO));
|
||||
}
|
||||
|
||||
@PostMapping("/{projectId}/refresh-draft")
|
||||
@Operation(summary = "手动刷新项目半月报默认稿")
|
||||
@PreAuthorize("@ss.hasPermission('" + WorkReportConstants.PERMISSION_PROJECT_OWNER + "')")
|
||||
public CommonResult<ProjectReportRespVO> refreshProjectDraft(@PathVariable("projectId") Long projectId,
|
||||
@Valid @RequestBody ProjectReportRefreshDraftReqVO reqVO) {
|
||||
return success(projectReportService.refreshProjectDraft(projectId, reqVO));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "新建项目半月报草稿")
|
||||
@PreAuthorize("@ss.hasPermission('" + WorkReportConstants.PERMISSION_PROJECT_OWNER + "')")
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
package com.njcn.rdms.module.project.controller.admin.workreport.project.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
import static com.njcn.rdms.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
|
||||
|
||||
@Schema(description = "管理后台 - 项目半月报手动刷新默认稿 Request VO")
|
||||
@Data
|
||||
public class ProjectReportRefreshDraftReqVO {
|
||||
|
||||
@NotBlank(message = "周期编码不能为空")
|
||||
private String periodKey;
|
||||
|
||||
@NotBlank(message = "周期名称不能为空")
|
||||
private String periodLabel;
|
||||
|
||||
@NotNull(message = "周期开始日期不能为空")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate periodStartDate;
|
||||
|
||||
@NotNull(message = "周期结束日期不能为空")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate periodEndDate;
|
||||
|
||||
@NotNull(message = "上半月/下半月标记不能为空")
|
||||
private Integer flag;
|
||||
|
||||
private String projectStatusDesc;
|
||||
|
||||
private String projectProgressPlan;
|
||||
|
||||
private String projectKeyPoints;
|
||||
|
||||
private String projectProblems;
|
||||
|
||||
@Valid
|
||||
private List<ProjectReportItemReqVO> currentItems;
|
||||
|
||||
@Valid
|
||||
private List<ProjectReportItemReqVO> nextItems;
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import com.njcn.rdms.module.project.controller.admin.workreport.weekly.vo.Weekly
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.weekly.vo.WeeklyReportDefaultDraftReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.weekly.vo.WeeklyReportExportVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.weekly.vo.WeeklyReportPageReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.weekly.vo.WeeklyReportRefreshDraftReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.weekly.vo.WeeklyReportRespVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.weekly.vo.WeeklyReportSaveReqVO;
|
||||
import com.njcn.rdms.module.project.service.workreport.export.WorkReportContentExportService;
|
||||
@@ -65,6 +66,13 @@ public class WeeklyReportController {
|
||||
return success(weeklyReportService.previewWeeklyDefaultDraft(reqVO));
|
||||
}
|
||||
|
||||
@PostMapping("/refresh-draft")
|
||||
@Operation(summary = "手动刷新周报默认稿")
|
||||
@PreAuthorize("@ss.hasPermission('" + WorkReportConstants.PERMISSION_CREATE + "')")
|
||||
public CommonResult<WeeklyReportRespVO> refreshWeeklyDraft(@Valid @RequestBody WeeklyReportRefreshDraftReqVO reqVO) {
|
||||
return success(weeklyReportService.refreshWeeklyDraft(reqVO));
|
||||
}
|
||||
|
||||
@PostMapping
|
||||
@Operation(summary = "新建周报草稿")
|
||||
@PreAuthorize("@ss.hasPermission('" + WorkReportConstants.PERMISSION_CREATE + "')")
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
package com.njcn.rdms.module.project.controller.admin.workreport.weekly.vo;
|
||||
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.common.vo.PersonalReportPlanItemReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.common.vo.PersonalReportReviewItemReqVO;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
import static com.njcn.rdms.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY;
|
||||
|
||||
@Schema(description = "管理后台 - 周报手动刷新默认稿 Request VO")
|
||||
@Data
|
||||
public class WeeklyReportRefreshDraftReqVO {
|
||||
|
||||
@NotBlank(message = "周期编码不能为空")
|
||||
private String periodKey;
|
||||
|
||||
@NotBlank(message = "周期名称不能为空")
|
||||
private String periodLabel;
|
||||
|
||||
@NotNull(message = "周期开始日期不能为空")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate periodStartDate;
|
||||
|
||||
@NotNull(message = "周期结束日期不能为空")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY)
|
||||
private LocalDate periodEndDate;
|
||||
|
||||
@NotNull(message = "是否出差不能为空")
|
||||
private Boolean isBusinessTrip;
|
||||
|
||||
@Valid
|
||||
private List<PersonalReportReviewItemReqVO> reviewItems;
|
||||
|
||||
@Valid
|
||||
private List<PersonalReportPlanItemReqVO> planItems;
|
||||
|
||||
@Valid
|
||||
private List<WeeklyReportTravelSegmentReqVO> travelSegments;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.njcn.rdms.module.project.dal.dataobject.job;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import com.njcn.rdms.framework.mybatis.core.dataobject.BaseDO;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* RDMS 任务运行日志表
|
||||
*/
|
||||
@TableName("rdms_work_report_job_run_log")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class JobRunLogDO extends BaseDO {
|
||||
|
||||
@TableId
|
||||
private Long id;
|
||||
|
||||
private String runId;
|
||||
|
||||
private String jobName;
|
||||
|
||||
private String jobStatus;
|
||||
|
||||
private LocalDate runDate;
|
||||
|
||||
private String periodKey;
|
||||
|
||||
private String triggerSource;
|
||||
|
||||
private String nodeName;
|
||||
|
||||
private LocalDateTime startedAt;
|
||||
|
||||
private LocalDateTime finishedAt;
|
||||
|
||||
private Integer successCount;
|
||||
|
||||
private Integer skipCount;
|
||||
|
||||
private Integer failCount;
|
||||
|
||||
private Long costMs;
|
||||
|
||||
private String message;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.njcn.rdms.module.project.dal.mysql.job;
|
||||
|
||||
import com.njcn.rdms.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.job.JobRunLogDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
@Mapper
|
||||
public interface JobRunLogMapper extends BaseMapperX<JobRunLogDO> {
|
||||
}
|
||||
@@ -65,6 +65,16 @@ public interface ProjectMapper extends BaseMapperX<ProjectDO> {
|
||||
.orderByDesc(BaseDO::getCreateTime));
|
||||
}
|
||||
|
||||
default List<ProjectDO> selectListByStatusCodesNotIn(Collection<String> statusCodes) {
|
||||
LambdaQueryWrapperX<ProjectDO> queryWrapper = new LambdaQueryWrapperX<>();
|
||||
queryWrapper.isNotNull(ProjectDO::getManagerUserId);
|
||||
queryWrapper.orderByDesc(BaseDO::getCreateTime);
|
||||
if (statusCodes != null && !statusCodes.isEmpty()) {
|
||||
queryWrapper.notIn(ProjectDO::getStatusCode, statusCodes);
|
||||
}
|
||||
return selectList(queryWrapper);
|
||||
}
|
||||
|
||||
default int updateStatusByIdAndStatus(Long id, String fromStatus, String toStatus, String lastStatusReason) {
|
||||
ProjectDO update = new ProjectDO();
|
||||
update.setStatusCode(toStatus);
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.njcn.rdms.module.project.service.workreport.autogen;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AutoGenPeriod {
|
||||
|
||||
private String periodKey;
|
||||
|
||||
private String periodLabel;
|
||||
|
||||
private LocalDate periodStartDate;
|
||||
|
||||
private LocalDate periodEndDate;
|
||||
|
||||
private Integer flag;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.njcn.rdms.module.project.service.workreport.autogen;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class AutoGenResult {
|
||||
|
||||
private LocalDateTime startedAt;
|
||||
|
||||
private LocalDateTime finishedAt;
|
||||
|
||||
private int successCount;
|
||||
|
||||
private int skipCount;
|
||||
|
||||
private int failCount;
|
||||
|
||||
private final List<String> failMessages = new ArrayList<>();
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.njcn.rdms.module.project.service.workreport.autogen;
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "rdms.work-report.auto-gen")
|
||||
@Data
|
||||
public class WorkReportAutoGenProperties {
|
||||
|
||||
private boolean enabled = false;
|
||||
|
||||
private TriggerProperties weekly = new TriggerProperties();
|
||||
|
||||
private TriggerProperties monthly = new TriggerProperties();
|
||||
|
||||
private TriggerProperties project = new TriggerProperties();
|
||||
|
||||
private ScopeProperties scope = new ScopeProperties();
|
||||
|
||||
@Data
|
||||
public static class TriggerProperties {
|
||||
|
||||
private boolean enabled = false;
|
||||
|
||||
private String cron;
|
||||
}
|
||||
|
||||
@Data
|
||||
public static class ScopeProperties {
|
||||
|
||||
private List<Long> deptIds = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.njcn.rdms.module.project.service.workreport.autogen;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class WorkReportAutoGenerateScheduler {
|
||||
|
||||
@Resource
|
||||
private WorkReportAutoGenerateService workReportAutoGenerateService;
|
||||
|
||||
@Scheduled(cron = "${rdms.work-report.auto-gen.weekly.cron:0 0 12 ? * FRI}", zone = "Asia/Shanghai")
|
||||
public void weekly() {
|
||||
workReportAutoGenerateService.autoGenerateWeeklyBySchedule();
|
||||
}
|
||||
|
||||
@Scheduled(cron = "${rdms.work-report.auto-gen.monthly.cron:0 0 12 1-31 * ?}", zone = "Asia/Shanghai")
|
||||
public void monthlyDaily() {
|
||||
workReportAutoGenerateService.autoGenerateMonthlyBySchedule();
|
||||
}
|
||||
|
||||
@Scheduled(cron = "${rdms.work-report.auto-gen.project.cron:0 0 12 1-31 * ?}", zone = "Asia/Shanghai")
|
||||
public void projectDaily() {
|
||||
workReportAutoGenerateService.autoGenerateProjectBySchedule();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,486 @@
|
||||
package com.njcn.rdms.module.project.service.workreport.autogen;
|
||||
|
||||
import com.njcn.rdms.framework.common.enums.UserTypeEnum;
|
||||
import com.njcn.rdms.framework.common.exception.ServiceException;
|
||||
import com.njcn.rdms.framework.common.pojo.CommonResult;
|
||||
import com.njcn.rdms.framework.common.util.json.JsonUtils;
|
||||
import com.njcn.rdms.framework.security.core.LoginUser;
|
||||
import com.njcn.rdms.module.project.constant.ProjectObjectConstants;
|
||||
import com.njcn.rdms.module.project.constant.WorkReportConstants;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.MonthlyReportSaveReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.ProjectReportSaveReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.weekly.vo.WeeklyReportSaveReqVO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.job.JobRunLogDO;
|
||||
import com.njcn.rdms.module.project.dal.dataobject.project.ProjectDO;
|
||||
import com.njcn.rdms.module.project.dal.mysql.job.JobRunLogMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.project.ProjectMapper;
|
||||
import com.njcn.rdms.module.project.dal.mysql.status.ObjectStatusModelMapper;
|
||||
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.enums.ErrorCodeConstants;
|
||||
import com.njcn.rdms.module.project.service.workreport.common.WorkReportCommonService;
|
||||
import com.njcn.rdms.module.system.api.dept.DeptApi;
|
||||
import com.njcn.rdms.module.system.api.dept.dto.DeptRespDTO;
|
||||
import com.njcn.rdms.module.system.api.user.AdminUserApi;
|
||||
import com.njcn.rdms.module.system.api.user.dto.AdminUserRespDTO;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.redisson.api.RLock;
|
||||
import org.redisson.api.RedissonClient;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.TemporalAdjusters;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Slf4j
|
||||
@Service
|
||||
public class WorkReportAutoGenerateService {
|
||||
|
||||
private static final ZoneId ASIA_SHANGHAI = ZoneId.of("Asia/Shanghai");
|
||||
private static final String TRIGGER_SOURCE_SCHEDULE = "SCHEDULE";
|
||||
private static final String STATUS_RUNNING = "RUNNING";
|
||||
private static final String STATUS_SUCCESS = "SUCCESS";
|
||||
private static final String STATUS_PARTIAL_SUCCESS = "PARTIAL_SUCCESS";
|
||||
private static final String STATUS_FAILED = "FAILED";
|
||||
private static final String JOB_NAME_WEEKLY = "WORK_REPORT_AUTO_GEN_WEEKLY";
|
||||
private static final String JOB_NAME_MONTHLY = "WORK_REPORT_AUTO_GEN_MONTHLY";
|
||||
private static final String JOB_NAME_PROJECT = "WORK_REPORT_AUTO_GEN_PROJECT";
|
||||
private static final String LOCK_KEY_TEMPLATE = "auto-gen:work-report:%s:%s:%s";
|
||||
private static final int MAX_FAIL_MESSAGES = 20;
|
||||
|
||||
@Resource
|
||||
private WorkReportAutoGenProperties properties;
|
||||
@Resource
|
||||
private WorkReportCommonService workReportCommonService;
|
||||
@Resource
|
||||
private WeeklyReportMapper weeklyReportMapper;
|
||||
@Resource
|
||||
private MonthlyReportMapper monthlyReportMapper;
|
||||
@Resource
|
||||
private ProjectReportMapper projectReportMapper;
|
||||
@Resource
|
||||
private ProjectMapper projectMapper;
|
||||
@Resource
|
||||
private ObjectStatusModelMapper objectStatusModelMapper;
|
||||
@Resource
|
||||
private JobRunLogMapper jobRunLogMapper;
|
||||
@Resource
|
||||
private DeptApi deptApi;
|
||||
@Resource
|
||||
private AdminUserApi adminUserApi;
|
||||
@Resource
|
||||
private RedissonClient redissonClient;
|
||||
|
||||
public void autoGenerateWeeklyBySchedule() {
|
||||
if (!properties.isEnabled() || !properties.getWeekly().isEnabled()) {
|
||||
return;
|
||||
}
|
||||
LocalDate today = LocalDate.now(ASIA_SHANGHAI);
|
||||
AutoGenPeriod period = buildWeeklyPeriod(today);
|
||||
runAs(buildSystemLoginUser(), () -> executeWeekly(period, today));
|
||||
}
|
||||
|
||||
public void autoGenerateMonthlyBySchedule() {
|
||||
if (!properties.isEnabled() || !properties.getMonthly().isEnabled()) {
|
||||
return;
|
||||
}
|
||||
LocalDate today = LocalDate.now(ASIA_SHANGHAI);
|
||||
if (!today.equals(today.with(TemporalAdjusters.lastDayOfMonth()))) {
|
||||
return;
|
||||
}
|
||||
AutoGenPeriod period = buildMonthlyPeriod(today);
|
||||
runAs(buildSystemLoginUser(), () -> executeMonthly(period, today));
|
||||
}
|
||||
|
||||
public void autoGenerateProjectBySchedule() {
|
||||
if (!properties.isEnabled() || !properties.getProject().isEnabled()) {
|
||||
return;
|
||||
}
|
||||
LocalDate today = LocalDate.now(ASIA_SHANGHAI);
|
||||
if (today.getDayOfMonth() != 15) {
|
||||
return;
|
||||
}
|
||||
AutoGenPeriod period = buildProjectFirstHalfPeriod(today);
|
||||
runAs(buildSystemLoginUser(), () -> executeProject(period, today));
|
||||
}
|
||||
|
||||
private void executeWeekly(AutoGenPeriod period, LocalDate runDate) {
|
||||
JobRunLogDO jobLog = createRunningJobLog(JOB_NAME_WEEKLY, runDate, period.getPeriodKey());
|
||||
AutoGenResult result = new AutoGenResult();
|
||||
result.setStartedAt(jobLog.getStartedAt());
|
||||
try {
|
||||
for (AdminUserRespDTO user : loadRdUsers()) {
|
||||
processWeeklyUser(period, result, user);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
appendFailMessage(result, "job=" + JOB_NAME_WEEKLY + ", message=" + ex.getMessage());
|
||||
log.error("[executeWeekly][periodKey={}]", period.getPeriodKey(), ex);
|
||||
} finally {
|
||||
finishJobLog(jobLog, result);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeMonthly(AutoGenPeriod period, LocalDate runDate) {
|
||||
JobRunLogDO jobLog = createRunningJobLog(JOB_NAME_MONTHLY, runDate, period.getPeriodKey());
|
||||
AutoGenResult result = new AutoGenResult();
|
||||
result.setStartedAt(jobLog.getStartedAt());
|
||||
try {
|
||||
for (AdminUserRespDTO user : loadRdUsers()) {
|
||||
processMonthlyUser(period, result, user);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
appendFailMessage(result, "job=" + JOB_NAME_MONTHLY + ", message=" + ex.getMessage());
|
||||
log.error("[executeMonthly][periodKey={}]", period.getPeriodKey(), ex);
|
||||
} finally {
|
||||
finishJobLog(jobLog, result);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeProject(AutoGenPeriod period, LocalDate runDate) {
|
||||
JobRunLogDO jobLog = createRunningJobLog(JOB_NAME_PROJECT, runDate, period.getPeriodKey());
|
||||
AutoGenResult result = new AutoGenResult();
|
||||
result.setStartedAt(jobLog.getStartedAt());
|
||||
try {
|
||||
for (ProjectAutoGenCandidate candidate : loadProjectCandidates()) {
|
||||
processProjectCandidate(period, result, candidate);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
appendFailMessage(result, "job=" + JOB_NAME_PROJECT + ", message=" + ex.getMessage());
|
||||
log.error("[executeProject][periodKey={}]", period.getPeriodKey(), ex);
|
||||
} finally {
|
||||
finishJobLog(jobLog, result);
|
||||
}
|
||||
}
|
||||
|
||||
private void processWeeklyUser(AutoGenPeriod period, AutoGenResult result, AdminUserRespDTO user) {
|
||||
String subjectKey = String.valueOf(user.getId());
|
||||
executeWithLock(WorkReportConstants.REPORT_TYPE_WEEKLY, period.getPeriodKey(), subjectKey, result, () -> {
|
||||
if (weeklyReportMapper.selectByReporterIdAndPeriodKey(user.getId(), period.getPeriodKey()) != null) {
|
||||
result.setSkipCount(result.getSkipCount() + 1);
|
||||
return;
|
||||
}
|
||||
WeeklyReportSaveReqVO reqVO = new WeeklyReportSaveReqVO();
|
||||
reqVO.setPeriodKey(period.getPeriodKey());
|
||||
reqVO.setPeriodLabel(period.getPeriodLabel());
|
||||
reqVO.setPeriodStartDate(period.getPeriodStartDate());
|
||||
reqVO.setPeriodEndDate(period.getPeriodEndDate());
|
||||
reqVO.setIsBusinessTrip(Boolean.FALSE);
|
||||
reqVO.setReviewItems(Collections.emptyList());
|
||||
reqVO.setPlanItems(Collections.emptyList());
|
||||
reqVO.setTravelSegments(Collections.emptyList());
|
||||
runAs(buildLoginUser(user), () -> workReportCommonService.createWeeklyReport(reqVO, user.getId()));
|
||||
result.setSuccessCount(result.getSuccessCount() + 1);
|
||||
}, () -> "userId=" + user.getId());
|
||||
}
|
||||
|
||||
private void processMonthlyUser(AutoGenPeriod period, AutoGenResult result, AdminUserRespDTO user) {
|
||||
String subjectKey = String.valueOf(user.getId());
|
||||
executeWithLock(WorkReportConstants.REPORT_TYPE_MONTHLY, period.getPeriodKey(), subjectKey, result, () -> {
|
||||
if (monthlyReportMapper.selectByReporterIdAndPeriodKey(user.getId(), period.getPeriodKey()) != null) {
|
||||
result.setSkipCount(result.getSkipCount() + 1);
|
||||
return;
|
||||
}
|
||||
MonthlyReportSaveReqVO reqVO = new MonthlyReportSaveReqVO();
|
||||
reqVO.setPeriodKey(period.getPeriodKey());
|
||||
reqVO.setPeriodLabel(period.getPeriodLabel());
|
||||
reqVO.setPeriodStartDate(period.getPeriodStartDate());
|
||||
reqVO.setPeriodEndDate(period.getPeriodEndDate());
|
||||
reqVO.setReviewItems(Collections.emptyList());
|
||||
reqVO.setPlanItems(Collections.emptyList());
|
||||
runAs(buildLoginUser(user), () -> workReportCommonService.createMonthlyReport(reqVO, user.getId()));
|
||||
result.setSuccessCount(result.getSuccessCount() + 1);
|
||||
}, () -> "userId=" + user.getId());
|
||||
}
|
||||
|
||||
private void processProjectCandidate(AutoGenPeriod period, AutoGenResult result, ProjectAutoGenCandidate candidate) {
|
||||
String subjectKey = candidate.projectId() + ":" + candidate.user().getId();
|
||||
executeWithLock(WorkReportConstants.REPORT_TYPE_PROJECT, period.getPeriodKey(), subjectKey, result, () -> {
|
||||
if (projectReportMapper.selectByProjectIdAndPeriodKeyAndProjectOwnerId(
|
||||
candidate.projectId(), period.getPeriodKey(), candidate.user().getId()) != null) {
|
||||
result.setSkipCount(result.getSkipCount() + 1);
|
||||
return;
|
||||
}
|
||||
ProjectReportSaveReqVO reqVO = new ProjectReportSaveReqVO();
|
||||
reqVO.setProjectId(candidate.projectId());
|
||||
reqVO.setPeriodKey(period.getPeriodKey());
|
||||
reqVO.setPeriodLabel(period.getPeriodLabel());
|
||||
reqVO.setPeriodStartDate(period.getPeriodStartDate());
|
||||
reqVO.setPeriodEndDate(period.getPeriodEndDate());
|
||||
reqVO.setFlag(period.getFlag());
|
||||
reqVO.setCurrentItems(Collections.emptyList());
|
||||
reqVO.setNextItems(Collections.emptyList());
|
||||
runAs(buildLoginUser(candidate.user()), () -> workReportCommonService.createProjectReport(reqVO, candidate.user().getId()));
|
||||
result.setSuccessCount(result.getSuccessCount() + 1);
|
||||
}, () -> "projectId=" + candidate.projectId() + ", userId=" + candidate.user().getId());
|
||||
}
|
||||
|
||||
private void executeWithLock(String reportType, String periodKey, String subjectKey, AutoGenResult result,
|
||||
Runnable action, Supplier<String> failContextSupplier) {
|
||||
RLock lock = redissonClient.getLock(String.format(LOCK_KEY_TEMPLATE, reportType, periodKey, subjectKey));
|
||||
try {
|
||||
if (!lock.tryLock(0, 30, TimeUnit.SECONDS)) {
|
||||
result.setSkipCount(result.getSkipCount() + 1);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
action.run();
|
||||
} catch (ServiceException ex) {
|
||||
if (Objects.equals(ex.getCode(), ErrorCodeConstants.WORK_REPORT_PERIOD_DUPLICATE.getCode())) {
|
||||
result.setSkipCount(result.getSkipCount() + 1);
|
||||
return;
|
||||
}
|
||||
result.setFailCount(result.getFailCount() + 1);
|
||||
appendFailMessage(result, failContextSupplier.get() + ", code=" + ex.getCode() + ", message=" + ex.getMessage());
|
||||
log.error("[executeWithLock][reportType={}][periodKey={}][subjectKey={}]", reportType, periodKey, subjectKey, ex);
|
||||
} catch (Exception ex) {
|
||||
result.setFailCount(result.getFailCount() + 1);
|
||||
appendFailMessage(result, failContextSupplier.get() + ", message=" + ex.getMessage());
|
||||
log.error("[executeWithLock][reportType={}][periodKey={}][subjectKey={}]", reportType, periodKey, subjectKey, ex);
|
||||
}
|
||||
} catch (InterruptedException ex) {
|
||||
Thread.currentThread().interrupt();
|
||||
result.setFailCount(result.getFailCount() + 1);
|
||||
appendFailMessage(result, failContextSupplier.get() + ", message=lock interrupted");
|
||||
} finally {
|
||||
if (lock.isHeldByCurrentThread()) {
|
||||
lock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private List<AdminUserRespDTO> loadRdUsers() {
|
||||
List<Long> rootDeptIds = properties.getScope().getDeptIds();
|
||||
if (rootDeptIds == null || rootDeptIds.isEmpty()) {
|
||||
log.warn("[loadRdUsers][未配置 rdms.work-report.auto-gen.scope.dept-ids,自动生成功能跳过]");
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Set<Long> deptIds = new LinkedHashSet<>();
|
||||
for (Long rootDeptId : rootDeptIds) {
|
||||
if (rootDeptId == null) {
|
||||
continue;
|
||||
}
|
||||
deptIds.add(rootDeptId);
|
||||
CommonResult<List<DeptRespDTO>> childResult = deptApi.getChildDeptList(rootDeptId);
|
||||
List<DeptRespDTO> childDepts = childResult == null || childResult.getCheckedData() == null
|
||||
? Collections.emptyList()
|
||||
: childResult.getCheckedData();
|
||||
for (DeptRespDTO dept : childDepts) {
|
||||
if (dept != null && dept.getId() != null) {
|
||||
deptIds.add(dept.getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (deptIds.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
CommonResult<List<AdminUserRespDTO>> result = adminUserApi.getUserListByDeptIds(deptIds);
|
||||
List<AdminUserRespDTO> users = result == null || result.getCheckedData() == null
|
||||
? Collections.emptyList()
|
||||
: result.getCheckedData();
|
||||
Map<Long, AdminUserRespDTO> deduplicated = new LinkedHashMap<>();
|
||||
for (AdminUserRespDTO user : users) {
|
||||
if (user == null || user.getId() == null || !Objects.equals(user.getStatus(), 0)) {
|
||||
continue;
|
||||
}
|
||||
deduplicated.put(user.getId(), user);
|
||||
}
|
||||
return new ArrayList<>(deduplicated.values());
|
||||
}
|
||||
|
||||
private List<ProjectAutoGenCandidate> loadProjectCandidates() {
|
||||
List<String> terminalStatusCodes = objectStatusModelMapper
|
||||
.selectTerminalStatusCodesByObjectTypeEnabled(ProjectObjectConstants.OBJECT_TYPE);
|
||||
List<ProjectDO> projects = projectMapper.selectListByStatusCodesNotIn(terminalStatusCodes);
|
||||
if (projects == null || projects.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
Set<Long> managerUserIds = projects.stream()
|
||||
.map(ProjectDO::getManagerUserId)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
if (managerUserIds.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
CommonResult<List<AdminUserRespDTO>> result = adminUserApi.getUserList(managerUserIds);
|
||||
List<AdminUserRespDTO> users = result == null || result.getCheckedData() == null
|
||||
? Collections.emptyList()
|
||||
: result.getCheckedData();
|
||||
Map<Long, AdminUserRespDTO> userMap = users.stream()
|
||||
.filter(Objects::nonNull)
|
||||
.filter(user -> user.getId() != null)
|
||||
.collect(Collectors.toMap(AdminUserRespDTO::getId, user -> user, (left, right) -> left, LinkedHashMap::new));
|
||||
List<ProjectAutoGenCandidate> candidates = new ArrayList<>();
|
||||
for (ProjectDO project : projects) {
|
||||
if (project.getManagerUserId() == null) {
|
||||
continue;
|
||||
}
|
||||
AdminUserRespDTO user = userMap.get(project.getManagerUserId());
|
||||
if (user == null || !Objects.equals(user.getStatus(), 0)) {
|
||||
continue;
|
||||
}
|
||||
candidates.add(new ProjectAutoGenCandidate(project.getId(), user));
|
||||
}
|
||||
return candidates;
|
||||
}
|
||||
|
||||
private AutoGenPeriod buildWeeklyPeriod(LocalDate today) {
|
||||
LocalDate periodStartDate = today.minusDays(today.getDayOfWeek().getValue() - 1L);
|
||||
LocalDate periodEndDate = periodStartDate.plusDays(6);
|
||||
int week = periodStartDate.get(java.time.temporal.IsoFields.WEEK_OF_WEEK_BASED_YEAR);
|
||||
int year = periodStartDate.get(java.time.temporal.IsoFields.WEEK_BASED_YEAR);
|
||||
return new AutoGenPeriod()
|
||||
.setPeriodKey(String.format("%d-W%02d", year, week))
|
||||
.setPeriodLabel(String.format("%d 年第 %02d 周", year, week))
|
||||
.setPeriodStartDate(periodStartDate)
|
||||
.setPeriodEndDate(periodEndDate);
|
||||
}
|
||||
|
||||
private AutoGenPeriod buildMonthlyPeriod(LocalDate today) {
|
||||
return new AutoGenPeriod()
|
||||
.setPeriodKey(String.format("%d-%02d", today.getYear(), today.getMonthValue()))
|
||||
.setPeriodLabel(String.format("%d 年 %02d 月", today.getYear(), today.getMonthValue()))
|
||||
.setPeriodStartDate(today.withDayOfMonth(1))
|
||||
.setPeriodEndDate(today.withDayOfMonth(today.lengthOfMonth()));
|
||||
}
|
||||
|
||||
private AutoGenPeriod buildProjectFirstHalfPeriod(LocalDate today) {
|
||||
return new AutoGenPeriod()
|
||||
.setPeriodKey(String.format("%d-%02d-01", today.getYear(), today.getMonthValue()))
|
||||
.setPeriodLabel(String.format("%d 年 %02d 月 上半月", today.getYear(), today.getMonthValue()))
|
||||
.setPeriodStartDate(today.withDayOfMonth(1))
|
||||
.setPeriodEndDate(today.withDayOfMonth(15))
|
||||
.setFlag(1);
|
||||
}
|
||||
|
||||
private JobRunLogDO createRunningJobLog(String jobName, LocalDate runDate, String periodKey) {
|
||||
JobRunLogDO jobLog = new JobRunLogDO();
|
||||
jobLog.setRunId(UUID.randomUUID().toString().replace("-", ""));
|
||||
jobLog.setJobName(jobName);
|
||||
jobLog.setJobStatus(STATUS_RUNNING);
|
||||
jobLog.setRunDate(runDate);
|
||||
jobLog.setPeriodKey(periodKey);
|
||||
jobLog.setTriggerSource(TRIGGER_SOURCE_SCHEDULE);
|
||||
jobLog.setNodeName(resolveNodeName());
|
||||
jobLog.setStartedAt(LocalDateTime.now(ASIA_SHANGHAI));
|
||||
jobLog.setSuccessCount(0);
|
||||
jobLog.setSkipCount(0);
|
||||
jobLog.setFailCount(0);
|
||||
jobRunLogMapper.insert(jobLog);
|
||||
return jobLog;
|
||||
}
|
||||
|
||||
private void finishJobLog(JobRunLogDO jobLog, AutoGenResult result) {
|
||||
LocalDateTime finishedAt = LocalDateTime.now(ASIA_SHANGHAI);
|
||||
result.setFinishedAt(finishedAt);
|
||||
jobLog.setFinishedAt(finishedAt);
|
||||
jobLog.setSuccessCount(result.getSuccessCount());
|
||||
jobLog.setSkipCount(result.getSkipCount());
|
||||
jobLog.setFailCount(result.getFailCount());
|
||||
jobLog.setCostMs(java.time.Duration.between(result.getStartedAt(), finishedAt).toMillis());
|
||||
jobLog.setJobStatus(resolveJobStatus(result));
|
||||
jobLog.setMessage(buildMessage(result.getFailMessages()));
|
||||
jobRunLogMapper.updateById(jobLog);
|
||||
}
|
||||
|
||||
private String resolveJobStatus(AutoGenResult result) {
|
||||
if (result.getFailCount() == 0) {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
if (result.getSuccessCount() > 0 || result.getSkipCount() > 0) {
|
||||
return STATUS_PARTIAL_SUCCESS;
|
||||
}
|
||||
return STATUS_FAILED;
|
||||
}
|
||||
|
||||
private String buildMessage(List<String> failMessages) {
|
||||
if (failMessages == null || failMessages.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
String message = JsonUtils.toJsonString(failMessages);
|
||||
return message.length() > 2000 ? message.substring(0, 2000) : message;
|
||||
}
|
||||
|
||||
private void appendFailMessage(AutoGenResult result, String message) {
|
||||
if (result.getFailMessages().size() >= MAX_FAIL_MESSAGES) {
|
||||
return;
|
||||
}
|
||||
result.getFailMessages().add(StringUtils.hasText(message) ? message : "unknown error");
|
||||
}
|
||||
|
||||
private LoginUser buildLoginUser(AdminUserRespDTO user) {
|
||||
LoginUser loginUser = new LoginUser();
|
||||
loginUser.setId(user.getId());
|
||||
loginUser.setUserType(UserTypeEnum.ADMIN.getValue());
|
||||
Map<String, String> info = new LinkedHashMap<>();
|
||||
info.put(LoginUser.INFO_KEY_NICKNAME, safeText(user.getNickname()));
|
||||
if (user.getDeptId() != null) {
|
||||
info.put(LoginUser.INFO_KEY_DEPT_ID, String.valueOf(user.getDeptId()));
|
||||
}
|
||||
loginUser.setInfo(info);
|
||||
return loginUser;
|
||||
}
|
||||
|
||||
private LoginUser buildSystemLoginUser() {
|
||||
LoginUser loginUser = new LoginUser();
|
||||
loginUser.setId(0L);
|
||||
loginUser.setUserType(UserTypeEnum.ADMIN.getValue());
|
||||
Map<String, String> info = new LinkedHashMap<>();
|
||||
info.put(LoginUser.INFO_KEY_NICKNAME, "system");
|
||||
loginUser.setInfo(info);
|
||||
return loginUser;
|
||||
}
|
||||
|
||||
private void runAs(LoginUser loginUser, Runnable action) {
|
||||
runAs(loginUser, () -> {
|
||||
action.run();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private <T> T runAs(LoginUser loginUser, Supplier<T> supplier) {
|
||||
SecurityContext previousContext = SecurityContextHolder.getContext();
|
||||
SecurityContext context = SecurityContextHolder.createEmptyContext();
|
||||
context.setAuthentication(new UsernamePasswordAuthenticationToken(loginUser, null, Collections.emptyList()));
|
||||
SecurityContextHolder.setContext(context);
|
||||
try {
|
||||
return supplier.get();
|
||||
} finally {
|
||||
SecurityContextHolder.setContext(previousContext);
|
||||
}
|
||||
}
|
||||
|
||||
private String resolveNodeName() {
|
||||
try {
|
||||
return InetAddress.getLocalHost().getHostName();
|
||||
} catch (Exception ex) {
|
||||
return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
private String safeText(String value) {
|
||||
return value == null ? "" : value.trim();
|
||||
}
|
||||
|
||||
private record ProjectAutoGenCandidate(Long projectId, AdminUserRespDTO user) {
|
||||
}
|
||||
}
|
||||
@@ -166,8 +166,30 @@ public class WorkReportCommonService {
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createWeeklyReport(WeeklyReportSaveReqVO reqVO) {
|
||||
return createWeeklyReportInternal(reqVO, null);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createWeeklyReport(WeeklyReportSaveReqVO reqVO, Long overrideReporterId) {
|
||||
return createWeeklyReportInternal(reqVO, overrideReporterId);
|
||||
}
|
||||
|
||||
public WeeklyReportRespVO mergeWeeklyDraft(WeeklyReportRespVO latestDraft, WeeklyReportRefreshDraftReqVO reqVO) {
|
||||
WeeklyReportRespVO respVO = latestDraft;
|
||||
respVO.setIsBusinessTrip(Boolean.TRUE.equals(reqVO.getIsBusinessTrip()));
|
||||
respVO.setTravelSegments(BeanUtils.toBean(defaultList(reqVO.getTravelSegments()), WeeklyReportTravelSegmentRespVO.class));
|
||||
respVO.setReviewItems(mergeReviewItems(reqVO.getReviewItems(), latestDraft.getReviewItems()));
|
||||
respVO.setPlanItems(mergePlanItems(reqVO.getPlanItems(), latestDraft.getPlanItems()));
|
||||
respVO.setTotalTravelDays(Boolean.TRUE.equals(reqVO.getIsBusinessTrip())
|
||||
? defaultIfNull(sumTravelDays(reqVO.getTravelSegments()))
|
||||
: BigDecimal.ZERO);
|
||||
respVO.setTotalWorkHours(sumReviewWorkHoursResp(respVO.getReviewItems()));
|
||||
return respVO;
|
||||
}
|
||||
|
||||
private Long createWeeklyReportInternal(WeeklyReportSaveReqVO reqVO, Long overrideReporterId) {
|
||||
validatePeriod(reqVO.getPeriodStartDate(), reqVO.getPeriodEndDate());
|
||||
CurrentUserProfile profile = loadCurrentUserProfile(true);
|
||||
CurrentUserProfile profile = resolveProfile(overrideReporterId, true);
|
||||
validateWeeklyDuplicate(profile.userId(), reqVO.getPeriodKey(), null);
|
||||
|
||||
WeeklyReportDO report = new WeeklyReportDO();
|
||||
@@ -308,8 +330,25 @@ public class WorkReportCommonService {
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createMonthlyReport(MonthlyReportSaveReqVO reqVO) {
|
||||
return createMonthlyReportInternal(reqVO, null);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createMonthlyReport(MonthlyReportSaveReqVO reqVO, Long overrideReporterId) {
|
||||
return createMonthlyReportInternal(reqVO, overrideReporterId);
|
||||
}
|
||||
|
||||
public MonthlyReportRespVO mergeMonthlyDraft(MonthlyReportRespVO latestDraft, MonthlyReportRefreshDraftReqVO reqVO) {
|
||||
MonthlyReportRespVO respVO = latestDraft;
|
||||
respVO.setReviewItems(mergeReviewItems(reqVO.getReviewItems(), latestDraft.getReviewItems()));
|
||||
respVO.setPlanItems(mergePlanItems(reqVO.getPlanItems(), latestDraft.getPlanItems()));
|
||||
respVO.setTotalWorkHours(sumReviewWorkHoursResp(respVO.getReviewItems()));
|
||||
return respVO;
|
||||
}
|
||||
|
||||
private Long createMonthlyReportInternal(MonthlyReportSaveReqVO reqVO, Long overrideReporterId) {
|
||||
validatePeriod(reqVO.getPeriodStartDate(), reqVO.getPeriodEndDate());
|
||||
CurrentUserProfile profile = loadCurrentUserProfile(true);
|
||||
CurrentUserProfile profile = resolveProfile(overrideReporterId, true);
|
||||
validateMonthlyDuplicate(profile.userId(), reqVO.getPeriodKey(), null);
|
||||
|
||||
MonthlyReportDO report = new MonthlyReportDO();
|
||||
@@ -460,9 +499,30 @@ public class WorkReportCommonService {
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createProjectReport(ProjectReportSaveReqVO reqVO) {
|
||||
return createProjectReportInternal(reqVO, null);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createProjectReport(ProjectReportSaveReqVO reqVO, Long overrideReporterId) {
|
||||
return createProjectReportInternal(reqVO, overrideReporterId);
|
||||
}
|
||||
|
||||
public ProjectReportRespVO mergeProjectDraft(ProjectReportRespVO latestDraft, ProjectReportRefreshDraftReqVO reqVO) {
|
||||
ProjectReportRespVO respVO = latestDraft;
|
||||
respVO.setProjectStatusDesc(normalizeNullableText(reqVO.getProjectStatusDesc()));
|
||||
respVO.setProjectProgressPlan(normalizeNullableText(reqVO.getProjectProgressPlan()));
|
||||
respVO.setProjectKeyPoints(normalizeNullableText(reqVO.getProjectKeyPoints()));
|
||||
respVO.setProjectProblems(normalizeNullableText(reqVO.getProjectProblems()));
|
||||
respVO.setCurrentItems(mergeProjectItems(reqVO.getCurrentItems(), latestDraft.getCurrentItems()));
|
||||
respVO.setNextItems(mergeProjectItems(reqVO.getNextItems(), latestDraft.getNextItems()));
|
||||
respVO.setTotalWorkHours(sumProjectCurrentWorkHoursResp(respVO.getCurrentItems()));
|
||||
return respVO;
|
||||
}
|
||||
|
||||
private Long createProjectReportInternal(ProjectReportSaveReqVO reqVO, Long overrideReporterId) {
|
||||
validatePeriod(reqVO.getPeriodStartDate(), reqVO.getPeriodEndDate());
|
||||
validateProjectFlag(reqVO.getFlag());
|
||||
CurrentUserProfile profile = loadCurrentUserProfile(true);
|
||||
CurrentUserProfile profile = resolveProfile(overrideReporterId, true);
|
||||
validateProjectReportDuplicate(reqVO.getProjectId(), reqVO.getPeriodKey(), profile.userId(), null);
|
||||
ProjectDO project = validateProjectExists(reqVO.getProjectId());
|
||||
|
||||
@@ -827,12 +887,22 @@ public class WorkReportCommonService {
|
||||
}
|
||||
}
|
||||
|
||||
private CurrentUserProfile resolveProfile(Long overrideReporterId, boolean requireManager) {
|
||||
return overrideReporterId != null
|
||||
? loadUserProfile(overrideReporterId, null, requireManager)
|
||||
: loadCurrentUserProfile(requireManager);
|
||||
}
|
||||
|
||||
private CurrentUserProfile loadCurrentUserProfile(boolean requireManager) {
|
||||
Long userId = SecurityFrameworkUtils.getLoginUserId();
|
||||
return loadUserProfile(userId, SecurityFrameworkUtils.getLoginUserNickname(), requireManager);
|
||||
}
|
||||
|
||||
private CurrentUserProfile loadUserProfile(Long userId, String fallbackUserName, boolean requireManager) {
|
||||
AdminUserRespDTO user = loadUser(userId);
|
||||
String userName = StringUtils.hasText(user.getNickname())
|
||||
? user.getNickname().trim()
|
||||
: defaultText(SecurityFrameworkUtils.getLoginUserNickname());
|
||||
: defaultText(fallbackUserName);
|
||||
|
||||
String deptName = null;
|
||||
if (user.getDeptId() != null) {
|
||||
@@ -1010,6 +1080,74 @@ public class WorkReportCommonService {
|
||||
insertProjectNextItems(reportId, reqVO.getNextItems());
|
||||
}
|
||||
|
||||
private List<PersonalReportReviewItemRespVO> mergeReviewItems(List<PersonalReportReviewItemReqVO> currentItems,
|
||||
List<PersonalReportReviewItemRespVO> latestItems) {
|
||||
List<PersonalReportReviewItemRespVO> merged = BeanUtils.toBean(defaultList(currentItems),
|
||||
PersonalReportReviewItemRespVO.class);
|
||||
Set<String> existingKeys = merged.stream()
|
||||
.map(item -> normalizeMergeText(item.getItemTitle()))
|
||||
.filter(StringUtils::hasText)
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
for (PersonalReportReviewItemRespVO item : defaultList(latestItems)) {
|
||||
String key = normalizeMergeText(item.getItemTitle());
|
||||
if (StringUtils.hasText(key) && existingKeys.contains(key)) {
|
||||
continue;
|
||||
}
|
||||
merged.add(BeanUtils.toBean(item, PersonalReportReviewItemRespVO.class));
|
||||
if (StringUtils.hasText(key)) {
|
||||
existingKeys.add(key);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < merged.size(); i++) {
|
||||
merged.get(i).setItemNumber(i + 1);
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
private List<PersonalReportPlanItemRespVO> mergePlanItems(List<PersonalReportPlanItemReqVO> currentItems,
|
||||
List<PersonalReportPlanItemRespVO> latestItems) {
|
||||
List<PersonalReportPlanItemRespVO> merged = BeanUtils.toBean(defaultList(currentItems),
|
||||
PersonalReportPlanItemRespVO.class);
|
||||
Set<String> existingKeys = merged.stream()
|
||||
.map(item -> normalizeMergeText(item.getItemTitle()))
|
||||
.filter(StringUtils::hasText)
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
for (PersonalReportPlanItemRespVO item : defaultList(latestItems)) {
|
||||
String key = normalizeMergeText(item.getItemTitle());
|
||||
if (StringUtils.hasText(key) && existingKeys.contains(key)) {
|
||||
continue;
|
||||
}
|
||||
merged.add(BeanUtils.toBean(item, PersonalReportPlanItemRespVO.class));
|
||||
if (StringUtils.hasText(key)) {
|
||||
existingKeys.add(key);
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < merged.size(); i++) {
|
||||
merged.get(i).setItemNumber(i + 1);
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
private List<ProjectReportItemRespVO> mergeProjectItems(List<ProjectReportItemReqVO> currentItems,
|
||||
List<ProjectReportItemRespVO> latestItems) {
|
||||
List<ProjectReportItemRespVO> merged = BeanUtils.toBean(defaultList(currentItems), ProjectReportItemRespVO.class);
|
||||
Set<String> existingKeys = merged.stream()
|
||||
.map(item -> buildProjectItemMergeKey(item.getItemTitle(), item.getPriorityCode()))
|
||||
.filter(StringUtils::hasText)
|
||||
.collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
for (ProjectReportItemRespVO item : defaultList(latestItems)) {
|
||||
String key = buildProjectItemMergeKey(item.getItemTitle(), item.getPriorityCode());
|
||||
if (StringUtils.hasText(key) && existingKeys.contains(key)) {
|
||||
continue;
|
||||
}
|
||||
merged.add(BeanUtils.toBean(item, ProjectReportItemRespVO.class));
|
||||
if (StringUtils.hasText(key)) {
|
||||
existingKeys.add(key);
|
||||
}
|
||||
}
|
||||
return merged;
|
||||
}
|
||||
|
||||
private void insertReviewItems(String reportType, Long reportId, List<PersonalReportReviewItemReqVO> items) {
|
||||
List<PersonalReportReviewItemReqVO> source = defaultList(items);
|
||||
for (int i = 0; i < source.size(); i++) {
|
||||
@@ -1326,6 +1464,16 @@ public class WorkReportCommonService {
|
||||
return total.compareTo(BigDecimal.ZERO) == 0 ? null : total;
|
||||
}
|
||||
|
||||
private BigDecimal sumReviewWorkHoursResp(List<PersonalReportReviewItemRespVO> items) {
|
||||
BigDecimal total = BigDecimal.ZERO;
|
||||
for (PersonalReportReviewItemRespVO item : defaultList(items)) {
|
||||
if (item.getWorkHours() != null) {
|
||||
total = total.add(item.getWorkHours());
|
||||
}
|
||||
}
|
||||
return total.compareTo(BigDecimal.ZERO) == 0 ? null : total;
|
||||
}
|
||||
|
||||
private BigDecimal sumProjectCurrentWorkHours(List<ProjectReportItemReqVO> items) {
|
||||
BigDecimal total = BigDecimal.ZERO;
|
||||
for (ProjectReportItemReqVO item : defaultList(items)) {
|
||||
@@ -1336,6 +1484,16 @@ public class WorkReportCommonService {
|
||||
return total.compareTo(BigDecimal.ZERO) == 0 ? null : total;
|
||||
}
|
||||
|
||||
private BigDecimal sumProjectCurrentWorkHoursResp(List<ProjectReportItemRespVO> items) {
|
||||
BigDecimal total = BigDecimal.ZERO;
|
||||
for (ProjectReportItemRespVO item : defaultList(items)) {
|
||||
if (item.getWorkHours() != null) {
|
||||
total = total.add(item.getWorkHours());
|
||||
}
|
||||
}
|
||||
return total.compareTo(BigDecimal.ZERO) == 0 ? null : total;
|
||||
}
|
||||
|
||||
private BigDecimal sumTravelDays(List<WeeklyReportTravelSegmentReqVO> items) {
|
||||
BigDecimal total = BigDecimal.ZERO;
|
||||
for (WeeklyReportTravelSegmentReqVO item : defaultList(items)) {
|
||||
@@ -1376,6 +1534,23 @@ public class WorkReportCommonService {
|
||||
return value.trim();
|
||||
}
|
||||
|
||||
private String normalizeMergeText(String value) {
|
||||
return StringUtils.hasText(value) ? value.trim() : null;
|
||||
}
|
||||
|
||||
private String buildProjectItemMergeKey(String itemTitle, String priorityCode) {
|
||||
String normalizedTitle = normalizeMergeText(itemTitle);
|
||||
String normalizedPriorityCode = normalizeMergeText(priorityCode);
|
||||
if (!StringUtils.hasText(normalizedTitle)) {
|
||||
return null;
|
||||
}
|
||||
return normalizedTitle + "||" + defaultText(normalizedPriorityCode);
|
||||
}
|
||||
|
||||
private BigDecimal defaultIfNull(BigDecimal value) {
|
||||
return value == null ? BigDecimal.ZERO : value;
|
||||
}
|
||||
|
||||
private String defaultText(String value) {
|
||||
return StringUtils.hasText(value) ? value.trim() : "";
|
||||
}
|
||||
@@ -1387,4 +1562,4 @@ public class WorkReportCommonService {
|
||||
private record CurrentUserProfile(Long userId, String userName, String deptName, String postName,
|
||||
Long directManagerId, String directManagerName) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.Month
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.MonthlyReportDefaultDraftReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.MonthlyReportExportVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.MonthlyReportPageReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.MonthlyReportRefreshDraftReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.MonthlyReportRespVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.MonthlyReportSaveReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.common.vo.WorkReportStatusActionReqVO;
|
||||
@@ -19,6 +20,8 @@ public interface MonthlyReportService {
|
||||
|
||||
MonthlyReportRespVO previewMonthlyDefaultDraft(MonthlyReportDefaultDraftReqVO reqVO);
|
||||
|
||||
MonthlyReportRespVO refreshMonthlyDraft(MonthlyReportRefreshDraftReqVO reqVO);
|
||||
|
||||
Long createMonthlyReport(MonthlyReportSaveReqVO reqVO);
|
||||
|
||||
void updateMonthlyReport(Long id, MonthlyReportSaveReqVO reqVO);
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.Month
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.MonthlyReportDefaultDraftReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.MonthlyReportExportVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.MonthlyReportPageReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.MonthlyReportRefreshDraftReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.MonthlyReportRespVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.monthly.vo.MonthlyReportSaveReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.common.vo.WorkReportStatusActionReqVO;
|
||||
@@ -35,9 +36,20 @@ public class MonthlyReportServiceImpl implements MonthlyReportService {
|
||||
return workReportDefaultDraftService.previewMonthlyDefaultDraft(reqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MonthlyReportRespVO refreshMonthlyDraft(MonthlyReportRefreshDraftReqVO reqVO) {
|
||||
MonthlyReportDefaultDraftReqVO draftReqVO = new MonthlyReportDefaultDraftReqVO();
|
||||
draftReqVO.setPeriodKey(reqVO.getPeriodKey());
|
||||
draftReqVO.setPeriodLabel(reqVO.getPeriodLabel());
|
||||
draftReqVO.setPeriodStartDate(reqVO.getPeriodStartDate());
|
||||
draftReqVO.setPeriodEndDate(reqVO.getPeriodEndDate());
|
||||
MonthlyReportRespVO latestDraft = workReportDefaultDraftService.previewMonthlyDefaultDraft(draftReqVO);
|
||||
return workReportCommonService.mergeMonthlyDraft(latestDraft, reqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long createMonthlyReport(MonthlyReportSaveReqVO reqVO) {
|
||||
return workReportCommonService.createMonthlyReport(reqVO);
|
||||
return workReportCommonService.createMonthlyReport(reqVO, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.Proje
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.ProjectReportDefaultDraftReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.ProjectReportOwnerProjectOptionRespVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.ProjectReportPageReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.ProjectReportRefreshDraftReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.ProjectReportRespVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.ProjectReportSaveReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.common.vo.WorkReportApprovalRecordRespVO;
|
||||
@@ -21,6 +22,8 @@ public interface ProjectReportService {
|
||||
|
||||
ProjectReportRespVO previewProjectDefaultDraft(Long projectId, ProjectReportDefaultDraftReqVO reqVO);
|
||||
|
||||
ProjectReportRespVO refreshProjectDraft(Long projectId, ProjectReportRefreshDraftReqVO reqVO);
|
||||
|
||||
Long createProjectReport(ProjectReportSaveReqVO reqVO);
|
||||
|
||||
void updateProjectReport(Long id, ProjectReportSaveReqVO reqVO);
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.Proje
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.ProjectReportDefaultDraftReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.ProjectReportOwnerProjectOptionRespVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.ProjectReportPageReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.ProjectReportRefreshDraftReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.ProjectReportRespVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.project.vo.ProjectReportSaveReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.common.vo.WorkReportApprovalRecordRespVO;
|
||||
@@ -42,10 +43,23 @@ public class ProjectReportServiceImpl implements ProjectReportService {
|
||||
return workReportDefaultDraftService.previewProjectDefaultDraft(projectId, reqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectReportRespVO refreshProjectDraft(Long projectId, ProjectReportRefreshDraftReqVO reqVO) {
|
||||
workReportCommonService.validateCurrentUserIsProjectReportProjectOwner(projectId);
|
||||
ProjectReportDefaultDraftReqVO draftReqVO = new ProjectReportDefaultDraftReqVO();
|
||||
draftReqVO.setPeriodKey(reqVO.getPeriodKey());
|
||||
draftReqVO.setPeriodLabel(reqVO.getPeriodLabel());
|
||||
draftReqVO.setPeriodStartDate(reqVO.getPeriodStartDate());
|
||||
draftReqVO.setPeriodEndDate(reqVO.getPeriodEndDate());
|
||||
draftReqVO.setFlag(reqVO.getFlag());
|
||||
ProjectReportRespVO latestDraft = workReportDefaultDraftService.previewProjectDefaultDraft(projectId, draftReqVO);
|
||||
return workReportCommonService.mergeProjectDraft(latestDraft, reqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long createProjectReport(ProjectReportSaveReqVO reqVO) {
|
||||
workReportCommonService.validateCurrentUserIsProjectReportProjectOwner(reqVO.getProjectId());
|
||||
return workReportCommonService.createProjectReport(reqVO);
|
||||
return workReportCommonService.createProjectReport(reqVO, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.njcn.rdms.framework.common.pojo.PageResult;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.weekly.vo.WeeklyReportExportVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.weekly.vo.WeeklyReportDefaultDraftReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.weekly.vo.WeeklyReportPageReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.weekly.vo.WeeklyReportRefreshDraftReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.weekly.vo.WeeklyReportRespVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.weekly.vo.WeeklyReportSaveReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.common.vo.WorkReportApprovalRecordRespVO;
|
||||
@@ -18,6 +19,8 @@ public interface WeeklyReportService {
|
||||
|
||||
WeeklyReportRespVO previewWeeklyDefaultDraft(WeeklyReportDefaultDraftReqVO reqVO);
|
||||
|
||||
WeeklyReportRespVO refreshWeeklyDraft(WeeklyReportRefreshDraftReqVO reqVO);
|
||||
|
||||
Long createWeeklyReport(WeeklyReportSaveReqVO reqVO);
|
||||
|
||||
void updateWeeklyReport(Long id, WeeklyReportSaveReqVO reqVO);
|
||||
|
||||
@@ -4,6 +4,7 @@ import com.njcn.rdms.framework.common.pojo.PageResult;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.weekly.vo.WeeklyReportExportVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.weekly.vo.WeeklyReportDefaultDraftReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.weekly.vo.WeeklyReportPageReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.weekly.vo.WeeklyReportRefreshDraftReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.weekly.vo.WeeklyReportRespVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.weekly.vo.WeeklyReportSaveReqVO;
|
||||
import com.njcn.rdms.module.project.controller.admin.workreport.common.vo.WorkReportApprovalRecordRespVO;
|
||||
@@ -34,9 +35,20 @@ public class WeeklyReportServiceImpl implements WeeklyReportService {
|
||||
return workReportDefaultDraftService.previewWeeklyDefaultDraft(reqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeeklyReportRespVO refreshWeeklyDraft(WeeklyReportRefreshDraftReqVO reqVO) {
|
||||
WeeklyReportDefaultDraftReqVO draftReqVO = new WeeklyReportDefaultDraftReqVO();
|
||||
draftReqVO.setPeriodKey(reqVO.getPeriodKey());
|
||||
draftReqVO.setPeriodLabel(reqVO.getPeriodLabel());
|
||||
draftReqVO.setPeriodStartDate(reqVO.getPeriodStartDate());
|
||||
draftReqVO.setPeriodEndDate(reqVO.getPeriodEndDate());
|
||||
WeeklyReportRespVO latestDraft = workReportDefaultDraftService.previewWeeklyDefaultDraft(draftReqVO);
|
||||
return workReportCommonService.mergeWeeklyDraft(latestDraft, reqVO);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long createWeeklyReport(WeeklyReportSaveReqVO reqVO) {
|
||||
return workReportCommonService.createWeeklyReport(reqVO);
|
||||
return workReportCommonService.createWeeklyReport(reqVO, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -106,5 +106,19 @@ rdms:
|
||||
email: dev@example.com
|
||||
license: Apache 2.0
|
||||
license-url: https://www.apache.org/licenses/LICENSE-2.0.html
|
||||
work-report:
|
||||
auto-gen:
|
||||
enabled: true
|
||||
weekly:
|
||||
enabled: true
|
||||
cron: "0 0 12 ? * FRI"
|
||||
monthly:
|
||||
enabled: true
|
||||
cron: "0 0 12 1-31 * ?"
|
||||
project:
|
||||
enabled: true
|
||||
cron: "0 0 12 1-31 * ?"
|
||||
scope:
|
||||
dept-ids: [101]
|
||||
|
||||
debug: false
|
||||
|
||||
Reference in New Issue
Block a user