Просмотр исходного кода

Merge branch 'V0.0.8' of http://10.87.21.221:8000/jzyd_yyds/soc into V0.0.8

 Conflicts:
	project_data/sql/0.0.8/soc/soc.sql
zhulu 1 год назад
Родитель
Сommit
e74bd63147
76 измененных файлов с 2939 добавлено и 302 удалено
  1. 7 0
      pom.xml
  2. 74 0
      project_data/sql/0.0.8/soc/soc.sql
  3. 2 0
      soc-api/soc-api-system/src/main/java/com/xunmei/system/api/RemoteFileService.java
  4. 44 0
      soc-api/soc-api-system/src/main/java/com/xunmei/system/api/domain/SysVersion.java
  5. 46 0
      soc-api/soc-api-system/src/main/java/com/xunmei/system/api/enums/AppType.java
  6. 5 0
      soc-api/soc-api-system/src/main/java/com/xunmei/system/api/factory/RemoteFileFallbackFactory.java
  7. 57 0
      soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/reminder/domain/CoreReminderConfiguration.java
  8. 50 0
      soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/reminder/domain/CoreReminderConfigurationOrg.java
  9. 38 0
      soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/reminder/domain/CoreReminderConfigurationRole.java
  10. 63 0
      soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/reminder/domain/CoreReminderLog.java
  11. 59 0
      soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/reminder/domain/CoreReminderSchedule.java
  12. 50 0
      soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/reminder/domain/CoreReminderTemplate.java
  13. 40 0
      soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/reminder/dto/ReminderConfigEditDto.java
  14. 31 0
      soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/reminder/dto/ReminderConfigPageDto.java
  15. 54 0
      soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/reminder/vo/ReminderConfigDetailVo.java
  16. 34 0
      soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/reminder/vo/ReminderConfigPageVo.java
  17. 6 7
      soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/retrieval/domain/CoreMonitoringRetrievalTask.java
  18. 45 0
      soc-common/soc-common-core/src/main/java/com/xunmei/common/core/enums/BusinessPlanType.java
  19. 2 2
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/access/service/impl/CoreMonitoringTaskRegistrationServiceImpl.java
  20. 243 111
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/access/service/impl/TMonitoringRetrievalPlanServiceImpl.java
  21. 31 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/compense/controller/CompensateController.java
  22. 27 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/compense/dto/CompensateDto.java
  23. 29 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/compense/handel/CompensateHandel.java
  24. 16 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/compense/interfaces/CompensateService.java
  25. 1 1
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/drill/service/ICoreDrillTaskService.java
  26. 186 28
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/drill/service/impl/CoreDrillPlanServiceImpl.java
  27. 33 10
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/drill/service/impl/CoreDrillTaskServiceImpl.java
  28. 1 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/edu/service/ICoreEduTrainingTaskService.java
  29. 167 4
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/edu/service/impl/CoreEduTrainingPlanServiceImpl.java
  30. 20 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/edu/service/impl/CoreEduTrainingTaskServiceImpl.java
  31. 56 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/controller/CoreReminderConfigurationController.java
  32. 21 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/controller/CoreReminderLogController.java
  33. 21 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/controller/CoreReminderScheduleController.java
  34. 21 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/controller/CoreReminderTemplateController.java
  35. 21 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/mapper/CoreReminderConfigurationMapper.java
  36. 22 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/mapper/CoreReminderConfigurationOrgMapper.java
  37. 21 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/mapper/CoreReminderConfigurationRoleMapper.java
  38. 16 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/mapper/CoreReminderLogMapper.java
  39. 16 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/mapper/CoreReminderScheduleMapper.java
  40. 16 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/mapper/CoreReminderTemplateMapper.java
  41. 16 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/ICoreReminderConfigurationOrgService.java
  42. 16 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/ICoreReminderConfigurationRoleService.java
  43. 25 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/ICoreReminderConfigurationService.java
  44. 16 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/ICoreReminderLogService.java
  45. 16 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/ICoreReminderScheduleService.java
  46. 16 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/ICoreReminderTemplateService.java
  47. 20 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/impl/CoreReminderConfigurationOrgServiceImpl.java
  48. 20 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/impl/CoreReminderConfigurationRoleServiceImpl.java
  49. 134 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/impl/CoreReminderConfigurationServiceImpl.java
  50. 20 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/impl/CoreReminderLogServiceImpl.java
  51. 20 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/impl/CoreReminderScheduleServiceImpl.java
  52. 20 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/impl/CoreReminderTemplateServiceImpl.java
  53. 4 0
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/resumption/mapper/AppPlanToExecOrgMapper.java
  54. 205 71
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/resumption/service/impl/AppPlanServiceImpl.java
  55. 2 9
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/retrieval/service/ICoreMonitoringRetrievalTaskBuilderService.java
  56. 57 33
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/retrieval/service/impl/CoreMonitoringRetrievalTaskBuilderServiceImpl.java
  57. 11 12
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/safetyCheck/job/SafetyCheckJobBusiness.java
  58. 166 6
      soc-modules/soc-modules-core/src/main/java/com/xunmei/core/safetyCheck/service/impl/CoreSafecheckPlanServiceImpl.java
  59. 38 0
      soc-modules/soc-modules-core/src/main/resources/mapper/reminder/CoreReminderConfigurationMapper.xml
  60. 14 0
      soc-modules/soc-modules-core/src/main/resources/mapper/reminder/CoreReminderConfigurationOrgMapper.xml
  61. 15 0
      soc-modules/soc-modules-core/src/main/resources/mapper/reminder/CoreReminderConfigurationRoleMapper.xml
  62. 5 0
      soc-modules/soc-modules-core/src/main/resources/mapper/reminder/CoreReminderLogMapper.xml
  63. 5 0
      soc-modules/soc-modules-core/src/main/resources/mapper/reminder/CoreReminderScheduleMapper.xml
  64. 5 0
      soc-modules/soc-modules-core/src/main/resources/mapper/reminder/CoreReminderTemplateMapper.xml
  65. 3 0
      soc-modules/soc-modules-core/src/main/resources/mapper/resumption/AppPlanToExecOrgMapper.xml
  66. 14 2
      soc-modules/soc-modules-file/src/main/java/com/xunmei/file/controller/SysFileController.java
  67. 1 1
      soc-modules/soc-modules-file/src/main/java/com/xunmei/file/service/ISysFileService.java
  68. 4 1
      soc-modules/soc-modules-file/src/main/java/com/xunmei/file/service/LocalSysFileServiceImpl.java
  69. 4 4
      soc-modules/soc-modules-gen/src/main/java/com/xunmei/gen/util/CodeGenerators.java
  70. 6 0
      soc-modules/soc-modules-system/pom.xml
  71. 67 0
      soc-modules/soc-modules-system/src/main/java/com/xunmei/system/controller/SysVersionController.java
  72. 29 0
      soc-modules/soc-modules-system/src/main/java/com/xunmei/system/dto/SysCheckUpdateDto.java
  73. 11 0
      soc-modules/soc-modules-system/src/main/java/com/xunmei/system/mapper/SysVersionMapper.java
  74. 31 0
      soc-modules/soc-modules-system/src/main/java/com/xunmei/system/service/ISysVersionService.java
  75. 201 0
      soc-modules/soc-modules-system/src/main/java/com/xunmei/system/service/impl/SysVersionServiceImpl.java
  76. 10 0
      soc-modules/soc-modules-system/src/main/resources/mapper/system/SysVersionMapper.xml

+ 7 - 0
pom.xml

@@ -43,6 +43,7 @@
         <freemarker.version>2.7.2</freemarker.version>
         <velocity.version>2.3</velocity.version>
         <knife4j.version>3.0.3</knife4j.version>
+        <zafarkhaja.version>0.9.0</zafarkhaja.version>
     </properties>
     <dependencyManagement>
         <dependencies>
@@ -242,6 +243,12 @@
                 <artifactId>lombok</artifactId>
                 <version>${lombok.version}</version>
             </dependency>
+
+            <dependency>
+                <groupId>com.github.zafarkhaja</groupId>
+                <artifactId>java-semver</artifactId>
+                <version>${zafarkhaja.version}</version>
+            </dependency>
 <!--                    <dependency>-->
 <!--                        <groupId>log4j</groupId>-->
 <!--                        <artifactId>log4j</artifactId>-->

+ 74 - 0
project_data/sql/0.0.8/soc/soc.sql

@@ -1,3 +1,77 @@
+create table if not exists core_reminder_configuration(
+    config_id             bigint               not null comment '配置ID'
+        primary key,
+    reminder_type         int                  not null comment '提醒类型(0:逾期提醒、1:临期提醒)',
+    send_module           varchar(50)          not null comment '发送模块(五大计划之一)',
+    org_id                bigint               null comment '发送目标组织机构',
+    org_name              varchar(125)         not null comment '发送目标组织机构',
+    org_path              varchar(125)         not null comment '发送目标组织机构',
+    org_type              int                  null comment '发送目标机构类型',
+    advance_notice_period int                  not null comment '临期时间(以天数表示)',
+    overdue_notice_period int                  not null comment '逾期时间(以天数表示)',
+    enabled               tinyint(1) default 1 not null comment '是否启用该提醒配置'
+)
+    comment '短信提醒配置表';
+-- auto-generated definition
+create table if not exists core_reminder_configuration_role(
+    config_id        bigint not null,
+    target_role_id   bigint not null,
+    target_role_name bigint not null,
+    primary key (config_id, target_role_id)
+)
+    comment '短信提醒配置角色关联表';
+
+create table if not exists core_reminder_configuration_org(
+    config_id        bigint not null comment '配置id',
+    target_org_id   bigint not null comment '发送目标机构id',
+    target_org_name varchar(125) not null comment '发送目标机构名称',
+    target_org_type int not null comment '发送目标机构类型',
+    target_org_path varchar(125) not null comment '发送目标机构路径',
+    primary key (config_id, target_org_id)
+)
+    comment '短信提醒配置机构关联表';
+
+-- auto-generated definition
+create table if not exists core_reminder_log(
+    log_id             bigint      not null comment '日志ID'
+        primary key,
+    schedule_id        bigint      not null comment '关联的提醒任务ID',
+    recipient_id       bigint      not null comment '目标接收者id',
+    recipient_name     varchar(50) not null comment '目标接收者',
+    message_content    text        not null comment '实际发送的短信内容',
+    send_time          datetime    not null comment '发送时间',
+    result_code        varchar(50) null comment '发送结果代码',
+    result_description text        null comment '发送结果描述'
+)
+    comment '短信提醒事件日志表';
+
+-- auto-generated definition
+create table if not exists core_reminder_schedule(
+    schedule_id    bigint        not null comment '任务ID'
+        primary key,
+    config_id      bigint        not null comment '关联的提醒配置ID',
+    recipient      varchar(50)   not null comment '目标接收者(手机号码或用户ID)',
+    scheduled_time datetime      null comment '计划发送时间',
+    status         varchar(20)   not null comment '任务状态(未发送、已发送、发送失败等)',
+    sent_time      datetime      null comment '实际发送时间(若已发送)',
+    retry_count    int default 0 null comment '重试次数(用于处理发送失败情况)'
+)
+    comment '短信提醒事件(任务)表';
+
+-- auto-generated definition
+create table if not exists core_reminder_template(
+    template_id      bigint       not null comment '模板ID'
+        primary key,
+    reminder_type    int          not null comment '提醒类型(与 core_reminder_configuration 关联)',
+    template_name    varchar(100) not null comment '模板名称',
+    template_content text         not null comment '提醒短信具体内容(支持变量替换)',
+    language         varchar(20)  not null comment '模板语言'
+)
+    comment '短信提醒内容模板表';
+
+
+
+
 DROP TABLE IF EXISTS `core_safety_work_summary`;
 CREATE TABLE `core_safety_work_summary` (
                                             `id` bigint NOT NULL,

+ 2 - 0
soc-api/soc-api-system/src/main/java/com/xunmei/system/api/RemoteFileService.java

@@ -98,4 +98,6 @@ public interface RemoteFileService {
 
     @PostMapping(value = "/file/readFile")
     byte[] readFile(@RequestBody Map<String, String> data);
+    @PostMapping(value = "/file/downloadFile/realName", consumes = MediaType.APPLICATION_JSON_VALUE)
+    Response downloadFileRealName(@RequestBody SysFile sysFile);
 }

+ 44 - 0
soc-api/soc-api-system/src/main/java/com/xunmei/system/api/domain/SysVersion.java

@@ -0,0 +1,44 @@
+package com.xunmei.system.api.domain;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.xunmei.common.core.web.domain.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 版本管理表 sys_version
+ *
+ * @author xunmei
+ */
+@Data
+@TableName("sys_version")
+@ApiModel(value = "SysVersion对象", description = "【请填写功能名称】")
+public class SysVersion extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键id")
+    private Long id;
+
+    @ApiModelProperty(value = "版本号")
+    private String version;
+
+    @ApiModelProperty(value = "版本说明")
+    private String note;
+
+    @ApiModelProperty(value = "下载地址")
+    private String path;
+
+    @ApiModelProperty(value = "文件名称")
+    private String packageName;
+
+    @ApiModelProperty(value = "是否使用")
+    private Boolean isUse;
+
+    @ApiModelProperty(value = "是否强制更新")
+    private Boolean isForce;
+
+    @ApiModelProperty(value = "版本类型 0.安卓 1.PC 2.挂墙终端 3.IOS")
+    private Integer type;
+}

+ 46 - 0
soc-api/soc-api-system/src/main/java/com/xunmei/system/api/enums/AppType.java

@@ -0,0 +1,46 @@
+package com.xunmei.system.api.enums;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.xunmei.system.api.enums.serializer.EnumSerializer;
+import lombok.Getter;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * 应用类型
+ */
+@JsonSerialize(using = EnumSerializer.class)
+@Getter
+public enum AppType {
+    APP(0,"安卓","APP"),
+    PC(1,"PC","PC"),
+    HANG_WALL(2,"挂墙终端","HANG_WALL"),
+    IOS(3,"IOS","IOS"),
+    ;
+
+    private final Integer index;
+    private final String text;
+    private final String typeDesc;
+
+    AppType(Integer index, String text, String typeDesc) {
+        this.index = index;
+        this.text = text;
+        this.typeDesc = typeDesc;
+    }
+
+    public static AppType getEnumByIndex(Integer index) {
+        return enumMap.get(index);
+    }
+
+    /**
+     * 所有枚举
+     */
+    private static final Map<Integer, AppType> enumMap = new LinkedHashMap<>();
+
+    static {
+        for (AppType typeEnum : AppType.values()) {
+            enumMap.put(typeEnum.index, typeEnum);
+        }
+    }
+}

+ 5 - 0
soc-api/soc-api-system/src/main/java/com/xunmei/system/api/factory/RemoteFileFallbackFactory.java

@@ -96,6 +96,11 @@ public class RemoteFileFallbackFactory implements FallbackFactory<RemoteFileServ
             public byte[] readFile(Map<String, String> data) {
                 throw new RuntimeException("读取文件超时,请稍后重试!");
             }
+
+            @Override
+            public Response downloadFileRealName(SysFile sysFile) {
+                return null;
+            }
         };
     }
 }

+ 57 - 0
soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/reminder/domain/CoreReminderConfiguration.java

@@ -0,0 +1,57 @@
+package com.xunmei.common.core.domain.reminder.domain;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ *
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("core_reminder_configuration")
+@ApiModel(value = "CoreReminderConfiguration对象", description = "")
+public class CoreReminderConfiguration implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "配置ID")
+    @TableId("config_id")
+    private Long configId;
+
+    @ApiModelProperty(value = "提醒类型(0:逾期提醒、1:临期提醒)")
+    @TableField("reminder_type")
+    private Integer reminderType;
+
+    /**
+     * @see com.xunmei.common.core.enums.BusinessPlanType
+     */
+    @ApiModelProperty(value = "发送模块")
+    @TableField("send_module")
+    private String sendModule;
+
+    @ApiModelProperty(value = "临期时间(以天数表示)")
+    @TableField("advance_notice_period")
+    private Integer advanceNoticePeriod;
+
+    @ApiModelProperty(value = "逾期时间(以天数表示)")
+    @TableField("overdue_notice_period")
+    private Integer overdueNoticePeriod;
+
+    @ApiModelProperty(value = "是否启用该提醒配置")
+    @TableField("enabled")
+    private Boolean enabled;
+
+
+}

+ 50 - 0
soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/reminder/domain/CoreReminderConfigurationOrg.java

@@ -0,0 +1,50 @@
+package com.xunmei.common.core.domain.reminder.domain;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 短信提醒配置机构关联表
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("core_reminder_configuration_org")
+@ApiModel(value="CoreReminderConfigurationOrg对象", description="短信提醒配置机构关联表")
+public class CoreReminderConfigurationOrg implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "配置id")
+    @TableId("config_id")
+    private Long configId;
+
+    @ApiModelProperty(value = "发送目标机构id")
+    @TableField("target_org_id")
+    private Long targetOrgId;
+
+    @ApiModelProperty(value = "发送目标机构名称")
+    @TableField("target_org_name")
+    private String targetOrgName;
+
+    @ApiModelProperty(value = "发送目标机构类型")
+    @TableField("target_org_type")
+    private Integer targetOrgType;
+
+    @ApiModelProperty(value = "发送目标机构路径")
+    @TableField("target_org_path")
+    private String targetOrgPath;
+
+
+}

+ 38 - 0
soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/reminder/domain/CoreReminderConfigurationRole.java

@@ -0,0 +1,38 @@
+package com.xunmei.common.core.domain.reminder.domain;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("core_reminder_configuration_role")
+@ApiModel(value="CoreReminderConfigurationRole对象", description="")
+public class CoreReminderConfigurationRole implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId("config_id")
+    private Long configId;
+
+    @TableField("target_role_id")
+    private Long targetRoleId;
+
+    @TableField("target_role_name")
+    private String targetRoleName;
+
+
+}

+ 63 - 0
soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/reminder/domain/CoreReminderLog.java

@@ -0,0 +1,63 @@
+package com.xunmei.common.core.domain.reminder.domain;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("core_reminder_log")
+@ApiModel(value="CoreReminderLog对象", description="")
+public class CoreReminderLog implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "日志ID")
+    @TableId("log_id")
+    private Long logId;
+
+    @ApiModelProperty(value = "关联的提醒任务ID")
+    @TableField("schedule_id")
+    private Long scheduleId;
+
+    @ApiModelProperty(value = "目标接收者id")
+    @TableField("recipient_id")
+    private Long recipientId;
+
+    @ApiModelProperty(value = "目标接收者名称")
+    @TableField("recipient_name")
+    private String recipientName;
+
+    @ApiModelProperty(value = "实际发送的短信内容")
+    @TableField("message_content")
+    private String messageContent;
+
+    @ApiModelProperty(value = "发送时间")
+    @TableField("send_time")
+    private LocalDateTime sendTime;
+
+    @ApiModelProperty(value = "发送结果代码")
+    @TableField("result_code")
+    private String resultCode;
+
+    @ApiModelProperty(value = "发送结果描述")
+    @TableField("result_description")
+    private String resultDescription;
+
+
+}

+ 59 - 0
soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/reminder/domain/CoreReminderSchedule.java

@@ -0,0 +1,59 @@
+package com.xunmei.common.core.domain.reminder.domain;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("core_reminder_schedule")
+@ApiModel(value="CoreReminderSchedule对象", description="")
+public class CoreReminderSchedule implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "任务ID")
+    @TableId("schedule_id")
+    private Long scheduleId;
+
+    @ApiModelProperty(value = "关联的提醒配置ID")
+    @TableField("config_id")
+    private Long configId;
+
+    @ApiModelProperty(value = "目标接收者(手机号码或用户ID)")
+    @TableField("recipient")
+    private String recipient;
+
+    @ApiModelProperty(value = "计划发送时间")
+    @TableField("scheduled_time")
+    private LocalDateTime scheduledTime;
+
+    @ApiModelProperty(value = "任务状态(未发送、已发送、发送失败等)")
+    @TableField("status")
+    private String status;
+
+    @ApiModelProperty(value = "实际发送时间(若已发送)")
+    @TableField("sent_time")
+    private LocalDateTime sentTime;
+
+    @ApiModelProperty(value = "重试次数(用于处理发送失败情况)")
+    @TableField("retry_count")
+    private Integer retryCount;
+
+
+}

+ 50 - 0
soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/reminder/domain/CoreReminderTemplate.java

@@ -0,0 +1,50 @@
+package com.xunmei.common.core.domain.reminder.domain;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@TableName("core_reminder_template")
+@ApiModel(value="CoreReminderTemplate对象", description="")
+public class CoreReminderTemplate implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "模板ID")
+    @TableId("template_id")
+    private Long templateId;
+
+    @ApiModelProperty(value = "提醒类型(与 core_reminder_configuration 关联)")
+    @TableField("reminder_type")
+    private Integer reminderType;
+
+    @ApiModelProperty(value = "模板名称")
+    @TableField("template_name")
+    private String templateName;
+
+    @ApiModelProperty(value = "提醒短信具体内容(支持变量替换)")
+    @TableField("template_content")
+    private String templateContent;
+
+    @ApiModelProperty(value = "模板语言")
+    @TableField("language")
+    private String language;
+
+
+}

+ 40 - 0
soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/reminder/dto/ReminderConfigEditDto.java

@@ -0,0 +1,40 @@
+package com.xunmei.common.core.domain.reminder.dto;
+
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.util.List;
+
+@Data
+public class ReminderConfigEditDto {
+
+    @ApiModelProperty(value = "提醒配置ID")
+    private Long configId;
+
+    @ApiModelProperty(value = "提醒类型(0:逾期提醒、1:临期提醒)")
+    @NotNull(message = "提醒类型不能为空")
+    private Integer reminderType;
+
+    /**
+     * @see com.xunmei.common.core.enums.BusinessPlanType
+     */
+    @NotNull(message = "业务类型不能为空")
+    @ApiModelProperty(value = "发送模块")
+    private String sendModule;
+
+    @NotNull(message = "天数不能为空")
+    @ApiModelProperty(value = "天数")
+    private Integer day;
+
+    @NotNull(message = "是否启用不能为空")
+    private Boolean enabled = true;
+
+    @Size(message = "角色不能为空",min = 1)
+    private List<Long> roleIdList;
+
+    @Size(message = "发送目标不能为空",min = 1)
+    private List<Long> orgIdList;
+}

+ 31 - 0
soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/reminder/dto/ReminderConfigPageDto.java

@@ -0,0 +1,31 @@
+package com.xunmei.common.core.domain.reminder.dto;
+
+import com.xunmei.common.core.domain.reminder.vo.ReminderConfigPageVo;
+import com.xunmei.common.core.web.domain.PageDto;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import javax.validation.constraints.Size;
+
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class ReminderConfigPageDto extends PageDto<ReminderConfigPageVo> {
+
+    @ApiModelProperty(value = "提醒类型(0:逾期提醒、1:临期提醒)")
+    private Integer reminderType;
+
+    /**
+     * @see com.xunmei.common.core.enums.BusinessPlanType
+     */
+    @ApiModelProperty(value = "发送模块")
+    private String sendModule;
+
+    private Boolean enabled;
+
+    @Size(message = "角色不能为空",min = 1)
+    private Long roleId;
+
+    @Size(message = "发送目标不能为空",min = 1)
+    private Long orgId;
+}

+ 54 - 0
soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/reminder/vo/ReminderConfigDetailVo.java

@@ -0,0 +1,54 @@
+package com.xunmei.common.core.domain.reminder.vo;
+
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderConfigurationOrg;
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderConfigurationRole;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * <p>
+ *
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class ReminderConfigDetailVo implements Serializable {
+
+
+    @ApiModelProperty(value = "配置ID")
+    private Long configId;
+
+    @ApiModelProperty(value = "提醒类型(0:逾期提醒、1:临期提醒)")
+    private Integer reminderType;
+
+    /**
+     * @see com.xunmei.common.core.enums.BusinessPlanType
+     */
+    @ApiModelProperty(value = "发送模块")
+    private String sendModule;
+
+    @ApiModelProperty(value = "临期时间(以天数表示)")
+    private Integer advanceNoticePeriod;
+
+    @ApiModelProperty(value = "逾期时间(以天数表示)")
+    private Integer overdueNoticePeriod;
+
+    @ApiModelProperty(value = "是否启用该提醒配置")
+    private Boolean enabled;
+
+    @ApiModelProperty(value = "发送目标机构")
+    private List<CoreReminderConfigurationOrg> orgList;
+
+    @ApiModelProperty(value = "发送目标角色")
+    private List<CoreReminderConfigurationRole> roleList;
+
+
+
+}

+ 34 - 0
soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/reminder/vo/ReminderConfigPageVo.java

@@ -0,0 +1,34 @@
+package com.xunmei.common.core.domain.reminder.vo;
+
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+public class ReminderConfigPageVo {
+
+    @ApiModelProperty(value = "配置ID")
+    private Long configId;
+
+    @ApiModelProperty(value = "提醒类型(0:逾期提醒、1:临期提醒)")
+    private Integer reminderType;
+
+    /**
+     * @see com.xunmei.common.core.enums.BusinessPlanType
+     */
+    @ApiModelProperty(value = "发送模块")
+    private String sendModule;
+
+    @ApiModelProperty(value = "临期时间(以天数表示)")
+    private Integer advanceNoticePeriod;
+
+    @ApiModelProperty(value = "逾期时间(以天数表示)")
+    private Integer overdueNoticePeriod;
+
+    @ApiModelProperty(value = "是否启用该提醒配置")
+    private Boolean enabled;
+
+    private String orgName;
+
+    private String roleName;
+}

+ 6 - 7
soc-common/soc-common-core/src/main/java/com/xunmei/common/core/domain/retrieval/domain/CoreMonitoringRetrievalTask.java

@@ -1,19 +1,18 @@
 package com.xunmei.common.core.domain.retrieval.domain;
 
-import java.util.Date;
-
+import com.baomidou.mybatisplus.annotation.TableName;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
-import org.apache.commons.lang3.builder.ToStringBuilder;
-import org.apache.commons.lang3.builder.ToStringStyle;
-import com.baomidou.mybatisplus.annotation.TableName;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 import lombok.experimental.Accessors;
-import com.xunmei.common.core.web.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+import java.util.Date;
 
 /**
  * 监控调阅任务对象 core_monitoring_retrieval_task
@@ -26,7 +25,7 @@ import com.xunmei.common.core.web.domain.BaseEntity;
 @Accessors(chain = true)
 @TableName("core_monitoring_retrieval_task")
 @ApiModel(value = "CoreMonitoringRetrievalTask对象", description = "监控调阅任务")
-public class CoreMonitoringRetrievalTask extends BaseEntity {
+public class CoreMonitoringRetrievalTask {
     private static final long serialVersionUID = 1L;
 
     /**

+ 45 - 0
soc-common/soc-common-core/src/main/java/com/xunmei/common/core/enums/BusinessPlanType.java

@@ -0,0 +1,45 @@
+package com.xunmei.common.core.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+@Getter
+@AllArgsConstructor
+public enum BusinessPlanType {
+
+    RESUMPTION("resumption", "安保履职"),
+    SAFETY_CHECK("safetyCheck", "安全检查"),
+    EDU_TRAINING("eduTraining", "教育培训"),
+    DRILL("drill", "预案演练"),
+    MONITORING_RETRIEVAL("monitoringRetrieval", "监控调阅"),
+
+
+
+    ;
+    private final String code;
+
+    private final String name;
+
+    /**
+     * 所有枚举
+     */
+    private static final Map<String, BusinessPlanType> enumMap = new LinkedHashMap<>();
+
+    static {
+        for (BusinessPlanType enumNode : BusinessPlanType.values()) {
+            enumMap.put(enumNode.code, enumNode);
+        }
+    }
+
+
+    /**
+     * 根据code获取name
+     */
+    public static BusinessPlanType getBusinessPlanType(String code) {
+        return enumMap.get(code);
+
+    }
+}

