diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmHotelDownstreamPushLogServiceImpl.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmHotelDownstreamPushLogServiceImpl.java index 08af89af..0769d4a5 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmHotelDownstreamPushLogServiceImpl.java +++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmHotelDownstreamPushLogServiceImpl.java @@ -26,15 +26,24 @@ public class SmHotelDownstreamPushLogServiceImpl @Override public Page pageLogs(Page page, SmHotelDownstreamPushLogEntity query) { + // 列表不查 request_body/response_body(mediumtext):全量推后行数暴涨,带大字段会极慢;详情再查全文 + String partner = query == null ? null : query.getPartnerCode(); + Long syncLogId = query == null ? null : query.getSyncLogId(); + Long hotelId = query == null ? null : query.getHotelId(); + String extHotelId = query == null ? null : query.getExtHotelId(); + String action = query == null ? null : query.getAction(); + String success = query == null ? null : query.getSuccess(); return baseMapper.selectPage(page, Wrappers.lambdaQuery() - .eq(StrUtil.isNotBlank(query.getPartnerCode()), SmHotelDownstreamPushLogEntity::getPartnerCode, - query.getPartnerCode()) - .eq(query.getSyncLogId() != null, SmHotelDownstreamPushLogEntity::getSyncLogId, query.getSyncLogId()) - .eq(query.getHotelId() != null, SmHotelDownstreamPushLogEntity::getHotelId, query.getHotelId()) - .eq(StrUtil.isNotBlank(query.getExtHotelId()), SmHotelDownstreamPushLogEntity::getExtHotelId, - query.getExtHotelId()) - .eq(StrUtil.isNotBlank(query.getAction()), SmHotelDownstreamPushLogEntity::getAction, query.getAction()) - .eq(StrUtil.isNotBlank(query.getSuccess()), SmHotelDownstreamPushLogEntity::getSuccess, query.getSuccess()) + .select(SmHotelDownstreamPushLogEntity.class, info -> { + String col = info.getColumn(); + return !"request_body".equalsIgnoreCase(col) && !"response_body".equalsIgnoreCase(col); + }) + .eq(StrUtil.isNotBlank(partner), SmHotelDownstreamPushLogEntity::getPartnerCode, partner) + .eq(syncLogId != null, SmHotelDownstreamPushLogEntity::getSyncLogId, syncLogId) + .eq(hotelId != null, SmHotelDownstreamPushLogEntity::getHotelId, hotelId) + .eq(StrUtil.isNotBlank(extHotelId), SmHotelDownstreamPushLogEntity::getExtHotelId, extHotelId) + .eq(StrUtil.isNotBlank(action), SmHotelDownstreamPushLogEntity::getAction, action) + .eq(StrUtil.isNotBlank(success), SmHotelDownstreamPushLogEntity::getSuccess, success) .orderByDesc(SmHotelDownstreamPushLogEntity::getCreateTime)); } diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmHotelMidServiceImpl.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmHotelMidServiceImpl.java index 1cdfd4c6..55a6f5d1 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmHotelMidServiceImpl.java +++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmHotelMidServiceImpl.java @@ -451,6 +451,19 @@ public class SmHotelMidServiceImpl implements SmHotelMidService { Map one; if (SmHotelDownstreamPushKind.isClose(kind)) { one = closeHotelDailyToPartner(hotel, partner, null); + // 圣诺 getInfo 确认对方无店时关房会跳过,按 skip 统计,不算失败 + if (Boolean.TRUE.equals(one.get("skipped"))) { + one.put("partnerCode", partner); + one.put("pushKind", SmHotelDownstreamPushKind.SKIP); + Map result = new HashMap<>(8); + result.put("pushKind", SmHotelDownstreamPushKind.SKIP); + result.put("skipped", true); + result.put("skipReason", one.get("skipReason")); + result.put("partners", List.of(partner)); + result.put("partnerResults", List.of(one)); + result.put("partnerErrors", Collections.emptyList()); + return R.ok(result); + } one.put("pushKind", SmHotelDownstreamPushKind.CLOSE); one.put("closed", true); } @@ -552,7 +565,7 @@ public class SmHotelMidServiceImpl implements SmHotelMidService { /** * 可售推 / 关房推 / 纯跳过(总览 §5.1)。 * SKIP:无酒店或无产品;CLOSE:有产品但下架或窗口无日历;SELL:上架+有产品+窗口有日历。 - * 圣诺:未填外部酒店ID(sHotelId/eid) 不调对方接口;关房仅在已有 ns 映射时可继续。 + * 圣诺:未填外部酒店ID(sHotelId/eid) 不调对方接口(可售/关房均跳过)。 */ private String resolveDownstreamPushKind(SmHotelEntity hotel, String partnerCode) { if (hotel == null) { @@ -564,6 +577,10 @@ public class SmHotelMidServiceImpl implements SmHotelMidService { if (productCount == null || productCount <= 0) { return SmHotelDownstreamPushKind.SKIP; } + // 圣诺无 eid:对方无法认店,关房也会「更新失败」,直接跳过 + if (isShengnuoPartner(partnerCode) && StrUtil.isBlank(StrUtil.trim(hotel.getSHotelId()))) { + return SmHotelDownstreamPushKind.SKIP; + } boolean offline = "OFFLINE".equalsIgnoreCase(hotel.getUpstreamStatus()); LocalDate[] window = resolveDownstreamDailyWindow(partnerCode); Long dailyCount = dailyMapper.selectCount(Wrappers.lambdaQuery() @@ -571,15 +588,7 @@ public class SmHotelMidServiceImpl implements SmHotelMidService { .ge(SmHotelDailyEntity::getStayDate, window[0]) .le(SmHotelDailyEntity::getStayDate, window[1])); boolean hasDaily = dailyCount != null && dailyCount > 0; - boolean needClose = offline || !hasDaily; - if (isShengnuoPartner(partnerCode) && StrUtil.isBlank(StrUtil.trim(hotel.getSHotelId()))) { - // 可售推必须 getInfo(eid),无 eid 直接跳过;关房仅 Redis 已有 nsHotelId 时可不调 getInfo - if (needClose && hasShengnuoNsMapping(partnerCode, hotelId)) { - return SmHotelDownstreamPushKind.CLOSE; - } - return SmHotelDownstreamPushKind.SKIP; - } - if (needClose) { + if (offline || !hasDaily) { return SmHotelDownstreamPushKind.CLOSE; } return SmHotelDownstreamPushKind.SELL; @@ -605,15 +614,6 @@ public class SmHotelMidServiceImpl implements SmHotelMidService { return ds != null && SmHotelDownstreamProtocol.isShengnuo(ds.getProtocol()); } - /** 圣诺本地↔nsHotelId 缓存是否已存在(关房可不依赖 eid) */ - private boolean hasShengnuoNsMapping(String partnerCode, Long hotelId) { - if (StrUtil.isBlank(partnerCode) || hotelId == null) { - return false; - } - cn.hutool.json.JSONObject cached = shengnuoIdMappingCache.getByLocal(partnerCode, hotelId); - return cached != null && cached.getLong("nsHotelId", 0L) > 0; - } - /** * 关房推:环启推 dailyStatus=0;慧订推空价态窗口(对方打满房)。 * @param onlyProducts 非空时只关这些产品(环启);慧订忽略,整窗清空 @@ -834,22 +834,66 @@ public class SmHotelMidServiceImpl implements SmHotelMidService { summary); } - /** 圣诺关房:pushHotelClose(整店) */ + /** + * 圣诺关房:先 getInfo(eid) 确认对方有店,再 pushHotelClose。 + * 对方无档/getInfo 失败 → 跳过关房,避免无意义「更新失败」。 + */ private Map closeHotelDailyToShengnuo(SmHotelEntity hotel, String partnerCode) { downstreamClient.assertPartnerReady(partnerCode); HotelDownstreamProperties ds = channelConfigService.resolveDownstreamRuntime(partnerCode); - long nsHotelId = resolveShengnuoHotelId(partnerCode, ds, hotel); + String eid = StrUtil.trim(hotel.getSHotelId()); + if (StrUtil.isBlank(eid)) { + String reason = "未填外部酒店ID(sHotelId/eid),跳过圣诺关房"; + recordDownstreamPushSkip(partnerCode, hotel, reason); + Map skip = new HashMap<>(6); + skip.put("protocol", SmHotelDownstreamProtocol.SHENGNUO); + skip.put("skipped", true); + skip.put("skipReason", reason); + skip.put("dailyCloseCount", 0); + return skip; + } + long nsHotelId; + try { + cn.hutool.json.JSONObject infoResp = shengnuoAdapter.getInfo(partnerCode, ds, eid); + cn.hutool.json.JSONObject infoData = infoResp == null ? null : infoResp.getJSONObject("data"); + nsHotelId = infoData == null ? 0L : infoData.getLong("id", 0L); + } + catch (Exception ex) { + String reason = "圣诺侧无此酒店或 getInfo 失败,跳过关房(eid=" + eid + "):" + ex.getMessage(); + recordDownstreamPushSkip(partnerCode, hotel, reason); + log.info("|下游关房推送[圣诺]|跳过|hotelId={}|partner={}|eid={}|err={}|", hotel.getId(), partnerCode, eid, + ex.getMessage()); + Map skip = new HashMap<>(6); + skip.put("protocol", SmHotelDownstreamProtocol.SHENGNUO); + skip.put("skipped", true); + skip.put("skipReason", reason); + skip.put("dailyCloseCount", 0); + return skip; + } + if (nsHotelId <= 0) { + String reason = "圣诺 getInfo 未返回酒店 id,跳过关房 eid=" + eid; + recordDownstreamPushSkip(partnerCode, hotel, reason); + Map skip = new HashMap<>(6); + skip.put("protocol", SmHotelDownstreamProtocol.SHENGNUO); + skip.put("skipped", true); + skip.put("skipReason", reason); + skip.put("dailyCloseCount", 0); + return skip; + } Map body = new LinkedHashMap<>(shengnuoAdapter.signedBase(ds)); body.put("id", nsHotelId); shengnuoAdapter.pushHotelClose(partnerCode, ds, hotel.getId(), String.valueOf(nsHotelId), body); - log.info("|下游关房推送[圣诺]|hotelId={}|partner={}|nsHotelId={}|", hotel.getId(), partnerCode, nsHotelId); + log.info("|下游关房推送[圣诺]|hotelId={}|partner={}|nsHotelId={}|eid={}|", hotel.getId(), partnerCode, nsHotelId, + eid); Map result = new HashMap<>(6); result.put("protocol", SmHotelDownstreamProtocol.SHENGNUO); result.put("nsHotelId", nsHotelId); + result.put("eid", eid); result.put("dailyCloseCount", 1); return result; } + /** 可售推等仍可用缓存 nsHotelId;关房已改为强制 getInfo 验活 */ private long resolveShengnuoHotelId(String partnerCode, HotelDownstreamProperties ds, SmHotelEntity hotel) { cn.hutool.json.JSONObject cached = shengnuoIdMappingCache.getByLocal(partnerCode, hotel.getId()); if (cached != null) { @@ -858,11 +902,9 @@ public class SmHotelMidServiceImpl implements SmHotelMidService { return id; } } - // 无缓存时只能靠真实 eid 调 getInfo;禁止 hotelCode 回落 String eid = StrUtil.trim(hotel.getSHotelId()); if (StrUtil.isBlank(eid)) { - throw new IllegalArgumentException("圣诺关房缺少外部酒店ID(sHotelId)且无本地映射,跳过调接口 hotelId=" - + hotel.getId()); + throw new IllegalArgumentException("圣诺缺少外部酒店ID(sHotelId)且无本地映射 hotelId=" + hotel.getId()); } cn.hutool.json.JSONObject infoResp = shengnuoAdapter.getInfo(partnerCode, ds, eid); cn.hutool.json.JSONObject infoData = infoResp == null ? null : infoResp.getJSONObject("data");