Changelog
All notable changes to the PO Email Notification extension are documented in this file. For detailed change documents, see the linked files below.
[1.2.0.0] - 2026-03-20
Change Document: CHANGE-v1.2.0.0.md
Security
- Migrated field ID 50119 to 80100 on Purchase Header, Warehouse Receipt Header, and Posted Whse. Receipt Header to avoid collision with BestwayUSA extension's reserved ID range (50100-50149)
- Migrated Email Scenario enum value 50149 to 80100 for the same reason
Fixed
- OnLookup concatenation bug: selecting an email from the address lookup when the field already had a value would embed the search text in the recipient list instead of appending to the existing value (CRITICAL)
- Unguarded
Get()inEmailFieldTransferSubscriberswould throw a runtime error and block warehouse receipt creation if the source Purchase Order record was missing - Four
SetLoadFieldsdeclarations were missing their corresponding filter fields — the same class of issue v1.1.1.0 was released to fix
Changed
- Added
SetLoadFieldsto thePurchHeader.Get()call inside the warehouse receipt subscriber loop, reducing the SQL projection from 200+ fields to 4 - Permission set now has
Caption = 'PO Email Notification'andAssignable = truefor better UX in BC's permission assignment UI
Removed
- Deleted
PO Email Dispatchercodeunit (80102) — dead code with no callers in the codebase
Migration Notes
- This version cannot be installed as an in-place upgrade. Uninstall the current version first (v1.0.88.5 in Production, v1.1.1.0 in Sandbox), then install v1.2.0.0 fresh. The field ID change (50119 to 80100) requires a clean schema.
- After installation, configure PO Email Setup and map the "Custom Purchase Emails" Email Scenario to an outbound email account.
[1.1.1.0] - 2026-03-16
Change Document: CHANGE-v1.1.1.0.md
Changed
- Eliminated one redundant database query per purchase receipt posting — line count for the Arrived notification is now derived in a single pass through
BuildHtmlTableFromPostedWRLines_Allrather than a separate pre-scan - Added three missing filter fields to
SetLoadFieldsdeclarations:TypeinBuildHtmlTableFromPostedWRLines_All,TypeinGetPOETA, andSource Type+Source No.in the Shipped notification'sWarehouseReceiptLinequery
[1.1.0.0] - 2026-03-16
Change Document: CHANGE-v1.1.0.0.md
Security
- Removed hardcoded Azure AD client credentials (client ID and secret) from source code — credentials are now stored in BC Isolated Storage via a new setup page
- Changed
GetAccessTokenreturn type fromTexttoSecretTextso the bearer token is never held in a plain-text variable
Added
- PO Email Setup page — administration UI for configuring Graph API tenant ID, client ID, and client secret; secret is persisted in
IsolatedStorage(DataScope::Module) and cannot be read back through the UI - PO Email Setup table — singleton setup record with
SetClientSecret,GetClientSecret,HasClientSecret, andClearClientSecretprocedures - Recipient validation —
BuildRecipientListFromPOnow trims whitespace and filters empty entries from the semicolon-delimited "Send E-mail To" field - Missing-recipient guard —
Notify_Arrived_OnWhseReceiptPostednow logs and exits early when no valid recipients are resolved, consistent with the Shipped notification - OData URL encoding — search text is URL-encoded before embedding in the Graph API
$filterquery parameter, preventing malformed URLs when display names contain&,%,+,#, or spaces - Conditional Graph search URL — when search text is empty, the filter parameter is omitted rather than applying an empty filter; result cap reduced from 500 to 50
- Comprehensive telemetry — 28 structured App Insights events covering the full notification lifecycle: setup misconfiguration (
setup.*), Graph API health (graph.token.*,graph.search.*), and all three notification paths (po.created.*,wr.shipped.*,arrived.*); each success event includes recipient count, line count, and Graph API search duration (DurationMs) - Zero-result warning (
graph.search.noresults) — logged when a Graph API search returns an empty result set; helps distinguish "no matching users" from connectivity failures - No-lines guards —
po.created.nolinesandarrived.nolineswarnings logged when the PO or posted receipt has no item lines, replacing silent exits
Changed
- Email sending switched from
Email.Send(blocking) toEmail.Enqueuevia a[TryFunction]wrapper — email failures no longer roll back purchase posting or warehouse receipt transactions - Removed
Commit()from the email lookup action inPurchOrderExt— unnecessary afterTempEmailResultswas declared as a temporary table - Removed hand-rolled
ReplaceAllprocedure; replaced with built-inText.Replace()method - Extracted duplicate HTML table header markup into a shared
TableHeaderHtml()procedure - Removed unused
PONoparameter fromBuildHtmlTableFromPostedWRLines_All - Fixed unclosed
<p>tag inBuildFooter(was missing</p>) - Improved HTML cell styling consistency across all three email templates
Fixed
TempEmailResultswas missingTableType = Temporary— without this declaration, BC would attempt to write search results to the database; the table is now correctly marked as in-memory onlyCommit()after email lookup — the original code calledCommit()inside a page trigger to flush temp table writes, which broke transactional integrity; this is no longer needed and has been removed- Unhandled HTTP errors —
GetAccessTokenandSearchEmailspreviously had no error handling on the HTTP response; both now checkIsSuccessStatusCode()and raise descriptive errors with telemetry
Migration Notes
- Deploy the new version to the sandbox and open PO Email Setup (search for it in BC) to enter the Graph API credentials. The extension will not be able to look up email addresses until setup is complete.
- Assign the PoEmailPermissionSet permission set to all users who access the email lookup or setup page.
- Map the "Custom Purchase Emails" email scenario to an active outbound email account in Settings → Email → Email Scenarios if not already configured.
[1.0.88.5] - 2025-10-01
Initial release by Sataware Technologies. Hardcoded Azure AD credentials, Email.Send (blocking), no setup page.