From 7817cc483394577ea4a794e3254425475aeff13d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miljan=20Milosavljevi=C4=87?= Date: Fri, 8 May 2026 14:20:18 +0200 Subject: [PATCH 1/2] Fix Subscription Line Calculation Base Amount when Prices Including VAT is enabled - Add EnsureCalculationBaseAmountExcludesVAT on Subscription Line table to strip VAT from Calculation Base Amount when the Sales Header has Prices Including VAT - Add event subscriber in SalesSubscriptionLineMgmt to recalculate Sales Subscription Line amounts when Prices Including VAT is toggled on the Sales Header - Add four tests covering: CBA equals unit price with/without PIV, recalculation on PIV toggle, and net CBA on posted Subscription Line - Refactor test helpers: extract FindNonZeroVATPostingSetup, FindCustomerDocumentPrice- SalesServiceCommitment, SetupItemCustomerAndSalesHeaderWithVAT; replace magic VAT sentinel with explicit ReassignSalesLineToDifferentVATGroup/ReassignSalesLineToZeroVATGroup - Add GIVEN/WHEN/THEN comments to CheckVatCalculationForServiceCommitmentRhythmInReports --- .../Codeunits/SalesDocuments.Codeunit.al | 2 + .../SalesSubscriptionLineMgmt.Codeunit.al | 27 ++ .../Tables/SubscriptionLine.Table.al | 18 ++ .../SalesServiceCommitmentTest.Codeunit.al | 237 ++++++++++++++++-- 4 files changed, 264 insertions(+), 20 deletions(-) diff --git a/src/Apps/W1/Subscription Billing/App/Billing/Codeunits/SalesDocuments.Codeunit.al b/src/Apps/W1/Subscription Billing/App/Billing/Codeunits/SalesDocuments.Codeunit.al index 7e8d53ef04..af7b9ab00b 100644 --- a/src/Apps/W1/Subscription Billing/App/Billing/Codeunits/SalesDocuments.Codeunit.al +++ b/src/Apps/W1/Subscription Billing/App/Billing/Codeunits/SalesDocuments.Codeunit.al @@ -1,5 +1,6 @@ namespace Microsoft.SubscriptionBilling; +using Microsoft.Finance.Currency; using Microsoft.Finance.GeneralLedger.Account; using Microsoft.Finance.GeneralLedger.Journal; using Microsoft.Finance.GeneralLedger.Posting; @@ -613,6 +614,7 @@ codeunit 8063 "Sales Documents" else SubscriptionLine.Validate("Subscription Line Start Date", CalcDate(SalesSubscriptionLine."Sub. Line Start Formula", SalesLine."Shipment Date")); SubscriptionLine.CopyFromSalesServiceCommitment(SalesSubscriptionLine); + SubscriptionLine.EnsureCalculationBaseAmountExcludesVAT(SalesLine, SalesHeader); if SalesSubscriptionLine.Discount then SubscriptionLine.Validate("Calculation Base Amount", SubscriptionLine."Calculation Base Amount" * -1); diff --git a/src/Apps/W1/Subscription Billing/App/Sales Service Commitments/Codeunits/SalesSubscriptionLineMgmt.Codeunit.al b/src/Apps/W1/Subscription Billing/App/Sales Service Commitments/Codeunits/SalesSubscriptionLineMgmt.Codeunit.al index db1bfd235e..d1bb6d67b9 100644 --- a/src/Apps/W1/Subscription Billing/App/Sales Service Commitments/Codeunits/SalesSubscriptionLineMgmt.Codeunit.al +++ b/src/Apps/W1/Subscription Billing/App/Sales Service Commitments/Codeunits/SalesSubscriptionLineMgmt.Codeunit.al @@ -1,5 +1,6 @@ namespace Microsoft.SubscriptionBilling; +using Microsoft.Finance.Currency; using Microsoft.Inventory.Item; using Microsoft.Sales.Archive; using Microsoft.Sales.Document; @@ -387,6 +388,32 @@ codeunit 8069 "Sales Subscription Line Mgmt." AddSalesServiceCommitmentsForSalesLine(ToSalesLine, false); end; + [EventSubscriber(ObjectType::Table, Database::"Sales Header", OnValidatePricesIncludingVATOnBeforeSalesLineModify, '', false, false)] + local procedure RecalculateSalesSubscriptionLineAmountsOnBeforeSalesLineModify(var SalesHeader: Record "Sales Header"; var SalesLine: Record "Sales Line"; Currency: Record Currency; RecalculatePrice: Boolean) + var + SalesSubscriptionLine: Record "Sales Subscription Line"; + VatFactor: Decimal; + begin + if not RecalculatePrice then + exit; + if SalesLine."VAT Calculation Type" = SalesLine."VAT Calculation Type"::"Full VAT" then + exit; + VatFactor := 1 + SalesLine.GetVATPct() / 100; + if VatFactor = 0 then + VatFactor := 1; + if not SalesHeader."Prices Including VAT" then + VatFactor := 1 / VatFactor; + SalesSubscriptionLine.FilterOnSalesLine(SalesLine); + SalesSubscriptionLine.SetRange(Partner, Enum::"Service Partner"::Customer); + if not SalesSubscriptionLine.FindSet(true) then + exit; + repeat + SalesSubscriptionLine.Validate("Calculation Base Amount", + Round(SalesSubscriptionLine."Calculation Base Amount" * VatFactor, Currency."Unit-Amount Rounding Precision")); + SalesSubscriptionLine.Modify(false); + until SalesSubscriptionLine.Next() = 0; + end; + [IntegrationEvent(false, false)] local procedure OnBeforeCreateSalesSubscriptionLineFromSubscriptionPackageLine(var SalesLine: Record "Sales Line"; var SubscriptionPackageLine: Record "Subscription Package Line"; var IsHandled: Boolean) begin diff --git a/src/Apps/W1/Subscription Billing/App/Service Commitments/Tables/SubscriptionLine.Table.al b/src/Apps/W1/Subscription Billing/App/Service Commitments/Tables/SubscriptionLine.Table.al index 541b482c7a..c9c071b8e6 100644 --- a/src/Apps/W1/Subscription Billing/App/Service Commitments/Tables/SubscriptionLine.Table.al +++ b/src/Apps/W1/Subscription Billing/App/Service Commitments/Tables/SubscriptionLine.Table.al @@ -1408,6 +1408,24 @@ table 8059 "Subscription Line" Rec."Currency Code" := CurrencyCode; end; + internal procedure EnsureCalculationBaseAmountExcludesVAT(SalesLine: Record "Sales Line"; SalesHeader: Record "Sales Header") + var + LocalCurrency: Record Currency; + NetBaseAmount: Decimal; + begin + if not SalesHeader."Prices Including VAT" then + exit; + if SalesLine."VAT Calculation Type" = SalesLine."VAT Calculation Type"::"Full VAT" then + exit; + if SalesLine.GetVATPct() = 0 then + exit; + LocalCurrency.Initialize(SalesHeader."Currency Code"); + NetBaseAmount := Round( + Rec."Calculation Base Amount" / (1 + SalesLine.GetVATPct() / 100), + LocalCurrency."Unit-Amount Rounding Precision"); + Rec.Validate("Calculation Base Amount", NetBaseAmount); + end; + internal procedure ErrorIfBillingLineForServiceCommitmentExist() begin if BillingLineExists() then diff --git a/src/Apps/W1/Subscription Billing/Test/Service Commitments/SalesServiceCommitmentTest.Codeunit.al b/src/Apps/W1/Subscription Billing/Test/Service Commitments/SalesServiceCommitmentTest.Codeunit.al index a075783284..bfe4501dca 100644 --- a/src/Apps/W1/Subscription Billing/Test/Service Commitments/SalesServiceCommitmentTest.Codeunit.al +++ b/src/Apps/W1/Subscription Billing/Test/Service Commitments/SalesServiceCommitmentTest.Codeunit.al @@ -427,15 +427,15 @@ codeunit 139915 "Sales Service Commitment Test" begin Initialize(); LibrarySales.CreateSalesHeader(SalesHeader, SalesHeader."Document Type"::Order, ''); - SetupSalesLineForTotalAndVatCalculation(Item, true, 19); + SetupSalesLineForTotalAndVatCalculation(Item, true); SalesLine.Validate("Unit Price", 100); SalesLine.Validate(Quantity, 1); SalesLine.Modify(false); - SetupSalesLineForTotalAndVatCalculation(Item2, false, 19); + SetupSalesLineForTotalAndVatCalculation(Item2, false); SalesLine.Validate("Unit Price", 100); SalesLine.Validate(Quantity, 1); SalesLine.Modify(false); - SetupSalesLineForTotalAndVatCalculation(Item3, false, 19); + SetupSalesLineForTotalAndVatCalculation(Item3, false); SalesLine.Validate("Unit Price", 100); SalesLine.Validate(Quantity, 1); SalesLine.Validate("Line Discount %", 50); @@ -884,6 +884,150 @@ codeunit 139915 "Sales Service Commitment Test" Assert.AreEqual(ExpectedCalculationBaseAmount, SalesServiceCommitment."Calculation Base Amount", StrSubstNo(UnexpectedValueTok, SalesServiceCommitment.FieldCaption("Calculation Base Amount"), SalesServiceCommitment.TableCaption(), SalesServiceCommitment.Partner, SalesServiceCommitment."Calculation Base Type")); end; + [Test] + procedure CheckCalculationBaseAmountEqualsSalesLineUnitPriceIncludingVAT() + var + VATPostingSetup: Record "VAT Posting Setup"; + CalcBaseAmtMustEqualUnitPriceWithVATErr: Label 'Calculation Base Amount must equal the unit price when Prices Including VAT is enabled.', Locked = true; + begin + // [SCENARIO] When Prices Including VAT is enabled on the Sales Header, the Calculation Base Amount + // on the Sales Subscription Line stores the VAT-inclusive unit price as-is (same as Sales Line Unit Price). + + // [GIVEN] A subscription item with a non-zero VAT%, and a Sales Order with Prices Including VAT = true + Initialize(); + SetupAdditionalServiceCommPackageLine(Enum::"Service Partner"::Customer, Enum::"Calculation Base Type"::"Document Price"); + SetupItemCustomerAndSalesHeaderWithVAT(VATPostingSetup); + SalesHeader.Validate("Prices Including VAT", true); + SalesHeader.Modify(true); + + // [WHEN] A sales line is created with the subscription item + LibrarySales.CreateSalesLine(SalesLine, SalesHeader, Enum::"Sales Line Type"::Item, Item."No.", 1); + + // [THEN] Calculation Base Amount equals the unit price as stored on the sales line (VAT-inclusive) + FindCustomerDocumentPriceSalesServiceCommitment(); + Assert.AreEqual( + SalesLine."Unit Price", + SalesServiceCommitment."Calculation Base Amount", + CalcBaseAmtMustEqualUnitPriceWithVATErr); + end; + + [Test] + procedure CheckCalculationBaseAmountEqualsSalesLineUnitPriceExcludingVAT() + var + VATPostingSetup: Record "VAT Posting Setup"; + CalcBaseAmtMustEqualUnitPriceNoVATErr: Label 'Calculation Base Amount must equal unit price when Prices Including VAT is disabled.', Locked = true; + begin + // [SCENARIO] When Prices Including VAT is disabled (default), the Calculation Base Amount on the + // Sales Subscription Line equals the unit price directly, with no VAT adjustment. + + // [GIVEN] A subscription item with a non-zero VAT%, and a Sales Order with Prices Including VAT = false + Initialize(); + SetupAdditionalServiceCommPackageLine(Enum::"Service Partner"::Customer, Enum::"Calculation Base Type"::"Document Price"); + SetupItemCustomerAndSalesHeaderWithVAT(VATPostingSetup); + + // [WHEN] A sales line is created with the subscription item (Prices Including VAT = false by default) + LibrarySales.CreateSalesLine(SalesLine, SalesHeader, Enum::"Sales Line Type"::Item, Item."No.", 1); + + // [THEN] Calculation Base Amount equals the unit price without any VAT adjustment + FindCustomerDocumentPriceSalesServiceCommitment(); + Assert.AreEqual( + SalesLine."Unit Price", + SalesServiceCommitment."Calculation Base Amount", + CalcBaseAmtMustEqualUnitPriceNoVATErr); + end; + + [Test] + [HandlerFunctions('ConfirmHandlerYes')] + procedure CheckCalculationBaseAmountRecalculatedOnPricesIncludingVATChange() + var + VATPostingSetup: Record "VAT Posting Setup"; + InitCalcBaseAmtMustEqualUnitPriceErr: Label 'Initial Calculation Base Amount must equal unit price when Prices Including VAT is disabled.', Locked = true; + CalcBaseAmtMustEqualUpdatedUnitPriceErr: Label 'Calculation Base Amount must equal the updated unit price when Prices Including VAT is toggled on.', Locked = true; + CalcBaseAmtMustRevertToUnitPriceErr: Label 'Calculation Base Amount must revert to unit price when Prices Including VAT is toggled off.', Locked = true; + begin + // [SCENARIO] Toggling Prices Including VAT on a Sales Header triggers recalculation of the + // Calculation Base Amount on all existing Sales Subscription Lines using the VAT factor, + // preserving any manual edits rather than recalculating from scratch. + + // [GIVEN] A Sales Order with Prices Including VAT = false and an existing subscription line + Initialize(); + SetupAdditionalServiceCommPackageLine(Enum::"Service Partner"::Customer, Enum::"Calculation Base Type"::"Document Price"); + SetupItemCustomerAndSalesHeaderWithVAT(VATPostingSetup); + LibrarySales.CreateSalesLine(SalesLine, SalesHeader, Enum::"Sales Line Type"::Item, Item."No.", 1); + FindCustomerDocumentPriceSalesServiceCommitment(); + Assert.AreEqual( + SalesLine."Unit Price", + SalesServiceCommitment."Calculation Base Amount", + InitCalcBaseAmtMustEqualUnitPriceErr); + + // [WHEN] Prices Including VAT is toggled to true on the Sales Header + SalesHeader.Validate("Prices Including VAT", true); + SalesHeader.Modify(true); + + // [THEN] Calculation Base Amount is updated to match the new VAT-inclusive unit price + SalesLine.Find(); + SalesServiceCommitment.Find(); + Assert.AreEqual( + SalesLine."Unit Price", + SalesServiceCommitment."Calculation Base Amount", + CalcBaseAmtMustEqualUpdatedUnitPriceErr); + + // [WHEN] Prices Including VAT is toggled back to false + SalesHeader.Validate("Prices Including VAT", false); + SalesHeader.Modify(true); + + // [THEN] Calculation Base Amount reverts to the VAT-exclusive unit price + SalesLine.Find(); + SalesServiceCommitment.Find(); + Assert.AreEqual( + SalesLine."Unit Price", + SalesServiceCommitment."Calculation Base Amount", + CalcBaseAmtMustRevertToUnitPriceErr); + end; + + [Test] + procedure CheckSubscriptionLineCalculationBaseAmountExcludesVATAfterPosting() + var + VATPostingSetup: Record "VAT Posting Setup"; + ExpectedNetBaseAmount: Decimal; + PostedSubLineCalcBaseAmtMustBeNetErr: Label 'Posted Subscription Line Calculation Base Amount must be the net (VAT-exclusive) amount when Prices Including VAT was enabled.', Locked = true; + begin + // [SCENARIO] When a Sales Order with Prices Including VAT is posted, the resulting Subscription Line + // Calculation Base Amount must be the VAT-exclusive (net) amount. + + // [GIVEN] A subscription item with a non-zero VAT%, and a Sales Order with Prices Including VAT = true + Initialize(); + // Use the single package line from Initialize: set Calculation Base Type = Document Price and Calculation Base % = 100 + // so that Calculation Base Amount exactly equals the Sales Line Unit Price (no scaling). + ServiceCommPackageLine."Calculation Base Type" := Enum::"Calculation Base Type"::"Document Price"; + ServiceCommPackageLine."Calculation Base %" := 100; + ServiceCommPackageLine.Modify(false); + SetupItemCustomerAndSalesHeaderWithVAT(VATPostingSetup); + SalesHeader.Validate("Prices Including VAT", true); + SalesHeader.Modify(true); + + // [WHEN] A sales line is created, the unit price is set, and the order is posted (shipped) + LibrarySales.CreateSalesLineWithShipmentDate(SalesLine, SalesHeader, Enum::"Sales Line Type"::Item, Item."No.", WorkDate(), 1); + SalesLine.Validate("Unit Price", LibraryRandom.RandDecInRange(100, 200, 2)); + SalesLine.Modify(true); + Currency.InitRoundingPrecision(); + ExpectedNetBaseAmount := Round( + SalesLine."Unit Price" / (1 + VATPostingSetup."VAT %" / 100), + Currency."Unit-Amount Rounding Precision"); + LibrarySales.PostSalesDocument(SalesHeader, true, false); + + // [THEN] The posted Subscription Line Calculation Base Amount is the net (VAT-exclusive) amount + ServiceObject.FilterOnItemNo(Item."No."); + ServiceObject.FindFirst(); + ServiceCommitment.SetRange("Subscription Header No.", ServiceObject."No."); + ServiceCommitment.SetRange(Partner, Enum::"Service Partner"::Customer); + ServiceCommitment.FindFirst(); + Assert.AreEqual( + ExpectedNetBaseAmount, + ServiceCommitment."Calculation Base Amount", + PostedSubLineCalcBaseAmtMustBeNetErr); + end; + [Test] procedure CheckSalesServiceCommitmentDiscountCalculation() var @@ -1113,8 +1257,19 @@ codeunit 139915 "Sales Service Commitment Test" Item4: Record Item; TempSalesServiceCommitmentBuff: Record "Sales Service Commitment Buff." temporary; ExpectedVATAmount: Decimal; + ItemVATPercent: Decimal; UniqueRhythmDictionary: Dictionary of [Code[20], Text]; begin + // [SCENARIO] CalcVATAmountLines correctly prorates subscription amounts by billing rhythm/period + // and groups buffer rows by (rhythm + base period + VAT rate). The expected VAT is calculated + // manually using the proration formula: Amount / (BasePeriodMonths / RhythmMonths) * VAT%. + + // [GIVEN] A Sales Order with four subscription lines covering three rhythm/period combinations: + // - Item (VAT rate A): Billing Rhythm <1M>, Billing Base Period <12M> → prorated as Amount/12*1 + // - Item4 (VAT rate B): Billing Rhythm <1M>, Billing Base Period <12M> → same rhythm, different VAT rate + // (produces a second buffer row for the same rhythm combination) + // - Item2 (VAT rate A): Billing Rhythm <3M>, Billing Base Period <12M> → prorated as Amount/12*3 + // - Item3 (VAT rate A): Billing Rhythm <3M>, Billing Base Period <2Y> → prorated as Amount/24*3 Initialize(); LibrarySales.CreateSalesHeader(SalesHeader, SalesHeader."Document Type"::Order, ''); if SalesHeader."Currency Code" = '' then @@ -1123,28 +1278,30 @@ codeunit 139915 "Sales Service Commitment Test" Currency.Get(SalesHeader."Currency Code"); ExpectedVATAmount := 0; - // "Billing Rhythm" = '<1M>', "Billing Base Period" = '<12M>' - SetupSalesLineForTotalAndVatCalculation(Item, true, 0); + // Item — Billing Rhythm <1M>, Billing Base Period <12M>, VAT rate A + SetupSalesLineForTotalAndVatCalculation(Item, true); SalesServiceCommitment.FilterOnSalesLine(SalesLine); SalesServiceCommitment.FindFirst(); ExpectedVATAmount += Round((SalesServiceCommitment.Amount / 12 * 1) * SalesLine."VAT %" / 100, Currency."Amount Rounding Precision", Currency.VATRoundingDirection()); - // Item with different VAT for same Billing Rhythm - SetupSalesLineForTotalAndVatCalculation(Item4, true, SalesLine."VAT %"); + // Item4 — same rhythm <1M>/<12M> but a different VAT rate (B), so it lands in a separate buffer row + ItemVATPercent := SalesLine."VAT %"; + SetupSalesLineForTotalAndVatCalculation(Item4, true); + ReassignSalesLineToDifferentVATGroup(ItemVATPercent); SalesServiceCommitment.FilterOnSalesLine(SalesLine); SalesServiceCommitment.FindFirst(); ExpectedVATAmount += Round((SalesServiceCommitment.Amount / 12 * 1) * SalesLine."VAT %" / 100, Currency."Amount Rounding Precision", Currency.VATRoundingDirection()); - // "Billing Rhythm" = '<3M>', "Billing Base Period" = '<12M>' - SetupSalesLineForTotalAndVatCalculation(Item2, true, 0); + // Item2 — Billing Rhythm <3M>, Billing Base Period <12M> + SetupSalesLineForTotalAndVatCalculation(Item2, true); SalesServiceCommitment.FilterOnSalesLine(SalesLine); SalesServiceCommitment.FindFirst(); Evaluate(SalesServiceCommitment."Billing Rhythm", '3M'); SalesServiceCommitment.Modify(false); ExpectedVATAmount += (SalesServiceCommitment.Amount / 12 * 3) * SalesLine."VAT %" / 100; - // "Billing Rhythm" = '<3M>', "Billing Base Period" = '<2Y>' - SetupSalesLineForTotalAndVatCalculation(Item3, true, 0); + // Item3 — Billing Rhythm <3M>, Billing Base Period <2Y> + SetupSalesLineForTotalAndVatCalculation(Item3, true); SalesServiceCommitment.FilterOnSalesLine(SalesLine); SalesServiceCommitment.FindFirst(); Evaluate(SalesServiceCommitment."Billing Base Period", '<2Y>'); @@ -1153,9 +1310,14 @@ codeunit 139915 "Sales Service Commitment Test" ExpectedVATAmount += (SalesServiceCommitment.Amount / 24 * 3) * SalesLine."VAT %" / 100; ExpectedVATAmount := Round(ExpectedVATAmount, Currency."Amount Rounding Precision", Currency.VATRoundingDirection()); + // [WHEN] VAT amount lines are calculated for the Sales Order SalesServiceCommitment.CalcVATAmountLines(SalesHeader, TempSalesServiceCommitmentBuff, UniqueRhythmDictionary); + // [THEN] The buffer contains one row per unique (rhythm + base period + VAT rate) combination. + // There are 3 unique rhythm/period combinations (UniqueRhythmDictionary.Count), but the <1M>/<12M> + // combination has two VAT rates (A and B), producing one extra row → Count + 1 rows in total. Assert.RecordCount(TempSalesServiceCommitmentBuff, UniqueRhythmDictionary.Count + 1); + // [THEN] The summed VAT amount across all buffer rows matches the manually prorated expected amount. TempSalesServiceCommitmentBuff.CalcSums("VAT Amount"); Assert.AreEqual(ExpectedVATAmount, TempSalesServiceCommitmentBuff."VAT Amount", 'Service Items VAT Amount not calculated properly.'); end; @@ -2126,6 +2288,34 @@ codeunit 139915 "Sales Service Commitment Test" SalesHeaderArchive.FindFirst(); end; + local procedure FindCustomerDocumentPriceSalesServiceCommitment() + begin + SalesServiceCommitment.FilterOnSalesLine(SalesLine); + SalesServiceCommitment.SetRange(Partner, Enum::"Service Partner"::Customer); + SalesServiceCommitment.SetRange("Calculation Base Type", Enum::"Calculation Base Type"::"Document Price"); + SalesServiceCommitment.FindFirst(); + end; + + local procedure FindNonZeroVATPostingSetup(var VATPostingSetup: Record "VAT Posting Setup") + begin + LibraryERM.FindVATPostingSetupInvt(VATPostingSetup); + if VATPostingSetup."VAT %" = 0 then begin + VATPostingSetup."VAT %" := LibraryRandom.RandDecInRange(10, 25, 0); + VATPostingSetup.Modify(false); + end; + end; + + local procedure ReassignSalesLineToDifferentVATGroup(ExcludeVATPct: Decimal) + var + VATPostingSetup: Record "VAT Posting Setup"; + begin + LibraryERM.FindVATPostingSetupInvt(VATPostingSetup); + VATPostingSetup.SetFilter("VAT %", '<>%1', ExcludeVATPct); + VATPostingSetup.FindFirst(); + SalesLine.Validate("VAT Prod. Posting Group", VATPostingSetup."VAT Prod. Posting Group"); + SalesLine.Modify(true); + end; + local procedure FindWarehouseActivityLine(var WarehouseActivityLine: Record "Warehouse Activity Line"; SourceType: Integer; SourceNo: Code[20]; ActivityType: Enum "Warehouse Activity Type") begin WarehouseActivityLine.SetRange("Source Type", SourceType); @@ -2221,6 +2411,19 @@ codeunit 139915 "Sales Service Commitment Test" ServiceCommPackageLine.Modify(false); end; + local procedure SetupItemCustomerAndSalesHeaderWithVAT(var VATPostingSetup: Record "VAT Posting Setup") + begin + FindNonZeroVATPostingSetup(VATPostingSetup); + ContractTestLibrary.SetupSalesServiceCommitmentItemAndAssignToServiceCommitmentPackage( + Item, Enum::"Item Service Commitment Type"::"Sales with Service Commitment", ServiceCommitmentPackage.Code); + Item.Validate("VAT Prod. Posting Group", VATPostingSetup."VAT Prod. Posting Group"); + Item.Modify(true); + LibrarySales.CreateCustomer(Customer); + Customer.Validate("VAT Bus. Posting Group", VATPostingSetup."VAT Bus. Posting Group"); + Customer.Modify(true); + LibrarySales.CreateSalesHeader(SalesHeader, SalesHeader."Document Type"::Order, Customer."No."); + end; + local procedure SetupForInventoryPick() begin SetupInventorySetupForInventoryPick(); @@ -2271,22 +2474,16 @@ codeunit 139915 "Sales Service Commitment Test" Location.Modify(true); end; - local procedure SetupSalesLineForTotalAndVatCalculation(var NewItem: Record Item; SetupServiceItemWithPackage: Boolean; ReferentVatPercent: Decimal) + local procedure SetupSalesLineForTotalAndVatCalculation(var NewItem: Record Item; SetupServiceItemWithPackage: Boolean) var VATPostingSetup: Record "VAT Posting Setup"; - begin if SetupServiceItemWithPackage then ContractTestLibrary.SetupSalesServiceCommitmentItemAndAssignToServiceCommitmentPackage(NewItem, Enum::"Item Service Commitment Type"::"Service Commitment Item", ServiceCommitmentPackage.Code) else ContractTestLibrary.CreateInventoryItem(NewItem); - if ReferentVatPercent <> 0 then begin - LibraryERM.FindVATPostingSetupInvt(VATPostingSetup); - VATPostingSetup.SetFilter("VAT Prod. Posting Group", '<>%1', NewItem."VAT Prod. Posting Group"); - VATPostingSetup.SetFilter("VAT %", '<>%1', ReferentVatPercent); - VATPostingSetup.FindFirst(); - NewItem.Validate("VAT Prod. Posting Group", VATPostingSetup."VAT Prod. Posting Group"); - end; + FindNonZeroVATPostingSetup(VATPostingSetup); + NewItem.Validate("VAT Prod. Posting Group", VATPostingSetup."VAT Prod. Posting Group"); ContractTestLibrary.UpdateItemUnitCostAndPrice(NewItem, LibraryRandom.RandDec(10000, 2), LibraryRandom.RandDec(10000, 2), false); LibrarySales.CreateSalesLine(SalesLine, SalesHeader, Enum::"Sales Line Type"::Item, NewItem."No.", LibraryRandom.RandInt(100)); end; From 5c26ab1ab433dcdcb96517a4ccc172a7e1c64e18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miljan=20Milosavljevi=C4=87?= Date: Mon, 11 May 2026 15:31:40 +0200 Subject: [PATCH 2/2] Unused using directive --- .../App/Billing/Codeunits/SalesDocuments.Codeunit.al | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Apps/W1/Subscription Billing/App/Billing/Codeunits/SalesDocuments.Codeunit.al b/src/Apps/W1/Subscription Billing/App/Billing/Codeunits/SalesDocuments.Codeunit.al index af7b9ab00b..b9eae6e219 100644 --- a/src/Apps/W1/Subscription Billing/App/Billing/Codeunits/SalesDocuments.Codeunit.al +++ b/src/Apps/W1/Subscription Billing/App/Billing/Codeunits/SalesDocuments.Codeunit.al @@ -1,6 +1,5 @@ namespace Microsoft.SubscriptionBilling; -using Microsoft.Finance.Currency; using Microsoft.Finance.GeneralLedger.Account; using Microsoft.Finance.GeneralLedger.Journal; using Microsoft.Finance.GeneralLedger.Posting;