Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -2434,7 +2434,7 @@ codeunit 10750 "SII XML Creator"
Amount[i], CustNo, CustLedgerEntry."Document Type".AsInteger(), CustLedgerEntry."Document No.",
CustLedgerEntry."Posting Date", IsService, true, IsLocalRule, false);
end;
UpdateAmountBufferWithOneStopShop(HasEntries, Amount, TempVATEntry);
UpdateAmountBufferWithOneStopShop(HasEntries, Amount, TempVATEntry, CustLedgerEntry."Document Type" = CustLedgerEntry."Document Type"::"Credit Memo");
ExportNonTaxableVATEntries(
TipoDesgloseXMLNode, DesgloseFacturaXMLNode, DomesticXMLNode,
DesgloseTipoOperacionXMLNode, EUXMLNode, IsService, DomesticCustomer, HasEntries, RegimeCodes, Amount);
Expand Down Expand Up @@ -2462,13 +2462,13 @@ codeunit 10750 "SII XML Creator"
OldCustLedgerEntry."Posting Date", IsService, true, IsLocalRule);
ReplacementAmount[i] := Abs(OldAmount + Amount);
end;
UpdateAmountBufferWithOneStopShop(HasEntries, ReplacementAmount, TempVATEntry);
UpdateAmountBufferWithOneStopShop(HasEntries, ReplacementAmount, TempVATEntry, CustLedgerEntry."Document Type" = CustLedgerEntry."Document Type"::"Credit Memo");
ExportNonTaxableVATEntries(
TipoDesgloseXMLNode, DesgloseFacturaXMLNode, DomesticXMLNode, DesgloseTipoOperacionXMLNode, EUXMLNode, IsService, DomesticCustomer,
HasEntries, RegimeCodes, ReplacementAmount);
end;

local procedure UpdateAmountBufferWithOneStopShop(var HasEntries: array[2] of Boolean; var Amount: array[2] of Decimal; var TempVATEntry: Record "VAT Entry" temporary)
local procedure UpdateAmountBufferWithOneStopShop(var HasEntries: array[2] of Boolean; var Amount: array[2] of Decimal; var TempVATEntry: Record "VAT Entry" temporary; IsCreditMemo: Boolean)
var
HasOneStopShopEntries: Boolean;
begin
Expand All @@ -2479,7 +2479,11 @@ codeunit 10750 "SII XML Creator"
if not HasOneStopShopEntries then
exit;
HasEntries[2] := true;
Amount[2] += Abs(TempVATEntry.Base);
// For One-Stop-Shop, credit memos must report a negative ImporteTAIReglasLocalizacion, while invoices stay positive
if IsCreditMemo then
Amount[2] += -Abs(TempVATEntry.Base)
else
Amount[2] += Abs(TempVATEntry.Base);
end;

local procedure ExportNonTaxableVATEntries(var TipoDesgloseXMLNode: DotNet XmlNode; var DesgloseFacturaXMLNode: DotNet XmlNode; var DomesticXMLNode: DotNet XmlNode; var DesgloseTipoOperacionXMLNode: DotNet XmlNode; var EUXMLNode: DotNet XmlNode; IsService: Boolean; DomesticCustomer: Boolean; HasEntries: array[2] of Boolean; RegimeCodes: array[3] of Code[2]; Amount: array[2] of Decimal)
Expand Down
84 changes: 79 additions & 5 deletions src/Layers/ES/Tests/Local/SIIDocumentsNoTaxable.Codeunit.al
Original file line number Diff line number Diff line change
Expand Up @@ -2528,10 +2528,10 @@ codeunit 147524 "SII Documents No Taxable"
// [WHEN] Create xml for sales credit memo
Assert.IsTrue(SIIXMLCreator.GenerateXml(CustLedgerEntry, XMLDoc, UploadType::Regular, false), IncorrectXMLDocErr);

