Dimensions Before You Post
Select a Dimension Value Code for the Dimension Code DEPARTMENT... — the single most common support ticket in Business Central finance. It always arrives the same way: someone clicks Post on a twelve-line order, the whole posting is refused because of one line, and nobody can tell which one until they walk the document by hand.
Your job is a pre-flight validator. Given a sales document, it reports every line whose dimensions break a default-dimension rule — all of them, in one pass, before anyone touches Post.
Requirements
Create a codeunit named "Dimension Precheck" with one public procedure:
procedure CheckSalesDocument(SalesHeader: Record "Sales Header"; var Violation: Record "Dimension Precheck Violation"): IntegerThe starter already contains the buffer table the procedure fills, "Dimension Precheck Violation", declared TableType = Temporary with these fields and the primary key "Line No.", "Dimension Code":
"Line No."(Integer) —0for the document header, otherwise the sales line's own"Line No."."Dimension Code"(Code[20]) — the dimension whose rule was broken."Value Posting"(Enum "Default Dimension Value Posting Type") — the rule that was broken.
Do not add the temporary keyword to the Violation parameter: the table is already temporary by declaration, and the tests pass a plain record variable.
What the procedure does
- It empties
Violation, writes one row per broken rule, and returns the number of rows it wrote. - Every source of rules is a master record carrying
Default Dimensionrows. The document header is checked against theCustomerinSalesHeader."Bill-to Customer No.", usingSalesHeader."Dimension Set ID"; findings are reported with"Line No."=0. - Every sales line of the document is checked twice: against that same customer, and against the line's own master record — the record its
Typeand"No."point at (anItemfor an item line, aG/L Accountfor a G/L account line, aResourcefor a resource line, aFixed Assetfor a fixed-asset line, anItem Chargefor a charge line). Both checks run againstSalesLine."Dimension Set ID"and are reported with that line's"Line No.". - Lines that point at no master record —
Typeis blank, or"No."is blank, as on description and comment lines — are skipped entirely and never reported. - A
Default Dimensionrow is a rule only when its"Value Posting"is not blank. Plain default-dimension rows ("Value Posting"blank) only supply a default value and can never be violated.
The three rules
For a rule on dimension D and the dimension set being checked:
- Code Mandatory — the set must hold a non-blank value for
D. Broken when the set has no value forD. - Same Code — the set's value for
Dmust be exactly the rule's"Dimension Value Code". When that field is blank, the set must hold no value forD. Broken in every other case. - No Code — the set must hold no value for
D. Broken when it holds one.
What you can rely on
- Sell-to and bill-to customer are the same on every document the tests build.
- For any one dimension set that gets checked, at most one of its two sources carries a rule for a given dimension code — so a
"Line No."+"Dimension Code"pair is never claimed twice, and you never have to decide which of two rules wins. - The same broken rule on three lines is three rows, one per line.
Pick object IDs in the range 50100–50199 and reference other objects by name, never by ID. Captions on your own objects are good practice but not graded.
What the tests check
The grading tests build sales orders in a real company, put Default Dimension rules of each of the three kinds on the customer, on an item, on a G/L account and on a resource, bend the document's dimension sets so a rule breaks, then call CheckSalesDocument and check both the returned count and the exact rows in the buffer — "Line No." (0 for the header), "Dimension Code" and the "Value Posting" rule named. Covered: a missing mandatory value, a Same Code rule met, a Same Code rule missed by a different value and missed by no value at all, a blank Same Code rule against a line that carries a value, a No Code rule met and missed, the customer's rules reaching every line, two broken rules on one line, a description-only line that must never be reported, a plain default dimension without a rule that must never be reported, and a buffer left over from an earlier call that must be emptied. Two tests anchor the result to reality: a document whose line the precheck flags is refused by the standard posting routine, and a document the precheck accepts posts successfully.
Learn More
- Work with dimensions — default dimensions per master record, and what the
Value Postingfield is for. - Troubleshoot and correct dimensions — every dimension error that posting can raise, and the rule behind each one.
- Dimension Set Entries Overview — how a document's dimensions are stored as a shared, immutable set.
- Temporary tables — what
TableType = Temporarymeans for the buffer you fill.
Default Dimension row carries a "Value Posting" rule for one master record and one dimension, and posting checks the document's dimension *set* against those rules — per line, not just once for the document."Dimension Set ID" on the header and on each line; a single pair inside it is DimensionSetEntry.Get(DimSetID, DimensionCode), which simply fails to find anything when that dimension is not in the set. Default Dimension is keyed by "Table ID", "No.", "Dimension Code" — filter it once per source record, and skip the rows whose "Value Posting" is blank.DimensionManagement maps a line to its master table for you: SalesLineTypeToTableID(SalesLine.Type) returns Database::Item for an item line, Database::"G/L Account" for a G/L account line, and so on. Its CheckDimValuePosting(TableID, No, DimSetID) is the very check that posting runs, but it answers yes/no and stops at the first broken rule — so walk the Default Dimension rows yourself if you want to name the dimension and report all of them. Watch the Same Code branch: comparing the set's value with the rule's "Dimension Value Code" already covers the blank case, as long as a missing entry reads back as a blank value.