Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
79657ea
new doc with issue and concerns
ventselartur Mar 29, 2026
3baca49
save plans
ventselartur Mar 30, 2026
98fae1a
update plans
ventselartur Mar 30, 2026
31a7c57
Merge branch 'main' of https://github.com/microsoft/BCApps into priva…
ventselartur Apr 3, 2026
b8fb566
fix: normalize ADI tax data to VAT percentage in E-Document Purchase …
ventselartur Apr 3, 2026
34b2207
feat: add [BC] VAT Prod. Posting Group field to E-Document Purchase Line
ventselartur Apr 3, 2026
47c64e8
feat: add VAT Prod. Posting Group column to E-Document draft subform
ventselartur Apr 3, 2026
dbb35b7
feat: add VAT Rate Mismatch notification type and handlers
ventselartur Apr 3, 2026
e0dd7f7
feat: resolve VAT Prod. Posting Group from extracted VAT rate during …
ventselartur Apr 3, 2026
4bfea7d
feat: apply resolved VAT Prod. Posting Group when creating purchase i…
ventselartur Apr 3, 2026
5d4b175
test: add integration tests for VAT Posting Group resolution during P…
ventselartur Apr 3, 2026
f6c8e55
style: sort using statements alphabetically in PreparePurchaseEDocDraft
ventselartur Apr 3, 2026
91447d6
docs: add design spec for VAT rate mismatch inline warning field
ventselartur Apr 3, 2026
a89ec5c
docs: update OnValidate logic to compare VAT % from setup against ext…
ventselartur Apr 3, 2026
b634ab3
docs: use exact VAT % comparison and handle zero-rate lines in OnVali…
ventselartur Apr 3, 2026
8a0a6d7
docs: add OnLookup trigger to open VAT Posting Setup filtered by vendor
ventselartur Apr 3, 2026
05edca8
Merge branch 'main' of https://github.com/microsoft/BCApps into priva…
ventselartur Apr 7, 2026
ac58f63
docs: filter VAT matching to Normal VAT and Reverse Charge VAT only
ventselartur Apr 7, 2026
31784c7
docs: add 7 new test cases for VAT calculation type filtering and OnV…
ventselartur Apr 7, 2026
72373db
docs: add implementation plan for VAT rate mismatch inline warning field
ventselartur Apr 7, 2026
0c0ed31
feat: add VAT Rate Mismatch field and OnValidate/OnLookup to VAT Prod…
ventselartur Apr 7, 2026
1bb68d8
refactor: set VAT Rate Mismatch flag instead of notification in Prepa…
ventselartur Apr 7, 2026
9e9d974
feat: add inline VAT warning column to draft subform page
ventselartur Apr 7, 2026
b745f53
refactor: remove VAT Rate Mismatch notification infrastructure
ventselartur Apr 7, 2026
307a1de
test: update VAT resolution tests to assert mismatch flag instead of …
ventselartur Apr 7, 2026
b0e91be
test: add tests for VAT Calculation Type filtering in Prepare Draft
ventselartur Apr 7, 2026
da77a1c
test: add OnValidate mismatch re-evaluation tests
ventselartur Apr 7, 2026
4f497cd
add minor changes
ventselartur Apr 7, 2026
886c294
refactor: move VAT tests to dedicated E-Doc Purch. VAT Tests codeunit
ventselartur Apr 7, 2026
bb35470
remove PayablesAgentVATIssue.md
ventselartur Apr 7, 2026
074152d
Merge branch 'main' of https://github.com/microsoft/BCApps into priva…
ventselartur Apr 7, 2026
eb04ce2
remove docs
ventselartur Apr 14, 2026
f3f27b9
add total line to the draft
ventselartur Apr 14, 2026
e9360b6
merge from master with manual resolve
ventselartur Apr 14, 2026
8f1d64e
resolve conflicts
ventselartur Apr 14, 2026
bc5d54d
fix EDocPurchVATTests.Codeunit.al
ventselartur Apr 14, 2026
7c5f77e
Merge branch 'main' of https://github.com/microsoft/BCApps into priva…
ventselartur Apr 20, 2026
ad40024
make total line amount not editable
ventselartur Apr 21, 2026
5a34323
Merge branch 'main' of https://github.com/microsoft/BCApps into priva…
ventselartur May 7, 2026
3caf30f
[E-Document] Substitute Standard Purchase Order with Omit Last Line a…
ventselartur May 8, 2026
c96a46d
feat(edoc): add LogVATRateMismatch on E-Document Purchase Line
ventselartur May 8, 2026
0604d4f
feat(edoc): log VAT mismatch from line OnValidate
ventselartur May 8, 2026
fb6df3a
feat(edoc): log VAT mismatch from ResolveVATProductPostingGroups
ventselartur May 8, 2026
1d41664
swamp company and vendor fields in EDocStandardPurchaseOrder.Report.al
ventselartur May 11, 2026
ddfcd2a
update for LogVATRateMismatch
ventselartur May 11, 2026
35cdfac
align EDocStandardPurchaseOrder.Report.al
ventselartur May 11, 2026
fc4e7aa
update
ventselartur May 11, 2026
39a9379
VAT amount diff
ventselartur May 11, 2026
20f51b0
update the page
ventselartur May 11, 2026
2e8171c
revert header to line inconsistency. part 1
ventselartur May 15, 2026
eee3358
remove remaining referenes to the header to lines inconsistency
ventselartur May 15, 2026
a826a76
merge from main
ventselartur May 18, 2026
224dba0
Merge branch 'main' of https://github.com/microsoft/BCApps into priva…
ventselartur May 19, 2026
0582b39
replace direct validation of VAT Product Posting group to the one wit…
ventselartur May 19, 2026
98e9df4
Merge branch 'main' of https://github.com/microsoft/BCApps into priva…
ventselartur May 19, 2026
2cc30fd
removeing unnecessary things
ventselartur May 19, 2026
9db4a01
add resolve VAT product posting group option
ventselartur May 19, 2026
8e9474d
add new options
ventselartur May 20, 2026
73a0312
remove unnecessary changes
ventselartur May 20, 2026
36d5570
remove more changes
ventselartur May 20, 2026
13c97d3
refactoring
ventselartur May 20, 2026
63562f7
Remove personal .claude symlinks
ventselartur May 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ pageextension 6162 "E-Doc. Purch. Payables Setup" extends "Purchases & Payables
ApplicationArea = All;
ToolTip = 'Specifies how the posting date is set on purchase invoices created from e-documents. Work Date uses the current work date. Document Date uses the document date from the e-document.';
}
field("Apply VAT Diff. For Purch EDoc"; Rec."Apply VAT Diff. For Purch EDoc")
{
ApplicationArea = All;
ToolTip = 'Specifies whether VAT difference should be applied when matching incoming E-Document line with Purchase Order line';
}
field("Resolve VAT Group Purch EDoc"; Rec."Resolve VAT Group Purch EDoc")
{
ApplicationArea = All;
ToolTip = 'Specifies whether to resolve VAT Product Group for purchase lines created from e-documents based on the VAT rate and the vendor''s VAT posting setup. If disabled, the VAT Product Group will not be identified based on the purchase e-document.';
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,16 @@ tableextension 6162 "E-Doc. Purch. Payables Setup" extends "Purchases & Payables
Caption = 'E-Document Default Posting Date';
DataClassification = CustomerContent;
}
field(6103; "Apply VAT Diff. For Purch EDoc"; Boolean)
{
Caption = 'Apply VAT Diff. For Purch. E-Doc.';
DataClassification = CustomerContent;
InitValue = true;
}
field(6104; "Resolve VAT Group Purch EDoc"; Boolean)
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\ 1}}$

