Skip to content

Extract IT withholding tax code - #9185

Open
Alexander-Ya wants to merge 10 commits into
mainfrom
bugs/Extract-IT-Withholding-Tax-code
Open

Extract IT withholding tax code#9185
Alexander-Ya wants to merge 10 commits into
mainfrom
bugs/Extract-IT-Withholding-Tax-code

Conversation

@Alexander-Ya

@Alexander-Ya Alexander-Ya commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

What & why

Linked work

Fixes AB#641996

How I validated this

  • I read the full diff and it contains only changes I intended.
  • I built the affected app(s) locally with no new analyzer warnings.
  • I ran the change in Business Central and confirmed it behaves as expected.
  • I added or updated tests for the new behavior, or explained below why none are needed.

What I tested and the outcome (required — be specific: scenarios, commands, screenshots for UI changes)

Risk & compatibility

@Alexander-Ya
Alexander-Ya requested a review from a team July 7, 2026 13:28
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Copilot PR Review

Iteration 7 · Outcome: completed

Knowledge source: https://github.com/microsoft/BCQuality@822cae1b2771ac25f665f73369f69093bd4fd630

Findings by domain

Findings split into Knowledge-backed (cite a BCQuality article) and Agent (the agent's own judgement, no matching BCQuality rule).

Domain Findings Knowledge-backed Agent Inline Fallback
Accessibility 3 3 0 1 1
Agent 1 0 1 0 0
Privacy 1 1 0 1 0
Security 1 1 0 1 0
Style 7 7 0 1 3
Upgrade 1 1 0 1 0

Totals: 13 knowledge-backed · 1 agent findings.

Orchestrator pre-filter (13 file(s) excluded)

  • layer-disabled (knowledge) : 13 file(s)

Findings produced by the Copilot CLI agent against BCQuality at 822cae1b2771ac25f665f73369f69093bd4fd630. Reply 👎 on any inline comment to flag false positives.

@Alexander-Ya Alexander-Ya added the Finance GitHub request for Finance area label Jul 7, 2026
#endif
end;

#if not CLREAN29

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟠\ High\ Severity\ —\ Upgrade} \quad \color{gray}{\texttt{\small Iteration\ 2}}$

The obsoleted procedure 'CheckWithholdTax' in Gen.

Jnl.-Post Line is guarded by '#if not CLREAN29' — the compiler symbol is misspelled ('CLREAN29' instead of 'CLEAN29'). Every other obsolete-removal block introduced in this same PR (in this file and in PurchPost.Codeunit.al) correctly uses '#if not CLEAN29'. Because 'CLREAN29' is never a real build symbol, 'not CLREAN29' is always true, so this block will never be compiled out — not even in a CLEAN29 build — defeating the staged-removal mechanic the referenced guidance describes ('the standard mechanic for retiring the actual implementation body is to remove the #if not CLEAN block in the same release that flips the state to Removed'). The obsolete wrapper will silently survive indefinitely alongside its now-duplicated logic in 'WHT Gen. Jnl.-Post Line IT'.

Suggested change
#if not CLREAN29
#if not CLEAN29

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

Caption = 'Contribution';
Image = "Report";
RunObject = Report Contribution;
ToolTip = 'Get a report of social security and workers´Š¢ compensation contribution taxes on non-inventory services that you have purchased from an independent contractor or consultant.';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Accessibility} \quad \color{gray}{\texttt{\small Iteration\ 3}}$

Two role-center tooltips in this page extension contain mojibake (workers´Š¢ compensation) instead of readable text, so users will see corrupted UI copy.

Replace the corrupted characters in both tooltips with a normal apostrophe or typographic apostrophe (workers' compensation / workers' compensation).

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

codeunit 12111 "WHT Gen. Journal Line IT"
{

[EventSubscriber(ObjectType::Table, Database::"Gen. Journal Line", 'OnAccountNoOnValidateOnBeforeCreateDim', '', true, false)]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟠\ High\ Severity\ —\ Performance} \quad \color{gray}{\texttt{\small Iteration\ 3}}$

The new Gen.

Journal Line subscribers for Account No. and Document Date immediately delegate to DeleteTmpWithhSocSec/UpdateTmpWithholdingContribution, which read the persistent Tmp Withholding Contribution table on every validation. This matches the anti-pattern of doing database work in frequently-fired subscribers without a cheap in-memory guard; add a fast exit so only lines that can actually have withholding state touch the table.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

}

var
Text12100: Label 'You cannot create the withhold entry from entry %1 because it''s an %2 Document.';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Style} \quad \color{gray}{\texttt{\small Iteration\ 3}}$

Label Text12100 has two placeholders (%1, %2) but no Comment explaining them.

