mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-08-06 17:36:53 +01:00
- Introduced `al-test-writer` to generate AL test codeunits for production objects based on TDD principles. - Added `al-userguide-test-writer` to create test codeunits from user guide steps, mapping actions and assertions. - Implemented `bc-extension-test-guide` to generate a comprehensive TEST_GUIDE.md for Business Central extensions, covering various categories. - Created `bc-webclient-runner` to automate UI testing of the Business Central web client, capturing screenshots and asserting UI states. - Developed `page-scripting-e2e` to produce a recording plan for Page Scripting, ensuring a structured approach to browser-level testing.
75 lines
3.2 KiB
AL
75 lines
3.2 KiB
AL
// Best practice: a resolution page over failed messages. Ops corrects the payload and flips
|
|
// Status to New; the processor re-runs the SAME Message ID under the SAME idempotency key, so
|
|
// the fix reprocesses without creating a duplicate. The shape mirrors what Microsoft ships for
|
|
// E-Document: editable staging, a resolution page, a status enum, retry actions, and an audit trail.
|
|
|
|
page 50220 "Integration Resolution"
|
|
{
|
|
PageType = List;
|
|
SourceTable = "Integration Message";
|
|
// Failed messages stay EDITABLE so ops can correct the payload without a developer or a deploy.
|
|
Editable = true;
|
|
SourceTableView = where(Status = const(Failed));
|
|
Caption = 'Integration Resolution';
|
|
|
|
layout
|
|
{
|
|
area(Content)
|
|
{
|
|
repeater(Group)
|
|
{
|
|
// The id is shown but NOT editable: re-running must reuse it so the idempotency
|
|
// key (derived from this id) stays the same and the retry cannot double-apply.
|
|
field("Message ID"; Rec."Message ID") { Editable = false; }
|
|
field("External Reference"; Rec."External Reference") { Editable = false; }
|
|
// The error context ops needs to diagnose the failure. Read-only: it is history.
|
|
field("Error Message"; Rec."Error Message") { Editable = false; }
|
|
field("Retry Count"; Rec."Retry Count") { Editable = false; }
|
|
// The payload ops actually edits to fix a malformed or mis-mapped message.
|
|
field(Request; Rec.GetRequest()) { }
|
|
field("Resolution Note"; Rec."Resolution Note") { } // audit of what was decided
|
|
}
|
|
}
|
|
}
|
|
|
|
actions
|
|
{
|
|
area(Processing)
|
|
{
|
|
action(Resolve)
|
|
{
|
|
Caption = 'Resolve';
|
|
trigger OnAction()
|
|
begin
|
|
// Re-run the SAME message: same Message ID, therefore same idempotency key.
|
|
// The processor reprocesses the corrected payload, and the receiver recognises
|
|
// the repeat, so a side effect that partly landed is not applied a second time.
|
|
Rec.Status := Rec.Status::New;
|
|
Rec.Modify(true);
|
|
end;
|
|
}
|
|
action(ConfirmByException)
|
|
{
|
|
Caption = 'Confirm by Exception';
|
|
trigger OnAction()
|
|
begin
|
|
// Accept as handled with NO retry (for example the work was completed manually
|
|
// out of band). The audit record is kept so the decision is traceable.
|
|
Rec.Status := Rec.Status::Resolved;
|
|
Rec."Resolution Note" := 'Confirmed by exception';
|
|
Rec.Modify(true);
|
|
end;
|
|
}
|
|
action(Reassign)
|
|
{
|
|
Caption = 'Reassign';
|
|
trigger OnAction()
|
|
begin
|
|
// Route to another handler/queue without losing the message or its history.
|
|
Rec."Assigned To" := PickHandler();
|
|
Rec.Modify(true);
|
|
end;
|
|
}
|
|
}
|
|
}
|
|
}
|