Resolve VAT Group defaults false, Apply VAT Diff defaults true

After upgrade, existing tenants will have "Apply VAT Diff. For Purch EDoc" = true (explicit InitValue = true) but "Resolve VAT Group Purch EDoc" = false (no InitValue). VAT differences will be redistributed across lines that still carry the BC-default VAT Prod. Posting Group rather than the e-document-matched one, potentially resulting in incorrect VAT postings.

Recommendation:

  • Either add InitValue = true to "Resolve VAT Group Purch EDoc" to match the paired field's default, or set InitValue = false on "Apply VAT Diff. For Purch EDoc" so both features are opt-in together.
Suggested change
field(6104; "Resolve VAT Group Purch EDoc"; Boolean)
field(6104; "Resolve VAT Group Purch EDoc"; Boolean)
{
Caption = 'Resolve VAT Product Group for Purch. E-Doc.';
DataClassification = CustomerContent;
InitValue = true;
}

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

{
Caption = 'Resolve VAT Product Group for Purch. E-Doc.';
DataClassification = CustomerContent;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,7 @@ codeunit 6117 "E-Doc. Create Purchase Invoice" implements IEDocumentFinishDraft,
LastReceiptNo := EDocLineByReceipt.ReceiptNo;
end;
EDocLineByReceipt.Close();
EDocPurchaseDocumentHelper.ApplyVATDifferenceToLines(PurchaseHeader, EDocumentPurchaseHeader);
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\ 1}}$

