From 73314b1cc4089d8dfc5b3b6e0849edd78321cf99 Mon Sep 17 00:00:00 2001 From: zjf <1799650030@qq.com> Date: Fri, 13 Nov 2026 17:52:22 +0800 Subject: [PATCH] =?UTF-8?q?=E9=85=92=E5=BA=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feign/RemoteSmHotelFxScheduleService.java | 24 ++++++++ ...mework.cloud.openfeign.FeignClient.imports | 4 ++ .../SmHotelFxScheduleInnerController.java | 61 +++++++++++++++++++ .../job/SmHotelFxCommissionLockSchedule.java | 5 +- .../job/SmHotelFxDemoteSchedule.java | 5 +- .../service/impl/SmHotelSyncServiceImpl.java | 5 +- pjcloud-visual/pjcloud-daemon-quartz/pom.xml | 6 ++ .../daemon/quartz/task/SmHotelFxTask.java | 56 +++++++++++++++++ 8 files changed, 161 insertions(+), 5 deletions(-) create mode 100644 pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/api/feign/RemoteSmHotelFxScheduleService.java create mode 100644 pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmHotelFxScheduleInnerController.java create mode 100644 pjcloud-visual/pjcloud-daemon-quartz/src/main/java/com/bsd/pjcloud/daemon/quartz/task/SmHotelFxTask.java diff --git a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/api/feign/RemoteSmHotelFxScheduleService.java b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/api/feign/RemoteSmHotelFxScheduleService.java new file mode 100644 index 000000000..32e4b8e5d --- /dev/null +++ b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/api/feign/RemoteSmHotelFxScheduleService.java @@ -0,0 +1,24 @@ +package com.bsd.pjcloud.supermarket.api.feign; + +import com.bsd.pjcloud.common.core.constant.ServiceNameConstants; +import com.bsd.pjcloud.common.core.util.R; +import com.bsd.pjcloud.common.feign.annotation.NoToken; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; + +/** + * 酒店分销定时:daemon-quartz 集群触发,supermarket 执行业务。 + */ +@FeignClient(contextId = "remoteSmHotelFxScheduleService", value = ServiceNameConstants.SUPERMARKET_SERVICE) +public interface RemoteSmHotelFxScheduleService { + + /** 退房 T+1:预计佣金 → 锁定;返回本批锁定条数 */ + @NoToken + @PostMapping("/inner/smHotelFx/schedule/lockDueCommissions") + R lockDueCommissions(); + + /** 二级保级窗口到期:未达门槛降三级;返回处理条数 */ + @NoToken + @PostMapping("/inner/smHotelFx/schedule/processDueDemotions") + R processDueDemotions(); +} diff --git a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/resources/META-INF/spring/org.springframework.cloud.openfeign.FeignClient.imports b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/resources/META-INF/spring/org.springframework.cloud.openfeign.FeignClient.imports index 191afdcd8..6dce906df 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/resources/META-INF/spring/org.springframework.cloud.openfeign.FeignClient.imports +++ b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/resources/META-INF/spring/org.springframework.cloud.openfeign.FeignClient.imports @@ -5,3 +5,7 @@ com.bsd.pjcloud.supermarket.api.feign.RemoteSupermarketUnitSkuService com.bsd.pjcloud.supermarket.api.feign.RemoteShopCategoryService com.bsd.pjcloud.supermarket.api.feign.RemoteShopSpuService com.bsd.pjcloud.supermarket.api.feign.RemoteShopSkuService +com.bsd.pjcloud.supermarket.api.feign.RemoteSmHotelFxScheduleService +com.bsd.pjcloud.supermarket.api.feign.RemoteSmHotelFxInviteService +com.bsd.pjcloud.supermarket.api.feign.RemoteSmHotelOrderService +com.bsd.pjcloud.supermarket.api.feign.RemoteSmHotelOrderCheckoutQueryService diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmHotelFxScheduleInnerController.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmHotelFxScheduleInnerController.java new file mode 100644 index 000000000..037b7cb80 --- /dev/null +++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmHotelFxScheduleInnerController.java @@ -0,0 +1,61 @@ +package com.bsd.pjcloud.supermarket.controller; + +import com.bsd.pjcloud.common.core.util.R; +import com.bsd.pjcloud.common.data.tenant.TenantBroker; +import com.bsd.pjcloud.common.feign.annotation.NoToken; +import com.bsd.pjcloud.common.security.annotation.Inner; +import com.bsd.pjcloud.supermarket.service.SmHotelFxAgentService; +import com.bsd.pjcloud.supermarket.service.SmHotelFxCommissionService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 酒店分销定时任务内部入口:供 daemon-quartz 集群单次触发,避免 supermarket 多实例 + * {@code @Scheduled} 重复跑。 + */ +@Slf4j +@RestController +@RequiredArgsConstructor +@RequestMapping("/inner/smHotelFx/schedule") +@Tag(name = "酒店分销-内部定时") +public class SmHotelFxScheduleInnerController { + + private final SmHotelFxCommissionService commissionService; + + private final SmHotelFxAgentService agentService; + + @Value("${sm-hotel.fx.tenant-id:1}") + private Long tenantId; + + @Inner + @NoToken + @Operation(summary = "内部触发退房T+1佣金锁定") + @PostMapping("/lockDueCommissions") + public R lockDueCommissions() { + Long tid = tenantId == null ? 1L : tenantId; + int n = TenantBroker.applyAs(tid, t -> commissionService.lockDueCommissions()); + if (n > 0) { + log.info("|酒店分销|Quartz触发T+1锁定|tenant={}|count={}|", tid, n); + } + return R.ok(n); + } + + @Inner + @NoToken + @Operation(summary = "内部触发二级保级到期处理") + @PostMapping("/processDueDemotions") + public R processDueDemotions() { + Long tid = tenantId == null ? 1L : tenantId; + int n = TenantBroker.applyAs(tid, t -> agentService.processDueDemotions()); + if (n > 0) { + log.info("|酒店分销|Quartz触发二级降级|tenant={}|count={}|", tid, n); + } + return R.ok(n); + } +} diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/job/SmHotelFxCommissionLockSchedule.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/job/SmHotelFxCommissionLockSchedule.java index e809cb30c..67289b954 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/job/SmHotelFxCommissionLockSchedule.java +++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/job/SmHotelFxCommissionLockSchedule.java @@ -9,7 +9,8 @@ import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; /** - * 退房 T+1 锁定预计佣金:默认每天 01:15。 + * 退房 T+1 锁定预计佣金(本地兜底,默认关闭)。 + *

正式调度请走 daemon-quartz {@code smHotelFxTask#lockDueCommissions},避免集群多实例重复跑。 */ @Slf4j @Component @@ -18,7 +19,7 @@ public class SmHotelFxCommissionLockSchedule { private final SmHotelFxCommissionService commissionService; - @Value("${sm-hotel.fx.lock-schedule-enabled:true}") + @Value("${sm-hotel.fx.lock-schedule-enabled:false}") private boolean scheduleEnabled; @Value("${sm-hotel.fx.tenant-id:1}") diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/job/SmHotelFxDemoteSchedule.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/job/SmHotelFxDemoteSchedule.java index 4eb1ed072..72eeec7b6 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/job/SmHotelFxDemoteSchedule.java +++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/job/SmHotelFxDemoteSchedule.java @@ -9,7 +9,8 @@ import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; /** - * 二级区域保级考核:窗口到期未达 demoteMin 则降三级;达标则滚动新窗口。默认每天 02:15。 + * 二级区域保级考核(本地兜底,默认关闭)。 + *

正式调度请走 daemon-quartz {@code smHotelFxTask#processDueDemotions},避免集群多实例重复跑。 */ @Slf4j @Component @@ -18,7 +19,7 @@ public class SmHotelFxDemoteSchedule { private final SmHotelFxAgentService agentService; - @Value("${sm-hotel.fx.demote-schedule-enabled:true}") + @Value("${sm-hotel.fx.demote-schedule-enabled:false}") private boolean scheduleEnabled; @Value("${sm-hotel.fx.tenant-id:1}") diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmHotelSyncServiceImpl.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmHotelSyncServiceImpl.java index 4dea06ec7..3c808d09f 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmHotelSyncServiceImpl.java +++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmHotelSyncServiceImpl.java @@ -2289,10 +2289,13 @@ public class SmHotelSyncServiceImpl implements SmHotelSyncService { } } saveResumeIdx(logId, processed.get()); + String batchPushHint = !thenPush ? "" + : " 推成功 " + pushOk.get() + " 推失败 " + pushFail.get(); progressSnapshot(logId, total <= 0 ? 50 : Math.min(95, 5 + (int) (processed.get() * 90L / total)), "PULL", "拉取中 " + processed.get() + "/" + total + " 成功 " + ok.get() + " 失败 " - + fail.get() + " 跳过 " + skip.get(), + + fail.get() + " 跳过 " + skip.get() + batchPushHint + + (thenPush ? " 边拉边推→" + thenPushHint : ""), ok.get(), fail.get(), skip.get(), total, failLines); // 近窗批次间再让出一小段,减轻业务高峰抢连接 if (nearJob && intervalMs > 0 && i + batchSize < hotelIds.size()) { diff --git a/pjcloud-visual/pjcloud-daemon-quartz/pom.xml b/pjcloud-visual/pjcloud-daemon-quartz/pom.xml index 9b1dc84a4..e874c9d76 100644 --- a/pjcloud-visual/pjcloud-daemon-quartz/pom.xml +++ b/pjcloud-visual/pjcloud-daemon-quartz/pom.xml @@ -38,6 +38,12 @@ pjcloud-hardware-api 5.7.0 + + + com.bsd + pjcloud-supermarket-api + 5.7.0 + com.alibaba.cloud diff --git a/pjcloud-visual/pjcloud-daemon-quartz/src/main/java/com/bsd/pjcloud/daemon/quartz/task/SmHotelFxTask.java b/pjcloud-visual/pjcloud-daemon-quartz/src/main/java/com/bsd/pjcloud/daemon/quartz/task/SmHotelFxTask.java new file mode 100644 index 000000000..58526c24f --- /dev/null +++ b/pjcloud-visual/pjcloud-daemon-quartz/src/main/java/com/bsd/pjcloud/daemon/quartz/task/SmHotelFxTask.java @@ -0,0 +1,56 @@ +package com.bsd.pjcloud.daemon.quartz.task; + +import com.bsd.pjcloud.common.core.util.R; +import com.bsd.pjcloud.daemon.quartz.constants.PjcloudQuartzEnum; +import com.bsd.pjcloud.supermarket.api.feign.RemoteSmHotelFxScheduleService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * 酒店分销定时:sys_job(job_type=2,class_name=smHotelFxTask)→ Feign → supermarket。 + * Quartz 集群保证同一次触发只跑一台。 + */ +@Slf4j +@Component("smHotelFxTask") +@RequiredArgsConstructor +public class SmHotelFxTask { + + private final RemoteSmHotelFxScheduleService remoteSmHotelFxScheduleService; + + /** 退房 T+1 锁定预计佣金(默认建议 cron:0 15 1 * * ?) */ + public String lockDueCommissions() { + try { + R result = remoteSmHotelFxScheduleService.lockDueCommissions(); + if (result == null || !result.isOk()) { + log.error("|酒店分销|T+1锁定失败|code={}|msg={}|", result == null ? null : result.getCode(), + result == null ? "null" : result.getMsg()); + return PjcloudQuartzEnum.JOB_LOG_STATUS_FAIL.getType(); + } + log.info("|酒店分销|T+1锁定完成|count={}|", result.getData()); + return PjcloudQuartzEnum.JOB_LOG_STATUS_SUCCESS.getType(); + } + catch (Exception e) { + log.error("|酒店分销|T+1锁定异常|{}", e.getMessage(), e); + return PjcloudQuartzEnum.JOB_LOG_STATUS_FAIL.getType(); + } + } + + /** 二级保级到期处理(默认建议 cron:0 15 2 * * ?) */ + public String processDueDemotions() { + try { + R result = remoteSmHotelFxScheduleService.processDueDemotions(); + if (result == null || !result.isOk()) { + log.error("|酒店分销|二级降级失败|code={}|msg={}|", result == null ? null : result.getCode(), + result == null ? "null" : result.getMsg()); + return PjcloudQuartzEnum.JOB_LOG_STATUS_FAIL.getType(); + } + log.info("|酒店分销|二级降级完成|count={}|", result.getData()); + return PjcloudQuartzEnum.JOB_LOG_STATUS_SUCCESS.getType(); + } + catch (Exception e) { + log.error("|酒店分销|二级降级异常|{}", e.getMessage(), e); + return PjcloudQuartzEnum.JOB_LOG_STATUS_FAIL.getType(); + } + } +}