Compare commits
No commits in common. '3ce8e1c59f3cf5aaadef5cc24cf98ff22206c502' and 'e4842142a613d6e6ae0175a34347861f267d1284' have entirely different histories.
3ce8e1c59f
...
e4842142a6
48 changed files with 1144 additions and 3683 deletions
@ -1,58 +0,0 @@
|
||||
package com.biutag.supervision.job; |
||||
|
||||
import lombok.RequiredArgsConstructor; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.scheduling.annotation.Scheduled; |
||||
import org.springframework.stereotype.Component; |
||||
|
||||
import java.time.LocalDate; |
||||
import java.time.LocalDateTime; |
||||
|
||||
import com.biutag.supervision.service.MailBoxCaptureService; |
||||
|
||||
/** |
||||
* @ClassName MailBoxCaptureJob |
||||
* @Description 局长信箱数据抓取定时任务 |
||||
* - 阶段1(每天2点):抓取来信,创建 Negative + ComplaintCollection |
||||
* - 阶段2(每天3点):同步涉及人和核查附件 |
||||
* @Author shihao |
||||
* @Date 2026/4/28 |
||||
*/ |
||||
@Slf4j |
||||
@RequiredArgsConstructor |
||||
@Component |
||||
public class MailBoxCaptureJob { |
||||
|
||||
private final MailBoxCaptureService mailBoxCaptureService; |
||||
|
||||
/** |
||||
* 阶段1:抓取来信 |
||||
* 每天凌晨2点执行 |
||||
*/ |
||||
@Scheduled(cron = "0 0 2 * * ?") |
||||
public void mailBoxCaptureCompletedToNegative() { |
||||
LocalDateTime start = LocalDate.now().minusDays(1).atStartOfDay(); |
||||
LocalDateTime end = LocalDate.now().atStartOfDay(); |
||||
mailBoxCaptureService.captureMayorMailbox(start, end); |
||||
} |
||||
|
||||
/** |
||||
* 阶段2:同步涉及人和核查附件 |
||||
* 每天凌晨3点执行 |
||||
*/ |
||||
@Scheduled(cron = "0 0 4 * * ?") |
||||
public void syncBlameAndFilesForCompletedMails() { |
||||
LocalDateTime start = LocalDate.now().minusDays(1).atStartOfDay(); |
||||
LocalDateTime end = LocalDate.now().atStartOfDay(); |
||||
mailBoxCaptureService.syncBlameAndFiles(start, end); |
||||
} |
||||
|
||||
/** |
||||
* 阶段3:同步延期信息(初核工作开展情况、初核附件) |
||||
* 每天凌晨4点执行 |
||||
*/ |
||||
@Scheduled(cron = "0 0 3 * * ?") |
||||
public void syncExtension() { |
||||
mailBoxCaptureService.syncExtension(); |
||||
} |
||||
} |
||||
@ -1,16 +0,0 @@
|
||||
package com.biutag.supervision.mapper; |
||||
|
||||
import com.baomidou.dynamic.datasource.annotation.DS; |
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
||||
import com.biutag.supervision.pojo.entity.mailbox.MailExtension; |
||||
|
||||
/** |
||||
* @ClassName MailExtensionMapper |
||||
* @Description 局长信箱延期表Mapper |
||||
* @Author auto-generate |
||||
* @Date 2026/4/29 |
||||
*/ |
||||
@DS("mailbox") |
||||
public interface MailExtensionMapper extends BaseMapper<MailExtension> { |
||||
|
||||
} |
||||
@ -1,29 +0,0 @@
|
||||
package com.biutag.supervision.pojo.dto; |
||||
|
||||
import com.biutag.supervision.pojo.entity.ComplaintCollection; |
||||
import com.biutag.supervision.pojo.entity.mailbox.Mail; |
||||
import com.biutag.supervision.pojo.entity.mailbox.MailBlame; |
||||
import io.swagger.v3.oas.annotations.media.Schema; |
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
import java.util.List; |
||||
|
||||
/** |
||||
* 局长信箱阶段2同步数据DTO |
||||
* 用于在循环内传递同步所需的数据 |
||||
*/ |
||||
@Getter |
||||
@Setter |
||||
@Schema(description = "局长信箱阶段2同步数据DTO") |
||||
public class MailBoxSyncDto { |
||||
|
||||
@Schema(description = "投诉举报收集表记录") |
||||
private ComplaintCollection cc; |
||||
|
||||
@Schema(description = "局长信箱邮件数据") |
||||
private Mail mail; |
||||
|
||||
@Schema(description = "涉及人列表") |
||||
private List<MailBlame> mailBlames; |
||||
} |
||||
@ -1,361 +0,0 @@
|
||||
package com.biutag.supervision.pojo.dto; |
||||
|
||||
import com.biutag.supervision.constants.enums.ProblemSourcesEnum; |
||||
import com.biutag.supervision.pojo.dto.flow.VerifyData; |
||||
import com.biutag.supervision.pojo.entity.NegativeBlame; |
||||
import com.biutag.supervision.pojo.entity.NegativeFile; |
||||
import com.biutag.supervision.pojo.entity.NegativeThingFile; |
||||
import com.fasterxml.jackson.annotation.JsonFormat; |
||||
import io.swagger.v3.oas.annotations.media.Schema; |
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
import java.time.LocalDateTime; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Negative纯数据保存DTO - 所有字段通过传参,不写死任何值 |
||||
*/ |
||||
@Setter |
||||
@Getter |
||||
@Schema(description = "Negative纯数据保存DTO") |
||||
public class NegativeDataOnlyDto { |
||||
|
||||
// ========== Negative主表所有字段 ==========
|
||||
|
||||
@Schema(description = "主键(可传可不传,不传则自动生成)") |
||||
private String id; |
||||
|
||||
@Schema(description = "样本来源编号") |
||||
private String originId; |
||||
|
||||
@Schema(description = "编号") |
||||
private String serialNumber; |
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm") |
||||
@Schema(description = "问题发生时间") |
||||
private LocalDateTime happenTime; |
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm") |
||||
@Schema(description = "问题发现时间") |
||||
private LocalDateTime discoveryTime; |
||||
|
||||
/** |
||||
* @see ProblemSourcesEnum |
||||
*/ |
||||
@Schema(description = "问题来源code") |
||||
private String problemSourcesCode; |
||||
/** |
||||
* @see ProblemSourcesEnum |
||||
*/ |
||||
|
||||
@Schema(description = "问题来源") |
||||
private String problemSources; |
||||
|
||||
@Schema(description = "业务类型code") |
||||
private String businessTypeCode; |
||||
|
||||
@Schema(description = "业务类别名称") |
||||
private String businessTypeName; |
||||
|
||||
@Schema(description = "涉嫌问题(列表,会转成逗号分隔字符串)") |
||||
private List<String> involveProblem = new ArrayList<>(); |
||||
|
||||
@Schema(description = "涉及警种名称") |
||||
private String policeTypeName; |
||||
|
||||
@Schema(description = "涉及警种") |
||||
private String policeType; |
||||
|
||||
@Schema(description = "涉及单位名称") |
||||
private String involveDepartName; |
||||
|
||||
@Schema(description = "涉及单位id") |
||||
private String involveDepartId; |
||||
|
||||
@Schema(description = "联系电话") |
||||
private String contactPhone; |
||||
|
||||
@Schema(description = "反映人姓名") |
||||
private String responderName; |
||||
|
||||
@Schema(description = "反映人身份证") |
||||
private String responderIdCard; |
||||
|
||||
@Schema(description = "简要描述") |
||||
private String thingDesc; |
||||
|
||||
@Schema(description = "填写人姓名") |
||||
private String fillName; |
||||
|
||||
@Schema(description = "填写人部门id") |
||||
private String fillDepartId; |
||||
|
||||
@Schema(description = "填写人部门名称") |
||||
private String fillDeaprtName; |
||||
|
||||
@Schema(description = "审核人姓名") |
||||
private String checkName; |
||||
|
||||
@Schema(description = "审核人身份证") |
||||
private String checkIdCode; |
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm") |
||||
@Schema(description = "创建时间(不传则自动填充)") |
||||
private LocalDateTime crtTime; |
||||
|
||||
@Schema(description = "更新人姓名") |
||||
private String updName; |
||||
|
||||
@Schema(description = "更新人") |
||||
private String updUser; |
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm") |
||||
@Schema(description = "更新时间(不传则自动填充)") |
||||
private LocalDateTime updTime; |
||||
|
||||
@Schema(description = "状态") |
||||
private String status; |
||||
|
||||
@Schema(description = "备注") |
||||
private String remark; |
||||
|
||||
@Schema(description = "预留字段") |
||||
private String reserve; |
||||
|
||||
@Schema(description = "核查情况") |
||||
private String checkStatus; |
||||
|
||||
@Schema(description = "核查情况名称") |
||||
private String checkStatusName; |
||||
|
||||
@Schema(description = "核查结论code") |
||||
private String checkStatusCode; |
||||
|
||||
@Schema(description = "完善状态") |
||||
private String completeStatus; |
||||
|
||||
@Schema(description = "最后编辑人员") |
||||
private String lastEditName; |
||||
|
||||
@Schema(description = "任务ID") |
||||
private String taskId; |
||||
|
||||
@Schema(description = "督察主题code") |
||||
private String supervisionSubjectCode; |
||||
|
||||
@Schema(description = "督察主题名称") |
||||
private String supervisionSubjectName; |
||||
|
||||
@Schema(description = "是否整改code") |
||||
private String isRectifyCode; |
||||
|
||||
@Schema(description = "是否整改名称") |
||||
private String isRectifyName; |
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm") |
||||
@Schema(description = "办结时间") |
||||
private LocalDateTime completeDate; |
||||
|
||||
@Schema(description = "督察报告id") |
||||
private String reportId; |
||||
|
||||
@Schema(description = "流程key") |
||||
private String flowKey; |
||||
|
||||
@Schema(description = "主办层级") |
||||
private String hostLevel; |
||||
|
||||
@Schema(description = "办理时限") |
||||
private String timeLimit; |
||||
|
||||
@Schema(description = "最大签收时长(天)") |
||||
private Integer maxSignDuration; |
||||
|
||||
@Schema(description = "最大办理时长(天)") |
||||
private Integer maxHandleDuration; |
||||
|
||||
@Schema(description = "最大延期时长(天)") |
||||
private Integer maxExtensionDuration; |
||||
|
||||
@Schema(description = "审批流程") |
||||
private String approvalFlow; |
||||
|
||||
@Schema(description = "核查情况描述") |
||||
private String checkStatusDesc; |
||||
|
||||
@Schema(description = "整改情况描述") |
||||
private String rectifyDesc; |
||||
|
||||
@Schema(description = "整改限制天数") |
||||
private Integer rectifyRestrictionDays; |
||||
|
||||
@Schema(description = "追责对象") |
||||
private String accountabilityTarget; |
||||
|
||||
@Schema(description = "办理状态") |
||||
private String processingStatus; |
||||
|
||||
@Schema(description = "延期申请ID") |
||||
private Integer negativeExtensionApplyId; |
||||
|
||||
@Schema(description = "是否能申请延期") |
||||
private Boolean extensionApplyFlag; |
||||
|
||||
@Schema(description = "延期天数") |
||||
private Integer extensionDays; |
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm") |
||||
@Schema(description = "市局下发时间") |
||||
private LocalDateTime firstDistributeTime; |
||||
|
||||
@Schema(description = "是否二级机构办理") |
||||
private Boolean isSecondHandle; |
||||
|
||||
@Schema(description = "二级办理单位id") |
||||
private String handleSecondDepartId; |
||||
|
||||
@Schema(description = "二级办理单位名称") |
||||
private String handleSecondDepartName; |
||||
|
||||
@Schema(description = "三级办理单位id") |
||||
private String handleThreeDepartId; |
||||
|
||||
@Schema(description = "三级办理单位名称") |
||||
private String handleThreeDepartName; |
||||
|
||||
@Schema(description = "涉及案件/警情编号") |
||||
private String caseNumber; |
||||
|
||||
@Schema(description = "办理超时(秒)") |
||||
private Long handleTimeout; |
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm") |
||||
@Schema(description = "申请办结时间") |
||||
private LocalDateTime handleTime; |
||||
|
||||
@Schema(description = "当前处理对象") |
||||
private String currentProcessingObject; |
||||
|
||||
@Schema(description = "专项督察") |
||||
private String specialSupervision; |
||||
|
||||
@Schema(description = "通报期数") |
||||
private String reportNumber; |
||||
|
||||
@Schema(description = "核查办理情况") |
||||
private String verifySituation; |
||||
|
||||
@Schema(description = "佐证材料情况") |
||||
private String verifyFileSituation; |
||||
|
||||
@Schema(description = "单位会签ID") |
||||
private Integer countersignApplyId; |
||||
|
||||
@Schema(description = "创建单位层级") |
||||
private Integer crtDepartLevel; |
||||
|
||||
@Schema(description = "市局下发意见") |
||||
private String firstDistributeComments; |
||||
|
||||
@Schema(description = "是否抽检") |
||||
private Boolean spotCheckFlag; |
||||
|
||||
@Schema(description = "抽检结果") |
||||
private String spotCheckResult; |
||||
|
||||
@Schema(description = "抽检情况") |
||||
private String spotCheckDesc; |
||||
|
||||
@Schema(description = "未整改原因") |
||||
private String unrectifyReason; |
||||
|
||||
@Schema(description = "二级部门id") |
||||
private String secondInvolveDepartId; |
||||
|
||||
@Schema(description = "三级部门id") |
||||
private String threeInvolveDepartId; |
||||
|
||||
@Schema(description = "经办人") |
||||
private String handlePolices; |
||||
|
||||
@Schema(description = "剩余办理时间") |
||||
private Long handleRemainingTime; |
||||
|
||||
@Schema(description = "样本ID") |
||||
private Integer sampleId; |
||||
|
||||
@Schema(description = "下发问题(JSON)") |
||||
private List<VerifyData.Problem> problems; |
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm") |
||||
@Schema(description = "核查时间") |
||||
private LocalDateTime verifyTime; |
||||
|
||||
@Schema(description = "项目名称") |
||||
private String projectName; |
||||
|
||||
@Schema(description = "涉及问题金额") |
||||
private Double involveMoney; |
||||
|
||||
@Schema(description = "化解情况") |
||||
private String resolveSituation; |
||||
|
||||
@Schema(description = "当前状态") |
||||
private String resolveStatus; |
||||
|
||||
@Schema(description = "接访领导姓名") |
||||
private String visitingLeaderName; |
||||
|
||||
@Schema(description = "接访领导工号") |
||||
private String visitingLeaderEmpNo; |
||||
|
||||
@Schema(description = "12337办理结果") |
||||
private String handleResult12337; |
||||
|
||||
@Schema(description = "12337办理结果分组") |
||||
private String handleResult12337Group; |
||||
|
||||
@Schema(description = "涉及人员是否领导班子") |
||||
private String verifiedIsLeader; |
||||
|
||||
@Schema(description = "办理结果") |
||||
private String processResult; |
||||
|
||||
@Schema(description = "处分处理情况") |
||||
private String disciplinaryActionDesc; |
||||
|
||||
@Schema(description = "来源类型") |
||||
private String sourceType; |
||||
|
||||
@Schema(description = "来源类型名称") |
||||
private String sourceTypeDesc; |
||||
|
||||
@Schema(description = "下发单位id") |
||||
private String issuingDepartId; |
||||
|
||||
@Schema(description = "下发单位名称") |
||||
private String issuingDepartName; |
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm") |
||||
@Schema(description = "最后一次审批节点操作时间") |
||||
private LocalDateTime latestProcessTime; |
||||
|
||||
@Schema(description = "二级审批累计时长(秒)") |
||||
private Long secondApprovalTime; |
||||
|
||||
@Schema(description = "市局审批累计时长(秒)") |
||||
private Long firstApproveTime; |
||||
|
||||
// ========== 关联表 ==========
|
||||
|
||||
@Schema(description = "涉及人员列表") |
||||
private List<NegativeBlame> blames = new ArrayList<>(); |
||||
|
||||
@Schema(description = "事件附件列表") |
||||
private List<NegativeThingFile> thingFiles = new ArrayList<>(); |
||||
|
||||
@Schema(description = "核查附件列表") |
||||
private List<NegativeFile> files = new ArrayList<>(); |
||||
} |
||||
@ -1,81 +0,0 @@
|
||||
package com.biutag.supervision.pojo.dto.complaintCollection; |
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty; |
||||
import com.fasterxml.jackson.annotation.JsonFormat; |
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
import java.time.LocalDateTime; |
||||
|
||||
@Getter |
||||
@Setter |
||||
public class ExportComplaintCollectionBlameVo { |
||||
|
||||
@ExcelProperty("关联负面清单ID") |
||||
private String negativeId; |
||||
|
||||
@ExcelProperty("信件编号") |
||||
private String originId; |
||||
|
||||
@ExcelProperty(value = "发现/受理时间", format = "yyyy-MM-dd HH:mm") |
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm") |
||||
private LocalDateTime discoveryTime; |
||||
|
||||
@ExcelProperty("来源") |
||||
private String sourceTablePath; |
||||
|
||||
@ExcelProperty("业务类别") |
||||
private String businessTypeName; |
||||
|
||||
@ExcelProperty("涉嫌问题") |
||||
private String involveProblemStr; |
||||
|
||||
@ExcelProperty("简要描述") |
||||
private String thingDesc; |
||||
|
||||
@ExcelProperty("涉及单位(二级)") |
||||
private String secondDepartName; |
||||
|
||||
@ExcelProperty("涉及单位(三级)") |
||||
private String thirdDepartName; |
||||
|
||||
@ExcelProperty("核查结论") |
||||
private String checkStatusName; |
||||
|
||||
@ExcelProperty("追责对象") |
||||
private String accountabilityTarget; |
||||
|
||||
@ExcelProperty("涉及人员姓名") |
||||
private String blameName; |
||||
|
||||
@ExcelProperty("警号") |
||||
private String blameEmpNo; |
||||
|
||||
@ExcelProperty("身份证") |
||||
private String blameIdCode; |
||||
|
||||
@ExcelProperty("人员属性") |
||||
private String ivPersonType; |
||||
|
||||
@ExcelProperty("责任追责") |
||||
private String handleResultName; |
||||
|
||||
@ExcelProperty("责任领导姓名") |
||||
private String leadName; |
||||
|
||||
@ExcelProperty("责任领导警号") |
||||
private String leadEmpNo; |
||||
|
||||
@ExcelProperty("责任领导身份证") |
||||
private String leadIdCode; |
||||
|
||||
@ExcelProperty("责任领导责任追责") |
||||
private String leadHandleResultName; |
||||
|
||||
@ExcelProperty("问题类型") |
||||
private String problemType; |
||||
|
||||
@ExcelProperty("督察措施") |
||||
private String superviseMeasuresName; |
||||
|
||||
} |
||||
@ -1,93 +0,0 @@
|
||||
package com.biutag.supervision.pojo.dto.complaintCollection; |
||||
|
||||
import com.alibaba.excel.annotation.ExcelProperty; |
||||
import com.fasterxml.jackson.annotation.JsonFormat; |
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
import java.time.LocalDateTime; |
||||
|
||||
@Getter |
||||
@Setter |
||||
public class ExportComplaintCollectionExcelVo { |
||||
|
||||
@ExcelProperty("关联负面清单ID") |
||||
private String negativeId; |
||||
|
||||
@ExcelProperty("信件编号") |
||||
private String originId; |
||||
|
||||
@ExcelProperty("来源") |
||||
private String sourceTablePath; |
||||
|
||||
@ExcelProperty(value = "发现/受理时间", format = "yyyy-MM-dd HH:mm") |
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm") |
||||
private LocalDateTime discoveryTime; |
||||
|
||||
@ExcelProperty("业务类别") |
||||
private String businessTypeName; |
||||
|
||||
@ExcelProperty("涉嫌问题") |
||||
private String involveProblemStr; |
||||
|
||||
@ExcelProperty("简要描述") |
||||
private String thingDesc; |
||||
|
||||
@ExcelProperty("投诉反映人") |
||||
private String responderName; |
||||
|
||||
@ExcelProperty("联系电话") |
||||
private String responderPhone; |
||||
|
||||
@ExcelProperty("涉及警种") |
||||
private String policeTypeName; |
||||
|
||||
@ExcelProperty("办理单位(二级)") |
||||
private String secondDepartName; |
||||
|
||||
@ExcelProperty("办理单位(三级)") |
||||
private String thirdDepartName; |
||||
|
||||
@ExcelProperty("涉及单位") |
||||
private String involveDepartName; |
||||
|
||||
@ExcelProperty("核查结论") |
||||
private String checkStatusName; |
||||
|
||||
// @ExcelProperty("追责对象")
|
||||
// private String accountabilityTarget;
|
||||
|
||||
// @ExcelProperty("涉及人数")
|
||||
// private Integer blameNumber;
|
||||
|
||||
@ExcelProperty("涉及人员") |
||||
private String blameStr; |
||||
|
||||
// @ExcelProperty("责任追责")
|
||||
// private String handleResultName;
|
||||
|
||||
// @ExcelProperty("是否追责")
|
||||
// private String isHoldAccountable;
|
||||
|
||||
// @ExcelProperty("问题类型")
|
||||
// private String problemTypeList;
|
||||
|
||||
@ExcelProperty("办理状态") |
||||
private String processingStatus; |
||||
|
||||
@ExcelProperty("办结情况") |
||||
private String completionStatus; |
||||
|
||||
@ExcelProperty("群众认可") |
||||
private String publicRecognition; |
||||
|
||||
@ExcelProperty("办理方式") |
||||
private String handleMethod; |
||||
|
||||
@ExcelProperty("是否重复件") |
||||
private String repeatt; |
||||
|
||||
@ExcelProperty("标签") |
||||
private String tag; |
||||
|
||||
} |
||||
@ -1,41 +0,0 @@
|
||||
package com.biutag.supervision.pojo.entity.mailbox; |
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableId; |
||||
import com.baomidou.mybatisplus.annotation.TableName; |
||||
import io.swagger.v3.oas.annotations.media.Schema; |
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
import java.time.LocalDateTime; |
||||
|
||||
/** |
||||
* @ClassName MailExtension |
||||
* @Description 局长信箱延期表 |
||||
* @Author auto-generate |
||||
* @Date 2026/4/29 |
||||
*/ |
||||
@Getter |
||||
@Setter |
||||
@TableName("mail_extension") |
||||
@Schema(description = "局长信箱延期表") |
||||
public class MailExtension { |
||||
|
||||
@Schema(description = "主键ID") |
||||
@TableId |
||||
private String id; |
||||
|
||||
@Schema(description = "信件ID") |
||||
private String mailId; |
||||
|
||||
@Schema(description = "延期天数") |
||||
private Integer days; |
||||
|
||||
@Schema(description = "延期理由") |
||||
private String extensionReason; |
||||
|
||||
@Schema(description = "创建时间") |
||||
private LocalDateTime createTime; |
||||
|
||||
@Schema(description = "初核材料(附件)") |
||||
private String initialVerifyAttachments; |
||||
} |
||||
@ -1,32 +0,0 @@
|
||||
package com.biutag.supervision.pojo.request.complaintCollection; |
||||
|
||||
import cn.hutool.core.util.StrUtil; |
||||
import com.biutag.supervision.aop.ParamChecked; |
||||
import io.swagger.v3.oas.annotations.media.Schema; |
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
/** |
||||
* @ClassName ComplaintCollectionDetailRequest |
||||
* @Description 涉访涉诉详情查询请求 |
||||
* @Author system |
||||
* @Date 2026/04/08 |
||||
*/ |
||||
@Setter |
||||
@Getter |
||||
@Schema(description = "涉访涉诉详情查询请求") |
||||
public class ComplaintCollectionDetailRequest implements ParamChecked { |
||||
|
||||
@Schema(description = "投诉举报主键ID") |
||||
private String id; |
||||
|
||||
@Schema(description = "问题id") |
||||
private String negativeId; |
||||
|
||||
@Override |
||||
public void check() { |
||||
if (StrUtil.isBlank(id) && StrUtil.isBlank(negativeId)) { |
||||
throw new IllegalArgumentException("投诉举报主键ID和问题ID不能同时空"); |
||||
} |
||||
} |
||||
} |
||||
@ -1,38 +0,0 @@
|
||||
package com.biutag.supervision.pojo.request.complaintCollection; |
||||
|
||||
|
||||
import com.biutag.supervision.aop.ParamChecked; |
||||
import com.biutag.supervision.util.CheckUtil; |
||||
import io.swagger.v3.oas.annotations.media.Schema; |
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
@Setter |
||||
@Getter |
||||
@Schema(description = "初核请求") |
||||
public class ComplaintCollectionInitialReviewRequest implements ParamChecked { |
||||
|
||||
@Schema(description = "涉访涉诉编号id") |
||||
private String complaintId; |
||||
|
||||
@Schema(description = "初核工作开展情况") |
||||
private String initWorkDes; |
||||
|
||||
@Schema(description = "初核发现的问题及下步工作计划") |
||||
private String initProblemPlan; |
||||
|
||||
@Schema(description = "初核结论") |
||||
private String initVerdict; |
||||
|
||||
@Schema(description = "初核附件") |
||||
private String initFile; |
||||
|
||||
|
||||
@Override |
||||
public void check() { |
||||
CheckUtil.checkNotBlank(complaintId, "涉访涉诉id不能为空"); |
||||
CheckUtil.checkNotBlank(initWorkDes, "初核工作开展情况不能为空"); |
||||
CheckUtil.checkNotBlank(initProblemPlan, "初核发现的问题及下步工作计划不能为空"); |
||||
CheckUtil.checkNotBlank(initVerdict, "初核结论不能为空"); |
||||
} |
||||
} |
||||
@ -1,31 +0,0 @@
|
||||
package com.biutag.supervision.pojo.request.complaintCollection; |
||||
|
||||
|
||||
import com.biutag.supervision.aop.ParamChecked; |
||||
import com.biutag.supervision.util.CheckUtil; |
||||
import io.swagger.v3.oas.annotations.media.Schema; |
||||
import lombok.Getter; |
||||
import lombok.Setter; |
||||
|
||||
@Setter |
||||
@Getter |
||||
@Schema(description = "初核请求") |
||||
public class ComplaintCollectionInitialReviewSaveRequest implements ParamChecked { |
||||
|
||||
@Schema(description = "涉访涉诉编号id") |
||||
private String complaintId; |
||||
|
||||
@Schema(description = "初核工作开展情况") |
||||
private String initWorkDes; |
||||
|
||||
@Schema(description = "初核发现的问题及下步工作计划") |
||||
private String initProblemPlan; |
||||
|
||||
@Schema(description = "初核结论") |
||||
private String initVerdict; |
||||
|
||||
@Override |
||||
public void check() { |
||||
CheckUtil.checkNotNull(complaintId, "投诉编号不能为空!"); |
||||
} |
||||
} |
||||
@ -1,85 +0,0 @@
|
||||
package com.biutag.supervision.pojo.vo.complaintCollection; |
||||
|
||||
import com.biutag.supervision.pojo.vo.FileVo; |
||||
import io.swagger.v3.oas.annotations.media.Schema; |
||||
import lombok.Data; |
||||
|
||||
import java.time.LocalDateTime; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* @ClassName ComplaintCollectionDetailVo |
||||
* @Description 涉访涉诉详情查询响应VO(用于修改弹窗数据回显) |
||||
* @Author system |
||||
* @Date 2026/04/08 |
||||
*/ |
||||
@Data |
||||
@Schema(description = "涉访涉诉详情查询响应VO(用于修改弹窗数据回显)") |
||||
public class ComplaintCollectionDetailVo { |
||||
|
||||
@Schema(description = "主键ID") |
||||
private String id; |
||||
|
||||
@Schema(description = "来源表类型") |
||||
private String sourceTable; |
||||
|
||||
@Schema(description = "来源子类型") |
||||
private String sourceTableSubOne; |
||||
|
||||
@Schema(description = "编号") |
||||
private String originId; |
||||
|
||||
@Schema(description = "登记/受理时间") |
||||
private LocalDateTime discoveryTime; |
||||
|
||||
@Schema(description = "来件人姓名") |
||||
private String responderName; |
||||
|
||||
@Schema(description = "身份证号") |
||||
private String responderIdCode; |
||||
|
||||
@Schema(description = "联系电话") |
||||
private String responderPhone; |
||||
|
||||
@Schema(description = "被投诉二级机构ID") |
||||
private String secondDepartId; |
||||
|
||||
@Schema(description = "被投诉二级机构名称") |
||||
private String secondDepartName; |
||||
|
||||
@Schema(description = "来件内容") |
||||
private String thingDesc; |
||||
|
||||
@Schema(description = "涉嫌问题(逗号分隔)") |
||||
private String involveProblem; |
||||
|
||||
@Schema(description = "涉嫌问题ID列表") |
||||
private List<String> involveProblemIdList; |
||||
|
||||
@Schema(description = "是否重复件") |
||||
private String repeatt; |
||||
|
||||
@Schema(description = "是否领导审批") |
||||
private String leadApproval; |
||||
|
||||
@Schema(description = "标签(逗号分隔)") |
||||
private String tag; |
||||
|
||||
@Schema(description = "标签列表") |
||||
private List<String> tags; |
||||
|
||||
@Schema(description = "办理方式") |
||||
private String handleMethod; |
||||
|
||||
@Schema(description = "业务类型code") |
||||
private String businessTypeCode; |
||||
|
||||
@Schema(description = "业务类型name") |
||||
private String businessTypeName; |
||||
|
||||
@Schema(description = "附件列表") |
||||
private List<FileVo> thingFiles; |
||||
|
||||
@Schema(description = "问题ID(negative表)") |
||||
private String negativeId; |
||||
} |
||||
@ -1,927 +0,0 @@
|
||||
package com.biutag.supervision.service; |
||||
|
||||
import cn.hutool.core.collection.CollectionUtil; |
||||
import cn.hutool.core.util.IdUtil; |
||||
import cn.hutool.core.util.StrUtil; |
||||
import com.alibaba.fastjson2.JSON; |
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
||||
import com.biutag.supervision.constants.enums.AccountabilityTargetEnum; |
||||
import com.biutag.supervision.constants.enums.BusinessTypeEnum; |
||||
import com.biutag.supervision.constants.enums.ProblemSourcesEnum; |
||||
import com.biutag.supervision.constants.enums.ProcessingStatusEnum; |
||||
import com.biutag.supervision.mapper.ComplaintCollectionMapper; |
||||
import com.biutag.supervision.mapper.MailBlameMapper; |
||||
import com.biutag.supervision.mapper.MailExtensionMapper; |
||||
import com.biutag.supervision.pojo.dto.MailBoxSyncDto; |
||||
import com.biutag.supervision.pojo.dto.NegativeDataOnlyDto; |
||||
import com.biutag.supervision.pojo.dto.mail.MailAttachmentDTO; |
||||
import com.biutag.supervision.pojo.entity.*; |
||||
import com.biutag.supervision.pojo.entity.mailbox.Mail; |
||||
import com.biutag.supervision.pojo.entity.mailbox.MailBlame; |
||||
import com.biutag.supervision.pojo.entity.mailbox.MailExtension; |
||||
import com.biutag.supervision.pojo.enums.complaintCollection.ComplaintCollectionInitialEnum; |
||||
import com.biutag.supervision.pojo.enums.complaintCollection.ComplaintCollectionSourceTableEnum; |
||||
import com.biutag.supervision.pojo.enums.negative.NegativeSourceTypeEnum; |
||||
import com.biutag.supervision.pojo.param.ComplaintCollection.ComplaintCollectionQueryParam; |
||||
import com.biutag.supervision.pojo.param.ComplaintCollection.ComplaintCollectionUpdateParam; |
||||
import com.biutag.supervision.pojo.param.MailQueryParam; |
||||
import com.biutag.supervision.pojo.param.SupDepartQueryParam; |
||||
import com.biutag.supervision.pojo.param.SupExternalDepartQueryParam; |
||||
import com.biutag.supervision.repository.complaintCollection.ComplaintCollectionResourceService; |
||||
import com.biutag.supervision.repository.mail.MailResourceService; |
||||
import com.biutag.supervision.repository.supExternalDepart.SupExternalDepartResourceService; |
||||
import com.biutag.supervision.repository.supdepart.SupDepartResourceService; |
||||
import com.biutag.supervision.service.complaintCollection.ComplaintCollectionService; |
||||
import com.biutag.supervision.util.TimeUtil; |
||||
import lombok.RequiredArgsConstructor; |
||||
import lombok.extern.slf4j.Slf4j; |
||||
import org.springframework.stereotype.Service; |
||||
import org.springframework.transaction.support.TransactionTemplate; |
||||
|
||||
import java.time.LocalDate; |
||||
import java.time.LocalDateTime; |
||||
import java.time.format.DateTimeFormatter; |
||||
import java.util.ArrayList; |
||||
import java.util.Collections; |
||||
import java.util.List; |
||||
import java.util.Objects; |
||||
import java.util.stream.Collectors; |
||||
|
||||
/** |
||||
* @ClassName MailBoxCaptureService |
||||
* @Description 局长信箱数据抓取业务逻辑 |
||||
* - 阶段1:抓取来信,创建 Negative 主表 + 来信附件 + ComplaintCollection |
||||
* - 阶段2:同步办结后的涉及人和核查附件 |
||||
* @Author shihao |
||||
* @Date 2026/4/28 |
||||
*/ |
||||
@Slf4j |
||||
@Service |
||||
@RequiredArgsConstructor |
||||
public class MailBoxCaptureService { |
||||
|
||||
private final NegativeService negativeService; |
||||
private final NegativeBlameService blameService; |
||||
private final NegativeProblemRelationService negativeProblemRelationService; |
||||
private final NegativeFileService fileService; |
||||
private final MailService mailService; |
||||
private final MailResourceService mailResourceService; |
||||
private final SupDepartResourceService supDepartResourceService; |
||||
private final SupExternalDepartResourceService supExternalDepartResourceService; |
||||
private final ComplaintCollectionResourceService complaintCollectionResourceService; |
||||
private final MailBlameMapper mailBlameMapper; |
||||
private final MailExtensionMapper mailExtensionMapper; |
||||
private final SupPoliceService supPoliceService; |
||||
private final SupDictHandleResultMapingService dictHandleResultMapingService; |
||||
private final SupDictProblemTypeMapingService dictProblemTypeMapingService; |
||||
private final SupDictProblemTypeService problemTypeService; |
||||
private final TransactionTemplate transactionTemplate; |
||||
private final ComplaintCollectionMapper complaintCollectionMapper; |
||||
private final ComplaintCollectionService complaintCollectionService; |
||||
private static final DateTimeFormatter INITIAL_REVIEW_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); |
||||
private static final int CHECK_LIMIT_DAYS = 4; |
||||
|
||||
// ==================== 阶段1:抓取来信 ====================
|
||||
|
||||
/** |
||||
* 抓取来信并创建 ComplaintCollection 和 Negative |
||||
*/ |
||||
public void captureMayorMailbox(LocalDateTime start, LocalDateTime end) { |
||||
log.info("【局长信箱抓取新信件】时间范围 {} ~ {}", start, end); |
||||
long startTimeMillis = System.currentTimeMillis(); |
||||
|
||||
try { |
||||
// 1. 查询来信的信件
|
||||
List<Mail> mailList = queryNewMails(start, end); |
||||
if (CollectionUtil.isEmpty(mailList)) { |
||||
log.warn("【局长信箱已办结抓取】未查询到任何投诉举报信件数据,任务结束"); |
||||
return; |
||||
} |
||||
log.info("【局长信箱抓取新信件】查询到投诉举报信件信件数量:{}", mailList.size()); |
||||
|
||||
// 3. 遍历处理
|
||||
int successCount = 0; |
||||
int skipCount = 0; |
||||
int failCount = 0; |
||||
|
||||
for (Mail mail : mailList) { |
||||
try { |
||||
// 每条记录在独立事务中执行
|
||||
boolean success = Boolean.TRUE.equals(transactionTemplate.execute(status -> { |
||||
return doCaptureSingleMail(mail); |
||||
})); |
||||
if (success) { |
||||
successCount++; |
||||
log.debug("【局长信箱抓取新信件】处理成功: mailId={}", mail.getId()); |
||||
} else { |
||||
skipCount++; |
||||
log.debug("【局长信箱抓取新信件】处理跳过: mailId={}", mail.getId()); |
||||
} |
||||
} catch (Exception e) { |
||||
failCount++; |
||||
log.error("【局长信箱抓取新信件】处理失败: mailId={}, error={}", mail.getId(), e.getMessage(), e); |
||||
} |
||||
} |
||||
|
||||
// 4. 输出统计
|
||||
long cost = System.currentTimeMillis() - startTimeMillis; |
||||
log.info("【局长信箱抓取新信件】完成,总数:{},成功:{},跳过:{},失败:{},耗时:{}ms", |
||||
mailList.size(), successCount, skipCount, failCount, cost); |
||||
|
||||
} catch (Exception e) { |
||||
log.error("【局长信箱抓取新信件】任务执行过程中发生严重异常,任务中断", e); |
||||
throw e; |
||||
} |
||||
} |
||||
|
||||
// ==================== 阶段2:同步涉及人、核查附件、核查情况 ====================
|
||||
|
||||
/** |
||||
* 同步办结后的涉及人和核查附件 |
||||
*/ |
||||
public void syncBlameAndFiles(LocalDateTime start, LocalDateTime end) { |
||||
log.info("【阶段2同步】时间范围 {} ~ {}", start, end); |
||||
long startTimeMillis = System.currentTimeMillis(); |
||||
|
||||
try { |
||||
// 1. 从 ComplaintCollection 查询局长信箱记录
|
||||
List<ComplaintCollection> completedList = queryCompletedMailbox(); |
||||
if (CollectionUtil.isEmpty(completedList)) { |
||||
log.warn("【阶段2同步】未查询到任何需要同步的数据,任务结束"); |
||||
return; |
||||
} |
||||
log.info("【阶段2同步】查询到需要同步数量:{}", completedList.size()); |
||||
|
||||
// 2. 遍历处理(每条记录独立事务)
|
||||
int successCount = 0; |
||||
int skipCount = 0; |
||||
int failCount = 0; |
||||
|
||||
for (ComplaintCollection cc : completedList) { |
||||
try { |
||||
String originId = cc.getOriginId(); |
||||
// 查询信件
|
||||
MailQueryParam param = new MailQueryParam(); |
||||
param.setId(originId); |
||||
param.setMailState("completion"); |
||||
List<Mail> mailList = mailResourceService.query(param); |
||||
if (CollectionUtil.isEmpty(mailList)) { |
||||
log.info("【阶段2同步】无对应办结Mail:originId=" + originId); |
||||
continue; |
||||
} |
||||
Mail mail = mailList.get(0); |
||||
|
||||
// 查询涉及人
|
||||
LambdaQueryWrapper<MailBlame> mailBlameLambdaQueryWrapper = new LambdaQueryWrapper<>(); |
||||
mailBlameLambdaQueryWrapper.eq(MailBlame::getMailId, mail.getId()); |
||||
List<MailBlame> mailBlames = mailBlameMapper.selectList(mailBlameLambdaQueryWrapper); |
||||
|
||||
// 构建 DTO
|
||||
MailBoxSyncDto dto = new MailBoxSyncDto(); |
||||
dto.setCc(cc); |
||||
dto.setMail(mail); |
||||
dto.setMailBlames(mailBlames); |
||||
|
||||
// 每条记录在独立事务中执行
|
||||
boolean success = Boolean.TRUE.equals(transactionTemplate.execute(status -> { |
||||
return doSyncSingleRecord(dto); |
||||
})); |
||||
if (success) { |
||||
successCount++; |
||||
log.debug("【阶段2同步】处理成功: ccId={}", cc.getId()); |
||||
} else { |
||||
skipCount++; |
||||
log.debug("【阶段2同步】处理跳过: ccId={}", cc.getId()); |
||||
} |
||||
} catch (Exception e) { |
||||
failCount++; |
||||
log.error("【阶段2同步】处理失败: ccId={}, error={}", cc.getId(), e.getMessage(), e); |
||||
} |
||||
} |
||||
// 3. 输出统计
|
||||
long cost = System.currentTimeMillis() - startTimeMillis; |
||||
log.info("【阶段2同步】完成,总数:{},成功:{},跳过:{},失败:{},耗时:{}ms", |
||||
completedList.size(), successCount, skipCount, failCount, cost); |
||||
} catch (Exception e) { |
||||
log.error("【阶段2同步】任务执行过程中发生严重异常,任务中断", e); |
||||
throw e; |
||||
} |
||||
} |
||||
|
||||
// ==================== 查询相关 ====================
|
||||
|
||||
/** |
||||
* 从 ComplaintCollection 查询局长信箱记录 |
||||
*/ |
||||
private List<ComplaintCollection> queryCompletedMailbox() { |
||||
ComplaintCollectionQueryParam param = new ComplaintCollectionQueryParam(); |
||||
param.setSourceTable(ComplaintCollectionSourceTableEnum.MAYOR_MAILBOX.getCode()); |
||||
param.setBlameSyncStatus("0"); // 未同步
|
||||
return complaintCollectionResourceService.query(param); |
||||
} |
||||
|
||||
/** |
||||
* 查询来信时间范围内的信件(按来信时间查询) |
||||
*/ |
||||
private List<Mail> queryNewMails(LocalDateTime start, LocalDateTime end) { |
||||
LambdaQueryWrapper<Mail> queryWrapper = new LambdaQueryWrapper<>(); |
||||
queryWrapper.in(Mail::getMailLevel, "涉警投诉"); |
||||
queryWrapper.between(Mail::getMailTime, start, end); |
||||
return mailService.list(queryWrapper); |
||||
} |
||||
|
||||
/** |
||||
* 判重检查:检查是否已处理 |
||||
*/ |
||||
private boolean isAlreadyProcessed(Mail mail) { |
||||
boolean exists = negativeService.exists(mail.getId()); |
||||
if (exists) { |
||||
log.debug("【局长信箱已办结抓取】跳过(已处理): mailId={}", mail.getId()); |
||||
} |
||||
return exists; |
||||
} |
||||
|
||||
// ==================== 单位查询 ====================
|
||||
|
||||
/** |
||||
* 根据外部单位ID查询单位实体(外部ID -> 内部ID -> 部门实体) |
||||
* |
||||
* @return 部门实体,找不到时返回 null(由调用方决定如何处理) |
||||
*/ |
||||
private SupDepart getDepartByExternalId(Integer externalId) { |
||||
if (externalId == null) { |
||||
log.warn("【局长信箱已办结抓取】外部单位ID为空"); |
||||
return null; |
||||
} |
||||
// 1. 通过外部ID查询映射表,获取内部ID
|
||||
SupExternalDepart externalDepart = findExternalDepart(externalId); |
||||
if (externalDepart == null) { |
||||
log.warn("【局长信箱已办结抓取】未找到SupExternalDepart映射,externalId={}", externalId); |
||||
return null; |
||||
} |
||||
String internalId = externalDepart.getInternalId(); |
||||
if (StrUtil.isBlank(internalId)) { |
||||
log.warn("【局长信箱已办结抓取】SupExternalDepart.internalId为空,externalId={}", externalId); |
||||
return null; |
||||
} |
||||
// 2. 通过内部ID查询部门实体
|
||||
SupDepart depart = findDepartById(internalId); |
||||
if (depart == null) { |
||||
log.warn("【局长信箱已办结抓取】未找到单位,internalId={}", internalId); |
||||
return null; |
||||
} |
||||
return depart; |
||||
} |
||||
|
||||
/** |
||||
* 根据外部ID查询单位映射 |
||||
* |
||||
* @return 单位映射,找不到时返回 null |
||||
*/ |
||||
private SupExternalDepart findExternalDepart(Integer externalId) { |
||||
SupExternalDepartQueryParam queryParam = new SupExternalDepartQueryParam(); |
||||
queryParam.setSource("局长信箱"); |
||||
queryParam.setExternalIds(Collections.singleton(String.valueOf(externalId))); |
||||
List<SupExternalDepart> list = supExternalDepartResourceService.query(queryParam); |
||||
if (CollectionUtil.isEmpty(list)) { |
||||
return null; |
||||
} |
||||
return list.get(0); |
||||
} |
||||
|
||||
/** |
||||
* 根据内部ID查询部门 |
||||
*/ |
||||
private SupDepart findDepartById(String id) { |
||||
SupDepartQueryParam queryParam = new SupDepartQueryParam(); |
||||
queryParam.setId(id); |
||||
List<SupDepart> list = supDepartResourceService.query(queryParam); |
||||
if (CollectionUtil.isEmpty(list)) { |
||||
return null; |
||||
} |
||||
return list.get(0); |
||||
} |
||||
|
||||
// ==================== 阶段1 抓取方法 ====================
|
||||
|
||||
/** |
||||
* 单条记录的抓取逻辑(独立事务执行) |
||||
*/ |
||||
public boolean doCaptureSingleMail(Mail mail) { |
||||
// 1. 判重检查
|
||||
if (isAlreadyProcessed(mail)) { |
||||
return false; |
||||
} |
||||
|
||||
// 2. 查询单位信息
|
||||
SupDepart secondDepart = getDepartByExternalId(mail.getSecondDeptId()); |
||||
SupDepart thirdDepart = getDepartByExternalId(mail.getThreeDeptId()); |
||||
|
||||
// 2.1 如果单位信息获取失败,抛出异常触发回滚
|
||||
if (secondDepart == null || thirdDepart == null) { |
||||
throw new RuntimeException("单位映射缺失: mailId=" + mail.getId()); |
||||
} |
||||
|
||||
// 3. 构建并保存 Negative(阶段1:主表 + 来信附件)
|
||||
NegativeDataOnlyDto dto = buildNegativeDto(mail, secondDepart, thirdDepart); |
||||
Negative negative = negativeService.saveNegativeMain(dto); |
||||
negativeService.saveThingFiles(dto, negative.getId()); |
||||
|
||||
// 4. 保存 ComplaintCollection
|
||||
ComplaintCollection cc = buildComplaintCollection(mail, negative.getId(), secondDepart, thirdDepart); |
||||
complaintCollectionResourceService.saveOrUpdateComplaintCollection(Collections.singletonList(cc)); |
||||
return true; |
||||
} |
||||
|
||||
// ==================== 阶段2 同步方法 ====================
|
||||
|
||||
/** |
||||
* 单条记录的同步逻辑(独立事务执行) |
||||
*/ |
||||
private boolean doSyncSingleRecord(MailBoxSyncDto dto) { |
||||
ComplaintCollection cc = dto.getCc(); |
||||
Mail mail = dto.getMail(); |
||||
List<MailBlame> mailBlames = dto.getMailBlames(); |
||||
|
||||
// 1. 通过 originId 找到对应的 Negative(只有阶段1创建过的才同步)
|
||||
Negative negative = negativeService.getByOriginId(cc.getOriginId()); |
||||
if (negative == null) { |
||||
log.warn("【阶段2同步】无对应Negative,跳过: originId={}", cc.getOriginId()); |
||||
return false; |
||||
} |
||||
|
||||
// 2. 组装数据并保存
|
||||
syncBlame(mail, negative.getId(), mailBlames); |
||||
syncFiles(mail, negative.getId()); |
||||
|
||||
// 3. 同步核查情况到 Negative
|
||||
syncCheckStatus(mail, negative); |
||||
|
||||
// 4. 更新同步标记(所有同步操作成功后)
|
||||
updateSyncTag(cc); |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* 同步涉及人 |
||||
*/ |
||||
private List<NegativeBlame> syncBlame(Mail mail, String negativeId, List<MailBlame> mailBlames) { |
||||
// 幂等性检查:已存在则跳过
|
||||
LambdaQueryWrapper<NegativeBlame> existWrapper = new LambdaQueryWrapper<>(); |
||||
existWrapper.eq(NegativeBlame::getNegativeId, negativeId); |
||||
if (blameService.count(existWrapper) > 0) { |
||||
log.info("【阶段2同步】涉及人已存在,跳过: negativeId={}", negativeId); |
||||
return Collections.emptyList(); |
||||
} |
||||
|
||||
// mailBlames 已由调用方在事务外查询好
|
||||
if (CollectionUtil.isEmpty(mailBlames)) { |
||||
return Collections.emptyList(); |
||||
} |
||||
|
||||
List<NegativeBlame> result = new ArrayList<>(); |
||||
for (MailBlame blame : mailBlames) { |
||||
// 通过姓名+警号查询 SupPolice 获取完整信息
|
||||
LambdaQueryWrapper<SupPolice> supPoliceLambdaQueryWrapper = new LambdaQueryWrapper<>(); |
||||
supPoliceLambdaQueryWrapper.eq(SupPolice::getIdCode, blame.getBlameIdCode()); |
||||
supPoliceLambdaQueryWrapper.last("limit 1"); |
||||
SupPolice police = supPoliceService.getOne(supPoliceLambdaQueryWrapper); |
||||
if (Objects.isNull(police)) { |
||||
log.warn("【阶段2同步】未找到该警员的数据! blameName={}, blameEmpNo={}", blame.getBlameName(), blame.getBlameEmpNo()); |
||||
continue; |
||||
} |
||||
|
||||
NegativeBlame negativeBlame = new NegativeBlame(); |
||||
negativeBlame.setBlameId(IdUtil.getSnowflakeNextIdStr()); |
||||
negativeBlame.setNegativeId(negativeId); |
||||
negativeBlame.setType("personal"); |
||||
negativeBlame.setBlameEmpNo(police.getEmpNo()); |
||||
negativeBlame.setBlameIdCode(police.getIdCode()); |
||||
negativeBlame.setBlameName(police.getName()); |
||||
negativeBlame.setCrtTime(LocalDateTime.now()); |
||||
negativeBlame.setUpdTime(LocalDateTime.now()); |
||||
negativeBlame.setLeadEmpNo(blame.getLeaderEmpNo()); |
||||
negativeBlame.setLeadName(blame.getLeaderName()); |
||||
negativeBlame.setLeadIdCode(blame.getLeaderIdCode()); |
||||
negativeBlame.setIvPersonType(police.getPersonType()); |
||||
|
||||
// 责任追究映射
|
||||
if (StrUtil.isNotBlank(blame.getVerifyPunish())) { |
||||
try { |
||||
List<String> externalNames = JSON.parseArray(blame.getVerifyPunish(), String.class); |
||||
List<SupDictHandleResultMaping> dictHandleResultMapings = dictHandleResultMapingService.list(externalNames); |
||||
negativeBlame.setHandleResultCode( |
||||
dictHandleResultMapings.stream() |
||||
.map(SupDictHandleResultMaping::getInternalId) |
||||
.collect(Collectors.joining(",")) |
||||
); |
||||
negativeBlame.setHandleResultName( |
||||
dictHandleResultMapings.stream() |
||||
.map(SupDictHandleResultMaping::getInternalName) |
||||
.collect(Collectors.joining("、")) |
||||
); |
||||
} catch (Exception e) { |
||||
log.warn("【阶段2同步】责任追究映射失败: verifyPunish={}", blame.getVerifyPunish(), e); |
||||
} |
||||
} |
||||
|
||||
// 查证属实问题映射 - 创建 NegativeProblemRelation
|
||||
if (StrUtil.isNotBlank(blame.getVerifyProblem())) { |
||||
try { |
||||
List<String> externalNames = JSON.parseArray(blame.getVerifyProblem(), String.class); |
||||
List<SupDictProblemTypeMaping> problemTypeMapings = dictProblemTypeMapingService.list(externalNames); |
||||
for (SupDictProblemTypeMaping problemTypeMaping : problemTypeMapings) { |
||||
SupDictProblemType threeProblem = problemTypeService.getById(problemTypeMaping.getInternalId()); |
||||
if (threeProblem == null) { |
||||
log.warn("【阶段2同步】未找到三级问题类型: internalId={}", problemTypeMaping.getInternalId()); |
||||
continue; |
||||
} |
||||
NegativeProblemRelation problemRelation = new NegativeProblemRelation(); |
||||
problemRelation.setBlameId(negativeBlame.getBlameId()); |
||||
problemRelation.setNegativeId(negativeId); |
||||
problemRelation.setThreeLevelCode(threeProblem.getId()); |
||||
problemRelation.setThreeLevelContent(threeProblem.getName()); |
||||
// 二级
|
||||
String parentCode = threeProblem.getParentCode(); |
||||
SupDictProblemType twoProblem = null; |
||||
if (StrUtil.isNotBlank(parentCode)) { |
||||
twoProblem = problemTypeService.getById(parentCode); |
||||
if (twoProblem != null) { |
||||
problemRelation.setTwoLevelCode(twoProblem.getId()); |
||||
problemRelation.setTwoLevelContent(twoProblem.getName()); |
||||
} |
||||
} |
||||
// 一级
|
||||
if (twoProblem != null) { |
||||
String twoParentCode = twoProblem.getParentCode(); |
||||
if (StrUtil.isNotBlank(twoParentCode)) { |
||||
SupDictProblemType oneProblem = problemTypeService.getById(twoParentCode); |
||||
if (oneProblem != null) { |
||||
problemRelation.setOneLevelCode(oneProblem.getId()); |
||||
problemRelation.setOneLevelContent(oneProblem.getName()); |
||||
} |
||||
} |
||||
} |
||||
negativeProblemRelationService.save(problemRelation); |
||||
} |
||||
} catch (Exception e) { |
||||
log.warn("【阶段2同步】查证属实问题映射失败: verifyProblem={}", blame.getVerifyProblem(), e); |
||||
} |
||||
} |
||||
|
||||
// 保存 NegativeBlame
|
||||
blameService.save(negativeBlame); |
||||
result.add(negativeBlame); |
||||
log.debug("【阶段2同步】保存涉及人: negativeId={}, blameName={}", negativeId, negativeBlame.getBlameName()); |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* 同步核查情况:Mail 表的核查字段 -> Negative 表 |
||||
*/ |
||||
private void syncCheckStatus(Mail mail, Negative negative) { |
||||
String checkStatus = null; |
||||
String checkStatusName = null; |
||||
String checkStatusCode = null; |
||||
|
||||
// 核查情况映射
|
||||
String verifyIsTrue = mail.getVerifyIsTrue(); |
||||
if ("属实".equals(verifyIsTrue)) { |
||||
checkStatus = "1"; |
||||
checkStatusName = "属实"; |
||||
checkStatusCode = "1"; |
||||
} else if ("基本属实".equals(verifyIsTrue)) { |
||||
checkStatus = "2"; |
||||
checkStatusName = "部分属实"; |
||||
checkStatusCode = "2"; |
||||
} else if ("不属实".equals(verifyIsTrue)) { |
||||
checkStatus = "3"; |
||||
checkStatusName = "不属实"; |
||||
checkStatusCode = "5"; |
||||
} |
||||
|
||||
// 核查结论(优先 verifyDetails,其次 completionComment)
|
||||
String checkStatusDesc = null; |
||||
if (StrUtil.isNotBlank(mail.getVerifyDetails())) { |
||||
checkStatusDesc = mail.getVerifyDetails(); |
||||
} else if (StrUtil.isNotBlank(mail.getCompletionComment())) { |
||||
checkStatusDesc = mail.getCompletionComment(); |
||||
} |
||||
|
||||
// 只有存在核查情况时才更新
|
||||
if (checkStatus != null) { |
||||
// 防御编程:使用 updateById 确保只更新单条记录
|
||||
negative.setCheckStatus(checkStatus); |
||||
negative.setCheckStatusName(checkStatusName); |
||||
negative.setCheckStatusDesc(checkStatusDesc); |
||||
negative.setCheckStatusCode(checkStatusCode); |
||||
negative.setProcessingStatus(ProcessingStatusEnum.completed.name()); |
||||
boolean updated = negativeService.updateById(negative); |
||||
if (updated) { |
||||
log.debug("【阶段2同步】更新核查情况: negativeId={}, checkStatus={}, checkStatusDesc={}", |
||||
negative.getId(), checkStatus, checkStatusDesc); |
||||
} else { |
||||
log.warn("【阶段2同步】更新核查情况失败,Negative不存在或已被删除: negativeId={}", negative.getId()); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 同步涉及人:MailBlame -> NegativeBlame(组装并保存) |
||||
* 参照 MailService#saveMailbox 的 for 循环逻辑 |
||||
*/ |
||||
|
||||
/** |
||||
* 同步核查附件:Mail.verifyAttachments -> NegativeFile(组装并保存) |
||||
*/ |
||||
private void syncFiles(Mail mail, String negativeId) { |
||||
if (StrUtil.isBlank(mail.getVerifyAttachments())) { |
||||
return; |
||||
} |
||||
|
||||
List<MailAttachmentDTO> attachments = JSON.parseArray(mail.getVerifyAttachments(), MailAttachmentDTO.class); |
||||
if (CollectionUtil.isEmpty(attachments)) { |
||||
return; |
||||
} |
||||
|
||||
// 幂等性检查:如果该 Negative 已有附件,直接跳过
|
||||
long existingCount = fileService.count( |
||||
new LambdaQueryWrapper<NegativeFile>().eq(NegativeFile::getNegtiveId, negativeId) |
||||
); |
||||
if (existingCount > 0) { |
||||
log.info("【阶段2同步】附件已存在,跳过: negativeId={}", negativeId); |
||||
return; |
||||
} |
||||
|
||||
for (MailAttachmentDTO att : attachments) { |
||||
NegativeFile file = new NegativeFile(); |
||||
file.setFileId(IdUtil.getSnowflakeNextIdStr()); |
||||
file.setNegtiveId(negativeId); |
||||
file.setFileName(StrUtil.isNotBlank(att.getOriginFilename()) ? att.getOriginFilename() : getFileName(att.getFilepath())); |
||||
file.setFilePath(buildFileUrl(att)); |
||||
file.setCrtTime(LocalDateTime.now()); |
||||
fileService.save(file); |
||||
log.debug("【阶段2同步】保存核查附件: negativeId={}, fileName={}", negativeId, file.getFileName()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 更新同步标记(所有同步操作成功后) |
||||
* |
||||
* @param cc |
||||
*/ |
||||
private void updateSyncTag(ComplaintCollection cc) { |
||||
ComplaintCollectionUpdateParam complaintCollectionUpdateParam = new ComplaintCollectionUpdateParam(); |
||||
complaintCollectionUpdateParam.setId(cc.getId()); |
||||
complaintCollectionUpdateParam.setBlameSyncStatus("1"); |
||||
boolean updated = complaintCollectionResourceService.updateSelectiveById(complaintCollectionUpdateParam); |
||||
if (!updated) { |
||||
throw new RuntimeException("更新blameSyncStatus失败: ccId=" + cc.getId()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 构建文件完整URL |
||||
*/ |
||||
private String buildFileUrl(MailAttachmentDTO att) { |
||||
String filepath = null; |
||||
if (StrUtil.isNotBlank(att.getDocxFilepath())) { |
||||
filepath = "http://65.47.60.145/lan-api/api/file/stream/" + att.getDocxFilepath(); |
||||
} else if (StrUtil.isNotBlank(att.getFilepath())) { |
||||
filepath = "http://65.47.60.145/lan-api/api/file/stream/" + att.getFilepath(); |
||||
} |
||||
return filepath; |
||||
} |
||||
|
||||
// ==================== 组装 ====================
|
||||
|
||||
/** |
||||
* 构建 NegativeDataOnlyDto |
||||
*/ |
||||
private NegativeDataOnlyDto buildNegativeDto(Mail mail, SupDepart secondDepart, SupDepart thirdDepart) { |
||||
NegativeDataOnlyDto dto = new NegativeDataOnlyDto(); |
||||
// 基础字段
|
||||
dto.setOriginId(mail.getId()); |
||||
dto.setDiscoveryTime(mail.getMailTime()); |
||||
// 创建时间以来信时间为准
|
||||
dto.setCrtTime(mail.getMailTime()); |
||||
dto.setProblemSourcesCode(ProblemSourcesEnum.JZXX.getValue()); |
||||
dto.setProblemSources(ProblemSourcesEnum.JZXX.getLabel()); |
||||
// 业务类型(其他)
|
||||
dto.setBusinessTypeCode(BusinessTypeEnum.QT.getValue()); |
||||
dto.setBusinessTypeName(BusinessTypeEnum.QT.getLabel()); |
||||
// 追责对象(涉及个人)
|
||||
dto.setAccountabilityTarget(AccountabilityTargetEnum.PERSONAL.getValue()); |
||||
// 反映人信息
|
||||
dto.setResponderName(mail.getContactName()); |
||||
dto.setContactPhone(mail.getContactPhone()); |
||||
// 办理状态(已完成)
|
||||
dto.setProcessingStatus("completed"); |
||||
// 来信内容
|
||||
dto.setThingDesc(mail.getContent()); |
||||
|
||||
// 涉及单位设置
|
||||
dto.setInvolveDepartId(thirdDepart.getId()); |
||||
dto.setInvolveDepartName(thirdDepart.getName()); |
||||
// 办理单位设置
|
||||
dto.setHandleSecondDepartId(secondDepart.getId()); |
||||
dto.setHandleSecondDepartName(secondDepart.getName()); |
||||
dto.setHandleThreeDepartId(thirdDepart.getId()); |
||||
dto.setHandleThreeDepartName(thirdDepart.getName()); |
||||
|
||||
// 来信附件
|
||||
dto.setThingFiles(buildThingFiles(mail.getAttachments())); |
||||
|
||||
// 来源字段
|
||||
dto.setSourceType(NegativeSourceTypeEnum.COMPLAINT_REPORT.getCode()); |
||||
dto.setSourceTypeDesc(NegativeSourceTypeEnum.COMPLAINT_REPORT.getDesc()); |
||||
// dto.setIssuingDepartId("-1");
|
||||
// dto.setIssuingDepartName("自定抓取");
|
||||
return dto; |
||||
} |
||||
|
||||
/** |
||||
* 构建问题附件列表 |
||||
*/ |
||||
private List<NegativeThingFile> buildThingFiles(String attachmentsJson) { |
||||
List<MailAttachmentDTO> attachments = parseAttachments(attachmentsJson); |
||||
if (CollectionUtil.isEmpty(attachments)) { |
||||
return Collections.emptyList(); |
||||
} |
||||
List<NegativeThingFile> list = new ArrayList<>(); |
||||
for (MailAttachmentDTO att : attachments) { |
||||
NegativeThingFile file = new NegativeThingFile(); |
||||
file.setFileName(StrUtil.isNotBlank(att.getOriginFilename()) ? att.getOriginFilename() : getFileName(att.getFilepath())); |
||||
file.setFilePath(att.getFilepath()); |
||||
file.setCreateTime(LocalDateTime.now()); |
||||
list.add(file); |
||||
} |
||||
return list; |
||||
} |
||||
|
||||
/** |
||||
* 解析附件 JSON |
||||
*/ |
||||
private List<MailAttachmentDTO> parseAttachments(String json) { |
||||
if (StrUtil.isBlank(json)) { |
||||
return Collections.emptyList(); |
||||
} |
||||
try { |
||||
List<MailAttachmentDTO> list = JSON.parseArray(json, MailAttachmentDTO.class); |
||||
list.forEach(item -> { |
||||
String filepath = null; |
||||
if (StrUtil.isNotBlank(item.getDocxFilepath())) { |
||||
filepath = "http://65.47.60.145/lan-api/api/file/stream/" + item.getDocxFilepath(); |
||||
} else { |
||||
filepath = "http://65.47.60.145/lan-api/api/file/stream/" + item.getFilepath(); |
||||
} |
||||
item.setFilepath(filepath); |
||||
}); |
||||
return list; |
||||
} catch (Exception e) { |
||||
log.warn("【局长信箱已办结抓取】附件JSON解析失败,json={}", json, e); |
||||
return Collections.emptyList(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 从路径获取文件名 |
||||
*/ |
||||
private String getFileName(String path) { |
||||
if (path == null) return null; |
||||
int index = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\')); |
||||
return index == -1 ? path : path.substring(index + 1); |
||||
} |
||||
|
||||
// ==================== ComplaintCollection 组装 ====================
|
||||
|
||||
/** |
||||
* 构建 ComplaintCollection |
||||
*/ |
||||
private ComplaintCollection buildComplaintCollection(Mail mail, String negativeId, SupDepart secondDepart, SupDepart thirdDepart) { |
||||
ComplaintCollection cc = new ComplaintCollection(); |
||||
// 设置问题编号
|
||||
cc.setNegativeId(negativeId); |
||||
cc.setOriginId(mail.getId()); |
||||
// 问题来源信息
|
||||
String sfssSourceTableSubOne = getSfssSourceTableSubOne(mail.getSource()); |
||||
cc.setSourceTable(ComplaintCollectionSourceTableEnum.MAYOR_MAILBOX.getCode()); |
||||
cc.setSourceTableSubOne(sfssSourceTableSubOne); |
||||
// 单位信息
|
||||
cc.setSecondDepartId(secondDepart.getId()); |
||||
cc.setSecondDepartName(secondDepart.getShortName()); |
||||
cc.setThirdDepartId(thirdDepart.getId()); |
||||
cc.setThirdDepartName(thirdDepart.getShortName()); |
||||
// 创建时间用来信时间
|
||||
cc.setCreateTime(mail.getMailTime()); |
||||
cc.setCreateBy("自动抓取"); |
||||
|
||||
// 身份证
|
||||
cc.setResponderIdCode(mail.getContactIdCard()); |
||||
|
||||
// 初核信息
|
||||
cc.setGwf3(ComplaintCollectionInitialEnum.UN_UPLOADED.getCode()); |
||||
return cc; |
||||
} |
||||
|
||||
|
||||
private String getSfssSourceTableSubOne(String str) { |
||||
if ("厅长信箱".equals(str)) { |
||||
return "23_tz"; |
||||
} |
||||
if ("mailbox".equals(str)) { |
||||
return "23_jz"; |
||||
} |
||||
if ("110_report_complaints".equals(str)) { |
||||
return "23_jb"; |
||||
} |
||||
return ""; |
||||
} |
||||
|
||||
// ==================== 延期同步(初核信息) ====================
|
||||
|
||||
/** |
||||
* 同步延期信息(初核工作开展情况、初核附件) |
||||
* 延期数据来源于 mailbox.mail_extension 表 |
||||
* - initWorkDes: 初核工作开展情况 <- extensionReason |
||||
* - initFile: 初核附件 <- initialVerifyAttachments |
||||
*/ |
||||
public void syncExtension() { |
||||
log.info("【延期同步】开始执行延期信息同步任务"); |
||||
long startTimeMillis = System.currentTimeMillis(); |
||||
|
||||
try { |
||||
// 1. 查询所有局长信箱来源没有初核的记录
|
||||
List<ComplaintCollection> mailBoxList = queryAllMailboxRecords(); |
||||
if (CollectionUtil.isEmpty(mailBoxList)) { |
||||
log.info("【延期同步】无局长信箱记录"); |
||||
return; |
||||
} |
||||
log.info("【延期同步】查询到局长信箱数量:{}", mailBoxList.size()); |
||||
|
||||
// 2. 遍历处理
|
||||
int successCount = 0; |
||||
int skipCount = 0; |
||||
int failCount = 0; |
||||
|
||||
for (ComplaintCollection cc : mailBoxList) { |
||||
try { |
||||
String originId = cc.getOriginId(); |
||||
// 查询延期信息(可扩展:后续可能来自多个来源)
|
||||
MailExtension extension = fetchExtensionInfo(originId); |
||||
if (extension == null) { |
||||
// 无延期记录(直接办结),只计算初核状态
|
||||
log.debug("【延期同步】无延期数据,直接计算初核状态:originId=" + originId); |
||||
syncInitialStatusForDirectCompletion(cc.getOriginId(), cc.getId()); |
||||
skipCount++; |
||||
continue; |
||||
} |
||||
|
||||
// 找到信件
|
||||
Mail mail = getMailByOriginId(originId); |
||||
ComplaintCollection complaintCollection = getComplaintCollectionByOriginId(originId); |
||||
// 初核计算
|
||||
syncInitialStatusWithExtension(mail, complaintCollection, extension); |
||||
successCount++; |
||||
} catch (Exception e) { |
||||
failCount++; |
||||
log.error("【延期同步】处理失败: ccId={}, error={}", cc.getId(), e.getMessage(), e); |
||||
} |
||||
} |
||||
|
||||
long cost = System.currentTimeMillis() - startTimeMillis; |
||||
log.info("【延期同步】完成,总数:{},成功:{},跳过:{},失败:{},耗时:{}ms", |
||||
mailBoxList.size(), successCount, skipCount, failCount, cost); |
||||
} catch (Exception e) { |
||||
log.error("【延期同步】任务执行过程中发生严重异常", e); |
||||
throw e; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 查询所有局长信箱来源并初核情况是空的记录 |
||||
*/ |
||||
private List<ComplaintCollection> queryAllMailboxRecords() { |
||||
LambdaQueryWrapper<ComplaintCollection> queryWrapper = new LambdaQueryWrapper<>(); |
||||
queryWrapper.isNotNull(ComplaintCollection::getGwf3); |
||||
queryWrapper.eq(ComplaintCollection::getProblemSourcesCode, ComplaintCollectionSourceTableEnum.MAYOR_MAILBOX.getCode()); |
||||
return complaintCollectionMapper.selectList(queryWrapper); |
||||
} |
||||
|
||||
/** |
||||
* 根据 originId 获取 Mail |
||||
* |
||||
* @param originId 原始信件ID |
||||
* @return Mail 实体 |
||||
*/ |
||||
private Mail getMailByOriginId(String originId) { |
||||
LambdaQueryWrapper<Mail> queryWrapper = new LambdaQueryWrapper<>(); |
||||
queryWrapper.eq(Mail::getId, originId); |
||||
Mail mail = mailService.getOne(queryWrapper); |
||||
if (mail == null) { |
||||
log.warn("【延期同步】未找到 Mail:originId={}", originId); |
||||
} |
||||
return mail; |
||||
} |
||||
|
||||
/** |
||||
* 根据 originId 获取 ComplaintCollection |
||||
* |
||||
* @param originId 原始信件ID |
||||
* @return ComplaintCollection 实体 |
||||
*/ |
||||
private ComplaintCollection getComplaintCollectionByOriginId(String originId) { |
||||
ComplaintCollectionQueryParam queryParam = new ComplaintCollectionQueryParam(); |
||||
queryParam.setOriginId(originId); |
||||
List<ComplaintCollection> list = complaintCollectionResourceService.query(queryParam); |
||||
if (CollectionUtil.isEmpty(list)) { |
||||
throw new IllegalArgumentException(String.format("未找到对应投诉举报数据,编号%s", originId)); |
||||
} |
||||
return list.get(0); |
||||
} |
||||
|
||||
/** |
||||
* 有延期记录时,同步初核状态 |
||||
* |
||||
* @param mail 邮件实体 |
||||
* @param cc 归集记录 |
||||
* @param extension 延期信息 |
||||
*/ |
||||
private void syncInitialStatusWithExtension(Mail mail, ComplaintCollection cc, MailExtension extension) { |
||||
long maxSeconds = CHECK_LIMIT_DAYS * TimeUtil.SECONDS_OF_A_DAY; |
||||
long remainingAtInitial = TimeUtil.getRemainingDuration(mail.getMailTime(), extension.getCreateTime(), maxSeconds); |
||||
String initialReviewStatus = (remainingAtInitial < 0) ? |
||||
ComplaintCollectionInitialEnum.TIMEOUT_UPLOAD.getCode() : ComplaintCollectionInitialEnum.UPLOADED.getCode(); |
||||
|
||||
ComplaintCollectionUpdateParam updateParam = new ComplaintCollectionUpdateParam(); |
||||
updateParam.setId(cc.getId()); |
||||
updateParam.setGwf2(String.valueOf(extension.getCreateTime())); |
||||
updateParam.setGwf3(initialReviewStatus); |
||||
updateParam.setInitWorkDes(extension.getExtensionReason()); |
||||
updateParam.setInitFile(extension.getInitialVerifyAttachments()); |
||||
complaintCollectionResourceService.updateSelectiveById(updateParam); |
||||
} |
||||
|
||||
/** |
||||
* 获取延期信息(扩展点:后续可支持多个来源) |
||||
* 拿最早的那次记录 |
||||
* @param originId 原始信件ID |
||||
* @return 延期信息,未找到返回 null |
||||
*/ |
||||
private MailExtension fetchExtensionInfo(String originId) { |
||||
// ========== 扩展点:后续可在此添加其他初核信息来源 ==========
|
||||
// 目前仅从 mail_extension 表获取延期信息,取创建时间最早的那条
|
||||
List<MailExtension> extensions = mailExtensionMapper.selectList( |
||||
new LambdaQueryWrapper<MailExtension>() |
||||
.eq(MailExtension::getMailId, originId) |
||||
.orderByAsc(MailExtension::getCreateTime) |
||||
.last("LIMIT 1") |
||||
); |
||||
return CollectionUtil.isEmpty(extensions) ? null : extensions.get(0); |
||||
} |
||||
|
||||
/** |
||||
* 无延期记录时(直接办结),计算初核状态 |
||||
* - 初核时间(gwf2)= submit_completion_time(提交办理时间) |
||||
* - 若 submit_completion_time 为空,则跳过(说明未办结也未申请延期) |
||||
* |
||||
* @param originId 原始信件ID |
||||
* @param ccId 归集记录ID |
||||
*/ |
||||
private void syncInitialStatusForDirectCompletion(String originId, String ccId) { |
||||
// 1. 查询 Mail
|
||||
Mail mail = getMailByOriginId(originId); |
||||
if (mail == null) { |
||||
return; |
||||
} |
||||
|
||||
// 2. 检查是否有 submit_completion_time
|
||||
LocalDateTime submitCompletionTime = mail.getSubmitCompletionTime(); |
||||
if (submitCompletionTime == null) { |
||||
// 未办结也未申请延期,跳过本次计算
|
||||
log.debug("【延期同步】无延期且未提交办理时间,跳过:originId={}", originId); |
||||
return; |
||||
} |
||||
|
||||
// 3. 用 submit_completion_time 计算初核状态
|
||||
LocalDateTime mailTime = mail.getMailTime(); |
||||
long maxSeconds = CHECK_LIMIT_DAYS * TimeUtil.SECONDS_OF_A_DAY; |
||||
long remainingAtInitial = TimeUtil.getRemainingDuration(mailTime, submitCompletionTime, maxSeconds); |
||||
String initialReviewStatus = (remainingAtInitial < 0) ? |
||||
ComplaintCollectionInitialEnum.TIMEOUT_UPLOAD.getCode() : |
||||
ComplaintCollectionInitialEnum.UPLOADED.getCode(); |
||||
|
||||
// 4. 更新
|
||||
ComplaintCollectionUpdateParam updateParam = new ComplaintCollectionUpdateParam(); |
||||
updateParam.setId(ccId); |
||||
updateParam.setGwf2(String.valueOf(submitCompletionTime)); |
||||
updateParam.setGwf3(initialReviewStatus); |
||||
updateParam.setInitWorkDes("直接办结"); |
||||
complaintCollectionResourceService.updateSelectiveById(updateParam); |
||||
|
||||
log.debug("【延期同步】无延期记录,初核状态计算完成:originId={}, status={}", |
||||
originId, initialReviewStatus); |
||||
} |
||||
|
||||
} |
||||
File diff suppressed because it is too large
Load Diff
@ -1,104 +0,0 @@
|
||||
package com.biutag.supervision.util; |
||||
|
||||
import cn.hutool.core.util.StrUtil; |
||||
|
||||
/** |
||||
* 参数校验工具类 |
||||
* 用于统一校验请求参数中的字符串,校验失败抛出 IllegalArgumentException |
||||
*/ |
||||
public class CheckUtil { |
||||
|
||||
/** |
||||
* 校验字符串不能为 null 或纯空白字符 |
||||
* |
||||
* @param str 待校验字符串 |
||||
* @param message 异常信息 |
||||
* @throws IllegalArgumentException 如果字符串为 null 或空白 |
||||
*/ |
||||
public static void checkNotBlank(String str, String message) { |
||||
if (StrUtil.isBlank(str)) { |
||||
throw new IllegalArgumentException(message); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 校验字符串不能为 null(允许空字符串) |
||||
* |
||||
* @param str 待校验字符串 |
||||
* @param message 异常信息 |
||||
* @throws IllegalArgumentException 如果字符串为 null |
||||
*/ |
||||
public static void checkNotNull(String str, String message) { |
||||
if (str == null) { |
||||
throw new IllegalArgumentException(message); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 校验字符串长度不能超过指定最大值 |
||||
* |
||||
* @param str 待校验字符串 |
||||
* @param max 最大长度 |
||||
* @param message 异常信息 |
||||
* @throws IllegalArgumentException 如果字符串长度超过 max |
||||
*/ |
||||
public static void checkMaxLength(String str, int max, String message) { |
||||
if (str != null && str.length() > max) { |
||||
throw new IllegalArgumentException(message); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 校验字符串长度不能小于指定最小值 |
||||
* |
||||
* @param str 待校验字符串 |
||||
* @param min 最小长度 |
||||
* @param message 异常信息 |
||||
* @throws IllegalArgumentException 如果字符串长度小于 min |
||||
*/ |
||||
public static void checkMinLength(String str, int min, String message) { |
||||
if (str != null && str.length() < min) { |
||||
throw new IllegalArgumentException(message); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 校验字符串长度必须在指定范围内 |
||||
* |
||||
* @param str 待校验字符串 |
||||
* @param min 最小长度(包含) |
||||
* @param max 最大长度(包含) |
||||
* @param message 异常信息 |
||||
* @throws IllegalArgumentException 如果字符串长度不在 [min, max] 范围内 |
||||
*/ |
||||
public static void checkLengthRange(String str, int min, int max, String message) { |
||||
if (str != null && (str.length() < min || str.length() > max)) { |
||||
throw new IllegalArgumentException(message); |
||||
} |
||||
} |
||||
|
||||
|
||||
/** |
||||
* 校验多个字符串是否全部为 null 或纯空白字符(即全部为空) |
||||
* 如果全部为空,则抛出 IllegalArgumentException |
||||
* |
||||
* @param message 异常信息 |
||||
* @param strings 待校验的字符串数组 |
||||
* @throws IllegalArgumentException 如果所有字符串均为 null 或空白 |
||||
*/ |
||||
public static void checkNotAllBlank(String message, String... strings) { |
||||
if (strings == null || strings.length == 0) { |
||||
throw new IllegalArgumentException(message); |
||||
} |
||||
boolean allBlank = true; |
||||
for (String str : strings) { |
||||
if (StrUtil.isNotBlank(str)) { |
||||
allBlank = false; |
||||
break; |
||||
} |
||||
} |
||||
if (allBlank) { |
||||
throw new IllegalArgumentException(message); |
||||
} |
||||
} |
||||
} |
||||
Loading…
Reference in new issue