ApplyVATDifference called before invoice discount

ApplyVATDifferenceToLines is invoked before ApplyInvDiscBasedOnAmt (line 181), so every PurchaseLine."Inv. Discount Amount" is still 0 at distribution time. The subtraction PurchaseLine."Line Amount" - PurchaseLine."Inv. Discount Amount" in the helper is therefore dead code and the proportional basis always equals the gross line amount, ignoring document-level discounts.

Recommendation:

  • Move ApplyVATDifferenceToLines to after PurchCalcDiscByType.ApplyInvDiscBasedOnAmt so invoice-discount amounts are already populated on the purchase lines when the VAT difference is distributed.
Suggested change
EDocPurchaseDocumentHelper.ApplyVATDifferenceToLines(PurchaseHeader, EDocumentPurchaseHeader);
PurchaseHeader.Modify();
PurchCalcDiscByType.ApplyInvDiscBasedOnAmt(EDocumentPurchaseHeader."Total Discount", PurchaseHeader);
EDocPurchaseDocumentHelper.ApplyVATDifferenceToLines(PurchaseHeader, EDocumentPurchaseHeader);
exit(PurchaseHeader);

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

PurchaseHeader.Modify();
PurchCalcDiscByType.ApplyInvDiscBasedOnAmt(EDocumentPurchaseHeader."Total Discount", PurchaseHeader);
exit(PurchaseHeader);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ namespace Microsoft.eServices.EDocument.Processing.Import;
using Microsoft.eServices.EDocument;
using Microsoft.eServices.EDocument.Processing;
using Microsoft.eServices.EDocument.Processing.Import.Purchase;
using Microsoft.Finance.Currency;
using Microsoft.Finance.Dimension;
using Microsoft.Finance.VAT.Setup;
using Microsoft.Foundation.Attachment;
using Microsoft.Purchases.Document;
using Microsoft.Purchases.Posting;
Expand Down Expand Up @@ -40,6 +42,9 @@ codeunit 6402 "E-Doc. Purch. Doc. Helper"
PurchaseLine."Variant Code" := EDocumentPurchaseLine."[BC] Variant Code";
PurchaseLine.Type := EDocumentPurchaseLine."[BC] Purchase Line Type";
ValidateFieldWithContext(PurchaseLine, PurchaseLine.FieldNo("No."), EDocumentPurchaseLine."[BC] Purchase Type No.");
if EDocumentPurchaseLine."[BC] VAT Prod. Posting Group" <> '' then
ValidateFieldWithContext(
PurchaseLine, PurchaseLine.FieldNo("VAT Prod. Posting Group"), EDocumentPurchaseLine."[BC] VAT Prod. Posting Group");
if (PurchaseLine.Type = PurchaseLine.Type::"G/L Account") and HasTotalDiscount then
ValidateFieldWithContext(PurchaseLine, PurchaseLine.FieldNo("Allow Invoice Disc."), true);
PurchaseLine.Description := EDocumentPurchaseLine.Description;
Expand Down Expand Up @@ -154,6 +159,43 @@ codeunit 6402 "E-Doc. Purch. Doc. Helper"
EDocImpSessionTelemetry.SetBool('Totals Validation', TryValidateDocumentTotals(PurchaseHeader));
end;

