酒店
This commit is contained in:
1 parent
c02a897876
commit
1ee75e9104
2 files changed
+86
-8
No files matched your search
+2
-2
@@ -33,7 +33,7 @@ public class SmHotelDownstreamPushLogEntity extends Model<SmHotelDownstreamPushL
|
||||
@Schema(description = "外部酒店ID")
|
||||
private String extHotelId;
|
||||
|
||||
@Schema(description = "动作:hotel_sync/apartment_sync/product_sync/daily_sync/push_skip")
|
||||
@Schema(description = "动作:hotel_sync/apartment_sync/product_sync/daily_sync/push_skip/push_partial")
|
||||
private String action;
|
||||
|
||||
@Schema(description = "完整请求URL")
|
||||
@@ -51,7 +51,7 @@ public class SmHotelDownstreamPushLogEntity extends Model<SmHotelDownstreamPushL
|
||||
@Schema(description = "业务code")
|
||||
private Integer bizCode;
|
||||
|
||||
@Schema(description = "1成功 0失败 2跳过(下架/无产品/无日历等预检)")
|
||||
@Schema(description = "1成功 0失败 2跳过/部分未推上(预检跳过或 push_partial)")
|
||||
private String success;
|
||||
|
||||
@Schema(description = "失败摘要")
|
||||
|
||||
+84
-6
@@ -653,19 +653,41 @@ public class SmHotelMidServiceImpl implements SmHotelMidService {
|
||||
cn.hutool.json.JSONArray nsRooms = infoData.getJSONArray("rooms");
|
||||
Map<String, Long> roomTypeToNs = matchShengnuoRooms(hotelId, nsRooms);
|
||||
|
||||
List<SmHotelRoomEntity> localRooms = roomMapper.selectList(Wrappers.<SmHotelRoomEntity>lambdaQuery()
|
||||
.eq(SmHotelRoomEntity::getHotelId, hotelId));
|
||||
Map<String, String> roomNameByCode = new HashMap<>();
|
||||
List<String> unmatchedRooms = new ArrayList<>();
|
||||
for (SmHotelRoomEntity room : localRooms) {
|
||||
if (room == null || StrUtil.isBlank(room.getRoomTypeCode())) {
|
||||
continue;
|
||||
}
|
||||
roomNameByCode.put(room.getRoomTypeCode(), StrUtil.blankToDefault(room.getRoomTypeName(), ""));
|
||||
if (!roomTypeToNs.containsKey(room.getRoomTypeCode())) {
|
||||
unmatchedRooms.add(room.getRoomTypeCode()
|
||||
+ (StrUtil.isNotBlank(room.getRoomTypeName()) ? "/" + room.getRoomTypeName() : ""));
|
||||
}
|
||||
}
|
||||
|
||||
List<SmHotelProductEntity> products = productMapper.selectList(Wrappers.<SmHotelProductEntity>lambdaQuery()
|
||||
.eq(SmHotelProductEntity::getHotelId, hotelId)
|
||||
.isNotNull(SmHotelProductEntity::getProductCode));
|
||||
Map<String, Long> productToPlan = new LinkedHashMap<>();
|
||||
int planOk = 0;
|
||||
int productTotal = 0;
|
||||
List<String> planErrors = new ArrayList<>();
|
||||
for (SmHotelProductEntity p : products) {
|
||||
if (p == null || StrUtil.isBlank(p.getProductCode()) || StrUtil.isBlank(p.getRoomTypeCode())) {
|
||||
continue;
|
||||
}
|
||||
productTotal++;
|
||||
String productLabel = p.getProductCode()
|
||||
+ (StrUtil.isNotBlank(p.getProductName()) ? "/" + p.getProductName() : "");
|
||||
String roomLabel = p.getRoomTypeCode()
|
||||
+ (StrUtil.isNotBlank(roomNameByCode.get(p.getRoomTypeCode()))
|
||||
? "/" + roomNameByCode.get(p.getRoomTypeCode()) : "");
|
||||
Long nsRoomId = roomTypeToNs.get(p.getRoomTypeCode());
|
||||
if (nsRoomId == null) {
|
||||
planErrors.add(p.getProductCode() + ":无匹配圣诺房型");
|
||||
planErrors.add(productLabel + "(房型 " + roomLabel + "):无匹配圣诺房型,计划/价格均未推");
|
||||
continue;
|
||||
}
|
||||
int breakfast = p.getMealCount() == null ? 0 : Math.max(0, p.getMealCount());
|
||||
@@ -688,14 +710,14 @@ public class SmHotelMidServiceImpl implements SmHotelMidService {
|
||||
String.valueOf(nsHotelId), body);
|
||||
long planId = extractShengnuoPlanId(planResp, breakfast);
|
||||
if (planId <= 0) {
|
||||
planErrors.add(p.getProductCode() + ":未返回 plan_id");
|
||||
planErrors.add(productLabel + "(房型 " + roomLabel + "):未返回 plan_id,价格未推");
|
||||
continue;
|
||||
}
|
||||
productToPlan.put(p.getProductCode(), planId);
|
||||
planOk++;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
planErrors.add(p.getProductCode() + ":" + ex.getMessage());
|
||||
planErrors.add(productLabel + "(房型 " + roomLabel + "):" + ex.getMessage());
|
||||
log.warn("|下游计划推送[圣诺]|失败|hotelId={}|product={}|{}", hotelId, p.getProductCode(),
|
||||
ex.getMessage());
|
||||
}
|
||||
@@ -713,22 +735,78 @@ public class SmHotelMidServiceImpl implements SmHotelMidService {
|
||||
int priceChunks = pushShengnuoPriceChunks(partnerCode, ds, hotelId, nsHotelId, products, roomTypeToNs,
|
||||
productToPlan, dailies, dailyFrom, dailyTo);
|
||||
|
||||
Map<String, Object> result = new HashMap<>(12);
|
||||
Map<String, Object> result = new HashMap<>(16);
|
||||
result.put("protocol", SmHotelDownstreamProtocol.SHENGNUO);
|
||||
result.put("nsHotelId", nsHotelId);
|
||||
result.put("eid", eid);
|
||||
result.put("matchedRooms", roomTypeToNs.size());
|
||||
result.put("unmatchedRooms", unmatchedRooms);
|
||||
result.put("productTotal", productTotal);
|
||||
result.put("planOk", planOk);
|
||||
result.put("planErrors", planErrors);
|
||||
result.put("priceChunks", priceChunks);
|
||||
result.put("dailyRowCount", dailies.size());
|
||||
result.put("windowFrom", dailyFrom.toString());
|
||||
result.put("windowTo", dailyTo.toString());
|
||||
log.info("|下游可售推送[圣诺]|hotelId={}|partner={}|nsHotelId={}|plans={}|chunks={}|", hotelId, partnerCode,
|
||||
nsHotelId, planOk, priceChunks);
|
||||
// 房型对不上 / 计划失败等不会打 HTTP 失败,单独落流水方便排查「哪些没推上」
|
||||
recordShengnuoPushGaps(partnerCode, hotel, eid, nsHotelId, unmatchedRooms, productTotal, planOk, planErrors,
|
||||
priceChunks, dailyFrom, dailyTo);
|
||||
log.info("|下游可售推送[圣诺]|hotelId={}|partner={}|nsHotelId={}|plans={}/{}|chunks={}|gaps={}|", hotelId,
|
||||
partnerCode, nsHotelId, planOk, productTotal, priceChunks, planErrors.size());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 圣诺推送缺口留底:房型未匹配、计划失败等会导致对应价格推不上,但整体 HTTP 可能仍成功。
|
||||
* success=2 部分缺口;全部产品都没推上则 success=0。
|
||||
*/
|
||||
private void recordShengnuoPushGaps(String partnerCode, SmHotelEntity hotel, String eid, long nsHotelId,
|
||||
List<String> unmatchedRooms, int productTotal, int planOk, List<String> planErrors, int priceChunks,
|
||||
LocalDate dailyFrom, LocalDate dailyTo) {
|
||||
boolean hasRoomGap = CollUtil.isNotEmpty(unmatchedRooms);
|
||||
boolean hasPlanGap = CollUtil.isNotEmpty(planErrors);
|
||||
boolean nothingPushed = productTotal > 0 && planOk <= 0;
|
||||
if (!hasRoomGap && !hasPlanGap && !nothingPushed) {
|
||||
return;
|
||||
}
|
||||
int gapCount = planErrors == null ? 0 : planErrors.size();
|
||||
String summary;
|
||||
if (nothingPushed) {
|
||||
summary = "圣诺可售推送:全部 " + productTotal + " 个产品未推上(计划成功0),请核对房型匹配/plan";
|
||||
}
|
||||
else {
|
||||
summary = "圣诺可售推送部分未推上:计划成功 " + planOk + "/" + productTotal + ",缺口 " + gapCount
|
||||
+ (hasRoomGap ? ",未匹配房型 " + unmatchedRooms.size() + " 个" : "");
|
||||
}
|
||||
Map<String, Object> detail = new LinkedHashMap<>(12);
|
||||
detail.put("eid", eid);
|
||||
detail.put("nsHotelId", nsHotelId);
|
||||
detail.put("windowFrom", dailyFrom == null ? null : dailyFrom.toString());
|
||||
detail.put("windowTo", dailyTo == null ? null : dailyTo.toString());
|
||||
detail.put("productTotal", productTotal);
|
||||
detail.put("planOk", planOk);
|
||||
detail.put("priceChunks", priceChunks);
|
||||
detail.put("unmatchedRooms", unmatchedRooms == null ? List.of() : unmatchedRooms);
|
||||
detail.put("planErrors", planErrors == null ? List.of() : planErrors);
|
||||
String extHotelId = hotel == null ? eid
|
||||
: StrUtil.blankToDefault(hotel.getSHotelId(),
|
||||
StrUtil.blankToDefault(hotel.getHotelCode(),
|
||||
hotel.getId() == null ? eid : String.valueOf(hotel.getId())));
|
||||
SmHotelDownstreamPushLogEntity row = new SmHotelDownstreamPushLogEntity();
|
||||
row.setPartnerCode(partnerCode);
|
||||
row.setSyncLogId(DownstreamPushLogContext.syncLogId());
|
||||
row.setHotelId(hotel == null ? null : hotel.getId());
|
||||
row.setExtHotelId(extHotelId);
|
||||
row.setAction("push_partial");
|
||||
row.setSuccess(nothingPushed ? "0" : "2");
|
||||
row.setErrorMsg(StrUtil.maxLength(summary, 900));
|
||||
row.setResponseBody(StrUtil.maxLength(JSONUtil.toJsonStr(detail), 4000));
|
||||
row.setCostMs(0L);
|
||||
downstreamPushLogService.record(row);
|
||||
log.warn("|下游推送缺口[圣诺]|hotelId={}|partner={}|{}|", hotel == null ? null : hotel.getId(), partnerCode,
|
||||
summary);
|
||||
}
|
||||
|
||||
/** 圣诺关房:pushHotelClose(整店) */
|
||||
private Map<String, Object> closeHotelDailyToShengnuo(SmHotelEntity hotel, String partnerCode) {
|
||||
downstreamClient.assertPartnerReady(partnerCode);
|
||||
|
||||
Reference in new issue
Block a user