diff --git a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/constant/SmHotelDownstreamPushKind.java b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/constant/SmHotelDownstreamPushKind.java
index 3c03f41d..f80760c0 100644
--- a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/constant/SmHotelDownstreamPushKind.java
+++ b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/constant/SmHotelDownstreamPushKind.java
@@ -3,16 +3,24 @@ package com.bsd.pjcloud.supermarket.constant;
/**
* 下游资源推送分类(环启等):可售推 / 关房推 / 纯跳过。
* 见 docs/xiayou/环启下游对接总览.md §5.1
+ *
+ * 圣诺特例:有 eid 后禁止因无产品/无日历 SKIP,应走 CLOSE(pushHotelClose)清对方旧价。
*/
public final class SmHotelDownstreamPushKind {
/** 上架且有产品且窗口内有日历 → 正常推本地价态 */
public static final String SELL = "SELL";
- /** 仍有产品,但已下架或窗口内无日历 → 推窗口内 dailyStatus=0,清对方旧价 */
+ /**
+ * 清对方旧价:下架、窗口无日历;圣诺在无产品时也走关房(对方可能仍有旧 plan)。
+ * 环启等仍通常要求本地有产品才能组关房报文。
+ */
public static final String CLOSE = "CLOSE";
- /** 本地已无产品 → 无法组关房报文,只记跳过 */
+ /**
+ * 纯跳过:酒店不存在;环启等无产品无法组关房;圣诺无 eid。
+ * 圣诺有 eid 时不应因无产品进入本态。
+ */
public static final String SKIP = "SKIP";
private SmHotelDownstreamPushKind() {
diff --git a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/dto/SmHotelShangyouChannelConfigDTO.java b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/dto/SmHotelShangyouChannelConfigDTO.java
index 078e3771..8e49918b 100644
--- a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/dto/SmHotelShangyouChannelConfigDTO.java
+++ b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/dto/SmHotelShangyouChannelConfigDTO.java
@@ -93,6 +93,12 @@ public class SmHotelShangyouChannelConfigDTO {
private Integer detailPullIntervalMs;
+ /** 全量详情酒店并发;建议 4~8 */
+ private Integer detailPullConcurrency;
+
+ /** 全量详情房价天数;≤0 用 priceDays;建议 15~30 */
+ private Integer detailPullPriceDays;
+
private Integer detailPullMaxHotels;
private Integer diffScanBatchSize;
diff --git a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/entity/SmHotelSyncLogEntity.java b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/entity/SmHotelSyncLogEntity.java
index 11768532..4980707c 100644
--- a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/entity/SmHotelSyncLogEntity.java
+++ b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/entity/SmHotelSyncLogEntity.java
@@ -27,6 +27,10 @@ public class SmHotelSyncLogEntity extends Model {
@Schema(description = "MANUAL / XXL / CRON")
private String triggerType;
+ /** 上游渠道 sheet_name,或下游全量推时的 partner_code;本地滚加为 local */
+ @Schema(description = "渠道/数据来源")
+ private String dataSource;
+
@Schema(description = "RUNNING / SUCCESS / FAILED")
private String status;
diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/config/ShangyouHotelProperties.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/config/ShangyouHotelProperties.java
index 04f6d4ea..ceefd11d 100644
--- a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/config/ShangyouHotelProperties.java
+++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/config/ShangyouHotelProperties.java
@@ -177,8 +177,20 @@ public class ShangyouHotelProperties {
/** 文档:全量房价两次间隔最少小时数 */
private int fullPriceSyncMinIntervalHours = 6;
- /** 全量拉详情:每家酒店间隔毫秒(防打爆上游;落库已批量,默认 50) */
- private int detailPullIntervalMs = 50;
+ /** 全量拉详情:每家酒店间隔毫秒(防打爆上游;并行时主要靠 price-api-qps,默认 0) */
+ private int detailPullIntervalMs = 0;
+
+ /**
+ * 全量拉详情并发度(酒店级并行)。对方房价约 20 QPS,建议 4~8;1=串行旧行为。
+ * 多实例时请降低,避免合计超限。
+ */
+ private int detailPullConcurrency = 6;
+
+ /**
+ * 全量拉详情房价天数;≤0 则用 {@link #priceDays}。
+ * 圣诺只推约 15 天时可配 15~30,比默认 90 天少 2/3 次 getRoomPrice。
+ */
+ private int detailPullPriceDays = 30;
/** 全量拉详情单次最多处理家数;0=不限制(慎用,酒店多时耗时长) */
private int detailPullMaxHotels = 0;
diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmHotelController.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmHotelController.java
index 82752fba..1b4e65dd 100644
--- a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmHotelController.java
+++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmHotelController.java
@@ -53,7 +53,7 @@ public class SmHotelController {
.eq(StrUtil.isNotBlank(query.getSheetName()), SmHotelEntity::getSheetName, query.getSheetName())
// 归属部门:渠道映射按部门推送时,便于按部门筛酒店核查
.eq(query.getDeptId() != null, SmHotelEntity::getDeptId, query.getDeptId())
- .orderByDesc(SmHotelEntity::getCreateTime)
+ // 默认按主键倒序:雪花 ID 近似创建时间,可走索引;避免无索引时 create_time 全表 filesort
.orderByDesc(SmHotelEntity::getId);
// 外部酒店ID/eid:推圣诺 getInfo 用 sHotelId,空时回落 hotelCode
if (StrUtil.isNotBlank(query.getSHotelId())) {
diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmHotelMidController.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmHotelMidController.java
index f624faf9..0b54c537 100644
--- a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmHotelMidController.java
+++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/controller/SmHotelMidController.java
@@ -149,10 +149,16 @@ public class SmHotelMidController {
@GetMapping("/mid/pushScope/preview")
@PreAuthorize("@pms.hasPermission('supermarket_smHotel_sync')")
public R