procedure ApplyVATDifferenceToLines(PurchaseHeader: Record "Purchase Header"; EDocumentPurchaseHeader: Record "E-Document Purchase Header")
var
PurchaseLine: Record "Purchase Line";
Currency: Record Currency;
LineAmount: Decimal;
TotalLineAmount, VATDiffRemainder, VATDiffForLine : Decimal;
begin
if EDocumentPurchaseHeader."Applied VAT Amount Diff." = 0 then
exit;

TotalLineAmount := ComputeTotalLineAmount(EDocumentPurchaseHeader."E-Document Entry No.");
if TotalLineAmount = 0 then
exit;

if PurchaseHeader."Currency Code" = '' then
Currency.InitRoundingPrecision()
else
Currency.Get(PurchaseHeader."Currency Code");

PurchaseLine.SetRange("Document Type", PurchaseHeader."Document Type");
PurchaseLine.SetRange("Document No.", PurchaseHeader."No.");
PurchaseLine.SetFilter(Type, '<>%1', PurchaseLine.Type::" ");
if not PurchaseLine.FindSet() then
exit;

VATDiffRemainder := 0;
repeat
LineAmount := PurchaseLine."Line Amount" - PurchaseLine."Inv. Discount Amount";
if LineAmount <> 0 then begin
VATDiffForLine := VATDiffRemainder + EDocumentPurchaseHeader."Applied VAT Amount Diff." * LineAmount / TotalLineAmount;
PurchaseLine."VAT Difference" := Round(VATDiffForLine, Currency."Amount Rounding Precision");
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\ 1}}$

VAT Difference set without Validate, skips BC checks

PurchaseLine."VAT Difference" := Round(...) is a direct field assignment that bypasses the OnValidate trigger and BC's internal purchase-line recalculation logic. This can leave VAT-related totals on the header inconsistent and will not respect any line-level VAT difference constraints.

Recommendation:

  • Use PurchaseLine.Validate("VAT Difference", Round(VATDiffForLine, Currency."Amount Rounding Precision")) and then call PurchaseLine.Modify(true) to ensure all dependent fields are recalculated.
Suggested change
PurchaseLine."VAT Difference" := Round(VATDiffForLine, Currency."Amount Rounding Precision");
PurchaseLine.Validate("VAT Difference", Round(VATDiffForLine, Currency."Amount Rounding Precision"));
VATDiffRemainder := VATDiffForLine - PurchaseLine."VAT Difference";
PurchaseLine.Modify(true);

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

VATDiffRemainder := VATDiffForLine - PurchaseLine."VAT Difference";
PurchaseLine.Modify();
end;
until PurchaseLine.Next() = 0;
end;

procedure RevertCreatedDocument(EDocument: Record "E-Document")
var
PurchaseHeader: Record "Purchase Header";
Expand Down Expand Up @@ -181,4 +223,25 @@ codeunit 6402 "E-Doc. Purch. Doc. Helper"
exit;
PurchaseHeader.Validate("Posting Date", EDocumentPurchaseHeader."Document Date");
end;

procedure SetNormalReverseChargeFilter(var VATPostingSetup: Record "VAT Posting Setup"; VATBusPostingGroup: Code[20])
begin
VATPostingSetup.SetRange("VAT Bus. Posting Group", VATBusPostingGroup);
VATPostingSetup.SetFilter("VAT Calculation Type", '%1|%2',
VATPostingSetup."VAT Calculation Type"::"Normal VAT",
VATPostingSetup."VAT Calculation Type"::"Reverse Charge VAT");
end;