Translators cannot infer from the text alone that %1 is the entry number and %2 is the document type, so the label should document both placeholders explicitly.

Suggested change
Text12100: Label 'You cannot create the withhold entry from entry %1 because it''s an %2 Document.';
Text12100: Label 'You cannot create the withhold entry from entry %1 because it''s an %2 Document.', Comment = '%1 = Entry No., %2 = Document Type';

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

$\textbf{🟠\ High\ Severity\ —\ Upgrade} \quad \color{gray}{\texttt{\small Iteration\ 3}}$

This PR deletes WHT-backed fields directly from existing base tables and reintroduces them in tableextensions (for example Vendor, Vendor Templ., and Gen.

Journal Line) with no Pending deprecation window. That is an immediate contract break for dependent extensions that still compile against the base-table symbols; per the referenced guidance, these fields need a staged Pending → Removed lifecycle instead of disappearing in one release. Notably, other parts of this same PR (e.g. procedures in GenJnlPostLine.Codeunit.al and PurchPost.Codeunit.al) correctly wrap the moved logic in #if not CLEAN29 with [Obsolete(...)] attributes, showing the staged-removal convention was known but not applied consistently to the table fields themselves.

Knowledge:

Line mapping was unavailable, so this was posted as an issue comment.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

$\textbf{🟠\ High\ Severity\ —\ Upgrade} \quad \color{gray}{\texttt{\small Iteration\ 3}}$

The move also removes public base-object entry points outright (OnBeforeValidateFiscalCode on Vendor and procedures such as DeleteTmpWithhSocSec / InitFields on Gen.

Journal Line) instead of first marking them obsolete with ObsoleteState, ObsoleteReason, and ObsoleteTag. Downstream extensions get no deprecation guidance and no versioned transition path before these symbols disappear.

Knowledge:

Line mapping was unavailable, so this was posted as an issue comment.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

end;

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Gen. Jnl.-Post Line", 'OnPrepareTempVendLedgEntryOnBeforeCheckAgainstApplnCurrency', '', true, false)]
local procedure OnPrepareTempVendLedgEntryOnBeforeCheckAgainstApplnCurrency(GenJournalLine: Record "Gen. Journal Line"; OldVendorLedgerEntry: Record "Vendor Ledger Entry")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🔴\ Critical\ Severity\ —\ Other} \quad \color{gray}{\texttt{\small Iteration\ 4}}$

This subscriber does not copy the publisher signature exactly.

OnPrepareTempVendLedgEntryOnBeforeCheckAgainstApplnCurrency is published with (GenJournalLine, NewCVLedgerEntryBuffer, OldVendorLedgerEntry), but the subscriber skips the middle parameter and makes its second parameter OldVendorLedgerEntry. For event subscribers, the parameter list must match the publisher order; skipping a non-trailing parameter prevents the subscriber from binding/compiling.

Suggested change
local procedure OnPrepareTempVendLedgEntryOnBeforeCheckAgainstApplnCurrency(GenJournalLine: Record "Gen. Journal Line"; OldVendorLedgerEntry: Record "Vendor Ledger Entry")
local procedure OnPrepareTempVendLedgEntryOnBeforeCheckAgainstApplnCurrency(GenJournalLine: Record "Gen. Journal Line"; NewCVLedgerEntryBuffer: Record "CV Ledger Entry Buffer"; OldVendorLedgerEntry: Record "Vendor Ledger Entry")

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

codeunit 12138 "WHT Gen. Jnl.-Post Line IT"
{
var
Text1130023: Label 'Because this invoice includes Withholding Tax, it should not be applied directly. Please use the function Payment Journals -> Payments -> Withh.Tax-Soc.Sec.';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Other} \quad \color{gray}{\texttt{\small Iteration\ 4}}$

Text1130023 is passed to Error() in this codeunit, but its name has no approved suffix.

Per AA0074, error labels should use an Err suffix so the call-site contract is visible from the identifier.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

}

var
Text12100: Label 'You cannot create the withhold entry from entry %1 because it''s an %2 Document.';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Other} \quad \color{gray}{\texttt{\small Iteration\ 4}}$

Text12100 is passed to Error() from this page extension, but its name has no approved suffix.

Per AA0074, error labels should use an Err suffix instead of a generic Text#### identifier.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

[EventSubscriber(ObjectType::Codeunit, Codeunit::"Purch.-Post", 'OnBeforeCheckPostRestrictions', '', true, false)]
local procedure OnBeforeCheckPostRestrictions(var PurchaseHeader: Record "Purchase Header"; var IsHandled: Boolean)
begin
CheckWithholdingTaxTotalAmount(PurchaseHeader);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Other} \quad \color{gray}{\texttt{\small Iteration\ 4}}$

