mirror of
https://github.com/microsoft/BCQuality.git
synced 2026-10-05 14:46:55 +01:00
- pages-must-not-contain-business-logic.good.al/.bad.al: the "good" codeunit still directly assigned real Sales Line."Line Amount" and called Modify(), bypassing the field's normal Validate cascade (discount, VAT, related-amount maintenance) - persisting inconsistent document lines regardless of which object the code lived in. Replaced the real Sales Line example with a self-contained "Sample Order Line" table and switched the codeunit to Validate()/Modify(true), so the fixture demonstrates the page-vs-codeunit separation without teaching unsafe direct field writes to a real BC document table. - bcpt-scenarios-must-be-app-specific.good.al: Customer.FindFirst() assumed a pre-existing customer (fails against an empty environment), and a session-local NextNo counter for the header key collides across concurrent BCPT sessions and repeated runs. Creates its own customer when none exists, and generates keys from CreateGuid() instead of an in-memory counter. - upgrade-tag-logic-must-not-nest-deeply: the rule conflated two different things - nesting one tag's existence check inside another (the real anti-pattern Microsoft's guidance warns against) with having business-data safety conditions inside a single tagged migration's own loop body (which Microsoft's own worked example does, and its own design guidance explicitly requires: "Implement extra safety checks to avoid data corruption, even though you're using upgrade tags"). Rewrote the Description/Best Practice/Anti Pattern to scope the rule to actual tag nesting and migrations blended under one tag, and rewrote both fixtures: good.al now shows two safety conditions correctly nested inside one migration's own loop plus a second, genuinely separate migration as its own flat tagged procedure; bad.al now shows the real anti-pattern, one tag's check nested inside another's guarded body. - table-design-must-match-bc-table-type-conventions: the rule and its worklist cue fired on any new table with a keys block, forcing buffers, queues, logs, mapping tables, and staging tables into the nearest-looking one of nine business-record archetypes. Added an explicit scope note that these nine types aren't an exhaustive table catalogue, and narrowed the al-data-modeling-review.md cue to require positive evidence (a type-specific naming suffix, key shape, or usage) before worklisting, instead of a bare keys/primary-key declaration.
73 lines
2.6 KiB
AL
73 lines
2.6 KiB
AL
codeunit 50100 "BCPT Create Service Request" implements "BCPT Test Param. Provider"
|
|
{
|
|
SingleInstance = true;
|
|
|
|
trigger OnRun()
|
|
begin
|
|
if not IsInitialized then begin
|
|
InitTest();
|
|
IsInitialized := true;
|
|
end;
|
|
CreateServiceRequest(GlobalBCPTTestContext);
|
|
end;
|
|
|
|
var
|
|
GlobalBCPTTestContext: Codeunit "BCPT Test Context";
|
|
CustomerNo: Code[20];
|
|
IsInitialized: Boolean;
|
|
|
|
local procedure InitTest()
|
|
var
|
|
Customer: Record Customer;
|
|
begin
|
|
// Do not assume a customer already exists: a BCPT run may target an
|
|
// otherwise-empty environment. Create one if none is found instead
|
|
// of failing on FindFirst().
|
|
if not Customer.FindFirst() then begin
|
|
Customer.Init();
|
|
Customer."No." := GenerateUniqueCode(MaxStrLen(Customer."No."));
|
|
Customer.Insert(true);
|
|
end;
|
|
CustomerNo := Customer."No.";
|
|
end;
|
|
|
|
local procedure GenerateUniqueCode(Length: Integer): Code[20]
|
|
begin
|
|
// A GUID-derived code, not a session-local counter: it stays unique
|
|
// across concurrent BCPT sessions and repeated runs against the
|
|
// same environment, which an in-memory counter reset per session
|
|
// cannot guarantee.
|
|
exit(CopyStr(DelChr(Format(CreateGuid()), '=', '{}-'), 1, Length));
|
|
end;
|
|
|
|
local procedure CreateServiceRequest(var BCPTTestContext: Codeunit "BCPT Test Context")
|
|
var
|
|
ServiceRequestHeader: Record "Service Request Header";
|
|
ServiceRequestLine: Record "Service Request Line";
|
|
begin
|
|
BCPTTestContext.StartScenario('Create Service Request Header');
|
|
ServiceRequestHeader.Init();
|
|
ServiceRequestHeader."No." := GenerateUniqueCode(MaxStrLen(ServiceRequestHeader."No."));
|
|
ServiceRequestHeader.Validate("Customer No.", CustomerNo);
|
|
ServiceRequestHeader.Insert(true);
|
|
BCPTTestContext.EndScenario('Create Service Request Header');
|
|
BCPTTestContext.UserWait();
|
|
|
|
BCPTTestContext.StartScenario('Add Service Request Line');
|
|
ServiceRequestLine.Init();
|
|
ServiceRequestLine."Document No." := ServiceRequestHeader."No.";
|
|
ServiceRequestLine."Line No." := 10000;
|
|
ServiceRequestLine.Description := 'Performance test line';
|
|
ServiceRequestLine.Insert(true);
|
|
BCPTTestContext.EndScenario('Add Service Request Line');
|
|
end;
|
|
|
|
procedure GetDefaultParameters(): Text[1000]
|
|
begin
|
|
exit('');
|
|
end;
|
|
|
|
procedure ValidateParameters(Parameters: Text[1000])
|
|
begin
|
|
end;
|
|
}
|