local procedure ComputeTotalLineAmount(EDocEntryNo: Integer): Decimal
var
EDocPurchLine: Record "E-Document Purchase Line";
TotalLineAmount: Decimal;
begin
EDocPurchLine.SetRange("E-Document Entry No.", EDocEntryNo);
if EDocPurchLine.FindSet() then
repeat
TotalLineAmount += Round(EDocPurchLine.Quantity * EDocPurchLine."Unit Price" - EDocPurchLine."Total Discount");
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\ 1}}$

ComputeTotalLineAmount uses default Round precision

Round(EDocPurchLine.Quantity * EDocPurchLine."Unit Price" - EDocPurchLine."Total Discount") uses BC's default 2-decimal rounding, while ApplyVATDifferenceToLines distributes using Currency."Amount Rounding Precision". For currencies with non-standard precision (e.g. JPY=0, BHD=3), the denominator will differ from the actual purchase line amounts, causing the sum of distributed VAT differences to diverge from Applied VAT Amount Diff..

Recommendation:

  • Pass the currency's amount rounding precision into ComputeTotalLineAmount (or read it from the purchase header) and use it in the Round() call to stay consistent with ApplyVATDifferenceToLines.
Suggested change
TotalLineAmount += Round(EDocPurchLine.Quantity * EDocPurchLine."Unit Price" - EDocPurchLine."Total Discount");
TotalLineAmount += Round(
EDocPurchLine.Quantity * EDocPurchLine."Unit Price" - EDocPurchLine."Total Discount",
Currency."Amount Rounding Precision");

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

until EDocPurchLine.Next() = 0;
exit(TotalLineAmount);
end;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,11 @@ using Microsoft.eServices.EDocument;
using Microsoft.eServices.EDocument.Processing.AI;
using Microsoft.eServices.EDocument.Processing.Import.Purchase;
using Microsoft.eServices.EDocument.Processing.Interfaces;
using Microsoft.Finance.GeneralLedger.Setup;
using Microsoft.Finance.VAT.Setup;
using Microsoft.Foundation.UOM;
using Microsoft.Purchases.Document;
using Microsoft.Purchases.Setup;
using Microsoft.Purchases.Vendor;
using System.Log;

Expand All @@ -36,6 +39,9 @@ codeunit 6406 "EDoc Prepare Purch. Draft"
IUnitOfMeasureProvider: Interface IUnitOfMeasureProvider;
IPurchaseLineProvider: Interface IPurchaseLineProvider;
IPurchaseOrderProvider: Interface IPurchaseOrderProvider;
LineAmount: Decimal;
LineVATAmount: Decimal;
TotalLineVATAmount: Decimal;
begin
IUnitOfMeasureProvider := EDocImportParameters."Processing Customizations";
IPurchaseLineProvider := EDocImportParameters."Processing Customizations";
Expand Down Expand Up @@ -72,16 +78,26 @@ codeunit 6406 "EDoc Prepare Purch. Draft"
EDocumentPurchaseLine.Modify();
until EDocumentPurchaseLine.Next() = 0;

// Resolve VAT Product Posting Groups from extracted VAT rates
ResolveVATProductPostingGroups(EDocument."Entry No", EDocumentPurchaseHeader);

CopilotLineMatching(EDocument."Entry No");
end;

Clear(EDocumentPurchaseLine);
EDocumentPurchaseLine.SetRange("E-Document Entry No.", EDocument."Entry No");
TotalLineVATAmount := 0;
if EDocumentPurchaseLine.FindSet() then
repeat
LineAmount := Round(EDocumentPurchaseLine.Quantity * EDocumentPurchaseLine."Unit Price" - EDocumentPurchaseLine."Total Discount");
LineVATAmount := Round(LineAmount * EDocumentPurchaseLine."VAT Rate" / 100);
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\ —\ Performance} \quad \color{gray}{\texttt{\small Iteration\ 1}}$

TotalLineVATAmount uses default Round, ignores currency precision