// [THEN] XML file has a sii:ImporteTAIReglasLocalizacion node with the VAT amount
// [THEN] XML file has a sii:ImporteTAIReglasLocalizacion node with the negative VAT amount
LibrarySII.VerifyOneNodeWithValueByXPath(
XMLDoc, XPathSalesNoTaxLocalTok, '',
SIIXMLCreator.FormatNumber(GetVATBaseAmountFromCustLedgEntry(CustLedgerEntry)));
SIIXMLCreator.FormatNumber(-GetVATBaseAmountFromCustLedgEntry(CustLedgerEntry)));
end;

[Test]
Expand All @@ -2553,10 +2553,33 @@ codeunit 147524 "SII Documents No Taxable"
// [WHEN] Create xml for sales credit memo
Assert.IsTrue(SIIXMLCreator.GenerateXml(CustLedgerEntry, XMLDoc, UploadType::Regular, false), IncorrectXMLDocErr);

// [THEN] XML file has a sii:ImporteTAIReglasLocalizacion node with the VAT amount
// [THEN] XML file has a sii:ImporteTAIReglasLocalizacion node with the negative VAT amount
LibrarySII.VerifyOneNodeWithValueByXPath(
XMLDoc, XPathSalesNoTaxLocalTok, '',
SIIXMLCreator.FormatNumber(GetVATBaseAmountFromCustLedgEntry(CustLedgerEntry)));
SIIXMLCreator.FormatNumber(-GetVATBaseAmountFromCustLedgEntry(CustLedgerEntry)));
end;

[Test]
[Scope('OnPrem')]
procedure CorrectiveSalesCrMemoWithOneStopShopHasNegativeAmount()
var
CustLedgerEntry: Record "Cust. Ledger Entry";
XMLDoc: DotNet XmlDocument;
begin
// [FEATURE] [Sales]
// [SCENARIO 639647] A corrective (R5) sales credit memo with One Stop Shop option has negative ImporteTAIReglasLocalizacion in SII XML

Initialize();
// [GIVEN] Posted sales invoice and posted corrective R5 sales credit memo with "Corrected Invoice No.", blank "Correction Type" and One Stop Shop option enabled
PostCorrectiveSalesCrMemoWithOneStopShop(CustLedgerEntry);

// [WHEN] Create xml for the corrective sales credit memo
Assert.IsTrue(SIIXMLCreator.GenerateXml(CustLedgerEntry, XMLDoc, UploadType::Regular, false), IncorrectXMLDocErr);

// [THEN] XML file has a sii:ImporteTAIReglasLocalizacion node with negative value
LibrarySII.VerifyOneNodeWithValueByXPath(
XMLDoc, XPathSalesNoTaxLocalTok, '',
SIIXMLCreator.FormatNumber(-GetVATBaseAmountFromCustLedgEntry(CustLedgerEntry)));
end;

[Test]
Expand Down Expand Up @@ -3223,6 +3246,56 @@ codeunit 147524 "SII Documents No Taxable"
LibraryERM.FindCustomerLedgerEntry(CustLedgerEntry, DocType, LibrarySales.PostSalesDocument(SalesHeader, true, true));
end;

