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 51 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
51 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
960da63
Merge branch 'microsoft:main' into edocumentconnector
geschwint Oct 23, 2024
ab0e875
Merge branch 'microsoft:main' into edocumentconnector
geschwint Oct 28, 2024
2ebc70d
Refactor Rename
geschwint Oct 28, 2024
7166b24
Refactor Delete Objects
geschwint Oct 28, 2024
fb7b4c8
Refactor New Objects
geschwint Oct 28, 2024
103aaa8
Refactor General Overhaul
geschwint Oct 28, 2024
b7fa7a9
Merge branch 'microsoft:main' into edocumentconnector
geschwint Oct 28, 2024
e599f8b
Merge branch 'edocumentconnector' of https://github.com/geschwint/ALA…
geschwint Oct 28, 2024
9a526ee
Merge branch 'microsoft:main' into edocumentconnector
geschwint Oct 29, 2024
cde490a
Merge branch 'microsoft:main' into edocumentconnector
geschwint Nov 1, 2024
c802756
Merge branch 'microsoft:main' into edocumentconnector
geschwint Nov 5, 2024
89cc82e
Merge branch 'microsoft:main' into edocumentconnector
geschwint Nov 13, 2024
ad78511
Merge branch 'microsoft:main' into edocumentconnector
geschwint Nov 20, 2024
e26eb31
Merge branch 'microsoft:main' into edocumentconnector
geschwint Nov 20, 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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
47 changes: 47 additions & 0 deletions Apps/W1/EDocumentConnectors/SignUp/app/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"id": "b56171bd-9a8e-47ad-a527-99f476d5af83",
"name": "E-Document Connector - SignUp",
"publisher": "Microsoft",
"brief": "E-Document Connector - SignUp",
"description": "E-Document Connector - SignUp",
"version": "26.0.0.0",
"privacyStatement": "https://go.microsoft.com/fwlink/?LinkId=724009",
"EULA": "https://go.microsoft.com/fwlink/?linkid=2009120",
"help": "https://go.microsoft.com/fwlink/?linkid=2204541",
"url": "https://go.microsoft.com/fwlink/?LinkId=724011",
"logo": "ExtensionLogo.png",
"contextSensitiveHelpUrl": "https://go.microsoft.com/fwlink/?linkid=2206603",
"dependencies": [
{
"id": "e1d97edc-c239-46b4-8d84-6368bdf67c8b",
"name": "E-Document Core",
"publisher": "Microsoft",
"version": "26.0.0.0"
},
{
"id": "d852a468-263e-49e5-bfda-f09e33342b89",
"name": "E-Documents Connector with External Endpoints",
"publisher": "Microsoft",
"version": "26.0.0.0"
}
],
"internalsVisibleTo": [],
"screenshots": [],
"platform": "26.0.0.0",
"idRanges": [
{
"from": 6380,
"to": 6389
}
],
"resourceExposurePolicy": {
"allowDebugging": true,
"allowDownloadingSource": true,
"includeSourceInSymbolFile": true
},
"application": "26.0.0.0",
"target": "OnPrem",
"features": [
"TranslationFile"
]
}
225 changes: 225 additions & 0 deletions Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
// ------------------------------------------------------------------------------------------------
// 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 APIRequests
{
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
ConnectionSetup: Record ConnectionSetup;
Payload: Text;
ContentHttpHeaders: HttpHeaders;
HttpContent: HttpContent;
ContentText: Text;
begin
InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage);
HttpRequestMessage := PrepareRequestMsg("Http Request Type"::POST, ConnectionSetup.ServiceURL + '/api/Peppol');

