This commit is contained in:
Michael Dieringer 2026-06-13 13:46:40 +02:00
parent 822cae1b27
commit c4a9f8e88e
2 changed files with 136 additions and 0 deletions

View file

@ -0,0 +1,65 @@
---
bc-version: [all]
domain: architecture
keywords: [page, trigger, onaction, modify, codeunit, logic]
technologies: [al]
countries: [w1]
application-area: [all]
---
## Description
In CURABIS codebases, pages are pure presentation. Business logic, calculations,
validations, and record modifications belong in codeunits — not in page triggers
or actions. This is stricter than the general BC guidance and applies to all
CURABIS PTE apps.
A page procedure that calculates a value and assigns it to a field, calls
`Rec.Modify()` directly, or implements business rules is an architecture violation
even if it compiles.
**Exceptions:**
- Setup pages may read and write their own setup record directly.
- The designated "Run Conversion" page may call the conversion codeunit directly.
## Anti Pattern
```al
// WRONG: calculation and Modify in a page action
trigger OnAction()
begin
Rec."Total Amount" := Rec.Quantity * Rec."Unit Price";
Rec."VAT Amount" := Rec."Total Amount" * 0.25;
Rec.Modify();
end;
```
```al
// WRONG: validation logic in page trigger
trigger OnValidate()
begin
if Rec.Quantity < 0 then
Error('Quantity cannot be negative');
Rec."Total Amount" := Rec.Quantity * Rec."Unit Price";
end;
```
## Best Practice
```al
// CORRECT: page delegates to codeunit
trigger OnAction()
begin
SVManagement.RecalculateLine(Rec);
end;
```
```al
// CORRECT: validation belongs in table or codeunit
trigger OnValidate()
begin
SVManagement.ValidateAndRecalculate(Rec);
end;
```
The codeunit owns the logic. The page owns the presentation.

View file

@ -0,0 +1,71 @@
---
bc-version: [all]
domain: testing
keywords: [test, library, setup, initialize, suppresscommit, asserterror]
technologies: [al]
countries: [w1]
application-area: [all]
---
## Description
In CURABIS test apps, all test setup is centralized in a dedicated Test Library
codeunit (e.g. `SV Test Library`). Individual test procedures must not call
BC standard library codeunits (`LibrarySales`, `LibraryInventory`, etc.) directly.
Additionally, two rules apply to every test that calls a posting codeunit:
1. `SetSuppressCommit(true)` must be called before `Run()` to prevent data
from leaking between tests.
2. `asserterror` must always be followed by `Assert.ExpectedErrorCode()` or
`Assert.ExpectedError()` — a naked `asserterror` passes on any error,
not just the expected one.
## Anti Pattern
```al
// WRONG: inline setup bypassing the test library
procedure MyTest()
var
Item: Record Item;
begin
LibraryInventory.CreateItem(Item); // do not call directly
// ...
end;
```
```al
// WRONG: posting without SuppressCommit
SVPost.Run(SVHeader); // commits to test database
```
```al
// WRONG: naked asserterror
asserterror SVPost.Run(SVHeader);
// no assertion follows — passes on any error
```
## Best Practice
```al
// CORRECT: delegate to test library
procedure MyTest()
var
Item: Record Item;
begin
SVLib.GivenScrapItem(Item); // test library owns setup
// ...
end;
```
```al
// CORRECT: SuppressCommit before Run
SVPost.SetSuppressCommit(true);
SVPost.Run(SVHeader);
```
```al
// CORRECT: asserterror followed by assertion
asserterror SVPost.Run(SVHeader);
Assert.ExpectedErrorCode('Dialog');
```