local procedure PostCorrectiveSalesCrMemoWithOneStopShop(var CustLedgerEntry: Record "Cust. Ledger Entry")
var
SalesOrderHeader: Record "Sales Header";
PostedSalesInvoiceHeader: Record "Sales Invoice Header";
CreditMemoSalesHeader: Record "Sales Header";
VATPostingSetup: Record "VAT Posting Setup";
VATBusinessPostingGroup: Record "VAT Business Posting Group";
VATProductPostingGroup: Record "VAT Product Posting Group";
SalesLine: Record "Sales Line";
CorrectPostedSalesInvoice: Codeunit "Correct Posted Sales Invoice";
PostedInvoiceNo: Code[20];
begin
LibrarySales.CreateSalesHeader(SalesOrderHeader, SalesOrderHeader."Document Type"::Order, LibrarySales.CreateCustomerNo());
SalesOrderHeader.Validate("Special Scheme Code", SalesOrderHeader."Special Scheme Code"::"17 Operations Under The One-Stop-Shop Regime");
SalesOrderHeader.Modify(true);
VATBusinessPostingGroup.Get(SalesOrderHeader."VAT Bus. Posting Group");
LibrarySII.CreateVATPostingSetup(
VATPostingSetup, VATProductPostingGroup, VATBusinessPostingGroup,
VATPostingSetup."VAT Calculation Type"::"Normal VAT", LibraryRandom.RandInt(50), false);
VATPostingSetup.Validate("Sales Special Scheme Code", VATPostingSetup."Sales Special Scheme Code"::"17 Operations Under The One-Stop-Shop Regime");
VATPostingSetup.Validate("One Stop Shop Reporting", true);
VATPostingSetup.Modify(true);

LibrarySales.CreateSalesLine(
SalesLine, SalesOrderHeader, SalesLine.Type::"G/L Account", LibraryERM.CreateGLAccountWithSalesSetup(), LibraryRandom.RandInt(100));
SalesLine.Validate("VAT Prod. Posting Group", VATPostingSetup."VAT Prod. Posting Group");
SalesLine.Validate("Unit Price", LibraryRandom.RandDec(100, 2));
SalesLine.Modify(true);
PostedInvoiceNo := LibrarySales.PostSalesDocument(SalesOrderHeader, true, true);

PostedSalesInvoiceHeader.Get(PostedInvoiceNo);
if not CorrectPostedSalesInvoice.CreateCreditMemoCopyDocument(PostedSalesInvoiceHeader, CreditMemoSalesHeader) then
Error('Could not create corrective sales credit memo from posted invoice %1.', PostedInvoiceNo);

CreditMemoSalesHeader.Validate("Cr. Memo Type", CreditMemoSalesHeader."Cr. Memo Type"::"R5 Corrected Invoice in Simplified Invoices");
CreditMemoSalesHeader.Modify(true);

CreditMemoSalesHeader.TestField("Corrected Invoice No.", PostedInvoiceNo);
// The R5 corrective credit memo from the repro keeps a blank "Correction Type" (routes through the SII "por diferencias" / Difference path), not Replacement
CreditMemoSalesHeader.TestField("Correction Type", CreditMemoSalesHeader."Correction Type"::" ");
CreditMemoSalesHeader.TestField("Special Scheme Code", CreditMemoSalesHeader."Special Scheme Code"::"17 Operations Under The One-Stop-Shop Regime");
CreditMemoSalesHeader.TestField("Cr. Memo Type", CreditMemoSalesHeader."Cr. Memo Type"::"R5 Corrected Invoice in Simplified Invoices");

// Post the corrective credit memo with only the single OSS line copied from the invoice, mirroring the repro
LibraryERM.FindCustomerLedgerEntry(
CustLedgerEntry,
"Sales Document Type"::"Credit Memo",
LibrarySales.PostSalesDocument(CreditMemoSalesHeader, true, true));
end;

procedure PostSalesDocWithMixedOneStopShopOptions(var CustLedgerEntry: Record "Cust. Ledger Entry"; DocType: Enum "Sales Document Type"; CorrType: Option)
var
SalesHeader: Record "Sales Header";
Expand Down Expand Up @@ -3260,7 +3333,8 @@ codeunit 147524 "SII Documents No Taxable"
VATEntry.SetRange("Document No.", CustLedgEntry."Document No.");
VATEntry.SetRange("Posting Date", CustLedgEntry."Posting Date");
VATEntry.SetRange("One Stop Shop Reporting", true);
VATEntry.FindFirst();
Assert.IsFalse(VATEntry.IsEmpty(), 'Expected at least one One Stop Shop VAT Entry for the posted customer ledger entry.');
VATEntry.CalcSums(Base);
exit(Abs(VATEntry.Base));
end;

Expand Down
Loading