Payload := XmlToTxt(TempBlob);
if Payload = '' then
exit(false);
Clear(HttpContent);
ContentText := PrepareContentForSend(GetDocumentType(EDocument), ConnectionSetup."Company Id", GetCustomerID(EDocument), GetSenderCountryCode(), Payload, ConnectionSetup."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
ConnectionSetup: Record ConnectionSetup;
begin
InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage);
HttpRequestMessage := PrepareRequestMsg("Http Request Type"::GET, ConnectionSetup.ServiceURL + '/api/Peppol/status?peppolInstanceId=' + 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
ConnectionSetup: Record ConnectionSetup;
begin
InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage);
HttpRequestMessage := PrepareRequestMsg("Http Request Type"::PATCH, ConnectionSetup.ServiceURL + '/api/Peppol/outbox?peppolInstanceId=' + 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
ConnectionSetup: Record ConnectionSetup;
begin
InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage);
HttpRequestMessage := PrepareRequestMsg("Http Request Type"::GET, ConnectionSetup.ServiceURL + '/api/Peppol/Inbox?peppolId=' + GetSenderReceiverPrefix() + ConnectionSetup."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
ConnectionSetup: Record ConnectionSetup;
begin
InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage);
HttpRequestMessage := PrepareRequestMsg("Http Request Type"::GET, ConnectionSetup.ServiceURL + '/api/Peppol/inbox-document?peppolId=' + GetSenderReceiverPrefix() + ConnectionSetup."Company Id" + '&peppolInstanceId=' + 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
ConnectionSetup: Record ConnectionSetup;
begin
InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage);
HttpRequestMessage := PrepareRequestMsg("Http Request Type"::PATCH, ConnectionSetup.ServiceURL + '/api/Peppol/inbox?peppolInstanceId=' + EDocument."Document Id");
exit(SendRequest(HttpRequestMessage, HttpResponseMessage));
end;

procedure GetMarketPlaceCredentials(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean
var
ConnectionSetup: Record ConnectionSetup;
Auth: Codeunit Auth;
begin
InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage);
HttpRequestMessage := PrepareRequestMsg("Http Request Type"::POST, Auth.GetRootUrl() + '/api/Registration/init?EntraTenantId=' + Auth.GetBCInstanceIdentifier());
exit(SendRequest(HttpRequestMessage, HttpResponseMessage, true));
end;

local procedure InitRequest(var ConnectionSetup: Record ConnectionSetup; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage)
var
MissingSetupErrorInfo: ErrorInfo;
begin
Clear(HttpRequestMessage);
Clear(HttpResponseMessage);
if not ConnectionSetup.Get() then begin
MissingSetupErrorInfo.Title := MissingSetupErr;
MissingSetupErrorInfo.Message := MissingSetupMessageLbl;
MissingSetupErrorInfo.PageNo := Page::"E-Document Services";
MissingSetupErrorInfo.AddNavigationAction(MissingSetupNavigationActionLbl);
Error(MissingSetupErrorInfo);
end;
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
Auth: Codeunit Auth;
HttpClient: HttpClient;
HttpHeaders: HttpHeaders;
begin
HttpRequestMessage.GetHeaders(HttpHeaders);
if RootRequest then
HttpHeaders.Add('Authorization', Auth.GetRootBearerAuthText())
else
HttpHeaders.Add('Authorization', Auth.GetBearerAuthText());
exit(HttpClient.Send(HttpRequestMessage, HttpResponseMessage));
end;

local procedure PrepareRequestMsg(HttpRequestType: Enum "Http Request Type"; Uri: Text) RequestMessage: HttpRequestMessage
var
Headers: HttpHeaders;
begin
RequestMessage.Method(Format(HttpRequestType));
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
geschwint marked this conversation as resolved.
Show resolved Hide resolved
"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');
else
Error(UnSupportedDocumentTypeLbl, EDocument."Document Type");
end;
end;

local procedure GetCustomerID(EDocument: Record "E-Document"): Text[50]
var
Customer: Record Customer;
begin
Customer.Get(EDocument."Bill-to/Pay-to No.");
Customer.TestField("Service Participant Id");
exit(Customer."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 SendMode): 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
begin
exit(SenderReceiverPrefixLbl);
end;

var
MissingSetupErr: Label 'Connection Setup is missing';
MissingSetupMessageLbl: Label 'You must set up service integration in the e-document service card.';
MissingSetupNavigationActionLbl: Label 'Show E-Document Services';
UnSupportedDocumentTypeLbl: Label 'Document %1 is not supported.', Comment = '%1 = EDocument Type', Locked = true;
SenderReceiverPrefixLbl: Label 'iso6523-actorid-upis::', Locked = true;
}
Loading
Loading