LineVATAmount := Round(LineAmount * EDocumentPurchaseLine."VAT Rate" / 100) applies the default 2-decimal rounding, independent of the document's currency. For currencies with fewer decimals (JPY) or more (BHD), the computed TotalLineVATAmount will diverge from the actual purchase line VAT amounts, generating a spurious or inflated Applied VAT Amount Diff..

Recommendation:

  • Retrieve the currency record for the e-document (or use the default amount rounding precision) and pass it as the second argument to Round().
Suggested change
LineVATAmount := Round(LineAmount * EDocumentPurchaseLine."VAT Rate" / 100);
LineVATAmount := Round(LineAmount * EDocumentPurchaseLine."VAT Rate" / 100, Currency."Amount Rounding Precision");

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

TotalLineVATAmount += LineVATAmount;
EDocImpSessionTelemetry.SetLine(EDocumentPurchaseLine.SystemId);
until EDocumentPurchaseLine.Next() = 0;

ComputeAndApplyVATAmountDifference(EDocumentPurchaseHeader, TotalLineVATAmount);
EDocumentPurchaseHeader.Modify();

LogAllActivitySessionChanges(EDocActivityLogSession);

if EDocActivityLogSession.EndSession() then;
Expand Down Expand Up @@ -138,6 +154,67 @@ codeunit 6406 "EDoc Prepare Purch. Draft"
ActivityLog.Log();
end;

local procedure ResolveVATProductPostingGroups(EDocumentEntryNo: Integer; EDocumentPurchaseHeader: Record "E-Document Purchase Header")
var
PurchasesPayablesSetup: Record "Purchases & Payables Setup";
EDocumentPurchaseLine: Record "E-Document Purchase Line";
Vendor: Record Vendor;
VATRate: Decimal;
LineCount: Integer;
begin
if not PurchasesPayablesSetup.Get() then
exit;
if not PurchasesPayablesSetup."Resolve VAT Group Purch EDoc" then
exit;
Vendor := EDocumentPurchaseHeader.GetBCVendor();
if Vendor."No." = '' then
exit;
if Vendor."VAT Bus. Posting Group" = '' then
exit;

EDocumentPurchaseLine.SetRange("E-Document Entry No.", EDocumentEntryNo);
LineCount := EDocumentPurchaseLine.Count();
if LineCount = 0 then
exit;

if EDocumentPurchaseLine.FindSet() then
repeat
VATRate := EDocumentPurchaseLine."VAT Rate";

// Single-line fallback: compute from header Total VAT
if (VATRate = 0) and (LineCount = 1) and
(EDocumentPurchaseHeader."Total VAT" > 0) and (EDocumentPurchaseHeader."Sub Total" > 0)
then
VATRate := Round((EDocumentPurchaseHeader."Total VAT" / EDocumentPurchaseHeader."Sub Total") * 100, 0.01);
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\ —\ Performance} \quad \color{gray}{\texttt{\small Iteration\ 1}}$

Single-line VAT rate fallback uses header-level Sub Total

For a single-line document where VAT Rate = 0, the fallback computes VATRate = ("Total VAT" / "Sub Total") * 100 from header fields. If the header Sub Total includes charges or differs from the individual line's base (e.g. due to header discounts, rounding, or fees), the computed rate will be wrong and an incorrect VAT Prod. Posting Group will be assigned.

Recommendation:

  • Prefer using the line's own Quantity * "Unit Price" - "Total Discount" as the denominator, falling back to the header Sub Total only when the line amount is zero.
Suggested change
VATRate := Round((EDocumentPurchaseHeader."Total VAT" / EDocumentPurchaseHeader."Sub Total") * 100, 0.01);
var LineBase: Decimal;
LineBase := EDocumentPurchaseLine.Quantity * EDocumentPurchaseLine."Unit Price" - EDocumentPurchaseLine."Total Discount";
if LineBase = 0 then
LineBase := EDocumentPurchaseHeader."Sub Total";
if LineBase > 0 then
VATRate := Round((EDocumentPurchaseHeader."Total VAT" / LineBase) * 100, 0.01);

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


