bcquality/microsoft/knowledge/data-modeling/document-print-and-email-actions-call-report-selections-directly.md
Michael Dieringer 83f041b662 Add 5 AL/BC patterns: document distribution (Report Selections, Document Sending Profile, Find Entries, TransferFields)
Five rules about Business Central's document distribution architecture,
verified against BCApps source and Microsoft Learn.

- custom-document-dispatch-must-not-bypass-report-selections
- document-print-and-email-actions-call-report-selections-directly
- extend-find-entries-navigate-for-new-document-types
- extend-report-selection-usage-for-new-document-types
- transferfields-mirrored-fields-must-match-type-and-length

Wired into al-data-modeling-review.md's worklist cues. Added a
disambiguation note on the TransferFields article distinguishing it from
the existing transferfields-skip-type-mismatch-can-drop-data.md
(type-mismatch skipping vs. length mismatch, which SkipFieldsNotMatchingType
does not affect).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-10 07:44:17 +02:00

99 lines
5.2 KiB
Markdown

---
bc-version: [all]
domain: data-modeling
keywords: [report-selections, document-sending-profile, print, email, post-and-send]
technologies: [al]
countries: [w1]
application-area: [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 that every
print/email path should route through — 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 ribbon actions call `table 77 "Report Selections"` directly
and are not affected by any Document Sending Profile at all. This is the
pattern BC's own base application uses for a document's plain print/email
actions: the Sales Order's "Print Confirmation"/"Email Confirmation"
actions (`codeunit "Document-Print"`, `PrintSalesOrder`/`EmailSalesHeader`)
call `ReportSelections.PrintWithDialogForCust`/`SendEmailToCust` directly,
and the posted `Purch. Inv. Header`'s own `PrintRecords` does the same
through `ReportSelection.PrintWithDialogForVend` — no customer's or
vendor's actually assigned Document Sending Profile is consulted by
either.
The unposted `Purchase Header`'s own `PrintRecords` is a partial exception
worth naming precisely: it calls `DocumentSendingProfile.TrySendToPrinterVendor(...)`,
but only as a stateless, never-`Get`'d local record carrying print-dialog
options, never a vendor's actually configured profile — that helper still
resolves the report through `ReportSelections.PrintWithDialogForVend(...)`,
the same as everywhere else.
Only the combined Post-and-Send flow resolves through Document Sending
Profile: `Sales-Post and Send` calls `Sales Invoice Header.SendProfile`,
which calls `DocumentSendingProfile.Send(...)`, which then decides
Print/Email/Disk/Electronic based on the customer's assigned profile and
only *then* calls back into `Report Selections` (for the PDF cases) or
`Electronic Document Format` (for machine-readable cases).
Whether a document needs outbound distribution at all isn't determined by
Customer-vs-Vendor, but by whether the document is genuinely *outbound* to
its counterparty. A posted Purchase Invoice records what a vendor already
billed you — nothing to send back — and its posted `Purch. Inv. Header`
exposes only a bare `PrintRecords`, no `SendProfile`/`SendRecords`/email at
all. A Purchase *Order* is genuinely outbound before posting, which is why
the full `SendProfile`/`SendRecords`/`PrintRecords` triplet lives on the
unposted `Purchase Header` instead.
## Best Practice
For a document's own interactive Print/Email actions, call the relevant
`Report Selections` procedure directly —
`PrintForCust`/`PrintWithDialogForCust`/`SendEmailToCust` for a
customer-facing document, `PrintWithDialogForVend`/`SendEmailToVendor` for
a vendor-facing one — using the usage value registered per
`extend-report-selection-usage-for-new-document-types.md`. Wire into
`Document Sending Profile` only when specifically building a combined
Post-and-Send action for that document. Before adding any send capability
at all, confirm the document is genuinely outbound to the counterparty
it's attached to; a document that only records something already received
needs print-for-reference at most, not a send path.
See sample: `document-print-and-email-actions-call-report-selections-directly.good.al`.
## Anti Pattern
Routing a document's plain, on-demand "Email" button through
`DocumentSendingProfile.Send`/`SendVendor` instead of calling
`ReportSelections.SendEmailToCust`/`SendEmailToVendor` directly. The
button's outcome now silently depends on that customer's or vendor's
assigned Document Sending Profile — if its `"E-Mail"` option happens to be
`No`, clicking "Email" does nothing observable, with no indication to the
user that a profile setting (meant for the Post-and-Send flow) is the
reason. A second version of the same mistake: adding an email action to 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`,
calling `ReportSelections.SendEmailToCust`/`PrintForCust`/`PrintWithDialogForCust`
directly), `PurchaseHeader.Table.al` (`SendProfile` at line ~6387, calling
`DocumentSendingProfile.SendVendor`), `PurchInvHeader.Table.al` (`PrintRecords`
calling `ReportSelection.PrintWithDialogForVend` directly, no send capability),
`SalesPost.Codeunit.al`
(`SendPostedDocumentRecord` at line 7660 → `SalesInvHeader.SendProfile` at
lines 7680/7699 → `DocumentSendingProfile.Send`),
`DocumentSendingProfile.Table.al` (table 60; `TrySendToPrinterVendor` at
line 552 and `SendToPrinterVendor` at line 716, called from
`PurchaseHeader.PrintRecords` at line 6357) — 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