diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Deployment/FlowStepDetail.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Deployment/FlowStepDetail.razor index cb9bbcc8..ce941dea 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Deployment/FlowStepDetail.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Deployment/FlowStepDetail.razor @@ -223,7 +223,7 @@ private string? ReportHref => Step is { CorrelationId: { } c } s && IsOutbound && s.Lifecycle is { Count: > 0 } ? s.Kind == FlowStepKind.Notify - ? $"/notifications/report?correlationId={c:D}" + ? $"/notifications/report?correlationId={c:N}" // NotificationId is minted as "N" (no dashes) — see ScriptRuntimeContext.Notify : $"/site-calls/report?correlationId={c:D}" : null; diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationReport.razor b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationReport.razor index 09f29ef5..87967c19 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationReport.razor +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Components/Pages/Notifications/NotificationReport.razor @@ -515,7 +515,9 @@ var candidate = values.ToString()?.Trim(); if (!string.IsNullOrEmpty(candidate) && candidate.Length <= MaxNotificationIdFilterLength) { - _notificationIdFilter = candidate; + // NotificationId is minted as a Guid in "N" form (no dashes); a caller that only has the + // audit row's CorrelationId (a Guid, usually rendered "D") must still land on the row. + _notificationIdFilter = Guid.TryParse(candidate, out var guid) ? guid.ToString("N") : candidate; } } } diff --git a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/FlowDebugService.cs b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/FlowDebugService.cs index c143bb3c..2d2eb085 100644 --- a/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/FlowDebugService.cs +++ b/src/ZB.MOM.WW.ScadaBridge.CentralUI/Services/FlowDebugService.cs @@ -225,7 +225,9 @@ public sealed class FlowDebugService : IFlowDebugService if (isNotify) { - var notificationId = c.ToString("D"); + // Notify.Send mints NotificationId as Guid "N" (no dashes; ScriptRuntimeContext) and the + // outbox parses it back into the audit row's CorrelationId — so the relay key is "N". + var notificationId = c.ToString("N"); if (retry) { var r = await _comms.RetryNotificationAsync(new RetryNotificationRequest(corr, notificationId, requestedBy), ct); diff --git a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Deployment/FlowStepDetailTests.cs b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Deployment/FlowStepDetailTests.cs index ed41976a..6a2b65f9 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Deployment/FlowStepDetailTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Deployment/FlowStepDetailTests.cs @@ -106,7 +106,7 @@ public class FlowStepDetailTests : BunitContext var notify = Step(FlowStepKind.Notify, FlowStepOutcome.Ok, "Planners", CachedLifecycle("Delivered"), c); cut = Render(p => p.Add(x => x.Step, notify)); link = cut.Find("a[data-test=open-report]"); - Assert.Equal($"/notifications/report?correlationId={c:D}", link.GetAttribute("href")); + Assert.Equal($"/notifications/report?correlationId={c:N}", link.GetAttribute("href")); Assert.Equal("Open in Notification report", link.TextContent.Trim()); var sync = Step(FlowStepKind.ApiCall, FlowStepOutcome.Ok, "Delmia.AckRecipe"); @@ -167,7 +167,7 @@ public class FlowStepDetailTests : BunitContext Assert.Contains("Parked", hint.TextContent); var hintLink = hint.QuerySelector("a"); Assert.NotNull(hintLink); - Assert.Equal($"/notifications/report?correlationId={c:D}", hintLink!.GetAttribute("href")); + Assert.Equal($"/notifications/report?correlationId={c:N}", hintLink!.GetAttribute("href")); } [Fact] diff --git a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/NotificationReportPageTests.cs b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/NotificationReportPageTests.cs index a8f58006..fd377ac2 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/NotificationReportPageTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Pages/NotificationReportPageTests.cs @@ -248,6 +248,25 @@ public class NotificationReportPageTests : BunitContext // with that id comes back. // ───────────────────────────────────────────────────────────────────────── + [Fact] + public void NotificationReport_CorrelationIdQuery_DashedGuid_IsNormalisedToTheStoredNForm() + { + // Notify.Send mints NotificationId as Guid "N"; the Flow Debugger / Audit Log hold the + // same value as a Guid and may render it "D". Either spelling must filter to the row. + var guid = Guid.Parse("a72bc17f-b681-43eb-a364-e136c54d51c0"); + var nav = (BunitNavigationManager)Services.GetRequiredService(); + nav.NavigateTo($"/notifications/report?correlationId={guid:D}"); + + var cut = Render(); + + cut.WaitForAssertion(() => + { + Assert.Single(_queryRequests); + Assert.Equal(guid.ToString("N"), _queryRequests[0].NotificationIdFilter); + Assert.Contains(guid.ToString("N")[..12], cut.Find("[data-test='notif-filter-notification']").TextContent); + }); + } + [Fact] public void NotificationReport_CorrelationIdQuery_SeedsTheNotificationFilterAndAutoOpensDetail() { diff --git a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Services/FlowDebugServiceTests.cs b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Services/FlowDebugServiceTests.cs index 8b1f8df8..c4414b7b 100644 --- a/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Services/FlowDebugServiceTests.cs +++ b/tests/ZB.MOM.WW.ScadaBridge.CentralUI.Tests/Services/FlowDebugServiceTests.cs @@ -120,7 +120,7 @@ public sealed class FlowDebugServiceTests : IDisposable Assert.True(result.Success, result.Message); Assert.Contains("re-queued", result.Message); var request = Assert.IsType(Assert.Single(_outboxRequests)); - Assert.Equal(c.ToString("D"), request.NotificationId); + Assert.Equal(c.ToString("N"), request.NotificationId); Assert.Equal("tester", request.RequestedBy); Assert.Empty(_siteCallRequests); }