if VATRate > 0 then begin
EDocumentPurchaseLine."[BC] VAT Prod. Posting Group" :=
FindVATProductPostingGroup(Vendor."VAT Bus. Posting Group", VATRate);
EDocumentPurchaseLine."[BC] VAT Rate Mismatch" :=
EDocumentPurchaseLine."[BC] VAT Prod. Posting Group" = '';
EDocumentPurchaseLine.Modify();
if EDocumentPurchaseLine."[BC] VAT Rate Mismatch" then
EDocumentPurchaseLine.LogVATRateMismatch(Vendor."VAT Bus. Posting Group", VATRate)
else
EDocumentPurchaseLine.LogVATRateResolved(Vendor."VAT Bus. Posting Group", VATRate);
end;
until EDocumentPurchaseLine.Next() = 0;
end;

local procedure FindVATProductPostingGroup(VATBusPostingGroup: Code[20]; VATRate: Decimal): Code[20]
var
VATPostingSetup: Record "VAT Posting Setup";
EDocPurchDocHelper: Codeunit "E-Doc. Purch. Doc. Helper";
begin
EDocPurchDocHelper.SetNormalReverseChargeFilter(VATPostingSetup, VATBusPostingGroup);
VATPostingSetup.SetRange("VAT %", VATRate);
if VATPostingSetup.Count() = 1 then begin
VATPostingSetup.FindFirst();
exit(VATPostingSetup."VAT Prod. Posting Group");
end;
exit('');
end;

local procedure CopilotLineMatching(EDocumentEntryNo: Integer)
var
EDocumentPurchaseLine: Record "E-Document Purchase Line";
Expand Down Expand Up @@ -172,4 +249,68 @@ codeunit 6406 "EDoc Prepare Purch. Draft"
if Codeunit.Run(Codeunit::"E-Doc. Deferral Matching", EDocumentPurchaseLine) then;
end;
end;

local procedure ComputeAndApplyVATAmountDifference(var EDocumentPurchaseHeader: Record "E-Document Purchase Header"; TotalLineVATAmount: Decimal)
var
PurchasesPayablesSetup: Record "Purchases & Payables Setup";
GeneralLedgerSetup: Record "General Ledger Setup";
ActivityLog: Codeunit "Activity Log Builder";
VATAmountDiff: Decimal;
Reasoning: Text[250];
VATDiffAppliedLbl: Label 'Applied VAT amount difference of %1 to reconcile document Total VAT %2 with computed Total Line VAT Amount %3.', Comment = '%1 = VAT difference, %2 = Total VAT, %3 = Total Line VAT Amount';
VATDiffSkippedSetupLbl: Label 'VAT amount difference of %1 was not applied because Apply VAT Diff. For Purch. E-Doc. is disabled in Purchases & Payables Setup.', Comment = '%1 = VAT difference';
VATDiffSkippedAllowLbl: Label 'VAT amount difference of %1 was not applied because Allow VAT Difference is disabled in Purchases & Payables Setup.', Comment = '%1 = VAT difference';
VATDiffSkippedMaxLbl: Label 'VAT amount difference of %1 was not applied because it exceeds the Max. VAT Difference Allowed of %2 in General Ledger Setup.', Comment = '%1 = VAT difference, %2 = Max. VAT Difference Allowed';
begin
EDocumentPurchaseHeader."Applied VAT Amount Diff." := 0;

if (EDocumentPurchaseHeader."Total VAT" = 0) or (TotalLineVATAmount = EDocumentPurchaseHeader."Total VAT") then
exit;

VATAmountDiff := EDocumentPurchaseHeader."Total VAT" - TotalLineVATAmount;

if not PurchasesPayablesSetup.Get() then
exit;

if not PurchasesPayablesSetup."Apply VAT Diff. For Purch EDoc" then begin
Reasoning := CopyStr(StrSubstNo(VATDiffSkippedSetupLbl, VATAmountDiff), 1, MaxStrLen(Reasoning));
ActivityLog
.Init(Database::"E-Document Purchase Header", EDocumentPurchaseHeader.FieldNo("Applied VAT Amount Diff."), EDocumentPurchaseHeader.SystemId)
.SetExplanation(Reasoning)
.SetType(Enum::"Activity Log Type"::"AL")
.Log();
exit;
end;

