- Resolve conflicts in al-data-modeling-review.md by keeping both sides' additions (folder-path support, InitRecord/Round cues from upstream; the 9 document-distribution/pricing/barcode cues from this branch). - Switch the data-modeling evaluation override from an ad-hoc additionalArticles field to upstream's now-established articles[] convention (used elsewhere for finance/scm/query/reporting/style), removing the redundant parallel code path from Test-ReviewFixtures.ps1. - Fix all 9 new articles' sample references to the markdown-link READ convention required by Knowledge-Retrieval.ps1's Assert-SampleLink (plain backticks satisfy validate_frontmatter.py's regex alone but not this stricter check - both validators must pass). Validators: frontmatter 0/0, review-fixtures 126 cases/20 domains PASSED, knowledge-index 342 articles/575 samples PASSED, skill-index 19 review leaves PASSED. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
5.5 KiB
| bc-version | domain | keywords | technologies | countries | application-area | |||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
data-modeling |
|
|
|
|
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