diff --git a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/entity/SmHotelMgrPushLogEntity.java b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/entity/SmHotelMgrPushLogEntity.java index b6aa76e6c..9191fb1b4 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/entity/SmHotelMgrPushLogEntity.java +++ b/pjcloud-supermarket/pjcloud-supermarket-api/src/main/java/com/bsd/pjcloud/supermarket/entity/SmHotelMgrPushLogEntity.java @@ -79,6 +79,9 @@ public class SmHotelMgrPushLogEntity extends Model { private String resultMsg; + @Schema(description = "下游请求体快照(失败/部分失败时写入 JSON)") + private String requestJson; + @TableField(fill = FieldFill.INSERT) private String createBy; diff --git a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmHotelMgrPushServiceImpl.java b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmHotelMgrPushServiceImpl.java index b4661422a..1cf73a1c3 100644 --- a/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmHotelMgrPushServiceImpl.java +++ b/pjcloud-supermarket/pjcloud-supermarket-biz/src/main/java/com/bsd/pjcloud/supermarket/service/impl/SmHotelMgrPushServiceImpl.java @@ -240,7 +240,7 @@ public class SmHotelMgrPushServiceImpl implements SmHotelMgrPushService { log.info("|酒店管理推送|新订单无接收人|orderId={}|deptId={}|adminEnabled={}|", orderId, deptId, adminEnabled); savePushLog(SmHotelMgrPushLogEntity.TYPE_NEW_ORDER, trigger, String.valueOf(orderId), - order.getHotelId(), hotelName, logDepts, List.of(), 0, 0, title, null, tip); + order.getHotelId(), hotelName, logDepts, List.of(), 0, 0, title, null, tip, null); return force ? PushResult.fail(tip) : PushResult.skip(tip); } Long tenantId = resolveTenantId(order.getTenantId(), hotel == null ? null : hotel.getTenantId()); @@ -262,6 +262,8 @@ public class SmHotelMgrPushServiceImpl implements SmHotelMgrPushService { : ("HOTEL_MGR_ORDER:" + orderId); int ok = 0; List failHints = new ArrayList<>(); + List> failRequests = new ArrayList<>(); + HotelManagerPushEventDto sampleRequest = null; for (Long userId : recipients) { if (userId == null) { continue; @@ -280,12 +282,20 @@ public class SmHotelMgrPushServiceImpl implements SmHotelMgrPushService { dto.setDeepLinkPath("/pages/hotel-manage/orders"); dto.setDeepLinkParamsJson(JSONUtil.toJsonStr(linkParams)); dto.setOccurredTime(LocalDateTime.now()); + if (sampleRequest == null) { + sampleRequest = dto; + } String err = pushOne(dto); if (err == null) { ok++; } - else if (failHints.size() < 3) { - failHints.add(displayUserName(userId) + ":" + err); + else { + if (failHints.size() < 3) { + failHints.add(displayUserName(userId) + ":" + err); + } + if (failRequests.size() < 5) { + failRequests.add(buildFailRequestItem(displayUserName(userId), err, dto)); + } } } List recipientList = new ArrayList<>(recipients); @@ -293,6 +303,7 @@ public class SmHotelMgrPushServiceImpl implements SmHotelMgrPushService { String leaderNames = resolveUserNames(leaders); String adminNames = resolveUserNames(admins); String detail = buildNewOrderDetail(orderLabel, deptName, leaderNames, adminNames, adminEnabled); + String requestJson = buildRequestSnapshot(sampleRequest, failRequests, ok, fail); log.info("|酒店管理推送|新订单完成|orderId={}|deptId={}|recipients={}|ok={}|force={}|admin={}|", orderId, deptId, recipientList.size(), ok, force, adminEnabled); if (ok == 0) { @@ -300,12 +311,14 @@ public class SmHotelMgrPushServiceImpl implements SmHotelMgrPushService { + (failHints.isEmpty() ? " 请确认 thirdparty 已重启并包含酒店管理推送接口。" : (" 原因:" + String.join(";", failHints))); savePushLog(SmHotelMgrPushLogEntity.TYPE_NEW_ORDER, trigger, String.valueOf(orderId), - order.getHotelId(), hotelName, logDepts, recipientList, 0, fail, title, content, tip); + order.getHotelId(), hotelName, logDepts, recipientList, 0, fail, title, content, tip, + requestJson); return force ? PushResult.fail(tip) : PushResult.skip(tip); } String msg = "已推送成功 " + ok + "/" + recipientList.size() + " 人" + detail; savePushLog(SmHotelMgrPushLogEntity.TYPE_NEW_ORDER, trigger, String.valueOf(orderId), - order.getHotelId(), hotelName, logDepts, recipientList, ok, fail, title, content, msg); + order.getHotelId(), hotelName, logDepts, recipientList, ok, fail, title, content, msg, + requestJson); return PushResult.success(ok, recipientList.size(), msg); } catch (Exception e) { @@ -352,7 +365,7 @@ public class SmHotelMgrPushServiceImpl implements SmHotelMgrPushService { + "部门示例:" + StrUtil.blankToDefault(resolveDeptNames(sampleDepts), "无"); log.info("|酒店管理推送|日历提醒无负责人|hour={}|deptCount={}|", hour, deptIds.size()); savePushLog(SmHotelMgrPushLogEntity.TYPE_CALENDAR, trigger, day + "-" + hour, null, null, - new ArrayList<>(deptIds), List.of(), 0, 0, title, content, tip); + new ArrayList<>(deptIds), List.of(), 0, 0, title, content, tip, null); return force ? PushResult.fail(tip) : PushResult.skip(tip); } Long tenantId = resolveTenantId(null, hotels.get(0).getTenantId()); @@ -365,6 +378,8 @@ public class SmHotelMgrPushServiceImpl implements SmHotelMgrPushService { : ("HOTEL_MGR_CAL:" + day + ":" + hour); int ok = 0; List failHints = new ArrayList<>(); + List> failRequests = new ArrayList<>(); + HotelManagerPushEventDto sampleRequest = null; for (Long userId : leaders) { if (userId == null) { continue; @@ -381,17 +396,26 @@ public class SmHotelMgrPushServiceImpl implements SmHotelMgrPushService { dto.setPayloadJson(JSONUtil.toJsonStr(payload)); dto.setDeepLinkPath("/pages/hotel-manage/list"); dto.setOccurredTime(LocalDateTime.now()); + if (sampleRequest == null) { + sampleRequest = dto; + } String err = pushOne(dto); if (err == null) { ok++; } - else if (failHints.size() < 3) { - failHints.add(displayUserName(userId) + ":" + err); + else { + if (failHints.size() < 3) { + failHints.add(displayUserName(userId) + ":" + err); + } + if (failRequests.size() < 5) { + failRequests.add(buildFailRequestItem(displayUserName(userId), err, dto)); + } } } int fail = Math.max(0, leaders.size() - ok); List leaderList = new ArrayList<>(leaders); String leaderNames = resolveUserNames(leaderList); + String requestJson = buildRequestSnapshot(sampleRequest, failRequests, ok, fail); log.info("|酒店管理推送|日历提醒完成|hour={}|deptCount={}|leaders={}|ok={}|", hour, deptIds.size(), leaders.size(), ok); List logDepts = deptsWithLeader.isEmpty() ? new ArrayList<>(deptIds) : deptsWithLeader; @@ -399,12 +423,12 @@ public class SmHotelMgrPushServiceImpl implements SmHotelMgrPushService { String tip = "找到负责人 " + leaders.size() + " 人(" + leaderNames + "),但投递全部失败。" + (failHints.isEmpty() ? "请确认 thirdparty 已重启。" : ("原因:" + String.join(";", failHints))); savePushLog(SmHotelMgrPushLogEntity.TYPE_CALENDAR, trigger, day + "-" + hour, null, null, - logDepts, leaderList, 0, fail, title, content, tip); + logDepts, leaderList, 0, fail, title, content, tip, requestJson); return force ? PushResult.fail(tip) : PushResult.skip(tip); } String msg = "日历提醒成功 " + ok + "/" + leaders.size() + " 人(负责人=" + leaderNames + ")"; savePushLog(SmHotelMgrPushLogEntity.TYPE_CALENDAR, trigger, day + "-" + hour, null, null, - logDepts, leaderList, ok, fail, title, content, msg); + logDepts, leaderList, ok, fail, title, content, msg, requestJson); return PushResult.success(ok, leaders.size(), msg); } @@ -460,9 +484,39 @@ public class SmHotelMgrPushServiceImpl implements SmHotelMgrPushService { return StrUtil.blankToDefault(names, String.valueOf(userId)); } + /** + * 组装下游排查快照:有失败时优先写失败请求;全部成功也保留 1 条样例请求便于对照。 + */ + private static String buildRequestSnapshot(HotelManagerPushEventDto sample, List> failItems, + int ok, int fail) { + if (sample == null && CollUtil.isEmpty(failItems)) { + return null; + } + Map root = new HashMap<>(8); + root.put("api", "thirdparty receiveHotelManagerPushEvent"); + root.put("successCount", ok); + root.put("failCount", fail); + if (CollUtil.isNotEmpty(failItems)) { + root.put("fails", failItems); + } + else if (sample != null) { + root.put("sampleRequest", sample); + } + return StrUtil.maxLength(JSONUtil.toJsonStr(root), 60000); + } + + private static Map buildFailRequestItem(String recipientName, String error, + HotelManagerPushEventDto dto) { + Map item = new HashMap<>(4); + item.put("recipientName", recipientName); + item.put("error", error); + item.put("request", dto); + return item; + } + private void savePushLog(String pushType, String triggerType, String bizId, Long hotelId, String hotelName, List deptIds, List userIds, int success, int fail, String title, String content, - String resultMsg) { + String resultMsg, String requestJson) { try { SmHotelMgrPushLogEntity row = new SmHotelMgrPushLogEntity(); row.setPushType(pushType); @@ -479,6 +533,7 @@ public class SmHotelMgrPushServiceImpl implements SmHotelMgrPushService { row.setTitle(title); row.setContent(StrUtil.maxLength(content, 500)); row.setResultMsg(StrUtil.maxLength(resultMsg, 900)); + row.setRequestJson(requestJson); if (success > 0 && fail <= 0) { row.setStatus(SmHotelMgrPushLogEntity.STATUS_OK); }