This codeunit calls its own procedures as bare identifiers (CheckWithholdingTaxTotalAmount, PostWithhSocSec, GetCompWithhTaxTotalAmount) instead of this.<procedure>(...).

The this prefix is the BC style convention for explicit self-reference inside codeunits.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

@alexei-dobriansky

Copy link
Copy Markdown
Contributor

Agentic PR Review - Round 1

Recommendation: Request Changes

What this PR does

This PR moves the Italian withholding tax customization out of base objects and into WHT-prefixed table, page, and codeunit extensions. It also adds BaseApp events so the new subscribers can run in the old posting and validation paths.

The extraction is a coherent feature increment and follows the same broad direction as the NL TrMode and ES Cartera extractions. The new event publishers are present in the in-repo IT BaseApp changes, and the main posting subscribers map back to the removed code paths. The PR is not ready because required checks fail, the work item link is missing, and the field/API move is not proven upgrade-safe.

Suggestions

S1 - Make the IT app builds pass
The IT Default and Clean builds fail. Default fails on removed role-center action names (Action1130000 and Contribution), and Clean fails because codeunits 12201 and 12211 already exist in the Base Application dependency. Preserve the public action identifiers and choose non-conflicting object IDs before merge.

S2 - Link the ADO work item
The PR body has no AB# link, and the internal work-item validation check fails. Add the approved Slice/Deliverable or bug link so reviewers can verify the scope and so the required check passes.

S3 - Make the field move upgrade-safe
The PR deletes WHT fields from Vendor, Vendor Templ., and Gen. Journal Line and adds them back in tableextensions. That can break dependent extensions or data upgrade if it is not staged. Use the same deprecation and upgrade path as the other extracted public members, or prove that the move keeps symbols and data compatible.

S4 - Add a withholding tax regression test
No test file changes are included. Payment posting and withholding tax are financially sensitive, and the W1 WithholdingTax test app already has test infrastructure. Add a test that posts an Italian WHT purchase/payment scenario and verifies the expected realized and unrealized entries after the extraction.

Risk assessment and necessity

Risk: This touches vendor master data, general journal lines, purchase posting, payment journals, role centers, permissions, and withholding tax posting. A wrong event point or missing upgrade step can change tax amounts, lose WHT field data, or break dependent extensions. The failing IT builds are direct evidence that the extraction is incomplete.

Necessity: Extracting the IT withholding tax customization is a valid direction and matches the NL/ES extraction pattern. The scope is still too risky to merge until the work item is linked, required checks pass, public symbols/data are protected, and a focused WHT posting regression test exists.


[AI-PR-REVIEW] version=1 system=github pr=9185 round=1 by=alexei-dobriansky at=2026-07-08 lastSha=80daea9cf3bf4a09f8d52143f4aa5e5e8e3afac0 suggestions=S1,S2,S3,S4

Comment on lines +11 to +14
var
ComputedWithholdingTax: Record "Computed Withholding Tax";
[SecurityFiltering(SecurityFilter::Filtered)]
WithholdingTax: Record "Withholding Tax";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Security} \quad \color{gray}{\texttt{\small Iteration\ 5}}$

In the extracted codeunit 'WHT Navigate Handler IT', the variable ComputedWithholdingTax: Record "Computed Withholding Tax" no longer carries [SecurityFiltering(SecurityFilter::Filtered)], while the sibling WithholdingTax variable in the same var block still does.

The original code this was extracted from (src/Layers/IT/BaseApp/Local/Foundation/Navigate/LocalNavigateHandler.Codeunit.al, pre-PR) applied [SecurityFiltering(SecurityFilter::Filtered)] to both variables. Dropping the attribute on ComputedWithholdingTax means the Navigate page's count/lookup against that table will no longer apply the record-level security filter, which can let a user without permission on filtered records see or count rows outside their allowed scope. Impact would normally warrant 'major', but per agent-finding severity rules it is capped at 'minor' here since no dedicated knowledge article backs the SecurityFiltering attribute pattern yet; this should be promoted to a knowledge-backed rule.

Recommendation:

  • restore the attribute — [SecurityFiltering(SecurityFilter::Filtered)] immediately before the ComputedWithholdingTax: Record "Computed Withholding Tax"; declaration.
Suggested change
var
ComputedWithholdingTax: Record "Computed Withholding Tax";
[SecurityFiltering(SecurityFilter::Filtered)]
WithholdingTax: Record "Withholding Tax";
var
[SecurityFiltering(SecurityFilter::Filtered)]
ComputedWithholdingTax: Record "Computed Withholding Tax";
[SecurityFiltering(SecurityFilter::Filtered)]
WithholdingTax: Record "Withholding Tax";

Agent judgement — not directly backed by a BCQuality knowledge article.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

end;

