Merge remote-tracking branch 'ztcloud/test' into dev
This commit is contained in:
132
sql/dm/外部系统推送配置初始化_DM8_20260120.sql
Normal file
132
sql/dm/外部系统推送配置初始化_DM8_20260120.sql
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
-- DM8 外部系统推送配置初始化脚本
|
||||||
|
-- 用于配置不同公司/部门/业务类型下的外部系统推送开关
|
||||||
|
-- 创建日期:2026-01-20
|
||||||
|
|
||||||
|
-- 重复执行时请先备份数据
|
||||||
|
-- DROP TABLE IF EXISTS system_external_push_config;
|
||||||
|
|
||||||
|
-- 创建表
|
||||||
|
CREATE TABLE system_external_push_config (
|
||||||
|
id BIGINT NOT NULL PRIMARY KEY,
|
||||||
|
company_id BIGINT DEFAULT NULL NULL,
|
||||||
|
dept_id BIGINT DEFAULT NULL NULL,
|
||||||
|
business_type VARCHAR(32) DEFAULT NULL NULL,
|
||||||
|
external_system VARCHAR(64) DEFAULT NULL NULL,
|
||||||
|
enable_push BIT DEFAULT '1' NOT NULL,
|
||||||
|
remark VARCHAR(512) DEFAULT NULL NULL,
|
||||||
|
tenant_id BIGINT DEFAULT 0 NOT NULL,
|
||||||
|
creator VARCHAR(64) DEFAULT '' NULL,
|
||||||
|
create_time DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||||
|
updater VARCHAR(64) DEFAULT '' NULL,
|
||||||
|
update_time DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||||
|
deleted TINYINT DEFAULT 0 NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 表和字段注释
|
||||||
|
COMMENT ON TABLE system_external_push_config IS '外部系统推送配置';
|
||||||
|
COMMENT ON COLUMN system_external_push_config.id IS '主键编号';
|
||||||
|
COMMENT ON COLUMN system_external_push_config.company_id IS '公司编号(关联 system_dept 表的 is_company=1 的记录,为空表示不限制公司)';
|
||||||
|
COMMENT ON COLUMN system_external_push_config.dept_id IS '部门编号(关联 system_dept 表的 is_company=0 的记录,为空表示公司级配置)';
|
||||||
|
COMMENT ON COLUMN system_external_push_config.business_type IS '业务类型(PURCHASE/SALE/PRODUCTION,为空表示所有业务类型)';
|
||||||
|
COMMENT ON COLUMN system_external_push_config.external_system IS '外部系统标识(ERP/IWORK/等,为空表示所有外部系统)';
|
||||||
|
COMMENT ON COLUMN system_external_push_config.enable_push IS '是否启用推送(1启用 0停用)';
|
||||||
|
COMMENT ON COLUMN system_external_push_config.remark IS '备注';
|
||||||
|
COMMENT ON COLUMN system_external_push_config.tenant_id IS '租户编号';
|
||||||
|
COMMENT ON COLUMN system_external_push_config.creator IS '创建者';
|
||||||
|
COMMENT ON COLUMN system_external_push_config.create_time IS '创建时间';
|
||||||
|
COMMENT ON COLUMN system_external_push_config.updater IS '更新者';
|
||||||
|
COMMENT ON COLUMN system_external_push_config.update_time IS '更新时间';
|
||||||
|
COMMENT ON COLUMN system_external_push_config.deleted IS '删除标记(0未删除 1已删除)';
|
||||||
|
|
||||||
|
/*-- 唯一索引:租户+公司+部门+业务类型+外部系统的组合唯一
|
||||||
|
-- 注意:因为 dept_id 和 external_system 可以为 NULL,使用 COALESCE 处理
|
||||||
|
CREATE UNIQUE INDEX uk_external_push_config_unique
|
||||||
|
ON system_external_push_config (tenant_id, company_id, COALESCE(dept_id, 0), business_type, COALESCE(external_system, ''));
|
||||||
|
|
||||||
|
-- 辅助索引:按公司查询
|
||||||
|
CREATE INDEX idx_external_push_config_company
|
||||||
|
ON system_external_push_config (tenant_id, company_id);
|
||||||
|
|
||||||
|
-- 辅助索引:按业务类型查询
|
||||||
|
CREATE INDEX idx_external_push_config_biz_type
|
||||||
|
ON system_external_push_config (tenant_id, business_type);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- 初始化菜单权限数据
|
||||||
|
-- 主菜单
|
||||||
|
INSERT INTO system_menu (
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, component_name, status,
|
||||||
|
visible, keep_alive, always_show, creator, create_time,
|
||||||
|
updater, update_time, deleted
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
20060, '外部系统推送配置', '', 2, 60, 1,
|
||||||
|
'external-push-config', 'setting', 'system/push/config/index', 'SystemExternalPushConfig', 0,
|
||||||
|
'1', '1', '1', 'admin', SYSDATE,
|
||||||
|
'admin', SYSDATE, 0
|
||||||
|
FROM dual
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1 FROM system_menu WHERE id = 20060
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 查询权限
|
||||||
|
INSERT INTO system_menu (
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status, visible, keep_alive,
|
||||||
|
creator, create_time, updater, update_time, deleted
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
2006001, '推送配置查询', 'system:external-push-config:query', 3, 1, 20060,
|
||||||
|
'', '', '', 0, '1', '1',
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
FROM dual
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1 FROM system_menu WHERE id = 2006001
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 创建权限
|
||||||
|
INSERT INTO system_menu (
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status, visible, keep_alive,
|
||||||
|
creator, create_time, updater, update_time, deleted
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
2006002, '推送配置创建', 'system:external-push-config:create', 3, 2, 20060,
|
||||||
|
'', '', '', 0, '1', '1',
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
FROM dual
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1 FROM system_menu WHERE id = 2006002
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 修改权限
|
||||||
|
INSERT INTO system_menu (
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status, visible, keep_alive,
|
||||||
|
creator, create_time, updater, update_time, deleted
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
2006003, '推送配置修改', 'system:external-push-config:update', 3, 3, 20060,
|
||||||
|
'', '', '', 0, '1', '1',
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
FROM dual
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1 FROM system_menu WHERE id = 2006003
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 删除权限
|
||||||
|
INSERT INTO system_menu (
|
||||||
|
id, name, permission, type, sort, parent_id,
|
||||||
|
path, icon, component, status, visible, keep_alive,
|
||||||
|
creator, create_time, updater, update_time, deleted
|
||||||
|
)
|
||||||
|
SELECT
|
||||||
|
2006004, '推送配置删除', 'system:external-push-config:delete', 3, 4, 20060,
|
||||||
|
'', '', '', 0, '1', '1',
|
||||||
|
'admin', SYSDATE, 'admin', SYSDATE, 0
|
||||||
|
FROM dual
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1 FROM system_menu WHERE id = 2006004
|
||||||
|
);*/
|
||||||
@@ -59,13 +59,15 @@ public class BusinessDeptHandleUtil {
|
|||||||
}
|
}
|
||||||
// 如果有 deptId,校验其是否属于该 companyId
|
// 如果有 deptId,校验其是否属于该 companyId
|
||||||
if (deptIdHeader != null) {
|
if (deptIdHeader != null) {
|
||||||
boolean valid = companyDeptSetByCompanyId.stream().anyMatch(info -> String.valueOf(info.getDeptId()).equals(deptIdHeader));
|
Optional<CompanyDeptInfo> matched = companyDeptSetByCompanyId.stream()
|
||||||
if (!valid) {
|
.filter(info -> String.valueOf(info.getDeptId()).equals(deptIdHeader))
|
||||||
|
.findFirst();
|
||||||
|
if (matched.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
|
||||||
// 部门存在,放行
|
|
||||||
return new HashSet<>();
|
|
||||||
}
|
}
|
||||||
|
// 部门存在,先设置登录信息再放行
|
||||||
|
applyAutoSelection(currentLoginUser, request, matched.get());
|
||||||
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
if (companyDeptSetByCompanyId.size() == 1) {
|
if (companyDeptSetByCompanyId.size() == 1) {
|
||||||
CompanyDeptInfo singleCompanyDept = companyDeptSetByCompanyId.iterator().next();
|
CompanyDeptInfo singleCompanyDept = companyDeptSetByCompanyId.iterator().next();
|
||||||
@@ -183,10 +185,10 @@ public class BusinessDeptHandleUtil {
|
|||||||
if (loginUser != null) {
|
if (loginUser != null) {
|
||||||
loginUser.setVisitCompanyId(Long.valueOf(info.getCompanyId()));
|
loginUser.setVisitCompanyId(Long.valueOf(info.getCompanyId()));
|
||||||
loginUser.setVisitCompanyName(info.getCompanyName());
|
loginUser.setVisitCompanyName(info.getCompanyName());
|
||||||
loginUser.setVisitCompanyCode(info.getCompanyName());
|
loginUser.setVisitCompanyCode(info.getCompanyCode());
|
||||||
loginUser.setVisitDeptId(Long.valueOf(info.getDeptId()));
|
loginUser.setVisitDeptId(Long.valueOf(info.getDeptId()));
|
||||||
loginUser.setVisitDeptName(info.getDeptName());
|
loginUser.setVisitDeptName(info.getDeptName());
|
||||||
loginUser.setVisitDeptCode(info.getDeptName());
|
loginUser.setVisitDeptCode(info.getDeptCode());
|
||||||
}
|
}
|
||||||
request.setAttribute(WebFrameworkUtils.HEADER_VISIT_COMPANY_ID, info.getCompanyId());
|
request.setAttribute(WebFrameworkUtils.HEADER_VISIT_COMPANY_ID, info.getCompanyId());
|
||||||
if (info.getCompanyName() != null) {
|
if (info.getCompanyName() != null) {
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.zt.plat.module.system.api.push;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||||
|
import com.zt.plat.module.system.enums.ApiConstants;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import org.springframework.cloud.openfeign.FeignClient;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 外部系统推送配置 Feign API
|
||||||
|
*
|
||||||
|
* @author ZT Cloud
|
||||||
|
*/
|
||||||
|
@FeignClient(name = ApiConstants.NAME)
|
||||||
|
@Tag(name = "RPC 服务 - 外部系统推送配置")
|
||||||
|
public interface ExternalPushConfigApi {
|
||||||
|
|
||||||
|
String PREFIX = ApiConstants.PREFIX + "/external-push-config";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否允许推送到外部系统
|
||||||
|
*
|
||||||
|
* @param companyId 公司编号(可选,为 null 时表示不限制公司)
|
||||||
|
* @param deptId 部门编号(可选,为 null 时只按公司配置判断)
|
||||||
|
* @param businessType 业务类型(可选:PURCHASE/SALE/PRODUCTION,为 null 时表示所有业务类型)
|
||||||
|
* @param externalSystem 外部系统标识(可选:ERP/IWORK/等,为 null 时表示所有外部系统)
|
||||||
|
* @return 是否允许推送(true=允许,false=禁止,默认 true)
|
||||||
|
*/
|
||||||
|
@GetMapping(PREFIX + "/is-push-enabled")
|
||||||
|
@Operation(summary = "判断是否允许推送到外部系统")
|
||||||
|
CommonResult<Boolean> isPushEnabled(
|
||||||
|
@RequestParam(value = "companyId", required = false) @Parameter(description = "公司编号") Long companyId,
|
||||||
|
@RequestParam(value = "deptId", required = false) @Parameter(description = "部门编号") Long deptId,
|
||||||
|
@RequestParam(value = "businessType", required = false) @Parameter(description = "业务类型") String businessType,
|
||||||
|
@RequestParam(value = "externalSystem", required = false) @Parameter(description = "外部系统标识") String externalSystem);
|
||||||
|
}
|
||||||
@@ -230,4 +230,11 @@ public interface ErrorCodeConstants {
|
|||||||
// ========== 门户网站 1-002-033-000 ==========
|
// ========== 门户网站 1-002-033-000 ==========
|
||||||
ErrorCode PORTAL_NOT_EXISTS = new ErrorCode(1_002_033_000, "门户不存在");
|
ErrorCode PORTAL_NOT_EXISTS = new ErrorCode(1_002_033_000, "门户不存在");
|
||||||
|
|
||||||
|
// ========== 外部系统推送配置 1_002_034_000 ==========
|
||||||
|
ErrorCode EXTERNAL_PUSH_CONFIG_NOT_EXISTS = new ErrorCode(1_002_034_001, "外部系统推送配置不存在");
|
||||||
|
ErrorCode EXTERNAL_PUSH_CONFIG_EXISTS = new ErrorCode(1_002_034_002, "该配置已存在");
|
||||||
|
ErrorCode EXTERNAL_PUSH_CONFIG_COMPANY_INVALID = new ErrorCode(1_002_034_003, "公司编号必须是公司节点(is_company=1)");
|
||||||
|
ErrorCode EXTERNAL_PUSH_CONFIG_DEPT_INVALID = new ErrorCode(1_002_034_004, "部门编号必须是部门节点(is_company=0)");
|
||||||
|
ErrorCode EXTERNAL_PUSH_CONFIG_BUSINESS_TYPE_INVALID = new ErrorCode(1_002_034_005, "业务类型无效,仅支持 PURCHASE/SALE/PRODUCTION");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package com.zt.plat.module.system.enums.push;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务类型枚举
|
||||||
|
*
|
||||||
|
* @author ZT Cloud
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum BusinessTypeEnum {
|
||||||
|
|
||||||
|
PURCHASE(1, "PURCHASE", "采购"),
|
||||||
|
SALE(2, "SALE", "销售"),
|
||||||
|
PRODUCTION(3, "PRODUCTION", "生产");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型
|
||||||
|
*/
|
||||||
|
private final Integer type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编码
|
||||||
|
*/
|
||||||
|
private final String code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 名称
|
||||||
|
*/
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据编码获取枚举
|
||||||
|
*/
|
||||||
|
public static BusinessTypeEnum valueOfCode(String code) {
|
||||||
|
if (code == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (BusinessTypeEnum value : BusinessTypeEnum.values()) {
|
||||||
|
if (value.getCode().equals(code)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据类型获取枚举
|
||||||
|
*/
|
||||||
|
public static BusinessTypeEnum valueOfType(Integer type) {
|
||||||
|
if (type == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
for (BusinessTypeEnum value : BusinessTypeEnum.values()) {
|
||||||
|
if (value.getType().equals(type)) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 验证编码是否有效
|
||||||
|
*/
|
||||||
|
public static boolean isValidCode(String code) {
|
||||||
|
return valueOfCode(code) != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.zt.plat.module.system.api.push;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||||
|
import com.zt.plat.module.system.service.push.ExternalPushConfigService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 外部系统推送配置 Feign API 实现类
|
||||||
|
*
|
||||||
|
* @author ZT Cloud
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@Validated
|
||||||
|
public class ExternalPushConfigApiImpl implements ExternalPushConfigApi {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ExternalPushConfigService externalPushConfigService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<Boolean> isPushEnabled(Long companyId, Long deptId, String businessType, String externalSystem) {
|
||||||
|
Boolean result = externalPushConfigService.isPushEnabled(companyId, deptId, businessType, externalSystem);
|
||||||
|
return success(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.zt.plat.module.system.controller.admin.integration.iwork.vo;
|
package com.zt.plat.module.system.controller.admin.integration.iwork.vo;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import com.zt.plat.module.system.enums.integration.IWorkSyncEntityTypeEnum;
|
import com.zt.plat.module.system.enums.integration.IWorkSyncEntityTypeEnum;
|
||||||
import io.swagger.v3.oas.annotations.media.Schema;
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
import jakarta.validation.constraints.Max;
|
import jakarta.validation.constraints.Max;
|
||||||
@@ -42,6 +43,66 @@ public class IWorkFullSyncReqVO {
|
|||||||
@Schema(description = "是否允许更新已存在的本地实体", example = "false")
|
@Schema(description = "是否允许更新已存在的本地实体", example = "false")
|
||||||
private Boolean allowUpdate = Boolean.FALSE;
|
private Boolean allowUpdate = Boolean.FALSE;
|
||||||
|
|
||||||
|
@JsonProperty("departmentcode")
|
||||||
|
@Schema(description = "部门编号")
|
||||||
|
private String departmentCode;
|
||||||
|
|
||||||
|
@JsonProperty("departmentname")
|
||||||
|
@Schema(description = "部门名称")
|
||||||
|
private String departmentName;
|
||||||
|
|
||||||
|
@JsonProperty("subcompanycode")
|
||||||
|
@Schema(description = "分部编号")
|
||||||
|
private String subcompanyCode;
|
||||||
|
|
||||||
|
@JsonProperty("subcompanyname")
|
||||||
|
@Schema(description = "分部名称")
|
||||||
|
private String subcompanyName;
|
||||||
|
|
||||||
|
@JsonProperty("subcompanyid1")
|
||||||
|
@Schema(description = "分部 ID")
|
||||||
|
private String subcompanyId1;
|
||||||
|
|
||||||
|
@JsonProperty("jobtitlename")
|
||||||
|
@Schema(description = "岗位名称")
|
||||||
|
private String jobTitleName;
|
||||||
|
|
||||||
|
@JsonProperty("workcode")
|
||||||
|
@Schema(description = "人员编号")
|
||||||
|
private String workCode;
|
||||||
|
|
||||||
|
@JsonProperty("loginid")
|
||||||
|
@Schema(description = "登录名")
|
||||||
|
private String loginId;
|
||||||
|
|
||||||
|
@JsonProperty("created")
|
||||||
|
@Schema(description = "创建时间戳(>=)")
|
||||||
|
private String created;
|
||||||
|
|
||||||
|
@JsonProperty("modified")
|
||||||
|
@Schema(description = "修改时间戳(>=)")
|
||||||
|
private String modified;
|
||||||
|
|
||||||
|
@JsonProperty("canceled")
|
||||||
|
@Schema(description = "封存标志,默认查询非封存数据。1:封存")
|
||||||
|
private String canceled;
|
||||||
|
|
||||||
|
@JsonProperty("custom_data")
|
||||||
|
@Schema(description = "自定义字段列表(逗号分隔)")
|
||||||
|
private String customData;
|
||||||
|
|
||||||
|
@JsonProperty("base_custom_data")
|
||||||
|
@Schema(description = "基本信息自定义字段列表(逗号分隔)")
|
||||||
|
private String baseCustomData;
|
||||||
|
|
||||||
|
@JsonProperty("person_custom_data")
|
||||||
|
@Schema(description = "个人信息自定义字段列表(逗号分隔)")
|
||||||
|
private String personCustomData;
|
||||||
|
|
||||||
|
@JsonProperty("work_custom_data")
|
||||||
|
@Schema(description = "工作信息自定义字段列表(逗号分隔)")
|
||||||
|
private String workCustomData;
|
||||||
|
|
||||||
public Set<IWorkSyncEntityTypeEnum> resolveScopes() {
|
public Set<IWorkSyncEntityTypeEnum> resolveScopes() {
|
||||||
EnumSet<IWorkSyncEntityTypeEnum> defaults = EnumSet.allOf(IWorkSyncEntityTypeEnum.class);
|
EnumSet<IWorkSyncEntityTypeEnum> defaults = EnumSet.allOf(IWorkSyncEntityTypeEnum.class);
|
||||||
if (scopes == null || scopes.isEmpty()) {
|
if (scopes == null || scopes.isEmpty()) {
|
||||||
|
|||||||
@@ -0,0 +1,160 @@
|
|||||||
|
package com.zt.plat.module.system.controller.admin.push;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.CommonResult;
|
||||||
|
import com.zt.plat.framework.common.pojo.PageResult;
|
||||||
|
import com.zt.plat.framework.common.util.collection.CollectionUtils;
|
||||||
|
import com.zt.plat.framework.common.util.object.BeanUtils;
|
||||||
|
import com.zt.plat.module.system.controller.admin.push.vo.BusinessTypeRespVO;
|
||||||
|
import com.zt.plat.module.system.controller.admin.push.vo.ExternalPushConfigPageReqVO;
|
||||||
|
import com.zt.plat.module.system.controller.admin.push.vo.ExternalPushConfigRespVO;
|
||||||
|
import com.zt.plat.module.system.controller.admin.push.vo.ExternalPushConfigSaveReqVO;
|
||||||
|
import com.zt.plat.module.system.dal.dataobject.dept.DeptDO;
|
||||||
|
import com.zt.plat.module.system.dal.dataobject.push.ExternalPushConfigDO;
|
||||||
|
import com.zt.plat.module.system.enums.push.BusinessTypeEnum;
|
||||||
|
import com.zt.plat.module.system.service.dept.DeptService;
|
||||||
|
import com.zt.plat.module.system.service.push.ExternalPushConfigService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static com.zt.plat.framework.common.pojo.CommonResult.success;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 外部系统推送配置 Controller
|
||||||
|
*
|
||||||
|
* @author ZT Cloud
|
||||||
|
*/
|
||||||
|
@Tag(name = "管理后台 - 外部系统推送配置")
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/system/external-push-config")
|
||||||
|
@Validated
|
||||||
|
public class ExternalPushConfigController {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ExternalPushConfigService externalPushConfigService;
|
||||||
|
@Resource
|
||||||
|
private DeptService deptService;
|
||||||
|
|
||||||
|
@PostMapping("/create")
|
||||||
|
@Operation(summary = "创建推送配置")
|
||||||
|
@PreAuthorize("@ss.hasPermission('system:external-push-config:create')")
|
||||||
|
public CommonResult<Long> create(@Valid @RequestBody ExternalPushConfigSaveReqVO createReqVO) {
|
||||||
|
Long id = externalPushConfigService.createExternalPushConfig(createReqVO);
|
||||||
|
return success(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping("/update")
|
||||||
|
@Operation(summary = "修改推送配置")
|
||||||
|
@PreAuthorize("@ss.hasPermission('system:external-push-config:update')")
|
||||||
|
public CommonResult<Boolean> update(@Valid @RequestBody ExternalPushConfigSaveReqVO updateReqVO) {
|
||||||
|
externalPushConfigService.updateExternalPushConfig(updateReqVO);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping("/delete")
|
||||||
|
@Operation(summary = "删除推送配置")
|
||||||
|
@PreAuthorize("@ss.hasPermission('system:external-push-config:delete')")
|
||||||
|
public CommonResult<Boolean> delete(@RequestParam("id") Long id) {
|
||||||
|
externalPushConfigService.deleteExternalPushConfig(id);
|
||||||
|
return success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/get")
|
||||||
|
@Operation(summary = "获取推送配置详情")
|
||||||
|
@PreAuthorize("@ss.hasPermission('system:external-push-config:query')")
|
||||||
|
public CommonResult<ExternalPushConfigRespVO> get(@RequestParam("id") Long id) {
|
||||||
|
ExternalPushConfigDO entity = externalPushConfigService.getExternalPushConfig(id);
|
||||||
|
ExternalPushConfigRespVO respVO = BeanUtils.toBean(entity, ExternalPushConfigRespVO.class);
|
||||||
|
fillDeptInfo(List.of(respVO));
|
||||||
|
return success(respVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/page")
|
||||||
|
@Operation(summary = "分页查询推送配置")
|
||||||
|
@PreAuthorize("@ss.hasPermission('system:external-push-config:query')")
|
||||||
|
public CommonResult<PageResult<ExternalPushConfigRespVO>> page(@Valid ExternalPushConfigPageReqVO reqVO) {
|
||||||
|
PageResult<ExternalPushConfigDO> pageResult = externalPushConfigService.getExternalPushConfigPage(reqVO);
|
||||||
|
PageResult<ExternalPushConfigRespVO> result = BeanUtils.toBean(pageResult, ExternalPushConfigRespVO.class);
|
||||||
|
fillDeptInfo(result.getList());
|
||||||
|
return success(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/is-push-enabled")
|
||||||
|
@Operation(summary = "判断是否允许推送")
|
||||||
|
@Parameter(name = "companyId", description = "公司编号(为空表示不限制公司)")
|
||||||
|
@Parameter(name = "deptId", description = "部门编号")
|
||||||
|
@Parameter(name = "businessType", description = "业务类型(为空表示所有业务类型)")
|
||||||
|
@Parameter(name = "externalSystem", description = "外部系统标识(为空表示所有外部系统)")
|
||||||
|
@PreAuthorize("@ss.hasPermission('system:external-push-config:query')")
|
||||||
|
public CommonResult<Boolean> isPushEnabled(
|
||||||
|
@RequestParam(value = "companyId", required = false) Long companyId,
|
||||||
|
@RequestParam(value = "deptId", required = false) Long deptId,
|
||||||
|
@RequestParam(value = "businessType", required = false) String businessType,
|
||||||
|
@RequestParam(value = "externalSystem", required = false) String externalSystem) {
|
||||||
|
Boolean result = externalPushConfigService.isPushEnabled(companyId, deptId, businessType, externalSystem);
|
||||||
|
return success(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/business-types")
|
||||||
|
@Operation(summary = "获取业务类型列表")
|
||||||
|
public CommonResult<List<BusinessTypeRespVO>> getBusinessTypes() {
|
||||||
|
List<BusinessTypeRespVO> result = Arrays.stream(BusinessTypeEnum.values())
|
||||||
|
.map(e -> new BusinessTypeRespVO(e.getType(), e.getCode(), e.getName()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
return success(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 填充公司和部门名称
|
||||||
|
*/
|
||||||
|
private void fillDeptInfo(List<ExternalPushConfigRespVO> list) {
|
||||||
|
if (list == null || list.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 收集所有公司ID和部门ID
|
||||||
|
Set<Long> deptIds = list.stream()
|
||||||
|
.flatMap(item -> {
|
||||||
|
Set<Long> ids = new java.util.HashSet<>();
|
||||||
|
ids.add(item.getCompanyId());
|
||||||
|
if (item.getDeptId() != null) {
|
||||||
|
ids.add(item.getDeptId());
|
||||||
|
}
|
||||||
|
return ids.stream();
|
||||||
|
})
|
||||||
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
if (deptIds.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量查询部门信息
|
||||||
|
Map<Long, DeptDO> deptMap = CollectionUtils.convertMap(
|
||||||
|
deptService.getDeptList(deptIds), DeptDO::getId);
|
||||||
|
|
||||||
|
// 填充名称
|
||||||
|
list.forEach(item -> {
|
||||||
|
DeptDO company = deptMap.get(item.getCompanyId());
|
||||||
|
if (company != null) {
|
||||||
|
item.setCompanyName(company.getName());
|
||||||
|
}
|
||||||
|
if (item.getDeptId() != null) {
|
||||||
|
DeptDO dept = deptMap.get(item.getDeptId());
|
||||||
|
if (dept != null) {
|
||||||
|
item.setDeptName(dept.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.zt.plat.module.system.controller.admin.push.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 业务类型 Response VO")
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class BusinessTypeRespVO {
|
||||||
|
|
||||||
|
@Schema(description = "类型", example = "1")
|
||||||
|
private Integer type;
|
||||||
|
|
||||||
|
@Schema(description = "编码", example = "PURCHASE")
|
||||||
|
private String code;
|
||||||
|
|
||||||
|
@Schema(description = "名称", example = "采购")
|
||||||
|
private String name;
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package com.zt.plat.module.system.controller.admin.push.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import jakarta.validation.constraints.Size;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 外部系统推送配置基础信息")
|
||||||
|
@Data
|
||||||
|
public class ExternalPushConfigBaseVO {
|
||||||
|
|
||||||
|
@Schema(description = "公司编号(为空表示不限制公司)", example = "1024")
|
||||||
|
private Long companyId;
|
||||||
|
|
||||||
|
@Schema(description = "部门编号(为空表示公司级配置)", example = "2048")
|
||||||
|
private Long deptId;
|
||||||
|
|
||||||
|
@Schema(description = "业务类型(为空表示所有业务类型)", example = "PURCHASE")
|
||||||
|
@Size(max = 32, message = "业务类型长度不能超过 32 个字符")
|
||||||
|
private String businessType;
|
||||||
|
|
||||||
|
@Schema(description = "外部系统标识(为空表示所有外部系统)", example = "ERP")
|
||||||
|
@Size(max = 64, message = "外部系统标识长度不能超过 64 个字符")
|
||||||
|
private String externalSystem;
|
||||||
|
|
||||||
|
@Schema(description = "是否启用推送", requiredMode = Schema.RequiredMode.REQUIRED, example = "true")
|
||||||
|
@NotNull(message = "推送开关不能为空")
|
||||||
|
private Boolean enablePush;
|
||||||
|
|
||||||
|
@Schema(description = "备注", example = "ERP 采购单推送配置")
|
||||||
|
@Size(max = 512, message = "备注长度不能超过 512 个字符")
|
||||||
|
private String remark;
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.zt.plat.module.system.controller.admin.push.vo;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.PageParam;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 外部系统推送配置分页 Request VO")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class ExternalPushConfigPageReqVO extends PageParam {
|
||||||
|
|
||||||
|
@Schema(description = "公司编号", example = "1024")
|
||||||
|
private Long companyId;
|
||||||
|
|
||||||
|
@Schema(description = "部门编号", example = "2048")
|
||||||
|
private Long deptId;
|
||||||
|
|
||||||
|
@Schema(description = "业务类型", example = "PURCHASE")
|
||||||
|
private String businessType;
|
||||||
|
|
||||||
|
@Schema(description = "外部系统标识", example = "ERP")
|
||||||
|
private String externalSystem;
|
||||||
|
|
||||||
|
@Schema(description = "是否启用推送", example = "true")
|
||||||
|
private Boolean enablePush;
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.zt.plat.module.system.controller.admin.push.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 外部系统推送配置 Response VO")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class ExternalPushConfigRespVO extends ExternalPushConfigBaseVO {
|
||||||
|
|
||||||
|
@Schema(description = "配置编号", example = "1024")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "公司名称", example = "浙江中天建设集团")
|
||||||
|
private String companyName;
|
||||||
|
|
||||||
|
@Schema(description = "部门名称", example = "采购部")
|
||||||
|
private String deptName;
|
||||||
|
|
||||||
|
@Schema(description = "创建时间")
|
||||||
|
private LocalDateTime createTime;
|
||||||
|
|
||||||
|
@Schema(description = "最后更新时间")
|
||||||
|
private LocalDateTime updateTime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.zt.plat.module.system.controller.admin.push.vo;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
@Schema(description = "管理后台 - 外部系统推送配置创建/修改 Request VO")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class ExternalPushConfigSaveReqVO extends ExternalPushConfigBaseVO {
|
||||||
|
|
||||||
|
@Schema(description = "配置编号", example = "1024")
|
||||||
|
private Long id;
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package com.zt.plat.module.system.dal.dataobject.push;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.KeySequence;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.zt.plat.framework.tenant.core.db.TenantBaseDO;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 外部系统推送配置 DO
|
||||||
|
*
|
||||||
|
* 用于配置不同公司/部门/业务类型下的外部系统推送开关
|
||||||
|
*
|
||||||
|
* @author ZT Cloud
|
||||||
|
*/
|
||||||
|
@TableName("system_external_push_config")
|
||||||
|
@KeySequence("system_external_push_config_seq")
|
||||||
|
@Data
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
public class ExternalPushConfigDO extends TenantBaseDO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主键编号
|
||||||
|
*/
|
||||||
|
@TableId(type = IdType.ASSIGN_ID)
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公司编号(可为空)
|
||||||
|
*
|
||||||
|
* 关联 system_dept 表,is_company = 1
|
||||||
|
* 为空表示不限制公司
|
||||||
|
*/
|
||||||
|
private Long companyId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 部门编号(可为空)
|
||||||
|
*
|
||||||
|
* 关联 system_dept 表,is_company = 0
|
||||||
|
* 为空表示公司级配置
|
||||||
|
*/
|
||||||
|
private Long deptId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务类型(可为空)
|
||||||
|
*
|
||||||
|
* 枚举值:PURCHASE, SALE, PRODUCTION
|
||||||
|
* 为空表示所有业务类型
|
||||||
|
* 枚举 {@link com.zt.plat.module.system.enums.push.BusinessTypeEnum}
|
||||||
|
*/
|
||||||
|
private String businessType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 外部系统标识(可为空)
|
||||||
|
*
|
||||||
|
* 如:ERP, IWORK
|
||||||
|
* 为空表示所有外部系统
|
||||||
|
* 枚举 {@link com.zt.plat.module.system.enums.dept.ExternalPlatformEnum}
|
||||||
|
*/
|
||||||
|
private String externalSystem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否启用推送
|
||||||
|
*
|
||||||
|
* true:启用推送
|
||||||
|
* false:停用推送
|
||||||
|
*/
|
||||||
|
private Boolean enablePush;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 备注
|
||||||
|
*/
|
||||||
|
private String remark;
|
||||||
|
}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
package com.zt.plat.module.system.dal.mysql.push;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.PageResult;
|
||||||
|
import com.zt.plat.framework.mybatis.core.mapper.BaseMapperX;
|
||||||
|
import com.zt.plat.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||||
|
import com.zt.plat.module.system.controller.admin.push.vo.ExternalPushConfigPageReqVO;
|
||||||
|
import com.zt.plat.module.system.dal.dataobject.push.ExternalPushConfigDO;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 外部系统推送配置 Mapper
|
||||||
|
*
|
||||||
|
* @author ZT Cloud
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface ExternalPushConfigMapper extends BaseMapperX<ExternalPushConfigDO> {
|
||||||
|
|
||||||
|
default PageResult<ExternalPushConfigDO> selectPage(ExternalPushConfigPageReqVO reqVO) {
|
||||||
|
LambdaQueryWrapperX<ExternalPushConfigDO> wrapper = new LambdaQueryWrapperX<ExternalPushConfigDO>()
|
||||||
|
.eqIfPresent(ExternalPushConfigDO::getCompanyId, reqVO.getCompanyId())
|
||||||
|
.eqIfPresent(ExternalPushConfigDO::getBusinessType, reqVO.getBusinessType())
|
||||||
|
.eqIfPresent(ExternalPushConfigDO::getExternalSystem, reqVO.getExternalSystem())
|
||||||
|
.eqIfPresent(ExternalPushConfigDO::getEnablePush, reqVO.getEnablePush());
|
||||||
|
|
||||||
|
// 如果传了 companyId 但没传 deptId,则只查公司级配置(dept_id IS NULL)
|
||||||
|
if (reqVO.getCompanyId() != null && reqVO.getDeptId() == null) {
|
||||||
|
wrapper.isNull(ExternalPushConfigDO::getDeptId);
|
||||||
|
} else if (reqVO.getDeptId() != null) {
|
||||||
|
// 如果传了 deptId,则查指定部门的配置
|
||||||
|
wrapper.eq(ExternalPushConfigDO::getDeptId, reqVO.getDeptId());
|
||||||
|
}
|
||||||
|
// 如果都没传,则查所有配置
|
||||||
|
|
||||||
|
wrapper.orderByDesc(ExternalPushConfigDO::getId);
|
||||||
|
return selectPage(reqVO, wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通用查询配置方法
|
||||||
|
*
|
||||||
|
* @param companyId 公司ID(null 表示查询 company_id IS NULL 的记录)
|
||||||
|
* @param deptId 部门ID(null 表示查询 dept_id IS NULL 的记录)
|
||||||
|
* @param businessType 业务类型(null 表示查询 business_type IS NULL 的记录)
|
||||||
|
* @param externalSystem 外部系统(null 表示查询 external_system IS NULL 的记录)
|
||||||
|
* @return 配置对象
|
||||||
|
*/
|
||||||
|
default ExternalPushConfigDO selectByConfig(Long companyId, Long deptId, String businessType, String externalSystem) {
|
||||||
|
LambdaQueryWrapperX<ExternalPushConfigDO> wrapper = new LambdaQueryWrapperX<>();
|
||||||
|
|
||||||
|
if (companyId == null) {
|
||||||
|
wrapper.isNull(ExternalPushConfigDO::getCompanyId);
|
||||||
|
} else {
|
||||||
|
wrapper.eq(ExternalPushConfigDO::getCompanyId, companyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (deptId == null) {
|
||||||
|
wrapper.isNull(ExternalPushConfigDO::getDeptId);
|
||||||
|
} else {
|
||||||
|
wrapper.eq(ExternalPushConfigDO::getDeptId, deptId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (businessType == null) {
|
||||||
|
wrapper.isNull(ExternalPushConfigDO::getBusinessType);
|
||||||
|
} else {
|
||||||
|
wrapper.eq(ExternalPushConfigDO::getBusinessType, businessType);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (externalSystem == null) {
|
||||||
|
wrapper.isNull(ExternalPushConfigDO::getExternalSystem);
|
||||||
|
} else {
|
||||||
|
wrapper.eq(ExternalPushConfigDO::getExternalSystem, externalSystem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return selectOne(wrapper);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询公司下所有配置
|
||||||
|
*/
|
||||||
|
default List<ExternalPushConfigDO> selectListByCompanyId(Long companyId) {
|
||||||
|
return selectList(ExternalPushConfigDO::getCompanyId, companyId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询部门下所有配置
|
||||||
|
*/
|
||||||
|
default List<ExternalPushConfigDO> selectListByDeptId(Long deptId) {
|
||||||
|
return selectList(ExternalPushConfigDO::getDeptId, deptId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.zt.plat.module.system.job.sync;
|
||||||
|
|
||||||
|
import com.xxl.job.core.handler.annotation.XxlJob;
|
||||||
|
import com.zt.plat.framework.tenant.core.job.TenantJob;
|
||||||
|
import com.zt.plat.module.system.service.sync.SyncIWorkUserChangeService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用于定时同步iWork当日修改的用户数据
|
||||||
|
* 同步时间:每日23:00
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@Slf4j
|
||||||
|
public class SyncIWorkUserChangeJob {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private SyncIWorkUserChangeService syncIWorkUserChangeService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行批量重跑任务
|
||||||
|
* 配置执行频率:每日23:00时执行一次
|
||||||
|
* cron表达式:0 0 23 * * ?
|
||||||
|
*/
|
||||||
|
@XxlJob("syncIWorkUserChangeJob")
|
||||||
|
@TenantJob
|
||||||
|
public void execute() {
|
||||||
|
log.info("[syncLogBatchRerunJob][开始执行同步iWork当日变更用户任务]");
|
||||||
|
try{
|
||||||
|
int processedCount = syncIWorkUserChangeService.process();
|
||||||
|
if (processedCount > 0) {
|
||||||
|
log.info("[syncLogBatchRerunJob][同步任务执行完成,处理了 {} 条记录]", processedCount);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("[syncLogBatchRerunJob][同步iWork当日变更用户任务执行异常]", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
package com.zt.plat.module.system.service.push;
|
||||||
|
|
||||||
|
import com.zt.plat.framework.common.pojo.PageResult;
|
||||||
|
import com.zt.plat.module.system.controller.admin.push.vo.ExternalPushConfigPageReqVO;
|
||||||
|
import com.zt.plat.module.system.controller.admin.push.vo.ExternalPushConfigSaveReqVO;
|
||||||
|
import com.zt.plat.module.system.dal.dataobject.push.ExternalPushConfigDO;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 外部系统推送配置 Service 接口
|
||||||
|
*
|
||||||
|
* @author ZT Cloud
|
||||||
|
*/
|
||||||
|
public interface ExternalPushConfigService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建推送配置
|
||||||
|
*/
|
||||||
|
Long createExternalPushConfig(@Valid ExternalPushConfigSaveReqVO createReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改推送配置
|
||||||
|
*/
|
||||||
|
void updateExternalPushConfig(@Valid ExternalPushConfigSaveReqVO updateReqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除推送配置
|
||||||
|
*/
|
||||||
|
void deleteExternalPushConfig(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取推送配置详情
|
||||||
|
*/
|
||||||
|
ExternalPushConfigDO getExternalPushConfig(Long id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分页查询推送配置
|
||||||
|
*/
|
||||||
|
PageResult<ExternalPushConfigDO> getExternalPushConfigPage(ExternalPushConfigPageReqVO reqVO);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否允许推送(核心业务逻辑)
|
||||||
|
*
|
||||||
|
* 优先级:部门配置 > 公司配置 > 默认允许
|
||||||
|
*
|
||||||
|
* @param companyId 公司编号(必填)
|
||||||
|
* @param deptId 部门编号(可选)
|
||||||
|
* @param businessType 业务类型(必填)
|
||||||
|
* @param externalSystem 外部系统标识(必填)
|
||||||
|
* @return 是否允许推送(true=允许,false=禁止,默认 true)
|
||||||
|
*/
|
||||||
|
Boolean isPushEnabled(Long companyId, Long deptId, String businessType, String externalSystem);
|
||||||
|
}
|
||||||
@@ -0,0 +1,280 @@
|
|||||||
|
package com.zt.plat.module.system.service.push;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.zt.plat.framework.common.pojo.PageResult;
|
||||||
|
import com.zt.plat.framework.common.util.object.BeanUtils;
|
||||||
|
import com.zt.plat.module.system.controller.admin.push.vo.ExternalPushConfigPageReqVO;
|
||||||
|
import com.zt.plat.module.system.controller.admin.push.vo.ExternalPushConfigSaveReqVO;
|
||||||
|
import com.zt.plat.module.system.dal.dataobject.dept.DeptDO;
|
||||||
|
import com.zt.plat.module.system.dal.dataobject.push.ExternalPushConfigDO;
|
||||||
|
import com.zt.plat.module.system.dal.mysql.dept.DeptMapper;
|
||||||
|
import com.zt.plat.module.system.dal.mysql.push.ExternalPushConfigMapper;
|
||||||
|
import com.zt.plat.module.system.enums.push.BusinessTypeEnum;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
|
||||||
|
import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||||
|
import static com.zt.plat.module.system.enums.ErrorCodeConstants.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 外部系统推送配置 Service 实现类
|
||||||
|
*
|
||||||
|
* @author ZT Cloud
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Validated
|
||||||
|
public class ExternalPushConfigServiceImpl implements ExternalPushConfigService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private ExternalPushConfigMapper externalPushConfigMapper;
|
||||||
|
@Resource
|
||||||
|
private DeptMapper deptMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long createExternalPushConfig(ExternalPushConfigSaveReqVO createReqVO) {
|
||||||
|
// 参数规范化
|
||||||
|
normalizeRequest(createReqVO);
|
||||||
|
|
||||||
|
// 业务校验
|
||||||
|
validateForCreateOrUpdate(null, createReqVO);
|
||||||
|
|
||||||
|
// 创建配置
|
||||||
|
ExternalPushConfigDO entity = BeanUtils.toBean(createReqVO, ExternalPushConfigDO.class);
|
||||||
|
if (entity.getEnablePush() == null) {
|
||||||
|
entity.setEnablePush(true);
|
||||||
|
}
|
||||||
|
externalPushConfigMapper.insert(entity);
|
||||||
|
return entity.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateExternalPushConfig(ExternalPushConfigSaveReqVO updateReqVO) {
|
||||||
|
// 参数规范化
|
||||||
|
normalizeRequest(updateReqVO);
|
||||||
|
|
||||||
|
// 校验存在
|
||||||
|
validateExists(updateReqVO.getId());
|
||||||
|
// 业务校验
|
||||||
|
validateForCreateOrUpdate(updateReqVO.getId(), updateReqVO);
|
||||||
|
|
||||||
|
// 更新配置
|
||||||
|
ExternalPushConfigDO updateObj = BeanUtils.toBean(updateReqVO, ExternalPushConfigDO.class);
|
||||||
|
externalPushConfigMapper.updateById(updateObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteExternalPushConfig(Long id) {
|
||||||
|
validateExists(id);
|
||||||
|
externalPushConfigMapper.deleteById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ExternalPushConfigDO getExternalPushConfig(Long id) {
|
||||||
|
return externalPushConfigMapper.selectById(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageResult<ExternalPushConfigDO> getExternalPushConfigPage(ExternalPushConfigPageReqVO reqVO) {
|
||||||
|
return externalPushConfigMapper.selectPage(reqVO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean isPushEnabled(Long companyId, Long deptId, String businessType, String externalSystem) {
|
||||||
|
// 规范化参数
|
||||||
|
String normalizedBusinessType = StrUtil.isNotBlank(businessType) ? businessType.trim().toUpperCase() : null;
|
||||||
|
String normalizedExternalSystem = StrUtil.isNotBlank(externalSystem) ? externalSystem.trim().toUpperCase() : null;
|
||||||
|
|
||||||
|
// 优先级 1:部门级配置(如果 deptId 不为空),递归查找父部门
|
||||||
|
if (deptId != null) {
|
||||||
|
ExternalPushConfigDO deptConfig = findDeptConfigRecursive(
|
||||||
|
companyId, deptId, normalizedBusinessType, normalizedExternalSystem);
|
||||||
|
if (deptConfig != null) {
|
||||||
|
return deptConfig.getEnablePush() != null ? deptConfig.getEnablePush() : true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 优先级 2:公司级配置(dept_id 为 null)
|
||||||
|
if (companyId != null) {
|
||||||
|
ExternalPushConfigDO companyConfig = externalPushConfigMapper.selectByConfig(
|
||||||
|
companyId, null, normalizedBusinessType, normalizedExternalSystem);
|
||||||
|
if (companyConfig != null) {
|
||||||
|
return companyConfig.getEnablePush() != null ? companyConfig.getEnablePush() : true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 优先级 3:全局配置(company_id 和 dept_id 都为空)
|
||||||
|
ExternalPushConfigDO globalConfig = externalPushConfigMapper.selectByConfig(
|
||||||
|
null, null, normalizedBusinessType, normalizedExternalSystem);
|
||||||
|
if (globalConfig != null) {
|
||||||
|
return globalConfig.getEnablePush() != null ? globalConfig.getEnablePush() : true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 优先级 4:没有配置,默认允许推送
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 递归查找部门配置(包括父部门)
|
||||||
|
*
|
||||||
|
* @param companyId 公司ID
|
||||||
|
* @param deptId 部门ID
|
||||||
|
* @param businessType 业务类型
|
||||||
|
* @param externalSystem 外部系统
|
||||||
|
* @return 配置对象,如果找不到返回 null
|
||||||
|
*/
|
||||||
|
private ExternalPushConfigDO findDeptConfigRecursive(Long companyId, Long deptId,
|
||||||
|
String businessType, String externalSystem) {
|
||||||
|
if (deptId == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询当前部门的配置
|
||||||
|
ExternalPushConfigDO config = externalPushConfigMapper.selectByConfig(
|
||||||
|
companyId, deptId, businessType, externalSystem);
|
||||||
|
if (config != null) {
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查询当前部门信息,获取父部门ID
|
||||||
|
DeptDO dept = deptMapper.selectById(deptId);
|
||||||
|
if (dept == null || dept.getParentId() == null || dept.getParentId() == 0L) {
|
||||||
|
// 没有父部门了,返回 null
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查父部门是否是公司节点
|
||||||
|
DeptDO parentDept = deptMapper.selectById(dept.getParentId());
|
||||||
|
if (parentDept != null && Boolean.TRUE.equals(parentDept.getIsCompany())) {
|
||||||
|
// 父部门是公司,不再向上查找(公司级配置在外层处理)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归查找父部门的配置
|
||||||
|
return findDeptConfigRecursive(companyId, dept.getParentId(), businessType, externalSystem);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==================== 私有方法 ====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验配置是否存在
|
||||||
|
*/
|
||||||
|
private ExternalPushConfigDO validateExists(Long id) {
|
||||||
|
if (id == null) {
|
||||||
|
throw exception(EXTERNAL_PUSH_CONFIG_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
ExternalPushConfigDO entity = externalPushConfigMapper.selectById(id);
|
||||||
|
if (entity == null) {
|
||||||
|
throw exception(EXTERNAL_PUSH_CONFIG_NOT_EXISTS);
|
||||||
|
}
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 业务校验
|
||||||
|
*/
|
||||||
|
private void validateForCreateOrUpdate(Long id, ExternalPushConfigSaveReqVO reqVO) {
|
||||||
|
// 1. 如果指定公司,校验公司存在且是公司节点
|
||||||
|
if (reqVO.getCompanyId() != null) {
|
||||||
|
DeptDO company = deptMapper.selectById(reqVO.getCompanyId());
|
||||||
|
if (company == null) {
|
||||||
|
throw exception(DEPT_NOT_FOUND);
|
||||||
|
}
|
||||||
|
if (!Boolean.TRUE.equals(company.getIsCompany())) {
|
||||||
|
throw exception(EXTERNAL_PUSH_CONFIG_COMPANY_INVALID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 如果指定部门,校验部门存在且不是公司节点
|
||||||
|
if (reqVO.getDeptId() != null) {
|
||||||
|
DeptDO dept = deptMapper.selectById(reqVO.getDeptId());
|
||||||
|
if (dept == null) {
|
||||||
|
throw exception(DEPT_NOT_FOUND);
|
||||||
|
}
|
||||||
|
if (Boolean.TRUE.equals(dept.getIsCompany())) {
|
||||||
|
throw exception(EXTERNAL_PUSH_CONFIG_DEPT_INVALID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 如果指定业务类型,校验业务类型有效性
|
||||||
|
if (StrUtil.isNotBlank(reqVO.getBusinessType())) {
|
||||||
|
if (!BusinessTypeEnum.isValidCode(reqVO.getBusinessType())) {
|
||||||
|
throw exception(EXTERNAL_PUSH_CONFIG_BUSINESS_TYPE_INVALID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 校验唯一性:同一租户+公司+部门+业务类型+外部系统的配置唯一
|
||||||
|
ExternalPushConfigDO existing = externalPushConfigMapper.selectByConfig(
|
||||||
|
reqVO.getCompanyId(), reqVO.getDeptId(),
|
||||||
|
reqVO.getBusinessType(), reqVO.getExternalSystem());
|
||||||
|
|
||||||
|
if (existing != null && (id == null || !existing.getId().equals(id))) {
|
||||||
|
throw exception(EXTERNAL_PUSH_CONFIG_EXISTS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 参数规范化
|
||||||
|
*/
|
||||||
|
private void normalizeRequest(ExternalPushConfigSaveReqVO reqVO) {
|
||||||
|
if (reqVO == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果 companyId 为空但 deptId 不为空,自动查找并填充顶级公司ID
|
||||||
|
if (reqVO.getCompanyId() == null && reqVO.getDeptId() != null) {
|
||||||
|
Long topCompanyId = findTopCompanyId(reqVO.getDeptId());
|
||||||
|
if (topCompanyId != null) {
|
||||||
|
reqVO.setCompanyId(topCompanyId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (StrUtil.isNotBlank(reqVO.getBusinessType())) {
|
||||||
|
reqVO.setBusinessType(reqVO.getBusinessType().trim().toUpperCase());
|
||||||
|
}
|
||||||
|
if (StrUtil.isNotBlank(reqVO.getExternalSystem())) {
|
||||||
|
reqVO.setExternalSystem(reqVO.getExternalSystem().trim().toUpperCase());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查找部门的顶级公司ID
|
||||||
|
*
|
||||||
|
* @param deptId 部门ID
|
||||||
|
* @return 顶级公司ID,如果不存在返回 null
|
||||||
|
*/
|
||||||
|
private Long findTopCompanyId(Long deptId) {
|
||||||
|
if (deptId == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeptDO dept = deptMapper.selectById(deptId);
|
||||||
|
if (dept == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归向上查找,直到找到公司节点或者parentId为空/0
|
||||||
|
Long currentDeptId = deptId;
|
||||||
|
while (currentDeptId != null) {
|
||||||
|
DeptDO currentDept = deptMapper.selectById(currentDeptId);
|
||||||
|
if (currentDept == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果当前节点是公司,返回其ID
|
||||||
|
if (Boolean.TRUE.equals(currentDept.getIsCompany())) {
|
||||||
|
return currentDept.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有父节点或父节点为0,结束查找
|
||||||
|
if (currentDept.getParentId() == null || currentDept.getParentId() == 0L) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 继续向上查找
|
||||||
|
currentDeptId = currentDept.getParentId();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.zt.plat.module.system.service.sync;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步iWork当日修改的用户数据
|
||||||
|
*/
|
||||||
|
public interface SyncIWorkUserChangeService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步入口
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
int process();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
package com.zt.plat.module.system.service.sync;
|
||||||
|
|
||||||
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkFullSyncReqVO;
|
||||||
|
import com.zt.plat.module.system.controller.admin.integration.iwork.vo.IWorkFullSyncRespVO;
|
||||||
|
import com.zt.plat.module.system.service.integration.iwork.IWorkSyncService;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class SyncIWorkUserChangeServiceImpl implements SyncIWorkUserChangeService {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private IWorkSyncService iWorkSyncService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int process() {
|
||||||
|
IWorkFullSyncReqVO reqVO = new IWorkFullSyncReqVO();
|
||||||
|
reqVO.setPageSize(10);
|
||||||
|
// 设置修改日期的查询条件为当日0时起
|
||||||
|
ZoneId zone = ZoneId.of("Asia/Shanghai");
|
||||||
|
String startOfToday = LocalDate.now(zone)
|
||||||
|
.atStartOfDay(zone)
|
||||||
|
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
reqVO.setModified(startOfToday);
|
||||||
|
IWorkFullSyncRespVO respVO = iWorkSyncService.fullSyncUsers(reqVO);
|
||||||
|
if(respVO!=null && respVO.getProcessedPages()!=null && respVO.getPageSize()!=null)
|
||||||
|
return respVO.getProcessedPages() * respVO.getPageSize();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user