+ 2 - 2
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/access/service/impl/CoreMonitoringTaskRegistrationServiceImpl.java

@@ -143,8 +143,8 @@ private ITMonitoringRetrievalPlanService itMonitoringRetrievalPlanService;
         CoreMonitoringRetrievalTask coreMonitoringRetrievalTask = coreMonitoringRetrievalTaskMapper.selectCoreMonitoringRetrievalTaskById(coreMonitoringTaskRegistration.getTaskId());
         coreMonitoringRetrievalTask.setStatus(TWO);
         coreMonitoringRetrievalTask.setEndTime(DateUtils.getNowDate());
-        coreMonitoringRetrievalTask.setUpdateBy(SecurityUtils.getUsername());
-        coreMonitoringRetrievalTask.setUpdateTime(DateUtils.getNowDate());
+        /*coreMonitoringRetrievalTask.setUpdateBy(SecurityUtils.getUsername());
+        coreMonitoringRetrievalTask.setUpdateTime(DateUtils.getNowDate());*/
         coreMonitoringRetrievalTask.setSubmitTime(DateUtils.getNowDate());
         coreMonitoringRetrievalTask.setRetrievalUser(SecurityUtils.getUserId());
         coreMonitoringRetrievalTask.setSignImg(coreMonitoringTaskRegistration.getSignImgUrl());

+ 243 - 111
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/access/service/impl/TMonitoringRetrievalPlanServiceImpl.java

@@ -4,20 +4,27 @@ package com.xunmei.core.access.service.impl;
 import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.alibaba.nacos.common.utils.CollectionUtils;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.xunmei.common.core.constant.CacheConstants;
 import com.xunmei.common.core.constant.DictConstants;
 import com.xunmei.common.core.constant.ErrorMsgConstants;
 import com.xunmei.common.core.constant.SecurityConstants;
 import com.xunmei.common.core.domain.registerbook.domain.CoreRegisterBookPdf;
 import com.xunmei.common.core.domain.retrieval.domain.CoreMonitoringRetrievalTask;
 import com.xunmei.common.core.enums.OrgTypeEnum;
+import com.xunmei.common.core.enums.PlanStatus;
 import com.xunmei.common.core.enums.RegisterBookType;
+import com.xunmei.common.core.enums.drill.DrillPlanStatus;
 import com.xunmei.common.core.exception.ServiceException;
 import com.xunmei.common.core.exception.SystemException;
 import com.xunmei.common.core.thread.ThreadPoolConfig;
+import com.xunmei.common.core.util.BeanHelper;
 import com.xunmei.common.core.utils.DateUtils;
 import com.xunmei.common.core.utils.StringUtils;
 import com.xunmei.common.core.web.page.TableDataInfo;
@@ -33,13 +40,17 @@ import com.xunmei.core.access.service.ITMonitoringRetrievalPlanService;
 import com.xunmei.core.access.service.ITMonitoringRetrievalPlanToExecOrgService;
 import com.xunmei.core.access.vo.AccessPdfVO;
 import com.xunmei.core.access.vo.TMonitoringRetrievalPlanVO;
+import com.xunmei.core.compense.dto.CompensateDto;
+import com.xunmei.core.compense.interfaces.CompensateService;
 import com.xunmei.core.registerbook.service.ICoreRegisterBookPdfService;
 import com.xunmei.core.retrieval.mapper.CoreMonitoringRetrievalTaskMapper;
 import com.xunmei.core.retrieval.service.ICoreMonitoringRetrievalTaskBuilderService;
 import com.xunmei.core.retrieval.service.ICoreMonitoringRetrievalTaskService;
 import com.xunmei.system.api.*;
 import com.xunmei.system.api.domain.*;
+import com.xunmei.common.core.enums.BusinessPlanType;
 import com.xunmei.system.api.function.RemoteCallHandlerExecutor;
+import com.xunmei.system.api.vo.SysOrgVO;
 import io.netty.util.internal.StringUtil;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -56,13 +67,12 @@ import java.io.File;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.time.LocalDate;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
 import java.util.concurrent.CompletableFuture;
 import java.util.stream.Collectors;
 
+import static java.util.stream.Collectors.toList;
+
 
 /**
  * 监控调阅计划Service业务层处理
@@ -72,7 +82,7 @@ import java.util.stream.Collectors;
  */
 @Lazy
 @Service
