Skip to content

Commit

Permalink
Upload VAT VIES example of interface-based injection #2
Browse files Browse the repository at this point in the history
  • Loading branch information
lvanvugt committed Dec 5, 2022
1 parent 203f4e7 commit 1928752
Show file tree
Hide file tree
Showing 19 changed files with 709 additions and 0 deletions.
11 changes: 11 additions & 0 deletions VAT VIES example/App/.vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"CRS.ObjectNameSuffix": "",
"CRS.FileNamePattern": "<ObjectNameShort>.<ObjectTypeShortPascalCase>.al",
"CRS.FileNamePatternExtensions": "<ObjectNameShort>.<ObjectTypeShortPascalCase>.al",
"CRS.ExtensionObjectNamePattern": "",
"CRS.RemoveSuffixFromFilename": true,
"al.assemblyProbingPaths": [
"./.netpackages",
"c:/Windows/assembly/"
]
}
33 changes: 33 additions & 0 deletions VAT VIES example/App/app.json
Original file line number Diff line number Diff line change
@@ -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"
]
}
184 changes: 184 additions & 0 deletions VAT VIES example/App/src/codeunit/CheckVIESForVATNoAndLog.Codeunit.al
Original file line number Diff line number Diff line change
@@ -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;
}

81 changes: 81 additions & 0 deletions VAT VIES example/App/src/codeunit/VATRegLogMgtSetup.Codeunit.al
Original file line number Diff line number Diff line change
@@ -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;
}
11 changes: 11 additions & 0 deletions VAT VIES example/App/src/enum/VATValidationHandlingType.Enum.al
Original file line number Diff line number Diff line change
@@ -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";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface "VAT Validation Handling Interface"
{
procedure CheckandLogVATNo(var VATRegistrationLog: Record "VAT Registration Log");
}
58 changes: 58 additions & 0 deletions VAT VIES example/App/src/page/VATRegistrationNos.Page.al
Original file line number Diff line number Diff line change
@@ -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";
}
}
}
}
Loading

0 comments on commit 1928752

Please sign in to comment.