Describe the issue
Codeunit 6785 "Withholding Tax Mgmt." procedure InsertWithholdingTax calculates and inserts vendor Withholding Tax Entry records during purchase posting, but it exposes no integration events on that path.
Realized withholding amount is always calculated as:
WithholdingTaxEntry.Amount := Round(WithholdingTaxEntry.Base * WithholdingTaxEntry."Withholding Tax %" / 100, GetAmountRoundingPrecision(WithholdingTaxEntry."Currency Code"));
Partners cannot adjust the calculated withholding amount before the entry is inserted and later applied to the purchase header / G/L.
Business scenario: some industries (for example agriculture / commodity purchases) need withholding based on quantity and a fixed fee per unit of measure (e.g. cents per bushel), not only as a percentage of invoice amount.
Related prior requests (redirected here by triage):
- ALAppExtensions #30266 — event before calling
InsertWithholdingTax with var AmountVAT (closed; contribute via BCApps)
- ALAppExtensions #30387 — refined request for event inside
InsertWithholdingTax (closed as not planned; contribute via BCApps)
After code review, the better extensibility point is inside InsertWithholdingTax, after the standard amount is calculated and before WithholdingTaxEntry.Insert(), with a var reference to the prepared Withholding Tax Entry.
App / path: src/Apps/W1/WithholdingTax
Object: Codeunit 6785 "Withholding Tax Mgmt."
Procedure: InsertWithholdingTax
There are currently no [IntegrationEvent] publishers in this codeunit. Employee WHT already has OnBeforeInsertEmployeeWHTEntry / OnAfterInsertEmployeeWHTEntry in WHTEmployeeCalculation, but the vendor purchase insert path has none.
Expected behavior
An integration event is raised after the standard realized withholding amount is calculated and before the Withholding Tax Entry is inserted, so extensions can recalculate Amount (and related rem fields) using document context.
Preferred raise point (realized branch, after amount assignment):
WithholdingTaxEntry."Unrealized Amount" := 0;
WithholdingTaxEntry."Unrealized Base" := 0;
WithholdingTaxEntry."Remaining Unrealized Amount" := 0;
WithholdingTaxEntry."Remaining Unrealized Base" := 0;
WithholdingTaxEntry.Amount := Round(WithholdingTaxEntry.Base * WithholdingTaxEntry."Withholding Tax %" / 100, GetAmountRoundingPrecision(WithholdingTaxEntry."Currency Code"));
WithholdingTaxEntry."Rem Realized Amount" := WithholdingTaxEntry.Amount;
WithholdingTaxEntry."Rem Realized Base" := WithholdingTaxEntry.Base;
WithholdingTaxEntry."Original Document No." := DocNo;
OnBeforeInsertWithholdingTaxEntry(
WithholdingTaxEntry, TransType, AmountVAT, AbsorbBase, DocNo, DocType, PayToVendCustNo);
Proposed event definition:
/// <summary>
/// Raised after the withholding tax entry amount is calculated and before the entry is inserted.
/// </summary>
[IntegrationEvent(false, false)]
local procedure OnBeforeInsertWithholdingTaxEntry(
var WithholdingTaxEntry: Record "Withholding Tax Entry";
TransType: Option Purchase,Sale;
AmountVAT: Decimal;
AbsorbBase: Decimal;
DocNo: Code[20];
DocType: Enum "Gen. Journal Document Type";
PayToVendCustNo: Code[20])
begin
end;
Why this shape (not IsHandled):
- Subscribers only need to adjust the calculated amount on the prepared entry.
- Standard insert, Abs/sign handling, and LCY conversion should continue to run.
- This matches Microsoft guidance for a regular OnBefore event when overriding the whole procedure is unnecessary.
Alternatives evaluated:
- Existing purchase posting events (
Purch.-Post / WHT purchase subscribers): fire around posting, but do not expose the in-memory Withholding Tax Entry amount calculation inside InsertWithholdingTax.
- Event only before
InsertWithholdingTax(TType::Purchase) with var AmountVAT (ALAppExtensions #30266): useful for base adjustment, but does not allow recalculating the final withholding amount after % is applied and other entry fields are set.
- Employee WHT events: not used on the vendor purchase path.
Impact considerations:
- Performance: single integration event raise; negligible.
- Data sensitivity: no new sensitive data exposure beyond existing WHT entry / document identifiers already used in this flow.
- Multi-extension risk: low; additive opt-in event. Subscribers changing
Amount should keep rem realized fields consistent.
I will provide the implementation once this issue is approved.
Steps to reproduce
- Enable Withholding Tax and configure posting setup with a withholding %.
- Post a purchase invoice / order that creates vendor withholding tax entries.
- Observe that
InsertWithholdingTax always sets WithholdingTaxEntry.Amount from Base * "Withholding Tax %" / 100.
- Search codeunit 6785 for
[IntegrationEvent] publishers around amount calculation / insert — none exist.
- Attempt to implement a per-bushel / fixed-fee withholding calculation from a PTE — not possible without modifying first-party code or replacing the whole flow.
Additional context
- Event quality intent: before-insert on a prepared record (valid pattern per Types of events for extensibility).
- Optional alternative placement: immediately before
WithholdingTaxEntry.Insert() (covers realized + unrealized). Preferred placement above keeps Abs/sign and LCY conversion running on subscriber-adjusted amounts for the realized invoice scenario.
- Contribution process followed: CONTRIBUTING.md Type A (small improvement / paper-cut extensibility). Waiting for the
approved label before opening a PR.
- Previous BCApps issue #9846 was closed when we briefly filed this in ALAppExtensions; triage confirmed BCApps is the correct place.
I will provide a fix for a bug
Describe the issue
Codeunit 6785
"Withholding Tax Mgmt."procedureInsertWithholdingTaxcalculates and inserts vendorWithholding Tax Entryrecords during purchase posting, but it exposes no integration events on that path.Realized withholding amount is always calculated as:
Partners cannot adjust the calculated withholding amount before the entry is inserted and later applied to the purchase header / G/L.
Business scenario: some industries (for example agriculture / commodity purchases) need withholding based on quantity and a fixed fee per unit of measure (e.g. cents per bushel), not only as a percentage of invoice amount.
Related prior requests (redirected here by triage):
InsertWithholdingTaxwithvar AmountVAT(closed; contribute via BCApps)InsertWithholdingTax(closed as not planned; contribute via BCApps)After code review, the better extensibility point is inside
InsertWithholdingTax, after the standard amount is calculated and beforeWithholdingTaxEntry.Insert(), with avarreference to the preparedWithholding Tax Entry.App / path:
src/Apps/W1/WithholdingTaxObject: Codeunit 6785
"Withholding Tax Mgmt."Procedure:
InsertWithholdingTaxThere are currently no
[IntegrationEvent]publishers in this codeunit. Employee WHT already hasOnBeforeInsertEmployeeWHTEntry/OnAfterInsertEmployeeWHTEntryinWHTEmployeeCalculation, but the vendor purchase insert path has none.Expected behavior
An integration event is raised after the standard realized withholding amount is calculated and before the
Withholding Tax Entryis inserted, so extensions can recalculateAmount(and related rem fields) using document context.Preferred raise point (realized branch, after amount assignment):
Proposed event definition:
Why this shape (not IsHandled):
Alternatives evaluated:
Purch.-Post/ WHT purchase subscribers): fire around posting, but do not expose the in-memoryWithholding Tax Entryamount calculation insideInsertWithholdingTax.InsertWithholdingTax(TType::Purchase)withvar AmountVAT(ALAppExtensions #30266): useful for base adjustment, but does not allow recalculating the final withholding amount after%is applied and other entry fields are set.Impact considerations:
Amountshould keep rem realized fields consistent.I will provide the implementation once this issue is approved.
Steps to reproduce
InsertWithholdingTaxalways setsWithholdingTaxEntry.AmountfromBase * "Withholding Tax %" / 100.[IntegrationEvent]publishers around amount calculation / insert — none exist.Additional context
WithholdingTaxEntry.Insert()(covers realized + unrealized). Preferred placement above keeps Abs/sign and LCY conversion running on subscriber-adjusted amounts for the realized invoice scenario.approvedlabel before opening a PR.I will provide a fix for a bug