Add knowledge-backed AL development

Add read-only planning and repository-changing development skills so BCQuality
knowledge can guide features, bug fixes, refactors, upgrades, and maintenance
before the existing AL review gate runs. Track Microsoft Learn ingestion and
add development and BCApps-shaped guidance evaluation fixtures.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 638b66d2-9f06-4f60-8781-808709e1485c
This commit is contained in:
Jesper Schulz-Wedde 2026-09-04 12:53:54 +02:00
parent 1a5afdc0eb
commit 56b80e6dcf
50 changed files with 11589 additions and 79 deletions

View file

@ -0,0 +1,28 @@
table 50603 "Sample Order Header Bad"
{
fields
{
field(1; "No."; Code[20])
{
DataClassification = CustomerContent;
}
field(2; "Document Date"; Date)
{
DataClassification = CustomerContent;
}
}
trigger OnInsert()
var
SalesSetup: Record "Sales & Receivables Setup";
NoSeries: Codeunit "No. Series";
begin
"Document Date" := WorkDate();
if "No." = '' then begin
SalesSetup.Get();
SalesSetup.TestField("Order Nos.");
"No." := NoSeries.GetNextNo(SalesSetup."Order Nos.");
end;
end;
}

View file

@ -0,0 +1,45 @@
table 50602 "Sample Order Header Good"
{
fields
{
field(1; "No."; Code[20])
{
DataClassification = CustomerContent;
}
field(2; "Document Date"; Date)
{
DataClassification = CustomerContent;
}
}
trigger OnInsert()
var
SalesSetup: Record "Sales & Receivables Setup";
NoSeries: Codeunit "No. Series";
begin
if "No." = '' then begin
SalesSetup.Get();
SalesSetup.TestField("Order Nos.");
"No." := NoSeries.GetNextNo(SalesSetup."Order Nos.");
end;
InitRecord();
end;
procedure InitRecord()
begin
OnBeforeInitRecord(Rec);
"Document Date" := WorkDate();
OnAfterInitRecord(Rec);
end;
[IntegrationEvent(false, false)]
local procedure OnBeforeInitRecord(var SampleOrderHeader: Record "Sample Order Header Good")
begin
end;
[IntegrationEvent(false, false)]
local procedure OnAfterInitRecord(var SampleOrderHeader: Record "Sample Order Header Good")
begin
end;
}

View file

@ -0,0 +1,30 @@
---
bc-version: [all]
domain: data-modeling
keywords: [document-header, initrecord, number-series, default-values, oninsert, initialization]
technologies: [al]
countries: [w1]
application-area: [all]
---
# Initialize document defaults in `InitRecord` after assigning the number
## Description
Business Central document headers assign their number series first and then call an `InitRecord` procedure that owns the remaining business defaults, such as posting and document dates. Keeping that sequence and extensibility point makes initialization consistent for every creation path and lets extensions subscribe around one documented operation. Defaults scattered across page triggers or unrelated helpers can differ between UI, API, test, and background creation.
## Best Practice
In the document table's insert path, assign the document number and then call `InitRecord`. Keep the default assignments in that procedure and expose narrow before/after events when other extensions must participate.
See sample: `initialize-document-defaults-in-initrecord.good.al`.
## Anti Pattern
Assigning document defaults in a page trigger, or scattering them directly through `OnInsert` with no `InitRecord` boundary. Non-page creation paths can then miss the defaults, and extensions have no stable initialization hook.
See sample: `initialize-document-defaults-in-initrecord.bad.al`.
## Reference
[Use the InitRecord function](https://learn.microsoft.com/en-us/training/modules/use-document-standards-business-central/3-use-initrecord-function)

View file

@ -0,0 +1,8 @@
codeunit 50601 "Directed Rounding Bad"
{
procedure FloorAmount(Value: Decimal; Precision: Decimal): Decimal
begin
// For negative values, '<' rounds toward zero rather than toward negative infinity.
exit(Round(Value, Precision, '<'));
end;
}

View file

@ -0,0 +1,10 @@
codeunit 50600 "Directed Rounding Good"
{
procedure RoundAmount(Value: Decimal; Precision: Decimal; IncreaseMagnitude: Boolean): Decimal
begin
if IncreaseMagnitude then
exit(Round(Value, Precision, '>'));
exit(Round(Value, Precision, '<'));
end;
}

View file

@ -0,0 +1,30 @@
---
bc-version: [all]
domain: data-modeling
keywords: [round, rounding, direction, precision, negative-decimal, amount]
technologies: [al]
countries: [w1]
application-area: [all]
---
# `Round` direction symbols follow magnitude, not mathematical ordering
## Description
AL's `Round(Number, Precision, Direction)` uses `'>'` to round away from zero and `'<'` to round toward zero. For a negative value this reverses mathematical ordering: `Round(-1234.56789, 0.001, '<')` returns `-1234.567`, while direction `'>'` returns `-1234.568`. Code that treats the symbols as mathematical ceiling and floor produces sign-dependent amount errors, commonly on credit documents and negative adjustments.
## Best Practice
Choose the direction from the business meaning: `'>'` increases absolute magnitude and `'<'` decreases absolute magnitude for both positive and negative values. Include positive and negative cases whenever a directed rounding rule is tested.
See sample: `round-direction-symbols-use-magnitude.good.al`.
## Anti Pattern
Using `'<'` as a mathematical floor or `'>'` as a mathematical ceiling. The result looks correct for positive amounts but moves in the opposite mathematical direction for negative amounts.
See sample: `round-direction-symbols-use-magnitude.bad.al`.
## Reference
[Use the Round function](https://learn.microsoft.com/en-us/training/modules/use-document-standards-business-central/4a-use-round-function)