if not PurchasesPayablesSetup."Allow VAT Difference" then begin
Reasoning := CopyStr(StrSubstNo(VATDiffSkippedAllowLbl, VATAmountDiff), 1, MaxStrLen(Reasoning));
ActivityLog
.Init(Database::"E-Document Purchase Header", EDocumentPurchaseHeader.FieldNo("Applied VAT Amount Diff."), EDocumentPurchaseHeader.SystemId)
.SetExplanation(Reasoning)
.SetType(Enum::"Activity Log Type"::"AL")
.Log();
exit;
end;

if not GeneralLedgerSetup.Get() then
exit;
if Abs(VATAmountDiff) > GeneralLedgerSetup."Max. VAT Difference Allowed" then begin
Reasoning := CopyStr(StrSubstNo(VATDiffSkippedMaxLbl, VATAmountDiff, GeneralLedgerSetup."Max. VAT Difference Allowed"), 1, MaxStrLen(Reasoning));
ActivityLog
.Init(Database::"E-Document Purchase Header", EDocumentPurchaseHeader.FieldNo("Applied VAT Amount Diff."), EDocumentPurchaseHeader.SystemId)
.SetExplanation(Reasoning)
.SetType(Enum::"Activity Log Type"::"AL")
.Log();
exit;
end;

EDocumentPurchaseHeader."Applied VAT Amount Diff." := VATAmountDiff;

Reasoning := CopyStr(StrSubstNo(VATDiffAppliedLbl, VATAmountDiff, EDocumentPurchaseHeader."Total VAT", TotalLineVATAmount), 1, MaxStrLen(Reasoning));
ActivityLog
.Init(Database::"E-Document Purchase Header", EDocumentPurchaseHeader.FieldNo("Applied VAT Amount Diff."), EDocumentPurchaseHeader.SystemId)
.SetExplanation(Reasoning)
.SetType(Enum::"Activity Log Type"::"AL")
.Log();
end;
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,11 @@ page 6183 "E-Doc. Purchase Draft Subform"
Lookup = true;
ShowMandatory = true;
}
field("VAT Prod. Posting Group"; Rec."[BC] VAT Prod. Posting Group")
{
ApplicationArea = All;
Lookup = true;
}
field("Item Reference No."; Rec."[BC] Item Reference No.")
{
ApplicationArea = All;
Expand Down Expand Up @@ -564,5 +569,4 @@ page 6183 "E-Doc. Purchase Draft Subform"
if WarningDetails.Length() > 0 then
Message(WarningDetails.ToText());
end;

}
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,14 @@ page 6181 "E-Document Purchase Draft"
group("E-Document Details")
{
ShowCaption = false;
field("Applied VAT Amount Diff."; EDocumentPurchaseHeader."Applied VAT Amount Diff.")
{
Caption = 'Applied VAT Amount Diff.';
ToolTip = 'Specifies the VAT amount difference that was automatically applied to reconcile the document total VAT with the computed line VAT amounts.';
Importance = Additional;
Editable = false;
Visible = EDocumentPurchaseHeader."Applied VAT Amount Diff." <> 0;
}
field("Amount Excl. VAT"; EDocumentPurchaseHeader."Sub Total")
{
Caption = 'Amount Excl. VAT';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,14 @@ table 6100 "E-Document Purchase Header"
Caption = 'Vendor Invoice No.';
DataClassification = CustomerContent;
}
field(44; "Applied VAT Amount Diff."; Decimal)
{
Caption = 'Applied VAT Amount Diff.';
DataClassification = CustomerContent;
AutoFormatType = 1;
AutoFormatExpression = Rec."Currency Code";
Editable = false;
}
#endregion Purchase fields

#region Business Central Data - Validated fields [101-200]
Expand Down
Loading
Loading