bcquality/microsoft/knowledge/data-modeling/document-print-and-email-actions-call-report-selections-directly.md
Michael Dieringer 31206f6616 Fix four merge-critical blockers from Jesper's review; add 4 more patterns
Addresses microsoft/BCQuality#175 review feedback:
- Extend al-data-modeling-review's entry gate/relevance scope and token
  list to recognize document actions, Navigate subscribers, Report
  Selection registration, price-calculation/price-source extensibility,
  TransferFields posting-cascade mirroring, and barcode font-provider
  usage - previously excluded before any worklist cue could run.
- Fix document-print-and-email-actions-call-report-selections-directly:
  permit the legitimate stateless DocumentSendingProfile.TrySendToPrinter/
  TrySendToEMail path; rework the bad fixture to load a configured
  profile instead of demonstrating a trivial blank-record no-op.
- Fix extend-report-selection-usage-for-new-document-types: scope to the
  applicable single counterparty (ReportSelectionHandlerCZZ partitions
  strictly; only genuinely two-sided usages like Compensation need both),
  and add the page-facing usage-enum map/validate events alongside the
  filter-event subscription for full Document Layouts support.
- Fix a stale field-citation in custom-document-dispatch-must-not-bypass-
  report-selections (Custom Report Layout Code is field 7, not part of
  the 19-26 email-configuration range).
- Add deterministic positive/clean evaluation coverage (review-fixtures.json
  additionalArticles + Test-ReviewFixtures.ps1 support) so all 9 new
  good/bad pairs are actually exercised, not just present.
- Add 4 new patterns: activate-new-price-calculation-handler-via-
  onfindsupportedsetup, extend-price-source-type-must-sync-document-
  subset-enum, new-price-source-must-add-candidate-and-trigger-
  recalculation, report-barcodes-must-use-barcode-module-and-production-
  font-name.

All claims verified against live microsoft/BCApps source and Microsoft
Learn. Validators: frontmatter 0/0, review-fixtures 52 cases/17 domains
PASSED, knowledge-index 309 articles PASSED.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-24 06:33:04 +02:00

5.3 KiB

bc-version domain keywords technologies countries application-area
all
data-modeling
report-selections
document-sending-profile
print
email
post-and-send
al
w1
all

A document's own Print/Email actions call Report Selections directly; Document Sending Profile is scoped to Post-and-Send

Description

table 60 "Document Sending Profile" is not a general gateway for every print/email path — it exists specifically for the combined Post and Send action: "You can set each customer up with a preferred method of sending sales documents, so that you do not have to select a sending option every time you choose the Post and Send action" (Microsoft Learn, "Set Up Document Sending Profiles"). A document's own, ordinary Print/Email actions are unaffected by any configured profile either way: the unposted Sales Order's "Print Confirmation"/"Email Confirmation" (codeunit "Document-Print", PrintSalesOrder/EmailSalesHeader) and the posted Purch. Inv. Header's PrintRecords call Report Selections literally directly (PrintWithDialogForCust/SendEmailToCust/PrintWithDialogForVend), while the posted Sales Invoice Header's PrintRecords/EmailRecords and the unposted Purchase Header's PrintRecords go through DocumentSendingProfile.TrySendToPrinter/TrySendToEMail/ TrySendToPrinterVendor instead. Those three helpers each declare a fresh, local, never-Get'd profile record, hardcode its Printer/"E-Mail" field to a "Yes" option themselves, and feed it into SendToPrinter/SendToEMailGroupedMultipleSelection — which resolve into Report Selections just like the direct route. The table is a throwaway options carrier here, not the counterparty's configuration.

Only a genuinely configured profile changes the outcome, and that only happens for the combined Post-and-Send flow: Sales-Post and Send loads the customer's assigned profile (Get(Customer."Document Sending Profile"), or the tenant default) before Sales Invoice Header.SendProfile → DocumentSendingProfile.Send, which gates SendToPrinter/SendToEMail/SendToDisk on whatever that record holds.

Whether a document needs outbound distribution isn't determined by Customer vs. Vendor, but by whether it's genuinely outbound to that party: a posted Purchase Invoice records what a vendor already billed, so the posted Purch. Inv. Header has only a bare PrintRecords; a Purchase Order is still outbound before posting, so the rich SendProfile/SendRecords/PrintRecords triplet lives there instead.

Best Practice

For a document's own interactive Print/Email actions, either call the relevant Report Selections procedure directly — PrintForCust/PrintWithDialogForCust/SendEmailToCust for a customer-facing document, PrintWithDialogForVend/SendEmailToVendor for a vendor-facing one — or call one of Document Sending Profile's stateless TrySendToPrinter/TrySendToEMail/TrySendToPrinterVendor helpers, using the usage value registered per extend-report-selection-usage-for-new-document-types.md. Both are equally correct; neither reads the counterparty's assigned profile. Reserve a genuine Get/GetDefaultForCustomer/GetDefaultForVendor lookup and Send/SendVendor for Post-and-Send.

See sample: document-print-and-email-actions-call-report-selections-directly.good.al.

Anti Pattern

Loading the counterparty's actually assigned Document Sending Profile (or the tenant default, via Get/GetDefaultForCustomer/ GetDefaultForVendor — the same lookup Sales-Post and Send performs) and calling Send/SendVendor on it from a plain, on-demand "Email" button, instead of ReportSelections.SendEmailToCust/SendEmailToVendor directly. The button's outcome now silently depends on a profile configured for Post-and-Send — if its "E-Mail" option is No, clicking "Email" does nothing observable. A second version of the same mistake: an email action on a document that only receives from its counterparty and was never meant to send anything back.

See sample: document-print-and-email-actions-call-report-selections-directly.bad.al.

Source

BCApps DocumentPrint.Codeunit.al (EmailSalesHeader/DoPrintSalesHeader/ PrintSalesOrder → ReportSelections.SendEmailToCust/PrintForCust/ PrintWithDialogForCust directly), SalesInvoiceHeader.Table.al (PrintRecords/EmailRecords, lines 1453/1528 → TrySendToPrinter/ TrySendToEMail, lines 1462/1541, on a local never-Get'd record), PurchaseHeader.Table.al (PrintRecords line 6357 → TrySendToPrinterVendor line 6374; SendProfile line 6387 → SendVendor line 6403), PurchInvHeader.Table.al (PrintRecords → ReportSelection.PrintWithDialogForVend directly, no send capability), SalesPostandSend.Codeunit.al/SalesPost.Codeunit.al (ConfirmPostAndSend loads Get(Customer."Document Sending Profile")/GetDefault; SendPostedDocumentRecord line 7660 → SalesInvHeader.SendProfile lines 7680/7699 → DocumentSendingProfile.Send), DocumentSendingProfile.Table.al (table 60; TrySendToPrinter/TrySendToEMail lines 536/562, TrySendToPrinterVendor line 552, GetDefaultForCustomer line 195, Send/SendVendor lines 482/506) — all under src/Layers/W1/BaseApp/. Microsoft Learn, "Set Up Document Sending Profiles": https://learn.microsoft.com/dynamics365/business-central/sales-how-setup-document-send-profiles