[EventSubscriber(ObjectType::Table, Database::"Purchase Header", 'OnBeforeShowPostedDocsToPrintCreatedMsg', '', true, false)]
local procedure OnBeforeShowPostedDocsToPrintCreatedMsg(var PurchaseHeader: Record "Purchase Header")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🔴\ Critical\ Severity\ —\ Style} \quad \color{gray}{\texttt{\small Iteration\ 5}}$

The event subscriber OnBeforeShowPostedDocsToPrintCreatedMsg in the new codeunit 'WHT Purchase Header IT' declares only one parameter, var PurchaseHeader: Record "Purchase Header", but the publisher in Purchase Header (src/Layers/IT/BaseApp/Purchases/Document/PurchaseHeader.Table.al, line 9381) declares (var ShowPostedDocsToPrint: Boolean; HideValidationDialog: Boolean; var PurchaseHeader: Record "Purchase Header").

AL binds event subscribers positionally against the publisher's leading parameters; a subscriber may omit trailing parameters but its declared parameters must match the publisher's from the first one onward. Here the subscriber's sole parameter is type Record where the publisher's first parameter is Boolean, so the signatures do not align and the subscriber will not bind/compile correctly. Fix by reproducing the publisher's full parameter list (or at least its leading Boolean, Boolean parameters) before the Record parameter, e.g. (var ShowPostedDocsToPrint: Boolean; HideValidationDialog: Boolean; var PurchaseHeader: Record "Purchase Header").

Suggested fix (apply manually — could not be anchored as a one-click suggestion):

    [EventSubscriber(ObjectType::Table, Database::"Purchase Header", 'OnBeforeShowPostedDocsToPrintCreatedMsg', '', true, false)]
    local procedure OnBeforeShowPostedDocsToPrintCreatedMsg(var ShowPostedDocsToPrint: Boolean; HideValidationDialog: Boolean; var PurchaseHeader: Record "Purchase Header")

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

using Microsoft.Foundation.Address;
using Microsoft.Utilities;

tableextension 12201 "WHT VEndor IT" extends Vendor

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Style} \quad \color{gray}{\texttt{\small Iteration\ 5}}$

The new table extension is named "WHT VEndor IT" (internal object name) — the 'E' in 'VEndor' is capitalized, a clear spelling typo of 'Vendor'.

It doesn't break compilation, but it is inconsistent with every sibling object in this PR (WHT Vendor Card IT, WHT Vendor Templ IT, WHT Vendor IT codeunit) and will look wrong in object lists, telemetry, and future greps for 'Vendor'. Recommend renaming to "WHT Vendor IT" for consistency before merge.

Suggested change
tableextension 12201 "WHT VEndor IT" extends Vendor
tableextension 12201 "WHT Vendor IT" extends Vendor

Agent judgement — not directly backed by a BCQuality knowledge article.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

@alexei-dobriansky

Copy link
Copy Markdown
Contributor

Agentic PR Review - Round 2

Recommendation: Request Changes

What this PR does

This PR extracts the Italian withholding tax code from base objects into WHT-prefixed object extensions. Since round 1, the new commit moves more bank payment, navigate, purchase, and withholding references into the WHT area.

The round-2 changes are not enough. The IT Default and Clean builds still fail, the PR body still has no AB# link, the field move still has no upgrade proof, and no withholding-tax regression test was added. The new manual payment split also leaves an edited WHT code path at risk of being ignored.

Status of previous suggestions
ID Title Status Author response
S1 Make the IT app builds pass Not addressed No response. Commit e566fd84cd updates references, but Build Apps IT (Default) and Build Apps IT (Clean) still fail. Current errors include AL0118 for VendorNo in WHTManualVendorPaymentLine.PageExt.al and unused using directives.
S2 Link the ADO work item Not addressed No response. The PR body still has no AB# link, and For Microsoft: Validate link to internal work items is still failed.
S3 Make the field move upgrade-safe Not addressed No response. The PR still removes WHT fields from Vendor, Vendor Templ., and Gen. Journal Line and recreates them in tableextensions, with no targeted upgrade, DataTransfer, or staging code in the changed WHT files.
S4 Add a withholding tax regression test Not addressed No response. The PR still has no test file changes for the withholding-tax posting or manual payment scenarios.
New observations (commits since round 1)

S5 - Preserve manual WHT code overrides
The new subscriber in WithholdingContribution.Codeunit.al sets the vendor bill line from the Vendor record when a manual line is inserted. The manual page still shows editable WHT fields in WHTManualVendorPaymentLine.PageExt.al, but edited page values are not passed to SetWithholdCode() or SetSocialSecurityCode(). Pass those values through the event, or make the UI read-only if manual overrides are no longer supported.

Risk assessment and necessity

