selectUnsyncedRevokelistBySlice(@Param("lastRevlistId") String lastRevlistId, @Param("pageSize") int pageSize);
+
}
diff --git a/src/main/java/com/chinaweal/aiccs/aiccs/revoke/schedule/RevokeSyncScheduled.java b/src/main/java/com/chinaweal/aiccs/aiccs/revoke/schedule/RevokeSyncScheduled.java
new file mode 100644
index 0000000..dda0428
--- /dev/null
+++ b/src/main/java/com/chinaweal/aiccs/aiccs/revoke/schedule/RevokeSyncScheduled.java
@@ -0,0 +1,237 @@
+package com.chinaweal.aiccs.aiccs.revoke.schedule;
+
+import com.chinaweal.aiccs.aiccs.entbase.entity.TREntBase;
+import com.chinaweal.aiccs.aiccs.entbase.service.TREntBaseService;
+import com.chinaweal.aiccs.aiccs.revoke.entity.EGtRevoke;
+import com.chinaweal.aiccs.aiccs.revoke.entity.ERevoke;
+import com.chinaweal.aiccs.aiccs.revoke.entity.Revokelist;
+import com.chinaweal.aiccs.aiccs.revoke.mapper.RevokelistMapper;
+import com.chinaweal.aiccs.aiccs.revoke.service.IEGtRevokeService;
+import com.chinaweal.aiccs.aiccs.revoke.service.IERevokeService;
+import com.chinaweal.aiccs.redis.RedisService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * 吊销数据同步定时任务
+ *
+ * 扫描REVOKELIST表,将未同步的数据根据市场主体类型分别写入E_REVOKE表或E_GT_REVOKE表
+ * - 个体户(enttype为9500或9910)写入E_GT_REVOKE表
+ * - 其他市场主体写入E_REVOKE表
+ *
+ * @author system
+ * @since 2026-03-27
+ */
+@Slf4j
+@Configuration
+@EnableScheduling
+public class RevokeSyncScheduled {
+
+ /**
+ * Redis锁key
+ */
+ private static final String REDIS_LOCK_KEY = "schedule:syncRevokeData:lock";
+
+ /**
+ * Redis锁超时时间(秒)
+ */
+ private static final int REDIS_LOCK_TIMEOUT = 30 * 60; // 30分钟
+
+ /**
+ * 个体户类型编码
+ */
+ private static final String ENTTYPE_INDIVIDUAL_9500 = "9500";
+ private static final String ENTTYPE_INDIVIDUAL_9910 = "9910";
+
+ @Autowired
+ private RevokelistMapper revokelistMapper;
+
+ @Autowired
+ private IERevokeService eRevokeService;
+
+ @Autowired
+ private IEGtRevokeService eGtRevokeService;
+
+ @Autowired
+ private TREntBaseService trEntBaseService;
+
+ @Autowired
+ private RedisService redisService;
+
+ /**
+ * 定时同步吊销数据
+ * 将REVOKELIST表中未同步的数据根据市场主体类型分别写入E_REVOKE或E_GT_REVOKE表
+ */
+ @Scheduled(cron = "${scheduling.cron.syncRevokeData:-}")
+ @Transactional(rollbackFor = Exception.class)
+ public void syncRevokeData() {
+ // 检查Redis并发锁
+ if (!acquireLock()) {
+ log.warn("【吊销数据同步任务】上一次执行尚未完成或锁已存在,本次跳过");
+ return;
+ }
+
+ try {
+ doSync();
+ } catch (Exception e) {
+ log.error("【吊销数据同步任务】执行异常:{}", e.getMessage(), e);
+ throw e;
+ } finally {
+ releaseLock();
+ }
+ }
+
+ /**
+ * 执行数据同步
+ */
+ private void doSync() {
+ log.info("【吊销数据同步任务】开始执行");
+
+ int pageSize = 100;
+ int successCount = 0;
+ int failCount = 0;
+ int batchNum = 0;
+ String lastRevlistId = null;
+
+ while (true) {
+ // 切片查询未同步的记录
+ List unsyncedList = getUnsynchronizedRevokelist(lastRevlistId, pageSize);
+ if (unsyncedList.isEmpty()) {
+ log.info("【吊销数据同步任务】没有更多需要同步的数据,任务结束");
+ break;
+ }
+
+ batchNum++;
+ log.info("【吊销数据同步任务】正在处理第{}批,记录数:{}", batchNum, unsyncedList.size());
+
+ // 更新lastRevlistId为当前批次的最后一条记录主键
+ lastRevlistId = unsyncedList.get(unsyncedList.size() - 1).getRevlistid();
+
+ for (Revokelist revokelist : unsyncedList) {
+ try {
+ // 根据PRIPID查询市场主体详细信息
+ TREntBase entBase = trEntBaseService.getById(revokelist.getPripid());
+ if (entBase == null) {
+ log.warn("【吊销数据同步任务】市场主体信息不存在,PRIPID:{}", revokelist.getPripid());
+ failCount++;
+ continue;
+ }
+
+ String enttype = entBase.getEnttype();
+ LocalDateTime now = LocalDateTime.now();
+
+ // 根据市场主体类型判断写入目标表
+ if (isIndividual(enttype)) {
+ // 个体户写入E_GT_REVOKE表
+ EGtRevoke eGtRevoke = buildEGtRevoke(revokelist, now);
+ eGtRevokeService.save(eGtRevoke);
+ log.debug("【吊销数据同步任务】个体户数据已写入,PRIPID:{}", revokelist.getPripid());
+ } else {
+ // 其他市场主体写入E_REVOKE表
+ ERevoke eRevoke = buildERevoke(revokelist, now);
+ eRevokeService.save(eRevoke);
+ log.debug("【吊销数据同步任务】企业数据已写入,PRIPID:{}", revokelist.getPripid());
+ }
+ successCount++;
+ } catch (Exception e) {
+ log.error("【吊销数据同步任务】数据同步失败,PRIPID:{},错误信息:{}", revokelist.getPripid(), e.getMessage(), e);
+ failCount++;
+ }
+ }
+ }
+
+ log.info("【吊销数据同步任务】执行完成,共处理{}批,成功:{},失败:{}", batchNum, successCount, failCount);
+ }
+
+ /**
+ * 获取分布式锁
+ *
+ * @return true-获取锁成功,false-锁已存在
+ */
+ private boolean acquireLock() {
+ // 检查锁是否存在
+ if (redisService.exists(REDIS_LOCK_KEY)) {
+ return false;
+ }
+ // 设置锁,30分钟超时
+ redisService.set(REDIS_LOCK_KEY, "1", REDIS_LOCK_TIMEOUT);
+ return true;
+ }
+
+ /**
+ * 释放分布式锁
+ */
+ private void releaseLock() {
+ redisService.remove(REDIS_LOCK_KEY);
+ log.debug("【吊销数据同步任务】Redis锁已释放");
+ }
+
+ /**
+ * 切片查询未同步的REVOKELIST记录
+ * 使用EXISTS语句判断E_REVOKE和E_GT_REVOKE表是否已存在该PRIPID
+ *
+ * @param lastRevlistId 上一次查询的最后一条主键ID,初始为null
+ * @param pageSize 每页记录数
+ * @return 未同步的REVOKELIST记录列表
+ */
+ private List getUnsynchronizedRevokelist(String lastRevlistId, int pageSize) {
+ return revokelistMapper.selectUnsyncedRevokelistBySlice(lastRevlistId, pageSize);
+ }
+
+ /**
+ * 判断是否为个体户
+ *
+ * @param enttype 市场主体类型编码
+ * @return true-是个体户,false-不是个体户
+ */
+ private boolean isIndividual(String enttype) {
+ return ENTTYPE_INDIVIDUAL_9500.equals(enttype) || ENTTYPE_INDIVIDUAL_9910.equals(enttype);
+ }
+
+ /**
+ * 构建E_REVOKE实体
+ */
+ private ERevoke buildERevoke(Revokelist revokelist, LocalDateTime now) {
+ ERevoke eRevoke = new ERevoke();
+ eRevoke.setPripid(revokelist.getPripid());
+ // REVDATE字段映射:revokelist的REVOKEDATE转换为LocalDate
+ if (revokelist.getRevokedate() != null) {
+ eRevoke.setRevdate(revokelist.getRevokedate().toLocalDate());
+ }
+ // ILLEGACT字段映射:revokelist的REVOKEREA存储吊销原因
+ eRevoke.setIllegact(revokelist.getRevokeRea());
+ // REVAUTH字段映射:revokelist的PUNISHORGCN存储处罚机关
+ eRevoke.setRevauth(revokelist.getPunishOrgCn());
+ // REVBASIS字段:可以从CASENO或WRITSID获取,此处暂时留空
+ eRevoke.setRevbasis(null);
+ // S_EXT_FROMNODE字段:数据汇总单位,从LAUPTIME或其他字段获取
+ eRevoke.setSExtFromnode("150000");
+ eRevoke.setSExtDatatime(now);
+ return eRevoke;
+ }
+
+ /**
+ * 构建EGtRevoke实体
+ */
+ private EGtRevoke buildEGtRevoke(Revokelist revokelist, LocalDateTime now) {
+ EGtRevoke eGtRevoke = new EGtRevoke();
+ eGtRevoke.setPripid(revokelist.getPripid());
+ // REVREA字段映射:revokelist的REVOKEREA存储吊销原因
+ eGtRevoke.setRevrea(revokelist.getRevokeRea());
+ // REVDATE字段映射:revokelist的REVOKEDATE转换为LocalDate
+ if (revokelist.getRevokedate() != null) {
+ eGtRevoke.setRevdate(revokelist.getRevokedate().toLocalDate());
+ }
+ // S_EXT_FROMNODE字段:数据汇总单位
+ eGtRevoke.setSExtFromnode("150000");
+ eGtRevoke.setSExtDatatime(now);
+ return eGtRevoke;
+ }
+}
diff --git a/src/main/java/com/chinaweal/aiccs/aiccs/revoke/service/IEGtRevokeService.java b/src/main/java/com/chinaweal/aiccs/aiccs/revoke/service/IEGtRevokeService.java
new file mode 100644
index 0000000..5f209fc
--- /dev/null
+++ b/src/main/java/com/chinaweal/aiccs/aiccs/revoke/service/IEGtRevokeService.java
@@ -0,0 +1,25 @@
+package com.chinaweal.aiccs.aiccs.revoke.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.chinaweal.aiccs.aiccs.revoke.entity.EGtRevoke;
+
+import java.util.List;
+
+/**
+ *
+ * 个体吊销信息表 服务类
+ *
+ *
+ * @author system
+ * @since 2026-03-27
+ */
+public interface IEGtRevokeService extends IService {
+
+ /**
+ * 根据主体身份代码查询
+ *
+ * @param pripid 主体身份代码
+ * @return 个体吊销信息列表
+ */
+ List selectByPripid(String pripid);
+}
diff --git a/src/main/java/com/chinaweal/aiccs/aiccs/revoke/service/IERevokeService.java b/src/main/java/com/chinaweal/aiccs/aiccs/revoke/service/IERevokeService.java
new file mode 100644
index 0000000..43b50ff
--- /dev/null
+++ b/src/main/java/com/chinaweal/aiccs/aiccs/revoke/service/IERevokeService.java
@@ -0,0 +1,25 @@
+package com.chinaweal.aiccs.aiccs.revoke.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.chinaweal.aiccs.aiccs.revoke.entity.ERevoke;
+
+import java.util.List;
+
+/**
+ *
+ * 吊销信息表 服务类
+ *
+ *
+ * @author system
+ * @since 2026-03-27
+ */
+public interface IERevokeService extends IService {
+
+ /**
+ * 根据主体身份代码查询
+ *
+ * @param pripid 主体身份代码
+ * @return 吊销信息列表
+ */
+ List selectByPripid(String pripid);
+}
diff --git a/src/main/java/com/chinaweal/aiccs/aiccs/revoke/service/impl/EGtRevokeServiceImpl.java b/src/main/java/com/chinaweal/aiccs/aiccs/revoke/service/impl/EGtRevokeServiceImpl.java
new file mode 100644
index 0000000..4802f3c
--- /dev/null
+++ b/src/main/java/com/chinaweal/aiccs/aiccs/revoke/service/impl/EGtRevokeServiceImpl.java
@@ -0,0 +1,26 @@
+package com.chinaweal.aiccs.aiccs.revoke.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.chinaweal.aiccs.aiccs.revoke.entity.EGtRevoke;
+import com.chinaweal.aiccs.aiccs.revoke.mapper.EGtRevokeMapper;
+import com.chinaweal.aiccs.aiccs.revoke.service.IEGtRevokeService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ *
+ * 个体吊销信息表 服务实现类
+ *
+ *
+ * @author system
+ * @since 2026-03-27
+ */
+@Service
+public class EGtRevokeServiceImpl extends ServiceImpl implements IEGtRevokeService {
+
+ @Override
+ public List selectByPripid(String pripid) {
+ return baseMapper.selectByPripid(pripid);
+ }
+}
diff --git a/src/main/java/com/chinaweal/aiccs/aiccs/revoke/service/impl/ERevokeServiceImpl.java b/src/main/java/com/chinaweal/aiccs/aiccs/revoke/service/impl/ERevokeServiceImpl.java
new file mode 100644
index 0000000..dc88144
--- /dev/null
+++ b/src/main/java/com/chinaweal/aiccs/aiccs/revoke/service/impl/ERevokeServiceImpl.java
@@ -0,0 +1,26 @@
+package com.chinaweal.aiccs.aiccs.revoke.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.chinaweal.aiccs.aiccs.revoke.entity.ERevoke;
+import com.chinaweal.aiccs.aiccs.revoke.mapper.ERevokeMapper;
+import com.chinaweal.aiccs.aiccs.revoke.service.IERevokeService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ *
+ * 吊销信息表 服务实现类
+ *
+ *
+ * @author system
+ * @since 2026-03-27
+ */
+@Service
+public class ERevokeServiceImpl extends ServiceImpl implements IERevokeService {
+
+ @Override
+ public List selectByPripid(String pripid) {
+ return baseMapper.selectByPripid(pripid);
+ }
+}
diff --git a/src/main/java/com/chinaweal/aiccs/aiccs/revoke/service/impl/TsbizrevlistServiceImpl.java b/src/main/java/com/chinaweal/aiccs/aiccs/revoke/service/impl/TsbizrevlistServiceImpl.java
index 610b272..6f2126e 100644
--- a/src/main/java/com/chinaweal/aiccs/aiccs/revoke/service/impl/TsbizrevlistServiceImpl.java
+++ b/src/main/java/com/chinaweal/aiccs/aiccs/revoke/service/impl/TsbizrevlistServiceImpl.java
@@ -30,6 +30,7 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
import javax.servlet.ServletOutputStream;
import java.io.File;
@@ -355,6 +356,7 @@ public class TsbizrevlistServiceImpl extends BaseServiceImpl pripids = dto.getPripids();
diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml
index 5230eaa..9862342 100644
--- a/src/main/resources/application-dev.yml
+++ b/src/main/resources/application-dev.yml
@@ -156,6 +156,7 @@ scheduling:
staticHqlcusers: 0 30 00 * * ? #定时获取浪潮用户
forceDeregisterNoticeExpired: '-' #拟强制注销公告期满更新定时任务
+ syncRevokeData: '-' #吊销数据同步任务(同步REVOKELIST到E_REVOKE和E_GT_REVOKE表)
ot:
bakCseDownloadPath: /ot/download/case
bakPermitDownloadPath: /ot/download/permit
diff --git a/src/main/resources/mybatis/mapper/aiccs/revoke/EGtRevokeMapper.xml b/src/main/resources/mybatis/mapper/aiccs/revoke/EGtRevokeMapper.xml
new file mode 100644
index 0000000..75d7e64
--- /dev/null
+++ b/src/main/resources/mybatis/mapper/aiccs/revoke/EGtRevokeMapper.xml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PRIPID, REVREA, REVDATE, S_EXT_FROMNODE, S_EXT_DATATIME
+
+
+
+
+
diff --git a/src/main/resources/mybatis/mapper/aiccs/revoke/ERevokeMapper.xml b/src/main/resources/mybatis/mapper/aiccs/revoke/ERevokeMapper.xml
new file mode 100644
index 0000000..6a324a6
--- /dev/null
+++ b/src/main/resources/mybatis/mapper/aiccs/revoke/ERevokeMapper.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PRIPID, REVDATE, ILLEGACT, REVAUTH, REVBASIS, S_EXT_FROMNODE, S_EXT_DATATIME
+
+
+
+
+
diff --git a/src/main/resources/mybatis/mapper/aiccs/revoke/RevokelistMapper.xml b/src/main/resources/mybatis/mapper/aiccs/revoke/RevokelistMapper.xml
index 104789b..a66abfc 100644
--- a/src/main/resources/mybatis/mapper/aiccs/revoke/RevokelistMapper.xml
+++ b/src/main/resources/mybatis/mapper/aiccs/revoke/RevokelistMapper.xml
@@ -65,5 +65,19 @@
order by REVOKEDATE desc
+
+