bcquality/microsoft/knowledge/data-modeling/check-post-line-batch-pattern.md
Michael Dieringer a28ba1a1d7 Address second round of Jesper Schulz-Wedde's review on PR #156
- dimension-management-wiring.md/.good.al: split into the two distinct
  models the article was conflating - master data (Default Dimension
  records via ValidateDimValueCode/SaveDefaultDim) vs. transactional/
  document data (a single Dimension Set ID assembled via AddDimSource +
  GetDefaultDimID, verified against BCApps' ExchRateAdjmtProcess.Codeunit.al).
  Added a compiling document-table example alongside the existing master
  table one.
- Deleted api-page-flowfields-must-be-calcfields (.md/.good.al/.bad.al):
  Microsoft's own FlowFields documentation states a FlowField used as a
  control's direct source expression is automatically calculated on any
  page - no API-page exception is documented, and none could be
  reproduced.
- prefer-email-module.bad.al/.md: Codeunit Mail has no Send/GetErrorDesc
  members; fixed to the real current 7-argument CreateMessage signature,
  and corrected the claim that the legacy path "still runs" - its base
  implementation no longer sends anything, only raises integration events.
- check-post-line-batch-pattern.md/.good.al: reframed from a universal
  invariant to the standard shape, naming the real Gen./Item/CA/Res./Job/
  Insurance/Mfg. Item/FA Jnl.-Check Line/-Post Line/-Post Batch codeunits
  it's based on. Added the missing Check Line companion codeunit so the
  good fixture is internally complete.
- test-data-must-be-random-and-complete.good.al: removed leftover
  "collision-free" wording contradicting the already-corrected article text.
- fixed-choice-set-must-use-enum-not-integer.md: removed the reintroduced
  state-count heuristic ("the line is the state count"), aligned with
  binary-choice-must-be-boolean.md's semantics-based distinction.
- namespace-must-be-verified-from-source.md: removed the false claim that
  the compiler and AL Language Server use different namespace-resolution
  rules.
- intrinsic-al-functions-must-use-modern-casing.md: removed the unverified
  claim that PascalCase is the VS Code formatter's default output.

Worklist completeness: added cues for the 8 rules in data-modeling,
testing, performance, and web-services that had none (Jesper's explicit
ask), plus the same gap in all 7 style rules from this PR (not explicitly
named this round, but the identical systemic issue) - 15 cues total across
al-data-modeling-review.md, al-testing-review.md, al-performance-review.md,
al-web-services-review.md, and al-style-review.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 22:26:33 +02:00

2.5 KiB

bc-version domain keywords technologies countries application-area
all
data-modeling
posting-routine
check-line
post-line
post-batch
companion-codeunit
yes-no-wrapper
journal
al
w1
all

Split posting routines into Check Line / Post Line / Post Batch

Contributions welcome — open a PR to refine or extend this article.

Description

Business Central's own journal-based posting routines consistently follow a three-codeunit split with distinct, non-overlapping responsibilities — Codeunit "Gen. Jnl.-Check Line" / "Gen. Jnl.-Post Line" / "Gen. Jnl.-Post Batch" for the general journal, and the same <Journal>-Check Line / <Journal>-Post Line / <Journal>-Post Batch shape repeated for Item, Resource, Job, Fixed Asset, Insurance, and Cost Accounting journals: Check Line validates one line, Post Line writes exactly one line to the ledger, and Post Batch loops both across the journal. A document posting routine (posting one document at a time) calls Post Line directly and skips Post Batch. This is the standard shape to evaluate a new journal-based posting routine against, not a platform-enforced constraint — a routine with a genuinely different transaction/reuse shape may legitimately organize itself differently. But a new routine that blurs this split without a specific reason either misses functionality other code expects to call directly, or exposes an interaction surface it shouldn't.

Best Practice

Check Line reads setup/dimension data only on its first call and shows no UI beyond errors. Post Line only operates on the record passed to it — never the Journal table — so it can be called directly by other posting code, including a document posting routine. Post Batch is the only one of the three that reads and updates the Journal table, and it is the only one invoked from the Post action on a journal page. A -Post document codeunit is never called directly from a page; a page calls a -Post (Yes/No) confirmation wrapper instead, so the same -Post codeunit can also run unattended from a batch-posting report.

See sample: check-post-line-batch-pattern.good.al.

Anti Pattern

A single monolithic posting codeunit that reads the Journal table, validates lines, writes ledger entries, and shows confirmation dialogs all in one procedure. It cannot be reused by another posting routine without fabricating journal records, and it cannot run unattended because it insists on user interaction.

See sample: check-post-line-batch-pattern.bad.al.