Risk: This is still high risk. The PR touches vendor master data, general journal lines, purchase posting, manual vendor payments, role centers, permissions, and withholding tax posting. The current failing IT builds prove the extraction is incomplete, and the unresolved field move can still break upgrade or dependent extensions.

Necessity: Extracting the IT withholding tax customization is still a valid direction. It should not merge until the required checks pass, the work item is linked, the field move is made upgrade-safe or proven safe, focused WHT regression coverage exists, and the manual payment WHT values are preserved.


[AI-PR-REVIEW] version=1 system=github pr=9185 round=2 by=alexei-dobriansky at=2026-07-08 lastSha=e566fd84cdf453ed2b7d609e29dc15d261681a41 suggestions=S1:notaddressed,S2:notaddressed,S3:notaddressed,S4:notaddressed,S5:new parentRound=1

{
fields
{
field(12101; "Fiscal Code"; Code[20])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🔴\ Critical\ Severity\ —\ Other} \quad \color{gray}{\texttt{\small Iteration\ 6}}$

This PR deletes persisted WHT fields 12101, 12130, 12131, and 12133-12138 from table 81 and recreates them in tableextension 12200.

Reusing the field numbers does not migrate stored values into extension storage, so existing Gen. Journal Line data will be lost on upgrade unless the old fields are staged through obsoletion and a Subtype = Upgrade migration copies the data before final removal.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

{
fields
{
field(12101; "Fiscal Code"; Code[20])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🔴\ Critical\ Severity\ —\ Other} \quad \color{gray}{\texttt{\small Iteration\ 6}}$

This PR removes Vendor fields 12101-12122, 12126-12131, and 12184-12185 from table 23 and redefines them in tableextension 12201.

That is a schema move to new storage with no Pending obsoletion metadata on the old fields and no upgrade codeunit to backfill the new extension fields, so existing vendor WHT data will come up blank after upgrade.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

{
fields
{
field(12101; "Fiscal Code"; Code[20])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🔴\ Critical\ Severity\ —\ Other} \quad \color{gray}{\texttt{\small Iteration\ 6}}$

This PR removes Vendor Templ.

fields 12101-12120, 12122, and 12126-12131 from the base table and recreates them in tableextension 12202. Existing template records do not get copied into extension storage automatically, and the diff adds neither obsoletion metadata nor any Subtype = Upgrade/DataTransfer migration, so WHT defaults stored in vendor templates will be stranded on upgrade.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

@alexei-dobriansky

Copy link
Copy Markdown
Contributor

Agentic PR Review - Round 3

Recommendation: Request Changes

What this PR does

This PR extracts the Italian withholding tax code from base objects into WHT-prefixed object extensions. Since round 2, commit c0c9060382 only moves VendorNo to a protected page variable and removes two unused using directives.

Those changes look like build-error cleanup, but the PR is still not ready. The IT Default and Clean build jobs are still IN_PROGRESS, so there is no passing IT build yet. The PR body still has no AB# link, the field move still has no upgrade or obsoletion proof, no WHT regression test was added, and manual WHT code overrides are still not preserved.

Status of previous suggestions
ID Title Status Author response
S1 Make the IT app builds pass Not addressed No response after round 2. Commit c0c9060382 fixes likely compile errors, but Build Apps IT (Default) and Build Apps IT (Clean) are still IN_PROGRESS, not passing.
S2 Link the ADO work item Not addressed No response after round 2. The PR body still has no AB# link, and For Microsoft: Validate link to internal work items is still FAILURE.
S3 Make the field move upgrade-safe Not addressed No response after round 2. The round-3 diff adds no upgrade code, DataTransfer, staging code, or obsoletion path for the fields moved from Vendor, Vendor Templ., and Gen. Journal Line into tableextensions.
S4 Add a withholding tax regression test Not addressed No response after round 2. There are still no test file changes for the withholding-tax posting or manual payment scenarios.
S5 Preserve manual WHT code overrides Not addressed No response after round 2. The manual payment page extension still has editable WHT fields, but the insert subscriber still calls SetWithholdCode(Vendor."Withholding Tax Code") and SetSocialSecurityCode(Vendor."Social Security Code") instead of using the edited page values.
New observations (commits since round 2)

None - commit c0c9060382 only contains compile-cleanup changes, and it does not introduce a separate new issue.

Risk assessment and necessity

Risk: This is still high risk. The PR touches vendor master data, general journal lines, purchase posting, manual vendor payments, permissions, role centers, and withholding tax posting. The field move and manual payment behavior can affect upgrade, dependent extensions, and financially sensitive WHT values.

Necessity: Extracting the IT withholding tax customization is still a valid direction. It should not merge until the required checks pass, the work item is linked, the field move has an upgrade-safe path or clear proof, focused WHT regression coverage exists, and manual payment WHT values are preserved.


[AI-PR-REVIEW] version=1 system=github pr=9185 round=3 by=alexei-dobriansky at=2026-07-08 lastSha=c0c9060382f8174c48b6e29526466eaa77a7a715 suggestions=S1:notaddressed,S2:notaddressed,S3:notaddressed,S4:notaddressed,S5:notaddressed parentRound=2

{
addafter("Vendor Sheet - Print")
{
action("Withholding Taxes")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Accessibility} \quad \color{gray}{\texttt{\small Iteration\ 7}}$

The new WHT Finance Manager role-center extension re-adds six withholding-tax actions without any ToolTip properties (Withholding Taxes, Contribution, Summary Withholding Payment, Compensation Details, Certifications, and Withhold Tax Code).

That leaves the new commands without hover/help text in the final UI after this refactor; add action-specific ToolTip text to each action before merge.

Agent judgement — not directly backed by a BCQuality knowledge article.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

field(12117; "Country of Fiscal Domicile"; Code[10])
{
Caption = 'Country/Region of Fiscal Domicile';
DataClassification = EndUserIdentifiableInformation;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Privacy} \quad \color{gray}{\texttt{\small Iteration\ 7}}$

WHTVendorTemplIT.TableExt classifies "Contribution Fiscal Code" as CustomerContent, but the field stores a fiscal/tax code and is therefore direct end-user identifying data.

That under-classifies this moved field versus the corresponding Vendor field and can make GDPR/data-classification surfaces treat a tax identifier as generic customer content. Classify it as EndUserIdentifiableInformation instead.

Suggested change
DataClassification = EndUserIdentifiableInformation;
DataClassification = EndUserIdentifiableInformation;

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

$\textbf{🟡\ Medium\ Severity\ —\ Style} \quad \color{gray}{\texttt{\small Iteration\ 7}}$

The new Labels Text12100 and Text12101 keep legacy Text#### names.

Per AA0074, new labels should use an approved suffix so the identifier shows whether the text is an error, caption label, or general text.

Knowledge:

Posting this finding as an issue comment because inline comment placement failed.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

$\textbf{🟡\ Medium\ Severity\ —\ Style} \quad \color{gray}{\texttt{\small Iteration\ 7}}$

Text12101 has three placeholders but no Comment describing what %1, %2, and %3 represent.

Translators cannot infer from the label alone that these are the missing field caption, field value, and table caption.

        Text12101: Label '%1 %2 does not exist in table %3.', Comment = '%1 = field caption, %2 = field value, %3 = table caption';

Knowledge:

Posting this finding as an issue comment because inline comment placement failed.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

$\textbf{🟡\ Medium\ Severity\ —\ Style} \quad \color{gray}{\texttt{\small Iteration\ 7}}$

The new page-scoped Labels Text11200, Text11201, and Text11202 use legacy Text#### names instead of an approved suffix (Lbl/Txt).

Per AA0074, new labels should carry a suffix that reflects how the text is consumed.

Knowledge:

Posting this finding as an issue comment because inline comment placement failed.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

@alexei-dobriansky

Copy link
Copy Markdown
Contributor

Agentic PR Review - Round 4

Recommendation: Request Changes

What this PR does

This PR extracts the Italian withholding tax code from base objects into WHT-prefixed object extensions. Since round 3, commit a36b1afc6f2a6d460f27c1ffcc9e813d596dcbfe only changes two WHT role-center page extensions: it restores the Action1130000 action identifier and adds a Contribution action.

Those changes are still not enough. The current Build Apps IT (Default) and Build Apps IT (Clean) checks fail, and the internal work-item validation check also fails. The current diff still does not add an AB# link, upgrade-safe field migration, WHT regression tests, or a fix for the manual WHT code override path.

Status of previous suggestions
ID Title Status Author response
S1 Make the IT app builds pass Not addressed No author response after round 3. Commit a36b1afc6 changes two role-center actions, but Build Apps IT (Default) and Build Apps IT (Clean) are still FAILURE. The current log still reports analyzer warnings for the moved role-center actions, including missing tooltips for Withholding Taxes, Contribution, Summary Withholding Payment, and Compensation Details.
S2 Link the ADO work item Not addressed No author response after round 3. The PR body still has no AB# link, and For Microsoft: Validate link to internal work items is still FAILURE.
S3 Make the field move upgrade-safe Not addressed No author response after round 3. The round-4 diff adds no upgrade code, DataTransfer, staging code, or obsoletion path for the fields moved from Vendor, Vendor Templ., and Gen. Journal Line into tableextensions.
S4 Add a withholding tax regression test Not addressed No author response after round 3. The round-4 diff changes only role-center page extensions, and the full PR still has no test file changes for withholding-tax posting or manual payment scenarios.
S5 Preserve manual WHT code overrides Not addressed No author response after round 3. The manual payment page extension still exposes editable WHT variables, but the insert subscriber still sets the vendor bill line from Vendor."Withholding Tax Code" and Vendor."Social Security Code" instead of using the edited page values.
New observations (commits since round 3)

None - commit a36b1afc6 is limited to role-center build cleanup and does not introduce a separate new issue beyond the still-failing build covered by S1.

Risk assessment and necessity

Risk: This is still high risk. The PR touches vendor master data, general journal lines, purchase posting, manual vendor payments, permissions, role centers, and withholding tax posting. The failed IT builds prove the extraction is still incomplete, and the unresolved field move and manual payment behavior can affect upgrade, dependent extensions, and financially sensitive WHT values.

Necessity: Extracting the IT withholding tax customization is still a valid direction. It should not merge until the required checks pass, the work item is linked, the field move has an upgrade-safe path or clear proof, focused WHT regression coverage exists, and manual payment WHT values are preserved.


[AI-PR-REVIEW] version=1 system=github pr=9185 round=4 by=alexei-dobriansky at=2026-07-09 lastSha=a36b1afc6f2a6d460f27c1ffcc9e813d596dcbfe suggestions=S1:notaddressed,S2:notaddressed,S3:notaddressed,S4:notaddressed,S5:notaddressed parentRound=3

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

$\textbf{🟡\ Medium\ Severity\ —\ Accessibility} \quad \color{gray}{\texttt{\small Iteration\ 7}}$

This new card page adds field controls without explicit Caption properties and relies on inherited table captions instead.

The caption rule expects page fields to declare their own user-facing labels so translation and page-specific wording do not depend on table metadata.

Knowledge:

Posting this finding as an issue comment because inline comment placement failed.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

{
addafter("Last Date Modified")
{
field("Fiscal Code"; Rec."Fiscal Code")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Accessibility} \quad \color{gray}{\texttt{\small Iteration\ 7}}$

The extension reintroduces a large block of Vendor Card fields without explicit Caption properties.

That leaves the UI dependent on table captions, and aliases such as First Name2/Last Name2 especially need deliberate page captions rather than inherited metadata.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

field(12109; "Date of Birth"; Date)
{
Caption = 'Date of Birth';
DataClassification = CustomerContent;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Privacy} \quad \color{gray}{\texttt{\small Iteration\ 7}}$

The extracted Vendor field "Date of Birth" is classified as CustomerContent, but it stores directly identifying personal data.

Per the referenced guidance, table fields holding personal data should use the classification that matches the stored data; this field should be classified as EndUserIdentifiableInformation.

Suggested change
DataClassification = CustomerContent;
DataClassification = EndUserIdentifiableInformation;

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

Caption = 'Date of Birth';
DataClassification = EndUserIdentifiableInformation;
}
field(12110; "Birth City"; Text[30])

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟠\ High\ Severity\ —\ Security} \quad \color{gray}{\texttt{\small Iteration\ 7}}$

The extracted vendor-template fields "Birth City", "Birth Post Code", "Residence Post Code", and "Residence City" disable TableRelation validation with ValidateTableRelation = false but do not add any replacement OnValidate existence checks.

Because Vendor Template data is user-editable setup, this allows invalid postcode/city references to be stored and later propagated into vendors.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

$\textbf{🟡\ Medium\ Severity\ —\ Style} \quad \color{gray}{\texttt{\small Iteration\ 7}}$

The extracted table introduces Text12100 and Text12101 as labels used only in Error(...) calls.

Per the approved suffix guidance, error labels should use an Err suffix so the call-site contract is obvious and AA0074 does not flag them.

Knowledge:

Posting this finding as an issue comment because inline comment placement failed.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

$\textbf{🟡\ Medium\ Severity\ —\ Style} \quad \color{gray}{\texttt{\small Iteration\ 7}}$

The label %1 %2 does not exist in table %3. has three placeholders but no Comment parameter.

Translators cannot infer from the string alone that %1 is a field caption, %2 is the entered code value, and %3 is the table caption.

        Text12101: Label '%1 %2 does not exist in table %3.', Comment = '%1 = field caption, %2 = entered code value, %3 = table caption';

Knowledge:

Posting this finding as an issue comment because inline comment placement failed.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

$\textbf{🟡\ Medium\ Severity\ —\ Style} \quad \color{gray}{\texttt{\small Iteration\ 7}}$

The new page-level labels Text11200, Text11201, and Text11202 use numeric Text#### names instead of an approved suffix.

Because they are consumed as caption text (CurrPage.Caption), give them approved caption/text suffixes such as Lbl so the usage is clear and CodeCop AA0074 is satisfied.

Knowledge:

Posting this finding as an issue comment because inline comment placement failed.

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

codeunit 12138 "WHT Gen. Jnl.-Post Line IT"
{
var
Text1130023: Label 'Because this invoice includes Withholding Tax, it should not be applied directly. Please use the function Payment Journals -> Payments -> Withh.Tax-Soc.Sec.';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🟡\ Medium\ Severity\ —\ Style} \quad \color{gray}{\texttt{\small Iteration\ 7}}$

The new codeunit declares Text1130023 and uses it as the format string for Error(...).

That should be renamed with an approved Err suffix so the label's intended usage is visible and AA0074 does not flag it.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

using Microsoft.Foundation.Address;
using Microsoft.Utilities;

tableextension 12201 "WHT VEndor IT" extends Vendor

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$\textbf{🔴\ Critical\ Severity\ —\ Upgrade} \quad \color{gray}{\texttt{\small Iteration\ 7}}$

This refactor removes persisted WHT data fields from live tables (Vendor, Vendor Templ., Gen.

Journal Line, Vendor Bill Line, Purchase Header — same field-number pattern repeats across all of them) and reintroduces them with identical field numbers inside new table extensions, but the PR adds no Subtype = Upgrade codeunit, no OnUpgrade... trigger, and no DataTransfer/upgrade-tag migration path. Table-extension fields are physically stored in a separate companion SQL table from the base table, so keeping the same field number does not preserve existing customer data when storage moves from the base table to extension storage — upgraded tenants will come up with empty/default values in the new WHT fields unless explicit upgrade logic copies the old data.

Knowledge:

👍 useful · ❤️ especially valuable · 👎 wrong - reply with why

@alexei-dobriansky

Copy link
Copy Markdown
Contributor

Agentic PR Review - Round 5

Recommendation: Request Changes

What this PR does

This PR extracts Italian withholding tax code from base objects into WHT-prefixed object extensions. Since round 4, commit 004b62c0548cb2819dc14c70b3445ff9a6ece40c only changes the Accounting Manager role-center area.

The current head is still not ready. Build Apps IT (Default) and Build Apps IT (Clean) still fail, the internal work-item validation still fails, and the earlier upgrade, test, and manual WHT override blockers are still open.

Status of previous suggestions
ID Title Status Author response
S1 Make the IT app builds pass Not addressed No author response after round 4. Current head 004b62c054 still has Build Apps IT (Default) and Build Apps IT (Clean) as FAILURE.
S2 Link the ADO work item Not addressed No author response after round 4. The PR body still has no AB# link, and For Microsoft: Validate link to internal work items is still FAILURE.
S3 Make the field move upgrade-safe Not addressed No author response after round 4. The new commit only changes role-center files, and the full PR still moves IT fields such as Withholding Tax Code and Social Security Code from base tables into tableextensions without upgrade, DataTransfer, staging, or an obsoletion path.
S4 Add a withholding tax regression test Not addressed No author response after round 4. The new commit only changes role-center files, and the full PR still has no test file changes for withholding-tax posting or manual payment scenarios.
S5 Preserve manual WHT code overrides Not addressed No author response after round 4. The manual payment page extension still stores the editable WHT values in local page variables, while the insert subscriber still passes Vendor."Withholding Tax Code" and Vendor."Social Security Code" to the vendor bill line.
New observations (commits since round 4)

S6 - Keep Social Security action in extension
Commit 004b62c054 adds the Social Security action back to AccountingManagerRoleCenter.Page.al and removes it from WHTAccountingManagerRCIT.PageExt.al. That keeps WHT/social-security role-center code in the base page instead of the WHT page extension, which is opposite of the extraction goal.

Risk assessment and necessity

Risk: This remains high risk. The PR touches vendor data, general journal lines, purchase posting, manual vendor payments, permissions, role centers, and withholding tax posting. The failed IT builds prove the extraction is incomplete, and the unresolved upgrade and manual payment issues can affect financially sensitive WHT values.

Necessity: Extracting the IT withholding tax customization is still a valid goal. It should not merge until the IT checks pass, the work item is linked, the field move is upgrade-safe, focused WHT regression coverage exists, and manual payment WHT values are preserved.


[AI-PR-REVIEW] version=1 system=github pr=9185 round=5 by=alexei-dobriansky at=2026-07-09 lastSha=004b62c0548cb2819dc14c70b3445ff9a6ece40c suggestions=S1:notaddressed,S2:notaddressed,S3:notaddressed,S4:notaddressed,S5:notaddressed,S6:new parentRound=4

@github-actions github-actions Bot added this to the Version 29.0 milestone Jul 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Finance GitHub request for Finance area

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants