Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[E-Document Connector] SignUp E-Document Connector #27261

Open
wants to merge 37 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
d70b100
EDocument Connector SignUp
Sep 16, 2024
758acd2
Change obsolete field reference
Sep 17, 2024
013d1a7
Use IsSaaSInfrastructure to make fields visible if not in SaaS Sandbo…
Sep 17, 2024
5d3ad67
Push forward object id range by 10 due to Avalara addition
Sep 17, 2024
74c785b
Menu item Open Onboarding only available in SaaS
Sep 17, 2024
1042f9f
Change permission structure. Correct spelling. Adjust broken file ending
Sep 18, 2024
69453b6
Change to using instead of full namespace path
Sep 19, 2024
ebdb725
Refactor (MS) - Prefix Removal, Error Raise on Missing Config, Parame…
Sep 20, 2024
9eb3704
Resolve Build Conflict in GitHub - Rename
Sep 24, 2024
94266e2
Resolve Build Conflict in GitHub - Refactor Codeunit Processing
Sep 24, 2024
f9c4dc2
Merge branch 'microsoft:main' into edocumentconnector
geschwint Sep 25, 2024
def7176
Relocate To Own App - Move Files
Sep 25, 2024
9e817ea
Merge branch 'microsoft:main' into edocumentconnector
geschwint Sep 25, 2024
cd8da89
Merge branch 'edocumentconnector' of https://github.com/geschwint/ALA…
Sep 25, 2024
3811370
Refactor - Rename Files
Sep 25, 2024
17944a2
Refactor - Add app.json
Sep 25, 2024
6cdeaea
Refactor - Restore Original Objects
Sep 25, 2024
4382237
Refactor - Rename Processing
Sep 25, 2024
7bd134c
Refactor - Permission Extensions, Object Rename
Sep 25, 2024
42b9a11
Refactor - References to Processing
Sep 25, 2024
6480969
Refactor - Restore app.json
Sep 25, 2024
d7ecea8
Refactor - Missed a spot in restoring original
Sep 25, 2024
f6bc5f9
Merge branch 'microsoft:main' into edocumentconnector
geschwint Sep 25, 2024
f39fb47
Refactor - Missing Logo
Sep 26, 2024
a8c22c7
Refactor - Exit return value
Sep 27, 2024
e11508a
Refactor - Move UriTemplates to Global
Sep 27, 2024
bfca640
Refactor - Eliminate unneeded calls
Sep 27, 2024
1e24593
Refactor - Error when unsupported EDocument Type
Sep 27, 2024
8027450
Refactor - To use ErrorInfo
Sep 27, 2024
cdc94a6
Merge branch 'microsoft:main' into edocumentconnector
geschwint Sep 27, 2024
8bd90ac
Refactor - Move local labels to global
Sep 27, 2024
896cbe8
Refactor - No need for Retry
Sep 27, 2024
a12493f
Refactor - Make labels Global
Sep 27, 2024
ea3a35e
Refactor - Remove labels, API path inline the Avalara way
Sep 27, 2024
e991757
Refactor - Correct Telemetry Token
Sep 30, 2024
a8c547d
Refactor - Fix bug introduced during refactoring, Rename procedure to…
Oct 1, 2024
594e897
Merge branch 'microsoft:main' into edocumentconnector
geschwint Oct 1, 2024
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
2 changes: 1 addition & 1 deletion Apps/W1/EDocumentsConnector/app/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
"idRanges": [
{
"from": 6360,
"to": 6379
"to": 6389
}
],
"resourceExposurePolicy": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@
// ------------------------------------------------------------------------------------------------
namespace Microsoft.EServices.EDocumentConnector;

using Microsoft.EServices.EDocumentConnector.SignUp;

permissionset 6361 "EDocConnector - Edit"
{
Access = Public;
Assignable = true;
IncludedPermissionSets = "EDocConnector - Read";
IncludedPermissionSets = "EDocConnector - Read",
SignUpEDocEdit;
geschwint marked this conversation as resolved.
Show resolved Hide resolved


Permissions = tabledata "E-Doc. Ext. Connection Setup" = IM,
tabledata Microsoft.EServices.EDocumentConnector.Avalara."Connection Setup" = imd;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
// ------------------------------------------------------------------------------------------------
namespace Microsoft.EServices.EDocumentConnector;

using Microsoft.EServices.EDocumentConnector.SignUp;

permissionset 6363 "EDoc. Connector Objects"
{
Access = Public;
Assignable = false;
IncludedPermissionSets = SignUpEDocObjects;
geschwint marked this conversation as resolved.
Show resolved Hide resolved

Permissions = table "E-Doc. Ext. Connection Setup" = X,
page "EDoc Ext Connection Setup Card" = X,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@
// ------------------------------------------------------------------------------------------------
namespace Microsoft.EServices.EDocumentConnector;

using Microsoft.EServices.EDocumentConnector.SignUp;
geschwint marked this conversation as resolved.
Show resolved Hide resolved

permissionset 6362 "EDocConnector - Read"
{
Access = Public;
Assignable = true;
IncludedPermissionSets = "EDoc. Connector Objects";
IncludedPermissionSets = "EDoc. Connector Objects",
SignUpEDocRead;
geschwint marked this conversation as resolved.
Show resolved Hide resolved

Permissions = tabledata "E-Doc. Ext. Connection Setup" = R,
tabledata Microsoft.EServices.EDocumentConnector.Avalara."Connection Setup" = r;
tabledata Microsoft.EServices.EDocumentConnector.Avalara."Connection Setup" = r;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------
namespace Microsoft.EServices.EDocumentConnector.SignUp;

permissionset 6382 SignUpEDocEdit
{
Access = Internal;
Assignable = false;
IncludedPermissionSets = SignUpEDocRead;

Permissions = tabledata SignUpConnectionSetup = IM,
tabledata SignUpConnectionAuth = IM;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------
namespace Microsoft.EServices.EDocumentConnector.SignUp;

permissionset 6380 SignUpEDocObjects
{
Access = Internal;
Assignable = false;

Permissions = table SignUpConnectionSetup = X,
table SignUpConnectionAuth = X,
page SignUpConnectionSetupCard = X,
codeunit SignUpIntegrationImpl = X,
codeunit SignUpProcessing = X,
codeunit SignUpAuth = X,
codeunit SignUpAPIRequests = X,
codeunit SignUpConnection = X,
codeunit SignUpPatchSent = X,
codeunit SignUpGetReadyStatus = X;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------
namespace Microsoft.EServices.EDocumentConnector.SignUp;

permissionset 6381 SignUpEDocRead
{
Access = Internal;
Assignable = false;
IncludedPermissionSets = SignUpEDocObjects;

Permissions = tabledata SignUpConnectionSetup = R,
tabledata SignUpConnectionAuth = R;
}
224 changes: 224 additions & 0 deletions Apps/W1/EDocumentsConnector/app/src/SignUp/APIRequests.Codeunit.al
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
// ------------------------------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
// ------------------------------------------------------------------------------------------------
namespace Microsoft.EServices.EDocumentConnector.SignUp;

using Microsoft.EServices.EDocument;
using Microsoft.Foundation.Company;
using Microsoft.Sales.Customer;
using System.Security.Authentication;
using System.Text;
using System.Utilities;
using System.Xml;

codeunit 6380 SignUpAPIRequests
geschwint marked this conversation as resolved.
Show resolved Hide resolved
{
Access = Internal;

// https://<BASE URL>/api/Peppol
procedure SendFilePostRequest(var TempBlob: Codeunit "Temp Blob"; EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean
var
SignUpConnectionSetup: Record SignUpConnectionSetup;
Payload: Text;
ContentHttpHeaders: HttpHeaders;
HttpContent: HttpContent;
ContentText: Text;
UriTemplateLbl: Label '%1/api/Peppol', Comment = '%1 = Service Url', Locked = true;
geschwint marked this conversation as resolved.
Show resolved Hide resolved
begin
InitRequest(SignUpConnectionSetup, HttpRequestMessage, HttpResponseMessage);
HttpRequestMessage := PrepareRequestMsg("Http Request Type"::POST, StrSubstNo(UriTemplateLbl, SignUpConnectionSetup.ServiceURL));

Payload := XmlToTxt(TempBlob);
if Payload = '' then
exit(false);
Clear(HttpContent);
ContentText := PrepareContentForSend(GetDocumentType(EDocument), SignUpConnectionSetup."Company Id", GetCustomerID(EDocument), GetSenderCountryCode(), Payload, SignUpConnectionSetup."Send Mode");
HttpContent.WriteFrom(ContentText);
HttpContent.GetHeaders(ContentHttpHeaders);
if ContentHttpHeaders.Contains('Content-Type') then
ContentHttpHeaders.Remove('Content-Type');
ContentHttpHeaders.Add('Content-Type', 'application/json');
HttpRequestMessage.Content(HttpContent);

exit(SendRequest(HttpRequestMessage, HttpResponseMessage));
end;

// https://<BASE URL>/api/Peppol/status?peppolInstanceId=
procedure GetSentDocumentStatus(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean
var
SignUpConnectionSetup: Record SignUpConnectionSetup;
UriTemplateLbl: Label '%1/api/Peppol/status?peppolInstanceId=%2', Comment = '%1 = Service Url, %2 = Document ID', Locked = true;
begin
InitRequest(SignUpConnectionSetup, HttpRequestMessage, HttpResponseMessage);
HttpRequestMessage := PrepareRequestMsg("Http Request Type"::GET, StrSubstNo(UriTemplateLbl, SignUpConnectionSetup.ServiceURL, EDocument."Document Id"));
exit(SendRequest(HttpRequestMessage, HttpResponseMessage));
end;

// https://<BASE URL>/api/Peppol/outbox?peppolInstanceId=
procedure PatchADocument(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean
var
SignUpConnectionSetup: Record SignUpConnectionSetup;
UriTemplateLbl: Label '%1/api/Peppol/outbox?peppolInstanceId=%2', Comment = '%1 = Service Url, %2 = Document ID', Locked = true;
begin
InitRequest(SignUpConnectionSetup, HttpRequestMessage, HttpResponseMessage);
HttpRequestMessage := PrepareRequestMsg("Http Request Type"::PATCH, StrSubstNo(UriTemplateLbl, SignUpConnectionSetup.ServiceURL, EDocument."Document Id"));
exit(SendRequest(HttpRequestMessage, HttpResponseMessage));
end;

// https://<BASE URL>/api/Peppol/Inbox?peppolId=
procedure GetReceivedDocumentsRequest(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage; Parameters: Dictionary of [Text, Text]): Boolean
var
SignUpConnectionSetup: Record SignUpConnectionSetup;
UriTemplateLbl: Label '%1/api/Peppol/Inbox?peppolId=%2', Comment = '%1 = Service Url, %2 = Peppol Identifier', Locked = true;
begin
InitRequest(SignUpConnectionSetup, HttpRequestMessage, HttpResponseMessage);
HttpRequestMessage := PrepareRequestMsg("Http Request Type"::GET, StrSubstNo(UriTemplateLbl, SignUpConnectionSetup.ServiceURL, GetSenderReceiverPrefix() + SignUpConnectionSetup."Company Id"));
exit(SendRequest(HttpRequestMessage, HttpResponseMessage));
end;

// https://<BASE URL>/api/Peppol/inbox-document?peppolId=
procedure GetTargetDocumentRequest(DocumentId: Text; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean
var
SignUpConnectionSetup: Record SignUpConnectionSetup;
UriTemplateLbl: Label '%1/api/Peppol/inbox-document?peppolId=%2&peppolInstanceId=%3', Comment = '%1 = Service Url, %2 = Peppol Identifier, %3 = Peppol Gateway Instance', Locked = true;
begin
InitRequest(SignUpConnectionSetup, HttpRequestMessage, HttpResponseMessage);
HttpRequestMessage := PrepareRequestMsg("Http Request Type"::GET, StrSubstNo(UriTemplateLbl, SignUpConnectionSetup.ServiceURL, GetSenderReceiverPrefix() + SignUpConnectionSetup."Company Id", DocumentId));
exit(SendRequest(HttpRequestMessage, HttpResponseMessage));
end;

// https://<BASE URL>/api/Peppol/inbox?peppolInstanceId=
procedure PatchReceivedDocument(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean
var
SignUpConnectionSetup: Record SignUpConnectionSetup;
UriTemplateLbl: Label '%1/api/Peppol/inbox?peppolInstanceId=%2', Comment = '%1 = Service Url, %2 = Peppol Gateway Instance', Locked = true;
begin
InitRequest(SignUpConnectionSetup, HttpRequestMessage, HttpResponseMessage);
HttpRequestMessage := PrepareRequestMsg("Http Request Type"::PATCH, StrSubstNo(UriTemplateLbl, SignUpConnectionSetup.ServiceURL, EDocument."Document Id"));
exit(SendRequest(HttpRequestMessage, HttpResponseMessage));
end;

procedure GetMarketPlaceCredentials(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean
var
SignUpConnectionSetup: Record SignUpConnectionSetup;
SignUpAuth: Codeunit SignUpAuth;
BaseUrlTxt: Label '%1/api/Registration/init?EntraTenantId=%2', Locked = true;
begin
InitRequest(SignUpConnectionSetup, HttpRequestMessage, HttpResponseMessage);
HttpRequestMessage := PrepareRequestMsg("Http Request Type"::POST, StrSubstNo(BaseUrlTxt, SignUpAuth.GetRootUrl(), SignUpAuth.GetBCInstanceIdentifier()));
exit(SendRequest(HttpRequestMessage, HttpResponseMessage, true));
end;

local procedure InitRequest(var SignUpConnectionSetup: Record SignUpConnectionSetup; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage)
begin
Clear(HttpRequestMessage);
Clear(HttpResponseMessage);
if not SignUpConnectionSetup.Get() then
Error(MissingSetupErr);
geschwint marked this conversation as resolved.
Show resolved Hide resolved
end;

local procedure SendRequest(HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean
begin
SendRequest(HttpRequestMessage, HttpResponseMessage, false);
end;

local procedure SendRequest(HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage; RootRequest: Boolean): Boolean
var
SignUpAuth: Codeunit SignUpAuth;
HttpClient: HttpClient;
HttpHeaders: HttpHeaders;
begin
HttpRequestMessage.GetHeaders(HttpHeaders);
if RootRequest then
HttpHeaders.Add('Authorization', SignUpAuth.GetRootBearerAuthText())
else
HttpHeaders.Add('Authorization', SignUpAuth.GetBearerAuthText());
exit(HttpClient.Send(HttpRequestMessage, HttpResponseMessage));
end;

local procedure PrepareRequestMsg(pHttpRequestType: Enum "Http Request Type"; Uri: Text) RequestMessage: HttpRequestMessage
geschwint marked this conversation as resolved.
Show resolved Hide resolved
var
Headers: HttpHeaders;
begin
RequestMessage.Method(Format(pHttpRequestType));
RequestMessage.SetRequestUri(Uri);
RequestMessage.GetHeaders(Headers);
Headers.Add('Accept', '*/*');
end;

local procedure XmlToTxt(var TempBlob: Codeunit "Temp Blob"): Text
var
XMLDOMManagement: Codeunit "XML DOM Management";
InStr: InStream;
Content: Text;
begin
TempBlob.CreateInStream(InStr, TextEncoding::UTF8);
XMLDOMManagement.TryGetXMLAsText(InStr, Content);
exit(Content);
end;

local procedure GetDocumentType(EDocument: Record "E-Document"): Text
begin
if EDocument.Direction = EDocument.Direction::Incoming then
exit('ApplicationResponse');

case EDocument."Document Type" of
"E-Document Type"::"Sales Invoice", "E-Document Type"::"Sales Credit Memo", "E-Document Type"::"Service Invoice", "E-Document Type"::"Service Credit Memo":
exit('Invoice');
"E-Document Type"::"Issued Finance Charge Memo", "E-Document Type"::"Issued Reminder":
exit('PaymentReminder');
end;
geschwint marked this conversation as resolved.
Show resolved Hide resolved
end;

local procedure GetCustomerID(EDocument: Record "E-Document"): Text[50]
var
Customer: Record Customer;
begin
if EDocument.Direction <> EDocument.Direction::Outgoing then
exit('');
geschwint marked this conversation as resolved.
Show resolved Hide resolved

Customer.Get(EDocument."Bill-to/Pay-to No.");
Customer.TestField("Service Participant Id");

Check failure on line 182 in Apps/W1/EDocumentsConnector/app/src/SignUp/APIRequests.Codeunit.al

View workflow job for this annotation

GitHub Actions / Build 1st Party Apps (W1) (Translated) / 1st Party Apps (W1) (Translated)

AL0118 The name '"Service Participant Id"' does not exist in the current context.
exit(Customer."Service Participant Id");

Check failure on line 183 in Apps/W1/EDocumentsConnector/app/src/SignUp/APIRequests.Codeunit.al

View workflow job for this annotation

GitHub Actions / Build 1st Party Apps (W1) (Translated) / 1st Party Apps (W1) (Translated)

AL0132 'Record Customer' does not contain a definition for 'Service Participant Id'
end;

local procedure GetSenderCountryCode(): Text
var
CompanyInformation: Record "Company Information";
begin
CompanyInformation.Get();
CompanyInformation.TestField("Country/Region Code");
exit(CompanyInformation."Country/Region Code");
end;

local procedure PrepareContentForSend(DocumentType: Text; SendingCompanyID: Text; RecieverCompanyID: Text; SenderCountryCode: Text; Payload: Text; SendMode: Enum SignUpSendMode): Text
var
Base64Convert: Codeunit "Base64 Convert";
SendJsonObject: JsonObject;
ContentText: Text;
begin
SendJsonObject.Add('documentType', DocumentType);
SendJsonObject.Add('receiver', GetSenderReceiverPrefix() + RecieverCompanyID);
SendJsonObject.Add('sender', GetSenderReceiverPrefix() + SendingCompanyID);
SendJsonObject.Add('senderCountryCode', SenderCountryCode);
SendJsonObject.Add('documentId', 'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2::Invoice##urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0::2.1');
SendJsonObject.Add('documentIdScheme', 'busdox-docid-qns');
SendJsonObject.Add('processId', 'urn:fdc:peppol.eu:2017:poacc:billing:01:1.0');
SendJsonObject.Add('processIdScheme', 'cenbii-procid-ubl');
SendJsonObject.Add('sendMode', Format(SendMode));
SendJsonObject.Add('document', Base64Convert.ToBase64(Payload));
SendJsonObject.WriteTo(ContentText);
exit(ContentText);
end;

local procedure GetSenderReceiverPrefix(): Text
var
SenderReceiverPrefixLbl: Label 'iso6523-actorid-upis::', Locked = true;
begin
exit(SenderReceiverPrefixLbl);
end;

var
MissingSetupErr: Label 'You must set up service integration in the E-Document service card.';
}
Loading
Loading