diff --git a/VAT VIES example/App/.vscode/settings.json b/VAT VIES example/App/.vscode/settings.json new file mode 100644 index 0000000..a220956 --- /dev/null +++ b/VAT VIES example/App/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "CRS.ObjectNameSuffix": "", + "CRS.FileNamePattern": "..al", + "CRS.FileNamePatternExtensions": "..al", + "CRS.ExtensionObjectNamePattern": "", + "CRS.RemoveSuffixFromFilename": true, + "al.assemblyProbingPaths": [ + "./.netpackages", + "c:/Windows/assembly/" + ] +} \ No newline at end of file diff --git a/VAT VIES example/App/app.json b/VAT VIES example/App/app.json new file mode 100644 index 0000000..c646acc --- /dev/null +++ b/VAT VIES example/App/app.json @@ -0,0 +1,33 @@ +{ + "id": "0540c3dc-8554-44a8-9c6e-f5205a664a7c", + "name": "VAT VIES Interface Example", + "publisher": "fluxxus.nl", + "brief": "Using VAT VIES interface example", + "description": "Using VAT VIES interface example to illustrate interface-based injection", + "version": "1.0.0.0", + "privacyStatement": "", + "EULA": "", + "help": "", + "url": "", + "logo": "", + "dependencies": [ ], + "screenshots": [], + "platform": "21.0.0.0", + "application": "1.0.0.0", + "idRanges": [ + { + "from": 58700, + "to": 58799 + } + ], + "target": "OnPrem", + "resourceExposurePolicy": { + "allowDebugging": true, + "allowDownloadingSource": true, + "includeSourceInSymbolFile": true + }, + "runtime": "10.0", + "features": [ + "NoImplicitWith" + ] +} diff --git a/VAT VIES example/App/src/codeunit/CheckVIESForVATNoAndLog.Codeunit.al b/VAT VIES example/App/src/codeunit/CheckVIESForVATNoAndLog.Codeunit.al new file mode 100644 index 0000000..613e111 --- /dev/null +++ b/VAT VIES example/App/src/codeunit/CheckVIESForVATNoAndLog.Codeunit.al @@ -0,0 +1,184 @@ +codeunit 58758 "Check VIES For VAT No And Log" implements "VAT Validation Handling Interface" +// abstracted from codeunit 248 "VAT Lookup Ext. Data Hndl" +{ + Permissions = TableData "VAT Registration Log" = rimd; + + procedure CheckandLogVATNo(var VATRegistrationLog: Record "VAT Registration Log"); + begin + VATRegistrationLog2 := VATRegistrationLog; + + LookupVatRegistrationFromWebService(true); + + OnRunOnAfterLookupVatRegistrationFromWebService(VATRegistrationLog); + + VATRegistrationLog := VATRegistrationLog2; + end; + + var + VATRegistrationLog2: Record "VAT Registration Log"; + VATRegistrationLogMgt: Codeunit "VAT Registration Log Mgt."; + + NamespaceTxt: Label 'urn:ec.europa.eu:taxud:vies:services:checkVat:types', Locked = true; + VatRegNrValidationWebServiceURLTxt: Label 'http://ec.europa.eu/taxation_customs/vies/services/checkVatService', Locked = true; + NoVATNoToValidateErr: Label 'Specify the VAT registration number that you want to verify.'; + EUVATRegNoValidationServiceTok: Label 'EUVATRegNoValidationServiceTelemetryCategoryTok', Locked = true; + ValidationSuccessfulMsg: Label 'The VAT reg. no. validation was successful', Locked = true; + ValidationFailureMsg: Label 'The VAT reg. no. validation failed. Http request failure', Locked = true; + VATRegistrationURL: Text; + + local procedure LookupVatRegistrationFromWebService(ShowErrors: Boolean) + var + TempBlobRequestBody: Codeunit "Temp Blob"; + begin + SendRequestToVatRegistrationService(TempBlobRequestBody, ShowErrors); + + InsertLogEntry(TempBlobRequestBody); + + Commit(); + end; + + local procedure SendRequestToVatRegistrationService(var TempBlobBody: Codeunit "Temp Blob"; ShowErrors: Boolean) + var + VATRegNoSrvConfig: Record "VAT Reg. No. Srv Config"; + SOAPWebServiceRequestMgt: Codeunit "SOAP Web Service Request Mgt."; + ResponseInStream: InStream; + InStream: InStream; + ResponseOutStream: OutStream; + IsHandled: Boolean; + begin + VATRegistrationURL := VATRegNoSrvConfig.GetVATRegNoURL(); + + if VATRegistrationLog2."VAT Registration No." = '' then + Error(NoVATNoToValidateErr); + + PrepareSOAPRequestBody(TempBlobBody); + + TempBlobBody.CreateInStream(InStream); + SOAPWebServiceRequestMgt.SetGlobals(InStream, VATRegistrationURL, '', ''); + SOAPWebServiceRequestMgt.DisableHttpsCheck(); + SOAPWebServiceRequestMgt.SetTimeout(60000); + SOAPWebServiceRequestMgt.SetContentType('text/xml;charset=utf-8'); + + OnSendRequestToVatRegistrationServiceOnBeforeSendRequestToWebService(SOAPWebServiceRequestMgt, TempBlobBody); + if SOAPWebServiceRequestMgt.SendRequestToWebService() then begin + SOAPWebServiceRequestMgt.GetResponseContent(ResponseInStream); + + TempBlobBody.CreateOutStream(ResponseOutStream); + CopyStream(ResponseOutStream, ResponseInStream); + + Session.LogMessage('0000C3Q', ValidationSuccessfulMsg, Verbosity::Normal, DataClassification::SystemMetadata, TelemetryScope::ExtensionPublisher, 'Category', EUVATRegNoValidationServiceTok); + end else begin + Session.LogMessage('0000C4S', ValidationFailureMsg, Verbosity::Error, DataClassification::SystemMetadata, TelemetryScope::ExtensionPublisher, 'Category', EUVATRegNoValidationServiceTok); + IsHandled := false; + OnSendRequestToVATRegistrationServiceBeforeShowErrors(VATRegistrationLog2, IsHandled); + if not IsHandled then + if ShowErrors then + SOAPWebServiceRequestMgt.ProcessFaultResponse(''); + end; + end; + + local procedure PrepareSOAPRequestBody(var TempBlob: Codeunit "Temp Blob") + var + Customer: Record Customer; + VATRegNoSrvTemplate: Record "VAT Reg. No. Srv. Template"; + XMLDOMMgt: Codeunit "XML DOM Management"; + RecordRef: RecordRef; + BodyContentInputStream: InStream; + BodyContentOutputStream: OutStream; + BodyContentXmlDoc: DotNet XmlDocument; + EnvelopeXmlNode: DotNet XmlNode; + CreatedXmlNode: DotNet XmlNode; + AccountName: Text; + AccountStreet: Text; + AccountCity: Text; + AccountPostCode: Text; + begin + TempBlob.CreateInStream(BodyContentInputStream); + BodyContentXmlDoc := BodyContentXmlDoc.XmlDocument(); + + XMLDOMMgt.AddRootElementWithPrefix(BodyContentXmlDoc, 'checkVatApprox', '', NamespaceTxt, EnvelopeXmlNode); + XMLDOMMgt.AddElement(EnvelopeXmlNode, 'countryCode', VATRegistrationLog2.GetCountryCode(), NamespaceTxt, CreatedXmlNode); + XMLDOMMgt.AddElement(EnvelopeXmlNode, 'vatNumber', VATRegistrationLog2.GetVATRegNo(), NamespaceTxt, CreatedXmlNode); + XMLDOMMgt.AddElement( + EnvelopeXmlNode, 'requesterCountryCode', VATRegistrationLog2.GetCountryCode(), NamespaceTxt, CreatedXmlNode); + XMLDOMMgt.AddElement( + EnvelopeXmlNode, 'requesterVatNumber', VATRegistrationLog2.GetVATRegNo(), NamespaceTxt, CreatedXmlNode); + + InitializeVATRegistrationLog(VATRegistrationLog2); + + if VATRegistrationLog2.GetAccountRecordRef(RecordRef) then begin + AccountName := GetField(RecordRef, Customer.FieldName(Name)); + AccountStreet := GetField(RecordRef, Customer.FieldName(Address)); + AccountPostCode := GetField(RecordRef, Customer.FieldName("Post Code")); + AccountCity := GetField(RecordRef, Customer.FieldName(City)); + VATRegistrationLog2.SetAccountDetails(AccountName, AccountStreet, AccountCity, AccountPostCode); + end; + + VATRegistrationLog2.CheckGetTemplate(VATRegNoSrvTemplate); + if VATRegNoSrvTemplate."Validate Name" then + XMLDOMMgt.AddElement(EnvelopeXmlNode, 'traderName', AccountName, NamespaceTxt, CreatedXmlNode); + if VATRegNoSrvTemplate."Validate Street" then + XMLDOMMgt.AddElement(EnvelopeXmlNode, 'traderStreet', AccountStreet, NamespaceTxt, CreatedXmlNode); + if VATRegNoSrvTemplate."Validate City" then + XMLDOMMgt.AddElement(EnvelopeXmlNode, 'traderCity', AccountCity, NamespaceTxt, CreatedXmlNode); + if VATRegNoSrvTemplate."Validate Post Code" then + XMLDOMMgt.AddElement(EnvelopeXmlNode, 'traderPostcode', AccountPostCode, NamespaceTxt, CreatedXmlNode); + + Clear(TempBlob); + TempBlob.CreateOutStream(BodyContentOutputStream); + BodyContentXmlDoc.Save(BodyContentOutputStream); + end; + + local procedure InitializeVATRegistrationLog(var VATRegistrationLog: Record "VAT Registration Log") + begin + VATRegistrationLog."Verified Name" := ''; + VATRegistrationLog."Verified City" := ''; + VATRegistrationLog."Verified Street" := ''; + VATRegistrationLog."Verified Postcode" := ''; + VATRegistrationLog."Verified Address" := ''; + VATRegistrationLog.Template := ''; + VATRegistrationLog."Details Status" := VATRegistrationLog."Details Status"::"Not Verified"; + end; + + local procedure InsertLogEntry(TempBlobRequestBody: Codeunit "Temp Blob") + var + XMLDOMManagement: Codeunit "XML DOM Management"; + XMLDocOut: DotNet XmlDocument; + InStream: InStream; + begin + TempBlobRequestBody.CreateInStream(InStream); + XMLDOMManagement.LoadXMLDocumentFromInStream(InStream, XMLDocOut); + + VATRegistrationLogMgt.LogVerification(VATRegistrationLog2, XMLDocOut, NamespaceTxt); + end; + + procedure GetVATRegNrValidationWebServiceURL(): Text[250] + begin + exit(VatRegNrValidationWebServiceURLTxt); + end; + + local procedure GetField(var RecordRef: RecordRef; FieldName: Text) Result: Text; + var + DataTypeManagement: Codeunit "Data Type Management"; + FieldRef: FieldRef; + begin + if DataTypeManagement.FindFieldByName(RecordRef, FieldRef, FieldName) then + Result := FieldRef.Value(); + end; + + [IntegrationEvent(false, false)] + local procedure OnRunOnAfterLookupVatRegistrationFromWebService(var VATRegistrationLog: Record "VAT Registration Log") + begin + end; + + [IntegrationEvent(false, false)] + local procedure OnSendRequestToVatRegistrationServiceOnBeforeSendRequestToWebService(var SOAPWebServiceRequestMgt: Codeunit "SOAP Web Service Request Mgt."; var TempBlobBody: Codeunit "Temp Blob") + begin + end; + + [IntegrationEvent(false, false)] + local procedure OnSendRequestToVATRegistrationServiceBeforeShowErrors(var VATRegistrationLog: Record "VAT Registration Log"; var IsHandled: Boolean) + begin + end; +} + diff --git a/VAT VIES example/App/src/codeunit/VATRegLogMgtSetup.Codeunit.al b/VAT VIES example/App/src/codeunit/VATRegLogMgtSetup.Codeunit.al new file mode 100644 index 0000000..94d9c26 --- /dev/null +++ b/VAT VIES example/App/src/codeunit/VATRegLogMgtSetup.Codeunit.al @@ -0,0 +1,81 @@ +codeunit 58759 "VAT Reg. Log Mgt. Setup" +// abstracted from codeunit 249 "VAT Registration Log Mgt." and adjusted: added VATRegNoSrvCodeunitId parameter +{ + Permissions = TableData "VAT Registration Log" = rimd; + + var + DataTypeManagement: Codeunit "Data Type Management"; + ValidVATNoMsg: Label 'The specified VAT registration number is valid.'; + InvalidVatRegNoMsg: Label 'We didn''t find a match for this VAT registration number. Please verify that you specified the right number.'; + NotVerifiedVATRegMsg: Label 'We couldn''t verify the VAT registration number. Please try again later.'; + DetailsNotVerifiedMsg: Label 'The specified VAT registration number is valid.\The VAT VIES validation service did not provide additional details.'; + + procedure ValidateVATRegNoWithVIES(var RecordRef: RecordRef; RecordVariant: Variant; EntryNo: Code[20]; AccountType: Option; CountryCode: Code[10]) + var + VATRegistrationLog: Record "VAT Registration Log"; + begin + CheckVIESForVATNo(RecordRef, VATRegistrationLog, RecordVariant, EntryNo, CountryCode, AccountType); + + if VATRegistrationLog.Find() then // Only update if the log was created + UpdateRecordFromVATRegLog(RecordRef, RecordVariant, VATRegistrationLog); + end; + + procedure CheckVIESForVATNo(var RecordRef: RecordRef; var VATRegistrationLog: Record "VAT Registration Log"; RecordVariant: Variant; EntryNo: Code[20]; CountryCode: Code[10]; AccountType: Option) + var + VATRegNo: Record "VAT Registration No."; + VATRegNoSrvConfig: Record "VAT Reg. No. Srv Config"; + CountryRegion: Record "Country/Region"; + VatRegNoFieldRef: FieldRef; + VATRegNoTxt: Text[20]; + begin + RecordRef.GetTable(RecordVariant); + if not CountryRegion.IsEUCountry(CountryCode) then + exit; // VAT Reg. check Srv. is only available for EU countries. + + if VATRegNoSrvConfig.VATRegNoSrvIsEnabled() then begin + DataTypeManagement.GetRecordRef(RecordVariant, RecordRef); + if not DataTypeManagement.FindFieldByName(RecordRef, VatRegNoFieldRef, VATRegNo.FieldName("VAT Registration No.")) then + exit; + VATRegNoTxt := VatRegNoFieldRef.Value; + + VATRegistrationLog.InitVATRegLog(VATRegistrationLog, CountryCode, AccountType, EntryNo, VATRegNoTxt); + CheckandLogVATNo(VATRegistrationLog); + end; + end; + + procedure UpdateRecordFromVATRegLog(var RecordRef: RecordRef; RecordVariant: Variant; VATRegistrationLog: Record "VAT Registration Log") + begin + if GuiAllowed() then begin + RecordRef.GetTable(RecordVariant); + case VATRegistrationLog.Status of + VATRegistrationLog.Status::Valid: + case VATRegistrationLog."Details Status" of + VATRegistrationLog."Details Status"::"Not Verified": + Message(DetailsNotVerifiedMsg); + VATRegistrationLog."Details Status"::Valid: + Message(ValidVATNoMsg); + VATRegistrationLog."Details Status"::"Partially Valid", + VATRegistrationLog."Details Status"::"Not Valid": + begin + DataTypeManagement.GetRecordRef(RecordVariant, RecordRef); + VATRegistrationLog.OpenDetailsForRecRef(RecordRef); + end; + end; + VATRegistrationLog.Status::Invalid: + Message(InvalidVatRegNoMsg); + else + Message(NotVerifiedVATRegMsg); + end; + end; + end; + + local procedure CheckandLogVATNo(var VATRegistrationLog: Record "VAT Registration Log") + var + VATRegNoSrvConfig: Record "VAT Reg. No. Srv Config"; + VATValidationHandlingInterface: interface "VAT Validation Handling Interface"; + begin + VATRegNoSrvConfig.Get(); + VATValidationHandlingInterface := VATRegNoSrvConfig."VAT Validation Handling Type"; + VATValidationHandlingInterface.CheckandLogVATNo(VATRegistrationLog); + end; +} \ No newline at end of file diff --git a/VAT VIES example/App/src/enum/VATValidationHandlingType.Enum.al b/VAT VIES example/App/src/enum/VATValidationHandlingType.Enum.al new file mode 100644 index 0000000..cdb51be --- /dev/null +++ b/VAT VIES example/App/src/enum/VATValidationHandlingType.Enum.al @@ -0,0 +1,11 @@ +enum 58700 "VAT Validation Handling Type" implements "VAT Validation Handling Interface" +{ + Extensible = true; + Caption = 'VAT Validation Handling Type'; + + value(0; "VAT VIES") + { + Caption = 'VAT VIES'; + Implementation = "VAT Validation Handling Interface" = "Check VIES For VAT No And Log"; + } +} \ No newline at end of file diff --git a/VAT VIES example/App/src/interface/VATValidationHandlingInterface.Interface.al b/VAT VIES example/App/src/interface/VATValidationHandlingInterface.Interface.al new file mode 100644 index 0000000..5193447 --- /dev/null +++ b/VAT VIES example/App/src/interface/VATValidationHandlingInterface.Interface.al @@ -0,0 +1,4 @@ +interface "VAT Validation Handling Interface" +{ + procedure CheckandLogVATNo(var VATRegistrationLog: Record "VAT Registration Log"); +} \ No newline at end of file diff --git a/VAT VIES example/App/src/page/VATRegistrationNos.Page.al b/VAT VIES example/App/src/page/VATRegistrationNos.Page.al new file mode 100644 index 0000000..d87b2ce --- /dev/null +++ b/VAT VIES example/App/src/page/VATRegistrationNos.Page.al @@ -0,0 +1,58 @@ +page 58700 "VAT Registration Nos." +{ + ApplicationArea = All; + Caption = 'VAT Registration Nos.'; + PageType = List; + SourceTable = "VAT Registration No."; + UsageCategory = Lists; + + layout + { + area(content) + { + repeater(General) + { + field("No."; Rec."Entry No.") + { + ToolTip = 'Specifies the value of the Entry No. field'; + ApplicationArea = All; + } + field("Country/Region Code"; Rec."Country/Region Code") + { + ToolTip = 'Specifies the value of the Country/Region Code field'; + ApplicationArea = All; + } + field("VAT Registration No."; Rec."VAT Registration No.") + { + ToolTip = 'Specifies the value of the VAT Registration No. field'; + ApplicationArea = All; + } + } + } + } + + actions + { + area(Navigation) + { + action(VATRegistrationConfig) + { + ApplicationArea = All; + Caption = 'EU VAT Registration No. Validation Service Setup'; + Image = NumberSetup; + Promoted = true; + PromotedCategory = Process; + RunObject = page "VAT Registration Config"; + } + action(VATRegistrationLog) + { + ApplicationArea = All; + Caption = 'VAT Registration Log'; + Image = ImportLog; + Promoted = true; + PromotedCategory = Process; + RunObject = page "VAT Registration Log"; + } + } + } +} \ No newline at end of file diff --git a/VAT VIES example/App/src/pageextension/VATRegistrationConfigExt.PageExt.al b/VAT VIES example/App/src/pageextension/VATRegistrationConfigExt.PageExt.al new file mode 100644 index 0000000..f9f48ef --- /dev/null +++ b/VAT VIES example/App/src/pageextension/VATRegistrationConfigExt.PageExt.al @@ -0,0 +1,14 @@ +pageextension 58700 "VAT Registration Config Ext." extends "VAT Registration Config" +{ + layout + { + addlast(General) + { + field("Handling Codeunit ID"; Rec."VAT Validation Handling Type") + { + ToolTip = 'Specifies the id of the codeunit that implements the interaction with the EU VAT Registration No. Validation Service.'; + ApplicationArea = All; + } + } + } +} \ No newline at end of file diff --git a/VAT VIES example/App/src/table/VATRegistrationNo.Table.al b/VAT VIES example/App/src/table/VATRegistrationNo.Table.al new file mode 100644 index 0000000..bb35766 --- /dev/null +++ b/VAT VIES example/App/src/table/VATRegistrationNo.Table.al @@ -0,0 +1,72 @@ +table 58700 "VAT Registration No." +{ + DataClassification = ToBeClassified; + Caption = 'VAT Registration Nos.'; + + fields + { + field(1; "Entry No."; Code[20]) + { + DataClassification = ToBeClassified; + Caption = 'No.'; + NotBlank = true; + } + field(35; "Country/Region Code"; Code[10]) + { + DataClassification = ToBeClassified; + Caption = 'Country/Region Code'; + TableRelation = "Country/Region"; + + trigger OnValidate() + begin + if "Country/Region Code" <> xRec."Country/Region Code" then + VATRegistrationValidation(); + end; + } + field(86; "VAT Registration No."; Text[20]) + { + DataClassification = ToBeClassified; + Caption = 'VAT Registration No.'; + + trigger OnValidate() + begin + "VAT Registration No." := UpperCase("VAT Registration No."); + if "VAT Registration No." <> xRec."VAT Registration No." then + VATRegistrationValidation(); + end; + } + } + + keys + { + key(PK; "Entry No.") + { + Clustered = true; + } + } + + local procedure VATRegistrationValidation() + var + VATRegistrationNoFormat: Record "VAT Registration No. Format"; + VATRegistrationLog: Record "VAT Registration Log"; + VATRegNoSrvConfig: Record "VAT Reg. No. Srv Config"; + VATRegistrationLogMgt: Codeunit "VAT Reg. Log Mgt. Setup"; + ResultRecordRef: RecordRef; + ApplicableCountryCode: Code[10]; + begin + if not VATRegistrationNoFormat.Test("VAT Registration No.", "Country/Region Code", "Entry No.", DATABASE::"VAT Registration No.") then + exit; + + if ("Country/Region Code" <> '') or (VATRegistrationNoFormat."Country/Region Code" <> '') then begin + ApplicableCountryCode := "Country/Region Code"; + if ApplicableCountryCode = '' then + ApplicableCountryCode := VATRegistrationNoFormat."Country/Region Code"; + if VATRegNoSrvConfig.VATRegNoSrvIsEnabled then begin + VATRegistrationLogMgt.ValidateVATRegNoWithVIES( + ResultRecordRef, Rec, "Entry No.", VATRegistrationLog."Account Type"::Customer.AsInteger(), ApplicableCountryCode); + + ResultRecordRef.SetTable(Rec); + end; + end; + end; +} \ No newline at end of file diff --git a/VAT VIES example/App/src/tableextension/VATRegNoSrvConfigExt.TableExt.al b/VAT VIES example/App/src/tableextension/VATRegNoSrvConfigExt.TableExt.al new file mode 100644 index 0000000..7bdfd7f --- /dev/null +++ b/VAT VIES example/App/src/tableextension/VATRegNoSrvConfigExt.TableExt.al @@ -0,0 +1,11 @@ +tableextension 58700 "VAT Reg. No. Srv Config Ext." extends "VAT Reg. No. Srv Config" +{ + fields + { + field(58700; "VAT Validation Handling Type"; Enum "VAT Validation Handling Type") + { + Caption = 'VAT Validation Handling Type'; + DataClassification = ToBeClassified; + } + } +} \ No newline at end of file diff --git a/VAT VIES example/Test/.vscode/settings.json b/VAT VIES example/Test/.vscode/settings.json new file mode 100644 index 0000000..a220956 --- /dev/null +++ b/VAT VIES example/Test/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "CRS.ObjectNameSuffix": "", + "CRS.FileNamePattern": "..al", + "CRS.FileNamePatternExtensions": "..al", + "CRS.ExtensionObjectNamePattern": "", + "CRS.RemoveSuffixFromFilename": true, + "al.assemblyProbingPaths": [ + "./.netpackages", + "c:/Windows/assembly/" + ] +} \ No newline at end of file diff --git a/VAT VIES example/Test/app.json b/VAT VIES example/Test/app.json new file mode 100644 index 0000000..1116410 --- /dev/null +++ b/VAT VIES example/Test/app.json @@ -0,0 +1,70 @@ +{ + "id": "81b90441-3f72-434f-b96c-18b946e85873", + "name": "Test VAT VIES Interface Example", + "publisher": "fluxxus.nl", + "brief": "Test app to VAT VIES interface example", + "description": "Test app to VAT VIES interface example to illustrate interface-based injection", + "version": "1.0.0.0", + "privacyStatement": "", + "EULA": "", + "help": "", + "url": "", + "logo": "", + "dependencies": [ + { + "id": "0540c3dc-8554-44a8-9c6e-f5205a664a7c", + "name": "VAT VIES Interface Example", + "publisher": "fluxxus.nl", + "version": "1.0.0.0" + }, + { + "id": "e7320ebb-08b3-4406-b1ec-b4927d3e280b", + "publisher": "Microsoft", + "version": "21.0.0.0", + "name": "Any" + }, + { + "id": "dd0be2ea-f733-4d65-bb34-a28f4624fb14", + "publisher": "Microsoft", + "version": "21.0.0.0", + "name": "Library Assert" + }, + { + "id": "5095f467-0a01-4b99-99d1-9ff1237d286f", + "publisher": "Microsoft", + "version": "21.0.0.0", + "name": "Library Variable Storage" + }, + { + "id": "5d86850b-0d76-4eca-bd7b-951ad998e997", + "publisher": "Microsoft", + "version": "21.0.0.0", + "name": "Tests-TestLibraries" + }, + { + "id": "23de40a6-dfe8-4f80-80db-d70f83ce8caf", + "name": "Test Runner", + "publisher": "Microsoft", + "version": "21.0.0.0" + } + ], + "screenshots": [], + "platform": "21.0.0.0", + "application": "1.0.0.0", + "idRanges": [ + { + "from": 89700, + "to": 89799 + } + ], + "target": "OnPrem", + "resourceExposurePolicy": { + "allowDebugging": true, + "allowDownloadingSource": true, + "includeSourceInSymbolFile": true + }, + "runtime": "10.0", + "features": [ + "NoImplicitWith" + ] +} diff --git a/VAT VIES example/Test/atdd.scenarios/Convert VAT Registration No Validation.ps1 b/VAT VIES example/Test/atdd.scenarios/Convert VAT Registration No Validation.ps1 new file mode 100644 index 0000000..be315a9 --- /dev/null +++ b/VAT VIES example/Test/atdd.scenarios/Convert VAT Registration No Validation.ps1 @@ -0,0 +1,8 @@ +& "./atdd.scenarios/VAT Registration No Validation.ps1" | ` + ConvertTo-ALTestCodeunit ` + -CodeunitID 89700 ` + -CodeunitName 'VAT Reg. No. Validation' ` + -InitializeFunction ` + -GivenFunctionName "Create {0}" ` + -ThenFunctionName "Verify {0}" ` + | Out-File '.\test\VATRegistrationNoValidation_2.Codeunit.al' \ No newline at end of file diff --git a/VAT VIES example/Test/atdd.scenarios/VAT Registration No Validation.ps1 b/VAT VIES example/Test/atdd.scenarios/VAT Registration No Validation.ps1 new file mode 100644 index 0000000..52494c1 --- /dev/null +++ b/VAT VIES example/Test/atdd.scenarios/VAT Registration No Validation.ps1 @@ -0,0 +1,35 @@ +Feature 'VAT Registration No. Validation ' { + Scenario 0001 'Test valid VAT registration number with DI' { + Given 'EU country' + Given 'Well formatted VAT registration number' + Given 'Enabled service' + Given 'Mock service handling codeunit returning valid' + When 'Set and validate country and VAT registration number' + Then 'Validation details page is shown' + Then 'Validation details contains name and address' + Then 'VAT registration log entry exists' + Then 'VAT registration log User Id equals current user' + Then 'VAT registration log Verified Date equals current datetime' + Then 'VAT registration log Status equals valid' + Then 'VAT registration log Request Identifier is populated' + Then 'VAT registration log Details Status equals Not Valid' + Then 'VAT registration log Verified Name equals name of details' + Then 'VAT registration log Verified Address equals address of details' + } + + Scenario 0002 'Test invalid VAT registration number with DI' { + Given 'EU country' + Given 'Well formatted VAT registration number' + Given 'Enabled service' + Given 'Mock service handling codeunit returning invalid' + When 'Set and validate country and VAT registration number' + Then 'No match found message thrown' + Then 'VAT registration log entry exists' + Then 'VAT registration log User Id equals current user' + Then 'VAT registration log Verified Date equals current datetime' + Then 'VAT registration log Status equals Invalid' + Then 'VAT registration log Request Identifier is empty' + Then 'VAT registration log Details Status equals Not Verified' + Then 'VAT registration log has no validation details' + } +} \ No newline at end of file diff --git a/VAT VIES example/Test/src/codeunit/InvalidVIESCheck.Codeunit.al b/VAT VIES example/Test/src/codeunit/InvalidVIESCheck.Codeunit.al new file mode 100644 index 0000000..929ec89 --- /dev/null +++ b/VAT VIES example/Test/src/codeunit/InvalidVIESCheck.Codeunit.al @@ -0,0 +1,34 @@ +codeunit 89799 "Invalid VIES Check" implements "VAT Validation Handling Interface" +// Mock of codeunit 248 "VAT Lookup Ext. Data Hndl" returning an invalid log entry +{ + Permissions = TableData "VAT Registration Log" = rimd; + + procedure CheckandLogVATNo(var VATRegistrationLog: Record "VAT Registration Log"); + begin + SetInvalidVATRegistrationLog(VATRegistrationLog); + end; + + local procedure SetInvalidVATRegistrationLog(var VATRegistrationLog: Record "VAT Registration Log") + var + VATRegistrationLogMgt: Codeunit "VAT Registration Log Mgt."; + InvalidVATResponseDoc: DotNet XmlDocument; + NamespaceTxt: Label 'urn:ec.europa.eu:taxud:vies:services:checkVat:types', Locked = true; + begin + CreateInvalidVATCheckResponse(InvalidVATResponseDoc); + VATRegistrationLogMgt.LogVerification(VATRegistrationLog, InvalidVATResponseDoc, NamespaceTxt); + end; + + local procedure CreateInvalidVATCheckResponse(var XMLDoc: DotNet XmlDocument) + var + XMLDOMMgt: Codeunit "XML DOM Management"; + VATNode: DotNet XmlNode; + InvalidNode: DotNet XmlNode; + NamespaceTxt: Label 'urn:ec.europa.eu:taxud:vies:services:checkVat:types', Locked = true; + VATTxt: Label 'vat', Locked = true; + ValidTxt: Label 'valid', Locked = true; + begin + XMLDoc := XMLDoc.XmlDocument; + XMLDOMMgt.AddRootElementWithPrefix(XMLDoc, VATTxt, '', NamespaceTxt, VATNode); + XMLDOMMgt.AddElement(VATNode, ValidTxt, 'false', NamespaceTxt, InvalidNode); + end; +} \ No newline at end of file diff --git a/VAT VIES example/Test/src/codeunit/ValidVIESCheck.Codeunit.al b/VAT VIES example/Test/src/codeunit/ValidVIESCheck.Codeunit.al new file mode 100644 index 0000000..90737e7 --- /dev/null +++ b/VAT VIES example/Test/src/codeunit/ValidVIESCheck.Codeunit.al @@ -0,0 +1,48 @@ +codeunit 89798 "Valid VIES Check" implements "VAT Validation Handling Interface" +// Mock of codeunit 248 "VAT Lookup Ext. Data Hndl" returning a invalid log entry +{ + Permissions = TableData "VAT Registration Log" = rimd; + + procedure CheckandLogVATNo(var VATRegistrationLog: Record "VAT Registration Log"); + begin + SetValidVATRegistrationLog(VATRegistrationLog); + + Commit(); // To allow for details page to be triggered to open after this + end; + + local procedure SetValidVATRegistrationLog(var VATRegistrationLog: Record "VAT Registration Log") + var + Any: Codeunit Any; + VATRegistrationLogMgt: Codeunit "VAT Registration Log Mgt."; + ValidVATResponseDoc: DotNet XmlDocument; + ValidatedName: Text; + ValidatedAddress: Text; + NamespaceTxt: Label 'urn:ec.europa.eu:taxud:vies:services:checkVat:types', Locked = true; + begin + ValidatedName := Any.AlphanumericText(15); + ValidatedAddress := Any.AlphanumericText(15); + CreateValidVATCheckResponse(ValidVATResponseDoc, ValidatedName, ValidatedAddress); + VATRegistrationLogMgt.LogVerification(VATRegistrationLog, ValidVATResponseDoc, NamespaceTxt); + end; + + local procedure CreateValidVATCheckResponse(var XMLDoc: DotNet XmlDocument; ValidatedName: Text; ValidatedAddress: Text) + var + Any: Codeunit Any; + XMLDOMMgt: Codeunit "XML DOM Management"; + VATNode: DotNet XmlNode; + ValidNode: DotNet XmlNode; + NamespaceTxt: Label 'urn:ec.europa.eu:taxud:vies:services:checkVat:types', Locked = true; + AddressTxt: Label 'traderAddress', Locked = true; + NameTxt: Label 'traderName', Locked = true; + RequestIdTxt: Label 'requestIdentifier', Locked = true; + VATTxt: Label 'vat', Locked = true; + ValidTxt: Label 'valid', Locked = true; + begin + XMLDoc := XMLDoc.XmlDocument; + XMLDOMMgt.AddRootElementWithPrefix(XMLDoc, VATTxt, '', NamespaceTxt, VATNode); + XMLDOMMgt.AddElement(VATNode, RequestIdTxt, Any.AlphanumericText(15), NamespaceTxt, ValidNode); + XMLDOMMgt.AddElement(VATNode, ValidTxt, 'true', NamespaceTxt, ValidNode); + XMLDOMMgt.AddElement(VATNode, NameTxt, ValidatedName, NamespaceTxt, ValidNode); + XMLDOMMgt.AddElement(VATNode, AddressTxt, ValidatedAddress, NamespaceTxt, ValidNode); + end; +} \ No newline at end of file diff --git a/VAT VIES example/Test/src/enumextension/VATValidationHandlingType.EnumExt.al b/VAT VIES example/Test/src/enumextension/VATValidationHandlingType.EnumExt.al new file mode 100644 index 0000000..cc29f70 --- /dev/null +++ b/VAT VIES example/Test/src/enumextension/VATValidationHandlingType.EnumExt.al @@ -0,0 +1,14 @@ +enumextension 89700 "VAT Validation Handling Type" extends "VAT Validation Handling Type" +{ + + value(89700; "Valid VAT VIES Mock") + { + Caption = 'Valid VAT VIES Mock'; + Implementation = "VAT Validation Handling Interface" = "Valid VIES Check"; + } + value(89701; "Invalid VAT VIES Mock") + { + Caption = 'Invalid VAT VIES Mock'; + Implementation = "VAT Validation Handling Interface" = "Invalid VIES Check"; + } +} \ No newline at end of file diff --git a/VAT VIES example/Test/test/VATRegistrationNoValidation.Codeunit.al b/VAT VIES example/Test/test/VATRegistrationNoValidation.Codeunit.al new file mode 100644 index 0000000..b4fb4e5 Binary files /dev/null and b/VAT VIES example/Test/test/VATRegistrationNoValidation.Codeunit.al differ diff --git a/VAT VIES example/VAT VIES example.code-workspace b/VAT VIES example/VAT VIES example.code-workspace new file mode 100644 index 0000000..07cc0eb --- /dev/null +++ b/VAT VIES example/VAT VIES example.code-workspace @@ -0,0 +1,10 @@ +{ + "folders": [ + { + "path": "App" + }, + { + "path": "Test" + } + ] +} \ No newline at end of file