-public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoringRetrievalPlanMapper, TMonitoringRetrievalPlan> implements ITMonitoringRetrievalPlanService {
+public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoringRetrievalPlanMapper, TMonitoringRetrievalPlan> implements ITMonitoringRetrievalPlanService, CompensateService {
     private static final Integer ZERO = 0;
     private static final String PARENT_ID = "parent_id";
     @Autowired
@@ -109,6 +119,7 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
     private ThreadPoolTaskExecutor threadPoolTaskExecutor;
     @Autowired
     private RemoteDictDataService dictDataService;
+
     @Override
     public TableDataInfo selectPage(TMonitoringRetrievalPlan tMonitoringRetrievalPlan) {
         //未删除
@@ -593,7 +604,7 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
 
 
         final CompletableFuture<List<TMonitoringRetrievalPlan>> planListFuture = CompletableFuture.supplyAsync(() -> {
-           return getNeedCreateTaskPlans(loginUserOrg, publishPlan);
+            return getNeedCreateTaskPlans(loginUserOrg, publishPlan);
         }, threadPoolTaskExecutor);
 
         planListFuture.thenAcceptAsync((result) -> {
@@ -610,8 +621,7 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
         return i;
     }
 
-    private List<TMonitoringRetrievalPlan> getNeedCreateTaskPlans(SysOrg loginUserOrg,TMonitoringRetrievalPlan publishPlan)
-    {
+    private List<TMonitoringRetrievalPlan> getNeedCreateTaskPlans(SysOrg loginUserOrg, TMonitoringRetrievalPlan publishPlan) {
         List<TMonitoringRetrievalPlan> tempPlans = new ArrayList<>();
         SysOrg publishPlanOrg = remoteOrgService.selectSysOrgById(publishPlan.getOrgId(), SecurityConstants.INNER);
         //如果登录当前是省联社 办事处
@@ -627,7 +637,7 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
                     tm.setPlanStatus(1);
                     tm.setIsDistribute("1");
                     baseMapper.updateById(tm);
-                    setPlanStartEndTime(publishPlan,tm);
+                    setPlanStartEndTime(publishPlan, tm);
                     tempPlans.add(tm);
 //                    if (publishPlan.getOrgType().equals("3")) {
 //                        setPlanStartEndTime(publishPlan,tm);
@@ -646,8 +656,7 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
 //                        }
 //                    }
                 }
-            }
-            else {
+            } else {
                 // 计划机构类型 是 省联社或者办事处及行社以下的机构类型 才创建子计划
                 if (!checkOrgType(Integer.parseInt(publishPlan.getOrgType()))) {
                     // 查询当前计划的具体执行机构
@@ -655,18 +664,17 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
 
                     List<Long> planExecOrgIds = planExecOrgList.stream().map(x -> x.getOrgId()).collect(Collectors.toList());
                     // 根据机构类型和具体调阅机构 获取需创建子计划的机构
-                    List<SysOrg> subPlanOrglist =getPlanOrgListByOrgTypeAndExecOrgs(planExecOrgIds,Integer.parseInt(publishPlan.getOrgType()), publishPlanOrg.getPath());
+                    List<SysOrg> subPlanOrglist = getPlanOrgListByOrgTypeAndExecOrgs(planExecOrgIds, Integer.parseInt(publishPlan.getOrgType()), publishPlanOrg.getPath());
 
-                    List<SysOrg> execOrglist=new ArrayList<>();
-                    if(ObjectUtil.isNotEmpty(planExecOrgList))
-                    {
-                        execOrglist= RemoteCallHandlerExecutor.executeRemoteCall(() ->
-                                        remoteOrgService.selectOrgByIdList(planExecOrgList.stream().map(x->x.getOrgId()).collect(Collectors.toList()), SecurityConstants.INNER),
+                    List<SysOrg> execOrglist = new ArrayList<>();
+                    if (ObjectUtil.isNotEmpty(planExecOrgList)) {
+                        execOrglist = RemoteCallHandlerExecutor.executeRemoteCall(() ->
+                                        remoteOrgService.selectOrgByIdList(planExecOrgList.stream().map(x -> x.getOrgId()).collect(Collectors.toList()), SecurityConstants.INNER),
                                 ErrorMsgConstants.QUERY_ORG_DATA_ERROR);
                     }
 
-                    List<TMonitoringRetrievalPlan> needAddSubPlans=new ArrayList<>();
-                    List<TMonitoringRetrievalPlanToExecOrg> needAddSubPlanExecOrgList=new ArrayList<>();
+                    List<TMonitoringRetrievalPlan> needAddSubPlans = new ArrayList<>();
+                    List<TMonitoringRetrievalPlanToExecOrg> needAddSubPlanExecOrgList = new ArrayList<>();
                     for (SysOrg subPlanOrg : subPlanOrglist) {
                         TMonitoringRetrievalPlan tMonitoringRetrievalPlan1 = new TMonitoringRetrievalPlan();
                         BeanUtils.copyProperties(publishPlan, tMonitoringRetrievalPlan1);
@@ -681,8 +689,8 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
                         tMonitoringRetrievalPlan1.setOrgName(publishPlanOrg.getShortName());
 //                        insertTMonitoringRetrievalPlan(tMonitoringRetrievalPlan1);
                         needAddSubPlans.add(tMonitoringRetrievalPlan1);
-                        if(ObjectUtil.isNotEmpty(planExecOrgList)){
-                            execOrglist.stream().filter(x -> x.getPath().contains(subPlanOrg.getPath())).forEach(x->{
+                        if (ObjectUtil.isNotEmpty(planExecOrgList)) {
+                            execOrglist.stream().filter(x -> x.getPath().contains(subPlanOrg.getPath())).forEach(x -> {
                                 TMonitoringRetrievalPlanToExecOrg tempExecOrg = new TMonitoringRetrievalPlanToExecOrg();
                                 tempExecOrg.setOrgId(x.getId());
                                 tempExecOrg.setPlanId(tMonitoringRetrievalPlan1.getId());
@@ -691,22 +699,20 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
                         }
                     }
                     //保存子计划和子计划具体执行机构
-                    if(ObjectUtil.isNotEmpty(needAddSubPlans))
-                    {
+                    if (ObjectUtil.isNotEmpty(needAddSubPlans)) {
                         this.saveBatch(needAddSubPlans);
                         itMonitoringRetrievalPlanToExecOrgService.saveBatch(needAddSubPlanExecOrgList);
-                        needAddSubPlans.stream().forEach(plan->{
-                            setPlanStartEndTime(plan,plan);
+                        needAddSubPlans.stream().forEach(plan -> {
+                            setPlanStartEndTime(plan, plan);
                         });
                         tempPlans.addAll(needAddSubPlans);
                     }
-                }
-                else{
+                } else {
                     publishPlan.setCreateType(1);
                     publishPlan.setUpdateBy(SecurityUtils.getUsername());
                     publishPlan.setUpdateTime(DateUtils.getNowDate());
                     baseMapper.updateById(publishPlan);
-                    setPlanStartEndTime(publishPlan,publishPlan);
+                    setPlanStartEndTime(publishPlan, publishPlan);
                     tempPlans.add(publishPlan);
                 }
 //                if (publishPlan.getOrgType().equals("3")) {
@@ -730,12 +736,11 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
 //                    }
 //                }
             }
-        }
-        else {
+        } else {
             publishPlan.setCreateType(1);
             publishPlan.setIsDistribute("1");
             baseMapper.updateById(publishPlan);
-            setPlanStartEndTime(publishPlan,publishPlan);
+            setPlanStartEndTime(publishPlan, publishPlan);
             tempPlans.add(publishPlan);
 //            SysOrg sysOrg = new SysOrg();
 //            sysOrg.setPath(loginUserOrg.getPath());
@@ -749,22 +754,20 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
         return tempPlans;
     }
 
-    private List<TMonitoringRetrievalPlan> buildSubPlans(TMonitoringRetrievalPlan parentPlan,List<Long> parentPlanExecOrgIds, SysOrg parentPlanOrg)
-    {
+    private List<TMonitoringRetrievalPlan> buildSubPlans(TMonitoringRetrievalPlan parentPlan, List<Long> parentPlanExecOrgIds, SysOrg parentPlanOrg) {
         List<TMonitoringRetrievalPlan> subPlans = new ArrayList<>();
         // 根据机构类型和具体调阅机构 获取需创建子计划的机构
-        List<SysOrg> hsOrglist =getPlanOrgListByOrgTypeAndExecOrgs(parentPlanExecOrgIds,3,parentPlanOrg.getPath());
+        List<SysOrg> hsOrglist = getPlanOrgListByOrgTypeAndExecOrgs(parentPlanExecOrgIds, 3, parentPlanOrg.getPath());
 
-        List<SysOrg> execOrglist=new ArrayList<>();
-        if(ObjectUtil.isNotEmpty(parentPlanExecOrgIds))
-        {
-            execOrglist= RemoteCallHandlerExecutor.executeRemoteCall(() ->
+        List<SysOrg> execOrglist = new ArrayList<>();
+        if (ObjectUtil.isNotEmpty(parentPlanExecOrgIds)) {
+            execOrglist = RemoteCallHandlerExecutor.executeRemoteCall(() ->
                             remoteOrgService.selectOrgByIdList(parentPlanExecOrgIds, SecurityConstants.INNER),
                     ErrorMsgConstants.QUERY_ORG_DATA_ERROR);
         }
 
-        List<TMonitoringRetrievalPlan> needAddSubPlans=new ArrayList<>();
-        List<TMonitoringRetrievalPlanToExecOrg> needAddSubPlanExecOrgList=new ArrayList<>();
+        List<TMonitoringRetrievalPlan> needAddSubPlans = new ArrayList<>();
+        List<TMonitoringRetrievalPlanToExecOrg> needAddSubPlanExecOrgList = new ArrayList<>();
         for (SysOrg l : hsOrglist) {
             TMonitoringRetrievalPlan tMonitoringRetrievalPlan1 = new TMonitoringRetrievalPlan();
             BeanUtils.copyProperties(parentPlan, tMonitoringRetrievalPlan1);
@@ -780,8 +783,8 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
                 tMonitoringRetrievalPlan1.setOrgName(parentPlanOrg.getShortName());
 //                        insertTMonitoringRetrievalPlan(tMonitoringRetrievalPlan1);
                 needAddSubPlans.add(tMonitoringRetrievalPlan1);
-                if(ObjectUtil.isNotEmpty(parentPlanExecOrgIds)){
-                    execOrglist.stream().filter(x -> x.getPath().contains(l.getPath())).forEach(x->{
+                if (ObjectUtil.isNotEmpty(parentPlanExecOrgIds)) {
+                    execOrglist.stream().filter(x -> x.getPath().contains(l.getPath())).forEach(x -> {
                         TMonitoringRetrievalPlanToExecOrg tempExecOrg = new TMonitoringRetrievalPlanToExecOrg();
                         tempExecOrg.setOrgId(x.getId());
                         tempExecOrg.setPlanId(tMonitoringRetrievalPlan1.getId());
@@ -795,34 +798,31 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
                 parentPlan.setUpdateTime(DateUtils.getNowDate());
                 baseMapper.updateById(parentPlan);
 
-                setPlanStartEndTime(parentPlan,tMonitoringRetrievalPlan1);
+                setPlanStartEndTime(parentPlan, tMonitoringRetrievalPlan1);
                 subPlans.add(tMonitoringRetrievalPlan1);
             } else {
-                List<SysOrg> sysOrgs=getExecOrgList(parentPlanExecOrgIds,Integer.valueOf(parentPlan.getOrgType()),l.getPath());
+                List<SysOrg> sysOrgs = getExecOrgList(parentPlanExecOrgIds, Integer.valueOf(parentPlan.getOrgType()), l.getPath());
                 for (SysOrg s : sysOrgs) {
-                    TMonitoringRetrievalPlan plan = createTempPlan(parentPlan,tMonitoringRetrievalPlan1.getId(),s);
+                    TMonitoringRetrievalPlan plan = createTempPlan(parentPlan, tMonitoringRetrievalPlan1.getId(), s);
                     subPlans.add(plan);
                 }
             }
         }
-        return  subPlans;
+        return subPlans;
     }
 
-    private List<TMonitoringRetrievalPlanToExecOrg> buildPlanExecOrgs(List<TMonitoringRetrievalPlan> plans , List<SysOrg> execOrglist)
-    {
-        if(ObjectUtil.isEmpty(plans))
-        {
+    private List<TMonitoringRetrievalPlanToExecOrg> buildPlanExecOrgs(List<TMonitoringRetrievalPlan> plans, List<SysOrg> execOrglist) {
+        if (ObjectUtil.isEmpty(plans)) {
             return new ArrayList<>();
         }
 
-        if(ObjectUtil.isEmpty(execOrglist))
-        {
+        if (ObjectUtil.isEmpty(execOrglist)) {
             return new ArrayList<>();
         }
-        List<TMonitoringRetrievalPlanToExecOrg> result=new ArrayList<>();
+        List<TMonitoringRetrievalPlanToExecOrg> result = new ArrayList<>();
 
-        plans.stream().forEach(x->{
-            execOrglist.stream().filter(eOrg -> eOrg.getPath().contains(x.getOrgPath())).forEach(y->{
+        plans.stream().forEach(x -> {
+            execOrglist.stream().filter(eOrg -> eOrg.getPath().contains(x.getOrgPath())).forEach(y -> {
                 TMonitoringRetrievalPlanToExecOrg tempExecOrg = new TMonitoringRetrievalPlanToExecOrg();
                 tempExecOrg.setOrgId(y.getId());
                 tempExecOrg.setPlanId(x.getId());
@@ -845,18 +845,17 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
     }
 
     /**
-     *  根据机构类型和具体调阅机构 获取需创建计划的行社机构
+     * 根据机构类型和具体调阅机构 获取需创建计划的行社机构
+     *
      * @param execOrgIds
      * @param orgType
      * @param belongOrgPath
      * @return
      */
-    public List<SysOrg> getPlanOrgListByOrgTypeAndExecOrgs(List<Long> execOrgIds,Integer orgType, String belongOrgPath) {
-        if(ObjectUtil.isNotEmpty(execOrgIds))
-        {
+    public List<SysOrg> getPlanOrgListByOrgTypeAndExecOrgs(List<Long> execOrgIds, Integer orgType, String belongOrgPath) {
+        if (ObjectUtil.isNotEmpty(execOrgIds)) {
             //省联社/办事处/行社
-            if(checkOrgType(orgType))
-            {
+            if (checkOrgType(orgType)) {
                 return RemoteCallHandlerExecutor.executeRemoteCall(() ->
                                 remoteOrgService.selectOrgByIdList(execOrgIds, SecurityConstants.INNER),
                         ErrorMsgConstants.QUERY_ORG_DATA_ERROR);
@@ -865,19 +864,15 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
             else {
                 return RemoteCallHandlerExecutor.executeRemoteCall(() -> remoteOrgService.selectParentHs(execOrgIds, SecurityConstants.INNER), ErrorMsgConstants.QUERY_ORG_DATA_ERROR);
             }
-        }
-        else {
+        } else {
             //省联社/办事处/行社
-            if(checkOrgType(orgType))
-            {
+            if (checkOrgType(orgType)) {
                 SysOrg org = new SysOrg();
                 org.setType(orgType);
                 org.setPath(belongOrgPath);
                 //查询符合的机构,需求是先把行社加入
                 return remoteOrgService.listByParentIdAndType(org, SecurityConstants.INNER);
-            }
-            else
-            {
+            } else {
                 SysOrg org = new SysOrg();
                 org.setType(3);
                 org.setPath(belongOrgPath);
@@ -898,8 +893,7 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
     }
 
     // 准备生成任务需要的临时计划
-    private TMonitoringRetrievalPlan createTempPlan(TMonitoringRetrievalPlan tMonitoringRetrievalPlan,Long planId,SysOrg org)
-    {
+    private TMonitoringRetrievalPlan createTempPlan(TMonitoringRetrievalPlan tMonitoringRetrievalPlan, Long planId, SysOrg org) {
         TMonitoringRetrievalPlan plan = new TMonitoringRetrievalPlan();
         BeanUtils.copyProperties(tMonitoringRetrievalPlan, plan);
         plan.setPlanName(tMonitoringRetrievalPlan.getPlanName());
@@ -956,12 +950,11 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
 //            Date time = cal.getTime();
 //            plan.setEndTime(time);
 //        }
-        setPlanStartEndTime(tMonitoringRetrievalPlan,plan);
+        setPlanStartEndTime(tMonitoringRetrievalPlan, plan);
         return plan;
     }
 
-    private void setPlanStartEndTime(TMonitoringRetrievalPlan tMonitoringRetrievalPlan,TMonitoringRetrievalPlan tempPlan)
-    {
+    private void setPlanStartEndTime(TMonitoringRetrievalPlan tMonitoringRetrievalPlan, TMonitoringRetrievalPlan tempPlan) {
         if (!tMonitoringRetrievalPlan.getPlanCycle().equals(ZERO.toString()) &&
                 tMonitoringRetrievalPlan.getImmediately().equals(Boolean.TRUE)) {
             tempPlan.setStartTime(new Date());
@@ -998,19 +991,18 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
         }
     }
 
-    private void checkPlanIsCreatingTask(Long planId,String msg)
-    {
-        String redisKey="Monitoring_Creating_Task" + planId;
+    private void checkPlanIsCreatingTask(Long planId, String msg) {
+        String redisKey = "Monitoring_Creating_Task" + planId;
         //仅当hashKey不存在时才设置
         Boolean hasKey = RedisUtils.hasKey(redisKey);
         if (hasKey) {
-            throw new ServiceException("该任务正在生成中,现在不能被"+msg+",请稍后再试。");
+            throw new ServiceException("该任务正在生成中,现在不能被" + msg + ",请稍后再试。");
         }
     }
 
     @Override
     public int withdraw(Long id) {
-        checkPlanIsCreatingTask(id,"撤回");
+        checkPlanIsCreatingTask(id, "撤回");
         TMonitoringRetrievalPlan plan = baseMapper.selectById(id);
         QueryWrapper queryWrapper = new QueryWrapper();
         queryWrapper.eq(PARENT_ID, id);
@@ -1222,16 +1214,17 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
         if (ObjectUtil.equal(tMonitoringRetrievalPlanDto.getPlanCycle(), 0) && ObjectUtil.hasEmpty(tMonitoringRetrievalPlanDto.getStartTime(), tMonitoringRetrievalPlanDto.getEndTime())) {
             throw new RuntimeException("当计划为无周期的时候,请填入开始时间和结束时间!");
         }
-        TMonitoringRetrievalPlan tMonitoringRetrievalPlan =new TMonitoringRetrievalPlan();
+        TMonitoringRetrievalPlan tMonitoringRetrievalPlan = new TMonitoringRetrievalPlan();
         BeanUtils.copyProperties(tMonitoringRetrievalPlanDto, tMonitoringRetrievalPlan);
-        int result= insertTMonitoringRetrievalPlan(tMonitoringRetrievalPlan);
+        int result = insertTMonitoringRetrievalPlan(tMonitoringRetrievalPlan);
         batchSavePlanToExecOrg(tMonitoringRetrievalPlanDto.getPlanExecOrgIdList(), tMonitoringRetrievalPlan.getId());
         return result;
     }
 
     public void batchSavePlanToExecOrg(List<Long> orgIdList, Long planId) {
-        if(ObjectUtil.isEmpty(orgIdList))
-        { return;}
+        if (ObjectUtil.isEmpty(orgIdList)) {
+            return;
+        }
         List<TMonitoringRetrievalPlanToExecOrg> planOrgList = new ArrayList();
         for (Long orgId : orgIdList) {
             TMonitoringRetrievalPlanToExecOrg org = new TMonitoringRetrievalPlanToExecOrg();
@@ -1360,34 +1353,31 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
     @Transactional
     @Override
     public int updateTMonitoringRetrievalPlan(TMonitoringRetrievalPlanDto tMonitoringRetrievalPlanDto) throws ParseException {
-        Integer result=1;
+        Integer result = 1;
         try {
-            TMonitoringRetrievalPlan newPlan =new TMonitoringRetrievalPlan();
+            TMonitoringRetrievalPlan newPlan = new TMonitoringRetrievalPlan();
             BeanUtils.copyProperties(tMonitoringRetrievalPlanDto, newPlan);
 
             boolean isComplete = getIsComplete(newPlan.getId());
             TMonitoringRetrievalPlan oldPlan = baseMapper.selectById(newPlan.getId());
 
-            if(!ObjectUtil.equal(newPlan.getRoleId(),oldPlan.getRoleId()))
-            {
+            if (!ObjectUtil.equal(newPlan.getRoleId(), oldPlan.getRoleId())) {
                 SysRole sysRole = remoteRoleService.getRoleById(newPlan.getRoleId(), SecurityConstants.INNER);
                 newPlan.setRoleName(sysRole.getRoleName());
             }
             BeanUtils.copyProperties(newPlan, oldPlan);
 
             // 草稿状态 下的计划不存在任务和子计划  直接修改
-            if(oldPlan.getPlanStatus()==0)
-            {
+            if (oldPlan.getPlanStatus() == 0) {
                 // 先删除具体调阅机构,再重新新增具体调阅机构
                 tMonitoringRetrievalPlanToExecOrgMapper.deleteByMap(MapUtil.of("plan_id", oldPlan.getId()));
                 batchSavePlanToExecOrg(tMonitoringRetrievalPlanDto.getPlanExecOrgIdList(), oldPlan.getId());
                 return tMonitoringRetrievalPlanMapper.updateById(oldPlan);
             }
             // 使用中,
-            else if(oldPlan.getPlanStatus()==1)
-            {
+            else if (oldPlan.getPlanStatus() == 1) {
                 // 但是任务都未完成,修改计划和所有子计划, 删除现有任务,根据是否立即生效 判断是否立即生成任务
-                if(!isComplete){
+                if (!isComplete) {
 
                     tMonitoringRetrievalPlanToExecOrgMapper.deleteByMap(MapUtil.of("plan_id", oldPlan.getId()));
                     batchSavePlanToExecOrg(tMonitoringRetrievalPlanDto.getPlanExecOrgIdList(), oldPlan.getId());
@@ -1398,42 +1388,36 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
                     tMonitoringRetrievalPlanMapper.delete(queryWrapper);
 
                     // 编辑的非行社创建计划,需处理子计划
-                    if(oldPlan.getOrgType()!="3")
-                    {
+                    if (oldPlan.getOrgType() != "3") {
                         iCoreMonitoringRetrievalTaskService.updateComplete(!isComplete, newPlan, oldPlan);
                     }
                     return result;
-                }
-                else // 任务中存在已完成的任务,只能修改任务名称
+                } else // 任务中存在已完成的任务,只能修改任务名称
                 {
                     tMonitoringRetrievalPlanMapper.updateById(oldPlan);
                     QueryWrapper queryWrapper = new QueryWrapper();
                     queryWrapper.eq(PARENT_ID, oldPlan.getId());
                     List<TMonitoringRetrievalPlan> subPlanList = tMonitoringRetrievalPlanMapper.selectList(queryWrapper);
-                    if(ObjectUtil.isNotEmpty(subPlanList))
-                    {
-                        subPlanList.forEach(x->x.setPlanName(oldPlan.getPlanName()));
+                    if (ObjectUtil.isNotEmpty(subPlanList)) {
+                        subPlanList.forEach(x -> x.setPlanName(oldPlan.getPlanName()));
                         this.saveOrUpdateBatch(subPlanList);
                     }
                     return result;
                 }
             }
             // 停用状态 肯定存在已完成的任务, 只能修改任务名称
-            else if(oldPlan.getPlanStatus()==2)
-            {
+            else if (oldPlan.getPlanStatus() == 2) {
                 tMonitoringRetrievalPlanMapper.updateById(oldPlan);
                 QueryWrapper queryWrapper = new QueryWrapper();
                 queryWrapper.eq(PARENT_ID, oldPlan.getId());
                 List<TMonitoringRetrievalPlan> subPlanList = tMonitoringRetrievalPlanMapper.selectList(queryWrapper);
-                if(ObjectUtil.isNotEmpty(subPlanList))
-                {
-                    subPlanList.forEach(x->x.setPlanName(oldPlan.getPlanName()));
+                if (ObjectUtil.isNotEmpty(subPlanList)) {
+                    subPlanList.forEach(x -> x.setPlanName(oldPlan.getPlanName()));
                     this.saveOrUpdateBatch(subPlanList);
                 }
                 return result;
             }
-        }
-        catch (Exception e) {
+        } catch (Exception e) {
             e.getMessage();
             return 0;
         }
@@ -1441,7 +1425,7 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
     }
 
     // 根据计划Id清除计划下的所有任务
-    private void clearTaskByPlanId(Long id){
+    private void clearTaskByPlanId(Long id) {
         TMonitoringRetrievalPlan plan = baseMapper.selectById(id);
         QueryWrapper queryWrapper = new QueryWrapper();
         queryWrapper.eq(PARENT_ID, id);
@@ -1451,8 +1435,7 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
         if (CollectionUtils.isNotEmpty(list1)) {
             planIds = list1.stream().map(TMonitoringRetrievalPlan::getId).collect(Collectors.toList());
             coreMonitoringRetrievalTaskBuilderService.deleteAllTaskByPlanIds(planIds);
-        }
-        else if (plan.getPlanCycle().equals("0")) {
+        } else if (plan.getPlanCycle().equals("0")) {
             planIds.add(id);
             coreMonitoringRetrievalTaskBuilderService.deleteAllTaskByPlanIds(planIds);
         }
@@ -1473,7 +1456,7 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
     public int deleteTMonitoringRetrievalPlanByIds(Long[] ids) {
         int i = 0;
         for (Long id : ids) {
-            checkPlanIsCreatingTask(id,"删除");
+            checkPlanIsCreatingTask(id, "删除");
 
             TMonitoringRetrievalPlan tMonitoringRetrievalPlan = new TMonitoringRetrievalPlan();
             tMonitoringRetrievalPlan.setIsDeleted(2L);
@@ -1599,8 +1582,8 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
         List<SysDictData> sysDictData = dictDataService.selectAllDictByeTypeFormDB(DictConstants.CORE_REGISTRATION_PROJECT, SecurityConstants.INNER);
         for (AccessDataVo vo : accessDataVos) {
             vo.setProject(DictUtils.getDictLabel(DictConstants.CORE_REGISTRATION_PROJECT, Integer.parseInt(vo.getProject())));
-            if (ObjectUtil.isEmpty(vo.getProject())){
-                sysDictData.stream().filter(d->d.getDictValue().equals(vo.getProject())).findFirst().ifPresent(d->vo.setProject(d.getDictLabel()));
+            if (ObjectUtil.isEmpty(vo.getProject())) {
+                sysDictData.stream().filter(d -> d.getDictValue().equals(vo.getProject())).findFirst().ifPresent(d -> vo.setProject(d.getDictLabel()));
             }
         }
         accessPdf.setDataVos(accessDataVos);
@@ -1623,4 +1606,153 @@ public class TMonitoringRetrievalPlanServiceImpl extends ServiceImpl<TMonitoring
         }
         return prefixPath + filePath;
     }
+
+    @Override
+    public BusinessPlanType getBusinessPlanType() {
+        return BusinessPlanType.MONITORING_RETRIEVAL;
+    }
+
+    @Override
+    public void compensate(CompensateDto compensateDto) {
+        TMonitoringRetrievalPlan retrievalPlan = getById(compensateDto.getPlanId());
+
+        if (ObjectUtil.isNull(retrievalPlan)) {
+            throw new ServiceException("计划不存在");
+        }
+
+        if (ObjectUtil.notEqual(retrievalPlan.getPlanStatus(), PlanStatus.USING.getCode())) {
+            throw new ServiceException("计划尚未下发或已停用");
+        }
+
+        if (ObjectUtil.equal(retrievalPlan.getIsDeleted(), "1")) {
+            throw new ServiceException("计划状态异常");
+        }
+
+        List<SysOrgVO> orgCacheList = RedisUtils.getCacheList(CacheConstants.ORG_CACHE_LIST_KEY);
+        //推断计划 创建任务
+        deducePlanAndBuildTask(retrievalPlan, compensateDto.getOrgIdList(), orgCacheList);
+    }
+
+    private static final Set<OrgTypeEnum> INVALID_ORG_TYPES = Sets.newHashSet(OrgTypeEnum.SHEGN_LIAN_SHE, OrgTypeEnum.BAN_SHI_CHU, OrgTypeEnum.DIQU_HANG_SHE);
+
+    private void deducePlanAndBuildTask(TMonitoringRetrievalPlan retrievalPlan, List<Long> orgIdList, List<SysOrgVO> orgCacheList) {
+        List<SysOrgVO> orgList = orgCacheList.stream().filter(org -> orgIdList.contains(org.getId())).collect(toList());
+        if (orgList.isEmpty()) {
+            throw new ServiceException("未查询到orgIdList中指定的机构信息");
+        }
+        List<Long> idList = orgList.stream().map(SysOrgVO::getId).collect(toList());
+        List<Integer> typeList = orgList.stream().map(SysOrgVO::getType).distinct().collect(toList());
+        if (typeList.size() > 1) {
+            throw new ServiceException("orgIdList中指定的机构信息存在多种机构类型");
+        }
+
+        OrgTypeEnum orgTypeEnum = OrgTypeEnum.getOrgTypeEnum(typeList.get(0));
+
+        // 省联社创建的计划
+        if (checkIsTopOrgCreatePlan(retrievalPlan, orgCacheList)) {
+            List<TMonitoringRetrievalPlan> allHsPlanList = getHsPlanList(retrievalPlan);
+            if (ObjectUtil.isEmpty(allHsPlanList)) {
+                return;
+            }
+
+            Map<String, Object> map = getHsOrg(orgCacheList, orgList, orgTypeEnum);
+            List<Long> hsPlanIdList = allHsPlanList.stream().map(TMonitoringRetrievalPlan::getId).collect(toList());
+            List<Long> hsOrgIdList = ((List<SysOrgVO>) map.get("list")).stream().map(SysOrgVO::getId).collect(toList());
+            if (ObjectUtil.hasEmpty(hsPlanIdList, hsOrgIdList)) {
+                return;
+            }
+            List<TMonitoringRetrievalPlan> reallyPlanList = findReallyPlanIdList(hsPlanIdList, hsOrgIdList);
+            boolean underHsOrgType = (boolean) map.get("underHsOrgType");
+            create(reallyPlanList, underHsOrgType ? idList : null);
+            return;
+        }
+        // 行社自建计划
+        if (INVALID_ORG_TYPES.contains(orgTypeEnum)) {
+            throw new ServiceException("orgIdList中传递机构信息错误!与计划信息不匹配");
+        }
+
+        List<TMonitoringRetrievalPlan> plans = Lists.newArrayList(retrievalPlan);
+        if (OrgTypeEnum.HANG_SHE.equals(orgTypeEnum)) {
+            create(plans, null);
+        } else {
+            //其实这里如果真是传入了行社以下的机构,那么大概率这里的reallyPlanIdList 计划id也只会有一个元素
+            create(plans, idList);
+        }
+    }
+
+    private void create(List<TMonitoringRetrievalPlan> planList, List<Long> idList) {
+        run(() -> coreMonitoringRetrievalTaskBuilderService.createAndSaveTask(planList, LocalDate.now(), idList), threadPoolTaskExecutor);
+    }
+
+    private List<TMonitoringRetrievalPlan> findReallyPlanIdList(List<Long> planIdList, List<Long> orgIdList) {
+
+        LambdaQueryWrapper<TMonitoringRetrievalPlan> wrapper = new LambdaQueryWrapper<>();
+        wrapper.in(TMonitoringRetrievalPlan::getId, planIdList);
+        wrapper.in(TMonitoringRetrievalPlan::getOrgId, orgIdList);
+        return baseMapper.selectList(wrapper);
+    }
+
+    private boolean checkIsTopOrgCreatePlan(TMonitoringRetrievalPlan retrievalPlan, List<SysOrgVO> orgCacheList) {
+        Long orgId = retrievalPlan.getOrgId();
+        SysOrgVO org = orgCacheList.stream().filter(o -> o.getId().equals(orgId)).findFirst().orElse(null);
+        if (org == null) {
+            throw new ServiceException("未查询到计划所属机构信息");
+        }
+        if (ObjectUtil.equal(org.getType(), OrgTypeEnum.SHEGN_LIAN_SHE.getCode())) {
+            return true;
+        }
+        if (ObjectUtil.equal(org.getType(), OrgTypeEnum.HANG_SHE.getCode())) {
+            return false;
+        }
+        throw new ServiceException("当前仅支持省联社/行社所创建的计划!");
+    }
+
+
+    private List<TMonitoringRetrievalPlan> getHsPlanList(TMonitoringRetrievalPlan drillPlan) {
+        LambdaQueryWrapper<TMonitoringRetrievalPlan> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(TMonitoringRetrievalPlan::getPlanStatus, DrillPlanStatus.USING.getCode());
+        wrapper.eq(TMonitoringRetrievalPlan::getIsDeleted, 0L);
+        wrapper.eq(TMonitoringRetrievalPlan::getParentId, drillPlan.getId());
+        return baseMapper.selectList(wrapper);
+    }
+
+    private Map<String, Object> getHsOrg(List<SysOrgVO> orgCacheList, List<SysOrgVO> needBuildTaskOrgList, OrgTypeEnum needBuildTaskOrgTypeEnum) {
+        List<SysOrgVO> list = new ArrayList<>();
+        boolean underHsOrgType = false;
+        switch (needBuildTaskOrgTypeEnum) {
+            //如果是省联社/办事处/地区行社 那么找到下级的行社
+            case SHEGN_LIAN_SHE:
+            case BAN_SHI_CHU:
+            case DIQU_HANG_SHE:
+                for (SysOrgVO sysOrgVO : needBuildTaskOrgList) {
+                    String path = sysOrgVO.getPath();
+                    List<SysOrgVO> collect = orgCacheList
+                            .stream()
+                            .filter(org -> ObjectUtil.isAllNotEmpty(org.getPath(), org.getType()))
+                            .filter(org -> org.getPath().contains(path))
+                            .filter(org -> org.getType().equals(OrgTypeEnum.HANG_SHE.getCode()))
+                            .collect(toList());
+                    list.addAll(collect);
+                }
+                break;
+            case HANG_SHE: //如果传进来的就是行社 那么直接返回
+                list = needBuildTaskOrgList;
+                break;
+            default:    //如果是行社以下机构类型,那么找到上级的行社机构返回
+                List<Long> ids = needBuildTaskOrgList.stream().map(SysOrgVO::getId).collect(toList());
+                List<SysOrg> sysOrgs = remoteOrgService.selectParentHs(ids, SecurityConstants.INNER);
+                list = BeanHelper.copyProperties(sysOrgs, SysOrgVO.class);
+                underHsOrgType = true;
+        }
+
+        Map<String, Object> map = new HashMap<>();
+        map.put("list", list);
+        map.put("underHsOrgType", underHsOrgType);
+        return map;
+    }
+
+    @Override
+    public void run(Runnable runnable, ThreadPoolTaskExecutor threadPoolTaskExecutor) {
+        CompletableFuture.runAsync(runnable, threadPoolTaskExecutor);
+    }
 }

+ 31 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/compense/controller/CompensateController.java

@@ -0,0 +1,31 @@
+package com.xunmei.core.compense.controller;
+
+
+import com.xunmei.common.core.web.domain.AjaxResult;
+import com.xunmei.core.compense.dto.CompensateDto;
+import com.xunmei.core.compense.handel.CompensateHandel;
+import com.xunmei.common.core.enums.BusinessPlanType;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+
+@RestController
+@RequestMapping
+public class CompensateController {
+
+
+
+    @RequestMapping("/compensate")
+    public AjaxResult compensate(@RequestBody @Valid CompensateDto compensateDto){
+
+        BusinessPlanType businessPlanType = BusinessPlanType.getBusinessPlanType(compensateDto.getCode());
+
+
+        CompensateHandel.getCompensateService(businessPlanType).compensate(compensateDto);
+
+
+        return AjaxResult.success();
+    }
+}

+ 27 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/compense/dto/CompensateDto.java

@@ -0,0 +1,27 @@
+package com.xunmei.core.compense.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+@Data
+public class CompensateDto {
+
+    /**
+     * @see com.xunmei.common.core.enums.BusinessPlanType
+     */
+    @NotNull(message = "补偿类型不能为空")
+    @ApiModelProperty(value = "补偿编码")
+    private String code;
+
+    @NotNull(message = "补偿计划ID不能为空")
+    @ApiModelProperty(value = "补偿计划ID")
+    private Long planId;
+
+    @NotNull(message = "补偿组织ID列表不能为空")
+    @ApiModelProperty(value = "补偿组织ID列表")
+    private List<Long> orgIdList;
+
+}

+ 29 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/compense/handel/CompensateHandel.java

@@ -0,0 +1,29 @@
+package com.xunmei.core.compense.handel;
+
+import cn.hutool.extra.spring.SpringUtil;
+import com.xunmei.core.compense.interfaces.CompensateService;
+import com.xunmei.common.core.enums.BusinessPlanType;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class CompensateHandel {
+
+
+    private static final Map<BusinessPlanType, CompensateService> CONCURRENT_HASH_MAP=new ConcurrentHashMap<>();
+
+    static {
+
+        SpringUtil.getBeansOfType(CompensateService.class).forEach((k,v)->{
+            CONCURRENT_HASH_MAP.put(v.getBusinessPlanType(),v);
+        });
+    }
+
+    public static CompensateService getCompensateService(BusinessPlanType businessPlanType){
+        CompensateService service = CONCURRENT_HASH_MAP.get(businessPlanType);
+        if(service==null){
+            throw new RuntimeException("未找到对应的补偿服务");
+        }
+        return service;
+    }
+}

+ 16 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/compense/interfaces/CompensateService.java

@@ -0,0 +1,16 @@
+package com.xunmei.core.compense.interfaces;
+
+import com.xunmei.core.compense.dto.CompensateDto;
+import com.xunmei.common.core.enums.BusinessPlanType;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+public interface CompensateService {
+
+
+    BusinessPlanType getBusinessPlanType();
+
+
+    void compensate(CompensateDto compensateDto);
+
+    void run(Runnable runnable, ThreadPoolTaskExecutor threadPoolTaskExecutor);
+}

+ 1 - 1
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/drill/service/ICoreDrillTaskService.java

@@ -6,7 +6,6 @@ import com.xunmei.common.core.domain.drill.domain.CoreDrillTask;
 import com.xunmei.common.core.domain.drill.domain.CoreDrillTaskToUser;
 import com.xunmei.common.core.domain.drill.dto.*;
 import com.xunmei.common.core.domain.drill.vo.*;
-import com.xunmei.common.core.domain.edu.dto.CoreEduTrainingTaskPageDto;
 import com.xunmei.common.core.domain.panel.dto.PanelListDto;
 import com.xunmei.common.core.domain.panel.vo.PanelListVo;
 import com.xunmei.common.core.domain.panel.vo.WebPanelResult;
@@ -83,6 +82,7 @@ public interface ICoreDrillTaskService extends IService<CoreDrillTask> {
 
 
     void createTaskForNow(CoreDrillPlanDataVo plan, Date start, Date end);
+    void createTaskForNow(CoreDrillPlanDataVo plan, Date start, Date end,List<Long> orgIdList);
 
     List<CoreDrillTaskReportVo> selectCoreDrillTaskReport(CoreDrillTaskReportDto request);
 

+ 186 - 28
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/drill/service/impl/CoreDrillPlanServiceImpl.java

@@ -12,6 +12,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.common.collect.Sets;
 import com.xunmei.common.core.constant.CacheConstants;
 import com.xunmei.common.core.constant.DictConstants;
 import com.xunmei.common.core.constant.ErrorMsgConstants;
@@ -32,8 +33,8 @@ import com.xunmei.common.core.enums.drill.DrillPlanCycleEnum;
 import com.xunmei.common.core.enums.drill.DrillPlanStatus;
 import com.xunmei.common.core.enums.edu.EduTrainingDoStatus;
 import com.xunmei.common.core.enums.edu.EduTrainingPlanCycleEnum;
-import com.xunmei.common.core.enums.edu.EduTrainingPlanStatus;
 import com.xunmei.common.core.exception.ServiceException;
+import com.xunmei.common.core.thread.ThreadPoolConfig;
 import com.xunmei.common.core.util.BeanHelper;
 import com.xunmei.common.core.utils.AssertUtil;
 import com.xunmei.common.core.utils.DateUtils;
@@ -41,15 +42,17 @@ import com.xunmei.common.core.web.page.TableDataInfo;
 import com.xunmei.common.redis.utils.RedisUtils;
 import com.xunmei.common.security.utils.DictUtils;
 import com.xunmei.common.security.utils.SecurityUtils;
+import com.xunmei.core.compense.dto.CompensateDto;
+import com.xunmei.core.compense.interfaces.CompensateService;
 import com.xunmei.core.drill.mapper.*;
 import com.xunmei.core.drill.service.ICoreDrillPlanService;
 import com.xunmei.core.drill.service.ICoreDrillPlanToExecOrgService;
 import com.xunmei.core.drill.service.ICoreDrillPlanToRoleService;
 import com.xunmei.core.drill.service.ICoreDrillTaskService;
 import com.xunmei.core.registerbook.service.ICoreRegisterBookPdfService;
-import com.xunmei.common.core.thread.ThreadPoolConfig;
 import com.xunmei.system.api.RemoteOrgService;
 import com.xunmei.system.api.domain.SysOrg;
+import com.xunmei.common.core.enums.BusinessPlanType;
 import com.xunmei.system.api.function.RemoteCallHandlerExecutor;
 import com.xunmei.system.api.vo.SysOrgVO;
 import lombok.extern.slf4j.Slf4j;
@@ -66,9 +69,10 @@ import org.springframework.transaction.support.TransactionSynchronizationManager
 import java.time.Duration;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
-import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import static java.util.stream.Collectors.toList;
+
 /**
  * 预案演练计划Service业务层处理
  *
@@ -77,7 +81,7 @@ import java.util.stream.Stream;
  */
 @Slf4j
 @Service
-public class CoreDrillPlanServiceImpl extends ServiceImpl<CoreDrillPlanMapper, CoreDrillPlan> implements ICoreDrillPlanService {
+public class CoreDrillPlanServiceImpl extends ServiceImpl<CoreDrillPlanMapper, CoreDrillPlan> implements ICoreDrillPlanService, CompensateService {
     @Autowired
     private CoreDrillPlanMapper coreDrillPlanMapper;
     @Autowired
@@ -164,7 +168,7 @@ public class CoreDrillPlanServiceImpl extends ServiceImpl<CoreDrillPlanMapper, C
         vo.setBuildTaskNow(ObjectUtil.equal(1, plan.getBuildTaskNow()));
         vo.setFileList(ObjectUtil.isNotEmpty(plan.getFileList()) ? JSON.parseArray(plan.getFileList(), String.class) : null);
         final List<CoreDrillPlanToExecOrg> execOrgList = coreDrillPlanToExecOrgMapper.selectByMap(MapUtil.of("plan_id", id));
-        final List<Long> execOrgIdList = execOrgList.stream().map(CoreDrillPlanToExecOrg::getOrgId).collect(Collectors.toList());
+        final List<Long> execOrgIdList = execOrgList.stream().map(CoreDrillPlanToExecOrg::getOrgId).collect(toList());
         vo.setPlanExecOrgIdList(ObjectUtil.isEmpty(execOrgIdList) ? null : execOrgIdList);
         vo.setCategoryText(DictUtils.getDictLabel(DictConstants.CORE_DRILL_CATEGORY, vo.getCategory()));
         /*final List<CoreDrillPlanToRole> planToRoles = coreDrillPlanToRoleMapper.selectByMap(MapUtil.of("plan_id", id));
@@ -306,15 +310,15 @@ public class CoreDrillPlanServiceImpl extends ServiceImpl<CoreDrillPlanMapper, C
 
         //现在能被编辑的计划一定是标准计划
         //updateStandardPlan(plan, request, range);
-        if (plan.getPlanStatus() == EduTrainingPlanStatus.DRAFT.getCode()) {
+        if (plan.getPlanStatus() == DrillPlanStatus.DRAFT.getCode()) {
             //草稿状态 支持编辑所有字段,
             doUpdatePlan(plan, request);
         }
-        if (plan.getPlanStatus() == EduTrainingPlanStatus.DELETED.getCode()) {
+        if (plan.getPlanStatus() == DrillPlanStatus.DELETED.getCode()) {
             //停用状态 支持编辑名称和检查内容;
             doUpdatePlanForDeleted(plan, request);
         }
-        if (plan.getPlanStatus() == EduTrainingPlanStatus.USING.getCode()) {
+        if (plan.getPlanStatus() == DrillPlanStatus.USING.getCode()) {
             //使用中 状态,支持编辑名称和检查内容;
             //存在已完成任务,本次修改内容将从下周期生效
             //不存在已完成任务,本次修改内容将立即生成
@@ -471,7 +475,7 @@ public class CoreDrillPlanServiceImpl extends ServiceImpl<CoreDrillPlanMapper, C
             coreDrillPlanToRoleMapper.delete(new LambdaQueryWrapper<CoreDrillPlanToRole>().in(CoreDrillPlanToRole::getPlanId, planIdList));
         }
         List<CoreDrillTask> taskIdList = coreDrillTaskMapper.selectList(new LambdaQueryWrapper<CoreDrillTask>().in(CoreDrillTask::getPlanId, planIdList).select(CoreDrillTask::getId));
-        List<Long> collect = taskIdList.stream().map(CoreDrillTask::getId).collect(Collectors.toList());
+        List<Long> collect = taskIdList.stream().map(CoreDrillTask::getId).collect(toList());
         if (ObjectUtil.isNotEmpty(collect)) {
             coreDrillTaskMapper.deleteBatchIds(collect);
             coreDrillTaskToRoleMapper.delete(new LambdaQueryWrapper<CoreDrillTaskToRole>().in(CoreDrillTaskToRole::getDrillTaskId, collect));
@@ -639,7 +643,7 @@ public class CoreDrillPlanServiceImpl extends ServiceImpl<CoreDrillPlanMapper, C
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void deleteCoreDrillPlanByIds(Long id) {
-        checkPlanIsCreatingTask(id,"删除");
+        checkPlanIsCreatingTask(id, "删除");
         List<Long> list = baseMapper.selectIdByParentId(id);
         if (ObjectUtil.isEmpty(list)) {
             //说明没有下发,还是草稿状态
@@ -733,12 +737,12 @@ public class CoreDrillPlanServiceImpl extends ServiceImpl<CoreDrillPlanMapper, C
         }, threadPoolTaskExecutor);
 
         planListFuture.thenAcceptAsync((result) -> {
-            String redisKey="Drill_Creating_Task" + planId;
+            String redisKey = "Drill_Creating_Task" + planId;
             RedisUtils.deleteObject(redisKey);
             //仅当hashKey不存在时才设置
             Boolean hasKey = RedisUtils.hasKey(redisKey);
             if (!hasKey) {
-                RedisUtils.setCacheObject(redisKey, planId, Duration.ofMillis(1000 * 60*5));
+                RedisUtils.setCacheObject(redisKey, planId, Duration.ofMillis(1000 * 60 * 5));
             }
             for (CoreDrillPlan drillPlan : result) {
                 if (checkCanBuildTaskNow(drillPlan)) {
@@ -778,19 +782,18 @@ public class CoreDrillPlanServiceImpl extends ServiceImpl<CoreDrillPlanMapper, C
                 || ObjectUtil.equal(orgType, OrgTypeEnum.YINGYE_WANGDIAN.getCode());
     }
 
-    private void checkPlanIsCreatingTask(Long planId,String msg)
-    {
-        String redisKey="Drill_Creating_Task" + planId;
+    private void checkPlanIsCreatingTask(Long planId, String msg) {
+        String redisKey = "Drill_Creating_Task" + planId;
         Boolean hasKey = RedisUtils.hasKey(redisKey);
         if (hasKey) {
-            throw new ServiceException("该任务正在生成中,现在不能被"+msg+",请稍后再试。");
+            throw new ServiceException("该任务正在生成中,现在不能被" + msg + ",请稍后再试。");
         }
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
     public int revocationPlan(Long planId) {
-        checkPlanIsCreatingTask(planId,"撤回");
+        checkPlanIsCreatingTask(planId, "撤回");
         List<Long> list = coreDrillPlanMapper.selectIdByParentId(planId);
         Integer isExecute = coreDrillTaskMapper.selectCount(new LambdaQueryWrapper<CoreDrillTask>()
                         .in(CoreDrillTask::getPlanId, list)
@@ -835,17 +838,17 @@ public class CoreDrillPlanServiceImpl extends ServiceImpl<CoreDrillPlanMapper, C
             case 1:
                 //省联社
                 final List<CoreDrillPlan> sLsPlanList = getPlanList(orgId, 1, 1);
-                return sLsPlanList.stream().map(x -> new IdName<>(x.getId().toString(), x.getPlanName())).collect(Collectors.toList());
+                return sLsPlanList.stream().map(x -> new IdName<>(x.getId().toString(), x.getPlanName())).collect(toList());
             case 2:
                 //办事处
                 SysOrg topOrg = RemoteCallHandlerExecutor.executeRemoteCall(() -> orgService.selectTopOrg(SecurityConstants.INNER), ErrorMsgConstants.QUERY_ORG_DATA_ERROR);
                 final List<CoreDrillPlan> lsPlanList = getPlanList(topOrg.getId(), 1, 1);
                 final List<CoreDrillPlan> bscPlanList = getPlanList(orgId, 1, 1);
-                return Stream.of(lsPlanList, bscPlanList).flatMap(Collection::stream).map(x -> new IdName<>(x.getId().toString(), x.getPlanName())).collect(Collectors.toList());
+                return Stream.of(lsPlanList, bscPlanList).flatMap(Collection::stream).map(x -> new IdName<>(x.getId().toString(), x.getPlanName())).collect(toList());
             case 3:
                 //行社
                 final List<CoreDrillPlan> hsPlanList = getPlanList(orgId, 0, 0);
-                return hsPlanList.stream().map(x -> new IdName<>(x.getId().toString(), x.getPlanName())).collect(Collectors.toList());
+                return hsPlanList.stream().map(x -> new IdName<>(x.getId().toString(), x.getPlanName())).collect(toList());
             default:
                 return new ArrayList<>();
         }
@@ -870,7 +873,7 @@ public class CoreDrillPlanServiceImpl extends ServiceImpl<CoreDrillPlanMapper, C
             planRoleList = coreDrillPlanToRoleMapper.selectList(ros);
         }*/
         List<SysOrgVO> all = RedisUtils.getCacheList(CacheConstants.ORG_CACHE_LIST_KEY);
-        all = all.stream().filter(o -> ObjectUtil.isNotEmpty(o.getPath())).collect(Collectors.toList());
+        all = all.stream().filter(o -> ObjectUtil.isNotEmpty(o.getPath())).collect(toList());
         final SysOrgVO planCreateOrg = all.stream().filter(org -> org.getId().equals(plan.getCreateOrgId())).findFirst().get();
         final long count = all.stream()
                 .filter(org -> ObjectUtil.isNotEmpty(org.getPath()))
@@ -954,8 +957,8 @@ public class CoreDrillPlanServiceImpl extends ServiceImpl<CoreDrillPlanMapper, C
         final List<CoreDrillPlanToExecOrg> coreDrillPlanToExecOrgList = coreDrillPlanToExecOrgMapper.selectList(eos);
 
         if (ObjectUtil.isNotEmpty(coreDrillPlanToExecOrgList)) {
-            final List<Long> list = coreDrillPlanToExecOrgList.stream().map(CoreDrillPlanToExecOrg::getOrgId).collect(Collectors.toList());
-            return all.stream().filter(org -> list.contains(org.getId())).collect(Collectors.toList());
+            final List<Long> list = coreDrillPlanToExecOrgList.stream().map(CoreDrillPlanToExecOrg::getOrgId).collect(toList());
+            return all.stream().filter(org -> list.contains(org.getId())).collect(toList());
 
         } else {
            /* List<CoreEduTrainingPlanToOrgType> toOrgTypeList = coreEduTrainingPlanToOrgTypeMapper.selectList(new LambdaQueryWrapper<CoreEduTrainingPlanToOrgType>()
@@ -964,24 +967,179 @@ public class CoreDrillPlanServiceImpl extends ServiceImpl<CoreDrillPlanMapper, C
             return all.stream().filter(org -> collect.contains(org.getType())).collect(Collectors.toList());*/
 
 
-            return all.stream().filter(org -> ObjectUtil.isNotNull(org.getType())).filter(org -> org.getType().equals(plan.getExecOrgType())).collect(Collectors.toList());
+            return all.stream().filter(org -> ObjectUtil.isNotNull(org.getType())).filter(org -> org.getType().equals(plan.getExecOrgType())).collect(toList());
         }
     }
 
 
     public List<SysOrgVO> getPlanPublishOrgList(List<SysOrgVO> list) {
         //省联社/办事处/行社
-        List<SysOrgVO> collect = list.stream().filter(org -> checkOrgType(org.getType())).collect(Collectors.toList());
+        List<SysOrgVO> collect = list.stream().filter(org -> checkOrgType(org.getType())).collect(toList());
         //行社以下的机构
-        List<SysOrgVO> collect1 = list.stream().filter(org -> !checkOrgType(org.getType())).collect(Collectors.toList());
+        List<SysOrgVO> collect1 = list.stream().filter(org -> !checkOrgType(org.getType())).collect(toList());
 
         if (ObjectUtil.isNotEmpty(collect1)) {
-            List<Long> orgIdList = collect1.stream().map(SysOrgVO::getId).collect(Collectors.toList());
+            List<Long> orgIdList = collect1.stream().map(SysOrgVO::getId).collect(toList());
             List<SysOrg> orgList = RemoteCallHandlerExecutor.executeRemoteCall(() -> orgService.selectParentHs(orgIdList, SecurityConstants.INNER), ErrorMsgConstants.QUERY_ORG_DATA_ERROR);
             List<SysOrgVO> sysOrgVOS = BeanHelper.copyProperties(orgList, SysOrgVO.class);
-            return Stream.of(sysOrgVOS, collect).flatMap(Collection::stream).collect(Collectors.toList());
+            return Stream.of(sysOrgVOS, collect).flatMap(Collection::stream).collect(toList());
         }
 
         return collect;
     }
+
+    @Override
+    public BusinessPlanType getBusinessPlanType() {
+        return BusinessPlanType.DRILL;
+
+    }
+
+    @Override
+    public void compensate(CompensateDto compensateDto) {
+
+
+        CoreDrillPlan drillPlan = getById(compensateDto.getPlanId());
+
+        if (ObjectUtil.isNull(drillPlan)) {
+            throw new ServiceException("计划不存在");
+        }
+
+        if (ObjectUtil.notEqual(drillPlan.getPlanStatus(), DrillPlanStatus.USING.getCode())) {
+            throw new ServiceException("计划尚未下发或已停用");
+        }
+
+        if (ObjectUtil.equal(drillPlan.getDeleted(), 1)) {
+            throw new ServiceException("计划状态异常");
+        }
+
+        List<SysOrgVO> orgCacheList = RedisUtils.getCacheList(CacheConstants.ORG_CACHE_LIST_KEY);
+        //推断计划
+        deducePlanAndBuildTask(drillPlan, compensateDto.getOrgIdList(), orgCacheList);
+
+    }
+
+
+    private static final Set<OrgTypeEnum> INVALID_ORG_TYPES = Sets.newHashSet(OrgTypeEnum.SHEGN_LIAN_SHE, OrgTypeEnum.BAN_SHI_CHU, OrgTypeEnum.DIQU_HANG_SHE);
+    private void deducePlanAndBuildTask(CoreDrillPlan drillPlan, List<Long> orgIdList, List<SysOrgVO> orgCacheList) {
+        List<SysOrgVO> orgList = orgCacheList.stream().filter(org -> orgIdList.contains(org.getId())).collect(toList());
+        if (orgList.isEmpty()) {
+            throw new ServiceException("未查询到orgIdList中指定的机构信息");
+        }
+        List<Long> idList = orgList.stream().map(SysOrgVO::getId).collect(toList());
+        List<Integer> typeList = orgList.stream().map(SysOrgVO::getType).distinct().collect(toList());
+        if (typeList.size() > 1) {
+            throw new ServiceException("orgIdList中指定的机构信息存在多种机构类型");
+        }
+
+        OrgTypeEnum orgTypeEnum = OrgTypeEnum.getOrgTypeEnum(typeList.get(0));
+
+        // 省联社创建的计划
+        if (checkIsParentPlan(drillPlan.getId())) {
+            List<CoreDrillPlan> allHsPlanList = getHsPlanList(drillPlan);
+            if (ObjectUtil.isEmpty(allHsPlanList)) {
+                return;
+            }
+
+            Map<String, Object> map = getHsOrg(orgCacheList, orgList, orgTypeEnum);
+            List<Long> hsPlanIdList = allHsPlanList.stream().map(CoreDrillPlan::getId).collect(toList());
+            List<Long> hsOrgIdList = ((List<SysOrgVO>) map.get("list")).stream().map(SysOrgVO::getId).collect(toList());
+            if (ObjectUtil.hasEmpty(hsPlanIdList, hsOrgIdList)){
+                return;
+            }
+            List<CoreDrillPlan> reallyPlanIdList = findReallyPlanIdList(hsPlanIdList, hsOrgIdList);
+            boolean underHsOrgType = (boolean) map.get("underHsOrgType");
+            for (CoreDrillPlan plan : reallyPlanIdList) {
+                create(plan, underHsOrgType ? idList : null);
+            }
+            return;
+        }
+        // 行社自建计划
+        if (INVALID_ORG_TYPES.contains(orgTypeEnum)) {
+            throw new ServiceException("orgIdList中传递机构信息错误!与计划信息不匹配");
+        }
+
+        if (OrgTypeEnum.HANG_SHE.equals(orgTypeEnum)) {
+            create(drillPlan, null);
+        } else {
+            //其实这里如果真是传入了行社以下的机构,那么大概率这里的reallyPlanIdList 计划id也只会有一个元素
+            create(drillPlan, idList);
+        }
+
+    }
+    private void create(CoreDrillPlan plan, List<Long> idList) {
+        Long planId = plan.getId();
+        Date planStartDate = plan.getPlanStartDate();
+        Date planEndDate = plan.getPlanEndDate();
+
+        run(() -> {
+            CoreDrillPlanDataVo detailPlanData = getCoreDrillPlanDataVo(planId);
+            coreDrillTaskService.createTaskForNow(detailPlanData, planStartDate, planEndDate, idList);
+        },threadPoolTaskExecutor);
+    }
+
+    private List<CoreDrillPlan> findReallyPlanIdList(List<Long> planIdList, List<Long> orgIdList) {
+
+        LambdaQueryWrapper<CoreDrillPlan> wrapper = new LambdaQueryWrapper<>();
+        wrapper.in(CoreDrillPlan::getId, planIdList);
+        wrapper.in(CoreDrillPlan::getBelongOrgId, orgIdList);
+        return baseMapper.selectList(wrapper);
+    }
+
+    private boolean checkIsParentPlan(Long planId) {
+        //演练与培训的 行社下发的计划 id=parentId
+        LambdaQueryWrapper<CoreDrillPlan> countWrapper = new LambdaQueryWrapper<>();
+        countWrapper.eq(CoreDrillPlan::getParentId, planId);
+        countWrapper.ne(CoreDrillPlan::getId, planId);
+        Long l = baseMapper.selectCount(countWrapper);
+        return ObjectUtil.isNotNull(l) && l.compareTo(0L) > 0;
+    }
+
+
+    private List<CoreDrillPlan> getHsPlanList(CoreDrillPlan drillPlan) {
+        LambdaQueryWrapper<CoreDrillPlan> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(CoreDrillPlan::getPlanStatus, DrillPlanStatus.USING.getCode());
+        wrapper.eq(CoreDrillPlan::getDeleted, 0);
+        wrapper.eq(CoreDrillPlan::getParentId, drillPlan.getId());
+        return baseMapper.selectList(wrapper);
+    }
+
+    private Map<String, Object> getHsOrg(List<SysOrgVO> orgCacheList, List<SysOrgVO> needBuildTaskOrgList, OrgTypeEnum needBuildTaskOrgTypeEnum) {
+        List<SysOrgVO> list = new ArrayList<>();
+        boolean underHsOrgType = false;
+        switch (needBuildTaskOrgTypeEnum) {
+            //如果是省联社/办事处/地区行社 那么找到下级的行社
+            case SHEGN_LIAN_SHE:
+            case BAN_SHI_CHU:
+            case DIQU_HANG_SHE:
+                for (SysOrgVO sysOrgVO : needBuildTaskOrgList) {
+                    String path = sysOrgVO.getPath();
+                    List<SysOrgVO> collect = orgCacheList
+                            .stream()
+                            .filter(org -> ObjectUtil.isAllNotEmpty(org.getPath(), org.getType()))
+                            .filter(org -> org.getPath().contains(path))
+                            .filter(org -> org.getType().equals(OrgTypeEnum.HANG_SHE.getCode()))
+                            .collect(toList());
+                    list.addAll(collect);
+                }
+                break;
+            case HANG_SHE: //如果传进来的就是行社 那么直接返回
+                list = needBuildTaskOrgList;
+                break;
+            default:    //如果是行社以下机构类型,那么找到上级的行社机构返回
+                List<Long> ids = needBuildTaskOrgList.stream().map(SysOrgVO::getId).collect(toList());
+                List<SysOrg> sysOrgs = orgService.selectParentHs(ids, SecurityConstants.INNER);
+                list = BeanHelper.copyProperties(sysOrgs, SysOrgVO.class);
+                underHsOrgType = true;
+        }
+
+        Map<String, Object> map = new HashMap<>();
+        map.put("list", list);
+        map.put("underHsOrgType", underHsOrgType);
+        return map;
+    }
+
+    @Override
+    public void run(Runnable runnable, ThreadPoolTaskExecutor threadPoolTaskExecutor) {
+        CompletableFuture.runAsync(runnable, threadPoolTaskExecutor);
+    }
 }

+ 33 - 10
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/drill/service/impl/CoreDrillTaskServiceImpl.java

@@ -305,12 +305,12 @@ public class CoreDrillTaskServiceImpl extends ServiceImpl<CoreDrillTaskMapper, C
             coreDrillTask.setEndDate(end);
         }
         if (ObjectUtil.equal(request.getSubmitType(), 2)) {
-            if (ObjectUtil.notEqual(coreDrillTask.getStatus(), DrillDoStatus.WAIT_SUBMIT.getCode())&&ObjectUtil.notEqual(coreDrillTask.getStatus(), DrillDoStatus.WAIT_RECORDED.getCode())){
+            if (ObjectUtil.notEqual(coreDrillTask.getStatus(), DrillDoStatus.WAIT_SUBMIT.getCode()) && ObjectUtil.notEqual(coreDrillTask.getStatus(), DrillDoStatus.WAIT_RECORDED.getCode())) {
                 throw new SystemException("当前状态不允许修改,请退出当前页面后刷新重试!");
             }
             coreDrillTask.setStatus(DrillDoStatus.WAIT_SIGN.getCode());
         } else {
-            if (ObjectUtil.notEqual(coreDrillTask.getStatus(), DrillDoStatus.WAIT_SUBMIT.getCode())&&ObjectUtil.notEqual(coreDrillTask.getStatus(), DrillDoStatus.WAIT_RECORDED.getCode())){
+            if (ObjectUtil.notEqual(coreDrillTask.getStatus(), DrillDoStatus.WAIT_SUBMIT.getCode()) && ObjectUtil.notEqual(coreDrillTask.getStatus(), DrillDoStatus.WAIT_RECORDED.getCode())) {
                 throw new SystemException("当前状态不允许修改,请退出当前页面后刷新重试!");
             }
             coreDrillTask.setStatus(DrillDoStatus.WAIT_SUBMIT.getCode());
@@ -403,6 +403,29 @@ public class CoreDrillTaskServiceImpl extends ServiceImpl<CoreDrillTaskMapper, C
         return coreDrillTaskMapper.deleteById(id);
     }
 
+
+    @Override
+    public void createTaskForNow(CoreDrillPlanDataVo plan, Date start, Date end, List<Long> orgIdList) {
+        if (plan.getPlanCycle() != 0) {
+            //如果不是无周期的计划,那么需要查询出他的时间范围,且需要判断作息时间是否存在
+            DateRange dateRange = DateUtils.getStartAndEnd(new Date(), plan.getPlanCycle());
+            start = dateRange.getStartTime();
+            end = dateRange.getEndTime();
+        } else {
+            //无周期
+            start = DateUtil.beginOfDay(start).setField(DateField.MILLISECOND, 0);
+            end = DateUtil.endOfDay(end).setField(DateField.MILLISECOND, 0);
+        }
+
+        List<SysOrg> orgList = getExecOrgList(plan.getPlanExecOrgList(), plan.getExecOrgType(), plan.getBelongOrgPath());
+
+        if (ObjectUtil.isNotEmpty(orgIdList)) {
+            orgList = orgList.stream().filter(org -> orgIdList.contains(org.getId())).collect(Collectors.toList());
+        }
+        final List<SysWorkTime> workTimeList = getWorkTimeList(orgList, start, end);
+        saveTaskAndRoleData(plan, start, end, orgList, workTimeList);
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
     public void createTaskForNow(CoreDrillPlanDataVo plan, Date start, Date end) {
@@ -1091,8 +1114,8 @@ public class CoreDrillTaskServiceImpl extends ServiceImpl<CoreDrillTaskMapper, C
             final Long count = coreDrillTaskMapper.selectCount(new LambdaQueryWrapper<CoreDrillTask>()
                     .in(CoreDrillTask::getRecStatus, Arrays.asList(DrillRecStatus.HS_EXCELLENT_CASE.getCode(), DrillRecStatus.REC_REGION_EXCELLENT_CASE.getCode()))
                     .likeRight(CoreDrillTask::getOrgPath, sysOrg.getPath())
-                    .ge(CoreDrillTask::getStartDate,range.getStartTime())
-                    .le(CoreDrillTask::getEndDate,range.getEndTime()));
+                    .ge(CoreDrillTask::getStartDate, range.getStartTime())
+                    .le(CoreDrillTask::getEndDate, range.getEndTime()));
             //如果 小于设置推荐上限则返回true,反之false
             return count < Integer.parseInt(sysConfig.getConfigValue());
         }
@@ -1108,8 +1131,8 @@ public class CoreDrillTaskServiceImpl extends ServiceImpl<CoreDrillTaskMapper, C
             final int count = coreDrillTaskMapper.selectCount(new LambdaQueryWrapper<CoreDrillTask>()
                     .in(CoreDrillTask::getRecStatus, Arrays.asList(DrillRecStatus.REGION_EXCELLENT_CASE.getCode(), DrillRecStatus.REC_PROVINCE_EXCELLENT_CASE.getCode()))
                     .likeRight(CoreDrillTask::getOrgPath, sysOrg.getPath())
-                    .ge(CoreDrillTask::getStartDate,range.getStartTime())
-                    .le(CoreDrillTask::getEndDate,range.getEndTime())).intValue();
+                    .ge(CoreDrillTask::getStartDate, range.getStartTime())
+                    .le(CoreDrillTask::getEndDate, range.getEndTime())).intValue();
             //如果 小于设置推荐上限则返回true,反之false
             return count < Integer.parseInt(sysConfig.getConfigValue());
         }
@@ -1140,8 +1163,8 @@ public class CoreDrillTaskServiceImpl extends ServiceImpl<CoreDrillTaskMapper, C
             List<CoreDrillTask> coreDrillTasks = coreDrillTaskMapper.selectList(new LambdaQueryWrapper<CoreDrillTask>()
                     .eq(CoreDrillTask::getRecStatus, DrillRecStatus.REC_REGION_EXCELLENT_CASE.getCode())
                     .likeRight(CoreDrillTask::getOrgPath, sysOrg.getPath())
-                    .ge(CoreDrillTask::getStartDate,range.getStartTime())
-                    .le(CoreDrillTask::getEndDate,range.getEndTime()).select(CoreDrillTask::getId, CoreDrillTask::getOrgId));
+                    .ge(CoreDrillTask::getStartDate, range.getStartTime())
+                    .le(CoreDrillTask::getEndDate, range.getEndTime()).select(CoreDrillTask::getId, CoreDrillTask::getOrgId));
             List<Long> list = coreDrillTasks.stream().map(CoreDrillTask::getId).collect(Collectors.toList());
             //判断重复推优评优
             if ((!list.contains(drillTask.getId())) && coreDrillTasks.size() >= Integer.parseInt(sysConfig.getConfigValue())) {
@@ -1161,8 +1184,8 @@ public class CoreDrillTaskServiceImpl extends ServiceImpl<CoreDrillTaskMapper, C
             List<CoreDrillTask> coreDrillTasks = coreDrillTaskMapper.selectList(new LambdaQueryWrapper<CoreDrillTask>()
                     .eq(CoreDrillTask::getRecStatus, DrillRecStatus.REC_PROVINCE_EXCELLENT_CASE.getCode())
                     .likeRight(CoreDrillTask::getOrgPath, sysOrg.getPath())
-                    .ge(CoreDrillTask::getStartDate,range.getStartTime())
-                    .le(CoreDrillTask::getEndDate,range.getEndTime()).select(CoreDrillTask::getId, CoreDrillTask::getOrgId));
+                    .ge(CoreDrillTask::getStartDate, range.getStartTime())
+                    .le(CoreDrillTask::getEndDate, range.getEndTime()).select(CoreDrillTask::getId, CoreDrillTask::getOrgId));
             List<Long> list = coreDrillTasks.stream().map(CoreDrillTask::getId).collect(Collectors.toList());
             //判断重复推优评优
             if ((!list.contains(drillTask.getId())) && coreDrillTasks.size() >= Integer.parseInt(sysConfig.getConfigValue())) {

+ 1 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/edu/service/ICoreEduTrainingTaskService.java

@@ -85,6 +85,7 @@ public interface ICoreEduTrainingTaskService extends IService<CoreEduTrainingTas
 
 
     void createTaskForNow(CoreEduTrainingPlanDataVo plan, Date start, Date end);
+    void createTaskForNow(CoreEduTrainingPlanDataVo plan, Date start, Date end,List<Long> orgIdList);
 
     List<CoreEduTrainingTaskReportVo> selectCoreEduTrainingTaskReport(CoreEduTrainingTaskReportDto request);
 

+ 167 - 4
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/edu/service/impl/CoreEduTrainingPlanServiceImpl.java

@@ -12,12 +12,16 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.common.collect.Sets;
 import com.xunmei.common.core.constant.CacheConstants;
 import com.xunmei.common.core.constant.ErrorMsgConstants;
 import com.xunmei.common.core.constant.SecurityConstants;
 import com.xunmei.common.core.domain.DateRange;
 import com.xunmei.common.core.domain.IdName;
-import com.xunmei.common.core.domain.edu.domain.*;
+import com.xunmei.common.core.domain.edu.domain.CoreEduTrainingPlan;
+import com.xunmei.common.core.domain.edu.domain.CoreEduTrainingPlanToExecOrg;
+import com.xunmei.common.core.domain.edu.domain.CoreEduTrainingPlanToRole;
+import com.xunmei.common.core.domain.edu.domain.CoreEduTrainingTask;
 import com.xunmei.common.core.domain.edu.dto.CoreEduTrainingPlanEditDto;
 import com.xunmei.common.core.domain.edu.dto.CoreEduTrainingPlanInsertDto;
 import com.xunmei.common.core.domain.edu.dto.CoreEduTrainingPlanPageDto;
@@ -27,25 +31,32 @@ import com.xunmei.common.core.domain.edu.vo.CoreEduTrainingPlanPageVo;
 import com.xunmei.common.core.domain.edu.vo.CoreEduTrainingPlanRoleVo;
 import com.xunmei.common.core.enums.OrgTypeEnum;
 import com.xunmei.common.core.enums.drill.DrillPlanCycleEnum;
+import com.xunmei.common.core.enums.drill.DrillPlanStatus;
 import com.xunmei.common.core.enums.edu.EduTrainingDoStatus;
 import com.xunmei.common.core.enums.edu.EduTrainingPlanCycleEnum;
 import com.xunmei.common.core.enums.edu.EduTrainingPlanStatus;
 import com.xunmei.common.core.exception.ServiceException;
+import com.xunmei.common.core.thread.ThreadPoolConfig;
 import com.xunmei.common.core.util.BeanHelper;
 import com.xunmei.common.core.utils.AssertUtil;
 import com.xunmei.common.core.utils.DateUtils;
 import com.xunmei.common.core.web.page.TableDataInfo;
 import com.xunmei.common.redis.utils.RedisUtils;
 import com.xunmei.common.security.utils.SecurityUtils;
-import com.xunmei.core.edu.mapper.*;
+import com.xunmei.core.compense.dto.CompensateDto;
+import com.xunmei.core.compense.interfaces.CompensateService;
+import com.xunmei.core.edu.mapper.CoreEduTrainingPlanMapper;
+import com.xunmei.core.edu.mapper.CoreEduTrainingPlanToExecOrgMapper;
+import com.xunmei.core.edu.mapper.CoreEduTrainingPlanToRoleMapper;
+import com.xunmei.core.edu.mapper.CoreEduTrainingTaskMapper;
 import com.xunmei.core.edu.service.ICoreEduTrainingPlanService;
 import com.xunmei.core.edu.service.ICoreEduTrainingPlanToExecOrgService;
 import com.xunmei.core.edu.service.ICoreEduTrainingPlanToRoleService;
 import com.xunmei.core.edu.service.ICoreEduTrainingTaskService;
 import com.xunmei.core.registerbook.service.ICoreRegisterBookPdfService;
-import com.xunmei.common.core.thread.ThreadPoolConfig;
 import com.xunmei.system.api.RemoteOrgService;
 import com.xunmei.system.api.domain.SysOrg;
+import com.xunmei.common.core.enums.BusinessPlanType;
 import com.xunmei.system.api.function.RemoteCallHandlerExecutor;
 import com.xunmei.system.api.vo.SysOrgVO;
 import lombok.extern.slf4j.Slf4j;
@@ -66,6 +77,8 @@ import java.util.concurrent.CompletableFuture;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import static java.util.stream.Collectors.toList;
+
 /**
  * 教育培训计划Service业务层处理
  *
@@ -74,7 +87,7 @@ import java.util.stream.Stream;
  */
 @Slf4j
 @Service
-public class CoreEduTrainingPlanServiceImpl extends ServiceImpl<CoreEduTrainingPlanMapper, CoreEduTrainingPlan> implements ICoreEduTrainingPlanService {
+public class CoreEduTrainingPlanServiceImpl extends ServiceImpl<CoreEduTrainingPlanMapper, CoreEduTrainingPlan> implements ICoreEduTrainingPlanService, CompensateService {
     @Autowired
     private CoreEduTrainingPlanMapper coreEduTrainingPlanMapper;
     @Autowired
@@ -951,4 +964,154 @@ public class CoreEduTrainingPlanServiceImpl extends ServiceImpl<CoreEduTrainingP
                 .select(CoreEduTrainingPlan::getId, CoreEduTrainingPlan::getPlanName)
         );
     }
+
+    @Override
+    public BusinessPlanType getBusinessPlanType() {
+        return BusinessPlanType.EDU_TRAINING;
+    }
+
+    @Override
+    public void compensate(CompensateDto compensateDto) {
+
+        CoreEduTrainingPlan eduTrainingPlan = getById(compensateDto.getPlanId());
+
+        if (ObjectUtil.isNull(eduTrainingPlan)) {
+            throw new ServiceException("计划不存在");
+        }
+
+        if (ObjectUtil.notEqual(eduTrainingPlan.getPlanStatus(), DrillPlanStatus.USING.getCode())) {
+            throw new ServiceException("计划尚未下发或已停用");
+        }
+
+        if (ObjectUtil.equal(eduTrainingPlan.getDeleted(), 1)) {
+            throw new ServiceException("计划状态异常");
+        }
+
+        List<SysOrgVO> orgCacheList = RedisUtils.getCacheList(CacheConstants.ORG_CACHE_LIST_KEY);
+        //推断计划
+        deducePlanAndBuildTask(eduTrainingPlan, compensateDto.getOrgIdList(), orgCacheList);
+    }
+
+    private static final Set<OrgTypeEnum> INVALID_ORG_TYPES = Sets.newHashSet(OrgTypeEnum.SHEGN_LIAN_SHE, OrgTypeEnum.BAN_SHI_CHU, OrgTypeEnum.DIQU_HANG_SHE);
+    private void deducePlanAndBuildTask(CoreEduTrainingPlan trainingPlan, List<Long> orgIdList, List<SysOrgVO> orgCacheList) {
+        List<SysOrgVO> orgList = orgCacheList.stream().filter(org -> orgIdList.contains(org.getId())).collect(toList());
+        if (orgList.isEmpty()) {
+            throw new ServiceException("未查询到orgIdList中指定的机构信息");
+        }
+        List<Long> idList = orgList.stream().map(SysOrgVO::getId).collect(toList());
+        List<Integer> typeList = orgList.stream().map(SysOrgVO::getType).distinct().collect(toList());
+        if (typeList.size() > 1) {
+            throw new ServiceException("orgIdList中指定的机构信息存在多种机构类型");
+        }
+
+        OrgTypeEnum orgTypeEnum = OrgTypeEnum.getOrgTypeEnum(typeList.get(0));
+
+        // 省联社创建的计划
+        if (checkIsParentPlan(trainingPlan.getId())) {
+            List<CoreEduTrainingPlan> allHsPlanList = getHsPlanList(trainingPlan);
+            if (ObjectUtil.isEmpty(allHsPlanList)) {
+                return;
+            }
+
+            Map<String, Object> map = getHsOrg(orgCacheList, orgList, orgTypeEnum);
+            List<Long> hsPlanIdList = allHsPlanList.stream().map(CoreEduTrainingPlan::getId).collect(toList());
+            List<Long> hsOrgIdList = ((List<SysOrgVO>) map.get("list")).stream().map(SysOrgVO::getId).collect(toList());
+            if (ObjectUtil.hasEmpty(hsPlanIdList, hsOrgIdList)){
+                return;
+            }
+            List<CoreEduTrainingPlan> reallyPlanIdList = findReallyPlanIdList(hsPlanIdList, hsOrgIdList);
+            boolean underHsOrgType = (boolean) map.get("underHsOrgType");
+            for (CoreEduTrainingPlan plan : reallyPlanIdList) {
+                create(plan, underHsOrgType ? idList : null, threadPoolTaskExecutor);
+            }
+            return;
+        }
+        // 行社自建计划
+        if (INVALID_ORG_TYPES.contains(orgTypeEnum)) {
+            throw new ServiceException("orgIdList中传递机构信息错误!与计划信息不匹配");
+        }
+
+        if (OrgTypeEnum.HANG_SHE.equals(orgTypeEnum)) {
+            create(trainingPlan, null, threadPoolTaskExecutor);
+        } else {
+            //其实这里如果真是传入了行社以下的机构,那么大概率这里的reallyPlanIdList 计划id也只会有一个元素
+            create(trainingPlan, idList, threadPoolTaskExecutor);
+        }
+
+    }
+    private void create(CoreEduTrainingPlan plan, List<Long> idList, ThreadPoolTaskExecutor executor) {
+        Long planId = plan.getId();
+        Date planStartDate = plan.getStartDate();
+        Date planEndDate = plan.getEndDate();
+
+        executor.execute(() -> {
+            CoreEduTrainingPlanDataVo detailPlanData = getCoreEduTrainingPlanDataVo(planId);
+            coreEduTrainingTaskService.createTaskForNow(detailPlanData, planStartDate, planEndDate, idList);
+        });
+    }
+
+    private List<CoreEduTrainingPlan> findReallyPlanIdList(List<Long> planIdList, List<Long> orgIdList) {
+
+        LambdaQueryWrapper<CoreEduTrainingPlan> wrapper = new LambdaQueryWrapper<>();
+        wrapper.in(CoreEduTrainingPlan::getId, planIdList);
+        wrapper.in(CoreEduTrainingPlan::getBelongOrgId, orgIdList);
+        return baseMapper.selectList(wrapper);
+    }
+
+    private boolean checkIsParentPlan(Long planId) {
+        //演练与培训的 行社下发的计划 id=parentId
+        LambdaQueryWrapper<CoreEduTrainingPlan> countWrapper = new LambdaQueryWrapper<>();
+        countWrapper.eq(CoreEduTrainingPlan::getParentId, planId);
+        countWrapper.ne(CoreEduTrainingPlan::getId, planId);
+        Long l = baseMapper.selectCount(countWrapper);
+        return ObjectUtil.isNotNull(l) && l.compareTo(0L) > 0;
+    }
+
+
+    private List<CoreEduTrainingPlan> getHsPlanList(CoreEduTrainingPlan drillPlan) {
+        LambdaQueryWrapper<CoreEduTrainingPlan> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(CoreEduTrainingPlan::getPlanStatus, DrillPlanStatus.USING.getCode());
+        wrapper.eq(CoreEduTrainingPlan::getDeleted, 0);
+        wrapper.eq(CoreEduTrainingPlan::getParentId, drillPlan.getId());
+        return baseMapper.selectList(wrapper);
+    }
+
+    private Map<String, Object> getHsOrg(List<SysOrgVO> orgCacheList, List<SysOrgVO> needBuildTaskOrgList, OrgTypeEnum needBuildTaskOrgTypeEnum) {
+        List<SysOrgVO> list = new ArrayList<>();
+        boolean underHsOrgType = false;
+        switch (needBuildTaskOrgTypeEnum) {
+            //如果是省联社/办事处/地区行社 那么找到下级的行社
+            case SHEGN_LIAN_SHE:
+            case BAN_SHI_CHU:
+            case DIQU_HANG_SHE:
+                for (SysOrgVO sysOrgVO : needBuildTaskOrgList) {
+                    String path = sysOrgVO.getPath();
+                    List<SysOrgVO> collect = orgCacheList
+                            .stream()
+                            .filter(org -> ObjectUtil.isAllNotEmpty(org.getPath(), org.getType()))
+                            .filter(org -> org.getPath().contains(path))
+                            .filter(org -> org.getType().equals(OrgTypeEnum.HANG_SHE.getCode()))
+                            .collect(toList());
+                    list.addAll(collect);
+                }
+                break;
+            case HANG_SHE: //如果传进来的就是行社 那么直接返回
+                list = needBuildTaskOrgList;
+                break;
+            default:    //如果是行社以下机构类型,那么找到上级的行社机构返回
+                List<Long> ids = needBuildTaskOrgList.stream().map(SysOrgVO::getId).collect(toList());
+                List<SysOrg> sysOrgs = orgService.selectParentHs(ids, SecurityConstants.INNER);
+                list = BeanHelper.copyProperties(sysOrgs, SysOrgVO.class);
+                underHsOrgType = true;
+        }
+
+        Map<String, Object> map = new HashMap<>();
+        map.put("list", list);
+        map.put("underHsOrgType", underHsOrgType);
+        return map;
+    }
+    @Override
+    public void run(Runnable runnable, ThreadPoolTaskExecutor threadPoolTaskExecutor) {
+        CompletableFuture.runAsync(runnable, threadPoolTaskExecutor);
+    }
 }

+ 20 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/edu/service/impl/CoreEduTrainingTaskServiceImpl.java

@@ -438,6 +438,26 @@ public class CoreEduTrainingTaskServiceImpl extends ServiceImpl<CoreEduTrainingT
     }
 
     @Override
+    public void createTaskForNow(CoreEduTrainingPlanDataVo plan, Date start, Date end, List<Long> orgIdList) {
+        if (plan.getPlanCycle() != 0) {
+            //如果不是无周期的计划,那么需要查询出他的时间范围
+            DateRange dateRange = DateUtils.getStartAndEnd(new Date(), EduTrainingPlanCycleEnum.toCommonEnum(plan.getPlanCycle()));
+            start = dateRange.getStartTime();
+            end = dateRange.getEndTime();
+        } else {
+            //无周期
+            start = DateUtil.beginOfDay(start).setField(DateField.MILLISECOND, 0);
+            end = DateUtil.endOfDay(end).setField(DateField.MILLISECOND, 0);
+        }
+        List<SysOrg> orgList = getExecOrgList(plan.getPlanExecOrgList(), plan.getExecOrgType(), plan.getBelongOrgPath());
+        if (ObjectUtil.isNotEmpty(orgIdList)) {
+            orgList = orgList.stream().filter(org -> orgIdList.contains(org.getId())).collect(Collectors.toList());
+        }
+        final List<SysWorkTime> workTimeList = getWorkTimeList(orgList, start, end);
+        saveTaskAndRoleData(plan, start, end, orgList, workTimeList);
+    }
+
+    @Override
     @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
     public void createTaskForNow(CoreEduTrainingPlanDataVo plan, Date start, Date end) {
 

+ 56 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/controller/CoreReminderConfigurationController.java

@@ -0,0 +1,56 @@
+package com.xunmei.core.reminder.controller;
+
+
+import com.xunmei.common.core.domain.reminder.dto.ReminderConfigEditDto;
+import com.xunmei.common.core.domain.reminder.dto.ReminderConfigPageDto;
+import com.xunmei.common.core.domain.reminder.vo.ReminderConfigDetailVo;
+import com.xunmei.common.core.web.domain.AjaxResult;
+import com.xunmei.common.core.web.page.TableDataInfo;
+import com.xunmei.core.reminder.service.ICoreReminderConfigurationService;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+import javax.validation.constraints.NotNull;
+
+/**
+ * <p>
+ * 前端控制器
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+@RestController
+@RequestMapping("/reminder/")
+public class CoreReminderConfigurationController {
+
+    @Autowired
+    private ICoreReminderConfigurationService configurationService;
+
+    @ApiOperation(value = "新增/修改配置")
+    @RequestMapping("page")
+    public TableDataInfo<?> page(@RequestBody ReminderConfigPageDto req) {
+        return configurationService.pageData(req);
+    }
+
+    @ApiOperation(value = "新增/修改配置")
+    @RequestMapping("config")
+    public AjaxResult addConfig(@RequestBody @Valid ReminderConfigEditDto editDto) {
+        configurationService.editConfig(editDto);
+        return AjaxResult.success();
+    }
+
+    @ApiOperation(value = "配置详情")
+    @RequestMapping("config/{id}")
+    public AjaxResult detail(@PathVariable("id") @NotNull String id) {
+        ReminderConfigDetailVo detailVo = configurationService.detail(id);
+        return AjaxResult.success(detailVo);
+    }
+
+}
+

+ 21 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/controller/CoreReminderLogController.java

@@ -0,0 +1,21 @@
+package com.xunmei.core.reminder.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+@RestController
+@RequestMapping("/com.xunmei.core.reminder/coreReminderLog")
+public class CoreReminderLogController {
+
+}
+

+ 21 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/controller/CoreReminderScheduleController.java

@@ -0,0 +1,21 @@
+package com.xunmei.core.reminder.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+@RestController
+@RequestMapping("/com.xunmei.core.reminder/coreReminderSchedule")
+public class CoreReminderScheduleController {
+
+}
+

+ 21 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/controller/CoreReminderTemplateController.java

@@ -0,0 +1,21 @@
+package com.xunmei.core.reminder.controller;
+
+
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+@RestController
+@RequestMapping("/com.xunmei.core.reminder/coreReminderTemplate")
+public class CoreReminderTemplateController {
+
+}
+

+ 21 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/mapper/CoreReminderConfigurationMapper.java

@@ -0,0 +1,21 @@
+package com.xunmei.core.reminder.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderConfiguration;
+import com.xunmei.common.core.domain.reminder.dto.ReminderConfigPageDto;
+import com.xunmei.common.core.domain.reminder.vo.ReminderConfigPageVo;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+public interface CoreReminderConfigurationMapper extends BaseMapper<CoreReminderConfiguration> {
+
+    Page<ReminderConfigPageVo> selectPageData(Page<ReminderConfigPageVo> page, @Param("req") ReminderConfigPageDto req);
+}

+ 22 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/mapper/CoreReminderConfigurationOrgMapper.java

@@ -0,0 +1,22 @@
+package com.xunmei.core.reminder.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderConfigurationOrg;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 短信提醒配置机构关联表 Mapper 接口
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+public interface CoreReminderConfigurationOrgMapper extends BaseMapper<CoreReminderConfigurationOrg> {
+
+    void deleteByConfigId(@Param("configId") Long configId);
+
+    List<CoreReminderConfigurationOrg> selectByConfigId(@Param("configId") Long configId);
+}

+ 21 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/mapper/CoreReminderConfigurationRoleMapper.java

@@ -0,0 +1,21 @@
+package com.xunmei.core.reminder.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderConfigurationRole;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+public interface CoreReminderConfigurationRoleMapper extends BaseMapper<CoreReminderConfigurationRole> {
+
+    void deleteByConfigId(@Param("configId") Long configId);
+    List<CoreReminderConfigurationRole> selectByConfigId(@Param("configId") Long configId);
+}

+ 16 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/mapper/CoreReminderLogMapper.java

@@ -0,0 +1,16 @@
+package com.xunmei.core.reminder.mapper;
+
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderLog;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+public interface CoreReminderLogMapper extends BaseMapper<CoreReminderLog> {
+
+}

+ 16 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/mapper/CoreReminderScheduleMapper.java

@@ -0,0 +1,16 @@
+package com.xunmei.core.reminder.mapper;
+
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderSchedule;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+public interface CoreReminderScheduleMapper extends BaseMapper<CoreReminderSchedule> {
+
+}

+ 16 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/mapper/CoreReminderTemplateMapper.java

@@ -0,0 +1,16 @@
+package com.xunmei.core.reminder.mapper;
+
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderTemplate;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+public interface CoreReminderTemplateMapper extends BaseMapper<CoreReminderTemplate> {
+
+}

+ 16 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/ICoreReminderConfigurationOrgService.java

@@ -0,0 +1,16 @@
+package com.xunmei.core.reminder.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderConfigurationOrg;
+
+/**
+ * <p>
+ * 短信提醒配置机构关联表 服务类
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+public interface ICoreReminderConfigurationOrgService extends IService<CoreReminderConfigurationOrg> {
+
+}

+ 16 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/ICoreReminderConfigurationRoleService.java

@@ -0,0 +1,16 @@
+package com.xunmei.core.reminder.service;
+
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderConfigurationRole;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+public interface ICoreReminderConfigurationRoleService extends IService<CoreReminderConfigurationRole> {
+
+}

+ 25 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/ICoreReminderConfigurationService.java

@@ -0,0 +1,25 @@
+package com.xunmei.core.reminder.service;
+
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderConfiguration;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.xunmei.common.core.domain.reminder.dto.ReminderConfigEditDto;
+import com.xunmei.common.core.domain.reminder.dto.ReminderConfigPageDto;
+import com.xunmei.common.core.domain.reminder.vo.ReminderConfigDetailVo;
+import com.xunmei.common.core.web.page.TableDataInfo;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+public interface ICoreReminderConfigurationService extends IService<CoreReminderConfiguration> {
+
+    void editConfig(ReminderConfigEditDto editDto);
+
+    ReminderConfigDetailVo detail(String id);
+
+    TableDataInfo<?> pageData(ReminderConfigPageDto req);
+}

+ 16 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/ICoreReminderLogService.java

@@ -0,0 +1,16 @@
+package com.xunmei.core.reminder.service;
+
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderLog;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+public interface ICoreReminderLogService extends IService<CoreReminderLog> {
+
+}

+ 16 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/ICoreReminderScheduleService.java

@@ -0,0 +1,16 @@
+package com.xunmei.core.reminder.service;
+
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderSchedule;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+public interface ICoreReminderScheduleService extends IService<CoreReminderSchedule> {
+
+}

+ 16 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/ICoreReminderTemplateService.java

@@ -0,0 +1,16 @@
+package com.xunmei.core.reminder.service;
+
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderTemplate;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+public interface ICoreReminderTemplateService extends IService<CoreReminderTemplate> {
+
+}

+ 20 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/impl/CoreReminderConfigurationOrgServiceImpl.java

@@ -0,0 +1,20 @@
+package com.xunmei.core.reminder.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderConfigurationOrg;
+import com.xunmei.core.reminder.mapper.CoreReminderConfigurationOrgMapper;
+import com.xunmei.core.reminder.service.ICoreReminderConfigurationOrgService;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 短信提醒配置机构关联表 服务实现类
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+@Service
+public class CoreReminderConfigurationOrgServiceImpl extends ServiceImpl<CoreReminderConfigurationOrgMapper, CoreReminderConfigurationOrg> implements ICoreReminderConfigurationOrgService {
+
+}

+ 20 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/impl/CoreReminderConfigurationRoleServiceImpl.java

@@ -0,0 +1,20 @@
+package com.xunmei.core.reminder.service.impl;
+
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderConfigurationRole;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.xunmei.core.reminder.mapper.CoreReminderConfigurationRoleMapper;
+import com.xunmei.core.reminder.service.ICoreReminderConfigurationRoleService;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+@Service
+public class CoreReminderConfigurationRoleServiceImpl extends ServiceImpl<CoreReminderConfigurationRoleMapper, CoreReminderConfigurationRole> implements ICoreReminderConfigurationRoleService {
+
+}

+ 134 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/impl/CoreReminderConfigurationServiceImpl.java

@@ -0,0 +1,134 @@
+package com.xunmei.core.reminder.service.impl;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.xunmei.common.core.constant.SecurityConstants;
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderConfiguration;
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderConfigurationOrg;
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderConfigurationRole;
+import com.xunmei.common.core.domain.reminder.dto.ReminderConfigEditDto;
+import com.xunmei.common.core.domain.reminder.dto.ReminderConfigPageDto;
+import com.xunmei.common.core.domain.reminder.vo.ReminderConfigDetailVo;
+import com.xunmei.common.core.domain.reminder.vo.ReminderConfigPageVo;
+import com.xunmei.common.core.vo.IdNameVo;
+import com.xunmei.common.core.web.page.TableDataInfo;
+import com.xunmei.core.reminder.mapper.CoreReminderConfigurationMapper;
+import com.xunmei.core.reminder.mapper.CoreReminderConfigurationOrgMapper;
+import com.xunmei.core.reminder.mapper.CoreReminderConfigurationRoleMapper;
+import com.xunmei.core.reminder.service.ICoreReminderConfigurationService;
+import com.xunmei.system.api.Eto.RoleConditionEto;
+import com.xunmei.system.api.RemoteOrgService;
+import com.xunmei.system.api.RemoteRoleService;
+import com.xunmei.system.api.domain.SysOrg;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 服务实现类
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+@Service
+public class CoreReminderConfigurationServiceImpl extends ServiceImpl<CoreReminderConfigurationMapper, CoreReminderConfiguration> implements ICoreReminderConfigurationService {
+    @Autowired
+    private RemoteOrgService orgService;
+    @Autowired
+    private RemoteRoleService roleService;
+    @Autowired
+    private CoreReminderConfigurationRoleMapper configurationRoleMapper;
+    @Autowired
+    private CoreReminderConfigurationOrgMapper coreReminderConfigurationOrgMapper;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void editConfig(ReminderConfigEditDto editDto) {
+        List<SysOrg> sysOrgList = orgService.selectByOrgIdList(editDto.getOrgIdList(), SecurityConstants.INNER);
+        List<IdNameVo> names = roleService.getNames(new RoleConditionEto(editDto.getRoleIdList()));
+        CoreReminderConfiguration config = getById(editDto.getConfigId());
+        if (config == null) {
+            config = new CoreReminderConfiguration();
+            populateBean(editDto, config);
+            save(config);
+            saveConfigurationRoles(config.getConfigId(), editDto.getRoleIdList(), names);
+            saveConfigurationOrgList(config.getConfigId(), sysOrgList);
+            return;
+        }
+        populateBean(editDto, config);
+        updateById(config);
+        configurationRoleMapper.deleteByConfigId(config.getConfigId());
+        saveConfigurationRoles(config.getConfigId(), editDto.getRoleIdList(), names);
+        coreReminderConfigurationOrgMapper.deleteByConfigId(config.getConfigId());
+        saveConfigurationOrgList(config.getConfigId(), sysOrgList);
+    }
+
+    @Override
+    public ReminderConfigDetailVo detail(String id) {
+
+        CoreReminderConfiguration configuration = getById(id);
+        if (configuration == null) {
+            throw new RuntimeException("未找到提醒配置");
+        }
+        ReminderConfigDetailVo detailVo = new ReminderConfigDetailVo();
+        BeanUtils.copyProperties(configuration, detailVo);
+        detailVo.setRoleList(configurationRoleMapper.selectByConfigId(configuration.getConfigId()));
+        detailVo.setOrgList(coreReminderConfigurationOrgMapper.selectByConfigId(configuration.getConfigId()));
+
+        return detailVo;
+    }
+
+    @Override
+    public TableDataInfo<?> pageData(ReminderConfigPageDto req) {
+        SysOrg sysOrg = orgService.selectOrgById(req.getOrgId(), SecurityConstants.INNER);
+        if (sysOrg == null) {
+            throw new RuntimeException("未找到机构");
+        }
+        req.setOrgPath(sysOrg.getPath());
+        Page<ReminderConfigPageVo> page = baseMapper.selectPageData(req.toPage(), req);
+        return TableDataInfo.build(page);
+    }
+
+    private void populateBean(ReminderConfigEditDto editDto, CoreReminderConfiguration config) {
+        config.setReminderType(editDto.getReminderType());
+        config.setSendModule(editDto.getSendModule());
+        if (editDto.getReminderType() == 0) {
+            config.setOverdueNoticePeriod(editDto.getDay());
+        } else {
+            config.setAdvanceNoticePeriod(editDto.getDay());
+        }
+        config.setEnabled(editDto.getEnabled());
+    }
+
+    private void saveConfigurationRoles(Long configId, List<Long> roleIdList, List<IdNameVo> names) {
+        for (Long roleId : roleIdList) {
+            CoreReminderConfigurationRole configurationRole = new CoreReminderConfigurationRole();
+            configurationRole.setTargetRoleId(roleId);
+            String targetRoleName = names.stream()
+                    .filter(idNameVo -> idNameVo.getId().equals(roleId))
+                    .map(IdNameVo::getName)
+                    .findFirst()
+                    .orElse(null);
+            configurationRole.setTargetRoleName(targetRoleName);
+            configurationRole.setConfigId(configId);
+            configurationRoleMapper.insert(configurationRole);
+        }
+    }
+
+    private void saveConfigurationOrgList(Long configId, List<SysOrg> orgList) {
+        for (SysOrg sysOrg : orgList) {
+            CoreReminderConfigurationOrg configurationOrg = new CoreReminderConfigurationOrg();
+            configurationOrg.setTargetOrgId(sysOrg.getId());
+            configurationOrg.setTargetOrgName(sysOrg.getName());
+            configurationOrg.setTargetOrgType(sysOrg.getType());
+            configurationOrg.setTargetOrgPath(sysOrg.getPath());
+            configurationOrg.setConfigId(configId);
+            coreReminderConfigurationOrgMapper.insert(configurationOrg);
+        }
+    }
+}

+ 20 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/impl/CoreReminderLogServiceImpl.java

@@ -0,0 +1,20 @@
+package com.xunmei.core.reminder.service.impl;
+
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderLog;
+import com.xunmei.core.reminder.mapper.CoreReminderLogMapper;
+import com.xunmei.core.reminder.service.ICoreReminderLogService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+@Service
+public class CoreReminderLogServiceImpl extends ServiceImpl<CoreReminderLogMapper, CoreReminderLog> implements ICoreReminderLogService {
+
+}

+ 20 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/impl/CoreReminderScheduleServiceImpl.java

@@ -0,0 +1,20 @@
+package com.xunmei.core.reminder.service.impl;
+
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderSchedule;
+import com.xunmei.core.reminder.mapper.CoreReminderScheduleMapper;
+import com.xunmei.core.reminder.service.ICoreReminderScheduleService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+@Service
+public class CoreReminderScheduleServiceImpl extends ServiceImpl<CoreReminderScheduleMapper, CoreReminderSchedule> implements ICoreReminderScheduleService {
+
+}

+ 20 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/reminder/service/impl/CoreReminderTemplateServiceImpl.java

@@ -0,0 +1,20 @@
+package com.xunmei.core.reminder.service.impl;
+
+import com.xunmei.common.core.domain.reminder.domain.CoreReminderTemplate;
+import com.xunmei.core.reminder.mapper.CoreReminderTemplateMapper;
+import com.xunmei.core.reminder.service.ICoreReminderTemplateService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author jingYuanChao
+ * @since 2024-04-12
+ */
+@Service
+public class CoreReminderTemplateServiceImpl extends ServiceImpl<CoreReminderTemplateMapper, CoreReminderTemplate> implements ICoreReminderTemplateService {
+
+}

+ 4 - 0
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/resumption/mapper/AppPlanToExecOrgMapper.java

@@ -3,8 +3,11 @@ package com.xunmei.core.resumption.mapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.xunmei.core.resumption.domain.AppPlanToExecOrg;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 import org.springframework.stereotype.Repository;
 
+import java.util.List;
+
 /**
  * 执行机构关系表(core_resumption_plan_to_exec_org)数据Mapper
  *
@@ -16,4 +19,5 @@ import org.springframework.stereotype.Repository;
 @Repository
 public interface AppPlanToExecOrgMapper extends BaseMapper<AppPlanToExecOrg> {
 
+    List<AppPlanToExecOrg> selectByPlanId(@Param("planId") Long planId);
 }

+ 205 - 71
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/resumption/service/impl/AppPlanServiceImpl.java

@@ -11,26 +11,28 @@ import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
-import com.xunmei.common.core.constant.Constants;
-import com.xunmei.common.core.constant.DictConstants;
-import com.xunmei.common.core.constant.ErrorMsgConstants;
-import com.xunmei.common.core.constant.SecurityConstants;
+import com.google.common.collect.Lists;
+import com.xunmei.common.core.constant.*;
 import com.xunmei.common.core.domain.DateRange;
 import com.xunmei.common.core.domain.R;
+import com.xunmei.common.core.domain.registerbook.domain.CoreRegisterBookPdf;
 import com.xunmei.common.core.enums.CycleCommonEnum;
 import com.xunmei.common.core.enums.OrgTypeEnum;
 import com.xunmei.common.core.enums.PlanStatus;
+import com.xunmei.common.core.enums.RegisterBookType;
 import com.xunmei.common.core.enums.resumption.ResumptionTaskStatus;
 import com.xunmei.common.core.exception.ServiceException;
-import com.xunmei.common.core.domain.registerbook.domain.CoreRegisterBookPdf;
-import com.xunmei.common.core.enums.RegisterBookType;
 import com.xunmei.common.core.exception.SystemException;
+import com.xunmei.common.core.thread.ThreadPoolConfig;
+import com.xunmei.common.core.util.BeanHelper;
 import com.xunmei.common.core.utils.DateUtils;
 import com.xunmei.common.core.utils.IDHelper;
 import com.xunmei.common.core.vo.IdNameVo;
 import com.xunmei.common.redis.utils.RedisUtils;
 import com.xunmei.common.security.utils.DictUtils;
 import com.xunmei.common.security.utils.SecurityUtils;
+import com.xunmei.core.compense.dto.CompensateDto;
+import com.xunmei.core.compense.interfaces.CompensateService;
 import com.xunmei.core.question.QuestionSrcType;
 import com.xunmei.core.question.domain.Question;
 import com.xunmei.core.question.service.IQuestionService;
@@ -43,17 +45,18 @@ import com.xunmei.core.resumption.dto.plan.CoreResumptionPlanPageDto;
 import com.xunmei.core.resumption.mapper.*;
 import com.xunmei.core.resumption.service.AppPlanService;
 import com.xunmei.core.resumption.service.IResumptionRecordService;
-import com.xunmei.core.resumption.task.ResumptionTaskBusinessService;
+import com.xunmei.core.resumption.task.ResumptionTaskBusiness;
 import com.xunmei.core.resumption.vo.appPlan.*;
 import com.xunmei.core.resumption.vo.resumptionRecord.AppResumptionDataInfoVo;
-import com.xunmei.common.core.thread.ThreadPoolConfig;
 import com.xunmei.system.api.RemoteFileService;
 import com.xunmei.system.api.RemoteOrgService;
 import com.xunmei.system.api.domain.ResumptionPdf;
 import com.xunmei.system.api.domain.SysDictData;
 import com.xunmei.system.api.domain.SysOrg;
+import com.xunmei.common.core.enums.BusinessPlanType;
 import com.xunmei.system.api.function.RemoteCallHandlerExecutor;
 import com.xunmei.system.api.vo.QuestionPdfVo;
+import com.xunmei.system.api.vo.SysOrgVO;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.BeanUtils;
@@ -79,7 +82,7 @@ import java.util.stream.Collectors;
  */
 @Slf4j
 @Service
-public class AppPlanServiceImpl extends ServiceImpl<AppPlanMapper, AppPlan> implements AppPlanService {
+public class AppPlanServiceImpl extends ServiceImpl<AppPlanMapper, AppPlan> implements AppPlanService, CompensateService {
     @Resource
     IResumptionRecordService resumptionRecordService;
     @Autowired
@@ -104,7 +107,7 @@ public class AppPlanServiceImpl extends ServiceImpl<AppPlanMapper, AppPlan> impl
     private ThreadPoolTaskExecutor threadPoolTaskExecutor;
 
     @Autowired
-    ResumptionTaskBusinessService resumptionTaskBusiness;
+    ResumptionTaskBusiness resumptionTaskBusiness;
 
     @Autowired
     ICoreRegisterBookPdfService coreRegisterBookPdfService;
@@ -119,7 +122,6 @@ public class AppPlanServiceImpl extends ServiceImpl<AppPlanMapper, AppPlan> impl
     private CoreRegisterBookPdfMapper coreRegisterBookPdfMapper;
 
 
-
     @Override
     public List<Long> selectItemIdsByPlanId(Long id) {
         return appPlanToItemMapper.selectItemIdsByPlanId(id);
@@ -304,7 +306,7 @@ public class AppPlanServiceImpl extends ServiceImpl<AppPlanMapper, AppPlan> impl
         }
 
         if (immediateEffect) {
-            resumptionTaskBusiness.rebuildCurrentCycleTask(hsPlans,dto.getId());
+            resumptionTaskBusiness.rebuildCurrentCycleTask(hsPlans, dto.getId());
         }
     }
 
@@ -364,18 +366,17 @@ public class AppPlanServiceImpl extends ServiceImpl<AppPlanMapper, AppPlan> impl
         baseMapper.copyPlanOrgs(id, newPlanId);
     }
 
-    private void checkPlanIsCreatingTask(Long planId,String msg)
-    {
-        String redisKey="Resumption_Creating_Task" + planId;
+    private void checkPlanIsCreatingTask(Long planId, String msg) {
+        String redisKey = "Resumption_Creating_Task" + planId;
         Boolean hasKey = RedisUtils.hasKey(redisKey);
         if (hasKey) {
-            throw new ServiceException("该任务正在生成中,现在不能被"+msg+",请稍后再试。");
+            throw new ServiceException("该任务正在生成中,现在不能被" + msg + ",请稍后再试。");
         }
     }
 
     @Override
     public void cheHui(Long id) {
-        checkPlanIsCreatingTask(id,"撤回");
+        checkPlanIsCreatingTask(id, "撤回");
         Date now = new Date();
         AppPlan plan = baseMapper.selectById(id);
         if (ObjectUtil.equal(plan.getTaskHasCompleted(), 1)) {
@@ -945,7 +946,7 @@ public class AppPlanServiceImpl extends ServiceImpl<AppPlanMapper, AppPlan> impl
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void deleted(Long id) throws Exception {
-        checkPlanIsCreatingTask(id,"删除");
+        checkPlanIsCreatingTask(id, "删除");
         AppPlan plan = baseMapper.selectById(id);
         if (ObjectUtil.isNull(plan)) {
             throw new ServiceException("任务不存在");
@@ -1112,13 +1113,12 @@ public class AppPlanServiceImpl extends ServiceImpl<AppPlanMapper, AppPlan> impl
             SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
             String dateStr = sdf.format(date);
             LambdaQueryWrapper<CoreRegisterBookPdf> wrapper = new LambdaQueryWrapper<>();
-            wrapper.eq(CoreRegisterBookPdf::getOrgId,orgId)
-                    .eq(CoreRegisterBookPdf::getDate,dateStr)
-                    .eq(CoreRegisterBookPdf::getRegisterBookType,RegisterBookType.ON_DUTY_USER.getNum())
-                    .like(CoreRegisterBookPdf::getFileName,sysOrg.getName() + "_" + RegisterBookType.ON_DUTY_USER.getText() + "_");
+            wrapper.eq(CoreRegisterBookPdf::getOrgId, orgId)
+                    .eq(CoreRegisterBookPdf::getDate, dateStr)
+                    .eq(CoreRegisterBookPdf::getRegisterBookType, RegisterBookType.ON_DUTY_USER.getNum())
+                    .like(CoreRegisterBookPdf::getFileName, sysOrg.getName() + "_" + RegisterBookType.ON_DUTY_USER.getText() + "_");
             CoreRegisterBookPdf registerBookPdf = coreRegisterBookPdfMapper.selectOne(wrapper);
-            if(ObjectUtil.isEmpty(registerBookPdf))
-            {
+            if (ObjectUtil.isEmpty(registerBookPdf)) {
                 registerBookPdf = new CoreRegisterBookPdf();
                 registerBookPdf.setId(IdWorker.getId());
                 registerBookPdf.setRegisterBookType(RegisterBookType.ON_DUTY_USER.getNum());
@@ -1128,8 +1128,7 @@ public class AppPlanServiceImpl extends ServiceImpl<AppPlanMapper, AppPlan> impl
                 registerBookPdf.setOrgPath(sysOrg.getPath());
                 registerBookPdf.setFileUrl(pdfUrl);
                 registerBookPdf.setFileName(fileName);
-            }
-            else{
+            } else {
                 registerBookPdf.setFileUrl(pdfUrl);
                 registerBookPdf.setFileName(fileName);
             }
@@ -1171,13 +1170,12 @@ public class AppPlanServiceImpl extends ServiceImpl<AppPlanMapper, AppPlan> impl
 
             String pdfUrl = r.getData();
             LambdaQueryWrapper<CoreRegisterBookPdf> wrapper = new LambdaQueryWrapper<>();
-            wrapper.eq(CoreRegisterBookPdf::getOrgId,orgId)
+            wrapper.eq(CoreRegisterBookPdf::getOrgId, orgId)
                     .eq(CoreRegisterBookPdf::getDate, dateStr)
-                    .eq(CoreRegisterBookPdf::getRegisterBookType,RegisterBookType.SECURITY_PERFORMANCE.getNum())
-                    .like(CoreRegisterBookPdf::getFileName,sysOrg.getName() + "_" + RegisterBookType.SECURITY_PERFORMANCE.getText() + "_");
+                    .eq(CoreRegisterBookPdf::getRegisterBookType, RegisterBookType.SECURITY_PERFORMANCE.getNum())
+                    .like(CoreRegisterBookPdf::getFileName, sysOrg.getName() + "_" + RegisterBookType.SECURITY_PERFORMANCE.getText() + "_");
             CoreRegisterBookPdf registerBookPdf = coreRegisterBookPdfMapper.selectOne(wrapper);
-            if(ObjectUtil.isEmpty(registerBookPdf))
-            {
+            if (ObjectUtil.isEmpty(registerBookPdf)) {
                 registerBookPdf = new CoreRegisterBookPdf();
                 registerBookPdf.setId(IdWorker.getId());
                 registerBookPdf.setRegisterBookType(RegisterBookType.SECURITY_PERFORMANCE.getNum());
@@ -1187,8 +1185,7 @@ public class AppPlanServiceImpl extends ServiceImpl<AppPlanMapper, AppPlan> impl
                 registerBookPdf.setOrgPath(sysOrg.getPath());
                 registerBookPdf.setFileUrl(pdfUrl);
                 registerBookPdf.setFileName(fileName);
-            }
-            else{
+            } else {
                 registerBookPdf.setFileUrl(pdfUrl);
                 registerBookPdf.setFileName(fileName);
             }
@@ -1251,13 +1248,12 @@ public class AppPlanServiceImpl extends ServiceImpl<AppPlanMapper, AppPlan> impl
                 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                 String dateStr = sdf.format(date);
                 LambdaQueryWrapper<CoreRegisterBookPdf> wrapper = new LambdaQueryWrapper<>();
-                wrapper.eq(CoreRegisterBookPdf::getOrgId,orgId)
-                        .eq(CoreRegisterBookPdf::getDate,dateStr)
-                        .eq(CoreRegisterBookPdf::getRegisterBookType,RegisterBookType.getEnums((Integer) data.get("planType")).getNum())
-                        .like(CoreRegisterBookPdf::getFileName,sysOrg.getName() + "_" + RegisterBookType.getEnums((Integer) data.get("planType")).getText() + "_");
+                wrapper.eq(CoreRegisterBookPdf::getOrgId, orgId)
+                        .eq(CoreRegisterBookPdf::getDate, dateStr)
+                        .eq(CoreRegisterBookPdf::getRegisterBookType, RegisterBookType.getEnums((Integer) data.get("planType")).getNum())
+                        .like(CoreRegisterBookPdf::getFileName, sysOrg.getName() + "_" + RegisterBookType.getEnums((Integer) data.get("planType")).getText() + "_");
                 CoreRegisterBookPdf registerBookPdf = coreRegisterBookPdfMapper.selectOne(wrapper);
-                if(ObjectUtil.isEmpty(registerBookPdf))
-                {
+                if (ObjectUtil.isEmpty(registerBookPdf)) {
                     registerBookPdf = new CoreRegisterBookPdf();
                     registerBookPdf.setId(IdWorker.getId());
                     registerBookPdf.setRegisterBookType(RegisterBookType.getEnums((Integer) data.get("planType")).getNum());
@@ -1267,8 +1263,7 @@ public class AppPlanServiceImpl extends ServiceImpl<AppPlanMapper, AppPlan> impl
                     registerBookPdf.setOrgPath(sysOrg.getPath());
                     registerBookPdf.setFileUrl(pdfUrl);
                     registerBookPdf.setFileName(data.get("fileName").toString());
-                }
-                else{
+                } else {
                     registerBookPdf.setFileUrl(pdfUrl);
                     registerBookPdf.setFileName(data.get("fileName").toString());
                 }
@@ -1287,9 +1282,8 @@ public class AppPlanServiceImpl extends ServiceImpl<AppPlanMapper, AppPlan> impl
         //查询执行时刻为全天的的履职数据
         List<Resumption> allDayDataList = resumptionMapper.selectBySubmitTimeAndPlanType(date, Arrays.asList(4, 5, 6), sysOrg.getId());
         // 获取未完成且任务结束时间在当天
-        List<Resumption> dataList2 = resumptionMapper.selectByEndDateAndPlanType(DateUtil.beginOfDay(date),DateUtil.endOfDay(date), Arrays.asList(4, 5, 6), sysOrg.getId());
-        if(dataList2.size()>0)
-        {
+        List<Resumption> dataList2 = resumptionMapper.selectByEndDateAndPlanType(DateUtil.beginOfDay(date), DateUtil.endOfDay(date), Arrays.asList(4, 5, 6), sysOrg.getId());
+        if (dataList2.size() > 0) {
             allDayDataList.addAll(dataList2);
         }
         //全天的的履职数据需要生成三种登记簿,所以还需要跟根据任务类型来分组 // 4:“110”入侵报警系统测试 5:不间断电源(UPS)维护 6:离行式自助银行巡检
@@ -1302,10 +1296,9 @@ public class AppPlanServiceImpl extends ServiceImpl<AppPlanMapper, AppPlan> impl
             List<AppResumptionDataInfoVo> allDayInfo = getItems(allDayDataList);
             Map<Long, List<AppResumptionDataInfoVo>> afterf = allDayInfo.stream().collect(Collectors.groupingBy(AppResumptionDataInfoVo::getItemId));
             data.put(DictUtils.getDictLabel(DictConstants.RESUMPTION_PLAN_EXEC, 1), getResult(afterf));
-            String tempSubmitNames=  allDayDataList.stream().map(Resumption::getSubmitorName).distinct().filter(x->ObjectUtil.isNotEmpty(x)).collect(Collectors.joining(","));
-            if("null".equals(tempSubmitNames))
-            {
-                tempSubmitNames=StringUtils.EMPTY;
+            String tempSubmitNames = allDayDataList.stream().map(Resumption::getSubmitorName).distinct().filter(x -> ObjectUtil.isNotEmpty(x)).collect(Collectors.joining(","));
+            if ("null".equals(tempSubmitNames)) {
+                tempSubmitNames = StringUtils.EMPTY;
             }
             // 提交人
             data.put("submiterNames", tempSubmitNames);
@@ -1326,18 +1319,16 @@ public class AppPlanServiceImpl extends ServiceImpl<AppPlanMapper, AppPlan> impl
         // 获取当天提交已完成的履职任务
         List<Resumption> dataList = resumptionMapper.selectBySubmitTimeAndPlanType(date, Arrays.asList(7), orgId);
         // 获取未完成且任务结束时间在当天
-        List<Resumption> dataList2 = resumptionMapper.selectByEndDateAndPlanType(DateUtil.beginOfDay(date),DateUtil.endOfDay(date), Arrays.asList(7), orgId);
-        if(dataList2.size()>0)
-        {
+        List<Resumption> dataList2 = resumptionMapper.selectByEndDateAndPlanType(DateUtil.beginOfDay(date), DateUtil.endOfDay(date), Arrays.asList(7), orgId);
+        if (dataList2.size() > 0) {
             dataList.addAll(dataList2);
         }
         List<AppResumptionDataInfoVo> notWorkTimeInfo = getItems(dataList);
         Map<Long, List<AppResumptionDataInfoVo>> afterf = notWorkTimeInfo.stream().collect(Collectors.groupingBy(AppResumptionDataInfoVo::getItemId));
         data.put(DictUtils.getDictLabel(DictConstants.RESUMPTION_PLAN_EXEC, 5), getResult(afterf));
-        String tempSubmitNames= dataList.stream().map(Resumption::getSubmitorName).distinct().filter(x->ObjectUtil.isNotEmpty(x)).collect(Collectors.joining(","));
-        if("null".equals(tempSubmitNames))
-        {
-            tempSubmitNames=StringUtils.EMPTY;
+        String tempSubmitNames = dataList.stream().map(Resumption::getSubmitorName).distinct().filter(x -> ObjectUtil.isNotEmpty(x)).collect(Collectors.joining(","));
+        if ("null".equals(tempSubmitNames)) {
+            tempSubmitNames = StringUtils.EMPTY;
         }
         // 提交人
         data.put("submiterNames", tempSubmitNames);
@@ -1385,14 +1376,12 @@ public class AppPlanServiceImpl extends ServiceImpl<AppPlanMapper, AppPlan> impl
         submiterNames.addAll(ing.stream().map(x -> x.getSubmitorName()).collect(Collectors.toList()));
         submiterNames.addAll(after.stream().map(x -> x.getSubmitorName()).collect(Collectors.toList()));
         submiterNames = submiterNames.stream().distinct().collect(Collectors.toList());
-        if(ObjectUtil.isNotEmpty(submiterNames))
-        {
-            submiterNames= submiterNames.stream().filter(x->ObjectUtil.isNotEmpty(x)).collect(Collectors.toList());
+        if (ObjectUtil.isNotEmpty(submiterNames)) {
+            submiterNames = submiterNames.stream().filter(x -> ObjectUtil.isNotEmpty(x)).collect(Collectors.toList());
         }
-        String tempSubmitNames= String.join(",", submiterNames);
-        if("null".equals(tempSubmitNames) || StringUtils.isEmpty(tempSubmitNames))
-        {
-            tempSubmitNames=StringUtils.EMPTY;
+        String tempSubmitNames = String.join(",", submiterNames);
+        if ("null".equals(tempSubmitNames) || StringUtils.isEmpty(tempSubmitNames)) {
+            tempSubmitNames = StringUtils.EMPTY;
         }
         data.put("submiterNames", tempSubmitNames);
         // 获取任务相关问题
@@ -1406,7 +1395,7 @@ public class AppPlanServiceImpl extends ServiceImpl<AppPlanMapper, AppPlan> impl
     public List<AppResumptionDataInfoVo> getItems(List<Resumption> resumptions) {
         List<AppResumptionDataInfoVo> vos = new ArrayList<>();
         for (Resumption r : resumptions) {
-            vos.addAll(resumptionRecordService.getResumptionDataById(r.getId(),r.getStatus(),r.getPlanId(),r.getOrgId()));
+            vos.addAll(resumptionRecordService.getResumptionDataById(r.getId(), r.getStatus(), r.getPlanId(), r.getOrgId()));
 //            List<ResumptionRecordItemVo> items = resumptionRecordVo.getItems();
 //            for (ResumptionRecordItemVo v : items) {
 //                vos.addAll(v.getDataInfoList());
@@ -1427,14 +1416,11 @@ public class AppPlanServiceImpl extends ServiceImpl<AppPlanMapper, AppPlan> impl
             // for (AppResumptionDataInfoVo vo :bef.get(l)) {
             for (AppResumptionDataInfoVo vo : map.getValue()) {
                 pointName = vo.getPointName();
-                if(ObjectUtil.isNotNull(vo.getResValue()))
-                {
-                    if(vo.getResValue()>0)
-                    {
-                        result=1;
-                    }
-                    else {
-                        result=0;
+                if (ObjectUtil.isNotNull(vo.getResValue())) {
+                    if (vo.getResValue() > 0) {
+                        result = 1;
+                    } else {
+                        result = 0;
                     }
                 }
                 if (!(submitName.toString().contains(vo.getSubmitName()))) {
@@ -1500,4 +1486,152 @@ public class AppPlanServiceImpl extends ServiceImpl<AppPlanMapper, AppPlan> impl
 
         return hsOrgs;
     }
+
+    @Override
+    public BusinessPlanType getBusinessPlanType() {
+        return BusinessPlanType.RESUMPTION;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void compensate(CompensateDto compensateDto) {
+        /**
+         * 1、判断用户传进来的计划是省联社计划id还是办事处/地区行社/行社计划id?
+         * 1.2、随后把找到的计划转成行社计划 = planIdLIst
+         * 2、判断用户传进来的机构id数组,机构类型到底是地区、行社还是网点及以下
+         * 2.2、随后把地区或者网点及以下机构全部转成行社=orgIdList
+         * 3、随后去数据库 用in查询 planIdLIst与orgIdList 两个数组,找到真正应该生成任务的计划id数组=reallyPlanIdList
+         * 3.3、再根据reallyPlanIdList 的执行类型或者具体机构找到应该生成任务的机构id=reallyOrgIdList
+         * 4、此时如果传进来的机构id数组 是网点及以下机构类型,那么说明用户是执行了具体需要生成任务的机构  那么根据传进来机构id数组 去过滤reallyOrgIdList
+         */
+        AppPlan appPlan = getById(compensateDto.getPlanId());
+
+        if (ObjectUtil.isNull(appPlan)) {
+            throw new ServiceException("计划不存在");
+        }
+
+        if (ObjectUtil.notEqual(appPlan.getPlanStatus(), PlanStatus.USING.getCode())) {
+            throw new ServiceException("计划尚未下发或已停用");
+        }
+
+        if (ObjectUtil.equal(appPlan.getDeleted(), 1)) {
+            throw new ServiceException("计划状态异常");
+        }
+
+        List<SysOrgVO> orgCacheList = RedisUtils.getCacheList(CacheConstants.ORG_CACHE_LIST_KEY);
+        //推断计划
+        deducePlanAndBuildTask(appPlan, compensateDto.getOrgIdList(), orgCacheList);
+
+    }
+
+    private void deducePlanAndBuildTask(AppPlan appPlan, List<Long> orgIdList, List<SysOrgVO> orgCacheList) {
+        List<SysOrgVO> orgList = orgCacheList.stream().filter(org -> orgIdList.contains(org.getId())).collect(Collectors.toList());
+        if (orgList.isEmpty()) {
+            throw new ServiceException("未查询到orgIdList中指定的机构信息");
+        }
+        List<Integer> typeList = orgList.stream().map(SysOrgVO::getType).distinct().collect(Collectors.toList());
+        if (typeList.size() > 1) {
+            throw new ServiceException("orgIdList中指定的机构信息存在多种机构类型");
+        }
+
+        OrgTypeEnum orgTypeEnum = OrgTypeEnum.getOrgTypeEnum(typeList.get(0));
+
+        //省联社创建的计划
+        if (checkIsParentPlan(appPlan.getId())) {
+            //把传进来的计划转成 行社计划
+            List<AppPlan> allHsPlanList = getHsPlanList(appPlan);
+            if (ObjectUtil.isEmpty(allHsPlanList)) {
+                return;
+            }
+            //把传进来的机构信息转成行社机构
+            Map<String, Object> map = getHsOrg(orgCacheList, orgList, orgTypeEnum);
+            List<Long> hsPlanIdList = allHsPlanList.stream().map(AppPlan::getId).collect(Collectors.toList());
+            List<Long> hsOrgIdList = ((List<SysOrgVO>) map.get("list")).stream().map(SysOrgVO::getId).collect(Collectors.toList());
+            List<AppPlan> reallyPlanIdList = findReallyPlanIdList(hsPlanIdList, hsOrgIdList);
+            boolean underHsOrgType = (boolean) map.get("underHsOrgType");
+            if (underHsOrgType) {
+                List<Long> idList = orgList.stream().map(SysOrgVO::getId).collect(Collectors.toList());
+                run(() -> resumptionTaskBusiness.buildTask(idList, reallyPlanIdList, new Date()), threadPoolTaskExecutor);
+            } else {
+                run(() -> resumptionTaskBusiness.buildTask(null, reallyPlanIdList, new Date()), threadPoolTaskExecutor);
+            }
+            return;
+        }
+        //行社自建计划
+        if (OrgTypeEnum.SHEGN_LIAN_SHE.equals(orgTypeEnum) || OrgTypeEnum.BAN_SHI_CHU.equals(orgTypeEnum) || OrgTypeEnum.DIQU_HANG_SHE.equals(orgTypeEnum)) {
+            throw new ServiceException("orgIdList中传递机构信息错误!与计划信息不匹配");
+        }
+        if (OrgTypeEnum.HANG_SHE.equals(orgTypeEnum)){
+            run(() -> resumptionTaskBusiness.buildTask(null, Lists.newArrayList(appPlan), new Date()), threadPoolTaskExecutor);
+        }else {
+            run(() -> resumptionTaskBusiness.buildTask(orgIdList, Lists.newArrayList(appPlan), new Date()), threadPoolTaskExecutor);
+        }
+
+
+    }
+
+    @Override
+    public void run(Runnable runnable, ThreadPoolTaskExecutor threadPoolTaskExecutor) {
+        CompletableFuture.runAsync(runnable, threadPoolTaskExecutor);
+    }
+
+    private List<AppPlan> findReallyPlanIdList(List<Long> planIdList, List<Long> orgIdList) {
+
+        LambdaQueryWrapper<AppPlan> wrapper = new LambdaQueryWrapper<>();
+        wrapper.in(AppPlan::getId, planIdList);
+        wrapper.in(AppPlan::getPlanOfOrgId, orgIdList);
+        return baseMapper.selectList(wrapper);
+    }
+
+    private boolean checkIsParentPlan(Long planId) {
+        LambdaQueryWrapper<AppPlan> countWrapper = new LambdaQueryWrapper<>();
+        countWrapper.eq(AppPlan::getParentId, planId);
+        Long l = baseMapper.selectCount(countWrapper);
+        return ObjectUtil.isNotNull(l) && l.compareTo(0L) > 0;
+    }
+
+
+    private List<AppPlan> getHsPlanList(AppPlan appPlan) {
+        LambdaQueryWrapper<AppPlan> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(AppPlan::getPlanStatus, PlanStatus.USING.getCode());
+        wrapper.eq(AppPlan::getDeleted, 0);
+        wrapper.eq(AppPlan::getParentId, appPlan.getId());
+        wrapper.eq(AppPlan::getPlanOfOrgType, OrgTypeEnum.HANG_SHE.getCode());
+        return baseMapper.selectList(wrapper);
+    }
+
+    private Map<String, Object> getHsOrg(List<SysOrgVO> orgCacheList, List<SysOrgVO> needBuildTaskOrgList, OrgTypeEnum needBuildTaskOrgTypeEnum) {
+        List<SysOrgVO> list = new ArrayList<>();
+        boolean underHsOrgType = false;
+        switch (needBuildTaskOrgTypeEnum) {
+            //如果是省联社/办事处/地区行社 那么找到下级的行社
+            case SHEGN_LIAN_SHE:
+            case BAN_SHI_CHU:
+            case DIQU_HANG_SHE:
+                for (SysOrgVO sysOrgVO : needBuildTaskOrgList) {
+                    String path = sysOrgVO.getPath();
+                    List<SysOrgVO> collect = orgCacheList
+                            .stream()
+                            .filter(org -> ObjectUtil.isAllNotEmpty(org.getPath(), org.getType()))
+                            .filter(org -> org.getPath().contains(path))
+                            .filter(org -> org.getType().equals(OrgTypeEnum.HANG_SHE.getCode()))
+                            .collect(Collectors.toList());
+                    list.addAll(collect);
+                }
+                break;
+            case HANG_SHE: //如果传进来的就是行社 那么直接返回
+                list = needBuildTaskOrgList;
+                break;
+            default:    //如果是行社以下机构类型,那么找到上级的行社机构返回
+                List<Long> ids = needBuildTaskOrgList.stream().map(SysOrgVO::getId).collect(Collectors.toList());
+                List<SysOrg> sysOrgs = remoteOrgService.selectParentHs(ids, SecurityConstants.INNER);
+                list = BeanHelper.copyProperties(sysOrgs, SysOrgVO.class);
+                underHsOrgType = true;
+        }
+
+        Map<String, Object> map = new HashMap<>();
+        map.put("list", list);
+        map.put("underHsOrgType", underHsOrgType);
+        return map;
+    }
 }

+ 2 - 9
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/retrieval/service/ICoreMonitoringRetrievalTaskBuilderService.java

@@ -1,20 +1,11 @@
 package com.xunmei.core.retrieval.service;
 
-import cn.hutool.core.date.DateTime;
 import com.baomidou.mybatisplus.extension.service.IService;
-import com.xunmei.common.core.domain.panel.dto.PanelListDto;
-import com.xunmei.common.core.domain.panel.vo.PanelListVo;
 import com.xunmei.common.core.domain.retrieval.domain.CoreMonitoringRetrievalTask;
-import com.xunmei.common.core.domain.retrieval.dto.RetrievalTaskPageDto;
 import com.xunmei.common.core.domain.retrieval.vo.CoreMonitoringRetrievalTaskOneVo;
-import com.xunmei.common.core.domain.safetyindex.dto.SafeScoreSourceDto;
 import com.xunmei.common.core.event.WorkTimeChangeEvent;
-import com.xunmei.common.core.web.page.TableDataInfo;
 import com.xunmei.core.access.domain.TMonitoringRetrievalPlan;
-import com.xunmei.core.access.dto.CoreMonitoringTaskRegistrationDTO;
 
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
 import java.time.LocalDate;
 import java.util.Date;
 import java.util.List;
@@ -169,4 +160,6 @@ public interface ICoreMonitoringRetrievalTaskBuilderService extends IService<Cor
 
 
     void taskChangeForTimeWorkChange(WorkTimeChangeEvent event);
+
+    void createAndSaveTask(List<TMonitoringRetrievalPlan> planList,LocalDate taskTime,List<Long> needBuildTaskOrgIdList);
 }

+ 57 - 33
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/retrieval/service/impl/CoreMonitoringRetrievalTaskBuilderServiceImpl.java

@@ -6,6 +6,7 @@ import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.ObjectUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -14,10 +15,11 @@ import com.xunmei.common.core.constant.ErrorMsgConstants;
 import com.xunmei.common.core.constant.SecurityConstants;
 import com.xunmei.common.core.domain.DateRange;
 import com.xunmei.common.core.domain.retrieval.domain.CoreMonitoringRetrievalTask;
-import com.xunmei.common.core.domain.retrieval.vo.*;
+import com.xunmei.common.core.domain.retrieval.vo.CoreMonitoringRetrievalTaskOneVo;
+import com.xunmei.common.core.domain.retrieval.vo.KeyValueVo;
+import com.xunmei.common.core.domain.retrieval.vo.TaskDataVo;
 import com.xunmei.common.core.domain.worktime.domain.SysWorkTime;
 import com.xunmei.common.core.domain.worktime.dto.WorkTimeDto;
-import com.xunmei.common.core.enums.OrgTypeEnum;
 import com.xunmei.common.core.enums.RetrievalTaskCycle;
 import com.xunmei.common.core.enums.edu.EduTrainingPlanCycleEnum;
 import com.xunmei.common.core.event.WorkTimeChangeEvent;
@@ -27,7 +29,6 @@ import com.xunmei.common.redis.utils.RedisUtils;
 import com.xunmei.common.security.utils.SecurityUtils;
 import com.xunmei.core.TaskCreatingServiceImplBase;
 import com.xunmei.core.access.domain.TMonitoringRetrievalPlan;
-import com.xunmei.core.access.domain.TMonitoringRetrievalPlanToExecOrg;
 import com.xunmei.core.access.mapper.CoreMonitoringTaskRegistrationMapper;
 import com.xunmei.core.access.mapper.TMonitoringRetrievalPlanToExecOrgMapper;
 import com.xunmei.core.access.service.ITMonitoringRetrievalPlanService;
@@ -84,7 +85,7 @@ public class CoreMonitoringRetrievalTaskBuilderServiceImpl extends ServiceImpl<C
      */
     @Override
     public void noCycleTask(List<TMonitoringRetrievalPlan> planList) {
-        createAndSaveTask(planList);
+        createAndSaveTask(planList, null, new ArrayList<>());
     }
 
     @Async
@@ -92,15 +93,15 @@ public class CoreMonitoringRetrievalTaskBuilderServiceImpl extends ServiceImpl<C
      * 无周期任务生成
      */
     @Override
-    public void noCycleTask(List<TMonitoringRetrievalPlan> planList,Long parentPlanId) {
+    public void noCycleTask(List<TMonitoringRetrievalPlan> planList, Long parentPlanId) {
         // 生成任务为异步方法,新增一个任务正在生成的标识,用于删除计划时的判断
-        String redisKey="Monitoring_Creating_Task" + parentPlanId;
+        String redisKey = "Monitoring_Creating_Task" + parentPlanId;
         RedisUtils.deleteObject(redisKey);
         Boolean hasKey = RedisUtils.hasKey(redisKey);
         if (!hasKey) {
-            RedisUtils.setCacheObject(redisKey, parentPlanId, Duration.ofMillis(1000 * 60*5));
+            RedisUtils.setCacheObject(redisKey, parentPlanId, Duration.ofMillis(1000 * 60 * 5));
         }
-        createAndSaveTask(planList);
+        createAndSaveTask(planList, null, new ArrayList<>());
         RedisUtils.deleteObject(redisKey);
     }
 
@@ -117,32 +118,35 @@ public class CoreMonitoringRetrievalTaskBuilderServiceImpl extends ServiceImpl<C
     }
 
 
-
-    private void createAndSaveTask(List<TMonitoringRetrievalPlan> planList)
-    {
-         List<CoreMonitoringRetrievalTask> allTask = createTask(planList, null);
-        this.saveBatch(allTask);
+    @Override
+    public void createAndSaveTask(List<TMonitoringRetrievalPlan> planList, LocalDate taskTime, List<Long> needBuildTaskOrgIdList) {
+        List<CoreMonitoringRetrievalTask> allTask = createTask(planList, taskTime, needBuildTaskOrgIdList);
+        if (ObjectUtil.isNotEmpty(allTask)){
+            this.saveBatch(allTask);
+        }
     }
 
-    private List<CoreMonitoringRetrievalTask> createTask(List<TMonitoringRetrievalPlan> planList, LocalDate taskTime)
-    {
+
+    private List<CoreMonitoringRetrievalTask> createTask(List<TMonitoringRetrievalPlan> planList, LocalDate taskTime, List<Long> needBuildTaskOrgIdList) {
         List<CoreMonitoringRetrievalTask> taskList = new ArrayList<>();
-        if(ObjectUtil.isNull(taskTime)){
+        if (ObjectUtil.isNull(taskTime)) {
             taskTime = planList.get(0).getStartTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
         }
-        LocalDate taskTime1=taskTime;
+        LocalDate taskTime1 = taskTime;
 
         for (TMonitoringRetrievalPlan plan : planList) {
 
-            List<Long> execOrgIds = tMonitoringRetrievalPlanToExecOrgMapper.selectByMap(MapUtil.of("plan_id", plan.getId())).stream().map(x->x.getOrgId()).collect(Collectors.toList());
-
+            List<Long> execOrgIds = tMonitoringRetrievalPlanToExecOrgMapper.selectByMap(MapUtil.of("plan_id", plan.getId())).stream().map(x -> x.getOrgId()).collect(Collectors.toList());
+            //运维接口传递此参数:needBuildTaskOrgIdList,说明指定了需要生成任务的机构信息
+            if (ObjectUtil.isNotEmpty(needBuildTaskOrgIdList)) {
+                execOrgIds = needBuildTaskOrgIdList;
+            }
             final List<SysOrg> execOrgList = getExecOrgList(execOrgIds, Integer.parseInt(plan.getOrgType()), plan.getOrgPath());
-
             //获取计划关联的机构
 //            List<SysOrg> listByType = orgList.stream().filter(r -> r.getId().equals(plan.getOrgId()) && r.getDeleted() == 0 && r.getIsLock().equals(0))
 //                    .collect(Collectors.toList());
             if (CollectionUtil.isNotEmpty(execOrgList)) {
-                execOrgList.stream().forEach(org->{
+                execOrgList.stream().forEach(org -> {
                     List<CoreMonitoringRetrievalTask> list = this.buildCoreMonitoringRetrievalTask(plan, taskTime1, org);
                     if (CollectionUtil.isNotEmpty(list)) {
                         taskList.addAll(list);
@@ -178,6 +182,7 @@ public class CoreMonitoringRetrievalTaskBuilderServiceImpl extends ServiceImpl<C
         }
         return listAll;
     }
+
     /**
      * 每天生成日任务 如果当天是周一还需生成周任务
      *
@@ -196,7 +201,7 @@ public class CoreMonitoringRetrievalTaskBuilderServiceImpl extends ServiceImpl<C
         //是周一生成周任务
         if (taskTime.getDayOfWeek() == DayOfWeek.MONDAY) {
             List<TMonitoringRetrievalPlan> buildTaskWeekPlanList = getBuildTaskPlanList(RetrievalTaskCycle.WEEKCYCLE.getCode());
-            List<CoreMonitoringRetrievalTask> listWeek =  createTask(buildTaskWeekPlanList,taskTime);
+            List<CoreMonitoringRetrievalTask> listWeek = createTask(buildTaskWeekPlanList, taskTime, new ArrayList<>());
 //            List<CoreMonitoringRetrievalTask> listWeek = this.buildCoreMonitoringRetrievalTask(RetrievalTaskCycle.WEEKCYCLE.getCode(), taskTime, orgList);
             if (CollectionUtil.isNotEmpty(listWeek)) {
                 list.addAll(listWeek);
@@ -205,7 +210,7 @@ public class CoreMonitoringRetrievalTaskBuilderServiceImpl extends ServiceImpl<C
         //生成每日任务
 //        List<CoreMonitoringRetrievalTask> listDay = this.buildCoreMonitoringRetrievalTask(RetrievalTaskCycle.DAYCYCLE.getCode(), taskTime, orgList);
         List<TMonitoringRetrievalPlan> buildTaskDayPlanList = getBuildTaskPlanList(RetrievalTaskCycle.DAYCYCLE.getCode());
-        List<CoreMonitoringRetrievalTask> listDay =  createTask(buildTaskDayPlanList,taskTime);
+        List<CoreMonitoringRetrievalTask> listDay = createTask(buildTaskDayPlanList, taskTime, new ArrayList<>());
         if (CollectionUtil.isNotEmpty(listDay)) {
             list.addAll(listDay);
         }
@@ -238,21 +243,21 @@ public class CoreMonitoringRetrievalTaskBuilderServiceImpl extends ServiceImpl<C
             //季度任务
 //            List<CoreMonitoringRetrievalTask> listQuarter = this.buildCoreMonitoringRetrievalTask(RetrievalTaskCycle.QUARTERCYCLE.getCode(), taskTime, orgList);
             List<TMonitoringRetrievalPlan> buildTaskQuarterPlanList = getBuildTaskPlanList(RetrievalTaskCycle.QUARTERCYCLE.getCode());
-            List<CoreMonitoringRetrievalTask> listQuarter =  createTask(buildTaskQuarterPlanList,taskTime);
+            List<CoreMonitoringRetrievalTask> listQuarter = createTask(buildTaskQuarterPlanList, taskTime, new ArrayList<>());
             if (CollectionUtil.isNotEmpty(listQuarter)) {
                 list.addAll(listQuarter);
             }
             //半年任务
 //            List<CoreMonitoringRetrievalTask> listHalfYear = this.buildCoreMonitoringRetrievalTask(RetrievalTaskCycle.HALFYEARCYCLE.getCode(), taskTime, orgList);
             List<TMonitoringRetrievalPlan> buildTaskHalfYearPlanList = getBuildTaskPlanList(RetrievalTaskCycle.HALFYEARCYCLE.getCode());
-            List<CoreMonitoringRetrievalTask> listHalfYear =  createTask(buildTaskHalfYearPlanList,taskTime);
+            List<CoreMonitoringRetrievalTask> listHalfYear = createTask(buildTaskHalfYearPlanList, taskTime, new ArrayList<>());
             if (CollectionUtil.isNotEmpty(listHalfYear)) {
                 list.addAll(listHalfYear);
             }
             //年任务
 //            List<CoreMonitoringRetrievalTask> listYear = this.buildCoreMonitoringRetrievalTask(RetrievalTaskCycle.YEARCYCLE.getCode(), taskTime, orgList);
             List<TMonitoringRetrievalPlan> buildTaskYearPlanList = getBuildTaskPlanList(RetrievalTaskCycle.YEARCYCLE.getCode());
-            List<CoreMonitoringRetrievalTask> listYear =  createTask(buildTaskYearPlanList,taskTime);
+            List<CoreMonitoringRetrievalTask> listYear = createTask(buildTaskYearPlanList, taskTime, new ArrayList<>());
             if (CollectionUtil.isNotEmpty(listYear)) {
                 list.addAll(listYear);
             }
@@ -262,7 +267,7 @@ public class CoreMonitoringRetrievalTaskBuilderServiceImpl extends ServiceImpl<C
             //季度任务
 //            List<CoreMonitoringRetrievalTask> listQuarter = this.buildCoreMonitoringRetrievalTask(RetrievalTaskCycle.QUARTERCYCLE.getCode(), taskTime, orgList);
             List<TMonitoringRetrievalPlan> buildTaskQuarterPlanList = getBuildTaskPlanList(RetrievalTaskCycle.QUARTERCYCLE.getCode());
-            List<CoreMonitoringRetrievalTask> listQuarter =  createTask(buildTaskQuarterPlanList,taskTime);
+            List<CoreMonitoringRetrievalTask> listQuarter = createTask(buildTaskQuarterPlanList, taskTime, new ArrayList<>());
             if (CollectionUtil.isNotEmpty(listQuarter)) {
                 list.addAll(listQuarter);
             }
@@ -272,14 +277,14 @@ public class CoreMonitoringRetrievalTaskBuilderServiceImpl extends ServiceImpl<C
             //季度任务
 //            List<CoreMonitoringRetrievalTask> listQuarter = this.buildCoreMonitoringRetrievalTask(RetrievalTaskCycle.QUARTERCYCLE.getCode(), taskTime, orgList);
             List<TMonitoringRetrievalPlan> buildTaskQuarterPlanList = getBuildTaskPlanList(RetrievalTaskCycle.QUARTERCYCLE.getCode());
-            List<CoreMonitoringRetrievalTask> listQuarter =  createTask(buildTaskQuarterPlanList,taskTime);
+            List<CoreMonitoringRetrievalTask> listQuarter = createTask(buildTaskQuarterPlanList, taskTime, new ArrayList<>());
             if (CollectionUtil.isNotEmpty(listQuarter)) {
                 list.addAll(listQuarter);
             }
             //半年任务
 //            List<CoreMonitoringRetrievalTask> listHalfYear = this.buildCoreMonitoringRetrievalTask(RetrievalTaskCycle.HALFYEARCYCLE.getCode(), taskTime, orgList);
             List<TMonitoringRetrievalPlan> buildTaskHalfYearPlanList = getBuildTaskPlanList(RetrievalTaskCycle.HALFYEARCYCLE.getCode());
-            List<CoreMonitoringRetrievalTask> listHalfYear =  createTask(buildTaskHalfYearPlanList,taskTime);
+            List<CoreMonitoringRetrievalTask> listHalfYear = createTask(buildTaskHalfYearPlanList, taskTime, new ArrayList<>());
             if (CollectionUtil.isNotEmpty(listHalfYear)) {
                 list.addAll(listHalfYear);
             }
@@ -287,7 +292,7 @@ public class CoreMonitoringRetrievalTaskBuilderServiceImpl extends ServiceImpl<C
         //所有日期都要生成月任务
 //        List<CoreMonitoringRetrievalTask> listMonth = this.buildCoreMonitoringRetrievalTask(RetrievalTaskCycle.MONTHCYCLE.getCode(), taskTime, orgList);
         List<TMonitoringRetrievalPlan> buildTaskMonthPlanList = getBuildTaskPlanList(RetrievalTaskCycle.HALFYEARCYCLE.getCode());
-        List<CoreMonitoringRetrievalTask> listMonth =  createTask(buildTaskMonthPlanList,taskTime);
+        List<CoreMonitoringRetrievalTask> listMonth = createTask(buildTaskMonthPlanList, taskTime, new ArrayList<>());
         if (CollectionUtil.isNotEmpty(listMonth)) {
             list.addAll(listMonth);
         }
@@ -403,7 +408,7 @@ public class CoreMonitoringRetrievalTaskBuilderServiceImpl extends ServiceImpl<C
         coreMonitoringRetrievalTaskMapper.updateDeleteTaskByPlanId(planId, isDeleted);
     }
 
-    private List<TMonitoringRetrievalPlan> getBuildTaskPlanList(Integer cycle){
+    private List<TMonitoringRetrievalPlan> getBuildTaskPlanList(Integer cycle) {
         //获取计划
         QueryWrapper<TMonitoringRetrievalPlan> queryWrapper = new QueryWrapper<>();
         queryWrapper.lambda().eq(TMonitoringRetrievalPlan::getPlanCycle, cycle);
@@ -436,7 +441,7 @@ public class CoreMonitoringRetrievalTaskBuilderServiceImpl extends ServiceImpl<C
             sysOrg.setType(Integer.valueOf(p.getOrgType()));
             List<SysOrg> sysOrgs = remoteOrgService.listByParentIdAndType(sysOrg, SecurityConstants.INNER);*/
             List<SysOrg> sysOrgs = orgList.stream().
-                    filter(s -> (ObjectUtil.equal(s.getIsLock(),0)  && ObjectUtil.equal(s.getDeleted(),0) && s.getPath() != null && s.getPath().contains(p.getOrgPath())) && (s.getType() != null && s.getType().toString().equals(p.getOrgType())))
+                    filter(s -> (ObjectUtil.equal(s.getIsLock(), 0) && ObjectUtil.equal(s.getDeleted(), 0) && s.getPath() != null && s.getPath().contains(p.getOrgPath())) && (s.getType() != null && s.getType().toString().equals(p.getOrgType())))
                     .collect(Collectors.toList());
             for (SysOrg s : sysOrgs) {
                 TMonitoringRetrievalPlan plan = new TMonitoringRetrievalPlan();
@@ -525,9 +530,28 @@ public class CoreMonitoringRetrievalTaskBuilderServiceImpl extends ServiceImpl<C
         for (Map.Entry<Short, DateRange> entry : dateRanges.entrySet()) {
             Integer key = entry.getKey().intValue();
             DateRange dateRange1 = entry.getValue();
+            LambdaQueryWrapper<CoreMonitoringRetrievalTask> queryWrapper = new LambdaQueryWrapper<>();
+            queryWrapper
+                    .eq(CoreMonitoringRetrievalTask::getPlanId, plan.getId())
+                    .eq(CoreMonitoringRetrievalTask::getOrgId, sysOrg.getId())
+                    .ge(CoreMonitoringRetrievalTask::getPlanStartTime, dateRange.getStartTime())
+                    .le(CoreMonitoringRetrievalTask::getPlanEndTime, dateRange.getEndTime());
+            List<CoreMonitoringRetrievalTask> exitTaskList = this.list(queryWrapper);
             CoreMonitoringRetrievalTask task = this.buildCoreMonitoringRetrievalTask(batchNum, key, plan, sysOrg,
                     dateRange1, ymd, dateRanges.size());
+            Optional<CoreMonitoringRetrievalTask> optional = exitTaskList.stream()
+                    .filter(t -> t.getPlanStartTime().equals(dateRange1.getStartTime()))
+                    .filter(t -> t.getPlanEndTime().equals(dateRange1.getEndTime()))
+                    .filter(t -> t.getOrgId().equals(sysOrg.getId()))
+                    .filter(t -> t.getPlanId().equals(plan.getId()))
+                    .findAny();
+            if (optional.isPresent()){
+                //说明已经存在相同的任务了,
+               continue;
+            }
             taskList.add(task);
+
+
         }
         return taskList;
 
@@ -582,7 +606,7 @@ public class CoreMonitoringRetrievalTaskBuilderServiceImpl extends ServiceImpl<C
         task.setYmdDay(ymd.getDay());
         task.setRoleId(plan.getRoleId());
         task.setStatus("0");
-        task.setCreateTime(DateTime.now());
+       // task.setCreateTime(DateTime.now());
         task.setIsDeleted(0);
         return task;
     }

+ 11 - 12
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/safetyCheck/job/SafetyCheckJobBusiness.java

@@ -3,7 +3,6 @@ package com.xunmei.core.safetyCheck.job;
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
-import cn.hutool.core.util.NumberUtil;
 import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -12,16 +11,13 @@ import com.xunmei.common.core.constant.SecurityConstants;
 import com.xunmei.common.core.domain.DateRange;
 import com.xunmei.common.core.domain.worktime.domain.SysWorkTime;
 import com.xunmei.common.core.enums.CycleCommonEnum;
-import com.xunmei.common.core.enums.OrgTypeEnum;
 import com.xunmei.common.core.enums.PlanStatus;
 import com.xunmei.common.core.utils.DateHelper;
 import com.xunmei.common.core.utils.DateUtils;
 import com.xunmei.common.core.utils.IDHelper;
 import com.xunmei.common.redis.utils.RedisUtils;
 import com.xunmei.core.TaskCreatingServiceImplBase;
-import com.xunmei.core.resumption.domain.Resumption;
 import com.xunmei.core.safetyCheck.domain.*;
-import com.xunmei.core.safetyCheck.domain.CoreSafecheckPlan;
 import com.xunmei.core.safetyCheck.dto.SafetyTaskBuildDto;
 import com.xunmei.core.safetyCheck.mapper.*;
 import com.xunmei.core.safetyCheck.service.ICoreSafetyTaskService;
@@ -37,7 +33,6 @@ import org.springframework.stereotype.Component;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
-import java.lang.reflect.Array;
 import java.text.SimpleDateFormat;
 import java.time.Duration;
 import java.util.*;
@@ -101,7 +96,7 @@ public class SafetyCheckJobBusiness extends TaskCreatingServiceImplBase<CoreSafe
      * @throws Exception
      */
     public void createTaskForCycle(DateTime dateTime, Date start, Date end, CoreSafecheckPlan plan, Boolean isNeedSendTodo, Integer sourceType) throws Exception {
-        List<PlanTaskBuildVo> planTask = createPlanTask(plan);
+        List<PlanTaskBuildVo> planTask = createPlanTask(plan,new ArrayList<>());
         //生成具体任务
         buildTask(dateTime, planTask, start, end, isNeedSendTodo, sourceType);
     }
@@ -164,7 +159,7 @@ public class SafetyCheckJobBusiness extends TaskCreatingServiceImplBase<CoreSafe
 
         List<PlanTaskBuildVo> tasks = new ArrayList<>();
         for (CoreSafecheckPlan plan : plans) {
-            List<PlanTaskBuildVo> planTask = createPlanTask(plan);
+            List<PlanTaskBuildVo> planTask = createPlanTask(plan,new ArrayList<>());
             tasks.addAll(planTask);
         }
 
@@ -180,7 +175,7 @@ public class SafetyCheckJobBusiness extends TaskCreatingServiceImplBase<CoreSafe
      */
     @Async
     public void createTaskByPlans(List<CoreSafecheckPlan> plans) {
-        createTask(plans);
+        createTask(plans,null);
     }
 
     @Async
@@ -191,11 +186,11 @@ public class SafetyCheckJobBusiness extends TaskCreatingServiceImplBase<CoreSafe
         if (!hasKey) {
             RedisUtils.setCacheObject(redisKey, parentPlanId, Duration.ofMillis(1000 * 60*5));
         }
-        createTask(plans);
+        createTask(plans,null);
         RedisUtils.deleteObject(redisKey);
     }
 
-    private void createTask(List<CoreSafecheckPlan> plans)
+    public void createTask(List<CoreSafecheckPlan> plans,List<Long> needBuildTaskOrgIds)
     {
         try {
             if (plans != null && plans.size() > 0) {
@@ -212,7 +207,7 @@ public class SafetyCheckJobBusiness extends TaskCreatingServiceImplBase<CoreSafe
                     if (ObjectUtil.notEqual(plan.getPlanStatus(), PlanStatus.USING.getCode())) {
                         continue;
                     }
-                    List<PlanTaskBuildVo> planTask = createPlanTask(plan);
+                    List<PlanTaskBuildVo> planTask = createPlanTask(plan,needBuildTaskOrgIds);
                     tasks.addAll(planTask);
                 }
 
@@ -230,7 +225,7 @@ public class SafetyCheckJobBusiness extends TaskCreatingServiceImplBase<CoreSafe
      *
      * @param plan
      */
-    private List<PlanTaskBuildVo> createPlanTask(CoreSafecheckPlan plan) {
+    private List<PlanTaskBuildVo> createPlanTask(CoreSafecheckPlan plan,List<Long> needBuildTaskOrgIds) {
 
         List<PlanTaskBuildVo> list = new ArrayList<>();
         Integer execOrgType = Math.toIntExact(plan.getExecOrgType());
@@ -295,6 +290,10 @@ public class SafetyCheckJobBusiness extends TaskCreatingServiceImplBase<CoreSafe
             }
 //            checkOrgs = checkOrgs.stream().filter(o -> ObjectUtil.equal(o.getIsLock(), false)).collect(Collectors.toList());
             checkOrgs = checkOrgs.stream().filter(o -> o.getIsLock() < 1).collect(Collectors.toList());
+            if (ObjectUtil.isNotEmpty(needBuildTaskOrgIds)) {
+                //此处是运维接口需要指定生成某个机构的情况下需要过滤
+                checkOrgs=checkOrgs.stream().filter(o->needBuildTaskOrgIds.contains(o.getId())).collect(Collectors.toList());
+            }
             //构建数据
             List<PlanTaskBuildVo> bs = getBuild(plan, org, checkOrgs, roles);
             list.addAll(bs);

+ 166 - 6
soc-modules/soc-modules-core/src/main/java/com/xunmei/core/safetyCheck/service/impl/CoreSafecheckPlanServiceImpl.java

@@ -11,6 +11,9 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.IdWorker;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.xunmei.common.core.constant.CacheConstants;
 import com.xunmei.common.core.constant.DictConstants;
 import com.xunmei.common.core.constant.ErrorMsgConstants;
 import com.xunmei.common.core.constant.SecurityConstants;
@@ -19,14 +22,19 @@ import com.xunmei.common.core.domain.registerbook.domain.CoreRegisterBookPdf;
 import com.xunmei.common.core.enums.OrgTypeEnum;
 import com.xunmei.common.core.enums.PlanStatus;
 import com.xunmei.common.core.enums.RegisterBookType;
+import com.xunmei.common.core.enums.drill.DrillPlanStatus;
 import com.xunmei.common.core.exception.ServiceException;
 import com.xunmei.common.core.exception.SystemException;
+import com.xunmei.common.core.thread.ThreadPoolConfig;
+import com.xunmei.common.core.util.BeanHelper;
 import com.xunmei.common.core.utils.DateHelper;
 import com.xunmei.common.core.utils.DateUtils;
 import com.xunmei.common.core.web.page.TableDataInfo;
 import com.xunmei.common.redis.utils.RedisUtils;
 import com.xunmei.common.security.utils.DictUtils;
 import com.xunmei.common.security.utils.SecurityUtils;
+import com.xunmei.core.compense.dto.CompensateDto;
+import com.xunmei.core.compense.interfaces.CompensateService;
 import com.xunmei.core.question.QuestionSrcType;
 import com.xunmei.core.question.service.IQuestionService;
 import com.xunmei.core.registerbook.service.ICoreRegisterBookPdfService;
@@ -46,12 +54,16 @@ import com.xunmei.system.api.RemoteOrgService;
 import com.xunmei.system.api.domain.CheckDataVo;
 import com.xunmei.system.api.domain.SafeCheckTaskRegisterBookVo;
 import com.xunmei.system.api.domain.SysOrg;
+import com.xunmei.common.core.enums.BusinessPlanType;
 import com.xunmei.system.api.function.RemoteCallHandlerExecutor;
+import com.xunmei.system.api.vo.SysOrgVO;
 import io.netty.util.internal.StringUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Propagation;
 import org.springframework.transaction.annotation.Transactional;
@@ -59,12 +71,12 @@ import org.springframework.transaction.annotation.Transactional;
 import java.io.File;
 import java.text.MessageFormat;
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
+import java.util.concurrent.CompletableFuture;
 import java.util.stream.Collectors;
 
+import static java.util.stream.Collectors.toList;
+
 /**
  * 常规安全检查计划Service业务层处理
  *
@@ -72,7 +84,7 @@ import java.util.stream.Collectors;
  * @date 2023-09-12
  */
 @Service
-public class CoreSafecheckPlanServiceImpl extends ServiceImpl<CoreSafecheckPlanMapper, CoreSafecheckPlan> implements ICoreSafecheckPlanService {
+public class CoreSafecheckPlanServiceImpl extends ServiceImpl<CoreSafecheckPlanMapper, CoreSafecheckPlan> implements ICoreSafecheckPlanService, CompensateService {
     @Autowired
     private CoreSafecheckPlanMapper coreSafecheckPlanMapper;
     @Autowired
@@ -105,6 +117,10 @@ public class CoreSafecheckPlanServiceImpl extends ServiceImpl<CoreSafecheckPlanM
     @Autowired
     private CoreSafecheckPlanToCheckOrgTypeMapper coreSafecheckPlanToCheckOrgTypeMapper;
 
+    @Autowired
+    @Qualifier(ThreadPoolConfig.SOC_EXECUTOR)
+    private ThreadPoolTaskExecutor threadPoolTaskExecutor;
+
     @Override
     public TableDataInfo<CoreSafecheckPlan> selectPage(CoreSafecheckPlan coreSafecheckPlan) {
         //未删除
@@ -1115,7 +1131,7 @@ public class CoreSafecheckPlanServiceImpl extends ServiceImpl<CoreSafecheckPlanM
             throw new ServiceException("计划不存在");
         }
 
-        LambdaUpdateWrapper<CoreSafecheckPlan> wrapper = new LambdaUpdateWrapper();
+        LambdaUpdateWrapper<CoreSafecheckPlan> wrapper = new LambdaUpdateWrapper<>();
         wrapper.eq(CoreSafecheckPlan::getId, planId)
                 .set(CoreSafecheckPlan::getTaskHasCompleted, state);
 
@@ -1124,4 +1140,148 @@ public class CoreSafecheckPlanServiceImpl extends ServiceImpl<CoreSafecheckPlanM
             baseMapper.updateParentPlanCompletedState(plan.getParentId());
         }
     }
+
+    @Override
+    public BusinessPlanType getBusinessPlanType() {
+        return BusinessPlanType.SAFETY_CHECK;
+    }
+
+    @Override
+    public void compensate(CompensateDto compensateDto) {
+
+        CoreSafecheckPlan safeCheckPlan = getById(compensateDto.getPlanId());
+
+        if (ObjectUtil.isNull(safeCheckPlan)) {
+            throw new ServiceException("计划不存在");
+        }
+
+        if (ObjectUtil.notEqual(safeCheckPlan.getPlanStatus(), PlanStatus.USING.getCode())) {
+            throw new ServiceException("计划尚未下发或已停用");
+        }
+
+        if (ObjectUtil.equal(safeCheckPlan.getIsDeleted(), "1")) {
+            throw new ServiceException("计划状态异常");
+        }
+
+        List<SysOrgVO> orgCacheList = RedisUtils.getCacheList(CacheConstants.ORG_CACHE_LIST_KEY);
+        //推断计划 创建任务
+        deducePlanAndBuildTask(safeCheckPlan, compensateDto.getOrgIdList(), orgCacheList);
+
+    }
+
+
+    private static final Set<OrgTypeEnum> INVALID_ORG_TYPES = Sets.newHashSet(OrgTypeEnum.SHEGN_LIAN_SHE, OrgTypeEnum.BAN_SHI_CHU, OrgTypeEnum.DIQU_HANG_SHE);
+
+    private void deducePlanAndBuildTask(CoreSafecheckPlan safeCheckPlan, List<Long> orgIdList, List<SysOrgVO> orgCacheList) {
+        List<SysOrgVO> orgList = orgCacheList.stream().filter(org -> orgIdList.contains(org.getId())).collect(toList());
+        if (orgList.isEmpty()) {
+            throw new ServiceException("未查询到orgIdList中指定的机构信息");
+        }
+        List<Long> idList = orgList.stream().map(SysOrgVO::getId).collect(toList());
+        List<Integer> typeList = orgList.stream().map(SysOrgVO::getType).distinct().collect(toList());
+        if (typeList.size() > 1) {
+            throw new ServiceException("orgIdList中指定的机构信息存在多种机构类型");
+        }
+
+        OrgTypeEnum orgTypeEnum = OrgTypeEnum.getOrgTypeEnum(typeList.get(0));
+
+        // 省联社创建的计划
+        if (checkIsParentPlan(safeCheckPlan.getId())) {
+            List<CoreSafecheckPlan> allHsPlanList = getHsPlanList(safeCheckPlan);
+            if (ObjectUtil.isEmpty(allHsPlanList)) {
+                return;
+            }
+
+            Map<String, Object> map = getHsOrg(orgCacheList, orgList, orgTypeEnum);
+            List<Long> hsPlanIdList = allHsPlanList.stream().map(CoreSafecheckPlan::getId).collect(toList());
+            List<Long> hsOrgIdList = ((List<SysOrgVO>) map.get("list")).stream().map(SysOrgVO::getId).collect(toList());
+            if (ObjectUtil.hasEmpty(hsPlanIdList, hsOrgIdList)) {
+                return;
+            }
+            List<CoreSafecheckPlan> reallyPlanList = findReallyPlanIdList(hsPlanIdList, hsOrgIdList);
+            boolean underHsOrgType = (boolean) map.get("underHsOrgType");
+            create(reallyPlanList, underHsOrgType ? idList : null);
+            return;
+        }
+        // 行社自建计划
+        if (INVALID_ORG_TYPES.contains(orgTypeEnum)) {
+            throw new ServiceException("orgIdList中传递机构信息错误!与计划信息不匹配");
+        }
+
+        List<CoreSafecheckPlan> plans = Lists.newArrayList(safeCheckPlan);
+        if (OrgTypeEnum.HANG_SHE.equals(orgTypeEnum)) {
+            create(plans, null);
+        } else {
+            //其实这里如果真是传入了行社以下的机构,那么大概率这里的reallyPlanIdList 计划id也只会有一个元素
+            create(plans, idList);
+        }
+    }
+
+    private void create(List<CoreSafecheckPlan> planList, List<Long> idList) {
+        run(() -> safetyCheckJobBusiness.createTask(planList, idList), threadPoolTaskExecutor);
+    }
+
+    private List<CoreSafecheckPlan> findReallyPlanIdList(List<Long> planIdList, List<Long> orgIdList) {
+
+        LambdaQueryWrapper<CoreSafecheckPlan> wrapper = new LambdaQueryWrapper<>();
+        wrapper.in(CoreSafecheckPlan::getId, planIdList);
+        wrapper.in(CoreSafecheckPlan::getPlanOfOrgId, orgIdList);
+        return baseMapper.selectList(wrapper);
+    }
+
+    private boolean checkIsParentPlan(Long planId) {
+        LambdaQueryWrapper<CoreSafecheckPlan> countWrapper = new LambdaQueryWrapper<>();
+        countWrapper.eq(CoreSafecheckPlan::getParentId, planId);
+        Long l = baseMapper.selectCount(countWrapper);
+        return ObjectUtil.isNotNull(l) && l.compareTo(0L) > 0;
+    }
+
+
+    private List<CoreSafecheckPlan> getHsPlanList(CoreSafecheckPlan drillPlan) {
+        LambdaQueryWrapper<CoreSafecheckPlan> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(CoreSafecheckPlan::getPlanStatus, DrillPlanStatus.USING.getCode());
+        wrapper.eq(CoreSafecheckPlan::getIsDeleted, "0");
+        wrapper.eq(CoreSafecheckPlan::getParentId, drillPlan.getId());
+        return baseMapper.selectList(wrapper);
+    }
+
+    private Map<String, Object> getHsOrg(List<SysOrgVO> orgCacheList, List<SysOrgVO> needBuildTaskOrgList, OrgTypeEnum needBuildTaskOrgTypeEnum) {
+        List<SysOrgVO> list = new ArrayList<>();
+        boolean underHsOrgType = false;
+        switch (needBuildTaskOrgTypeEnum) {
+            //如果是省联社/办事处/地区行社 那么找到下级的行社
+            case SHEGN_LIAN_SHE:
+            case BAN_SHI_CHU:
+            case DIQU_HANG_SHE:
+                for (SysOrgVO sysOrgVO : needBuildTaskOrgList) {
+                    String path = sysOrgVO.getPath();
+                    List<SysOrgVO> collect = orgCacheList
+                            .stream()
+                            .filter(org -> ObjectUtil.isAllNotEmpty(org.getPath(), org.getType()))
+                            .filter(org -> org.getPath().contains(path))
+                            .filter(org -> org.getType().equals(OrgTypeEnum.HANG_SHE.getCode()))
+                            .collect(toList());
+                    list.addAll(collect);
+                }
+                break;
+            case HANG_SHE: //如果传进来的就是行社 那么直接返回
+                list = needBuildTaskOrgList;
+                break;
+            default:    //如果是行社以下机构类型,那么找到上级的行社机构返回
+                List<Long> ids = needBuildTaskOrgList.stream().map(SysOrgVO::getId).collect(toList());
+                List<SysOrg> sysOrgs = orgService.selectParentHs(ids, SecurityConstants.INNER);
+                list = BeanHelper.copyProperties(sysOrgs, SysOrgVO.class);
+                underHsOrgType = true;
+        }
+
+        Map<String, Object> map = new HashMap<>();
+        map.put("list", list);
+        map.put("underHsOrgType", underHsOrgType);
+        return map;
+    }
+
+    @Override
+    public void run(Runnable runnable, ThreadPoolTaskExecutor threadPoolTaskExecutor) {
+        CompletableFuture.runAsync(runnable, threadPoolTaskExecutor);
+    }
 }

+ 38 - 0
soc-modules/soc-modules-core/src/main/resources/mapper/reminder/CoreReminderConfigurationMapper.xml

@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.xunmei.core.reminder.mapper.CoreReminderConfigurationMapper">
+
+    <select id="selectPageData" resultType="com.xunmei.common.core.domain.reminder.vo.ReminderConfigPageVo">
+        select c.config_id,
+        c.reminder_type,
+        c.send_module,
+        c.advance_notice_period,
+        c.overdue_notice_period,
+        c.enabled,
+        group_concat(cr.target_role_name) as roleName,
+        group_concat(o.target_org_name) as orgName
+        from core_reminder_configuration c
+        inner join core_reminder_configuration_role cr
+            on c.config_id = cr.config_id
+        inner join core_reminder_configuration_org o
+            on o.config_id = c.config_id
+
+        <where>
+            <if test="req.enabled != null">
+                and c.enabled = #{req.enabled}
+            </if>
+            <if test="req.reminderType != null">
+                and c.reminder_type = #{req.reminderType}
+            </if>
+            <if test="req.sendModule != null">
+                and c.send_module = #{req.sendModule}
+            </if>
+            <if test="req.roleId != null">
+                and cr.role_id = #{req.roleId}
+            </if>
+            <if test="req.checkSub ==true">
+                and o.target_org_path like concat(#{req.orgPath},'%')
+            </if>
+        </where>
+    </select>
+</mapper>

+ 14 - 0
soc-modules/soc-modules-core/src/main/resources/mapper/reminder/CoreReminderConfigurationOrgMapper.xml

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.xunmei.core.reminder.mapper.CoreReminderConfigurationOrgMapper">
+
+    <delete id="deleteByConfigId">
+        delete from core_reminder_configuration_org where config_id = #{configId}
+    </delete>
+
+    <select id="selectByConfigId" resultType="com.xunmei.common.core.domain.reminder.domain.CoreReminderConfigurationOrg">
+        select *
+        from core_reminder_configuration_org
+        where config_id = #{configId}
+    </select>
+</mapper>

+ 15 - 0
soc-modules/soc-modules-core/src/main/resources/mapper/reminder/CoreReminderConfigurationRoleMapper.xml

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.xunmei.core.reminder.mapper.CoreReminderConfigurationRoleMapper">
+
+    <delete id="deleteByConfigId">
+        delete from core_reminder_configuration_role where config_id = #{configId}
+    </delete>
+
+    <select id="selectByConfigId"
+            resultType="com.xunmei.common.core.domain.reminder.domain.CoreReminderConfigurationRole">
+        select *
+        from core_reminder_configuration_role
+        where config_id
+    </select>
+</mapper>

+ 5 - 0
soc-modules/soc-modules-core/src/main/resources/mapper/reminder/CoreReminderLogMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.xunmei.core.reminder.mapper.CoreReminderLogMapper">
+
+</mapper>

+ 5 - 0
soc-modules/soc-modules-core/src/main/resources/mapper/reminder/CoreReminderScheduleMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.xunmei.core.reminder.mapper.CoreReminderScheduleMapper">
+
+</mapper>

+ 5 - 0
soc-modules/soc-modules-core/src/main/resources/mapper/reminder/CoreReminderTemplateMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.xunmei.core.reminder.mapper.CoreReminderTemplateMapper">
+
+</mapper>

+ 3 - 0
soc-modules/soc-modules-core/src/main/resources/mapper/resumption/AppPlanToExecOrgMapper.xml

@@ -9,4 +9,7 @@
         plan_id,org_id
     </sql>
 
+    <select id="selectByPlanId" resultType="com.xunmei.core.resumption.domain.AppPlanToExecOrg">
+        select * from core_resumption_plan_to_exec_org where plan_id = #{planId}
+    </select>
 </mapper>

+ 14 - 2
soc-modules/soc-modules-file/src/main/java/com/xunmei/file/controller/SysFileController.java

@@ -120,7 +120,19 @@ public class SysFileController {
     public void downloadFile(HttpServletResponse response, @RequestBody SysFile sysFile) {
         try {
             String filePath = DesUtil.decode(sysFile.getCode(), secretKey);
-            sysFileService.downloadFile(response, filePath);
+            sysFileService.downloadFile(response, filePath,null);
+        } catch (Exception e) {
+            log.error("下载文件失败", e);
+            throw new RuntimeException(e);
+        }
+    }
+
+    @PostMapping("/downloadFile/realName")
+    public void downloadFileRealName(HttpServletResponse response, @RequestBody SysFile sysFile) {
+        try {
+            //String filePath = DesUtil.decode(sysFile.getCode(), secretKey);
+            String filePath = sysFile.getUrl().replace(prefix,"");
+            sysFileService.downloadFile(response, filePath,sysFile.getRealName());
         } catch (Exception e) {
             log.error("下载文件失败", e);
             throw new RuntimeException(e);
@@ -137,7 +149,7 @@ public class SysFileController {
     public void getFile(HttpServletResponse response, @PathVariable String code) {
         try {
             String filePath = DesUtil.decode(code, secretKey);
-            sysFileService.downloadFile(response, filePath);
+            sysFileService.downloadFile(response, filePath,null);
         } catch (Exception e) {
             log.error("下载文件失败", e);
             throw new RuntimeException(e);

+ 1 - 1
soc-modules/soc-modules-file/src/main/java/com/xunmei/file/service/ISysFileService.java

@@ -46,7 +46,7 @@ public interface ISysFileService
      * @return
      * @throws Exception
      */
-    void downloadFile(HttpServletResponse response, String filePath) throws Exception;
+    void downloadFile(HttpServletResponse response, String filePath, String realName) throws Exception;
 
     String generateEduTrainingPdf(Map<String, Object> data) throws Exception;
     String generateResumptionPdf(Map<String, Object> data) throws Exception;

+ 4 - 1
soc-modules/soc-modules-file/src/main/java/com/xunmei/file/service/LocalSysFileServiceImpl.java

@@ -167,7 +167,7 @@ public class LocalSysFileServiceImpl implements ISysFileService {
     }
 
     @Override
-    public void downloadFile(HttpServletResponse response, String filePath) {
+    public void downloadFile(HttpServletResponse response, String filePath,String realName) {
         ByteArrayOutputStream out = null;
         try {
             filePath = localFilePath + filePath;
@@ -175,6 +175,9 @@ public class LocalSysFileServiceImpl implements ISysFileService {
             out = FileDownUtils.downloadFile(filePath);
             String fileSuffix = FileDownUtils.getFileSuffix(filePath);
             String formFileName = UUID.randomUUID().toString() + fileSuffix;
+            if (StringUtils.isNotEmpty(realName)){
+                formFileName = realName;
+            }
             String userAgent = request.getHeader("User-Agent");
 
             // 针对IE或者以IE为内核的浏览器:

+ 4 - 4
soc-modules/soc-modules-gen/src/main/java/com/xunmei/gen/util/CodeGenerators.java

@@ -29,8 +29,8 @@ public class CodeGenerators {
         throw new MybatisPlusException("请输入正确的" + tip + "!");
     }*/
 
-    public static final String moduleName="com.xunmei.mediator";
-    public static final String tableNames="iot_sensor_data,iot_sensor_data_log";
+    public static final String moduleName="com.xunmei.core.reminder";
+    public static final String tableNames="core_reminder_configuration_org";
 
     public static void main(String[] args) {
         // 代码生成器
@@ -38,10 +38,10 @@ public class CodeGenerators {
         // 全局配置
         GlobalConfig gc = new GlobalConfig();
         // System.getProperty("user.dir");
-        String projectPath = "D:\\test";
+        String projectPath = "/Users/jingyuanchao/Downloads";
         //生成文件输出目录
         gc.setOutputDir(projectPath + "/java");
-        gc.setAuthor("oygj");
+        gc.setAuthor("jingYuanChao");
         //生成代码后,是否打开文件夹
         gc.setOpen(true);
         // 实体属性 Swagger2 注解

+ 6 - 0
soc-modules/soc-modules-system/pom.xml

@@ -52,6 +52,12 @@
             <artifactId>mysql-connector-java</artifactId>
         </dependency>
 
+        <!-- 语义化规范2.0版本对比 -->
+        <dependency>
+            <groupId>com.github.zafarkhaja</groupId>
+            <artifactId>java-semver</artifactId>
+        </dependency>
+
         <!--soc datascope 数据权限-->
         <dependency>
             <groupId>com.xunmei</groupId>

+ 67 - 0
soc-modules/soc-modules-system/src/main/java/com/xunmei/system/controller/SysVersionController.java

@@ -0,0 +1,67 @@
+package com.xunmei.system.controller;
+
+import com.xunmei.common.core.web.controller.BaseController;
+import com.xunmei.common.core.web.domain.AjaxResult;
+import com.xunmei.common.core.web.page.TableDataInfo;
+import com.xunmei.common.security.annotation.RequiresPermissions;
+import com.xunmei.common.security.utils.SecurityUtils;
+import com.xunmei.system.api.domain.SysVersion;
+import com.xunmei.system.api.model.LoginUser;
+import com.xunmei.system.dto.SysCheckUpdateDto;
+import com.xunmei.system.service.ISysVersionService;
+import io.swagger.annotations.Api;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+
+@Api(tags = {"SysVersion" })
+@RestController
+@RequestMapping("/version")
+public class SysVersionController extends BaseController {
+
+    @Resource
+    private ISysVersionService versionService;
+
+    @RequiresPermissions("system:version:list")
+    @GetMapping("/list")
+    public TableDataInfo<SysVersion> list(SysVersion version) {
+        return versionService.selectPage(version);
+    }
+
+    @RequiresPermissions("system:version:add")
+    @PostMapping("/add")
+    public AjaxResult add(@RequestBody SysVersion version) {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        version.setCreateBy(loginUser.getName());
+        return  versionService.insertVersion(version);
+    }
+
+    @RequiresPermissions("system:version:edit")
+    @PostMapping("/edit")
+    public AjaxResult edit(@RequestBody SysVersion version) {
+        LoginUser loginUser = SecurityUtils.getLoginUser();
+        version.setUpdateBy(loginUser.getName());
+        return  versionService.updateVersion(version);
+    }
+
+    //@RequiresPermissions("system:version:edit")
+    @GetMapping("/detail/{id}")
+    public AjaxResult detail(@PathVariable Long id) {
+
+        return  success(versionService.getDetailById(id));
+    }
+
+    //@RequiresPermissions("system:version:download")
+    @GetMapping("/download/{id}")
+    public void download(HttpServletResponse response ,@PathVariable Long id) {
+        versionService.downloadFile(response,id);
+    }
+
+    @PostMapping("/checkUpdate")
+    public AjaxResult checkUpdate(@RequestBody SysCheckUpdateDto updateDto) {
+        SysCheckUpdateDto dto = versionService.checkUpdate(updateDto);
+        return success(dto);
+    }
+
+}

+ 29 - 0
soc-modules/soc-modules-system/src/main/java/com/xunmei/system/dto/SysCheckUpdateDto.java

@@ -0,0 +1,29 @@
+package com.xunmei.system.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+public class SysCheckUpdateDto {
+
+    @ApiModelProperty(value = "当前版本")
+    private String currentVersion;
+
+    @ApiModelProperty(value = "平台类型")
+    private String typeDesc;
+
+    @ApiModelProperty(value = "是否有新版本")
+    private boolean needUpdate;
+
+    @ApiModelProperty(value = "是否强制更新")
+    private boolean isForce;
+
+    @ApiModelProperty(value = "下载地址")
+    private String downloadUrl;
+
+    @ApiModelProperty(value = "新版本")
+    private String newVersion;
+
+    @ApiModelProperty(value = "版本说明")
+    private String note;
+}

+ 11 - 0
soc-modules/soc-modules-system/src/main/java/com/xunmei/system/mapper/SysVersionMapper.java

@@ -0,0 +1,11 @@
+package com.xunmei.system.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.xunmei.system.api.domain.SysVersion;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+@Mapper
+public interface SysVersionMapper extends BaseMapper<SysVersion> {
+    void disabledOthers(@Param("id") Long id, @Param("type") Integer type);
+}

+ 31 - 0
soc-modules/soc-modules-system/src/main/java/com/xunmei/system/service/ISysVersionService.java

@@ -0,0 +1,31 @@
+package com.xunmei.system.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.xunmei.common.core.web.domain.AjaxResult;
+import com.xunmei.common.core.web.page.TableDataInfo;
+import com.xunmei.system.api.domain.SysVersion;
+import com.xunmei.system.dto.SysCheckUpdateDto;
+
+import javax.servlet.http.HttpServletResponse;
+
+public interface ISysVersionService extends IService<SysVersion> {
+
+    TableDataInfo<SysVersion> selectPage(SysVersion sysVersion);
+
+    AjaxResult insertVersion(SysVersion sysVersion);
+
+    AjaxResult updateVersion(SysVersion sysVersion);
+
+    /**
+     * 修改当前类型的升级包,其他版本的为未使用
+     * @param id
+     * @param type
+     */
+    void disabledOthers(Long id,Integer type);
+
+    SysVersion getDetailById(Long id);
+
+    void downloadFile(HttpServletResponse response, Long id);
+
+    SysCheckUpdateDto checkUpdate(SysCheckUpdateDto checkUpdateDto);
+}

+ 201 - 0
soc-modules/soc-modules-system/src/main/java/com/xunmei/system/service/impl/SysVersionServiceImpl.java

@@ -0,0 +1,201 @@
+package com.xunmei.system.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.xunmei.common.core.utils.StringUtils;
+import com.xunmei.common.core.web.domain.AjaxResult;
+import com.xunmei.common.core.web.page.TableDataInfo;
+import com.xunmei.system.api.RemoteFileService;
+import com.xunmei.system.api.domain.SysFile;
+import com.xunmei.system.api.domain.SysVersion;
+import com.xunmei.system.api.enums.AppType;
+import com.xunmei.system.dto.SysCheckUpdateDto;
+import com.xunmei.system.mapper.SysVersionMapper;
+import com.xunmei.system.service.ISysVersionService;
+import feign.Response;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.github.zafarkhaja.semver.Version;
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.io.*;
+import java.util.Date;
+import java.util.Objects;
+
+@Service
+public class SysVersionServiceImpl extends ServiceImpl<SysVersionMapper, SysVersion> implements ISysVersionService {
+
+    @Resource
+    private SysVersionMapper versionMapper;
+
+
+    @Resource
+    private RemoteFileService fileService;
+
+    @Override
+    public TableDataInfo<SysVersion> selectPage(SysVersion sysVersion) {
+        Page<SysVersion> page;
+        if (sysVersion.getPageNum() != null && sysVersion.getPageSize() != null) {
+            page = new Page<>(sysVersion.getPageNum(), sysVersion.getPageSize());
+        } else {
+            page = new Page<>();
+        }
+        QueryWrapper<SysVersion> wrapper = new QueryWrapper<>();
+        if (sysVersion.getType() != null ){
+            wrapper.eq("type",sysVersion.getType());
+        }
+        if (StringUtils.isNotEmpty(sysVersion.getVersion())){
+            wrapper.like("version",sysVersion.getVersion());
+        }
+        page = versionMapper.selectPage(page, wrapper);
+        return TableDataInfo.build(page);
+    }
+
+    @Transactional
+    @Override
+    public AjaxResult insertVersion(SysVersion sysVersion) {
+        //查询当前类型是否有当前版本
+        String msg = checkSameVersion(sysVersion,false);
+        if (StringUtils.isNotEmpty(msg)){
+            return AjaxResult.error(msg);
+        }
+
+        sysVersion.setCreateTime(new Date());
+        this.save(sysVersion);
+        if (sysVersion.getIsUse()){
+            disabledOthers(sysVersion.getId(),sysVersion.getType());
+        }
+        return AjaxResult.success();
+    }
+
+    @Transactional
+    @Override
+    public AjaxResult updateVersion(SysVersion sysVersion) {
+        //查询当前类型是否有当前版本
+        String msg = checkSameVersion(sysVersion,true);
+        if (StringUtils.isNotEmpty(msg)){
+            return AjaxResult.error(msg);
+        }
+
+        if (sysVersion.getId() != null){
+            sysVersion.setUpdateTime(new Date());
+            this.updateById(sysVersion);
+            if (sysVersion.getIsUse()){
+                disabledOthers(sysVersion.getId(),sysVersion.getType());
+            }
+        }
+        return AjaxResult.success();
+    }
+
+    @Override
+    public void disabledOthers(Long id, Integer type) {
+        versionMapper.disabledOthers(id,type);
+    }
+
+    @Override
+    public SysVersion getDetailById(Long id) {
+        return getById(id);
+    }
+
+    @Override
+    public void downloadFile(HttpServletResponse response, Long id){
+        InputStream inputStream = null;
+        BufferedInputStream bufferedInputStream = null;
+        BufferedOutputStream bufferedOutputStream = null;
+        try {
+            SysVersion version = getById(id);
+            if (null != version){
+                SysFile sysFile = new SysFile();
+                sysFile.setRealName(version.getPackageName());
+                sysFile.setUrl(version.getPath());
+                //Feign远程调用获取文件流
+                Response result = fileService.downloadFileRealName(sysFile);
+                Response.Body body = result.body();
+                inputStream = body.asInputStream();
+                bufferedInputStream = new BufferedInputStream(inputStream);
+                response.setHeader("Content-Type","application/octet-stream");
+                response.setHeader("Content-Disposition", result.headers().get("Content-Disposition").toString().replace("[", "").replace("]", ""));
+                bufferedOutputStream = new BufferedOutputStream(response.getOutputStream());
+                int length = 0;
+                byte[] temp = new byte[1024 * 10];
+                while ((length = bufferedInputStream.read(temp)) != -1) {
+                    bufferedOutputStream.write(temp, 0, length);
+                }
+                bufferedOutputStream.flush();
+                bufferedOutputStream.close();
+                bufferedInputStream.close();
+                inputStream.close();
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public SysCheckUpdateDto checkUpdate(SysCheckUpdateDto checkUpdateDto) {
+        SysCheckUpdateDto dto = new SysCheckUpdateDto();
+        dto.setNeedUpdate(false);
+        dto.setCurrentVersion(checkUpdateDto.getCurrentVersion());
+        dto.setTypeDesc(checkUpdateDto.getTypeDesc());
+        int type = -1;
+        switch (checkUpdateDto.getTypeDesc()){
+            case "APP":
+                type = AppType.APP.getIndex();
+                break;
+            case "PC":
+                type = AppType.PC.getIndex();
+                break;
+            case "IOS":
+                type = AppType.IOS.getIndex();
+                break;
+            case "HANG_WALL":
+                type = AppType.HANG_WALL.getIndex();
+                break;
+        }
+        if (type == -1){
+            return dto;
+        }
+        //使用的版本只有一个
+        QueryWrapper<SysVersion> wrapper = new QueryWrapper<>();
+        wrapper.eq("type",type);
+        wrapper.eq("is_use",1);
+        SysVersion version = getOne(wrapper);
+        if (null != version){
+            //判断终端版本是否小于等于使用版本
+            Version currentVersion = Version.valueOf(checkUpdateDto.getCurrentVersion());
+            Version useVersion = Version.valueOf(version.getVersion());
+            if (useVersion.compareTo(currentVersion) > 0){
+                //使用版本大于终端版本,需要升级
+                dto.setNeedUpdate(true);
+                dto.setForce(version.getIsForce());
+                dto.setNewVersion(version.getVersion());
+                dto.setNote(version.getNote());
+                dto.setDownloadUrl("/system/version/download/"+version.getId());
+                return dto;
+            }
+        }
+        return dto;
+    }
+
+    private String checkSameVersion(SysVersion sysVersion,boolean isUpdate){
+        //查询当前类型是否有当前版本
+        QueryWrapper<SysVersion> wrapper = new QueryWrapper<>();
+        wrapper.eq("type",sysVersion.getType());
+        wrapper.eq("version",sysVersion.getVersion());
+        //同一类型同一版本只有一条数据
+        SysVersion one = getOne(wrapper);
+        if (isUpdate){
+            if (null != one && !Objects.equals(one.getId(), sysVersion.getId())){
+                AppType appType = AppType.getEnumByIndex(sysVersion.getType());
+                return appType.getText() + " 终端已存在 " + sysVersion.getVersion() + " 版本包,请重新输入!";
+            }
+        }else {
+            if (null != one){
+                AppType appType = AppType.getEnumByIndex(sysVersion.getType());
+                return appType.getText() + " 终端已存在 " + sysVersion.getVersion() + " 版本包,请重新输入!";
+            }
+        }
+        return null;
+    }
+}

+ 10 - 0
soc-modules/soc-modules-system/src/main/resources/mapper/system/SysVersionMapper.xml

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.xunmei.system.mapper.SysVersionMapper">
+
+    <update id="disabledOthers">
+        update sys_version set is_use = 0 where id != #{id} and `type` = #{type}
+    </update>
+</mapper>