From d70b100f2420a3384c40c426abd23f9c9b5201bb Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Mon, 16 Sep 2024 10:01:01 +0200 Subject: [PATCH 01/63] EDocument Connector SignUp --- .../EDocConnectorEdit.PermissionSet.al | 4 +- .../EDocConnectorObjects.PermissionSet.al | 3 + .../EDocConnectorRead.PermissionSet.al | 4 +- .../app/src/SignUp/APIRequests.Codeunit.al | 224 +++++++ .../app/src/SignUp/Auth.Codeunit.al | 327 ++++++++++ .../app/src/SignUp/Connection.Codeunit.al | 105 ++++ .../app/src/SignUp/ConnectionAuth.Table.al | 57 ++ .../app/src/SignUp/ConnectionSetup.Table.al | 104 ++++ .../src/SignUp/ConnectionSetupCard.Page.al | 202 ++++++ .../app/src/SignUp/ErrorSensitive.Codeunit.al | 54 ++ .../app/src/SignUp/GetReadyStatus.Codeunit.al | 134 ++++ .../app/src/SignUp/Helpers.Codeunit.al | 63 ++ .../src/SignUp/IntegrationEnumExt.EnumExt.al | 16 + .../src/SignUp/IntegrationImpl.Codeunit.al | 59 ++ .../app/src/SignUp/PatchSent.Codeunit.al | 81 +++ .../app/src/SignUp/Processing.Codeunit.al | 573 ++++++++++++++++++ .../app/src/SignUp/SendMode.Enum.al | 19 + 17 files changed, 2027 insertions(+), 2 deletions(-) create mode 100644 Apps/W1/EDocumentsConnector/app/src/SignUp/APIRequests.Codeunit.al create mode 100644 Apps/W1/EDocumentsConnector/app/src/SignUp/Auth.Codeunit.al create mode 100644 Apps/W1/EDocumentsConnector/app/src/SignUp/Connection.Codeunit.al create mode 100644 Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionAuth.Table.al create mode 100644 Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetup.Table.al create mode 100644 Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al create mode 100644 Apps/W1/EDocumentsConnector/app/src/SignUp/ErrorSensitive.Codeunit.al create mode 100644 Apps/W1/EDocumentsConnector/app/src/SignUp/GetReadyStatus.Codeunit.al create mode 100644 Apps/W1/EDocumentsConnector/app/src/SignUp/Helpers.Codeunit.al create mode 100644 Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationEnumExt.EnumExt.al create mode 100644 Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationImpl.Codeunit.al create mode 100644 Apps/W1/EDocumentsConnector/app/src/SignUp/PatchSent.Codeunit.al create mode 100644 Apps/W1/EDocumentsConnector/app/src/SignUp/Processing.Codeunit.al create mode 100644 Apps/W1/EDocumentsConnector/app/src/SignUp/SendMode.Enum.al diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorEdit.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorEdit.PermissionSet.al index 88f0f656e6..b5d9dfe957 100644 --- a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorEdit.PermissionSet.al +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorEdit.PermissionSet.al @@ -11,5 +11,7 @@ permissionset 6361 "EDocConnector - Edit" IncludedPermissionSets = "EDocConnector - Read"; Permissions = tabledata "E-Doc. Ext. Connection Setup" = IM, - tabledata Microsoft.EServices.EDocumentConnector.Avalara."Connection Setup" = imd; + tabledata Microsoft.EServices.EDocumentConnector.Avalara."Connection Setup" = imd + tabledata SignUpConnectionSetup = IM, + tabledata SignUpConnectionAuth = IM; } \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorObjects.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorObjects.PermissionSet.al index f5fb6cb8e0..39a8d6e2b3 100644 --- a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorObjects.PermissionSet.al +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorObjects.PermissionSet.al @@ -10,7 +10,10 @@ permissionset 6363 "EDoc. Connector Objects" Assignable = false; Permissions = table "E-Doc. Ext. Connection Setup" = X, + table SignUpConnectionSetup = X, + table SignUpConnectionAuth = X, page "EDoc Ext Connection Setup Card" = X, + page SignUpConnectionSetupCard = X, codeunit "Pagero API Requests" = X, codeunit "Pagero Auth." = X, codeunit "Pagero Connection" = X, diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al index 07be9b89a6..1edcfb769e 100644 --- a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al @@ -11,5 +11,7 @@ permissionset 6362 "EDocConnector - Read" IncludedPermissionSets = "EDoc. Connector Objects"; Permissions = tabledata "E-Doc. Ext. Connection Setup" = R, - tabledata Microsoft.EServices.EDocumentConnector.Avalara."Connection Setup" = r; + tabledata Microsoft.EServices.EDocumentConnector.Avalara."Connection Setup" = r + tabledata SignUpConnectionSetup = R, + tabledata SignUpConnectionAuth = R; } \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/APIRequests.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/APIRequests.Codeunit.al new file mode 100644 index 0000000000..9081d37ac2 --- /dev/null +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/APIRequests.Codeunit.al @@ -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 6370 SignUpAPIRequests +{ + Access = Internal; + + // https:///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; + 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:///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:///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:///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:///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:///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); + end; + + local procedure SendRequest(HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + begin + SendRequest(HttpRequestMessage, HttpResponseMessage, false); + end; + + local procedure SendRequest(HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage; RootReequest: Boolean): Boolean + var + SignUpAuth: Codeunit SignUpAuth; + HttpClient: HttpClient; + HttpHeaders: HttpHeaders; + begin + HttpRequestMessage.GetHeaders(HttpHeaders); + if RootReequest 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 + 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; + end; + + local procedure GetCustomerID(EDocument: Record "E-Document"): Text[50] + var + Customer: Record Customer; + begin + if EDocument.Direction <> EDocument.Direction::Outgoing then + exit(''); + + 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 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.'; +} \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/Auth.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/Auth.Codeunit.al new file mode 100644 index 0000000000..401818638d --- /dev/null +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/Auth.Codeunit.al @@ -0,0 +1,327 @@ +// ------------------------------------------------------------------------------------------------ +// 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 System.Azure.KeyVault; +using Microsoft.Sales.Customer; +using System.Environment; +using System.Reflection; + +codeunit 6371 SignUpAuth +{ + Access = Internal; + + procedure InitConnectionSetup() + var + lSignUpConnectionSetup: Record SignUpConnectionSetup; + begin + if lSignUpConnectionSetup.Get() then + exit; + lSignUpConnectionSetup."Authentication URL" := AuthURLTxt; + lSignUpConnectionSetup.ServiceURL := ProdServiceAPITxt; + StorageSet(lSignUpConnectionSetup."Client Tenant", ProdTenantIdTxt); + lSignUpConnectionSetup.Insert(); + end; + + procedure GetRootOnboardingUrl(): Text + var + UrlTxt: Label '%1/supm/landingpage?EntraTenantId=%2', Comment = '%1 = Root Market URL, %2 = BC Instance Identifier', Locked = true; + begin + exit(StrSubstNo(UrlTxt, GetRootUrl(), GetBCInstanceIdentifier())); + end; + + [NonDebuggable] + procedure CreateClientCredentials() + var + HttpRequestMessage: HttpRequestMessage; + HttpResponseMessage: HttpResponseMessage; + JText: Text; + ClientId: Text; + ClientSecret: SecretText; + ErrorUnableToCreateClientCredentialsLbl: Label 'Unable to create client credentials.'; + begin + if not GetClientCredentials(HttpRequestMessage, HttpResponseMessage) then + Error(ErrorUnableToCreateClientCredentialsLbl); + if HttpResponseMessage.Content.ReadAs(JText) then begin + ClientId := SignUpHelpers.GetJsonValueFromText(JText, 'clientId'); + ClientSecret := SignUpHelpers.GetJsonValueFromText(JText, 'clientSecret'); + if (ClientId <> '') and (not ClientSecret.IsEmpty()) then + SaveClientCredentials(ClientId, ClientSecret); + end; + end; + + [NonDebuggable] + local procedure GetClientCredentials(var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean + var + SignUpSignUpAPIRequests: Codeunit SignUpAPIRequests; + begin + SignUpSignUpAPIRequests.GetMarketPlaceCredentials(HttpRequest, HttpResponse); + if not HttpResponse.IsSuccessStatusCode then + exit(false); + exit(SignUpHelpers.ParseJsonString(HttpResponse.Content) <> ''); + end; + + procedure GetBearerAuthText(): SecretText; + begin + exit(secretStrSubstNo(BearerTxt, GetAuthBearerToken())); + end; + + procedure GetRootBearerAuthText(): SecretText; + begin + exit(secretStrSubstNo(BearerTxt, GetRootAuthBearerToken())); + end; + + procedure GetAuthBearerToken(): SecretText; + var + SignUpConnectionAuth: Record SignUpConnectionAuth; + HttpError: Text; + begin + SignUpConnectionAuth.GetRecordOnce(); + if SignUpConnectionAuth."Token Timestamp" < CurrentDateTime() + 60 * 1000 then + if not RefreshAccessToken(HttpError) then + Error(HttpError); + + exit(StorageGet(SignUpConnectionAuth."Access Token", DataScope::Company)); + end; + + procedure GetRootAuthBearerToken() ReturnValue: SecretText; + var + ErrorTokenLbl: Label 'Unable to fetch a root token.'; + begin + if not GetRootAccessToken(ReturnValue) then + Error(ErrorTokenLbl); + end; + + [NonDebuggable] + local procedure RefreshAccessToken(var HttpError: Text): Boolean; + var + SignUpConnectionAuth: Record SignUpConnectionAuth; + SecretToken: SecretText; + RefreshToken: SecretText; + begin + SignUpConnectionAuth.GetRecordOnce(); + if not GetClientAccessToken(SecretToken) then begin + HttpError := GetLastErrorText(); + exit(false); + end; + SignUpConnectionAuth."Token Timestamp" := CurrentDateTime(); + SaveTokens(SignUpConnectionAuth, DataScope::Company, SecretToken, RefreshToken); + SignUpConnectionAuth.Modify(); + exit(true); + end; + + [NonDebuggable] + local procedure GetRootAccessToken(var AccessToken: SecretText): Boolean + begin + exit(GetAccessToken(AccessToken, GetRootId(), GetRootSecret(), GetRootTenant())); + end; + + [NonDebuggable] + local procedure GetClientAccessToken(var AccessToken: SecretText): Boolean + begin + SignUpConnectionSetup.GetRecordOnce(); + exit(GetAccessToken( + AccessToken, + StorageGetText(SignUpConnectionSetup."Client ID", DataScope::Module), + StorageGet(SignUpConnectionSetup."Client Secret", DataScope::Module), + StorageGetText(SignUpConnectionSetup."Client Tenant", DataScope::Module))); + end; + + [NonDebuggable] + local procedure GetAccessToken(var AccessToken: SecretText; ClientId: Text; ClientSecret: SecretText; ClientTenant: Text): Boolean + var + TypeHelper: Codeunit "Type Helper"; + HttpClient: HttpClient; + HttpRequestMessage: HttpRequestMessage; + HttpResponseMessage: HttpResponseMessage; + HttpContent: HttpContent; + HttpHeaders: HttpHeaders; + ContentText: SecretText; + ContentTemplateTxt: Label 'grant_type=client_credentials&client_id=%1&client_secret=%2&resource=%3', Locked = true; + JText: Text; + begin + SignUpConnectionSetup.GetRecordOnce(); + SignUpConnectionSetup.TestField("Authentication URL"); + + ContentText := SecretStrSubstNo(ContentTemplateTxt, TypeHelper.UriEscapeDataString(ClientId), ClientSecret, TypeHelper.UriEscapeDataString(ClientId)); + + HttpContent.WriteFrom(ContentText); + + HttpContent.GetHeaders(HttpHeaders); + HttpHeaders.Remove('Content-Type'); + HttpHeaders.Add('Content-Type', 'application/x-www-form-urlencoded'); + + HttpRequestMessage.Method := 'POST'; + HttpRequestMessage.SetRequestUri(StrSubstNo(SignUpConnectionSetup."Authentication URL", ClientTenant)); + HttpRequestMessage.Content(HttpContent); + + Clear(AccessToken); + if HttpClient.Send(HttpRequestMessage, HttpResponseMessage) then + if HttpResponseMessage.IsSuccessStatusCode() then + if HttpResponseMessage.Content.ReadAs(JText) then + AccessToken := SignUpHelpers.GetJsonValueFromText(JText, 'access_token'); + exit(not AccessToken.IsEmpty()); + end; + + local procedure SaveTokens(var SignUpConnectionAuth: Record SignUpConnectionAuth; TokenDataScope: DataScope; AccessToken: SecretText; RefreshToken: SecretText) + begin + StorageSet(SignUpConnectionAuth."Access Token", AccessToken, TokenDataScope); + StorageSet(SignUpConnectionAuth."Refresh Token", RefreshToken, TokenDataScope); + end; + + procedure SaveClientCredentials(ClientId: Text; ClientSecret: SecretText) + begin + Clear(SignUpConnectionSetup); + SignUpConnectionSetup.GetRecordOnce(); + StorageSet(SignUpConnectionSetup."Client ID", ClientId); + StorageSet(SignUpConnectionSetup."Client Secret", ClientSecret); + SignUpConnectionSetup.Modify(); + Clear(SignUpConnectionSetup); + end; + + local procedure StorageGet(TokenKey: Text; TokenDataScope: DataScope) TokenValueAsSecret: SecretText + begin + if not StorageContains(TokenKey, TokenDataScope) then + exit(TokenValueAsSecret); + + IsolatedStorage.Get(TokenKey, TokenDataScope, TokenValueAsSecret); + end; + + [NonDebuggable] + local procedure StorageGetText(TokenKey: Text; TokenDataScope: DataScope) TokenValue: Text + begin + if not StorageContains(TokenKey, TokenDataScope) then + exit(TokenValue); + + IsolatedStorage.Get(TokenKey, TokenDataScope, TokenValue); + end; + + local procedure StorageContains(TokenKey: Text; TokenDataScope: DataScope): Boolean + begin + exit(IsolatedStorage.Contains(TokenKey, TokenDataScope)); + end; + + [NonDebuggable] + procedure StorageSet(var TokenKey: Guid; Value: Text) + begin + ValidateValueKey(TokenKey); + if Value = '' then begin + if IsolatedStorage.Contains(TokenKey, DataScope::Module) then + IsolatedStorage.Delete(TokenKey, DataScope::Module) + end else + IsolatedStorage.Set(TokenKey, Value, DataScope::Module); + end; + + procedure StorageSet(var TokenKey: Guid; Value: SecretText) + begin + ValidateValueKey(TokenKey); + if Value.IsEmpty() then begin + if IsolatedStorage.Contains(TokenKey, DataScope::Module) then + IsolatedStorage.Delete(TokenKey, DataScope::Module) + end else + IsolatedStorage.Set(TokenKey, Value, DataScope::Module); + end; + + procedure StorageSet(var TokenKey: Guid; Value: SecretText; TokenDataScope: DataScope) + begin + ValidateValueKey(TokenKey); + if Value.IsEmpty() then begin + if IsolatedStorage.Contains(TokenKey, TokenDataScope) then + IsolatedStorage.Delete(TokenKey, TokenDataScope) + end else + IsolatedStorage.Set(TokenKey, Value, TokenDataScope); + end; + + local procedure ValidateValueKey(var ValueKey: Guid) + begin + if IsNullGuid(ValueKey) then + ValueKey := CreateGuid(); + end; + + [NonDebuggable] + local procedure GetRootId() ReturnValue: Text + begin + if FetchSecretFromKeyVault('signup-root-id', ReturnValue) then + exit; + if SignUpConnectionSetup.GetRecordOnce() then begin + SignUpConnectionSetup.TestField("Root App ID"); + ReturnValue := StorageGetText(SignUpConnectionSetup."Root App ID", DataScope::Module); + end; + end; + + [NonDebuggable] + local procedure GetRootSecret() ReturnValue: Text + begin + if FetchSecretFromKeyVault('signup-root-secret', ReturnValue) then + exit; + if SignUpConnectionSetup.GetRecordOnce() then begin + SignUpConnectionSetup.TestField("Root Secret"); + ReturnValue := StorageGetText(SignUpConnectionSetup."Root Secret", DataScope::Module); + end; + end; + + [NonDebuggable] + local procedure GetRootTenant() ReturnValue: Text + begin + if FetchSecretFromKeyVault('signup-root-tenant', ReturnValue) then + exit; + if SignUpConnectionSetup.GetRecordOnce() then begin + SignUpConnectionSetup.TestField("Root Tenant"); + ReturnValue := StorageGetText(SignUpConnectionSetup."Root Tenant", DataScope::Module); + end; + end; + + [NonDebuggable] + procedure GetRootUrl() ReturnValue: Text + begin + if FetchSecretFromKeyVault('signup-root-url', ReturnValue) then + exit; + if SignUpConnectionSetup.GetRecordOnce() then begin + SignUpConnectionSetup.TestField("Root Market URL"); + ReturnValue := StorageGetText(SignUpConnectionSetup."Root Market URL", DataScope::Module); + end; + end; + + [NonDebuggable] + local procedure FetchSecretFromKeyVault(KeyName: Text; var KeyValue: Text): Boolean + var + AzureKeyVault: Codeunit "Azure Key Vault"; + EnvironmentInfo: Codeunit "Environment Information"; + begin + if EnvironmentInfo.IsSaaSInfrastructure() then + exit(AzureKeyVault.GetAzureKeyVaultSecret(KeyName, KeyValue)); + end; + + procedure GetBCInstanceIdentifier() Identifier: Text + var + AADTenantID, AADDomainName : Text; + begin + Identifier := '10000000-d8ef-4dfb-b761-ffb073057794'; // Hardcoded fake during testing only + if GetAADTenantInformation(AADTenantID, AADDomainName) then + Identifier := AADTenantID; + end; + + local procedure GetAADTenantInformation(var AADTenantID: Text; var AADDomainName: Text): Boolean + var + SignUpSignUpErrorSensitive: Codeunit SignUpErrorSensitive; + begin + Clear(SignUpSignUpErrorSensitive); + SignUpSignUpErrorSensitive.SetParameter('AADDETAILS'); + Commit(); + if SignUpSignUpErrorSensitive.Run() then begin + AADTenantID := SignUpSignUpErrorSensitive.GetFirstResult(); + AADDomainName := SignUpSignUpErrorSensitive.GetSecondResult(); + exit(true); + end; + end; + + var + SignUpConnectionSetup: Record SignUpConnectionSetup; + SignUpHelpers: Codeunit SignUpHelpers; + BearerTxt: Label 'Bearer %1', Comment = '%1 = text value', Locked = true; + AuthURLTxt: Label 'https://login.microsoftonline.com/%1/oauth2/token', Comment = '%1 Entra Tenant Id', Locked = true; + ProdTenantIdTxt: Label '0d725623-dc26-484f-a090-b09d2003d092', Locked = true; + ProdServiceAPITxt: Label 'https://edoc.exflow.io', Locked = true; +} \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/Connection.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/Connection.Codeunit.al new file mode 100644 index 0000000000..46836c8e1d --- /dev/null +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/Connection.Codeunit.al @@ -0,0 +1,105 @@ +// ------------------------------------------------------------------------------------------------ +// 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.Purchases.Document; +using Microsoft.Purchases.Posting; +using System.Utilities; + +codeunit 6372 SignUpConnection +{ + Access = Internal; + Permissions = tabledata "E-Document" = m; + + procedure HandleSendFilePostRequest(var TempBlob: Codeunit "Temp Blob"; var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage; Retry: Boolean): Boolean + begin + if not SignUpAPIRequests.SendFilePostRequest(TempBlob, EDocument, HttpRequest, HttpResponse) then + if Retry then + SignUpAPIRequests.SendFilePostRequest(TempBlob, EDocument, HttpRequest, HttpResponse); + + exit(CheckIfSuccessfulRequest(EDocument, HttpResponse)); + end; + + procedure CheckDocumentStatus(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage; Retry: Boolean): Boolean + begin + if not SignUpAPIRequests.GetSentDocumentStatus(EDocument, HttpRequest, HttpResponse) then + if Retry then + SignUpAPIRequests.GetSentDocumentStatus(EDocument, HttpRequest, HttpResponse); + + exit(CheckIfSuccessfulRequest(EDocument, HttpResponse)); + end; + + procedure GetReceivedDocuments(var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage; Retry: Boolean): Boolean + var + Parameters: Dictionary of [Text, Text]; + begin + if not SignUpAPIRequests.GetReceivedDocumentsRequest(HttpRequest, HttpResponse, Parameters) then + if Retry then + SignUpAPIRequests.GetReceivedDocumentsRequest(HttpRequest, HttpResponse, Parameters); + + if not HttpResponse.IsSuccessStatusCode then + exit(false); + + exit(SignUpHelpers.ParseJsonString(HttpResponse.Content) <> ''); + end; + + procedure HandleGetTargetDocumentRequest(DocumentId: Text; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage; Retry: Boolean): Boolean + begin + if not SignUpAPIRequests.GetTargetDocumentRequest(DocumentId, HttpRequest, HttpResponse) then + if Retry then + SignUpAPIRequests.GetTargetDocumentRequest(DocumentId, HttpRequest, HttpResponse); + + exit(HttpResponse.IsSuccessStatusCode); + end; + + procedure RemoveDocumentFromReceived(EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage; Retry: Boolean): Boolean + begin + if not SignUpAPIRequests.PatchReceivedDocument(EDocument, HttpRequest, HttpResponse) then + if Retry then + SignUpAPIRequests.PatchReceivedDocument(EDocument, HttpRequest, HttpResponse); + exit(HttpResponse.IsSuccessStatusCode); + end; + + local procedure CheckIfSuccessfulRequest(EDocument: Record "E-Document"; HttpResponse: HttpResponseMessage): Boolean + var + EDocumentErrorHelper: Codeunit "E-Document Error Helper"; + begin + if HttpResponse.IsSuccessStatusCode then + exit(true); + + if HttpResponse.IsBlockedByEnvironment then + EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, EnvironmentBlocksErr) + else + EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, StrSubstNo(UnsuccessfulResponseErr, HttpResponse.HttpStatusCode, HttpResponse.ReasonPhrase)); + end; + + [EventSubscriber(ObjectType::Codeunit, Codeunit::"Purch.-Post", 'OnAfterCheckAndUpdate', '', false, false)] + local procedure CheckOnPosting(var PurchaseHeader: Record "Purchase Header"; CommitIsSuppressed: Boolean; PreviewMode: Boolean) + var + EDocument: Record "E-Document"; + EDocumentService: Record "E-Document Service"; + EDocumentServiceStatus: Record "E-Document Service Status"; + begin + EDocument.SetRange("Document Record ID", PurchaseHeader.RecordId); + if not EDocument.FindFirst() then + exit; + + EDocumentService.SetRange("Service Integration", EDocumentService."Service Integration"::"ExFlow E-Invoicing"); + if EDocumentService.FindFirst() then; + EDocumentServiceStatus.SetRange("E-Document Entry No", EDocument."Entry No"); + EDocumentServiceStatus.SetRange("E-Document Service Code", EDocumentService.Code); + if EDocumentServiceStatus.FindSet() then + repeat + EDocumentServiceStatus.TestField(EDocumentServiceStatus.Status, EDocumentServiceStatus.Status::Approved); + until EDocumentServiceStatus.Next() = 0; + end; + + var + SignUpAPIRequests: Codeunit SignUpAPIRequests; + SignUpHelpers: Codeunit SignUpHelpers; + UnsuccessfulResponseErr: Label 'There was an error sending the request. Response code: %1 and error message: %2', Comment = '%1 - http response status code, e.g. 400, %2- error message'; + EnvironmentBlocksErr: Label 'The request to send documents has been blocked. To resolve the problem, enable outgoing HTTP requests for the E-Document apps on the Extension Management page.'; +} \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionAuth.Table.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionAuth.Table.al new file mode 100644 index 0000000000..b363f7fd2f --- /dev/null +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionAuth.Table.al @@ -0,0 +1,57 @@ +// ------------------------------------------------------------------------------------------------ +// 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; + +table 6370 SignUpConnectionAuth +{ + Access = Internal; + + fields + { + field(1; PK; Code[10]) + { + DataClassification = CustomerContent; + } + field(2; "Access Token"; Guid) + { + Caption = 'Access Token'; + DataClassification = CustomerContent; + } + field(3; "Refresh Token"; Guid) + { + Caption = 'Refresh Token'; + DataClassification = CustomerContent; + } + field(30; "Token Timestamp"; DateTime) + { + Caption = 'Token Timestamp'; + DataClassification = CustomerContent; + } + } + + keys + { + key(Key1; PK) + { + Clustered = true; + } + } + + var + RecordHasBeenRead: Boolean; + + procedure GetRecordOnce(): Boolean + begin + if RecordHasBeenRead then + exit(RecordHasBeenRead); + Clear(Rec); + RecordHasBeenRead := Get(); + if not RecordHasBeenRead then begin + Insert(); + RecordHasBeenRead := Get(); + end; + exit(RecordHasBeenRead); + end; +} \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetup.Table.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetup.Table.al new file mode 100644 index 0000000000..a1e2891bfd --- /dev/null +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetup.Table.al @@ -0,0 +1,104 @@ +// ------------------------------------------------------------------------------------------------ +// 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; + +table 6371 SignUpConnectionSetup +{ + Access = Internal; + DataPerCompany = false; + + fields + { + field(1; PK; Code[10]) + { + DataClassification = CustomerContent; + } + field(4; "Authentication URL"; Text[250]) + { + Caption = 'Authentication URL'; + DataClassification = CustomerContent; + } + field(9; "Company Id"; Text[100]) + { + Caption = 'Company ID'; + DataClassification = CustomerContent; + } + field(10; "Client ID"; Guid) + { + Caption = 'Client ID'; + DataClassification = EndUserIdentifiableInformation; + } + field(11; "Client Secret"; Guid) + { + Caption = 'Client Secret'; + DataClassification = EndUserIdentifiableInformation; + } + field(12; "Send Mode"; Enum SignUpSendMode) + { + Caption = 'Send Mode'; + DataClassification = CustomerContent; + } + field(13; ServiceURL; Text[250]) + { + Caption = 'Service URL'; + DataClassification = CustomerContent; + } + field(20; "Root App ID"; Guid) + { + Caption = 'Root App ID'; + DataClassification = CustomerContent; + } + field(21; "Root Secret"; Guid) + { + Caption = 'Root App Secret'; + DataClassification = CustomerContent; + } + field(22; "Root Tenant"; Guid) + { + Caption = 'Root App Tenant'; + DataClassification = CustomerContent; + } + field(23; "Root Market URL"; Guid) + { + Caption = 'Root Market URL'; + DataClassification = CustomerContent; + } + field(24; "Client Tenant"; Guid) + { + Caption = 'Client App Tenant'; + DataClassification = CustomerContent; + } // "Access Token Due DateTime" + field(30; "Client Token Due DateTime"; DateTime) + { + Caption = 'Client Token Timestamp'; + DataClassification = SystemMetadata; + } + field(31; "Root Token Due DateTime"; DateTime) + { + Caption = 'Root Token Timestamp'; + DataClassification = SystemMetadata; + } + } + + keys + { + key(Key1; PK) + { + Clustered = true; + } + } + + var + RecordHasBeenRead: Boolean; + + procedure GetRecordOnce(): Boolean + begin + if RecordHasBeenRead then + exit(RecordHasBeenRead); + Clear(Rec); + RecordHasBeenRead := Get(); + exit(RecordHasBeenRead); + end; +} \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al new file mode 100644 index 0000000000..cd3d3c5f87 --- /dev/null +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al @@ -0,0 +1,202 @@ +// ------------------------------------------------------------------------------------------------ +// 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 System.Telemetry; + +page 6370 SignUpConnectionSetupCard +{ + PageType = Card; + SourceTable = SignUpConnectionSetup; + ApplicationArea = Basic, Suite; + UsageCategory = None; + Caption = 'E-Document External Connection Setup'; + Extensible = false; + + layout + { + area(Content) + { + group(General) + { + field(ClientID; ClientID) + { + Caption = 'Client ID'; + ToolTip = 'Specifies the client ID token.'; + ApplicationArea = Basic, Suite; + ExtendedDatatype = Masked; + ShowMandatory = true; + + trigger OnValidate() + begin + SignUpAuth.StorageSet(Rec."Client ID", ClientID); + end; + } + field(ClientSecret; ClientSecret) + { + Caption = 'Client Secret'; + ToolTip = 'Specifies the client secret token.'; + ApplicationArea = Basic, Suite; + ExtendedDatatype = Masked; + ShowMandatory = true; + + trigger OnValidate() + begin + SignUpAuth.StorageSet(Rec."Client Secret", ClientSecret); + end; + } + field(ClientTenant; ClientTenant) + { + Caption = 'Client Tenant ID'; + ToolTip = 'Specifies the client tenant id token.'; + ApplicationArea = Basic, Suite; + ExtendedDatatype = Masked; + Visible = false; + + trigger OnValidate() + begin + SignUpAuth.StorageSet(Rec."Client Tenant", ClientTenant); + end; + } + field(RootID; RootID) + { + Caption = 'Root App ID'; + ToolTip = 'Specifies the root app id token.'; + ApplicationArea = Basic, Suite; + ExtendedDatatype = Masked; + Visible = false; + + trigger OnValidate() + begin + SignUpAuth.StorageSet(Rec."Root App ID", RootID); + end; + } + field(RootSecret; RootSecret) + { + Caption = 'Root Secret'; + ToolTip = 'Specifies the root secret token.'; + ApplicationArea = Basic, Suite; + ExtendedDatatype = Masked; + Visible = false; + + trigger OnValidate() + begin + SignUpAuth.StorageSet(Rec."Root Secret", RootSecret); + end; + } + field(RootTenant; RootTenant) + { + Caption = 'Root Tenant ID'; + ToolTip = 'Specifies the root tenant id token.'; + ApplicationArea = Basic, Suite; + ExtendedDatatype = Masked; + Visible = false; + + trigger OnValidate() + begin + SignUpAuth.StorageSet(Rec."Root Tenant", RootTenant); + end; + } + field(RootUrl; RootUrl) + { + Caption = 'Root Url'; + ToolTip = 'Specifies the root url token.'; + ApplicationArea = Basic, Suite; + ExtendedDatatype = Masked; + Visible = false; + + trigger OnValidate() + begin + SignUpAuth.StorageSet(Rec."Root Market URL", RootUrl); + end; + } + field("Authentication URL"; Rec."Authentication URL") + { + ApplicationArea = Basic, Suite; + ToolTip = 'Specifies the URL to connect Microsoft Entra.'; + } + field(ServiceURL; Rec.ServiceURL) + { + ApplicationArea = Basic, Suite; + ToolTip = 'Specifies the service URL.'; + } + field("Company Id"; Rec."Company Id") + { + ApplicationArea = Basic, Suite; + ToolTip = 'Specifies the company ID.'; + ShowMandatory = true; + } + field("Send Mode"; Rec."Send Mode") + { + ApplicationArea = Basic, Suite; + ToolTip = 'Specifies the send mode.'; + ShowMandatory = true; + } + } + } + } + + actions + { + area(processing) + { + action(InitOnboarding01) + { + ApplicationArea = Basic, Suite; + Caption = 'Open Onboarding'; + Image = Setup; + Promoted = true; + PromotedCategory = Process; + PromotedOnly = true; + ToolTip = 'Create client credentials and open the onboarding process in a web browser.'; + + trigger OnAction() + begin + SignUpAuth.CreateClientCredentials(); + CurrPage.Update(); + SetPageVariables(); + Hyperlink(SignUpAuth.GetRootOnboardingUrl()); + FeatureTelemetry.LogUptake('', ExternalServiceTok, Enum::"Feature Uptake Status"::"Set up"); + end; + } + } + } + + trigger OnOpenPage() + begin + SignUpAuth.InitConnectionSetup(); + if Rec.Get() then + ; + SetPageVariables(); + FeatureTelemetry.LogUptake('', ExternalServiceTok, Enum::"Feature Uptake Status"::Discovered); + end; + + local procedure SetPageVariables() + begin + if not IsNullGuid(Rec."Client ID") then + ClientID := '*'; + if not IsNullGuid(Rec."Client Secret") then + ClientSecret := '*'; + if not IsNullGuid(Rec."Client Tenant") then + ClientTenant := '*'; + if not IsNullGuid(Rec."Root App ID") then + RootID := '*'; + if not IsNullGuid(Rec."Root Secret") then + RootSecret := '*'; + if not IsNullGuid(Rec."Root Tenant") then + RootTenant := '*'; + if not IsNullGuid(Rec."Root Market URL") then + RootUrl := '*'; + end; + + var + SignUpAuth: Codeunit SignUpAuth; + FeatureTelemetry: Codeunit "Feature Telemetry"; + [NonDebuggable] + ClientID, ClientSecret, ClientTenant, ClientUrl, RootID, RootSecret, RootTenant, RootUrl : Text; + ExternalServiceTok: Label 'ExternalServiceConnector', Locked = true; + + +} diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/ErrorSensitive.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/ErrorSensitive.Codeunit.al new file mode 100644 index 0000000000..3303e277aa --- /dev/null +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/ErrorSensitive.Codeunit.al @@ -0,0 +1,54 @@ +// ------------------------------------------------------------------------------------------------ +// 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 System.Azure.Identity; + +codeunit 6373 SignUpErrorSensitive +{ + Access = Internal; + Description = 'Create functions to run sensitive code that may fail out of your control but you need to keep the code going'; + + trigger OnRun() + begin + case gParameter of + 'AADDETAILS': + TryGetAADDetails(); + end; + end; + + // + // Error prone function(s) + // + local procedure TryGetAADDetails() + begin + gResult1 := AzureADTenant.GetAadTenantId(); + gResult2 := AzureADTenant.GetAadTenantDomainName(); + end; + + // + // Generic Get/Set methods to communicate before and after try-catch + // + procedure SetParameter(Parameter: Text) + begin + gParameter := Parameter; + end; + + procedure GetFirstResult(): Text; + begin + exit(gResult1); + end; + + procedure GetSecondResult(): Text; + begin + exit(gResult2); + end; + + var + AzureADTenant: Codeunit "Azure AD Tenant"; + gParameter: Text; + gResult1: Text; + gResult2: Text; +} diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/GetReadyStatus.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/GetReadyStatus.Codeunit.al new file mode 100644 index 0000000000..07df54d9c0 --- /dev/null +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/GetReadyStatus.Codeunit.al @@ -0,0 +1,134 @@ +// ------------------------------------------------------------------------------------------------ +// 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 System.Telemetry; +using System.Threading; +using Microsoft.EServices.EDocument; + +codeunit 6374 SignUpGetReadyStatus +{ + TableNo = "Job Queue Entry"; + Access = Internal; + + trigger OnRun() + var + BlankRecordId: RecordId; + begin + if not IsEDocumentStatusSent() then + exit; + + ProcessSentDocuments(); + + if IsEDocumentStatusSent() then + ScheduleEDocumentJob(Codeunit::SignUpGetReadyStatus, BlankRecordId, 300000); + end; + + local procedure ProcessSentDocuments() + var + EDocumentServiceStatus: Record "E-Document Service Status"; + EDocumentService: Record "E-Document Service"; + EDocument: Record "E-Document"; + begin + EDocumentServiceStatus.SetRange(Status, EDocumentServiceStatus.Status::Sent); + if EDocumentServiceStatus.FindSet() then + repeat + FetchEDocumentAndService(EDocument, EDocumentService, EDocumentServiceStatus); + HandleResponse(EDocument, EDocumentService, EDocumentServiceStatus); + FetchEDocumentAndService(EDocument, EDocumentService, EDocumentServiceStatus); + until EDocumentServiceStatus.Next() = 0; + end; + + local procedure FetchEDocumentAndService(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; var EDocumentServiceStatus: Record "E-Document Service Status") + begin + EDocumentService.Get(EDocumentServiceStatus."E-Document Service Code"); + EDocument.Get(EDocumentServiceStatus."E-Document Entry No"); + end; + + local procedure HandleResponse(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; var EDocumentServiceStatus: Record "E-Document Service Status") + var + SignUpProcessing: Codeunit SignUpProcessing; + BlankRecordId: RecordId; + HttpResponse: HttpResponseMessage; + HttpRequest: HttpRequestMessage; + begin + if GetResponse(EDocumentServiceStatus, HttpRequest, HttpResponse) then begin + SignUpProcessing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Approved, 0, HttpRequest, HttpResponse); + ScheduleEDocumentJob(Codeunit::SignUpPatchSent, BlankRecordId, 300000); + end; + + end; + + local procedure GetResponse(var EDocumentServiceStatus: Record "E-Document Service Status"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) ReturnStatus: Boolean + var + EDocument: Record "E-Document"; + SignUpProcessing: Codeunit SignUpProcessing; + TelemetryDimensions: Dictionary of [Text, Text]; + begin + // Commit before create document with error handling + Commit(); + Telemetry.LogMessage('', EDocTelemetryGetResponseScopeStartLbl, Verbosity::Normal, DataClassification::OrganizationIdentifiableInformation, TelemetryScope::All, TelemetryDimensions); + + EDocument.Get(EDocumentServiceStatus."E-Document Entry No"); + + if SignUpProcessing.GetDocumentSentResponse(EDocument, HttpRequest, HttpResponse) then + ReturnStatus := true; + + Telemetry.LogMessage('', EDocTelemetryGetResponseScopeEndLbl, Verbosity::Normal, DataClassification::OrganizationIdentifiableInformation, TelemetryScope::All); + end; + + local procedure IsEDocumentStatusSent(): Boolean + var + EdocumentServiceStatus: Record "E-Document Service Status"; + begin + EdocumentServiceStatus.SetRange(Status, EdocumentServiceStatus.Status::Sent); + exit(not EdocumentServiceStatus.IsEmpty()); + end; + + procedure ScheduleEDocumentJob(CodeunitId: Integer; JobRecordId: RecordId; EarliestStartDateTime: Integer): Guid + var + JobQueueEntry: Record "Job Queue Entry"; + TelemetryDimensions: Dictionary of [Text, Text]; + begin + if IsJobQueueScheduled(CodeunitId) then + exit; + + JobQueueEntry.Init(); + JobQueueEntry."Object Type to Run" := JobQueueEntry."Object Type to Run"::Codeunit; + JobQueueEntry."Object ID to Run" := CodeunitId; + JobQueueEntry."Record ID to Process" := JobRecordId; + JobQueueEntry."User Session ID" := SessionId(); + JobQueueEntry."Job Queue Category Code" := JobQueueCategoryTok; + JobQueueEntry."No. of Attempts to Run" := 0; + JobQueueEntry."Earliest Start Date/Time" := CurrentDateTime + EarliestStartDateTime; + + TelemetryDimensions.Add('Job Queue Id', JobQueueEntry.ID); + TelemetryDimensions.Add('Codeunit Id', Format(CodeunitId)); + TelemetryDimensions.Add('Record Id', Format(JobRecordId)); + TelemetryDimensions.Add('User Session ID', Format(JobQueueEntry."User Session ID")); + TelemetryDimensions.Add('Earliest Start Date/Time', Format(JobQueueEntry."Earliest Start Date/Time")); + Telemetry.LogMessage('', EDocumentJobTelemetryLbl, Verbosity::Normal, DataClassification::OrganizationIdentifiableInformation, TelemetryScope::All, TelemetryDimensions); + Codeunit.Run(Codeunit::"Job Queue - Enqueue", JobQueueEntry); + exit(JobQueueEntry.ID); + end; + + local procedure IsJobQueueScheduled(CodeunitId: Integer): Boolean + var + JobQueueEntry: Record "Job Queue Entry"; + begin + JobQueueEntry.SetRange("Object Type to Run", JobQueueEntry."Object Type to Run"::Codeunit); + JobQueueEntry.SetRange("Object ID to Run", CodeunitId); + JobQueueEntry.SetFilter(Status, '%1|%2', JobQueueEntry.Status::Ready, JobQueueEntry.Status::"In Process"); + if not JobQueueEntry.IsEmpty() then + exit(true); + end; + + var + Telemetry: Codeunit Telemetry; + EDocTelemetryGetResponseScopeStartLbl: Label 'E-Document Get Response: Start Scope', Locked = true; + EDocTelemetryGetResponseScopeEndLbl: Label 'E-Document Get Response: End Scope', Locked = true; + JobQueueCategoryTok: Label 'EDocument', Locked = true, Comment = 'Max Length 10'; + EDocumentJobTelemetryLbl: Label 'E-Document Background Job Scheduled', Locked = true; +} \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/Helpers.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/Helpers.Codeunit.al new file mode 100644 index 0000000000..26f82a5eb9 --- /dev/null +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/Helpers.Codeunit.al @@ -0,0 +1,63 @@ +// ------------------------------------------------------------------------------------------------ +// 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 System.Text; + +codeunit 6375 SignUpHelpers +{ + Access = Internal; + + [NonDebuggable] + procedure ParseJsonString(HttpContentResponse: HttpContent): Text + var + ResponseJObject: JsonObject; + ResponseJson: Text; + Result: Text; + IsJsonResponse: Boolean; + begin + HttpContentResponse.ReadAs(Result); + IsJsonResponse := ResponseJObject.ReadFrom(Result); + if IsJsonResponse then + ResponseJObject.WriteTo(ResponseJson) + else + exit(''); + + if not TryInitJson(ResponseJson) then + exit(''); + + exit(Result); + end; + + [TryFunction] + [NonDebuggable] + local procedure TryInitJson(JsonTxt: Text) + var + JsonManagement: Codeunit "JSON Management"; + begin + JSONManagement.InitializeObject(JsonTxt); + end; + + [NonDebuggable] + procedure GetJsonValueFromText(JsonText: Text; Path: Text) return: Text + var + JObject: JsonObject; + JToken: JsonToken; + begin + if JObject.ReadFrom(JsonText) then + if JObject.SelectToken(Path, JToken) then + return := GetJsonValue(JToken.AsValue()); + end; + + [NonDebuggable] + procedure GetJsonValue(JValue: JsonValue): Text + begin + if JValue.IsNull then + exit(''); + if JValue.IsUndefined then + exit(''); + exit(JValue.AsText()); + end; +} \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationEnumExt.EnumExt.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationEnumExt.EnumExt.al new file mode 100644 index 0000000000..6566ecaf0c --- /dev/null +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationEnumExt.EnumExt.al @@ -0,0 +1,16 @@ +// ------------------------------------------------------------------------------------------------ +// 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; + +enumextension 6370 SignUpIntegrationEnumExt extends "E-Document Integration" +{ + value(6370; "ExFlow E-Invoicing") + { + Caption = 'ExFlow E-Invoicing'; + Implementation = "E-Document Integration" = SignUpIntegrationImpl; + } +} \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationImpl.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationImpl.Codeunit.al new file mode 100644 index 0000000000..2f36aff0f6 --- /dev/null +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationImpl.Codeunit.al @@ -0,0 +1,59 @@ +// ------------------------------------------------------------------------------------------------ +// 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 System.Utilities; +using Microsoft.EServices.EDocument; + +codeunit 6376 SignUpIntegrationImpl implements "E-Document Integration" +{ + Access = Internal; + + procedure Send(var EDocument: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) + var + begin + SignUpProcessing.SendEDocument(EDocument, TempBlob, IsAsync, HttpRequest, HttpResponse); + end; + + procedure SendBatch(var EDocuments: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) + begin + IsAsync := false; + Error('Batch sending is not supported in this version'); + end; + + procedure GetResponse(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean + begin + exit(SignUpProcessing.GetDocumentResponse(EDocument, HttpRequest, HttpResponse)); + end; + + procedure GetApproval(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean + begin + exit(SignUpProcessing.GetDocumentApproval(EDocument, HttpRequest, HttpResponse)); + end; + + procedure Cancel(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean + begin + Error('Cancel is not supported in this version'); + end; + + procedure ReceiveDocument(var TempBlob: Codeunit "Temp Blob"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) + begin + SignUpProcessing.ReceiveDocument(TempBlob, HttpRequest, HttpResponse); + end; + + procedure GetDocumentCountInBatch(var TempBlob: Codeunit "Temp Blob"): Integer + begin + exit(SignUpProcessing.GetDocumentCountInBatch(TempBlob)); + end; + + procedure GetIntegrationSetup(var SetupPage: Integer; var SetupTable: Integer) + begin + SetupPage := Page::SignUpConnectionSetupCard; + SetupTable := Database::SignUpConnectionSetup; + end; + + var + SignUpProcessing: Codeunit SignUpProcessing; +} \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/PatchSent.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/PatchSent.Codeunit.al new file mode 100644 index 0000000000..0dd968b139 --- /dev/null +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/PatchSent.Codeunit.al @@ -0,0 +1,81 @@ +// ------------------------------------------------------------------------------------------------ +// 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 System.Threading; +using Microsoft.EServices.EDocument; + +codeunit 6377 SignUpPatchSent +{ + TableNo = "Job Queue Entry"; + Access = Internal; + + trigger OnRun() + var + SignUpGetReadyStatus: Codeunit SignUpGetReadyStatus; + BlankRecordId: RecordId; + begin + if not IsEDocumentApproved() then + exit; + + ProcessApprovedDocuments(); + + if IsEDocumentApproved() then + SignUpGetReadyStatus.ScheduleEDocumentJob(Codeunit::SignUpPatchSent, BlankRecordId, 300000); + end; + + local procedure ProcessApprovedDocuments() + var + EDocumentServiceStatus: Record "E-Document Service Status"; + EDocumentService: Record "E-Document Service"; + EDocumentIntegrationLog: Record "E-Document Integration Log"; + EDocument: Record "E-Document"; + SignUpAPIRequests: Codeunit SignUpAPIRequests; + SignUpProcessing: Codeunit SignUpProcessing; + HttpResponse: HttpResponseMessage; + HttpRequest: HttpRequestMessage; + begin + EDocumentServiceStatus.SetRange(Status, EDocumentServiceStatus.Status::Approved); + if EDocumentServiceStatus.FindSet() then + repeat + FetchEDocumentAndService(EDocument, EDocumentService, EDocumentServiceStatus); + + EDocumentIntegrationLog.Reset(); + EDocumentIntegrationLog.SetRange("E-Doc. Entry No", EDocument."Entry No"); + EDocumentIntegrationLog.SetRange("Response Status", 204); + EDocumentIntegrationLog.SetRange(Method, 'PATCH'); + if EDocumentIntegrationLog.IsEmpty then + if SignUpAPIRequests.PatchADocument(EDocument, HttpRequest, HttpResponse) then + SignUpProcessing.InsertIntegrationLog(EDocument, EDocumentService, HttpRequest, HttpResponse); + until EDocumentServiceStatus.Next() = 0; + end; + + local procedure FetchEDocumentAndService(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; var EDocumentServiceStatus: Record "E-Document Service Status") + begin + EDocumentService.Get(EDocumentServiceStatus."E-Document Service Code"); + EDocument.Get(EDocumentServiceStatus."E-Document Entry No"); + end; + + local procedure IsEDocumentApproved(): Boolean + var + EdocumentServiceStatus: Record "E-Document Service Status"; + EDocumentIntegrationLog: Record "E-Document Integration Log"; + HasRecords: Boolean; + begin + EdocumentServiceStatus.SetRange(Status, EdocumentServiceStatus.Status::Approved); + if EdocumentServiceStatus.FindSet() then + repeat + EDocumentIntegrationLog.Reset(); + EDocumentIntegrationLog.SetRange("E-Doc. Entry No", EdocumentServiceStatus."E-Document Entry No"); + EDocumentIntegrationLog.SetRange("Response Status", 204); + EDocumentIntegrationLog.SetRange(Method, 'PATCH'); + if EDocumentIntegrationLog.IsEmpty then + HasRecords := true; + + until (EdocumentServiceStatus.Next() = 0) or (HasRecords); + + exit(HasRecords); + end; +} \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/Processing.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/Processing.Codeunit.al new file mode 100644 index 0000000000..b6fe6e0888 --- /dev/null +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/Processing.Codeunit.al @@ -0,0 +1,573 @@ +// ------------------------------------------------------------------------------------------------ +// 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 System.Telemetry; +using System.Text; +using System.Utilities; + +codeunit 6378 SignUpProcessing +{ + Access = Internal; + Permissions = tabledata "E-Document" = m, + tabledata "E-Document Service Status" = m; + + procedure SendEDocument(var EDocument: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) + var + EDocumentServiceStatus: Record "E-Document Service Status"; + EdocumentService: Record "E-Document Service"; + FeatureTelemetry: Codeunit "Feature Telemetry"; + begin + IsAsync := true; + + EDocumentHelper.GetEdocumentService(EDocument, EdocumentService); + EDocumentServiceStatus.Get(EDocument."Entry No", EdocumentService.Code); + + case EDocumentServiceStatus.Status of + EDocumentServiceStatus.Status::Exported: + SendEDocument(EDocument, TempBlob, HttpRequest, HttpResponse); + EDocumentServiceStatus.Status::"Sending Error": + if EDocument."Document Id" = '' then + SendEDocument(EDocument, TempBlob, HttpRequest, HttpResponse); + end; + + FeatureTelemetry.LogUptake('', ExternalServiceTok, Enum::"Feature Uptake Status"::Used); + end; + + procedure GetDocumentResponse(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean + var + begin + if not CheckIfDocumentStatusSuccessful(EDocument, HttpRequest, HttpResponse) then + exit(false); + + exit(true); + end; + + procedure GetDocumentSentResponse(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + EDocumentService: Record "E-Document Service"; + EDocumentServiceStatus: Record "E-Document Service Status"; + SignUpAPIRequests: Codeunit SignUpAPIRequests; + SignUpProcessing: Codeunit SignUpProcessing; + HttpContentResponse: HttpContent; + Status, StatusDescription : Text; + begin + EDocumentHelper.GetEdocumentService(EDocument, EdocumentService); + EDocumentServiceStatus.Get(EDocument."Entry No", EdocumentService.Code); + SignUpAPIRequests.GetSentDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage); + HttpContentResponse := HttpResponseMessage.Content; + if ParseGetADocumentApprovalResponse(HttpContentResponse, Status, StatusDescription) then + case Status of + 'Ready': + exit(true); + 'Failed': + begin + if StatusDescription <> '' then + EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, 'Reason: ' + StatusDescription); + SignUpProcessing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Rejected, 0, HttpRequestMessage, HttpResponseMessage); + exit(false); + end; + end; + exit(false); + end; + + procedure GetDocumentApproval(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + EDocumentService: Record "E-Document Service"; + EDocumentServiceStatus: Record "E-Document Service Status"; + SignUpAPIRequests: Codeunit SignUpAPIRequests; + SignUpGetReadyStatus: Codeunit SignUpGetReadyStatus; + SignUpProcessing: Codeunit SignUpProcessing; + BlankRecordId: RecordId; + HttpContentResponse: HttpContent; + Status, StatusDescription : Text; + begin + EDocumentHelper.GetEdocumentService(EDocument, EdocumentService); + EDocumentServiceStatus.Get(EDocument."Entry No", EdocumentService.Code); + if not (EDocumentServiceStatus.Status in [EDocumentServiceStatus.Status::Sent, EDocumentServiceStatus.Status::"Pending Response"]) then + Error(GetApprovalCheckStatusErr, EDocumentServiceStatus.Status); + + SignUpAPIRequests.GetSentDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage); + HttpContentResponse := HttpResponseMessage.Content; + if ParseGetADocumentApprovalResponse(HttpContentResponse, Status, StatusDescription) then + case Status of + 'Ready': + begin + if EDocumentServiceStatus.Status = EDocumentServiceStatus.Status::Approved then + SignUpGetReadyStatus.ScheduleEDocumentJob(Codeunit::SignUpPatchSent, BlankRecordId, 300000) + else + SignUpGetReadyStatus.ScheduleEDocumentJob(Codeunit::SignUpGetReadyStatus, BlankRecordId, 300000); + exit(true); + end; + 'Failed': + begin + if StatusDescription <> '' then + EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, 'Reason: ' + StatusDescription); + SignUpProcessing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Rejected, 0, HttpRequestMessage, HttpResponseMessage); + exit(false); + end; + end; + exit(false); + end; + + procedure ReceiveDocument(var TempBlob: Codeunit "Temp Blob"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) + var + ContentData: Text; + OutStream: OutStream; + begin + if not SignUpConnection.GetReceivedDocuments(HttpRequest, HttpResponse, true) then + exit; + + HttpResponse.Content.ReadAs(ContentData); + + TempBlob.CreateOutStream(OutStream, TextEncoding::UTF8); + OutStream.WriteText(ContentData); + end; + + procedure GetDocumentCountInBatch(var TempBlob: Codeunit "Temp Blob"): Integer + var + ResponseInstream: InStream; + ResponseTxt: Text; + begin + TempBlob.CreateInStream(ResponseInstream); + ResponseInstream.ReadText(ResponseTxt); + + exit(GetNumberOfReceivedDocuments(ResponseTxt)); + end; + + local procedure SendEDocument(EDocument: Record "E-Document"; TempBlob: Codeunit "Temp Blob"; HttpRequest: HttpRequestMessage; HttpResponse: HttpResponseMessage); + var + HttpContentResponse: HttpContent; + begin + SignUpConnection.HandleSendFilePostRequest(TempBlob, EDocument, HttpRequest, HttpResponse, true); + HttpContentResponse := HttpResponse.Content; + SetEDocumentFileID(EDocument."Entry No", ParseSendFileResponse(HttpContentResponse)); + end; + + local procedure ParseReceivedDocument(InputTxt: Text; Index: Integer; var DocumentId: Text): Boolean + var + JsonManagement: Codeunit "JSON Management"; + JsonManagement2: Codeunit "JSON Management"; + IncrementalTable: Text; + Value: Text; + begin + if not JsonManagement.InitializeFromString(InputTxt) then + exit(false); + + JsonManagement.GetArrayPropertyValueAsStringByName('inbox', Value); + JsonManagement.InitializeCollection(Value); + + if Index = 0 then + Index := 1; + + if Index > JsonManagement.GetCollectionCount() then + exit(false); + + JsonManagement.GetObjectFromCollectionByIndex(IncrementalTable, Index - 1); + JsonManagement2.InitializeObject(IncrementalTable); + JsonManagement2.GetArrayPropertyValueAsStringByName('instanceId', DocumentId); + exit(true); + end; + + local procedure GetNumberOfReceivedDocuments(InputTxt: Text): Integer + var + JsonManagement: Codeunit "JSON Management"; + Value: Text; + begin + InputTxt := LeaveJustNewLine(InputTxt); + + if not JsonManagement.InitializeFromString(InputTxt) then + exit(0); + + JsonManagement.GetArrayPropertyValueAsStringByName('inbox', Value); + JsonManagement.InitializeCollection(Value); + + exit(JsonManagement.GetCollectionCount()); + end; + + local procedure CheckIfDocumentStatusSuccessful(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean + var + ErrorDescription: Text; + begin + if not SignUpConnection.CheckDocumentStatus(EDocument, HttpRequestMessage, HttpResponse, true) then + exit(false); + + if DocumentHasErrorOrProcessing(EDocument, HttpResponse, ErrorDescription) then + exit(false); + + exit(true); + end; + + local procedure ParseSendFileResponse(HttpContentResponse: HttpContent): Text + var + JsonManagement: Codeunit "JSON Management"; + Result: Text; + Value: Text; + begin + Result := SignUpHelpers.ParseJsonString(HttpContentResponse); + if Result = '' then + exit(''); + + if not JsonManagement.InitializeFromString(Result) then + exit(''); + + JsonManagement.GetStringPropertyValueByName('peppolInstanceId', Value); + exit(Value); + end; + + local procedure SetEDocumentFileID(EDocEntryNo: Integer; FileId: Text) + var + EDocument: Record "E-Document"; + begin + if FileId = '' then + exit; + if not EDocument.Get(EDocEntryNo) then + exit; + + EDocument."Document Id" := CopyStr(FileId, 1, MaxStrLen(EDocument."Document Id")); + EDocument.Modify(); + end; + + local procedure DocumentHasErrorOrProcessing(EDocument: Record "E-Document"; HttpResponse: HttpResponseMessage; var ErrorDescription: Text): Boolean + var + EDocumentService: Record "E-Document Service"; + EDocumentServiceStatus: Record "E-Document Service Status"; + JsonManagement: Codeunit "JSON Management"; + SignUpGetReadyStatus: Codeunit SignUpGetReadyStatus; + BlankRecordId: RecordId; + HttpContentResponse: HttpContent; + Result, Value : Text; + begin + HttpContentResponse := HttpResponse.Content; + Result := SignUpHelpers.ParseJsonString(HttpContentResponse); + if Result = '' then + exit(true); + + if not JsonManagement.InitializeFromString(Result) then + exit(true); + + JsonManagement.GetArrayPropertyValueAsStringByName('status', Value); + + if Value in ['Sent'] then begin + SignUpGetReadyStatus.ScheduleEDocumentJob(Codeunit::SignUpGetReadyStatus, BlankRecordId, 120000); + exit(false); + end; + + if Value in ['Ready'] then begin + EDocumentHelper.GetEdocumentService(EDocument, EDocumentService); + EDocumentServiceStatus.Get(EDocument."Entry No", EdocumentService.Code); + if EDocumentServiceStatus.Status = EDocumentServiceStatus.Status::Approved then + SignUpGetReadyStatus.ScheduleEDocumentJob(Codeunit::SignUpPatchSent, BlankRecordId, 180000) + else + SignUpGetReadyStatus.ScheduleEDocumentJob(Codeunit::SignUpGetReadyStatus, BlankRecordId, 120000); + exit(false); + end; + + if Value = 'Failed' then begin + JsonManagement.GetArrayPropertyValueAsStringByName('description', ErrorDescription); + exit(false); + end; + + JsonManagement.GetArrayPropertyValueAsStringByName('description', ErrorDescription); + exit(true); + end; + + procedure ParseGetADocumentApprovalResponse(HttpContentResponse: HttpContent; var Status: Text; var StatusDescription: Text): Boolean + var + JsonManagement: Codeunit "JSON Management"; + Result: Text; + begin + Result := SignUpHelpers.ParseJsonString(HttpContentResponse); + if Result = '' then + exit(false); + + if not JsonManagement.InitializeFromString(Result) then + exit(false); + + JsonManagement.GetArrayPropertyValueAsStringByName('status', Status); + + if Status in ['Ready', 'Sent'] then + exit(true); + + if Status = 'Failed' then begin + JsonManagement.GetArrayPropertyValueAsStringByName('description', StatusDescription); + exit(true); + end; + + exit(false); + end; + + [EventSubscriber(ObjectType::Codeunit, Codeunit::"E-Doc. Integration Management", 'OnGetEDocumentApprovalReturnsFalse', '', false, false)] + local procedure OnGetEDocumentApprovalReturnsFalse(EDocuments: Record "E-Document"; EDocumentService: Record "E-Document Service"; HttpRequest: HttpRequestMessage; HttpResponse: HttpResponseMessage; var IsHandled: Boolean) + var + HttpContentResponse: HttpContent; + Status, StatusDescription : Text; + begin + HttpContentResponse := HttpResponse.Content; + if not ParseGetADocumentApprovalResponse(HttpContentResponse, Status, StatusDescription) then + IsHandled := true; + end; + + [EventSubscriber(ObjectType::Codeunit, Codeunit::"E-Doc. Import", 'OnAfterInsertImportedEdocument', '', false, false)] + local procedure OnAfterInsertEdocument(var EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; var TempBlob: Codeunit "Temp Blob"; EDocCount: Integer; HttpRequest: HttpRequestMessage; HttpResponse: HttpResponseMessage) + var + LocalHttpRequest: HttpRequestMessage; + LocalHttpResponse: HttpResponseMessage; + DocumentOutStream: OutStream; + ContentData, DocumentId : Text; + begin + + if EDocumentService."Service Integration" <> EDocumentService."Service Integration"::"ExFlow E-Invoicing" then + exit; + + HttpResponse.Content.ReadAs(ContentData); + + ContentData := LeaveJustNewLine(ContentData); + + if not ParseReceivedDocument(ContentData, EDocument."Index In Batch", DocumentId) then begin + EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, DocumentIdNotFoundErr); + exit; + end; + + SignUpConnection.HandleGetTargetDocumentRequest(DocumentId, LocalHttpRequest, LocalHttpResponse, false); + EDocumentLogHelper.InsertIntegrationLog(EDocument, EDocumentService, LocalHttpRequest, LocalHttpResponse); + + LocalHttpResponse.Content.ReadAs(ContentData); + + if not ParseContentData(ContentData) then + ContentData := ''; + + if ContentData = '' then + EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, StrSubstNo(CouldNotRetrieveDocumentErr, DocumentId)); + + Clear(TempBlob); + TempBlob.CreateOutStream(DocumentOutStream, TextEncoding::UTF8); + DocumentOutStream.WriteText(ContentData); + EDocument."Document Id" := CopyStr(DocumentId, 1, MaxStrLen(EDocument."Document Id")); + EDocumentLogHelper.InsertLog(EDocument, EDocumentService, TempBlob, "E-Document Service Status"::Imported); + SignUpConnection.RemoveDocumentFromReceived(EDocument, LocalHttpRequest, LocalHttpResponse, true); + EDocumentLogHelper.InsertIntegrationLog(EDocument, EDocumentService, LocalHttpRequest, LocalHttpResponse); + end; + + + internal procedure InsertIntegrationLog(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; HttpRequest: HttpRequestMessage; HttpResponse: HttpResponseMessage) + var + EDocumentIntegrationLog: Record "E-Document Integration Log"; + EDocumentIntegrationLogRecRef: RecordRef; + RequestTxt: Text; + begin + if EDocumentService."Service Integration" = EDocumentService."Service Integration"::"No Integration" then + exit; + + EDocumentIntegrationLog.Validate("E-Doc. Entry No", EDocument."Entry No"); + EDocumentIntegrationLog.Validate("Service Code", EDocumentService.Code); + EDocumentIntegrationLog.Validate("Response Status", HttpResponse.HttpStatusCode()); + EDocumentIntegrationLog.Validate(URL, HttpRequest.GetRequestUri()); + EDocumentIntegrationLog.Validate(Method, HttpRequest.Method()); + EDocumentIntegrationLog.Insert(); + + EDocumentIntegrationLogRecRef.GetTable(EDocumentIntegrationLog); + + if HttpRequest.Content.ReadAs(RequestTxt) then begin + InsertIntegrationBlob(EDocumentIntegrationLogRecRef, RequestTxt, EDocumentIntegrationLog.FieldNo(EDocumentIntegrationLog."Request Blob")); + EDocumentIntegrationLogRecRef.Modify(); + end; + + if HttpResponse.Content.ReadAs(RequestTxt) then begin + InsertIntegrationBlob(EDocumentIntegrationLogRecRef, RequestTxt, EDocumentIntegrationLog.FieldNo(EDocumentIntegrationLog."Response Blob")); + EDocumentIntegrationLogRecRef.Modify(); + end; + end; + + + internal procedure InsertLog(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; EDocDataStorageEntryNo: Integer; EDocumentServiceStatus: Enum "E-Document Service Status"): Integer + var + EDocumentLog: Record "E-Document Log"; + begin + if EDocumentService.Code <> '' then + UpdateServiceStatus(EDocument, EDocumentService, EDocumentServiceStatus); + + EDocumentLog.Validate("Document Type", EDocument."Document Type"); + EDocumentLog.Validate("Document No.", EDocument."Document No."); + EDocumentLog.Validate("E-Doc. Entry No", EDocument."Entry No"); + EDocumentLog.Validate(Status, EDocumentServiceStatus); + EDocumentLog.Validate("Service Integration", EDocumentService."Service Integration"); + EDocumentLog.Validate("Service Code", EDocumentService.Code); + EDocumentLog.Validate("Document Format", EDocumentService."Document Format"); + EDocumentLog.Validate("E-Doc. Data Storage Entry No.", EDocDataStorageEntryNo); + + EDocumentLog.Insert(); + exit(EDocumentLog."Entry No."); + end; + + internal procedure UpdateServiceStatus(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; EDocumentStatus: Enum "E-Document Service Status") + var + EDocumentServiceStatus: Record "E-Document Service Status"; + Exists: Boolean; + begin + EDocument.Get(EDocument."Entry No"); + Exists := EDocumentServiceStatus.Get(EDocument."Entry No", EDocumentService.Code); + EDocumentServiceStatus.Validate(Status, EDocumentStatus); + if Exists then + EDocumentServiceStatus.Modify() + else begin + EDocumentServiceStatus.Validate("E-Document Entry No", EDocument."Entry No"); + EDocumentServiceStatus.Validate("E-Document Service Code", EDocumentService.Code); + EDocumentServiceStatus.Validate(Status, EDocumentStatus); + EDocumentServiceStatus.Insert(); + end; + + UpdateEDocumentStatus(EDocument); + end; + + local procedure UpdateEDocumentStatus(var EDocument: Record "E-Document") + var + IsHandled: Boolean; + begin + if IsHandled then + exit; + + if EDocumentHasErrors(EDocument) then + exit; + + SetDocumentStatus(EDocument); + end; + + local procedure EDocumentHasErrors(var EDocument: Record "E-Document"): Boolean + var + EDocumentServiceStatus: Record "E-Document Service Status"; + begin + EDocumentServiceStatus.SetRange("E-Document Entry No", EDocument."Entry No"); + EDocumentServiceStatus.SetFilter(Status, '%1|%2|%3|%4|%5', + EDocumentServiceStatus.Status::"Sending Error", + EDocumentServiceStatus.Status::"Export Error", + EDocumentServiceStatus.Status::"Cancel Error", + EDocumentServiceStatus.Status::"Imported Document Processing Error", + EDocumentServiceStatus.Status::Rejected); + + if EDocumentServiceStatus.IsEmpty() then + exit(false); + + EDocument.Validate(Status, EDocument.Status::Error); + EDocument.Modify(); + exit(true); + end; + + local procedure InsertIntegrationBlob(var EDocumentIntegrationLogRecRef: RecordRef; Data: Text; FieldNo: Integer) + var + TempBlob: Codeunit "Temp Blob"; + OutStreamObj: OutStream; + begin + TempBlob.CreateOutStream(OutStreamObj); + OutStreamObj.WriteText(Data); + + TempBlob.ToRecordRef(EDocumentIntegrationLogRecRef, FieldNo); + end; + + local procedure SetDocumentStatus(var EDocument: Record "E-Document") + var + EDocumentServiceStatus: Record "E-Document Service Status"; + EDocServiceCount: Integer; + begin + EDocumentServiceStatus.SetRange("E-Document Entry No", EDocument."Entry No"); + EDocServiceCount := EDocumentServiceStatus.Count; + + EDocumentServiceStatus.SetFilter(Status, '%1|%2|%3|%4|%5', + EDocumentServiceStatus.Status::Exported, + EDocumentServiceStatus.Status::"Imported Document Created", + EDocumentServiceStatus.Status::"Journal Line Created", + EDocumentServiceStatus.Status::Approved, + EDocumentServiceStatus.Status::Canceled); + if EDocumentServiceStatus.Count = EDocServiceCount then + EDocument.Status := EDocument.Status::Processed + else + EDocument.Status := EDocument.Status::"In Progress"; + + EDocument.Modify(); + end; + + internal procedure InsertLogWithIntegration(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; EDocumentServiceStatus: Enum "E-Document Service Status"; EDocDataStorageEntryNo: Integer; + HttpRequest: HttpRequestMessage; + HttpResponse: HttpResponseMessage) + begin + InsertLog(EDocument, EDocumentService, EDocDataStorageEntryNo, EDocumentServiceStatus); + if (HttpRequest.GetRequestUri() <> '') and (HttpResponse.Headers.Keys().Count > 0) then + InsertIntegrationLog(EDocument, EDocumentService, HttpRequest, HttpResponse); + end; + + local procedure LeaveJustNewLine(InputText: Text): Text + var + InputJson: JsonObject; + InputJsonArray: JsonArray; + InputJsonToken: JsonToken; + DocumentJsonToken: JsonToken; + OutputDocumentJsonArray: JsonArray; + OutputDocumentJsonObject: JsonObject; + OutputJsonObject: JsonObject; + OutputText: text; + DocumentList: List of [Text]; + i: Integer; + begin + OutputText := InputText; + InputJson.ReadFrom(InputText); + if InputJson.Contains('inbox') then begin + InputJson.Get('inbox', InputJsonToken); + InputJsonArray := InputJsonToken.AsArray(); + foreach InputJsonToken in InputJsonArray do + if InputJsonToken.AsObject().Get('status', DocumentJsonToken) then + if DocumentJsonToken.AsValue().AsText() = 'New' then begin + InputJsonToken.AsObject().Get('instanceId', DocumentJsonToken); + DocumentList.Add(DocumentJsonToken.AsValue().AsText()); + end; + + for i := 1 to DocumentList.Count do begin + Clear(OutputDocumentJsonObject); + OutputDocumentJsonObject.Add('instanceId', DocumentList.Get(i)); + OutputDocumentJsonArray.Add(OutputDocumentJsonObject); + end; + + OutputJsonObject.Add('inbox', OutputDocumentJsonArray); + OutputJsonObject.WriteTo(OutputText) + + end; + exit(OutputText); + end; + + local procedure ParseContentData(var InputText: Text): Boolean + var + JsonManagement: Codeunit "JSON Management"; + Base64Convert: Codeunit "Base64 Convert"; + Value: Text; + ParsePosition: Integer; + begin + if not JsonManagement.InitializeFromString(InputText) then + exit(false); + + JsonManagement.GetArrayPropertyValueAsStringByName('document', Value); + InputText := Base64Convert.FromBase64(Value); + ParsePosition := StrPos(InputText, ''); + if ParsePosition > 0 then begin + InputText := CopyStr(InputText, parsePosition, StrLen(InputText)); + ParsePosition := StrPos(InputText, ''); + InputText := CopyStr(InputText, 1, parsePosition - 1); + end; + + exit(true); + end; + + var + SignUpConnection: Codeunit SignUpConnection; + SignUpHelpers: Codeunit SignUpHelpers; + EDocumentHelper: Codeunit "E-Document Helper"; + EDocumentLogHelper: Codeunit "E-Document Log Helper"; + EDocumentErrorHelper: Codeunit "E-Document Error Helper"; + GetApprovalCheckStatusErr: Label 'You cannot ask for approval with the E-Document in this current status %1. You can request for approval when E-document status is Sent or Pending Response.', Comment = '%1 - Status'; + CouldNotRetrieveDocumentErr: Label 'Could not retrieve document with id: %1 from the service', Comment = '%1 - Document ID'; + DocumentIdNotFoundErr: Label 'Document ID not found in response'; + ExternalServiceTok: Label 'ExternalServiceConnector', Locked = true; +} \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/SendMode.Enum.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/SendMode.Enum.al new file mode 100644 index 0000000000..7ca9775a4c --- /dev/null +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/SendMode.Enum.al @@ -0,0 +1,19 @@ +// ------------------------------------------------------------------------------------------------ +// 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; + +enum 6370 SignUpSendMode +{ + Access = Internal; + + value(0; Production) + { + Caption = 'Production', Locked = true; + } + value(1; Test) + { + Caption = 'Test', Locked = true; + } +} \ No newline at end of file From 758acd2436bacd182e2856710230f6388be40fd6 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Tue, 17 Sep 2024 09:57:32 +0200 Subject: [PATCH 02/63] Change obsolete field reference --- .../EDocumentsConnector/app/src/SignUp/Processing.Codeunit.al | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/Processing.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/Processing.Codeunit.al index b6fe6e0888..2f29f05c04 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/Processing.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/Processing.Codeunit.al @@ -365,7 +365,7 @@ codeunit 6378 SignUpProcessing EDocumentIntegrationLog.Validate("E-Doc. Entry No", EDocument."Entry No"); EDocumentIntegrationLog.Validate("Service Code", EDocumentService.Code); EDocumentIntegrationLog.Validate("Response Status", HttpResponse.HttpStatusCode()); - EDocumentIntegrationLog.Validate(URL, HttpRequest.GetRequestUri()); + EDocumentIntegrationLog.Validate("Request URL", HttpRequest.GetRequestUri()); EDocumentIntegrationLog.Validate(Method, HttpRequest.Method()); EDocumentIntegrationLog.Insert(); From 013d1a7b072b4ca9209b2a9a83ef722a0a4ab9de Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Tue, 17 Sep 2024 10:22:44 +0200 Subject: [PATCH 03/63] Use IsSaaSInfrastructure to make fields visible if not in SaaS Sandbox or production. To be populated manually. --- .../app/src/SignUp/ConnectionSetupCard.Page.al | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al index cd3d3c5f87..bb7e1b5f34 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al @@ -5,6 +5,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using System.Telemetry; +using System.Environment; page 6370 SignUpConnectionSetupCard { @@ -27,6 +28,7 @@ page 6370 SignUpConnectionSetupCard ToolTip = 'Specifies the client ID token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; + Visible = not IsSaaSInfrastructure; ShowMandatory = true; trigger OnValidate() @@ -40,6 +42,7 @@ page 6370 SignUpConnectionSetupCard ToolTip = 'Specifies the client secret token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; + Visible = not IsSaaSInfrastructure; ShowMandatory = true; trigger OnValidate() @@ -53,7 +56,7 @@ page 6370 SignUpConnectionSetupCard ToolTip = 'Specifies the client tenant id token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; - Visible = false; + Visible = not IsSaaSInfrastructure; trigger OnValidate() begin @@ -66,7 +69,7 @@ page 6370 SignUpConnectionSetupCard ToolTip = 'Specifies the root app id token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; - Visible = false; + Visible = not IsSaaSInfrastructure; trigger OnValidate() begin @@ -79,7 +82,7 @@ page 6370 SignUpConnectionSetupCard ToolTip = 'Specifies the root secret token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; - Visible = false; + Visible = not IsSaaSInfrastructure; trigger OnValidate() begin @@ -92,7 +95,7 @@ page 6370 SignUpConnectionSetupCard ToolTip = 'Specifies the root tenant id token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; - Visible = false; + Visible = not IsSaaSInfrastructure; trigger OnValidate() begin @@ -105,7 +108,7 @@ page 6370 SignUpConnectionSetupCard ToolTip = 'Specifies the root url token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; - Visible = false; + Visible = not IsSaaSInfrastructure; trigger OnValidate() begin @@ -165,7 +168,10 @@ page 6370 SignUpConnectionSetupCard } trigger OnOpenPage() + var + EnvironmentInfo: Codeunit "Environment Information"; begin + IsSaaSInfrastructure := EnvironmentInfo.IsSaaSInfrastructure(); SignUpAuth.InitConnectionSetup(); if Rec.Get() then ; @@ -196,6 +202,7 @@ page 6370 SignUpConnectionSetupCard FeatureTelemetry: Codeunit "Feature Telemetry"; [NonDebuggable] ClientID, ClientSecret, ClientTenant, ClientUrl, RootID, RootSecret, RootTenant, RootUrl : Text; + IsSaaSInfrastructure: Boolean; ExternalServiceTok: Label 'ExternalServiceConnector', Locked = true; From 5d3ad670b8e355f11f131577f47f32c60b614ed0 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Tue, 17 Sep 2024 10:32:42 +0200 Subject: [PATCH 04/63] Push forward object id range by 10 due to Avalara addition --- Apps/W1/EDocumentsConnector/app/app.json | 2 +- .../app/src/SignUp/APIRequests.Codeunit.al | 2 +- Apps/W1/EDocumentsConnector/app/src/SignUp/Auth.Codeunit.al | 2 +- .../EDocumentsConnector/app/src/SignUp/Connection.Codeunit.al | 2 +- .../app/src/SignUp/ConnectionAuth.Table.al | 2 +- .../app/src/SignUp/ConnectionSetup.Table.al | 4 ++-- .../app/src/SignUp/ConnectionSetupCard.Page.al | 2 +- .../app/src/SignUp/ErrorSensitive.Codeunit.al | 2 +- .../app/src/SignUp/GetReadyStatus.Codeunit.al | 2 +- .../W1/EDocumentsConnector/app/src/SignUp/Helpers.Codeunit.al | 2 +- .../app/src/SignUp/IntegrationEnumExt.EnumExt.al | 4 ++-- .../app/src/SignUp/IntegrationImpl.Codeunit.al | 2 +- .../EDocumentsConnector/app/src/SignUp/PatchSent.Codeunit.al | 2 +- .../EDocumentsConnector/app/src/SignUp/Processing.Codeunit.al | 2 +- Apps/W1/EDocumentsConnector/app/src/SignUp/SendMode.Enum.al | 2 +- 15 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Apps/W1/EDocumentsConnector/app/app.json b/Apps/W1/EDocumentsConnector/app/app.json index 301840542b..30fafc9597 100644 --- a/Apps/W1/EDocumentsConnector/app/app.json +++ b/Apps/W1/EDocumentsConnector/app/app.json @@ -31,7 +31,7 @@ "idRanges": [ { "from": 6360, - "to": 6379 + "to": 6389 } ], "resourceExposurePolicy": { diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/APIRequests.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/APIRequests.Codeunit.al index 9081d37ac2..1ea08656e5 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/APIRequests.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/APIRequests.Codeunit.al @@ -12,7 +12,7 @@ using System.Text; using System.Utilities; using System.Xml; -codeunit 6370 SignUpAPIRequests +codeunit 6380 SignUpAPIRequests { Access = Internal; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/Auth.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/Auth.Codeunit.al index 401818638d..1a2167f901 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/Auth.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/Auth.Codeunit.al @@ -9,7 +9,7 @@ using Microsoft.Sales.Customer; using System.Environment; using System.Reflection; -codeunit 6371 SignUpAuth +codeunit 6381 SignUpAuth { Access = Internal; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/Connection.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/Connection.Codeunit.al index 46836c8e1d..833cec05a2 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/Connection.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/Connection.Codeunit.al @@ -9,7 +9,7 @@ using Microsoft.Purchases.Document; using Microsoft.Purchases.Posting; using System.Utilities; -codeunit 6372 SignUpConnection +codeunit 6382 SignUpConnection { Access = Internal; Permissions = tabledata "E-Document" = m; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionAuth.Table.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionAuth.Table.al index b363f7fd2f..d735de2598 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionAuth.Table.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionAuth.Table.al @@ -4,7 +4,7 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -table 6370 SignUpConnectionAuth +table 6380 SignUpConnectionAuth { Access = Internal; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetup.Table.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetup.Table.al index a1e2891bfd..69964f235f 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetup.Table.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetup.Table.al @@ -4,7 +4,7 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -table 6371 SignUpConnectionSetup +table 6381 SignUpConnectionSetup { Access = Internal; DataPerCompany = false; @@ -69,7 +69,7 @@ table 6371 SignUpConnectionSetup { Caption = 'Client App Tenant'; DataClassification = CustomerContent; - } // "Access Token Due DateTime" + } field(30; "Client Token Due DateTime"; DateTime) { Caption = 'Client Token Timestamp'; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al index bb7e1b5f34..97fb1a8dbc 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al @@ -7,7 +7,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using System.Telemetry; using System.Environment; -page 6370 SignUpConnectionSetupCard +page 6380 SignUpConnectionSetupCard { PageType = Card; SourceTable = SignUpConnectionSetup; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/ErrorSensitive.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/ErrorSensitive.Codeunit.al index 3303e277aa..a1f3c22ea8 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/ErrorSensitive.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/ErrorSensitive.Codeunit.al @@ -6,7 +6,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using System.Azure.Identity; -codeunit 6373 SignUpErrorSensitive +codeunit 6383 SignUpErrorSensitive { Access = Internal; Description = 'Create functions to run sensitive code that may fail out of your control but you need to keep the code going'; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/GetReadyStatus.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/GetReadyStatus.Codeunit.al index 07df54d9c0..36cf672292 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/GetReadyStatus.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/GetReadyStatus.Codeunit.al @@ -8,7 +8,7 @@ using System.Telemetry; using System.Threading; using Microsoft.EServices.EDocument; -codeunit 6374 SignUpGetReadyStatus +codeunit 6384 SignUpGetReadyStatus { TableNo = "Job Queue Entry"; Access = Internal; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/Helpers.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/Helpers.Codeunit.al index 26f82a5eb9..f97642792e 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/Helpers.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/Helpers.Codeunit.al @@ -6,7 +6,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using System.Text; -codeunit 6375 SignUpHelpers +codeunit 6385 SignUpHelpers { Access = Internal; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationEnumExt.EnumExt.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationEnumExt.EnumExt.al index 6566ecaf0c..63f5c5c08f 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationEnumExt.EnumExt.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationEnumExt.EnumExt.al @@ -6,9 +6,9 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.EServices.EDocument; -enumextension 6370 SignUpIntegrationEnumExt extends "E-Document Integration" +enumextension 6380 SignUpIntegrationEnumExt extends "E-Document Integration" { - value(6370; "ExFlow E-Invoicing") + value(6380; "ExFlow E-Invoicing") { Caption = 'ExFlow E-Invoicing'; Implementation = "E-Document Integration" = SignUpIntegrationImpl; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationImpl.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationImpl.Codeunit.al index 2f36aff0f6..577c4fe44c 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationImpl.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationImpl.Codeunit.al @@ -7,7 +7,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using System.Utilities; using Microsoft.EServices.EDocument; -codeunit 6376 SignUpIntegrationImpl implements "E-Document Integration" +codeunit 6386 SignUpIntegrationImpl implements "E-Document Integration" { Access = Internal; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/PatchSent.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/PatchSent.Codeunit.al index 0dd968b139..66f637d269 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/PatchSent.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/PatchSent.Codeunit.al @@ -7,7 +7,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using System.Threading; using Microsoft.EServices.EDocument; -codeunit 6377 SignUpPatchSent +codeunit 6387 SignUpPatchSent { TableNo = "Job Queue Entry"; Access = Internal; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/Processing.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/Processing.Codeunit.al index 2f29f05c04..52f9e1f2a8 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/Processing.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/Processing.Codeunit.al @@ -9,7 +9,7 @@ using System.Telemetry; using System.Text; using System.Utilities; -codeunit 6378 SignUpProcessing +codeunit 6388 SignUpProcessing { Access = Internal; Permissions = tabledata "E-Document" = m, diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/SendMode.Enum.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/SendMode.Enum.al index 7ca9775a4c..22915cce76 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/SendMode.Enum.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/SendMode.Enum.al @@ -4,7 +4,7 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -enum 6370 SignUpSendMode +enum 6380 SignUpSendMode { Access = Internal; From 74c785bc2b1f9666442e068297487163c514ef22 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Tue, 17 Sep 2024 11:45:49 +0200 Subject: [PATCH 05/63] Menu item Open Onboarding only available in SaaS --- .../app/src/SignUp/ConnectionSetupCard.Page.al | 1 + 1 file changed, 1 insertion(+) diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al index 97fb1a8dbc..cb3c40ba2c 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al @@ -153,6 +153,7 @@ page 6380 SignUpConnectionSetupCard Promoted = true; PromotedCategory = Process; PromotedOnly = true; + Visible = IsSaaSInfrastructure; ToolTip = 'Create client credentials and open the onboarding process in a web browser.'; trigger OnAction() From 1042f9f431d0c07e28b9c85dca13640e45530fc2 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Wed, 18 Sep 2024 15:09:17 +0200 Subject: [PATCH 06/63] Change permission structure. Correct spelling. Adjust broken file ending --- .../EDocConnectorEdit.PermissionSet.al | 8 +++---- .../EDocConnectorObjects.PermissionSet.al | 4 +--- .../EDocConnectorRead.PermissionSet.al | 7 +++--- .../SignUpEDocEdit.PermissionSet.al | 15 +++++++++++++ .../SignUpEDocObjects.PermissionSet.al | 22 +++++++++++++++++++ .../SignUpEDocRead.PermissionSet.al | 15 +++++++++++++ .../app/src/SignUp/APIRequests.Codeunit.al | 4 ++-- .../src/SignUp/ConnectionSetupCard.Page.al | 3 ++- .../app/src/SignUp/ErrorSensitive.Codeunit.al | 2 +- 9 files changed, 65 insertions(+), 15 deletions(-) create mode 100644 Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocEdit.PermissionSet.al create mode 100644 Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocObjects.PermissionSet.al create mode 100644 Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocRead.PermissionSet.al diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorEdit.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorEdit.PermissionSet.al index b5d9dfe957..eb8795c0da 100644 --- a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorEdit.PermissionSet.al +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorEdit.PermissionSet.al @@ -8,10 +8,10 @@ permissionset 6361 "EDocConnector - Edit" { Access = Public; Assignable = true; - IncludedPermissionSets = "EDocConnector - Read"; + IncludedPermissionSets = "EDocConnector - Read", + Microsoft.EServices.EDocumentConnector.SignUp.SignUpEDocEdit; + Permissions = tabledata "E-Doc. Ext. Connection Setup" = IM, - tabledata Microsoft.EServices.EDocumentConnector.Avalara."Connection Setup" = imd - tabledata SignUpConnectionSetup = IM, - tabledata SignUpConnectionAuth = IM; + tabledata Microsoft.EServices.EDocumentConnector.Avalara."Connection Setup" = imd; } \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorObjects.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorObjects.PermissionSet.al index 39a8d6e2b3..61ff8046b5 100644 --- a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorObjects.PermissionSet.al +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorObjects.PermissionSet.al @@ -8,12 +8,10 @@ permissionset 6363 "EDoc. Connector Objects" { Access = Public; Assignable = false; + IncludedPermissionSets = Microsoft.EServices.EDocumentConnector.SignUp.SignUpEDocObjects; Permissions = table "E-Doc. Ext. Connection Setup" = X, - table SignUpConnectionSetup = X, - table SignUpConnectionAuth = X, page "EDoc Ext Connection Setup Card" = X, - page SignUpConnectionSetupCard = X, codeunit "Pagero API Requests" = X, codeunit "Pagero Auth." = X, codeunit "Pagero Connection" = X, diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al index 1edcfb769e..8f5d3e035d 100644 --- a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al @@ -8,10 +8,9 @@ permissionset 6362 "EDocConnector - Read" { Access = Public; Assignable = true; - IncludedPermissionSets = "EDoc. Connector Objects"; + IncludedPermissionSets = "EDoc. Connector Objects", + Microsoft.EServices.EDocumentConnector.SignUp.SignUpEDocRead; Permissions = tabledata "E-Doc. Ext. Connection Setup" = R, - tabledata Microsoft.EServices.EDocumentConnector.Avalara."Connection Setup" = r - tabledata SignUpConnectionSetup = R, - tabledata SignUpConnectionAuth = R; + tabledata Microsoft.EServices.EDocumentConnector.Avalara."Connection Setup" = r; } \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocEdit.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocEdit.PermissionSet.al new file mode 100644 index 0000000000..d6bc51215c --- /dev/null +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocEdit.PermissionSet.al @@ -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; +} \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocObjects.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocObjects.PermissionSet.al new file mode 100644 index 0000000000..35cd908ae2 --- /dev/null +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocObjects.PermissionSet.al @@ -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; +} \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocRead.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocRead.PermissionSet.al new file mode 100644 index 0000000000..85c62e581f --- /dev/null +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocRead.PermissionSet.al @@ -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; +} \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/APIRequests.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/APIRequests.Codeunit.al index 1ea08656e5..f33d29d208 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/APIRequests.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/APIRequests.Codeunit.al @@ -123,14 +123,14 @@ codeunit 6380 SignUpAPIRequests SendRequest(HttpRequestMessage, HttpResponseMessage, false); end; - local procedure SendRequest(HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage; RootReequest: Boolean): Boolean + local procedure SendRequest(HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage; RootRequest: Boolean): Boolean var SignUpAuth: Codeunit SignUpAuth; HttpClient: HttpClient; HttpHeaders: HttpHeaders; begin HttpRequestMessage.GetHeaders(HttpHeaders); - if RootReequest then + if RootRequest then HttpHeaders.Add('Authorization', SignUpAuth.GetRootBearerAuthText()) else HttpHeaders.Add('Authorization', SignUpAuth.GetBearerAuthText()); diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al index cb3c40ba2c..b4499623f4 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al @@ -198,6 +198,7 @@ page 6380 SignUpConnectionSetupCard RootUrl := '*'; end; + var SignUpAuth: Codeunit SignUpAuth; FeatureTelemetry: Codeunit "Feature Telemetry"; @@ -207,4 +208,4 @@ page 6380 SignUpConnectionSetupCard ExternalServiceTok: Label 'ExternalServiceConnector', Locked = true; -} +} \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/ErrorSensitive.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/ErrorSensitive.Codeunit.al index a1f3c22ea8..bc11430480 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/ErrorSensitive.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/ErrorSensitive.Codeunit.al @@ -51,4 +51,4 @@ codeunit 6383 SignUpErrorSensitive gParameter: Text; gResult1: Text; gResult2: Text; -} +} \ No newline at end of file From 69453b64c043643021f42189a956b2d208bb5122 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Thu, 19 Sep 2024 08:13:23 +0200 Subject: [PATCH 07/63] Change to using instead of full namespace path --- .../app/src/Permissions/EDocConnectorEdit.PermissionSet.al | 4 +++- .../app/src/Permissions/EDocConnectorObjects.PermissionSet.al | 4 +++- .../app/src/Permissions/EDocConnectorRead.PermissionSet.al | 4 +++- .../app/src/SignUp/ConnectionSetupCard.Page.al | 1 - 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorEdit.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorEdit.PermissionSet.al index eb8795c0da..0cb8967ece 100644 --- a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorEdit.PermissionSet.al +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorEdit.PermissionSet.al @@ -4,12 +4,14 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector; +using Microsoft.EServices.EDocumentConnector.SignUp; + permissionset 6361 "EDocConnector - Edit" { Access = Public; Assignable = true; IncludedPermissionSets = "EDocConnector - Read", - Microsoft.EServices.EDocumentConnector.SignUp.SignUpEDocEdit; + SignUpEDocEdit; Permissions = tabledata "E-Doc. Ext. Connection Setup" = IM, diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorObjects.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorObjects.PermissionSet.al index 61ff8046b5..3712c9bccb 100644 --- a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorObjects.PermissionSet.al +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorObjects.PermissionSet.al @@ -4,11 +4,13 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector; +using Microsoft.EServices.EDocumentConnector.SignUp; + permissionset 6363 "EDoc. Connector Objects" { Access = Public; Assignable = false; - IncludedPermissionSets = Microsoft.EServices.EDocumentConnector.SignUp.SignUpEDocObjects; + IncludedPermissionSets = SignUpEDocObjects; Permissions = table "E-Doc. Ext. Connection Setup" = X, page "EDoc Ext Connection Setup Card" = X, diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al index 8f5d3e035d..8a233ea4d5 100644 --- a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al @@ -4,12 +4,14 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector; +using Microsoft.EServices.EDocumentConnector.SignUp; + permissionset 6362 "EDocConnector - Read" { Access = Public; Assignable = true; IncludedPermissionSets = "EDoc. Connector Objects", - Microsoft.EServices.EDocumentConnector.SignUp.SignUpEDocRead; + SignUpEDocRead; Permissions = tabledata "E-Doc. Ext. Connection Setup" = R, tabledata Microsoft.EServices.EDocumentConnector.Avalara."Connection Setup" = r; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al index b4499623f4..5227c39da9 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al @@ -198,7 +198,6 @@ page 6380 SignUpConnectionSetupCard RootUrl := '*'; end; - var SignUpAuth: Codeunit SignUpAuth; FeatureTelemetry: Codeunit "Feature Telemetry"; From ebdb7257e10b197fe1331825895521d727d3d9f3 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Fri, 20 Sep 2024 11:02:16 +0200 Subject: [PATCH 08/63] Refactor (MS) - Prefix Removal, Error Raise on Missing Config, Parameter Name, Fully Qualify Perm.Sets --- .../EDocConnectorEdit.PermissionSet.al | 5 +- .../EDocConnectorObjects.PermissionSet.al | 4 +- .../EDocConnectorRead.PermissionSet.al | 4 +- .../SignUpEDocEdit.PermissionSet.al | 8 +- .../SignUpEDocObjects.PermissionSet.al | 22 ++-- .../SignUpEDocRead.PermissionSet.al | 8 +- .../app/src/SignUp/APIRequests.Codeunit.al | 67 +++++----- .../app/src/SignUp/Auth.Codeunit.al | 119 +++++++++--------- .../app/src/SignUp/Connection.Codeunit.al | 28 ++--- .../app/src/SignUp/ConnectionAuth.Table.al | 2 +- .../app/src/SignUp/ConnectionSetup.Table.al | 8 +- .../src/SignUp/ConnectionSetupCard.Page.al | 26 ++-- .../app/src/SignUp/ErrorSensitive.Codeunit.al | 2 +- .../app/src/SignUp/GetReadyStatus.Codeunit.al | 14 +-- .../app/src/SignUp/Helpers.Codeunit.al | 2 +- .../src/SignUp/IntegrationEnumExt.EnumExt.al | 4 +- .../src/SignUp/IntegrationImpl.Codeunit.al | 18 +-- .../app/src/SignUp/PatchSent.Codeunit.al | 14 +-- .../app/src/SignUp/Processing.Codeunit.al | 52 ++++---- .../app/src/SignUp/SendMode.Enum.al | 2 +- 20 files changed, 199 insertions(+), 210 deletions(-) diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorEdit.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorEdit.PermissionSet.al index 0cb8967ece..a55382fbf8 100644 --- a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorEdit.PermissionSet.al +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorEdit.PermissionSet.al @@ -4,15 +4,12 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector; -using Microsoft.EServices.EDocumentConnector.SignUp; - permissionset 6361 "EDocConnector - Edit" { Access = Public; Assignable = true; IncludedPermissionSets = "EDocConnector - Read", - SignUpEDocEdit; - + Microsoft.EServices.EDocumentConnector.SignUp."SignUpEDoc. - Edit"; Permissions = tabledata "E-Doc. Ext. Connection Setup" = IM, tabledata Microsoft.EServices.EDocumentConnector.Avalara."Connection Setup" = imd; diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorObjects.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorObjects.PermissionSet.al index 3712c9bccb..0a1e7a24aa 100644 --- a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorObjects.PermissionSet.al +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorObjects.PermissionSet.al @@ -4,13 +4,11 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector; -using Microsoft.EServices.EDocumentConnector.SignUp; - permissionset 6363 "EDoc. Connector Objects" { Access = Public; Assignable = false; - IncludedPermissionSets = SignUpEDocObjects; + IncludedPermissionSets = Microsoft.EServices.EDocumentConnector.SignUp."SignUpEDoc. - Objects"; Permissions = table "E-Doc. Ext. Connection Setup" = X, page "EDoc Ext Connection Setup Card" = X, diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al index 8a233ea4d5..0086239cfa 100644 --- a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al @@ -4,14 +4,12 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector; -using Microsoft.EServices.EDocumentConnector.SignUp; - permissionset 6362 "EDocConnector - Read" { Access = Public; Assignable = true; IncludedPermissionSets = "EDoc. Connector Objects", - SignUpEDocRead; + Microsoft.EServices.EDocumentConnector.SignUp."SignUpEDoc. - Read"; Permissions = tabledata "E-Doc. Ext. Connection Setup" = R, tabledata Microsoft.EServices.EDocumentConnector.Avalara."Connection Setup" = r; diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocEdit.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocEdit.PermissionSet.al index d6bc51215c..eac95d8021 100644 --- a/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocEdit.PermissionSet.al +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocEdit.PermissionSet.al @@ -4,12 +4,12 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -permissionset 6382 SignUpEDocEdit +permissionset 6382 "SignUpEDoc. - Edit" { Access = Internal; Assignable = false; - IncludedPermissionSets = SignUpEDocRead; + IncludedPermissionSets = "SignUpEDoc. - Read"; - Permissions = tabledata SignUpConnectionSetup = IM, - tabledata SignUpConnectionAuth = IM; + Permissions = tabledata ConnectionSetup = IM, + tabledata ConnectionAuth = IM; } \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocObjects.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocObjects.PermissionSet.al index 35cd908ae2..9dad400f69 100644 --- a/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocObjects.PermissionSet.al +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocObjects.PermissionSet.al @@ -4,19 +4,19 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -permissionset 6380 SignUpEDocObjects +permissionset 6380 "SignUpEDoc. - Objects" { 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; + Permissions = table ConnectionSetup = X, + table ConnectionAuth = X, + page ConnectionSetupCard = X, + codeunit IntegrationImpl = X, + codeunit Processing = X, + codeunit Auth = X, + codeunit APIRequests = X, + codeunit Connection = X, + codeunit PatchSent = X, + codeunit GetReadyStatus = X; } \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocRead.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocRead.PermissionSet.al index 85c62e581f..1bf5a00de2 100644 --- a/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocRead.PermissionSet.al +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocRead.PermissionSet.al @@ -4,12 +4,12 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -permissionset 6381 SignUpEDocRead +permissionset 6381 "SignUpEDoc. - Read" { Access = Internal; Assignable = false; - IncludedPermissionSets = SignUpEDocObjects; + IncludedPermissionSets = "SignUpEDoc. - Objects"; - Permissions = tabledata SignUpConnectionSetup = R, - tabledata SignUpConnectionAuth = R; + Permissions = tabledata ConnectionSetup = R, + tabledata ConnectionAuth = R; } \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/APIRequests.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/APIRequests.Codeunit.al index f33d29d208..7daf0c6b99 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/APIRequests.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/APIRequests.Codeunit.al @@ -12,28 +12,28 @@ using System.Text; using System.Utilities; using System.Xml; -codeunit 6380 SignUpAPIRequests +codeunit 6380 APIRequests { Access = Internal; // https:///api/Peppol procedure SendFilePostRequest(var TempBlob: Codeunit "Temp Blob"; EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - SignUpConnectionSetup: Record SignUpConnectionSetup; + ConnectionSetup: Record ConnectionSetup; Payload: Text; ContentHttpHeaders: HttpHeaders; HttpContent: HttpContent; ContentText: Text; UriTemplateLbl: Label '%1/api/Peppol', Comment = '%1 = Service Url', Locked = true; begin - InitRequest(SignUpConnectionSetup, HttpRequestMessage, HttpResponseMessage); - HttpRequestMessage := PrepareRequestMsg("Http Request Type"::POST, StrSubstNo(UriTemplateLbl, SignUpConnectionSetup.ServiceURL)); + InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); + HttpRequestMessage := PrepareRequestMsg("Http Request Type"::POST, StrSubstNo(UriTemplateLbl, ConnectionSetup.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"); + 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 @@ -47,74 +47,74 @@ codeunit 6380 SignUpAPIRequests // https:///api/Peppol/status?peppolInstanceId= procedure GetSentDocumentStatus(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - SignUpConnectionSetup: Record SignUpConnectionSetup; + ConnectionSetup: Record ConnectionSetup; 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")); + InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); + HttpRequestMessage := PrepareRequestMsg("Http Request Type"::GET, StrSubstNo(UriTemplateLbl, ConnectionSetup.ServiceURL, EDocument."Document Id")); exit(SendRequest(HttpRequestMessage, HttpResponseMessage)); end; // https:///api/Peppol/outbox?peppolInstanceId= procedure PatchADocument(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - SignUpConnectionSetup: Record SignUpConnectionSetup; + ConnectionSetup: Record ConnectionSetup; 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")); + InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); + HttpRequestMessage := PrepareRequestMsg("Http Request Type"::PATCH, StrSubstNo(UriTemplateLbl, ConnectionSetup.ServiceURL, EDocument."Document Id")); exit(SendRequest(HttpRequestMessage, HttpResponseMessage)); end; // https:///api/Peppol/Inbox?peppolId= procedure GetReceivedDocumentsRequest(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage; Parameters: Dictionary of [Text, Text]): Boolean var - SignUpConnectionSetup: Record SignUpConnectionSetup; + ConnectionSetup: Record ConnectionSetup; 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")); + InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); + HttpRequestMessage := PrepareRequestMsg("Http Request Type"::GET, StrSubstNo(UriTemplateLbl, ConnectionSetup.ServiceURL, GetSenderReceiverPrefix() + ConnectionSetup."Company Id")); exit(SendRequest(HttpRequestMessage, HttpResponseMessage)); end; // https:///api/Peppol/inbox-document?peppolId= procedure GetTargetDocumentRequest(DocumentId: Text; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - SignUpConnectionSetup: Record SignUpConnectionSetup; + ConnectionSetup: Record ConnectionSetup; 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)); + InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); + HttpRequestMessage := PrepareRequestMsg("Http Request Type"::GET, StrSubstNo(UriTemplateLbl, ConnectionSetup.ServiceURL, GetSenderReceiverPrefix() + ConnectionSetup."Company Id", DocumentId)); exit(SendRequest(HttpRequestMessage, HttpResponseMessage)); end; // https:///api/Peppol/inbox?peppolInstanceId= procedure PatchReceivedDocument(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - SignUpConnectionSetup: Record SignUpConnectionSetup; + ConnectionSetup: Record ConnectionSetup; 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")); + InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); + HttpRequestMessage := PrepareRequestMsg("Http Request Type"::PATCH, StrSubstNo(UriTemplateLbl, ConnectionSetup.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; + ConnectionSetup: Record ConnectionSetup; + Auth: Codeunit Auth; 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())); + InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); + HttpRequestMessage := PrepareRequestMsg("Http Request Type"::POST, StrSubstNo(BaseUrlTxt, Auth.GetRootUrl(), Auth.GetBCInstanceIdentifier())); exit(SendRequest(HttpRequestMessage, HttpResponseMessage, true)); end; - local procedure InitRequest(var SignUpConnectionSetup: Record SignUpConnectionSetup; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) + local procedure InitRequest(var ConnectionSetup: Record ConnectionSetup; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) begin Clear(HttpRequestMessage); Clear(HttpResponseMessage); - if not SignUpConnectionSetup.Get() then + if not ConnectionSetup.Get() then Error(MissingSetupErr); end; @@ -125,23 +125,23 @@ codeunit 6380 SignUpAPIRequests local procedure SendRequest(HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage; RootRequest: Boolean): Boolean var - SignUpAuth: Codeunit SignUpAuth; + Auth: Codeunit Auth; HttpClient: HttpClient; HttpHeaders: HttpHeaders; begin HttpRequestMessage.GetHeaders(HttpHeaders); if RootRequest then - HttpHeaders.Add('Authorization', SignUpAuth.GetRootBearerAuthText()) + HttpHeaders.Add('Authorization', Auth.GetRootBearerAuthText()) else - HttpHeaders.Add('Authorization', SignUpAuth.GetBearerAuthText()); + HttpHeaders.Add('Authorization', Auth.GetBearerAuthText()); exit(HttpClient.Send(HttpRequestMessage, HttpResponseMessage)); end; - local procedure PrepareRequestMsg(pHttpRequestType: Enum "Http Request Type"; Uri: Text) RequestMessage: HttpRequestMessage + local procedure PrepareRequestMsg(HttpRequestType: Enum "Http Request Type"; Uri: Text) RequestMessage: HttpRequestMessage var Headers: HttpHeaders; begin - RequestMessage.Method(Format(pHttpRequestType)); + RequestMessage.Method(Format(HttpRequestType)); RequestMessage.SetRequestUri(Uri); RequestMessage.GetHeaders(Headers); Headers.Add('Accept', '*/*'); @@ -175,9 +175,6 @@ codeunit 6380 SignUpAPIRequests var Customer: Record Customer; begin - if EDocument.Direction <> EDocument.Direction::Outgoing then - exit(''); - Customer.Get(EDocument."Bill-to/Pay-to No."); Customer.TestField("Service Participant Id"); exit(Customer."Service Participant Id"); @@ -192,7 +189,7 @@ codeunit 6380 SignUpAPIRequests exit(CompanyInformation."Country/Region Code"); end; - local procedure PrepareContentForSend(DocumentType: Text; SendingCompanyID: Text; RecieverCompanyID: Text; SenderCountryCode: Text; Payload: Text; SendMode: Enum SignUpSendMode): Text + local procedure PrepareContentForSend(DocumentType: Text; SendingCompanyID: Text; RecieverCompanyID: Text; SenderCountryCode: Text; Payload: Text; SendMode: Enum SendMode): Text var Base64Convert: Codeunit "Base64 Convert"; SendJsonObject: JsonObject; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/Auth.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/Auth.Codeunit.al index 1a2167f901..43e627b37a 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/Auth.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/Auth.Codeunit.al @@ -5,24 +5,23 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using System.Azure.KeyVault; -using Microsoft.Sales.Customer; using System.Environment; using System.Reflection; -codeunit 6381 SignUpAuth +codeunit 6381 Auth { Access = Internal; procedure InitConnectionSetup() var - lSignUpConnectionSetup: Record SignUpConnectionSetup; + lConnectionSetup: Record ConnectionSetup; begin - if lSignUpConnectionSetup.Get() then + if lConnectionSetup.Get() then exit; - lSignUpConnectionSetup."Authentication URL" := AuthURLTxt; - lSignUpConnectionSetup.ServiceURL := ProdServiceAPITxt; - StorageSet(lSignUpConnectionSetup."Client Tenant", ProdTenantIdTxt); - lSignUpConnectionSetup.Insert(); + lConnectionSetup."Authentication URL" := AuthURLTxt; + lConnectionSetup.ServiceURL := ProdServiceAPITxt; + StorageSet(lConnectionSetup."Client Tenant", ProdTenantIdTxt); + lConnectionSetup.Insert(); end; procedure GetRootOnboardingUrl(): Text @@ -45,8 +44,8 @@ codeunit 6381 SignUpAuth if not GetClientCredentials(HttpRequestMessage, HttpResponseMessage) then Error(ErrorUnableToCreateClientCredentialsLbl); if HttpResponseMessage.Content.ReadAs(JText) then begin - ClientId := SignUpHelpers.GetJsonValueFromText(JText, 'clientId'); - ClientSecret := SignUpHelpers.GetJsonValueFromText(JText, 'clientSecret'); + ClientId := Helpers.GetJsonValueFromText(JText, 'clientId'); + ClientSecret := Helpers.GetJsonValueFromText(JText, 'clientSecret'); if (ClientId <> '') and (not ClientSecret.IsEmpty()) then SaveClientCredentials(ClientId, ClientSecret); end; @@ -55,12 +54,12 @@ codeunit 6381 SignUpAuth [NonDebuggable] local procedure GetClientCredentials(var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean var - SignUpSignUpAPIRequests: Codeunit SignUpAPIRequests; + APIRequests: Codeunit APIRequests; begin - SignUpSignUpAPIRequests.GetMarketPlaceCredentials(HttpRequest, HttpResponse); + APIRequests.GetMarketPlaceCredentials(HttpRequest, HttpResponse); if not HttpResponse.IsSuccessStatusCode then exit(false); - exit(SignUpHelpers.ParseJsonString(HttpResponse.Content) <> ''); + exit(Helpers.ParseJsonString(HttpResponse.Content) <> ''); end; procedure GetBearerAuthText(): SecretText; @@ -75,15 +74,15 @@ codeunit 6381 SignUpAuth procedure GetAuthBearerToken(): SecretText; var - SignUpConnectionAuth: Record SignUpConnectionAuth; + ConnectionAuth: Record ConnectionAuth; HttpError: Text; begin - SignUpConnectionAuth.GetRecordOnce(); - if SignUpConnectionAuth."Token Timestamp" < CurrentDateTime() + 60 * 1000 then + ConnectionAuth.GetRecordOnce(); + if ConnectionAuth."Token Timestamp" < CurrentDateTime() + 60 * 1000 then if not RefreshAccessToken(HttpError) then Error(HttpError); - exit(StorageGet(SignUpConnectionAuth."Access Token", DataScope::Company)); + exit(StorageGet(ConnectionAuth."Access Token", DataScope::Company)); end; procedure GetRootAuthBearerToken() ReturnValue: SecretText; @@ -97,18 +96,18 @@ codeunit 6381 SignUpAuth [NonDebuggable] local procedure RefreshAccessToken(var HttpError: Text): Boolean; var - SignUpConnectionAuth: Record SignUpConnectionAuth; + ConnectionAuth: Record ConnectionAuth; SecretToken: SecretText; RefreshToken: SecretText; begin - SignUpConnectionAuth.GetRecordOnce(); + ConnectionAuth.GetRecordOnce(); if not GetClientAccessToken(SecretToken) then begin HttpError := GetLastErrorText(); exit(false); end; - SignUpConnectionAuth."Token Timestamp" := CurrentDateTime(); - SaveTokens(SignUpConnectionAuth, DataScope::Company, SecretToken, RefreshToken); - SignUpConnectionAuth.Modify(); + ConnectionAuth."Token Timestamp" := CurrentDateTime(); + SaveTokens(ConnectionAuth, DataScope::Company, SecretToken, RefreshToken); + ConnectionAuth.Modify(); exit(true); end; @@ -121,12 +120,12 @@ codeunit 6381 SignUpAuth [NonDebuggable] local procedure GetClientAccessToken(var AccessToken: SecretText): Boolean begin - SignUpConnectionSetup.GetRecordOnce(); + ConnectionSetup.GetRecordOnce(); exit(GetAccessToken( AccessToken, - StorageGetText(SignUpConnectionSetup."Client ID", DataScope::Module), - StorageGet(SignUpConnectionSetup."Client Secret", DataScope::Module), - StorageGetText(SignUpConnectionSetup."Client Tenant", DataScope::Module))); + StorageGetText(ConnectionSetup."Client ID", DataScope::Module), + StorageGet(ConnectionSetup."Client Secret", DataScope::Module), + StorageGetText(ConnectionSetup."Client Tenant", DataScope::Module))); end; [NonDebuggable] @@ -142,8 +141,8 @@ codeunit 6381 SignUpAuth ContentTemplateTxt: Label 'grant_type=client_credentials&client_id=%1&client_secret=%2&resource=%3', Locked = true; JText: Text; begin - SignUpConnectionSetup.GetRecordOnce(); - SignUpConnectionSetup.TestField("Authentication URL"); + ConnectionSetup.GetRecordOnce(); + ConnectionSetup.TestField("Authentication URL"); ContentText := SecretStrSubstNo(ContentTemplateTxt, TypeHelper.UriEscapeDataString(ClientId), ClientSecret, TypeHelper.UriEscapeDataString(ClientId)); @@ -154,31 +153,31 @@ codeunit 6381 SignUpAuth HttpHeaders.Add('Content-Type', 'application/x-www-form-urlencoded'); HttpRequestMessage.Method := 'POST'; - HttpRequestMessage.SetRequestUri(StrSubstNo(SignUpConnectionSetup."Authentication URL", ClientTenant)); + HttpRequestMessage.SetRequestUri(StrSubstNo(ConnectionSetup."Authentication URL", ClientTenant)); HttpRequestMessage.Content(HttpContent); Clear(AccessToken); if HttpClient.Send(HttpRequestMessage, HttpResponseMessage) then if HttpResponseMessage.IsSuccessStatusCode() then if HttpResponseMessage.Content.ReadAs(JText) then - AccessToken := SignUpHelpers.GetJsonValueFromText(JText, 'access_token'); + AccessToken := Helpers.GetJsonValueFromText(JText, 'access_token'); exit(not AccessToken.IsEmpty()); end; - local procedure SaveTokens(var SignUpConnectionAuth: Record SignUpConnectionAuth; TokenDataScope: DataScope; AccessToken: SecretText; RefreshToken: SecretText) + local procedure SaveTokens(var ConnectionAuth: Record ConnectionAuth; TokenDataScope: DataScope; AccessToken: SecretText; RefreshToken: SecretText) begin - StorageSet(SignUpConnectionAuth."Access Token", AccessToken, TokenDataScope); - StorageSet(SignUpConnectionAuth."Refresh Token", RefreshToken, TokenDataScope); + StorageSet(ConnectionAuth."Access Token", AccessToken, TokenDataScope); + StorageSet(ConnectionAuth."Refresh Token", RefreshToken, TokenDataScope); end; procedure SaveClientCredentials(ClientId: Text; ClientSecret: SecretText) begin - Clear(SignUpConnectionSetup); - SignUpConnectionSetup.GetRecordOnce(); - StorageSet(SignUpConnectionSetup."Client ID", ClientId); - StorageSet(SignUpConnectionSetup."Client Secret", ClientSecret); - SignUpConnectionSetup.Modify(); - Clear(SignUpConnectionSetup); + Clear(ConnectionSetup); + ConnectionSetup.GetRecordOnce(); + StorageSet(ConnectionSetup."Client ID", ClientId); + StorageSet(ConnectionSetup."Client Secret", ClientSecret); + ConnectionSetup.Modify(); + Clear(ConnectionSetup); end; local procedure StorageGet(TokenKey: Text; TokenDataScope: DataScope) TokenValueAsSecret: SecretText @@ -243,11 +242,11 @@ codeunit 6381 SignUpAuth [NonDebuggable] local procedure GetRootId() ReturnValue: Text begin - if FetchSecretFromKeyVault('signup-root-id', ReturnValue) then + if FetchSecretFromKeyVault('-root-id', ReturnValue) then exit; - if SignUpConnectionSetup.GetRecordOnce() then begin - SignUpConnectionSetup.TestField("Root App ID"); - ReturnValue := StorageGetText(SignUpConnectionSetup."Root App ID", DataScope::Module); + if ConnectionSetup.GetRecordOnce() then begin + ConnectionSetup.TestField("Root App ID"); + ReturnValue := StorageGetText(ConnectionSetup."Root App ID", DataScope::Module); end; end; @@ -256,9 +255,9 @@ codeunit 6381 SignUpAuth begin if FetchSecretFromKeyVault('signup-root-secret', ReturnValue) then exit; - if SignUpConnectionSetup.GetRecordOnce() then begin - SignUpConnectionSetup.TestField("Root Secret"); - ReturnValue := StorageGetText(SignUpConnectionSetup."Root Secret", DataScope::Module); + if ConnectionSetup.GetRecordOnce() then begin + ConnectionSetup.TestField("Root Secret"); + ReturnValue := StorageGetText(ConnectionSetup."Root Secret", DataScope::Module); end; end; @@ -267,9 +266,9 @@ codeunit 6381 SignUpAuth begin if FetchSecretFromKeyVault('signup-root-tenant', ReturnValue) then exit; - if SignUpConnectionSetup.GetRecordOnce() then begin - SignUpConnectionSetup.TestField("Root Tenant"); - ReturnValue := StorageGetText(SignUpConnectionSetup."Root Tenant", DataScope::Module); + if ConnectionSetup.GetRecordOnce() then begin + ConnectionSetup.TestField("Root Tenant"); + ReturnValue := StorageGetText(ConnectionSetup."Root Tenant", DataScope::Module); end; end; @@ -278,9 +277,9 @@ codeunit 6381 SignUpAuth begin if FetchSecretFromKeyVault('signup-root-url', ReturnValue) then exit; - if SignUpConnectionSetup.GetRecordOnce() then begin - SignUpConnectionSetup.TestField("Root Market URL"); - ReturnValue := StorageGetText(SignUpConnectionSetup."Root Market URL", DataScope::Module); + if ConnectionSetup.GetRecordOnce() then begin + ConnectionSetup.TestField("Root Market URL"); + ReturnValue := StorageGetText(ConnectionSetup."Root Market URL", DataScope::Module); end; end; @@ -305,21 +304,21 @@ codeunit 6381 SignUpAuth local procedure GetAADTenantInformation(var AADTenantID: Text; var AADDomainName: Text): Boolean var - SignUpSignUpErrorSensitive: Codeunit SignUpErrorSensitive; + ErrorSensitive: Codeunit ErrorSensitive; begin - Clear(SignUpSignUpErrorSensitive); - SignUpSignUpErrorSensitive.SetParameter('AADDETAILS'); + Clear(ErrorSensitive); + ErrorSensitive.SetParameter('AADDETAILS'); Commit(); - if SignUpSignUpErrorSensitive.Run() then begin - AADTenantID := SignUpSignUpErrorSensitive.GetFirstResult(); - AADDomainName := SignUpSignUpErrorSensitive.GetSecondResult(); + if ErrorSensitive.Run() then begin + AADTenantID := ErrorSensitive.GetFirstResult(); + AADDomainName := ErrorSensitive.GetSecondResult(); exit(true); end; end; var - SignUpConnectionSetup: Record SignUpConnectionSetup; - SignUpHelpers: Codeunit SignUpHelpers; + ConnectionSetup: Record ConnectionSetup; + Helpers: Codeunit Helpers; BearerTxt: Label 'Bearer %1', Comment = '%1 = text value', Locked = true; AuthURLTxt: Label 'https://login.microsoftonline.com/%1/oauth2/token', Comment = '%1 Entra Tenant Id', Locked = true; ProdTenantIdTxt: Label '0d725623-dc26-484f-a090-b09d2003d092', Locked = true; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/Connection.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/Connection.Codeunit.al index 833cec05a2..34bcd77c6e 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/Connection.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/Connection.Codeunit.al @@ -9,25 +9,25 @@ using Microsoft.Purchases.Document; using Microsoft.Purchases.Posting; using System.Utilities; -codeunit 6382 SignUpConnection +codeunit 6382 Connection { Access = Internal; Permissions = tabledata "E-Document" = m; procedure HandleSendFilePostRequest(var TempBlob: Codeunit "Temp Blob"; var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage; Retry: Boolean): Boolean begin - if not SignUpAPIRequests.SendFilePostRequest(TempBlob, EDocument, HttpRequest, HttpResponse) then + if not APIRequests.SendFilePostRequest(TempBlob, EDocument, HttpRequest, HttpResponse) then if Retry then - SignUpAPIRequests.SendFilePostRequest(TempBlob, EDocument, HttpRequest, HttpResponse); + APIRequests.SendFilePostRequest(TempBlob, EDocument, HttpRequest, HttpResponse); exit(CheckIfSuccessfulRequest(EDocument, HttpResponse)); end; procedure CheckDocumentStatus(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage; Retry: Boolean): Boolean begin - if not SignUpAPIRequests.GetSentDocumentStatus(EDocument, HttpRequest, HttpResponse) then + if not APIRequests.GetSentDocumentStatus(EDocument, HttpRequest, HttpResponse) then if Retry then - SignUpAPIRequests.GetSentDocumentStatus(EDocument, HttpRequest, HttpResponse); + APIRequests.GetSentDocumentStatus(EDocument, HttpRequest, HttpResponse); exit(CheckIfSuccessfulRequest(EDocument, HttpResponse)); end; @@ -36,30 +36,30 @@ codeunit 6382 SignUpConnection var Parameters: Dictionary of [Text, Text]; begin - if not SignUpAPIRequests.GetReceivedDocumentsRequest(HttpRequest, HttpResponse, Parameters) then + if not APIRequests.GetReceivedDocumentsRequest(HttpRequest, HttpResponse, Parameters) then if Retry then - SignUpAPIRequests.GetReceivedDocumentsRequest(HttpRequest, HttpResponse, Parameters); + APIRequests.GetReceivedDocumentsRequest(HttpRequest, HttpResponse, Parameters); if not HttpResponse.IsSuccessStatusCode then exit(false); - exit(SignUpHelpers.ParseJsonString(HttpResponse.Content) <> ''); + exit(Helpers.ParseJsonString(HttpResponse.Content) <> ''); end; procedure HandleGetTargetDocumentRequest(DocumentId: Text; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage; Retry: Boolean): Boolean begin - if not SignUpAPIRequests.GetTargetDocumentRequest(DocumentId, HttpRequest, HttpResponse) then + if not APIRequests.GetTargetDocumentRequest(DocumentId, HttpRequest, HttpResponse) then if Retry then - SignUpAPIRequests.GetTargetDocumentRequest(DocumentId, HttpRequest, HttpResponse); + APIRequests.GetTargetDocumentRequest(DocumentId, HttpRequest, HttpResponse); exit(HttpResponse.IsSuccessStatusCode); end; procedure RemoveDocumentFromReceived(EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage; Retry: Boolean): Boolean begin - if not SignUpAPIRequests.PatchReceivedDocument(EDocument, HttpRequest, HttpResponse) then + if not APIRequests.PatchReceivedDocument(EDocument, HttpRequest, HttpResponse) then if Retry then - SignUpAPIRequests.PatchReceivedDocument(EDocument, HttpRequest, HttpResponse); + APIRequests.PatchReceivedDocument(EDocument, HttpRequest, HttpResponse); exit(HttpResponse.IsSuccessStatusCode); end; @@ -98,8 +98,8 @@ codeunit 6382 SignUpConnection end; var - SignUpAPIRequests: Codeunit SignUpAPIRequests; - SignUpHelpers: Codeunit SignUpHelpers; + APIRequests: Codeunit APIRequests; + Helpers: Codeunit Helpers; UnsuccessfulResponseErr: Label 'There was an error sending the request. Response code: %1 and error message: %2', Comment = '%1 - http response status code, e.g. 400, %2- error message'; EnvironmentBlocksErr: Label 'The request to send documents has been blocked. To resolve the problem, enable outgoing HTTP requests for the E-Document apps on the Extension Management page.'; } \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionAuth.Table.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionAuth.Table.al index d735de2598..e1cc465a0b 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionAuth.Table.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionAuth.Table.al @@ -4,7 +4,7 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -table 6380 SignUpConnectionAuth +table 6380 ConnectionAuth { Access = Internal; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetup.Table.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetup.Table.al index 69964f235f..af59bc6a08 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetup.Table.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetup.Table.al @@ -4,7 +4,7 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -table 6381 SignUpConnectionSetup +table 6381 ConnectionSetup { Access = Internal; DataPerCompany = false; @@ -28,14 +28,14 @@ table 6381 SignUpConnectionSetup field(10; "Client ID"; Guid) { Caption = 'Client ID'; - DataClassification = EndUserIdentifiableInformation; + DataClassification = CustomerContent; } field(11; "Client Secret"; Guid) { Caption = 'Client Secret'; - DataClassification = EndUserIdentifiableInformation; + DataClassification = CustomerContent; } - field(12; "Send Mode"; Enum SignUpSendMode) + field(12; "Send Mode"; Enum SendMode) { Caption = 'Send Mode'; DataClassification = CustomerContent; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al index 5227c39da9..d49482d7ea 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al @@ -7,10 +7,10 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using System.Telemetry; using System.Environment; -page 6380 SignUpConnectionSetupCard +page 6380 ConnectionSetupCard { PageType = Card; - SourceTable = SignUpConnectionSetup; + SourceTable = ConnectionSetup; ApplicationArea = Basic, Suite; UsageCategory = None; Caption = 'E-Document External Connection Setup'; @@ -33,7 +33,7 @@ page 6380 SignUpConnectionSetupCard trigger OnValidate() begin - SignUpAuth.StorageSet(Rec."Client ID", ClientID); + Auth.StorageSet(Rec."Client ID", ClientID); end; } field(ClientSecret; ClientSecret) @@ -47,7 +47,7 @@ page 6380 SignUpConnectionSetupCard trigger OnValidate() begin - SignUpAuth.StorageSet(Rec."Client Secret", ClientSecret); + Auth.StorageSet(Rec."Client Secret", ClientSecret); end; } field(ClientTenant; ClientTenant) @@ -60,7 +60,7 @@ page 6380 SignUpConnectionSetupCard trigger OnValidate() begin - SignUpAuth.StorageSet(Rec."Client Tenant", ClientTenant); + Auth.StorageSet(Rec."Client Tenant", ClientTenant); end; } field(RootID; RootID) @@ -73,7 +73,7 @@ page 6380 SignUpConnectionSetupCard trigger OnValidate() begin - SignUpAuth.StorageSet(Rec."Root App ID", RootID); + Auth.StorageSet(Rec."Root App ID", RootID); end; } field(RootSecret; RootSecret) @@ -86,7 +86,7 @@ page 6380 SignUpConnectionSetupCard trigger OnValidate() begin - SignUpAuth.StorageSet(Rec."Root Secret", RootSecret); + Auth.StorageSet(Rec."Root Secret", RootSecret); end; } field(RootTenant; RootTenant) @@ -99,7 +99,7 @@ page 6380 SignUpConnectionSetupCard trigger OnValidate() begin - SignUpAuth.StorageSet(Rec."Root Tenant", RootTenant); + Auth.StorageSet(Rec."Root Tenant", RootTenant); end; } field(RootUrl; RootUrl) @@ -112,7 +112,7 @@ page 6380 SignUpConnectionSetupCard trigger OnValidate() begin - SignUpAuth.StorageSet(Rec."Root Market URL", RootUrl); + Auth.StorageSet(Rec."Root Market URL", RootUrl); end; } field("Authentication URL"; Rec."Authentication URL") @@ -158,10 +158,10 @@ page 6380 SignUpConnectionSetupCard trigger OnAction() begin - SignUpAuth.CreateClientCredentials(); + Auth.CreateClientCredentials(); CurrPage.Update(); SetPageVariables(); - Hyperlink(SignUpAuth.GetRootOnboardingUrl()); + Hyperlink(Auth.GetRootOnboardingUrl()); FeatureTelemetry.LogUptake('', ExternalServiceTok, Enum::"Feature Uptake Status"::"Set up"); end; } @@ -173,7 +173,7 @@ page 6380 SignUpConnectionSetupCard EnvironmentInfo: Codeunit "Environment Information"; begin IsSaaSInfrastructure := EnvironmentInfo.IsSaaSInfrastructure(); - SignUpAuth.InitConnectionSetup(); + Auth.InitConnectionSetup(); if Rec.Get() then ; SetPageVariables(); @@ -199,7 +199,7 @@ page 6380 SignUpConnectionSetupCard end; var - SignUpAuth: Codeunit SignUpAuth; + Auth: Codeunit Auth; FeatureTelemetry: Codeunit "Feature Telemetry"; [NonDebuggable] ClientID, ClientSecret, ClientTenant, ClientUrl, RootID, RootSecret, RootTenant, RootUrl : Text; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/ErrorSensitive.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/ErrorSensitive.Codeunit.al index bc11430480..25eafdafe4 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/ErrorSensitive.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/ErrorSensitive.Codeunit.al @@ -6,7 +6,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using System.Azure.Identity; -codeunit 6383 SignUpErrorSensitive +codeunit 6383 ErrorSensitive { Access = Internal; Description = 'Create functions to run sensitive code that may fail out of your control but you need to keep the code going'; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/GetReadyStatus.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/GetReadyStatus.Codeunit.al index 36cf672292..92cb4f7474 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/GetReadyStatus.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/GetReadyStatus.Codeunit.al @@ -8,7 +8,7 @@ using System.Telemetry; using System.Threading; using Microsoft.EServices.EDocument; -codeunit 6384 SignUpGetReadyStatus +codeunit 6384 GetReadyStatus { TableNo = "Job Queue Entry"; Access = Internal; @@ -23,7 +23,7 @@ codeunit 6384 SignUpGetReadyStatus ProcessSentDocuments(); if IsEDocumentStatusSent() then - ScheduleEDocumentJob(Codeunit::SignUpGetReadyStatus, BlankRecordId, 300000); + ScheduleEDocumentJob(Codeunit::GetReadyStatus, BlankRecordId, 300000); end; local procedure ProcessSentDocuments() @@ -49,14 +49,14 @@ codeunit 6384 SignUpGetReadyStatus local procedure HandleResponse(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; var EDocumentServiceStatus: Record "E-Document Service Status") var - SignUpProcessing: Codeunit SignUpProcessing; + Processing: Codeunit Processing; BlankRecordId: RecordId; HttpResponse: HttpResponseMessage; HttpRequest: HttpRequestMessage; begin if GetResponse(EDocumentServiceStatus, HttpRequest, HttpResponse) then begin - SignUpProcessing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Approved, 0, HttpRequest, HttpResponse); - ScheduleEDocumentJob(Codeunit::SignUpPatchSent, BlankRecordId, 300000); + Processing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Approved, 0, HttpRequest, HttpResponse); + ScheduleEDocumentJob(Codeunit::PatchSent, BlankRecordId, 300000); end; end; @@ -64,7 +64,7 @@ codeunit 6384 SignUpGetReadyStatus local procedure GetResponse(var EDocumentServiceStatus: Record "E-Document Service Status"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) ReturnStatus: Boolean var EDocument: Record "E-Document"; - SignUpProcessing: Codeunit SignUpProcessing; + Processing: Codeunit Processing; TelemetryDimensions: Dictionary of [Text, Text]; begin // Commit before create document with error handling @@ -73,7 +73,7 @@ codeunit 6384 SignUpGetReadyStatus EDocument.Get(EDocumentServiceStatus."E-Document Entry No"); - if SignUpProcessing.GetDocumentSentResponse(EDocument, HttpRequest, HttpResponse) then + if Processing.GetDocumentSentResponse(EDocument, HttpRequest, HttpResponse) then ReturnStatus := true; Telemetry.LogMessage('', EDocTelemetryGetResponseScopeEndLbl, Verbosity::Normal, DataClassification::OrganizationIdentifiableInformation, TelemetryScope::All); diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/Helpers.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/Helpers.Codeunit.al index f97642792e..4b1406aba7 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/Helpers.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/Helpers.Codeunit.al @@ -6,7 +6,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using System.Text; -codeunit 6385 SignUpHelpers +codeunit 6385 Helpers { Access = Internal; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationEnumExt.EnumExt.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationEnumExt.EnumExt.al index 63f5c5c08f..db4953f886 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationEnumExt.EnumExt.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationEnumExt.EnumExt.al @@ -6,11 +6,11 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.EServices.EDocument; -enumextension 6380 SignUpIntegrationEnumExt extends "E-Document Integration" +enumextension 6380 IntegrationEnumExt extends "E-Document Integration" { value(6380; "ExFlow E-Invoicing") { Caption = 'ExFlow E-Invoicing'; - Implementation = "E-Document Integration" = SignUpIntegrationImpl; + Implementation = "E-Document Integration" = IntegrationImpl; } } \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationImpl.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationImpl.Codeunit.al index 577c4fe44c..0b257a5e64 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationImpl.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationImpl.Codeunit.al @@ -7,14 +7,14 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using System.Utilities; using Microsoft.EServices.EDocument; -codeunit 6386 SignUpIntegrationImpl implements "E-Document Integration" +codeunit 6386 IntegrationImpl implements "E-Document Integration" { Access = Internal; procedure Send(var EDocument: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) var begin - SignUpProcessing.SendEDocument(EDocument, TempBlob, IsAsync, HttpRequest, HttpResponse); + Processing.SendEDocument(EDocument, TempBlob, IsAsync, HttpRequest, HttpResponse); end; procedure SendBatch(var EDocuments: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) @@ -25,12 +25,12 @@ codeunit 6386 SignUpIntegrationImpl implements "E-Document Integration" procedure GetResponse(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean begin - exit(SignUpProcessing.GetDocumentResponse(EDocument, HttpRequest, HttpResponse)); + exit(Processing.GetDocumentResponse(EDocument, HttpRequest, HttpResponse)); end; procedure GetApproval(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean begin - exit(SignUpProcessing.GetDocumentApproval(EDocument, HttpRequest, HttpResponse)); + exit(Processing.GetDocumentApproval(EDocument, HttpRequest, HttpResponse)); end; procedure Cancel(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean @@ -40,20 +40,20 @@ codeunit 6386 SignUpIntegrationImpl implements "E-Document Integration" procedure ReceiveDocument(var TempBlob: Codeunit "Temp Blob"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) begin - SignUpProcessing.ReceiveDocument(TempBlob, HttpRequest, HttpResponse); + Processing.ReceiveDocument(TempBlob, HttpRequest, HttpResponse); end; procedure GetDocumentCountInBatch(var TempBlob: Codeunit "Temp Blob"): Integer begin - exit(SignUpProcessing.GetDocumentCountInBatch(TempBlob)); + exit(Processing.GetDocumentCountInBatch(TempBlob)); end; procedure GetIntegrationSetup(var SetupPage: Integer; var SetupTable: Integer) begin - SetupPage := Page::SignUpConnectionSetupCard; - SetupTable := Database::SignUpConnectionSetup; + SetupPage := Page::ConnectionSetupCard; + SetupTable := Database::ConnectionSetup; end; var - SignUpProcessing: Codeunit SignUpProcessing; + Processing: Codeunit Processing; } \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/PatchSent.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/PatchSent.Codeunit.al index 66f637d269..c7994b9648 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/PatchSent.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/PatchSent.Codeunit.al @@ -7,14 +7,14 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using System.Threading; using Microsoft.EServices.EDocument; -codeunit 6387 SignUpPatchSent +codeunit 6387 PatchSent { TableNo = "Job Queue Entry"; Access = Internal; trigger OnRun() var - SignUpGetReadyStatus: Codeunit SignUpGetReadyStatus; + GetReadyStatus: Codeunit GetReadyStatus; BlankRecordId: RecordId; begin if not IsEDocumentApproved() then @@ -23,7 +23,7 @@ codeunit 6387 SignUpPatchSent ProcessApprovedDocuments(); if IsEDocumentApproved() then - SignUpGetReadyStatus.ScheduleEDocumentJob(Codeunit::SignUpPatchSent, BlankRecordId, 300000); + GetReadyStatus.ScheduleEDocumentJob(Codeunit::PatchSent, BlankRecordId, 300000); end; local procedure ProcessApprovedDocuments() @@ -32,8 +32,8 @@ codeunit 6387 SignUpPatchSent EDocumentService: Record "E-Document Service"; EDocumentIntegrationLog: Record "E-Document Integration Log"; EDocument: Record "E-Document"; - SignUpAPIRequests: Codeunit SignUpAPIRequests; - SignUpProcessing: Codeunit SignUpProcessing; + APIRequests: Codeunit APIRequests; + Processing: Codeunit Processing; HttpResponse: HttpResponseMessage; HttpRequest: HttpRequestMessage; begin @@ -47,8 +47,8 @@ codeunit 6387 SignUpPatchSent EDocumentIntegrationLog.SetRange("Response Status", 204); EDocumentIntegrationLog.SetRange(Method, 'PATCH'); if EDocumentIntegrationLog.IsEmpty then - if SignUpAPIRequests.PatchADocument(EDocument, HttpRequest, HttpResponse) then - SignUpProcessing.InsertIntegrationLog(EDocument, EDocumentService, HttpRequest, HttpResponse); + if APIRequests.PatchADocument(EDocument, HttpRequest, HttpResponse) then + Processing.InsertIntegrationLog(EDocument, EDocumentService, HttpRequest, HttpResponse); until EDocumentServiceStatus.Next() = 0; end; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/Processing.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/Processing.Codeunit.al index 52f9e1f2a8..5684cc5b2c 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/Processing.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/Processing.Codeunit.al @@ -9,7 +9,7 @@ using System.Telemetry; using System.Text; using System.Utilities; -codeunit 6388 SignUpProcessing +codeunit 6388 Processing { Access = Internal; Permissions = tabledata "E-Document" = m, @@ -50,14 +50,14 @@ codeunit 6388 SignUpProcessing var EDocumentService: Record "E-Document Service"; EDocumentServiceStatus: Record "E-Document Service Status"; - SignUpAPIRequests: Codeunit SignUpAPIRequests; - SignUpProcessing: Codeunit SignUpProcessing; + APIRequests: Codeunit APIRequests; + Processing: Codeunit Processing; HttpContentResponse: HttpContent; Status, StatusDescription : Text; begin EDocumentHelper.GetEdocumentService(EDocument, EdocumentService); EDocumentServiceStatus.Get(EDocument."Entry No", EdocumentService.Code); - SignUpAPIRequests.GetSentDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage); + APIRequests.GetSentDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage); HttpContentResponse := HttpResponseMessage.Content; if ParseGetADocumentApprovalResponse(HttpContentResponse, Status, StatusDescription) then case Status of @@ -67,7 +67,7 @@ codeunit 6388 SignUpProcessing begin if StatusDescription <> '' then EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, 'Reason: ' + StatusDescription); - SignUpProcessing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Rejected, 0, HttpRequestMessage, HttpResponseMessage); + Processing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Rejected, 0, HttpRequestMessage, HttpResponseMessage); exit(false); end; end; @@ -78,9 +78,9 @@ codeunit 6388 SignUpProcessing var EDocumentService: Record "E-Document Service"; EDocumentServiceStatus: Record "E-Document Service Status"; - SignUpAPIRequests: Codeunit SignUpAPIRequests; - SignUpGetReadyStatus: Codeunit SignUpGetReadyStatus; - SignUpProcessing: Codeunit SignUpProcessing; + APIRequests: Codeunit APIRequests; + GetReadyStatus: Codeunit GetReadyStatus; + Processing: Codeunit Processing; BlankRecordId: RecordId; HttpContentResponse: HttpContent; Status, StatusDescription : Text; @@ -90,23 +90,23 @@ codeunit 6388 SignUpProcessing if not (EDocumentServiceStatus.Status in [EDocumentServiceStatus.Status::Sent, EDocumentServiceStatus.Status::"Pending Response"]) then Error(GetApprovalCheckStatusErr, EDocumentServiceStatus.Status); - SignUpAPIRequests.GetSentDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage); + APIRequests.GetSentDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage); HttpContentResponse := HttpResponseMessage.Content; if ParseGetADocumentApprovalResponse(HttpContentResponse, Status, StatusDescription) then case Status of 'Ready': begin if EDocumentServiceStatus.Status = EDocumentServiceStatus.Status::Approved then - SignUpGetReadyStatus.ScheduleEDocumentJob(Codeunit::SignUpPatchSent, BlankRecordId, 300000) + GetReadyStatus.ScheduleEDocumentJob(Codeunit::PatchSent, BlankRecordId, 300000) else - SignUpGetReadyStatus.ScheduleEDocumentJob(Codeunit::SignUpGetReadyStatus, BlankRecordId, 300000); + GetReadyStatus.ScheduleEDocumentJob(Codeunit::GetReadyStatus, BlankRecordId, 300000); exit(true); end; 'Failed': begin if StatusDescription <> '' then EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, 'Reason: ' + StatusDescription); - SignUpProcessing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Rejected, 0, HttpRequestMessage, HttpResponseMessage); + Processing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Rejected, 0, HttpRequestMessage, HttpResponseMessage); exit(false); end; end; @@ -118,7 +118,7 @@ codeunit 6388 SignUpProcessing ContentData: Text; OutStream: OutStream; begin - if not SignUpConnection.GetReceivedDocuments(HttpRequest, HttpResponse, true) then + if not Connection.GetReceivedDocuments(HttpRequest, HttpResponse, true) then exit; HttpResponse.Content.ReadAs(ContentData); @@ -142,7 +142,7 @@ codeunit 6388 SignUpProcessing var HttpContentResponse: HttpContent; begin - SignUpConnection.HandleSendFilePostRequest(TempBlob, EDocument, HttpRequest, HttpResponse, true); + Connection.HandleSendFilePostRequest(TempBlob, EDocument, HttpRequest, HttpResponse, true); HttpContentResponse := HttpResponse.Content; SetEDocumentFileID(EDocument."Entry No", ParseSendFileResponse(HttpContentResponse)); end; @@ -192,7 +192,7 @@ codeunit 6388 SignUpProcessing var ErrorDescription: Text; begin - if not SignUpConnection.CheckDocumentStatus(EDocument, HttpRequestMessage, HttpResponse, true) then + if not Connection.CheckDocumentStatus(EDocument, HttpRequestMessage, HttpResponse, true) then exit(false); if DocumentHasErrorOrProcessing(EDocument, HttpResponse, ErrorDescription) then @@ -207,7 +207,7 @@ codeunit 6388 SignUpProcessing Result: Text; Value: Text; begin - Result := SignUpHelpers.ParseJsonString(HttpContentResponse); + Result := Helpers.ParseJsonString(HttpContentResponse); if Result = '' then exit(''); @@ -236,13 +236,13 @@ codeunit 6388 SignUpProcessing EDocumentService: Record "E-Document Service"; EDocumentServiceStatus: Record "E-Document Service Status"; JsonManagement: Codeunit "JSON Management"; - SignUpGetReadyStatus: Codeunit SignUpGetReadyStatus; + GetReadyStatus: Codeunit GetReadyStatus; BlankRecordId: RecordId; HttpContentResponse: HttpContent; Result, Value : Text; begin HttpContentResponse := HttpResponse.Content; - Result := SignUpHelpers.ParseJsonString(HttpContentResponse); + Result := Helpers.ParseJsonString(HttpContentResponse); if Result = '' then exit(true); @@ -252,7 +252,7 @@ codeunit 6388 SignUpProcessing JsonManagement.GetArrayPropertyValueAsStringByName('status', Value); if Value in ['Sent'] then begin - SignUpGetReadyStatus.ScheduleEDocumentJob(Codeunit::SignUpGetReadyStatus, BlankRecordId, 120000); + GetReadyStatus.ScheduleEDocumentJob(Codeunit::GetReadyStatus, BlankRecordId, 120000); exit(false); end; @@ -260,9 +260,9 @@ codeunit 6388 SignUpProcessing EDocumentHelper.GetEdocumentService(EDocument, EDocumentService); EDocumentServiceStatus.Get(EDocument."Entry No", EdocumentService.Code); if EDocumentServiceStatus.Status = EDocumentServiceStatus.Status::Approved then - SignUpGetReadyStatus.ScheduleEDocumentJob(Codeunit::SignUpPatchSent, BlankRecordId, 180000) + GetReadyStatus.ScheduleEDocumentJob(Codeunit::PatchSent, BlankRecordId, 180000) else - SignUpGetReadyStatus.ScheduleEDocumentJob(Codeunit::SignUpGetReadyStatus, BlankRecordId, 120000); + GetReadyStatus.ScheduleEDocumentJob(Codeunit::GetReadyStatus, BlankRecordId, 120000); exit(false); end; @@ -280,7 +280,7 @@ codeunit 6388 SignUpProcessing JsonManagement: Codeunit "JSON Management"; Result: Text; begin - Result := SignUpHelpers.ParseJsonString(HttpContentResponse); + Result := Helpers.ParseJsonString(HttpContentResponse); if Result = '' then exit(false); @@ -332,7 +332,7 @@ codeunit 6388 SignUpProcessing exit; end; - SignUpConnection.HandleGetTargetDocumentRequest(DocumentId, LocalHttpRequest, LocalHttpResponse, false); + Connection.HandleGetTargetDocumentRequest(DocumentId, LocalHttpRequest, LocalHttpResponse, false); EDocumentLogHelper.InsertIntegrationLog(EDocument, EDocumentService, LocalHttpRequest, LocalHttpResponse); LocalHttpResponse.Content.ReadAs(ContentData); @@ -348,7 +348,7 @@ codeunit 6388 SignUpProcessing DocumentOutStream.WriteText(ContentData); EDocument."Document Id" := CopyStr(DocumentId, 1, MaxStrLen(EDocument."Document Id")); EDocumentLogHelper.InsertLog(EDocument, EDocumentService, TempBlob, "E-Document Service Status"::Imported); - SignUpConnection.RemoveDocumentFromReceived(EDocument, LocalHttpRequest, LocalHttpResponse, true); + Connection.RemoveDocumentFromReceived(EDocument, LocalHttpRequest, LocalHttpResponse, true); EDocumentLogHelper.InsertIntegrationLog(EDocument, EDocumentService, LocalHttpRequest, LocalHttpResponse); end; @@ -561,8 +561,8 @@ codeunit 6388 SignUpProcessing end; var - SignUpConnection: Codeunit SignUpConnection; - SignUpHelpers: Codeunit SignUpHelpers; + Connection: Codeunit Connection; + Helpers: Codeunit Helpers; EDocumentHelper: Codeunit "E-Document Helper"; EDocumentLogHelper: Codeunit "E-Document Log Helper"; EDocumentErrorHelper: Codeunit "E-Document Error Helper"; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/SendMode.Enum.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/SendMode.Enum.al index 22915cce76..8dd530ae19 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/SendMode.Enum.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/SendMode.Enum.al @@ -4,7 +4,7 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -enum 6380 SignUpSendMode +enum 6380 SendMode { Access = Internal; From 9eb37045c2101ee5b0aa63cda0754f70cf3373a5 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Tue, 24 Sep 2024 10:46:43 +0200 Subject: [PATCH 09/63] Resolve Build Conflict in GitHub - Rename --- .../{Processing.Codeunit.al => SignUpProcessing.Codeunit.al} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Apps/W1/EDocumentsConnector/app/src/SignUp/{Processing.Codeunit.al => SignUpProcessing.Codeunit.al} (100%) diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/Processing.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/SignUpProcessing.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentsConnector/app/src/SignUp/Processing.Codeunit.al rename to Apps/W1/EDocumentsConnector/app/src/SignUp/SignUpProcessing.Codeunit.al From 94266e2e72ce3a074b6bc3d9fa15b35716470975 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Tue, 24 Sep 2024 10:51:09 +0200 Subject: [PATCH 10/63] Resolve Build Conflict in GitHub - Refactor Codeunit Processing --- .../Permissions/SignUpEDocObjects.PermissionSet.al | 2 +- .../app/src/SignUp/Auth.Codeunit.al | 12 ++++++------ .../app/src/SignUp/GetReadyStatus.Codeunit.al | 8 ++++---- .../app/src/SignUp/IntegrationImpl.Codeunit.al | 12 ++++++------ .../app/src/SignUp/PatchSent.Codeunit.al | 4 ++-- .../app/src/SignUp/SignUpProcessing.Codeunit.al | 10 +++++----- 6 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocObjects.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocObjects.PermissionSet.al index 9dad400f69..1a071065c4 100644 --- a/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocObjects.PermissionSet.al +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocObjects.PermissionSet.al @@ -13,7 +13,7 @@ permissionset 6380 "SignUpEDoc. - Objects" table ConnectionAuth = X, page ConnectionSetupCard = X, codeunit IntegrationImpl = X, - codeunit Processing = X, + codeunit SignUpProcessing = X, codeunit Auth = X, codeunit APIRequests = X, codeunit Connection = X, diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/Auth.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/Auth.Codeunit.al index 43e627b37a..035d32ef13 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/Auth.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/Auth.Codeunit.al @@ -14,14 +14,14 @@ codeunit 6381 Auth procedure InitConnectionSetup() var - lConnectionSetup: Record ConnectionSetup; + LConnectionSetup: Record ConnectionSetup; begin - if lConnectionSetup.Get() then + if LConnectionSetup.Get() then exit; - lConnectionSetup."Authentication URL" := AuthURLTxt; - lConnectionSetup.ServiceURL := ProdServiceAPITxt; - StorageSet(lConnectionSetup."Client Tenant", ProdTenantIdTxt); - lConnectionSetup.Insert(); + LConnectionSetup."Authentication URL" := AuthURLTxt; + LConnectionSetup.ServiceURL := ProdServiceAPITxt; + StorageSet(LConnectionSetup."Client Tenant", ProdTenantIdTxt); + LConnectionSetup.Insert(); end; procedure GetRootOnboardingUrl(): Text diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/GetReadyStatus.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/GetReadyStatus.Codeunit.al index 92cb4f7474..9254b3f20a 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/GetReadyStatus.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/GetReadyStatus.Codeunit.al @@ -49,13 +49,13 @@ codeunit 6384 GetReadyStatus local procedure HandleResponse(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; var EDocumentServiceStatus: Record "E-Document Service Status") var - Processing: Codeunit Processing; + SignUpProcessing: Codeunit SignUpProcessing; BlankRecordId: RecordId; HttpResponse: HttpResponseMessage; HttpRequest: HttpRequestMessage; begin if GetResponse(EDocumentServiceStatus, HttpRequest, HttpResponse) then begin - Processing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Approved, 0, HttpRequest, HttpResponse); + SignUpProcessing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Approved, 0, HttpRequest, HttpResponse); ScheduleEDocumentJob(Codeunit::PatchSent, BlankRecordId, 300000); end; @@ -64,7 +64,7 @@ codeunit 6384 GetReadyStatus local procedure GetResponse(var EDocumentServiceStatus: Record "E-Document Service Status"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) ReturnStatus: Boolean var EDocument: Record "E-Document"; - Processing: Codeunit Processing; + SignUpProcessing: Codeunit SignUpProcessing; TelemetryDimensions: Dictionary of [Text, Text]; begin // Commit before create document with error handling @@ -73,7 +73,7 @@ codeunit 6384 GetReadyStatus EDocument.Get(EDocumentServiceStatus."E-Document Entry No"); - if Processing.GetDocumentSentResponse(EDocument, HttpRequest, HttpResponse) then + if SignUpProcessing.GetDocumentSentResponse(EDocument, HttpRequest, HttpResponse) then ReturnStatus := true; Telemetry.LogMessage('', EDocTelemetryGetResponseScopeEndLbl, Verbosity::Normal, DataClassification::OrganizationIdentifiableInformation, TelemetryScope::All); diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationImpl.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationImpl.Codeunit.al index 0b257a5e64..ab4eadc630 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationImpl.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationImpl.Codeunit.al @@ -14,7 +14,7 @@ codeunit 6386 IntegrationImpl implements "E-Document Integration" procedure Send(var EDocument: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) var begin - Processing.SendEDocument(EDocument, TempBlob, IsAsync, HttpRequest, HttpResponse); + SignUpProcessing.SendEDocument(EDocument, TempBlob, IsAsync, HttpRequest, HttpResponse); end; procedure SendBatch(var EDocuments: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) @@ -25,12 +25,12 @@ codeunit 6386 IntegrationImpl implements "E-Document Integration" procedure GetResponse(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean begin - exit(Processing.GetDocumentResponse(EDocument, HttpRequest, HttpResponse)); + exit(SignUpProcessing.GetDocumentResponse(EDocument, HttpRequest, HttpResponse)); end; procedure GetApproval(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean begin - exit(Processing.GetDocumentApproval(EDocument, HttpRequest, HttpResponse)); + exit(SignUpProcessing.GetDocumentApproval(EDocument, HttpRequest, HttpResponse)); end; procedure Cancel(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean @@ -40,12 +40,12 @@ codeunit 6386 IntegrationImpl implements "E-Document Integration" procedure ReceiveDocument(var TempBlob: Codeunit "Temp Blob"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) begin - Processing.ReceiveDocument(TempBlob, HttpRequest, HttpResponse); + SignUpProcessing.ReceiveDocument(TempBlob, HttpRequest, HttpResponse); end; procedure GetDocumentCountInBatch(var TempBlob: Codeunit "Temp Blob"): Integer begin - exit(Processing.GetDocumentCountInBatch(TempBlob)); + exit(SignUpProcessing.GetDocumentCountInBatch(TempBlob)); end; procedure GetIntegrationSetup(var SetupPage: Integer; var SetupTable: Integer) @@ -55,5 +55,5 @@ codeunit 6386 IntegrationImpl implements "E-Document Integration" end; var - Processing: Codeunit Processing; + SignUpProcessing: Codeunit SignUpProcessing; } \ No newline at end of file diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/PatchSent.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/PatchSent.Codeunit.al index c7994b9648..144fa8b40e 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/PatchSent.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/PatchSent.Codeunit.al @@ -33,7 +33,7 @@ codeunit 6387 PatchSent EDocumentIntegrationLog: Record "E-Document Integration Log"; EDocument: Record "E-Document"; APIRequests: Codeunit APIRequests; - Processing: Codeunit Processing; + SignUpProcessing: Codeunit SignUpProcessing; HttpResponse: HttpResponseMessage; HttpRequest: HttpRequestMessage; begin @@ -48,7 +48,7 @@ codeunit 6387 PatchSent EDocumentIntegrationLog.SetRange(Method, 'PATCH'); if EDocumentIntegrationLog.IsEmpty then if APIRequests.PatchADocument(EDocument, HttpRequest, HttpResponse) then - Processing.InsertIntegrationLog(EDocument, EDocumentService, HttpRequest, HttpResponse); + SignUpProcessing.InsertIntegrationLog(EDocument, EDocumentService, HttpRequest, HttpResponse); until EDocumentServiceStatus.Next() = 0; end; diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/SignUpProcessing.Codeunit.al b/Apps/W1/EDocumentsConnector/app/src/SignUp/SignUpProcessing.Codeunit.al index 5684cc5b2c..fa91f382e4 100644 --- a/Apps/W1/EDocumentsConnector/app/src/SignUp/SignUpProcessing.Codeunit.al +++ b/Apps/W1/EDocumentsConnector/app/src/SignUp/SignUpProcessing.Codeunit.al @@ -9,7 +9,7 @@ using System.Telemetry; using System.Text; using System.Utilities; -codeunit 6388 Processing +codeunit 6388 SignUpProcessing { Access = Internal; Permissions = tabledata "E-Document" = m, @@ -51,7 +51,7 @@ codeunit 6388 Processing EDocumentService: Record "E-Document Service"; EDocumentServiceStatus: Record "E-Document Service Status"; APIRequests: Codeunit APIRequests; - Processing: Codeunit Processing; + SignUpProcessing: Codeunit SignUpProcessing; HttpContentResponse: HttpContent; Status, StatusDescription : Text; begin @@ -67,7 +67,7 @@ codeunit 6388 Processing begin if StatusDescription <> '' then EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, 'Reason: ' + StatusDescription); - Processing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Rejected, 0, HttpRequestMessage, HttpResponseMessage); + SignUpProcessing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Rejected, 0, HttpRequestMessage, HttpResponseMessage); exit(false); end; end; @@ -80,7 +80,7 @@ codeunit 6388 Processing EDocumentServiceStatus: Record "E-Document Service Status"; APIRequests: Codeunit APIRequests; GetReadyStatus: Codeunit GetReadyStatus; - Processing: Codeunit Processing; + SignUpProcessing: Codeunit SignUpProcessing; BlankRecordId: RecordId; HttpContentResponse: HttpContent; Status, StatusDescription : Text; @@ -106,7 +106,7 @@ codeunit 6388 Processing begin if StatusDescription <> '' then EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, 'Reason: ' + StatusDescription); - Processing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Rejected, 0, HttpRequestMessage, HttpResponseMessage); + SignUpProcessing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Rejected, 0, HttpRequestMessage, HttpResponseMessage); exit(false); end; end; From def717600af21165b403e3e052fcb700f489c730 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Wed, 25 Sep 2024 10:22:45 +0200 Subject: [PATCH 11/63] Relocate To Own App - Move Files --- .../SignUp/app/src}/APIRequests.Codeunit.al | 0 .../SignUp/app/src}/Auth.Codeunit.al | 0 .../SignUp/app/src}/Connection.Codeunit.al | 0 .../SignUp/app/src}/ConnectionAuth.Table.al | 0 .../SignUp/app/src}/ConnectionSetup.Table.al | 0 .../SignUp/app/src}/ConnectionSetupCard.Page.al | 0 .../SignUp/app/src}/ErrorSensitive.Codeunit.al | 0 .../SignUp/app/src/Extensions}/IntegrationEnumExt.EnumExt.al | 0 .../SignUp/app/src}/GetReadyStatus.Codeunit.al | 0 .../SignUp/app/src}/Helpers.Codeunit.al | 0 .../SignUp/app/src}/IntegrationImpl.Codeunit.al | 0 .../SignUp/app/src}/PatchSent.Codeunit.al | 0 .../SignUp}/app/src/Permissions/SignUpEDocEdit.PermissionSet.al | 0 .../app/src/Permissions/SignUpEDocObjects.PermissionSet.al | 0 .../SignUp}/app/src/Permissions/SignUpEDocRead.PermissionSet.al | 0 .../SignUp/app/src}/SendMode.Enum.al | 0 .../SignUp/app/src}/SignUpProcessing.Codeunit.al | 0 17 files changed, 0 insertions(+), 0 deletions(-) rename Apps/W1/{EDocumentsConnector/app/src/SignUp => EDocumentConnectors/SignUp/app/src}/APIRequests.Codeunit.al (100%) rename Apps/W1/{EDocumentsConnector/app/src/SignUp => EDocumentConnectors/SignUp/app/src}/Auth.Codeunit.al (100%) rename Apps/W1/{EDocumentsConnector/app/src/SignUp => EDocumentConnectors/SignUp/app/src}/Connection.Codeunit.al (100%) rename Apps/W1/{EDocumentsConnector/app/src/SignUp => EDocumentConnectors/SignUp/app/src}/ConnectionAuth.Table.al (100%) rename Apps/W1/{EDocumentsConnector/app/src/SignUp => EDocumentConnectors/SignUp/app/src}/ConnectionSetup.Table.al (100%) rename Apps/W1/{EDocumentsConnector/app/src/SignUp => EDocumentConnectors/SignUp/app/src}/ConnectionSetupCard.Page.al (100%) rename Apps/W1/{EDocumentsConnector/app/src/SignUp => EDocumentConnectors/SignUp/app/src}/ErrorSensitive.Codeunit.al (100%) rename Apps/W1/{EDocumentsConnector/app/src/SignUp => EDocumentConnectors/SignUp/app/src/Extensions}/IntegrationEnumExt.EnumExt.al (100%) rename Apps/W1/{EDocumentsConnector/app/src/SignUp => EDocumentConnectors/SignUp/app/src}/GetReadyStatus.Codeunit.al (100%) rename Apps/W1/{EDocumentsConnector/app/src/SignUp => EDocumentConnectors/SignUp/app/src}/Helpers.Codeunit.al (100%) rename Apps/W1/{EDocumentsConnector/app/src/SignUp => EDocumentConnectors/SignUp/app/src}/IntegrationImpl.Codeunit.al (100%) rename Apps/W1/{EDocumentsConnector/app/src/SignUp => EDocumentConnectors/SignUp/app/src}/PatchSent.Codeunit.al (100%) rename Apps/W1/{EDocumentsConnector => EDocumentConnectors/SignUp}/app/src/Permissions/SignUpEDocEdit.PermissionSet.al (100%) rename Apps/W1/{EDocumentsConnector => EDocumentConnectors/SignUp}/app/src/Permissions/SignUpEDocObjects.PermissionSet.al (100%) rename Apps/W1/{EDocumentsConnector => EDocumentConnectors/SignUp}/app/src/Permissions/SignUpEDocRead.PermissionSet.al (100%) rename Apps/W1/{EDocumentsConnector/app/src/SignUp => EDocumentConnectors/SignUp/app/src}/SendMode.Enum.al (100%) rename Apps/W1/{EDocumentsConnector/app/src/SignUp => EDocumentConnectors/SignUp/app/src}/SignUpProcessing.Codeunit.al (100%) diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/APIRequests.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentsConnector/app/src/SignUp/APIRequests.Codeunit.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/Auth.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Auth.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentsConnector/app/src/SignUp/Auth.Codeunit.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Auth.Codeunit.al diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/Connection.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Connection.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentsConnector/app/src/SignUp/Connection.Codeunit.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Connection.Codeunit.al diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionAuth.Table.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionAuth.Table.al similarity index 100% rename from Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionAuth.Table.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionAuth.Table.al diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetup.Table.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionSetup.Table.al similarity index 100% rename from Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetup.Table.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionSetup.Table.al diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionSetupCard.Page.al similarity index 100% rename from Apps/W1/EDocumentsConnector/app/src/SignUp/ConnectionSetupCard.Page.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionSetupCard.Page.al diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/ErrorSensitive.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/ErrorSensitive.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentsConnector/app/src/SignUp/ErrorSensitive.Codeunit.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/ErrorSensitive.Codeunit.al diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationEnumExt.EnumExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Extensions/IntegrationEnumExt.EnumExt.al similarity index 100% rename from Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationEnumExt.EnumExt.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Extensions/IntegrationEnumExt.EnumExt.al diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/GetReadyStatus.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/GetReadyStatus.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentsConnector/app/src/SignUp/GetReadyStatus.Codeunit.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/GetReadyStatus.Codeunit.al diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/Helpers.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Helpers.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentsConnector/app/src/SignUp/Helpers.Codeunit.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Helpers.Codeunit.al diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/IntegrationImpl.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentsConnector/app/src/SignUp/IntegrationImpl.Codeunit.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/IntegrationImpl.Codeunit.al diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/PatchSent.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/PatchSent.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentsConnector/app/src/SignUp/PatchSent.Codeunit.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/PatchSent.Codeunit.al diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocEdit.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocEdit.PermissionSet.al similarity index 100% rename from Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocEdit.PermissionSet.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocEdit.PermissionSet.al diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocObjects.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocObjects.PermissionSet.al similarity index 100% rename from Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocObjects.PermissionSet.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocObjects.PermissionSet.al diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocRead.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocRead.PermissionSet.al similarity index 100% rename from Apps/W1/EDocumentsConnector/app/src/Permissions/SignUpEDocRead.PermissionSet.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocRead.PermissionSet.al diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/SendMode.Enum.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SendMode.Enum.al similarity index 100% rename from Apps/W1/EDocumentsConnector/app/src/SignUp/SendMode.Enum.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/SendMode.Enum.al diff --git a/Apps/W1/EDocumentsConnector/app/src/SignUp/SignUpProcessing.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentsConnector/app/src/SignUp/SignUpProcessing.Codeunit.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al From 381137015addf5a44dbfb8e34c15195a9710afdd Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Wed, 25 Sep 2024 12:43:28 +0200 Subject: [PATCH 12/63] Refactor - Rename Files --- .../{SignUpEDocEdit.PermissionSet.al => Edit.PermissionSet.al} | 0 ...ignUpEDocObjects.PermissionSet.al => Objects.PermissionSet.al} | 0 .../{SignUpEDocRead.PermissionSet.al => Read.PermissionSet.al} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/{SignUpEDocEdit.PermissionSet.al => Edit.PermissionSet.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/{SignUpEDocObjects.PermissionSet.al => Objects.PermissionSet.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/{SignUpEDocRead.PermissionSet.al => Read.PermissionSet.al} (100%) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocEdit.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Edit.PermissionSet.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocEdit.PermissionSet.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Edit.PermissionSet.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocObjects.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Objects.PermissionSet.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocObjects.PermissionSet.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Objects.PermissionSet.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocRead.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Read.PermissionSet.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocRead.PermissionSet.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Read.PermissionSet.al From 17944a29538f4acee7038bcf383224da816def69 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Wed, 25 Sep 2024 12:45:51 +0200 Subject: [PATCH 13/63] Refactor - Add app.json --- .../EDocumentConnectors/SignUp/app/app.json | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/app.json diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/app.json b/Apps/W1/EDocumentConnectors/SignUp/app/app.json new file mode 100644 index 0000000000..5d02eb4470 --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/app/app.json @@ -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" + ] +} \ No newline at end of file From 6cdeaeaf12baa3ff6fe4010ccabfb4debb008537 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Wed, 25 Sep 2024 12:46:22 +0200 Subject: [PATCH 14/63] Refactor - Restore Original Objects --- .../app/src/Permissions/EDocConnectorEdit.PermissionSet.al | 3 +-- .../app/src/Permissions/EDocConnectorObjects.PermissionSet.al | 1 - .../app/src/Permissions/EDocConnectorRead.PermissionSet.al | 3 +-- 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorEdit.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorEdit.PermissionSet.al index a55382fbf8..88f0f656e6 100644 --- a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorEdit.PermissionSet.al +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorEdit.PermissionSet.al @@ -8,8 +8,7 @@ permissionset 6361 "EDocConnector - Edit" { Access = Public; Assignable = true; - IncludedPermissionSets = "EDocConnector - Read", - Microsoft.EServices.EDocumentConnector.SignUp."SignUpEDoc. - Edit"; + IncludedPermissionSets = "EDocConnector - Read"; Permissions = tabledata "E-Doc. Ext. Connection Setup" = IM, tabledata Microsoft.EServices.EDocumentConnector.Avalara."Connection Setup" = imd; diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorObjects.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorObjects.PermissionSet.al index 0a1e7a24aa..f5fb6cb8e0 100644 --- a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorObjects.PermissionSet.al +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorObjects.PermissionSet.al @@ -8,7 +8,6 @@ permissionset 6363 "EDoc. Connector Objects" { Access = Public; Assignable = false; - IncludedPermissionSets = Microsoft.EServices.EDocumentConnector.SignUp."SignUpEDoc. - Objects"; Permissions = table "E-Doc. Ext. Connection Setup" = X, page "EDoc Ext Connection Setup Card" = X, diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al index 0086239cfa..1d01f7b465 100644 --- a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al @@ -8,8 +8,7 @@ permissionset 6362 "EDocConnector - Read" { Access = Public; Assignable = true; - IncludedPermissionSets = "EDoc. Connector Objects", - Microsoft.EServices.EDocumentConnector.SignUp."SignUpEDoc. - Read"; + IncludedPermissionSets = "EDoc. Connector Objects"; Permissions = tabledata "E-Doc. Ext. Connection Setup" = R, tabledata Microsoft.EServices.EDocumentConnector.Avalara."Connection Setup" = r; From 4382237430d89de68c780ab5ad43c1dda88221a1 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Wed, 25 Sep 2024 12:51:39 +0200 Subject: [PATCH 15/63] Refactor - Rename Processing --- .../src/{SignUpProcessing.Codeunit.al => Processing.Codeunit.al} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Apps/W1/EDocumentConnectors/SignUp/app/src/{SignUpProcessing.Codeunit.al => Processing.Codeunit.al} (100%) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al From 7bd134c511796e93654fe93961bdd942e8c3a5eb Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Wed, 25 Sep 2024 12:54:21 +0200 Subject: [PATCH 16/63] Refactor - Permission Extensions, Object Rename --- .../SignUp/app/src/Permissions/Edit.PermissionSet.al | 9 +++++---- .../app/src/Permissions/Objects.PermissionSet.al | 5 +++-- .../SignUp/app/src/Permissions/Read.PermissionSet.al | 9 +++++---- .../SignUpEDocConnectorEdit.PermissionSetExt.al | 11 +++++++++++ .../SignUpEDocConnectorRead.PermissionSetExt.al | 11 +++++++++++ 5 files changed, 35 insertions(+), 10 deletions(-) create mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocConnectorEdit.PermissionSetExt.al create mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocConnectorRead.PermissionSetExt.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Edit.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Edit.PermissionSet.al index eac95d8021..b017d9b5e7 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Edit.PermissionSet.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Edit.PermissionSet.al @@ -4,12 +4,13 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -permissionset 6382 "SignUpEDoc. - Edit" +permissionset 6382 Edit { Access = Internal; Assignable = false; - IncludedPermissionSets = "SignUpEDoc. - Read"; + Caption = 'SignUp E-Document Connector - Edit'; + IncludedPermissionSets = Read; - Permissions = tabledata ConnectionSetup = IM, - tabledata ConnectionAuth = IM; + Permissions = tabledata ConnectionSetup = imd, + tabledata ConnectionAuth = imd; } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Objects.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Objects.PermissionSet.al index 1a071065c4..e0f855fc66 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Objects.PermissionSet.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Objects.PermissionSet.al @@ -4,16 +4,17 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -permissionset 6380 "SignUpEDoc. - Objects" +permissionset 6380 Objects { Access = Internal; Assignable = false; + Caption = 'SignUp E-Document Connector - Objects'; Permissions = table ConnectionSetup = X, table ConnectionAuth = X, page ConnectionSetupCard = X, codeunit IntegrationImpl = X, - codeunit SignUpProcessing = X, + codeunit Processing = X, codeunit Auth = X, codeunit APIRequests = X, codeunit Connection = X, diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Read.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Read.PermissionSet.al index 1bf5a00de2..1a9b95afc2 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Read.PermissionSet.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Read.PermissionSet.al @@ -4,12 +4,13 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -permissionset 6381 "SignUpEDoc. - Read" +permissionset 6381 Read { Access = Internal; Assignable = false; - IncludedPermissionSets = "SignUpEDoc. - Objects"; + Caption = 'SignUp E-Document Connector - Read'; + IncludedPermissionSets = Objects; - Permissions = tabledata ConnectionSetup = R, - tabledata ConnectionAuth = R; + Permissions = tabledata ConnectionSetup = r, + tabledata ConnectionAuth = r; } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocConnectorEdit.PermissionSetExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocConnectorEdit.PermissionSetExt.al new file mode 100644 index 0000000000..94cbf00cde --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocConnectorEdit.PermissionSetExt.al @@ -0,0 +1,11 @@ +// ------------------------------------------------------------------------------------------------ +// 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.EDocumentConnector; + +permissionsetextension 6380 "SignUp EDoc. Connector - Edit" extends "EDocConnector - Edit" +{ + IncludedPermissionSets = Edit; +} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocConnectorRead.PermissionSetExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocConnectorRead.PermissionSetExt.al new file mode 100644 index 0000000000..9c27703bce --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocConnectorRead.PermissionSetExt.al @@ -0,0 +1,11 @@ +// ------------------------------------------------------------------------------------------------ +// 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.EDocumentConnector; + +permissionsetextension 6381 "SignUp EDoc. Connector - Read" extends "EDocConnector - Read" +{ + IncludedPermissionSets = Read; +} \ No newline at end of file From 42b9a11b6fd3b2917997212860db3194bf796fd8 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Wed, 25 Sep 2024 12:55:01 +0200 Subject: [PATCH 17/63] Refactor - References to Processing --- .../SignUp/app/src/GetReadyStatus.Codeunit.al | 8 ++++---- .../SignUp/app/src/IntegrationImpl.Codeunit.al | 12 ++++++------ .../SignUp/app/src/PatchSent.Codeunit.al | 4 ++-- .../SignUp/app/src/Processing.Codeunit.al | 10 +++++----- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/GetReadyStatus.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/GetReadyStatus.Codeunit.al index 9254b3f20a..92cb4f7474 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/GetReadyStatus.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/GetReadyStatus.Codeunit.al @@ -49,13 +49,13 @@ codeunit 6384 GetReadyStatus local procedure HandleResponse(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; var EDocumentServiceStatus: Record "E-Document Service Status") var - SignUpProcessing: Codeunit SignUpProcessing; + Processing: Codeunit Processing; BlankRecordId: RecordId; HttpResponse: HttpResponseMessage; HttpRequest: HttpRequestMessage; begin if GetResponse(EDocumentServiceStatus, HttpRequest, HttpResponse) then begin - SignUpProcessing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Approved, 0, HttpRequest, HttpResponse); + Processing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Approved, 0, HttpRequest, HttpResponse); ScheduleEDocumentJob(Codeunit::PatchSent, BlankRecordId, 300000); end; @@ -64,7 +64,7 @@ codeunit 6384 GetReadyStatus local procedure GetResponse(var EDocumentServiceStatus: Record "E-Document Service Status"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) ReturnStatus: Boolean var EDocument: Record "E-Document"; - SignUpProcessing: Codeunit SignUpProcessing; + Processing: Codeunit Processing; TelemetryDimensions: Dictionary of [Text, Text]; begin // Commit before create document with error handling @@ -73,7 +73,7 @@ codeunit 6384 GetReadyStatus EDocument.Get(EDocumentServiceStatus."E-Document Entry No"); - if SignUpProcessing.GetDocumentSentResponse(EDocument, HttpRequest, HttpResponse) then + if Processing.GetDocumentSentResponse(EDocument, HttpRequest, HttpResponse) then ReturnStatus := true; Telemetry.LogMessage('', EDocTelemetryGetResponseScopeEndLbl, Verbosity::Normal, DataClassification::OrganizationIdentifiableInformation, TelemetryScope::All); diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/IntegrationImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/IntegrationImpl.Codeunit.al index ab4eadc630..0b257a5e64 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/IntegrationImpl.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/IntegrationImpl.Codeunit.al @@ -14,7 +14,7 @@ codeunit 6386 IntegrationImpl implements "E-Document Integration" procedure Send(var EDocument: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) var begin - SignUpProcessing.SendEDocument(EDocument, TempBlob, IsAsync, HttpRequest, HttpResponse); + Processing.SendEDocument(EDocument, TempBlob, IsAsync, HttpRequest, HttpResponse); end; procedure SendBatch(var EDocuments: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) @@ -25,12 +25,12 @@ codeunit 6386 IntegrationImpl implements "E-Document Integration" procedure GetResponse(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean begin - exit(SignUpProcessing.GetDocumentResponse(EDocument, HttpRequest, HttpResponse)); + exit(Processing.GetDocumentResponse(EDocument, HttpRequest, HttpResponse)); end; procedure GetApproval(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean begin - exit(SignUpProcessing.GetDocumentApproval(EDocument, HttpRequest, HttpResponse)); + exit(Processing.GetDocumentApproval(EDocument, HttpRequest, HttpResponse)); end; procedure Cancel(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean @@ -40,12 +40,12 @@ codeunit 6386 IntegrationImpl implements "E-Document Integration" procedure ReceiveDocument(var TempBlob: Codeunit "Temp Blob"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) begin - SignUpProcessing.ReceiveDocument(TempBlob, HttpRequest, HttpResponse); + Processing.ReceiveDocument(TempBlob, HttpRequest, HttpResponse); end; procedure GetDocumentCountInBatch(var TempBlob: Codeunit "Temp Blob"): Integer begin - exit(SignUpProcessing.GetDocumentCountInBatch(TempBlob)); + exit(Processing.GetDocumentCountInBatch(TempBlob)); end; procedure GetIntegrationSetup(var SetupPage: Integer; var SetupTable: Integer) @@ -55,5 +55,5 @@ codeunit 6386 IntegrationImpl implements "E-Document Integration" end; var - SignUpProcessing: Codeunit SignUpProcessing; + Processing: Codeunit Processing; } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/PatchSent.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/PatchSent.Codeunit.al index 144fa8b40e..c7994b9648 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/PatchSent.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/PatchSent.Codeunit.al @@ -33,7 +33,7 @@ codeunit 6387 PatchSent EDocumentIntegrationLog: Record "E-Document Integration Log"; EDocument: Record "E-Document"; APIRequests: Codeunit APIRequests; - SignUpProcessing: Codeunit SignUpProcessing; + Processing: Codeunit Processing; HttpResponse: HttpResponseMessage; HttpRequest: HttpRequestMessage; begin @@ -48,7 +48,7 @@ codeunit 6387 PatchSent EDocumentIntegrationLog.SetRange(Method, 'PATCH'); if EDocumentIntegrationLog.IsEmpty then if APIRequests.PatchADocument(EDocument, HttpRequest, HttpResponse) then - SignUpProcessing.InsertIntegrationLog(EDocument, EDocumentService, HttpRequest, HttpResponse); + Processing.InsertIntegrationLog(EDocument, EDocumentService, HttpRequest, HttpResponse); until EDocumentServiceStatus.Next() = 0; end; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al index fa91f382e4..5684cc5b2c 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al @@ -9,7 +9,7 @@ using System.Telemetry; using System.Text; using System.Utilities; -codeunit 6388 SignUpProcessing +codeunit 6388 Processing { Access = Internal; Permissions = tabledata "E-Document" = m, @@ -51,7 +51,7 @@ codeunit 6388 SignUpProcessing EDocumentService: Record "E-Document Service"; EDocumentServiceStatus: Record "E-Document Service Status"; APIRequests: Codeunit APIRequests; - SignUpProcessing: Codeunit SignUpProcessing; + Processing: Codeunit Processing; HttpContentResponse: HttpContent; Status, StatusDescription : Text; begin @@ -67,7 +67,7 @@ codeunit 6388 SignUpProcessing begin if StatusDescription <> '' then EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, 'Reason: ' + StatusDescription); - SignUpProcessing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Rejected, 0, HttpRequestMessage, HttpResponseMessage); + Processing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Rejected, 0, HttpRequestMessage, HttpResponseMessage); exit(false); end; end; @@ -80,7 +80,7 @@ codeunit 6388 SignUpProcessing EDocumentServiceStatus: Record "E-Document Service Status"; APIRequests: Codeunit APIRequests; GetReadyStatus: Codeunit GetReadyStatus; - SignUpProcessing: Codeunit SignUpProcessing; + Processing: Codeunit Processing; BlankRecordId: RecordId; HttpContentResponse: HttpContent; Status, StatusDescription : Text; @@ -106,7 +106,7 @@ codeunit 6388 SignUpProcessing begin if StatusDescription <> '' then EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, 'Reason: ' + StatusDescription); - SignUpProcessing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Rejected, 0, HttpRequestMessage, HttpResponseMessage); + Processing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Rejected, 0, HttpRequestMessage, HttpResponseMessage); exit(false); end; end; From 6480969a1199ec40885c39f42d27b373064d2042 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Wed, 25 Sep 2024 12:56:04 +0200 Subject: [PATCH 18/63] Refactor - Restore app.json --- Apps/W1/EDocumentsConnector/app/app.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Apps/W1/EDocumentsConnector/app/app.json b/Apps/W1/EDocumentsConnector/app/app.json index 30fafc9597..301840542b 100644 --- a/Apps/W1/EDocumentsConnector/app/app.json +++ b/Apps/W1/EDocumentsConnector/app/app.json @@ -31,7 +31,7 @@ "idRanges": [ { "from": 6360, - "to": 6389 + "to": 6379 } ], "resourceExposurePolicy": { From d7ecea8419eeae80c1abf5fbfc6930f0f6885a68 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Wed, 25 Sep 2024 13:05:33 +0200 Subject: [PATCH 19/63] Refactor - Missed a spot in restoring original --- .../app/src/Permissions/EDocConnectorRead.PermissionSet.al | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al index 1d01f7b465..07be9b89a6 100644 --- a/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al +++ b/Apps/W1/EDocumentsConnector/app/src/Permissions/EDocConnectorRead.PermissionSet.al @@ -11,5 +11,5 @@ permissionset 6362 "EDocConnector - Read" IncludedPermissionSets = "EDoc. Connector Objects"; Permissions = tabledata "E-Doc. Ext. Connection Setup" = R, - tabledata Microsoft.EServices.EDocumentConnector.Avalara."Connection Setup" = r; + tabledata Microsoft.EServices.EDocumentConnector.Avalara."Connection Setup" = r; } \ No newline at end of file From f39fb473cbeb679d3b8aa1053c18972fd897cb69 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Thu, 26 Sep 2024 15:53:05 +0200 Subject: [PATCH 20/63] Refactor - Missing Logo --- .../SignUp/app/ExtensionLogo.png | Bin 0 -> 5446 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/ExtensionLogo.png diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/ExtensionLogo.png b/Apps/W1/EDocumentConnectors/SignUp/app/ExtensionLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..4d2c9a626cb9617350617c40cd73904129d4c108 GIT binary patch literal 5446 zcma)=S5VVywD$iAMIcgC2u+$uktV%J6$Dhev_NQrfC^Fsq!|cJ=^|Z`P&U*^N-uuwi#_w5i!*aB*89x5SkKKnv*ua91anhEW+omc005Zp+`e`1 zOsW4C1O3^nWxbYuCX9Z!?E(M*a`E2+jm<_J0|5K}om)4pLZ&wJ&3t(K(|ffcq#?ky z#^aeQO#|lO9vyUeb0ezqQtpipl3Sj#-xy!eh7lu@5+BnW zNhL-~3Zpw&1u=bMN*Q(sgYksq4dM>Iw7p&Qk_Su~b*PgEs#LK~^K}aDaTG_6Q?_tM<8wOS}`Z+?~Et8GB>T%(k7$9`DL!d5)f!ZoXco-vj+s_QLEs2cf zKM&F>#c9w|TmM9MFtl8L*cYQgl9khf5CYMR)DJOUf;M~a9|+ys@RYR zCusNC(CSlUk|r`qdS&ZKh$O=@#&e0>;W~S#|KjHdfLx!-J9r1JtP4RGIhS|Rm0eZ6 z7eOE~Zfo4Li~K^|&)d^-r?8Rh2Q}#ZjL=?VJZ7~hlp4(!U!0K%679I`OR&x54*0&4 znho|hKu)WR)4PUVA1}N;jXHg}AG+gSKQ6O_fEP^Y51!LwBERH09|t!GNx2KH4co>r zA%cgSHxh2Sezx-w!S5DTG#0zVCbnLM6BP}2P-G{8 zh**wJHj<652FS05bSQNx-0fS7^(wREYvZwpt;$!!k4H0U*iyhS8(syBDMv>L<)~LI zPl!Y^-cM{_J@{hY1=XJ#T=Ef(FD!I^r1^lca3c0ftVuvo-(%!Zn)C1bK{}-i*Jc); zIIc+o&iMgvboj&4`@5sF23MV!*zIVmA0>{1;*H*faMAG6EZ7XydTfaGyABAGx>)yl z@Y+|)SVxCx@!GWqspay7GBetK*s2@CJ?s{8v!(b|ShLb|O;3T1rAMB?DJ?Z`@013q zoyIvV84eYiS+?kRJOz`3AFcR~ZQ1Uq7wCnbSJ%-HZwhAnJ^4zDp2W8I)~WI7ush5> z&f3O)rj~2ZGr!c@=p3!n>jG-O#9`$7&WyF7bB}(rq4ldokUp5TY?E62r+YJbJp8Jf znDW3fYZ^nBQ9O}3?zH_*mZ9+G#HHnwop1Vfm!Df~{Z%D?5KzMN&RA>&#q8iCzTfAt zV#TyMeyyh8=M$8tyA|KeUwo_Q6Si)P)%n(W-*QE~08BG|>J!sQPq?IF;;%1ypP?Z` zK_0Un>p;9=9d675ELHboC0+fNMY&(;k(|=0TS>ka)BKI3q#)zx!Jp@zv0QfeEAjU< z=vI5@-d^A^-*#|P+b2QFiGxk4z<8Tp4p6{aOp88x>SQEa0M`VxX%IUb$bya!5EgRf6$fFw zp}jNTKUXjNe0x(;)Nu)Ij5K?QD0u6~mRHQ-!;6m#VP>)}=irAqy;f$e{W-EWnR75~ zm2b0u@r7ASk4x0oTqs9{f&F|eAmD*Gf^A;te7f}J{dXqLaH_4%D_(mnp0VmWhq>^E z&7>5*-mh>FX{w5SJf^#th&GrpOQk58U-+4 zq3$q~C4ySH7@lr>W+|c0`UF*ieC+3vC1$4m}F(ic|G7}QDt(t z7`#>$c4U-4LU_;nWHhdN9Fcv~L8h6M_}nW&EGTjgW(=c}uD9>eU^rDOrkNg_effOV z^8z_y=vNIt{`wOfgG2o^3ey`R!aP1=t7Mz@&MKK3>_BH_QkgNO@4IoQ-2d8EqsDg) zTMb-5lqlubRot-7!RD@+udO?O9_Da3XV5bvjW zXTb2psHUdeiIaI(lknQE_<+YlY31}R!VfoM_BuILQ{>Q89=LB5j;V|-yAW2gY82+~ zYlu~#*R(cHw2NO1h5xaiAD2oiIEQ-aQyA-D^y^z2ZHNfM{o(3M#SbqOP3>k9FOdDO z(t%c9hk)NCPe_8>=Y^U-_-6IwS-D0cE=pwdyLp!;r-fWiXtbUS$<dl!~WV$TR8 zP$KU?K>m?*O)mSGccn&kn|nj7NXFeo<0D=ue8s^~BK#P?J~gB}v5<0nK9GPipjT#9 zkm6yXFyLlgoUIDEVxw*0Z-WDqp8swCs(bcjAqdDLl1oUqYf#a`NjT6IO3?=P`FvUZ zlWC&lWb9_dexSz%N~-oscM`oC%b#KS|KS7AptwRX5h&1VDCKWzP{&??TFdF3h53&c zU(v)WhOr)#!V6Y6d7CzOO-@KF%@67>kh34@Exj7Rh}p5_0?yUeyC7@c7DHf+mW=~wpLeLYDA9#W-Ri*S|M@g zjPHH@qHrPuzq(+5y$V*UoFEg(g$$mRNUEF!C{IN3Rig{tU54W|OD_`M0G3u)B{WhC z*D?hTF7J+YdF8-Z-Uuw{3jBx`_!aus`uDDBecwuu&tsVpj2~DZJb2-!a2l??m{}er}lR6Lqu)-2+Vm)jr(g{nfQPx9-<^1d;k-d zkU{E^g7qwp+D`b+QtU5@+swaVKp9<`>sT~U)O!EEMBo!*)~s_<`6Yl z7fX2;ki>kVDfdietW1k;TYvaY({>?5X)&(d&_y<-J7Qa@b z(zwGCI=`P#^b>1>2#Y!9T5|AdtaU|zXxw9^KpIu6CAmQf$GzaeOJmYVsc3eh5%6lb z)t~(Ak2J`;KW_L6psME-h?xF6ryr4d{q;>-b`Q$L43T{r`{N?U6cqP(Q3f%kA8`c@ z<82KXjte|7u_Lo~MV!d%y$tYi(hzU$6t+*ml~Z&Mg{eK?@}^XEBK+-&j`Uv95x)=_ zZLs=Mpg_IuZenjm(~}b8Aggaaje8NX$A_7^G%-)!xtu)C{N|S<3hVOmU;{|i+q6zn zfr(1Ua*jF!%-dU3L}O2fvWAe%-4kxtXo_vJHF(AxSx)4AI8-$^uBQO_86Z_y%RZX4 zJpu5`pOAztxv?jXv9yx|r>#9!0|`71C-fli@v${6r+V$hgvcr|W_I`{=7*0s(PKQH zzn8r2+tSeD15stz|DIJ3%X%8EkyN?bsHhuq4(5D0Oewn_)-o)Nx$eNs{0V*ZTSVt4 z3ifXGGw5fBv+9b6d~Nl+08L4VbbZqf3DL^e?l@!uZVdWkdOpJPaE?{zF!ZI?c(vF3 zvX~OK4vktvm&R$MgNpiKA~&zT!1#H7!q1h7AQiuSNG9<=$64)Zym(UQ``(j#^hDzt}{aur0pS?mmBi&z4I0Jfieqh%Pa_A%N?_1OZHm-S{ zQ*)4(N_J;y7tRh0o>xs25-s9!M-)i;@I68#SGXB2XgS}N zx_r3%V)z1jLA_M&?)E^DT$kzdHMJF%e2w6BH@iI5tKWM+zcuhCsz@N0a_1RBvrdZx zjzD>V%;c4*$RkEv{zHuVyaB+ANl(iT8w{pJdziC7YcO2&(ciqGLhs@q-dNh! zkV_V_(_~$*>ND}j1yozMedYnu-_GKMh?IpP<@D+edeB4M%3@xr3oj{@mdFKoBVpm^)1_}Y^}rOWBSB|Uv)*-pTdiU ztW9~{qq5@iB+$QpbeJVKH^n^9vV})i>Z@2CHoY2$PC888c;#Yz-pHRK@EVheWhE!> zZzjPmy?0Ni8#=o_k6_s3DY7nS^&Bm}BW&ZfAuF7bQbDgAGM$dE)RM6RvdobKb&MhsYD4exRm9*jcHPjbz#rI?vj$u zPLF5Gjv|8}?ta9`&^H}Va3H;llghU-BC7pxo6?-eTP`7CUZHJrw{5 zhkDYeIYlhL%brQJ1X#<#fz#E}Z87Kj=Hde*f{l|A`9E my8jz0{9hgZgN;Rh%;ug!HJ{lE_@04L;EulOt!iDD=>G@$cU!Ii literal 0 HcmV?d00001 From a8c22c702c52b49e0ff153fa2526053a46d9ecda Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Fri, 27 Sep 2024 13:44:26 +0200 Subject: [PATCH 21/63] Refactor - Exit return value --- .../SignUp/app/src/ConnectionSetupCard.Page.al | 1 - .../SignUp/app/src/Processing.Codeunit.al | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionSetupCard.Page.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionSetupCard.Page.al index d49482d7ea..c611fa91ab 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionSetupCard.Page.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionSetupCard.Page.al @@ -206,5 +206,4 @@ page 6380 ConnectionSetupCard IsSaaSInfrastructure: Boolean; ExternalServiceTok: Label 'ExternalServiceConnector', Locked = true; - } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al index 5684cc5b2c..bcd78891bc 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al @@ -193,12 +193,9 @@ codeunit 6388 Processing ErrorDescription: Text; begin if not Connection.CheckDocumentStatus(EDocument, HttpRequestMessage, HttpResponse, true) then - exit(false); - - if DocumentHasErrorOrProcessing(EDocument, HttpResponse, ErrorDescription) then - exit(false); + exit; - exit(true); + exit(not DocumentHasErrorOrProcessing(EDocument, HttpResponse, ErrorDescription)); end; local procedure ParseSendFileResponse(HttpContentResponse: HttpContent): Text From e11508ab8440e305ae019b7cc4367bc7535a866b Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Fri, 27 Sep 2024 14:01:28 +0200 Subject: [PATCH 22/63] Refactor - Move UriTemplates to Global --- .../SignUp/app/src/APIRequests.Codeunit.al | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al index 7daf0c6b99..0fb1b3739b 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al @@ -24,10 +24,9 @@ codeunit 6380 APIRequests ContentHttpHeaders: HttpHeaders; HttpContent: HttpContent; ContentText: Text; - UriTemplateLbl: Label '%1/api/Peppol', Comment = '%1 = Service Url', Locked = true; begin InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); - HttpRequestMessage := PrepareRequestMsg("Http Request Type"::POST, StrSubstNo(UriTemplateLbl, ConnectionSetup.ServiceURL)); + HttpRequestMessage := PrepareRequestMsg("Http Request Type"::POST, StrSubstNo(SendFilePostRequestUriTxt, ConnectionSetup.ServiceURL)); Payload := XmlToTxt(TempBlob); if Payload = '' then @@ -48,10 +47,9 @@ codeunit 6380 APIRequests procedure GetSentDocumentStatus(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var ConnectionSetup: Record ConnectionSetup; - UriTemplateLbl: Label '%1/api/Peppol/status?peppolInstanceId=%2', Comment = '%1 = Service Url, %2 = Document ID', Locked = true; begin InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); - HttpRequestMessage := PrepareRequestMsg("Http Request Type"::GET, StrSubstNo(UriTemplateLbl, ConnectionSetup.ServiceURL, EDocument."Document Id")); + HttpRequestMessage := PrepareRequestMsg("Http Request Type"::GET, StrSubstNo(GetSentDocumentStatusUriTxt, ConnectionSetup.ServiceURL, EDocument."Document Id")); exit(SendRequest(HttpRequestMessage, HttpResponseMessage)); end; @@ -59,10 +57,9 @@ codeunit 6380 APIRequests procedure PatchADocument(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var ConnectionSetup: Record ConnectionSetup; - UriTemplateLbl: Label '%1/api/Peppol/outbox?peppolInstanceId=%2', Comment = '%1 = Service Url, %2 = Document ID', Locked = true; begin InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); - HttpRequestMessage := PrepareRequestMsg("Http Request Type"::PATCH, StrSubstNo(UriTemplateLbl, ConnectionSetup.ServiceURL, EDocument."Document Id")); + HttpRequestMessage := PrepareRequestMsg("Http Request Type"::PATCH, StrSubstNo(PatchADocumentUriTxt, ConnectionSetup.ServiceURL, EDocument."Document Id")); exit(SendRequest(HttpRequestMessage, HttpResponseMessage)); end; @@ -70,10 +67,9 @@ codeunit 6380 APIRequests procedure GetReceivedDocumentsRequest(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage; Parameters: Dictionary of [Text, Text]): Boolean var ConnectionSetup: Record ConnectionSetup; - UriTemplateLbl: Label '%1/api/Peppol/Inbox?peppolId=%2', Comment = '%1 = Service Url, %2 = Peppol Identifier', Locked = true; begin InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); - HttpRequestMessage := PrepareRequestMsg("Http Request Type"::GET, StrSubstNo(UriTemplateLbl, ConnectionSetup.ServiceURL, GetSenderReceiverPrefix() + ConnectionSetup."Company Id")); + HttpRequestMessage := PrepareRequestMsg("Http Request Type"::GET, StrSubstNo(GetReceivedDocumentsUriTxt, ConnectionSetup.ServiceURL, GetSenderReceiverPrefix() + ConnectionSetup."Company Id")); exit(SendRequest(HttpRequestMessage, HttpResponseMessage)); end; @@ -81,10 +77,9 @@ codeunit 6380 APIRequests procedure GetTargetDocumentRequest(DocumentId: Text; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var ConnectionSetup: Record ConnectionSetup; - 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(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); - HttpRequestMessage := PrepareRequestMsg("Http Request Type"::GET, StrSubstNo(UriTemplateLbl, ConnectionSetup.ServiceURL, GetSenderReceiverPrefix() + ConnectionSetup."Company Id", DocumentId)); + HttpRequestMessage := PrepareRequestMsg("Http Request Type"::GET, StrSubstNo(GetTargetDocumentUriTxt, ConnectionSetup.ServiceURL, GetSenderReceiverPrefix() + ConnectionSetup."Company Id", DocumentId)); exit(SendRequest(HttpRequestMessage, HttpResponseMessage)); end; @@ -92,10 +87,9 @@ codeunit 6380 APIRequests procedure PatchReceivedDocument(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var ConnectionSetup: Record ConnectionSetup; - UriTemplateLbl: Label '%1/api/Peppol/inbox?peppolInstanceId=%2', Comment = '%1 = Service Url, %2 = Peppol Gateway Instance', Locked = true; begin InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); - HttpRequestMessage := PrepareRequestMsg("Http Request Type"::PATCH, StrSubstNo(UriTemplateLbl, ConnectionSetup.ServiceURL, EDocument."Document Id")); + HttpRequestMessage := PrepareRequestMsg("Http Request Type"::PATCH, StrSubstNo(PatchReceivedDocumentUriTxt, ConnectionSetup.ServiceURL, EDocument."Document Id")); exit(SendRequest(HttpRequestMessage, HttpResponseMessage)); end; @@ -103,10 +97,9 @@ codeunit 6380 APIRequests var ConnectionSetup: Record ConnectionSetup; Auth: Codeunit Auth; - BaseUrlTxt: Label '%1/api/Registration/init?EntraTenantId=%2', Locked = true; begin InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); - HttpRequestMessage := PrepareRequestMsg("Http Request Type"::POST, StrSubstNo(BaseUrlTxt, Auth.GetRootUrl(), Auth.GetBCInstanceIdentifier())); + HttpRequestMessage := PrepareRequestMsg("Http Request Type"::POST, StrSubstNo(GetMarketPlaceCredentialsUriTxt, Auth.GetRootUrl(), Auth.GetBCInstanceIdentifier())); exit(SendRequest(HttpRequestMessage, HttpResponseMessage, true)); end; @@ -218,4 +211,11 @@ codeunit 6380 APIRequests var MissingSetupErr: Label 'You must set up service integration in the E-Document service card.'; + GetSentDocumentStatusUriTxt: Label '%1/api/Peppol/status?peppolInstanceId=%2', Comment = '%1 = Service Url, %2 = Document ID', Locked = true; + SendFilePostRequestUriTxt: Label '%1/api/Peppol', Comment = '%1 = Service Url', Locked = true; + PatchADocumentUriTxt: Label '%1/api/Peppol/outbox?peppolInstanceId=%2', Comment = '%1 = Service Url, %2 = Document ID', Locked = true; + GetReceivedDocumentsUriTxt: Label '%1/api/Peppol/Inbox?peppolId=%2', Comment = '%1 = Service Url, %2 = Peppol Identifier', Locked = true; + GetTargetDocumentUriTxt: Label '%1/api/Peppol/inbox-document?peppolId=%2&peppolInstanceId=%3', Comment = '%1 = Service Url, %2 = Peppol Identifier, %3 = Peppol Gateway Instance', Locked = true; + PatchReceivedDocumentUriTxt: Label '%1/api/Peppol/inbox?peppolInstanceId=%2', Comment = '%1 = Service Url, %2 = Peppol Gateway Instance', Locked = true; + GetMarketPlaceCredentialsUriTxt: Label '%1/api/Registration/init?EntraTenantId=%2', Locked = true; } \ No newline at end of file From bfca6405e67570f7f2c85daed6127214c56cd9f6 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Fri, 27 Sep 2024 14:21:06 +0200 Subject: [PATCH 23/63] Refactor - Eliminate unneeded calls --- .../SignUp/app/src/Processing.Codeunit.al | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al index bcd78891bc..ef3cb0285b 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al @@ -39,11 +39,11 @@ codeunit 6388 Processing procedure GetDocumentResponse(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean var + ErrorDescription: Text; begin - if not CheckIfDocumentStatusSuccessful(EDocument, HttpRequest, HttpResponse) then - exit(false); - - exit(true); + if not Connection.CheckDocumentStatus(EDocument, HttpRequest, HttpResponse, true) then + exit; + exit(DocumentHasErrorOrProcessing(EDocument, HttpResponse, ErrorDescription)); end; procedure GetDocumentSentResponse(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean @@ -188,16 +188,6 @@ codeunit 6388 Processing exit(JsonManagement.GetCollectionCount()); end; - local procedure CheckIfDocumentStatusSuccessful(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean - var - ErrorDescription: Text; - begin - if not Connection.CheckDocumentStatus(EDocument, HttpRequestMessage, HttpResponse, true) then - exit; - - exit(not DocumentHasErrorOrProcessing(EDocument, HttpResponse, ErrorDescription)); - end; - local procedure ParseSendFileResponse(HttpContentResponse: HttpContent): Text var JsonManagement: Codeunit "JSON Management"; From 1e245932e5e20a481b12631b6838b0a5baa18f15 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Fri, 27 Sep 2024 14:27:19 +0200 Subject: [PATCH 24/63] Refactor - Error when unsupported EDocument Type --- .../EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al index 0fb1b3739b..faa1f49aad 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al @@ -161,6 +161,8 @@ codeunit 6380 APIRequests exit('Invoice'); "E-Document Type"::"Issued Finance Charge Memo", "E-Document Type"::"Issued Reminder": exit('PaymentReminder'); + else + Error(UnSupportedDocumentTypeLbl, EDocument."Document Type"); end; end; @@ -218,4 +220,5 @@ codeunit 6380 APIRequests GetTargetDocumentUriTxt: Label '%1/api/Peppol/inbox-document?peppolId=%2&peppolInstanceId=%3', Comment = '%1 = Service Url, %2 = Peppol Identifier, %3 = Peppol Gateway Instance', Locked = true; PatchReceivedDocumentUriTxt: Label '%1/api/Peppol/inbox?peppolInstanceId=%2', Comment = '%1 = Service Url, %2 = Peppol Gateway Instance', Locked = true; GetMarketPlaceCredentialsUriTxt: Label '%1/api/Registration/init?EntraTenantId=%2', Locked = true; + UnSupportedDocumentTypeLbl: Label 'Document %1 is not supported.', Comment = '%1 = EDocument Type', Locked = true; } \ No newline at end of file From 80274503d1e7dfb7c1c663bcd2d1d13b8e57ac38 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Fri, 27 Sep 2024 14:49:32 +0200 Subject: [PATCH 25/63] Refactor - To use ErrorInfo --- .../SignUp/app/src/APIRequests.Codeunit.al | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al index faa1f49aad..a4541781fc 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al @@ -104,11 +104,18 @@ codeunit 6380 APIRequests 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 - Error(MissingSetupErr); + 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 @@ -212,7 +219,9 @@ codeunit 6380 APIRequests end; var - MissingSetupErr: Label 'You must set up service integration in the E-Document service card.'; + 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'; GetSentDocumentStatusUriTxt: Label '%1/api/Peppol/status?peppolInstanceId=%2', Comment = '%1 = Service Url, %2 = Document ID', Locked = true; SendFilePostRequestUriTxt: Label '%1/api/Peppol', Comment = '%1 = Service Url', Locked = true; PatchADocumentUriTxt: Label '%1/api/Peppol/outbox?peppolInstanceId=%2', Comment = '%1 = Service Url, %2 = Document ID', Locked = true; From 8bd90ac22b1480ae613d501e3bee4def98a326b8 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Fri, 27 Sep 2024 14:57:30 +0200 Subject: [PATCH 26/63] Refactor - Move local labels to global --- .../SignUp/app/src/IntegrationImpl.Codeunit.al | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/IntegrationImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/IntegrationImpl.Codeunit.al index 0b257a5e64..55d28f88d0 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/IntegrationImpl.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/IntegrationImpl.Codeunit.al @@ -20,7 +20,7 @@ codeunit 6386 IntegrationImpl implements "E-Document Integration" procedure SendBatch(var EDocuments: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) begin IsAsync := false; - Error('Batch sending is not supported in this version'); + Error(BatchSendNotSupportedErr); end; procedure GetResponse(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean @@ -35,7 +35,7 @@ codeunit 6386 IntegrationImpl implements "E-Document Integration" procedure Cancel(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean begin - Error('Cancel is not supported in this version'); + Error(CancelNotSupportedErr); end; procedure ReceiveDocument(var TempBlob: Codeunit "Temp Blob"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) @@ -56,4 +56,6 @@ codeunit 6386 IntegrationImpl implements "E-Document Integration" var Processing: Codeunit Processing; + BatchSendNotSupportedErr: Label 'Batch sending is not supported in this version'; + CancelNotSupportedErr: Label 'Cancel is not supported in this version'; } \ No newline at end of file From 896cbe865ec2405ae93405fb052caaa138a2803e Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Fri, 27 Sep 2024 15:06:24 +0200 Subject: [PATCH 27/63] Refactor - No need for Retry --- .../SignUp/app/src/Connection.Codeunit.al | 33 ++++++------------- .../SignUp/app/src/Processing.Codeunit.al | 10 +++--- 2 files changed, 15 insertions(+), 28 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Connection.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Connection.Codeunit.al index 34bcd77c6e..7543cbe345 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Connection.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Connection.Codeunit.al @@ -14,31 +14,23 @@ codeunit 6382 Connection Access = Internal; Permissions = tabledata "E-Document" = m; - procedure HandleSendFilePostRequest(var TempBlob: Codeunit "Temp Blob"; var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage; Retry: Boolean): Boolean + procedure HandleSendFilePostRequest(var TempBlob: Codeunit "Temp Blob"; var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean begin - if not APIRequests.SendFilePostRequest(TempBlob, EDocument, HttpRequest, HttpResponse) then - if Retry then - APIRequests.SendFilePostRequest(TempBlob, EDocument, HttpRequest, HttpResponse); - + APIRequests.SendFilePostRequest(TempBlob, EDocument, HttpRequest, HttpResponse); exit(CheckIfSuccessfulRequest(EDocument, HttpResponse)); end; - procedure CheckDocumentStatus(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage; Retry: Boolean): Boolean + procedure CheckDocumentStatus(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean begin - if not APIRequests.GetSentDocumentStatus(EDocument, HttpRequest, HttpResponse) then - if Retry then - APIRequests.GetSentDocumentStatus(EDocument, HttpRequest, HttpResponse); - + APIRequests.GetSentDocumentStatus(EDocument, HttpRequest, HttpResponse); exit(CheckIfSuccessfulRequest(EDocument, HttpResponse)); end; - procedure GetReceivedDocuments(var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage; Retry: Boolean): Boolean + procedure GetReceivedDocuments(var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean var Parameters: Dictionary of [Text, Text]; begin - if not APIRequests.GetReceivedDocumentsRequest(HttpRequest, HttpResponse, Parameters) then - if Retry then - APIRequests.GetReceivedDocumentsRequest(HttpRequest, HttpResponse, Parameters); + APIRequests.GetReceivedDocumentsRequest(HttpRequest, HttpResponse, Parameters); if not HttpResponse.IsSuccessStatusCode then exit(false); @@ -46,20 +38,15 @@ codeunit 6382 Connection exit(Helpers.ParseJsonString(HttpResponse.Content) <> ''); end; - procedure HandleGetTargetDocumentRequest(DocumentId: Text; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage; Retry: Boolean): Boolean + procedure HandleGetTargetDocumentRequest(DocumentId: Text; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean begin - if not APIRequests.GetTargetDocumentRequest(DocumentId, HttpRequest, HttpResponse) then - if Retry then - APIRequests.GetTargetDocumentRequest(DocumentId, HttpRequest, HttpResponse); - + APIRequests.GetTargetDocumentRequest(DocumentId, HttpRequest, HttpResponse); exit(HttpResponse.IsSuccessStatusCode); end; - procedure RemoveDocumentFromReceived(EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage; Retry: Boolean): Boolean + procedure RemoveDocumentFromReceived(EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean begin - if not APIRequests.PatchReceivedDocument(EDocument, HttpRequest, HttpResponse) then - if Retry then - APIRequests.PatchReceivedDocument(EDocument, HttpRequest, HttpResponse); + APIRequests.PatchReceivedDocument(EDocument, HttpRequest, HttpResponse); exit(HttpResponse.IsSuccessStatusCode); end; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al index ef3cb0285b..d93bac6fe7 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al @@ -41,7 +41,7 @@ codeunit 6388 Processing var ErrorDescription: Text; begin - if not Connection.CheckDocumentStatus(EDocument, HttpRequest, HttpResponse, true) then + if not Connection.CheckDocumentStatus(EDocument, HttpRequest, HttpResponse) then exit; exit(DocumentHasErrorOrProcessing(EDocument, HttpResponse, ErrorDescription)); end; @@ -118,7 +118,7 @@ codeunit 6388 Processing ContentData: Text; OutStream: OutStream; begin - if not Connection.GetReceivedDocuments(HttpRequest, HttpResponse, true) then + if not Connection.GetReceivedDocuments(HttpRequest, HttpResponse) then exit; HttpResponse.Content.ReadAs(ContentData); @@ -142,7 +142,7 @@ codeunit 6388 Processing var HttpContentResponse: HttpContent; begin - Connection.HandleSendFilePostRequest(TempBlob, EDocument, HttpRequest, HttpResponse, true); + Connection.HandleSendFilePostRequest(TempBlob, EDocument, HttpRequest, HttpResponse); HttpContentResponse := HttpResponse.Content; SetEDocumentFileID(EDocument."Entry No", ParseSendFileResponse(HttpContentResponse)); end; @@ -319,7 +319,7 @@ codeunit 6388 Processing exit; end; - Connection.HandleGetTargetDocumentRequest(DocumentId, LocalHttpRequest, LocalHttpResponse, false); + Connection.HandleGetTargetDocumentRequest(DocumentId, LocalHttpRequest, LocalHttpResponse); EDocumentLogHelper.InsertIntegrationLog(EDocument, EDocumentService, LocalHttpRequest, LocalHttpResponse); LocalHttpResponse.Content.ReadAs(ContentData); @@ -335,7 +335,7 @@ codeunit 6388 Processing DocumentOutStream.WriteText(ContentData); EDocument."Document Id" := CopyStr(DocumentId, 1, MaxStrLen(EDocument."Document Id")); EDocumentLogHelper.InsertLog(EDocument, EDocumentService, TempBlob, "E-Document Service Status"::Imported); - Connection.RemoveDocumentFromReceived(EDocument, LocalHttpRequest, LocalHttpResponse, true); + Connection.RemoveDocumentFromReceived(EDocument, LocalHttpRequest, LocalHttpResponse); EDocumentLogHelper.InsertIntegrationLog(EDocument, EDocumentService, LocalHttpRequest, LocalHttpResponse); end; From a12493f4d55c3f0e3898f628e4082e634bdfdc90 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Fri, 27 Sep 2024 16:45:52 +0200 Subject: [PATCH 28/63] Refactor - Make labels Global --- .../SignUp/app/src/APIRequests.Codeunit.al | 3 +-- .../SignUp/app/src/Auth.Codeunit.al | 11 ++++------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al index a4541781fc..8e86fb5bda 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al @@ -212,8 +212,6 @@ codeunit 6380 APIRequests end; local procedure GetSenderReceiverPrefix(): Text - var - SenderReceiverPrefixLbl: Label 'iso6523-actorid-upis::', Locked = true; begin exit(SenderReceiverPrefixLbl); end; @@ -230,4 +228,5 @@ codeunit 6380 APIRequests PatchReceivedDocumentUriTxt: Label '%1/api/Peppol/inbox?peppolInstanceId=%2', Comment = '%1 = Service Url, %2 = Peppol Gateway Instance', Locked = true; GetMarketPlaceCredentialsUriTxt: Label '%1/api/Registration/init?EntraTenantId=%2', Locked = true; UnSupportedDocumentTypeLbl: Label 'Document %1 is not supported.', Comment = '%1 = EDocument Type', Locked = true; + SenderReceiverPrefixLbl: Label 'iso6523-actorid-upis::', Locked = true; } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Auth.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Auth.Codeunit.al index 035d32ef13..984108a704 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Auth.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Auth.Codeunit.al @@ -25,10 +25,8 @@ codeunit 6381 Auth end; procedure GetRootOnboardingUrl(): Text - var - UrlTxt: Label '%1/supm/landingpage?EntraTenantId=%2', Comment = '%1 = Root Market URL, %2 = BC Instance Identifier', Locked = true; begin - exit(StrSubstNo(UrlTxt, GetRootUrl(), GetBCInstanceIdentifier())); + exit(GetRootUrl() + '/supm/landingpage?EntraTenantId=' + GetBCInstanceIdentifier()); end; [NonDebuggable] @@ -39,7 +37,6 @@ codeunit 6381 Auth JText: Text; ClientId: Text; ClientSecret: SecretText; - ErrorUnableToCreateClientCredentialsLbl: Label 'Unable to create client credentials.'; begin if not GetClientCredentials(HttpRequestMessage, HttpResponseMessage) then Error(ErrorUnableToCreateClientCredentialsLbl); @@ -86,8 +83,6 @@ codeunit 6381 Auth end; procedure GetRootAuthBearerToken() ReturnValue: SecretText; - var - ErrorTokenLbl: Label 'Unable to fetch a root token.'; begin if not GetRootAccessToken(ReturnValue) then Error(ErrorTokenLbl); @@ -138,7 +133,6 @@ codeunit 6381 Auth HttpContent: HttpContent; HttpHeaders: HttpHeaders; ContentText: SecretText; - ContentTemplateTxt: Label 'grant_type=client_credentials&client_id=%1&client_secret=%2&resource=%3', Locked = true; JText: Text; begin ConnectionSetup.GetRecordOnce(); @@ -323,4 +317,7 @@ codeunit 6381 Auth AuthURLTxt: Label 'https://login.microsoftonline.com/%1/oauth2/token', Comment = '%1 Entra Tenant Id', Locked = true; ProdTenantIdTxt: Label '0d725623-dc26-484f-a090-b09d2003d092', Locked = true; ProdServiceAPITxt: Label 'https://edoc.exflow.io', Locked = true; + ContentTemplateTxt: Label 'grant_type=client_credentials&client_id=%1&client_secret=%2&resource=%3', Locked = true; + ErrorTokenLbl: Label 'Unable to fetch a root token.'; + ErrorUnableToCreateClientCredentialsLbl: Label 'Unable to create client credentials.'; } \ No newline at end of file From ea3a35e1d62d3b0a63e40a3d91bf70f7f405e6ed Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Fri, 27 Sep 2024 17:00:40 +0200 Subject: [PATCH 29/63] Refactor - Remove labels, API path inline the Avalara way --- .../SignUp/app/src/APIRequests.Codeunit.al | 21 +++++++------------ 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al index 8e86fb5bda..a17bd2d256 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al @@ -26,7 +26,7 @@ codeunit 6380 APIRequests ContentText: Text; begin InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); - HttpRequestMessage := PrepareRequestMsg("Http Request Type"::POST, StrSubstNo(SendFilePostRequestUriTxt, ConnectionSetup.ServiceURL)); + HttpRequestMessage := PrepareRequestMsg("Http Request Type"::POST, ConnectionSetup.ServiceURL + '/api/Peppol'); Payload := XmlToTxt(TempBlob); if Payload = '' then @@ -49,7 +49,7 @@ codeunit 6380 APIRequests ConnectionSetup: Record ConnectionSetup; begin InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); - HttpRequestMessage := PrepareRequestMsg("Http Request Type"::GET, StrSubstNo(GetSentDocumentStatusUriTxt, ConnectionSetup.ServiceURL, EDocument."Document Id")); + HttpRequestMessage := PrepareRequestMsg("Http Request Type"::GET, ConnectionSetup.ServiceURL + '/api/Peppol/status?peppolInstanceId=' + EDocument."Document Id"); exit(SendRequest(HttpRequestMessage, HttpResponseMessage)); end; @@ -59,7 +59,7 @@ codeunit 6380 APIRequests ConnectionSetup: Record ConnectionSetup; begin InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); - HttpRequestMessage := PrepareRequestMsg("Http Request Type"::PATCH, StrSubstNo(PatchADocumentUriTxt, ConnectionSetup.ServiceURL, EDocument."Document Id")); + HttpRequestMessage := PrepareRequestMsg("Http Request Type"::PATCH, ConnectionSetup.ServiceURL + '/api/Peppol/outbox?peppolInstanceId=' + EDocument."Document Id"); exit(SendRequest(HttpRequestMessage, HttpResponseMessage)); end; @@ -69,7 +69,7 @@ codeunit 6380 APIRequests ConnectionSetup: Record ConnectionSetup; begin InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); - HttpRequestMessage := PrepareRequestMsg("Http Request Type"::GET, StrSubstNo(GetReceivedDocumentsUriTxt, ConnectionSetup.ServiceURL, GetSenderReceiverPrefix() + ConnectionSetup."Company Id")); + HttpRequestMessage := PrepareRequestMsg("Http Request Type"::GET, ConnectionSetup.ServiceURL + '/api/Peppol/Inbox?peppolId=' + GetSenderReceiverPrefix() + ConnectionSetup."Company Id"); exit(SendRequest(HttpRequestMessage, HttpResponseMessage)); end; @@ -79,7 +79,7 @@ codeunit 6380 APIRequests ConnectionSetup: Record ConnectionSetup; begin InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); - HttpRequestMessage := PrepareRequestMsg("Http Request Type"::GET, StrSubstNo(GetTargetDocumentUriTxt, ConnectionSetup.ServiceURL, GetSenderReceiverPrefix() + ConnectionSetup."Company Id", DocumentId)); + HttpRequestMessage := PrepareRequestMsg("Http Request Type"::GET, ConnectionSetup.ServiceURL + '/api/Peppol/inbox-document?peppolId=' + GetSenderReceiverPrefix() + ConnectionSetup."Company Id" + '&peppolInstanceId=' + DocumentId); exit(SendRequest(HttpRequestMessage, HttpResponseMessage)); end; @@ -89,7 +89,7 @@ codeunit 6380 APIRequests ConnectionSetup: Record ConnectionSetup; begin InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); - HttpRequestMessage := PrepareRequestMsg("Http Request Type"::PATCH, StrSubstNo(PatchReceivedDocumentUriTxt, ConnectionSetup.ServiceURL, EDocument."Document Id")); + HttpRequestMessage := PrepareRequestMsg("Http Request Type"::PATCH, ConnectionSetup.ServiceURL + '/api/Peppol/inbox?peppolInstanceId=' + EDocument."Document Id"); exit(SendRequest(HttpRequestMessage, HttpResponseMessage)); end; @@ -99,7 +99,7 @@ codeunit 6380 APIRequests Auth: Codeunit Auth; begin InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); - HttpRequestMessage := PrepareRequestMsg("Http Request Type"::POST, StrSubstNo(GetMarketPlaceCredentialsUriTxt, Auth.GetRootUrl(), Auth.GetBCInstanceIdentifier())); + HttpRequestMessage := PrepareRequestMsg("Http Request Type"::POST, Auth.GetRootUrl() + '/api/Registration/init?EntraTenantId=' + Auth.GetBCInstanceIdentifier()); exit(SendRequest(HttpRequestMessage, HttpResponseMessage, true)); end; @@ -220,13 +220,6 @@ codeunit 6380 APIRequests 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'; - GetSentDocumentStatusUriTxt: Label '%1/api/Peppol/status?peppolInstanceId=%2', Comment = '%1 = Service Url, %2 = Document ID', Locked = true; - SendFilePostRequestUriTxt: Label '%1/api/Peppol', Comment = '%1 = Service Url', Locked = true; - PatchADocumentUriTxt: Label '%1/api/Peppol/outbox?peppolInstanceId=%2', Comment = '%1 = Service Url, %2 = Document ID', Locked = true; - GetReceivedDocumentsUriTxt: Label '%1/api/Peppol/Inbox?peppolId=%2', Comment = '%1 = Service Url, %2 = Peppol Identifier', Locked = true; - GetTargetDocumentUriTxt: Label '%1/api/Peppol/inbox-document?peppolId=%2&peppolInstanceId=%3', Comment = '%1 = Service Url, %2 = Peppol Identifier, %3 = Peppol Gateway Instance', Locked = true; - PatchReceivedDocumentUriTxt: Label '%1/api/Peppol/inbox?peppolInstanceId=%2', Comment = '%1 = Service Url, %2 = Peppol Gateway Instance', Locked = true; - GetMarketPlaceCredentialsUriTxt: Label '%1/api/Registration/init?EntraTenantId=%2', Locked = true; UnSupportedDocumentTypeLbl: Label 'Document %1 is not supported.', Comment = '%1 = EDocument Type', Locked = true; SenderReceiverPrefixLbl: Label 'iso6523-actorid-upis::', Locked = true; } \ No newline at end of file From e991757c8afd53304bad7f816fc6c26d78ed009e Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Mon, 30 Sep 2024 11:29:33 +0200 Subject: [PATCH 30/63] Refactor - Correct Telemetry Token --- .../SignUp/app/src/ConnectionSetupCard.Page.al | 3 +-- .../EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionSetupCard.Page.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionSetupCard.Page.al index c611fa91ab..859575abb5 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionSetupCard.Page.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionSetupCard.Page.al @@ -204,6 +204,5 @@ page 6380 ConnectionSetupCard [NonDebuggable] ClientID, ClientSecret, ClientTenant, ClientUrl, RootID, RootSecret, RootTenant, RootUrl : Text; IsSaaSInfrastructure: Boolean; - ExternalServiceTok: Label 'ExternalServiceConnector', Locked = true; - + ExternalServiceTok: Label 'E-Document - SignUp', Locked = true; } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al index d93bac6fe7..6dfed28e56 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al @@ -556,5 +556,5 @@ codeunit 6388 Processing GetApprovalCheckStatusErr: Label 'You cannot ask for approval with the E-Document in this current status %1. You can request for approval when E-document status is Sent or Pending Response.', Comment = '%1 - Status'; CouldNotRetrieveDocumentErr: Label 'Could not retrieve document with id: %1 from the service', Comment = '%1 - Document ID'; DocumentIdNotFoundErr: Label 'Document ID not found in response'; - ExternalServiceTok: Label 'ExternalServiceConnector', Locked = true; + ExternalServiceTok: Label 'E-Document - SignUp', Locked = true; } \ No newline at end of file From a8c547d84f8e9d344b4dcf1fcb756031873e7952 Mon Sep 17 00:00:00 2001 From: Stefan Lindberg Date: Tue, 1 Oct 2024 09:39:31 +0200 Subject: [PATCH 31/63] Refactor - Fix bug introduced during refactoring, Rename procedure to more logical name --- .../EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al index 6dfed28e56..df0dd30acd 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al @@ -43,7 +43,7 @@ codeunit 6388 Processing begin if not Connection.CheckDocumentStatus(EDocument, HttpRequest, HttpResponse) then exit; - exit(DocumentHasErrorOrProcessing(EDocument, HttpResponse, ErrorDescription)); + exit(not DocumentHasErrorOrStillInProcessing(EDocument, HttpResponse, ErrorDescription)); end; procedure GetDocumentSentResponse(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean @@ -218,7 +218,7 @@ codeunit 6388 Processing EDocument.Modify(); end; - local procedure DocumentHasErrorOrProcessing(EDocument: Record "E-Document"; HttpResponse: HttpResponseMessage; var ErrorDescription: Text): Boolean + local procedure DocumentHasErrorOrStillInProcessing(EDocument: Record "E-Document"; HttpResponse: HttpResponseMessage; var ErrorDescription: Text): Boolean var EDocumentService: Record "E-Document Service"; EDocumentServiceStatus: Record "E-Document Service Status"; From 2ebc70d71e69b8d1c6f3f995d74c4dd25f51b99b Mon Sep 17 00:00:00 2001 From: geschwint Date: Mon, 28 Oct 2024 14:09:10 +0100 Subject: [PATCH 32/63] Refactor Rename --- .../app/src/{Auth.Codeunit.al => Authentication.Codeunit.al} | 0 .../app/src/{Helpers.Codeunit.al => HelpersImpl.Codeunit.al} | 0 .../src/{Extensions => Integration}/IntegrationEnumExt.EnumExt.al | 0 .../SignUp/app/src/{ => Integration}/IntegrationImpl.Codeunit.al | 0 .../GetReadyStatusJob.Codeunit.al} | 0 .../src/{PatchSent.Codeunit.al => Jobs/PatchSentJob.Codeunit.al} | 0 .../SignUp/app/src/{ => Setup}/ConnectionSetup.Table.al | 0 .../SignUp/app/src/{ => Setup}/ConnectionSetupCard.Page.al | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename Apps/W1/EDocumentConnectors/SignUp/app/src/{Auth.Codeunit.al => Authentication.Codeunit.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/{Helpers.Codeunit.al => HelpersImpl.Codeunit.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/{Extensions => Integration}/IntegrationEnumExt.EnumExt.al (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/{ => Integration}/IntegrationImpl.Codeunit.al (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/{GetReadyStatus.Codeunit.al => Jobs/GetReadyStatusJob.Codeunit.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/{PatchSent.Codeunit.al => Jobs/PatchSentJob.Codeunit.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/{ => Setup}/ConnectionSetup.Table.al (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/{ => Setup}/ConnectionSetupCard.Page.al (100%) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Auth.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Authentication.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Auth.Codeunit.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Authentication.Codeunit.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Helpers.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/HelpersImpl.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Helpers.Codeunit.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/HelpersImpl.Codeunit.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Extensions/IntegrationEnumExt.EnumExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/IntegrationEnumExt.EnumExt.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Extensions/IntegrationEnumExt.EnumExt.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/IntegrationEnumExt.EnumExt.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/IntegrationImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/IntegrationImpl.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/IntegrationImpl.Codeunit.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/IntegrationImpl.Codeunit.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/GetReadyStatus.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/GetReadyStatusJob.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/GetReadyStatus.Codeunit.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/GetReadyStatusJob.Codeunit.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/PatchSent.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/PatchSentJob.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/PatchSent.Codeunit.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/PatchSentJob.Codeunit.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionSetup.Table.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetup.Table.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionSetup.Table.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetup.Table.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionSetupCard.Page.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetupCard.Page.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionSetupCard.Page.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetupCard.Page.al From 7166b2469dede735566c002854f136a8ae1fc7b1 Mon Sep 17 00:00:00 2001 From: geschwint Date: Mon, 28 Oct 2024 14:10:48 +0100 Subject: [PATCH 33/63] Refactor Delete Objects --- .../SignUp/app/src/ConnectionAuth.Table.al | 57 ------------------- .../SignUp/app/src/ErrorSensitive.Codeunit.al | 54 ------------------ .../SignUp/app/src/SendMode.Enum.al | 19 ------- 3 files changed, 130 deletions(-) delete mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionAuth.Table.al delete mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/ErrorSensitive.Codeunit.al delete mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/SendMode.Enum.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionAuth.Table.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionAuth.Table.al deleted file mode 100644 index e1cc465a0b..0000000000 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionAuth.Table.al +++ /dev/null @@ -1,57 +0,0 @@ -// ------------------------------------------------------------------------------------------------ -// 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; - -table 6380 ConnectionAuth -{ - Access = Internal; - - fields - { - field(1; PK; Code[10]) - { - DataClassification = CustomerContent; - } - field(2; "Access Token"; Guid) - { - Caption = 'Access Token'; - DataClassification = CustomerContent; - } - field(3; "Refresh Token"; Guid) - { - Caption = 'Refresh Token'; - DataClassification = CustomerContent; - } - field(30; "Token Timestamp"; DateTime) - { - Caption = 'Token Timestamp'; - DataClassification = CustomerContent; - } - } - - keys - { - key(Key1; PK) - { - Clustered = true; - } - } - - var - RecordHasBeenRead: Boolean; - - procedure GetRecordOnce(): Boolean - begin - if RecordHasBeenRead then - exit(RecordHasBeenRead); - Clear(Rec); - RecordHasBeenRead := Get(); - if not RecordHasBeenRead then begin - Insert(); - RecordHasBeenRead := Get(); - end; - exit(RecordHasBeenRead); - end; -} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/ErrorSensitive.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/ErrorSensitive.Codeunit.al deleted file mode 100644 index 25eafdafe4..0000000000 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/ErrorSensitive.Codeunit.al +++ /dev/null @@ -1,54 +0,0 @@ -// ------------------------------------------------------------------------------------------------ -// 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 System.Azure.Identity; - -codeunit 6383 ErrorSensitive -{ - Access = Internal; - Description = 'Create functions to run sensitive code that may fail out of your control but you need to keep the code going'; - - trigger OnRun() - begin - case gParameter of - 'AADDETAILS': - TryGetAADDetails(); - end; - end; - - // - // Error prone function(s) - // - local procedure TryGetAADDetails() - begin - gResult1 := AzureADTenant.GetAadTenantId(); - gResult2 := AzureADTenant.GetAadTenantDomainName(); - end; - - // - // Generic Get/Set methods to communicate before and after try-catch - // - procedure SetParameter(Parameter: Text) - begin - gParameter := Parameter; - end; - - procedure GetFirstResult(): Text; - begin - exit(gResult1); - end; - - procedure GetSecondResult(): Text; - begin - exit(gResult2); - end; - - var - AzureADTenant: Codeunit "Azure AD Tenant"; - gParameter: Text; - gResult1: Text; - gResult2: Text; -} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SendMode.Enum.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SendMode.Enum.al deleted file mode 100644 index 8dd530ae19..0000000000 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SendMode.Enum.al +++ /dev/null @@ -1,19 +0,0 @@ -// ------------------------------------------------------------------------------------------------ -// 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; - -enum 6380 SendMode -{ - Access = Internal; - - value(0; Production) - { - Caption = 'Production', Locked = true; - } - value(1; Test) - { - Caption = 'Test', Locked = true; - } -} \ No newline at end of file From fb7b4c8373dfd1fe9aaf482f3583e9dcd9a24066 Mon Sep 17 00:00:00 2001 From: geschwint Date: Mon, 28 Oct 2024 14:11:45 +0100 Subject: [PATCH 34/63] Refactor New Objects --- .../app/src/APIRequestsImpl.Codeunit.al | 286 +++++++++ .../app/src/AuthenticationImpl.Codeunit.al | 344 +++++++++++ .../SignUp/app/src/ConnectionImpl.Codeunit.al | 116 ++++ .../app/src/Jobs/JobHelperImpl.Codeunit.al | 83 +++ .../SignUp/app/src/ProcessingImpl.Codeunit.al | 580 ++++++++++++++++++ .../app/src/Setup/EnvironmentType.Enum.al | 20 + 6 files changed, 1429 insertions(+) create mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequestsImpl.Codeunit.al create mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/AuthenticationImpl.Codeunit.al create mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionImpl.Codeunit.al create mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/JobHelperImpl.Codeunit.al create mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/ProcessingImpl.Codeunit.al create mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/EnvironmentType.Enum.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequestsImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequestsImpl.Codeunit.al new file mode 100644 index 0000000000..bb47a40cff --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequestsImpl.Codeunit.al @@ -0,0 +1,286 @@ +// ------------------------------------------------------------------------------------------------ +// 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 6389 APIRequestsImpl +{ + Access = Internal; + InherentEntitlements = X; + InherentPermissions = X; + + #region variables + + var + MissingSetupErr: Label 'Connection Setup is missing'; + MissingSetupMessageErr: Label 'You must set up service integration in the e-document service card.'; + MissingSetupNavigationActionErr: Label 'Show E-Document Services'; + UnSupportedDocumentTypeTxt: Label 'Document %1 is not supported.', Comment = '%1 = EDocument Type', Locked = true; + SenderReceiverPrefixTxt: Label 'iso6523-actorid-upis::', Locked = true; + ContentTypeTxt: Label 'Content-Type', Locked = true; + ApplicationJsonTxt: Label 'application/json', Locked = true; + AuthorizationTxt: Label 'Authorization', Locked = true; + AcceptTxt: Label 'Accept', Locked = true; + AllTxt: Label '*/*', Locked = true; + ApplicationResponseTxt: Label 'ApplicationResponse', Locked = true; + InvoiceTxt: Label 'Invoice', Locked = true; + PaymentReminderTxt: Label 'PaymentReminder', Locked = true; + DocumentTypeTxt: Label 'documentType', Locked = true; + ReceiverTxt: Label 'receiver', Locked = true; + SenderTxt: Label 'sender', Locked = true; + SenderCountryCodeTxt: Label 'senderCountryCode', Locked = true; + DocumentIdTxt: Label 'documentId', Locked = true; + DocumentIdValueTxt: Label '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', Locked = true; + DocumentIdSchemeTxt: Label 'documentIdScheme', Locked = true; + BusdoxDocIdQNSTxt: Label 'busdox-docid-qns', Locked = true; + ProcessIdTxt: Label 'processId', Locked = true; + ProcessIdValueTxt: Label 'urn:fdc:peppol.eu:2017:poacc:billing:01:1.0', Locked = true; + ProcessIdSchemeTxt: Label 'processIdScheme', Locked = true; + ProcessIdSchemeValueTxt: Label 'cenbii-procid-ubl', Locked = true; + SendModeTxt: Label 'sendMode', Locked = true; + DocumentTxt: Label 'document', Locked = true; + + #endregion + + #region public methods + + // https:///api/Peppol + procedure SendFilePostRequest(var TempBlob: Codeunit "Temp Blob"; EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + ConnectionSetup: Record ConnectionSetup; + HttpContent: HttpContent; + Payload: Text; + begin + Payload := this.XmlToTxt(TempBlob); + if Payload = '' then + exit; + + this.InitRequest(HttpRequestMessage, HttpResponseMessage); + ConnectionSetup.SetLoadFields("Company Id", "Environment Type", ServiceURL); + this.GetSetup(ConnectionSetup); + + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::POST, ConnectionSetup.ServiceURL + '/api/Peppol'); + this.PrepareContent(HttpContent, Payload, EDocument, ConnectionSetup); + HttpRequestMessage.Content(HttpContent); + exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); + end; + + // https:///api/Peppol/status?peppolInstanceId= + procedure GetSentDocumentStatus(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + ConnectionSetup: Record ConnectionSetup; + begin + this.InitRequest(HttpRequestMessage, HttpResponseMessage); + ConnectionSetup.SetLoadFields(ServiceURL); + this.GetSetup(ConnectionSetup); + + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::GET, ConnectionSetup.ServiceURL + '/api/Peppol/status?peppolInstanceId=' + EDocument."Document Id"); + exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); + end; + + // https:///api/Peppol/outbox?peppolInstanceId= + procedure PatchDocument(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + ConnectionSetup: Record ConnectionSetup; + begin + this.InitRequest(HttpRequestMessage, HttpResponseMessage); + ConnectionSetup.SetLoadFields(ServiceURL); + this.GetSetup(ConnectionSetup); + + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::PATCH, ConnectionSetup.ServiceURL + '/api/Peppol/outbox?peppolInstanceId=' + EDocument."Document Id"); + exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); + end; + + // https:///api/Peppol/Inbox?peppolId= + procedure GetReceivedDocumentsRequest(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + ConnectionSetup: Record ConnectionSetup; + begin + this.InitRequest(HttpRequestMessage, HttpResponseMessage); + ConnectionSetup.SetLoadFields(ServiceURL, "Company Id"); + this.GetSetup(ConnectionSetup); + + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::GET, ConnectionSetup.ServiceURL + '/api/Peppol/Inbox?peppolId=' + this.SenderReceiverPrefixTxt + ConnectionSetup."Company Id"); + exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); + end; + + // https:///api/Peppol/inbox-document?peppolId= + procedure GetTargetDocumentRequest(DocumentId: Text; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + ConnectionSetup: Record ConnectionSetup; + begin + this.InitRequest(HttpRequestMessage, HttpResponseMessage); + ConnectionSetup.SetLoadFields(ServiceURL, "Company Id"); + this.GetSetup(ConnectionSetup); + + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::GET, ConnectionSetup.ServiceURL + '/api/Peppol/inbox-document?peppolId=' + this.SenderReceiverPrefixTxt + ConnectionSetup."Company Id" + '&peppolInstanceId=' + DocumentId); + exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); + end; + + // https:///api/Peppol/inbox?peppolInstanceId= + procedure PatchReceivedDocument(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + ConnectionSetup: Record ConnectionSetup; + begin + this.InitRequest(HttpRequestMessage, HttpResponseMessage); + ConnectionSetup.SetLoadFields(ServiceURL); + this.GetSetup(ConnectionSetup); + + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::PATCH, ConnectionSetup.ServiceURL + '/api/Peppol/inbox?peppolInstanceId=' + EDocument."Document Id"); + exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); + end; + + procedure GetMarketPlaceCredentials(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + Authentication: Codeunit Authentication; + begin + this.InitRequest(HttpRequestMessage, HttpResponseMessage); + + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::POST, Authentication.GetRootUrl() + '/api/Registration/init?EntraTenantId=' + Authentication.GetBCInstanceIdentifier()); + exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage, true)); + end; + + #endregion + + #region local methods + + local procedure InitRequest(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) + begin + Clear(HttpRequestMessage); + Clear(HttpResponseMessage); + end; + + local procedure GetSetup(var ConnectionSetup: Record ConnectionSetup) + var + MissingSetupErrorInfo: ErrorInfo; + begin + if not IsNullGuid(ConnectionSetup.SystemId) then + exit; + + if not ConnectionSetup.Get() then begin + MissingSetupErrorInfo.Title := this.MissingSetupErr; + MissingSetupErrorInfo.Message := this.MissingSetupMessageErr; + MissingSetupErrorInfo.PageNo := Page::"E-Document Services"; + MissingSetupErrorInfo.AddNavigationAction(this.MissingSetupNavigationActionErr); + Error(MissingSetupErrorInfo); + end; + end; + + local procedure PrepareContent(var HttpContent: HttpContent; Payload: Text; EDocument: Record "E-Document"; ConnectionSetup: Record ConnectionSetup) + var + ContentText: Text; + HttpHeaders: HttpHeaders; + begin + Clear(HttpContent); + ContentText := this.PrepareContentForSend(this.GetDocumentType(EDocument), ConnectionSetup."Company Id", this.GetCustomerID(EDocument), this.GetSenderCountryCode(), Payload, ConnectionSetup."Environment Type"); + HttpContent.WriteFrom(ContentText); + HttpContent.GetHeaders(HttpHeaders); + if HttpHeaders.Contains(this.ContentTypeTxt) then + HttpHeaders.Remove(this.ContentTypeTxt); + HttpHeaders.Add(this.ContentTypeTxt, this.ApplicationJsonTxt); + end; + + local procedure SendRequest(HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + begin + this.SendRequest(HttpRequestMessage, HttpResponseMessage, false); + end; + + local procedure SendRequest(HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage; RootRequest: Boolean): Boolean + var + Authentication: Codeunit Authentication; + HttpClient: HttpClient; + HttpHeaders: HttpHeaders; + begin + HttpRequestMessage.GetHeaders(HttpHeaders); + if RootRequest then + HttpHeaders.Add(this.AuthorizationTxt, Authentication.GetRootBearerAuthToken()) + else + HttpHeaders.Add(this.AuthorizationTxt, Authentication.GetBearerAuthToken()); + exit(HttpClient.Send(HttpRequestMessage, HttpResponseMessage)); + end; + + local procedure PrepareRequestMsg(HttpRequestType: Enum "Http Request Type"; Uri: Text) RequestMessage: HttpRequestMessage + var + HttpHeaders: HttpHeaders; + begin + RequestMessage.Method(Format(HttpRequestType)); + RequestMessage.SetRequestUri(Uri); + RequestMessage.GetHeaders(HttpHeaders); + HttpHeaders.Add(this.AcceptTxt, this.AllTxt); + end; + + local procedure XmlToTxt(var TempBlob: Codeunit "Temp Blob"): Text + var + XMLDOMManagement: Codeunit "XML DOM Management"; + Content: Text; + begin + XMLDOMManagement.TryGetXMLAsText(TempBlob.CreateInStream(TextEncoding::UTF8), Content); + exit(Content); + end; + + local procedure GetDocumentType(EDocument: Record "E-Document"): Text + begin + if EDocument.Direction = EDocument.Direction::Incoming then + exit(this.ApplicationResponseTxt); + + 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(this.InvoiceTxt); + "E-Document Type"::"Issued Finance Charge Memo", "E-Document Type"::"Issued Reminder": + exit(this.PaymentReminderTxt); + else + Error(this.UnSupportedDocumentTypeTxt, EDocument."Document Type"); + end; + end; + + local procedure GetCustomerID(EDocument: Record "E-Document"): Text[50] + var + Customer: Record Customer; + begin + Customer.SetLoadFields("Service Participant Id"); + 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.SetLoadFields("Country/Region Code"); + 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 EnvironmentType): Text + var + Base64Convert: Codeunit "Base64 Convert"; + JsonObject: JsonObject; + ContentText: Text; + begin + JsonObject.Add(this.DocumentTypeTxt, DocumentType); + JsonObject.Add(this.ReceiverTxt, this.SenderReceiverPrefixTxt + RecieverCompanyID); + JsonObject.Add(this.SenderTxt, this.SenderReceiverPrefixTxt + SendingCompanyID); + JsonObject.Add(this.SenderCountryCodeTxt, SenderCountryCode); + JsonObject.Add(this.DocumentIdTxt, this.DocumentIdValueTxt); + JsonObject.Add(this.DocumentIdSchemeTxt, this.BusdoxDocIdQNSTxt); + JsonObject.Add(this.ProcessIdTxt, this.ProcessIdValueTxt); + JsonObject.Add(this.ProcessIdSchemeTxt, this.ProcessIdSchemeValueTxt); + JsonObject.Add(this.SendModeTxt, Format(SendMode)); + JsonObject.Add(this.DocumentTxt, Base64Convert.ToBase64(Payload)); + JsonObject.WriteTo(ContentText); + exit(ContentText); + end; + + #endregion +} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/AuthenticationImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/AuthenticationImpl.Codeunit.al new file mode 100644 index 0000000000..eb67cae275 --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/AuthenticationImpl.Codeunit.al @@ -0,0 +1,344 @@ +// ------------------------------------------------------------------------------------------------ +// 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 System.Azure.KeyVault; +using System.Environment; +using System.Security.Authentication; +using System.Azure.Identity; + +codeunit 6390 AuthenticationImpl +{ + Access = Internal; + InherentEntitlements = X; + InherentPermissions = X; + + #region variables + var + ConnectionSetup: Record ConnectionSetup; + HelpersImpl: Codeunit HelpersImpl; + BearerTxt: Label 'Bearer %1', Comment = '%1 = text value', Locked = true; + AuthURLTxt: Label 'https://login.microsoftonline.com/%1/oauth2/token', Comment = '%1 Entra Tenant Id', Locked = true; + ProdTenantIdTxt: Label '0d725623-dc26-484f-a090-b09d2003d092', Locked = true; + ProdServiceAPITxt: Label 'https://edoc.exflow.io', Locked = true; + ErrorTokenLbl: Label 'Unable to fetch a root token.'; + ErrorUnableToCreateClientCredentialsLbl: Label 'Unable to create client credentials.'; + ClientIdTxt: Label 'clientId', Locked = true; + ClientSecretTxt: Label 'clientSecret', Locked = true; + SignupRootUrlTxt: Label 'signup-root-url', Locked = true; + RootIdTxt: Label '-root-id', Locked = true; + SignUpRootSecretTxt: Label 'signup-root-secret', Locked = true; + SignUpRootTenantTxt: Label 'signup-root-tenant', Locked = true; + SignUpAccessTokenKeyTxt: Label '{E45BB975-E67B-4A87-AC24-D409A5EF8301}', Locked = true; + + #endregion + + #region public methods + + procedure InitConnectionSetup() + begin + if this.ConnectionSetup.Get() then + exit; + + this.ConnectionSetup."Authentication URL" := this.AuthURLTxt; + this.ConnectionSetup.ServiceURL := this.ProdServiceAPITxt; + this.StorageSet(this.ConnectionSetup."Client Tenant", this.ProdTenantIdTxt); + this.ConnectionSetup.Insert(); + end; + + procedure GetRootOnboardingUrl(): Text + begin + exit(this.GetRootUrl() + '/supm/landingpage?EntraTenantId=' + this.GetBCInstanceIdentifier()); + end; + + [NonDebuggable] + procedure CreateClientCredentials() + var + HttpRequestMessage: HttpRequestMessage; + HttpResponseMessage: HttpResponseMessage; + ClientId, Response : Text; + ClientSecret: SecretText; + begin + if not this.GetClientCredentials(HttpRequestMessage, HttpResponseMessage) then + Error(this.ErrorUnableToCreateClientCredentialsLbl); + + if not HttpResponseMessage.Content.ReadAs(Response) then + exit; + + ClientId := this.HelpersImpl.GetJsonValueFromText(Response, this.ClientIdTxt); + ClientSecret := this.HelpersImpl.GetJsonValueFromText(Response, this.ClientSecretTxt); + + if (ClientId <> '') and (not ClientSecret.IsEmpty()) then + this.SaveClientCredentials(ClientId, ClientSecret); + end; + + procedure GetBearerAuthToken(): SecretText; + begin + exit(SecretStrSubstNo(this.BearerTxt, this.GetAuthToken())); + end; + + procedure GetRootBearerAuthToken(): SecretText; + begin + exit(SecretStrSubstNo(this.BearerTxt, this.GetRootAuthToken())); + end; + + [NonDebuggable] + procedure StorageSet(var TokenKey: Guid; Value: Text): Boolean + var + ModuleDataScope: DataScope; + begin + ModuleDataScope := ModuleDataScope::Module; + this.ValidateValueKey(TokenKey); + + if Value = '' then begin + if IsolatedStorage.Contains(TokenKey, ModuleDataScope) then + exit(IsolatedStorage.Delete(TokenKey, ModuleDataScope)) + end else + exit(IsolatedStorage.Set(TokenKey, Value, ModuleDataScope)); + end; + + procedure StorageSet(var TokenKey: Guid; Value: SecretText): Boolean + begin + exit(this.StorageSet(TokenKey, Value, DataScope::Module)); + end; + + procedure GetBCInstanceIdentifier() Identifier: Text + var + AADTenantID, AADDomainName : Text; + begin + Identifier := '10000000-d8ef-4dfb-b761-ffb073057794'; // Hardcoded fake during testing only + + if this.GetAADTenantInformation(AADTenantID, AADDomainName) then + Identifier := AADTenantID; + end; + + [NonDebuggable] + procedure GetRootUrl() ReturnValue: Text + begin + if this.FetchSecretFromKeyVault(this.SignupRootUrlTxt, ReturnValue) then + exit; + + if not this.ConnectionSetup.GetSetup() then + exit; + + this.ConnectionSetup.TestField("Root Market URL"); + ReturnValue := this.StorageGetText(this.ConnectionSetup."Root Market URL", DataScope::Module); + end; + + #endregion + + #region local methods + + local procedure GetAuthToken() AccessToken: SecretText; + var + HttpError: Text; + begin + AccessToken := this.StorageGet(this.SignUpAccessTokenKeyTxt, DataScope::Company); + + if this.HelpersImpl.IsTokenValid(AccessToken) then + exit; + + if not this.RefreshAccessToken(HttpError) then + Error(HttpError); + + exit(this.StorageGet(this.SignUpAccessTokenKeyTxt, DataScope::Company)); + end; + + local procedure GetRootAuthToken() ReturnValue: SecretText; + begin + if not this.GetRootAccessToken(ReturnValue) then + Error(this.ErrorTokenLbl); + end; + + local procedure SaveClientCredentials(ClientId: Text; ClientSecret: SecretText) + begin + Clear(this.ConnectionSetup); + + this.ConnectionSetup.GetSetup(); + this.StorageSet(this.ConnectionSetup."Client ID", ClientId); + this.StorageSet(this.ConnectionSetup."Client Secret", ClientSecret); + this.ConnectionSetup.Modify(); + + Clear(this.ConnectionSetup); + end; + + [NonDebuggable] + local procedure GetClientCredentials(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + APIRequests: Codeunit APIRequests; + begin + APIRequests.GetMarketPlaceCredentials(HttpRequestMessage, HttpResponseMessage); + + if not HttpResponseMessage.IsSuccessStatusCode() then + exit; + + exit(this.HelpersImpl.ParseJsonString(HttpResponseMessage.Content) <> ''); + end; + + [NonDebuggable] + local procedure RefreshAccessToken(var HttpError: Text): Boolean; + var + SecretToken: SecretText; + begin + if not this.GetClientAccessToken(SecretToken) then begin + HttpError := GetLastErrorText(); + exit; + end; + + exit(this.SaveSignUpAccessToken(DataScope::Company, SecretToken)); + end; + + [NonDebuggable] + local procedure GetRootAccessToken(var AccessToken: SecretText): Boolean + begin + exit(this.GetAccessToken(AccessToken, this.GetRootId(), this.GetRootSecret(), this.GetRootTenant())); + end; + + [NonDebuggable] + local procedure GetClientAccessToken(var AccessToken: SecretText): Boolean + var + ModuleDataScope: DataScope; + begin + ModuleDataScope := ModuleDataScope::Module; + this.ConnectionSetup.GetSetup(); + + exit(this.GetAccessToken(AccessToken, this.StorageGetText(this.ConnectionSetup."Client ID", ModuleDataScope), + this.StorageGet(this.ConnectionSetup."Client Secret", ModuleDataScope), + this.StorageGetText(this.ConnectionSetup."Client Tenant", ModuleDataScope))); + end; + + [NonDebuggable] + local procedure GetAccessToken(var AccessToken: SecretText; ClientId: Text; ClientSecret: SecretText; ClientTenant: Text) Success: Boolean + var + OAuth2: Codeunit OAuth2; + begin + Success := OAuth2.AcquireTokenWithClientCredentials(ClientId, ClientSecret, StrSubstNo(this.ConnectionSetup."Authentication URL", ClientTenant), '', ClientId, AccessToken); + exit(Success and not AccessToken.IsEmpty()); + end; + + local procedure StorageSet(var TokenKey: Guid; Value: SecretText; TokenDataScope: DataScope): Boolean + begin + this.ValidateValueKey(TokenKey); + + if Value.IsEmpty() then begin + if IsolatedStorage.Contains(TokenKey, TokenDataScope) then + exit(IsolatedStorage.Delete(TokenKey, TokenDataScope)) + end else + exit(IsolatedStorage.Set(TokenKey, Value, TokenDataScope)); + end; + + local procedure StorageGet(TokenKey: Text; TokenDataScope: DataScope) TokenValueAsSecret: SecretText + begin + if not this.StorageContains(TokenKey, TokenDataScope) then + exit(TokenValueAsSecret); + + IsolatedStorage.Get(TokenKey, TokenDataScope, TokenValueAsSecret); + end; + + [NonDebuggable] + local procedure StorageGetText(TokenKey: Text; TokenDataScope: DataScope) TokenValue: Text + begin + if not this.StorageContains(TokenKey, TokenDataScope) then + exit(TokenValue); + + IsolatedStorage.Get(TokenKey, TokenDataScope, TokenValue); + end; + + local procedure SaveSignUpAccessToken(TokenDataScope: DataScope; AccessToken: SecretText): Boolean + var + SignUpAccessTokenKey: Guid; + begin + SignUpAccessTokenKey := this.GetSignUpAccessTokenKey(); + exit(this.StorageSet(SignUpAccessTokenKey, AccessToken, TokenDataScope)); + end; + + local procedure StorageContains(TokenKey: Text; TokenDataScope: DataScope): Boolean + begin + exit(IsolatedStorage.Contains(TokenKey, TokenDataScope)); + end; + + local procedure ValidateValueKey(var ValueKey: Guid) + begin + if IsNullGuid(ValueKey) then + ValueKey := CreateGuid(); + end; + + local procedure GetSignUpAccessTokenKey() SignUpAccessTokenKey: Guid + begin + Evaluate(SignUpAccessTokenKey, this.SignUpAccessTokenKeyTxt); + end; + + [NonDebuggable] + local procedure GetRootId() ReturnValue: Text + begin + if this.FetchSecretFromKeyVault(this.RootIdTxt, ReturnValue) then + exit; + + if not this.ConnectionSetup.GetSetup() then + exit; + + this.ConnectionSetup.TestField("Root App ID"); + ReturnValue := this.StorageGetText(this.ConnectionSetup."Root App ID", DataScope::Module); + end; + + [NonDebuggable] + local procedure GetRootSecret() ReturnValue: Text + begin + if this.FetchSecretFromKeyVault(this.SignUpRootSecretTxt, ReturnValue) then + exit; + + if not this.ConnectionSetup.GetSetup() then + exit; + + this.ConnectionSetup.TestField("Root Secret"); + ReturnValue := this.StorageGetText(this.ConnectionSetup."Root Secret", DataScope::Module); + end; + + [NonDebuggable] + local procedure GetRootTenant() ReturnValue: Text + begin + if this.FetchSecretFromKeyVault(this.SignUpRootTenantTxt, ReturnValue) then + exit; + + if not this.ConnectionSetup.GetSetup() then + exit; + + this.ConnectionSetup.TestField("Root Tenant"); + ReturnValue := this.StorageGetText(this.ConnectionSetup."Root Tenant", DataScope::Module); + end; + + [NonDebuggable] + local procedure FetchSecretFromKeyVault(KeyName: Text; var KeyValue: Text): Boolean + var + AzureKeyVault: Codeunit "Azure Key Vault"; + EnvironmentInformation: Codeunit "Environment Information"; + begin + if EnvironmentInformation.IsSaaSInfrastructure() then + exit(AzureKeyVault.GetAzureKeyVaultSecret(KeyName, KeyValue)); + end; + + local procedure GetAADTenantInformation(var AADTenantID: Text; var AADDomainName: Text): Boolean + begin + exit(this.GetAADTenantID(AADTenantID) and this.GetAADDomainName(AADDomainName)); + end; + + [TryFunction] + local procedure GetAADTenantID(var AADTenantID: Text) + var + AzureADTenant: Codeunit "Azure AD Tenant"; + begin + AADTenantID := AzureADTenant.GetAadTenantId(); + end; + + [TryFunction] + local procedure GetAADDomainName(var AADDomainName: Text) + var + AzureADTenant: Codeunit "Azure AD Tenant"; + begin + AADDomainName := AzureADTenant.GetAadTenantId(); + end; + + #endregion +} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionImpl.Codeunit.al new file mode 100644 index 0000000000..520cd055c6 --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionImpl.Codeunit.al @@ -0,0 +1,116 @@ +// ------------------------------------------------------------------------------------------------ +// 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.Purchases.Document; +using Microsoft.Purchases.Posting; +using System.Utilities; + +codeunit 6391 ConnectionImpl +{ + Access = Internal; + InherentEntitlements = X; + InherentPermissions = X; + Permissions = tabledata "E-Document" = m; + + #region variables + + var + APIRequests: Codeunit APIRequests; + HelpersImpl: Codeunit HelpersImpl; + UnsuccessfulResponseErr: Label 'There was an error sending the request. Response code: %1 and error message: %2', Comment = '%1 - http response status code, e.g. 400, %2- error message'; + EnvironmentBlocksErr: Label 'The request to send documents has been blocked. To resolve the problem, enable outgoing HTTP requests for the E-Document apps on the Extension Management page.'; + + #endregion + + #region public methods + + procedure SendFilePostRequest(var TempBlob: Codeunit "Temp Blob"; var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + begin + this.APIRequests.SendFilePostRequest(TempBlob, EDocument, HttpRequestMessage, HttpResponseMessage); + exit(this.CheckIfSuccessfulRequest(EDocument, HttpResponseMessage)); + end; + + procedure CheckDocumentStatus(var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + begin + this.APIRequests.GetSentDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage); + exit(this.CheckIfSuccessfulRequest(EDocument, HttpResponseMessage)); + end; + + procedure GetReceivedDocuments(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + begin + this.APIRequests.GetReceivedDocumentsRequest(HttpRequestMessage, HttpResponseMessage); + + if not HttpResponseMessage.IsSuccessStatusCode() then + exit; + + exit(this.HelpersImpl.ParseJsonString(HttpResponseMessage.Content) <> ''); + end; + + procedure GetTargetDocumentRequest(DocumentId: Text; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + begin + this.APIRequests.GetTargetDocumentRequest(DocumentId, HttpRequestMessage, HttpResponseMessage); + exit(HttpResponseMessage.IsSuccessStatusCode()); + end; + + procedure RemoveDocumentFromReceived(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + begin + this.APIRequests.PatchReceivedDocument(EDocument, HttpRequestMessage, HttpResponseMessage); + exit(HttpResponseMessage.IsSuccessStatusCode()); + end; + + #endregion + + #region local methods + + local procedure CheckIfSuccessfulRequest(EDocument: Record "E-Document"; HttpResponseMessage: HttpResponseMessage): Boolean + var + EDocumentErrorHelper: Codeunit "E-Document Error Helper"; + begin + if HttpResponseMessage.IsSuccessStatusCode() then + exit(true); + + if HttpResponseMessage.IsBlockedByEnvironment() then + EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, this.EnvironmentBlocksErr) + else + EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, StrSubstNo(this.UnsuccessfulResponseErr, HttpResponseMessage.HttpStatusCode, HttpResponseMessage.ReasonPhrase)); + end; + + #endregion + + #region event subscribers + + [EventSubscriber(ObjectType::Codeunit, Codeunit::"Purch.-Post", OnAfterCheckAndUpdate, '', false, false)] + local procedure CheckOnPosting(var PurchaseHeader: Record "Purchase Header"; CommitIsSuppressed: Boolean; PreviewMode: Boolean) + var + EDocument: Record "E-Document"; + EDocumentService: Record "E-Document Service"; + EDocumentServiceStatus: Record "E-Document Service Status"; + begin + if PurchaseHeader.IsTemporary() then + exit; + + EDocument.SetLoadFields("Entry No"); + EDocument.SetRange("Document Record ID", PurchaseHeader.RecordId); + if not EDocument.FindFirst() then + exit; + + EDocumentService.SetLoadFields(Code); + EDocumentService.SetRange("Service Integration", EDocumentService."Service Integration"::"ExFlow E-Invoicing"); + if not EDocumentService.FindFirst() then + exit; + + EDocumentServiceStatus.SetLoadFields(Status); + EDocumentServiceStatus.SetRange("E-Document Entry No", EDocument."Entry No"); + EDocumentServiceStatus.SetRange("E-Document Service Code", EDocumentService.Code); + if EDocumentServiceStatus.FindSet() then + repeat + EDocumentServiceStatus.TestField(EDocumentServiceStatus.Status, EDocumentServiceStatus.Status::Approved); + until EDocumentServiceStatus.Next() = 0; + end; + + #endregion +} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/JobHelperImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/JobHelperImpl.Codeunit.al new file mode 100644 index 0000000000..fac63284e2 --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/JobHelperImpl.Codeunit.al @@ -0,0 +1,83 @@ +// ------------------------------------------------------------------------------------------------ +// 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 System.Telemetry; +using System.Threading; +using Microsoft.EServices.EDocument; + +codeunit 6392 JobHelperImpl +{ + TableNo = "Job Queue Entry"; + Access = Internal; + InherentEntitlements = X; + InherentPermissions = X; + + #region variables + + var + Telemetry: Codeunit Telemetry; + JobQueueCategoryTok: Label 'EDocument', Locked = true, Comment = 'Max Length 10'; + EDocumentJobTelemetryLbl: Label 'E-Document Background Job Scheduled', Locked = true; + JobQueueIdTxt: Label 'Job Queue Id', Locked = true; + CodeunitIsTxt: Label 'Codeunit Id', Locked = true; + RecordIdTxt: Label 'Record Id', Locked = true; + UserSessionIdTxt: Label 'User Session ID', Locked = true; + EarliestStartDateTimeTxt: Label 'Earliest Start Date/Time', Locked = true; + + #endregion + + #region public methods + + procedure ScheduleEDocumentJob(CodeunitId: Integer; JobRecordId: RecordId; EarliestStartDateTime: Integer): Guid + var + JobQueueEntry: Record "Job Queue Entry"; + TelemetryDimensions: Dictionary of [Text, Text]; + begin + if this.IsJobQueueScheduled(CodeunitId) then + exit; + + JobQueueEntry.Init(); + JobQueueEntry."Object Type to Run" := JobQueueEntry."Object Type to Run"::Codeunit; + JobQueueEntry."Object ID to Run" := CodeunitId; + JobQueueEntry."Record ID to Process" := JobRecordId; + JobQueueEntry."User Session ID" := SessionId(); + JobQueueEntry."Job Queue Category Code" := this.JobQueueCategoryTok; + JobQueueEntry."No. of Attempts to Run" := 0; + JobQueueEntry."Earliest Start Date/Time" := CurrentDateTime + EarliestStartDateTime; + + TelemetryDimensions.Add(this.JobQueueIdTxt, JobQueueEntry.ID); + TelemetryDimensions.Add(this.CodeunitIsTxt, Format(CodeunitId)); + TelemetryDimensions.Add(this.RecordIdTxt, Format(JobRecordId)); + TelemetryDimensions.Add(this.UserSessionIdTxt, Format(JobQueueEntry."User Session ID")); + TelemetryDimensions.Add(this.EarliestStartDateTimeTxt, Format(JobQueueEntry."Earliest Start Date/Time")); + this.Telemetry.LogMessage('', this.EDocumentJobTelemetryLbl, Verbosity::Normal, DataClassification::OrganizationIdentifiableInformation, TelemetryScope::All, TelemetryDimensions); + Codeunit.Run(Codeunit::"Job Queue - Enqueue", JobQueueEntry); + exit(JobQueueEntry.ID); + end; + + procedure FetchEDocumentAndService(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; EDocumentServiceStatus: Record "E-Document Service Status") + begin + EDocumentService.SetLoadFields("Service Integration", "Document Format"); + EDocumentService.Get(EDocumentServiceStatus."E-Document Service Code"); + EDocument.Get(EDocumentServiceStatus."E-Document Entry No"); + end; + + #endregion + + #region local methods + + local procedure IsJobQueueScheduled(CodeunitId: Integer): Boolean + var + JobQueueEntry: Record "Job Queue Entry"; + begin + JobQueueEntry.SetRange("Object Type to Run", JobQueueEntry."Object Type to Run"::Codeunit); + JobQueueEntry.SetRange("Object ID to Run", CodeunitId); + JobQueueEntry.SetFilter(Status, '%1|%2', JobQueueEntry.Status::Ready, JobQueueEntry.Status::"In Process"); + exit(not JobQueueEntry.IsEmpty()); + end; + + #endregion +} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/ProcessingImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/ProcessingImpl.Codeunit.al new file mode 100644 index 0000000000..0412890010 --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/ProcessingImpl.Codeunit.al @@ -0,0 +1,580 @@ +// ------------------------------------------------------------------------------------------------ +// 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 System.Telemetry; +using System.Text; +using System.Utilities; + +codeunit 6383 ProcessingImpl +{ + Access = Internal; + InherentEntitlements = X; + InherentPermissions = X; + Permissions = tabledata "E-Document" = rim, + tabledata "E-Document Service Status" = rm, + tabledata "E-Document Service" = r, + tabledata "E-Document Integration Log" = ri, + tabledata "E-Document Log" = ri; + + #region variables + var + Connection: Codeunit Connection; + HelpersImpl: Codeunit HelpersImpl; + EDocumentHelper: Codeunit "E-Document Helper"; + EDocumentLogHelper: Codeunit "E-Document Log Helper"; + EDocumentErrorHelper: Codeunit "E-Document Error Helper"; + GetApprovalCheckStatusErr: Label 'You cannot ask for approval with the E-Document in this current status %1. You can request for approval when E-document status is Sent or Pending Response.', Comment = '%1 - Status'; + CouldNotRetrieveDocumentErr: Label 'Could not retrieve document with id: %1 from the service', Comment = '%1 - Document ID'; + DocumentIdNotFoundErr: Label 'Document ID not found in response'; + ExternalServiceTok: Label 'E-Document - SignUp', Locked = true; + InboxTxt: Label 'inbox', Locked = true; + InstanceIdTxt: Label 'instanceId', Locked = true; + PeppolInstanceIdTxt: Label 'peppolInstanceId', Locked = true; + StatusTxt: Label 'status', Locked = true; + SentTxt: Label 'sent', Locked = true; + ReadyTxt: Label 'ready', Locked = true; + FailedTxt: Label 'failed', Locked = true; + DescriptionTxt: Label 'description', Locked = true; + ReasonTxt: Label 'Reason: ', Locked = true; + NewTxt: Label 'new', Locked = true; + DocumentTxt: Label 'document', Locked = true; + StandardBusinessDocumentHeaderTxt: Label '', Locked = true; + InvoiceTxt: Label '', Locked = true; + + + #endregion + + #region public methods + + procedure SendEDocument(var EDocument: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) + var + EDocumentServiceStatus: Record "E-Document Service Status"; + EDocumentService: Record "E-Document Service"; + FeatureTelemetry: Codeunit "Feature Telemetry"; + begin + IsAsync := true; + + this.EDocumentHelper.GetEdocumentService(EDocument, EDocumentService); + EDocumentServiceStatus.Get(EDocument."Entry No", EDocumentService.Code); + + case EDocumentServiceStatus.Status of + EDocumentServiceStatus.Status::Exported: + this.SendEDocument(EDocument, TempBlob, HttpRequestMessage, HttpResponseMessage); + EDocumentServiceStatus.Status::"Sending Error": + if EDocument."Document Id" = '' then + this.SendEDocument(EDocument, TempBlob, HttpRequestMessage, HttpResponseMessage); + end; + + FeatureTelemetry.LogUptake('', this.ExternalServiceTok, Enum::"Feature Uptake Status"::Used); + end; + + procedure GetDocumentResponse(var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + ErrorDescription: Text; + begin + if not this.Connection.CheckDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage) then + exit; + exit(not this.DocumentHasErrorOrStillInProcessing(EDocument, HttpResponseMessage, ErrorDescription)); + end; + + procedure GetDocumentSentResponse(var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + EDocumentService: Record "E-Document Service"; + APIRequests: Codeunit APIRequests; + Status, StatusDescription : Text; + begin + this.EDocumentHelper.GetEdocumentService(EDocument, EdocumentService); + APIRequests.GetSentDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage); + if not this.ParseGetADocumentApprovalResponse(HttpResponseMessage.Content, Status, StatusDescription) then + exit; + + case Status of + this.ReadyTxt: + exit(true); + this.FailedTxt: + begin + if StatusDescription <> '' then + this.EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, this.ReasonTxt + StatusDescription); + this.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Rejected, 0, HttpRequestMessage, HttpResponseMessage); + exit; + end; + end; + end; + + procedure GetDocumentApproval(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + EDocumentService: Record "E-Document Service"; + EDocumentServiceStatus: Record "E-Document Service Status"; + APIRequests: Codeunit APIRequests; + JobHelperImpl: Codeunit JobHelperImpl; + BlankRecordId: RecordId; + Status, StatusDescription : Text; + begin + this.EDocumentHelper.GetEdocumentService(EDocument, EdocumentService); + EDocumentServiceStatus.SetLoadFields(Status); + EDocumentServiceStatus.Get(EDocument."Entry No", EdocumentService.Code); + if not (EDocumentServiceStatus.Status in [EDocumentServiceStatus.Status::Sent, EDocumentServiceStatus.Status::"Pending Response"]) then + Error(this.GetApprovalCheckStatusErr, EDocumentServiceStatus.Status); + + APIRequests.GetSentDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage); + if not this.ParseGetADocumentApprovalResponse(HttpResponseMessage.Content, Status, StatusDescription) then + exit; + + case Status of + this.ReadyTxt: + begin + if EDocumentServiceStatus.Status = EDocumentServiceStatus.Status::Approved then + JobHelperImpl.ScheduleEDocumentJob(Codeunit::PatchSentJob, BlankRecordId, 300000) + else + JobHelperImpl.ScheduleEDocumentJob(Codeunit::GetReadyStatusJob, BlankRecordId, 300000); + exit(true); + end; + this.FailedTxt: + begin + if StatusDescription <> '' then + this.EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, this.ReasonTxt + StatusDescription); + this.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Rejected, 0, HttpRequestMessage, HttpResponseMessage); + exit; + end; + end; + end; + + procedure ReceiveDocument(var TempBlob: Codeunit "Temp Blob"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) + var + ContentData: Text; + begin + if not this.Connection.GetReceivedDocuments(HttpRequestMessage, HttpResponseMessage) then + exit; + + if not HttpResponseMessage.Content.ReadAs(ContentData) then + exit; + + TempBlob.CreateOutStream(TextEncoding::UTF8).WriteText(ContentData); + end; + + procedure GetDocumentCountInBatch(var TempBlob: Codeunit "Temp Blob"): Integer + var + ResponseTxt: Text; + begin + TempBlob.CreateInStream().ReadText(ResponseTxt); + exit(this.GetNumberOfReceivedDocuments(ResponseTxt)); + end; + + procedure InsertIntegrationLog(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; HttpRequestMessage: HttpRequestMessage; HttpResponseMessage: HttpResponseMessage) + var + EDocumentIntegrationLog: Record "E-Document Integration Log"; + EDocIntegrationLogRecordRef: RecordRef; + RequestTxt: Text; + begin + if EDocumentService."Service Integration" = EDocumentService."Service Integration"::"No Integration" then + exit; + + EDocumentIntegrationLog.Validate("E-Doc. Entry No", EDocument."Entry No"); + EDocumentIntegrationLog.Validate("Service Code", EDocumentService.Code); + EDocumentIntegrationLog.Validate("Response Status", HttpResponseMessage.HttpStatusCode()); + EDocumentIntegrationLog.Validate("Request URL", HttpRequestMessage.GetRequestUri()); + EDocumentIntegrationLog.Validate(Method, HttpRequestMessage.Method()); + EDocumentIntegrationLog.Insert(); + + EDocIntegrationLogRecordRef.GetTable(EDocumentIntegrationLog); + + if HttpRequestMessage.Content.ReadAs(RequestTxt) then begin + this.InsertIntegrationBlob(EDocIntegrationLogRecordRef, RequestTxt, EDocumentIntegrationLog.FieldNo(EDocumentIntegrationLog."Request Blob")); + EDocIntegrationLogRecordRef.Modify(); + end; + + if HttpResponseMessage.Content.ReadAs(RequestTxt) then begin + this.InsertIntegrationBlob(EDocIntegrationLogRecordRef, RequestTxt, EDocumentIntegrationLog.FieldNo(EDocumentIntegrationLog."Response Blob")); + EDocIntegrationLogRecordRef.Modify(); + end; + end; + + procedure InsertLogWithIntegration(var EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; + EDocumentServiceStatus: Enum "E-Document Service Status"; EDocDataStorageEntryNo: Integer; HttpRequestMessage: HttpRequestMessage; HttpResponseMessage: HttpResponseMessage) + begin + this.InsertLog(EDocument, EDocumentService, EDocDataStorageEntryNo, EDocumentServiceStatus); + + if (HttpRequestMessage.GetRequestUri() <> '') and (HttpResponseMessage.Headers.Keys().Count > 0) then + this.InsertIntegrationLog(EDocument, EDocumentService, HttpRequestMessage, HttpResponseMessage); + end; + + #endregion + + #region local methods + + local procedure ParseGetADocumentApprovalResponse(HttpContentResponse: HttpContent; var Status: Text; var StatusDescription: Text): Boolean + var + JsonManagement: Codeunit "JSON Management"; + Result: Text; + begin + Result := this.HelpersImpl.ParseJsonString(HttpContentResponse); + if Result = '' then + exit; + + if not JsonManagement.InitializeFromString(Result) then + exit; + + Status := this.GetStatus(JsonManagement); + + if Status in [this.ReadyTxt, this.SentTxt] then + exit(true); + + if Status = this.FailedTxt then begin + JsonManagement.GetArrayPropertyValueAsStringByName(this.DescriptionTxt, StatusDescription); + exit(true); + end; + + exit; + end; + + local procedure InsertLog(var EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; EDocDataStorageEntryNo: Integer; EDocumentServiceStatus: Enum "E-Document Service Status"): Integer + var + EDocumentLog: Record "E-Document Log"; + begin + if EDocumentService.Code <> '' then + this.UpdateServiceStatus(EDocument, EDocumentService, EDocumentServiceStatus); + + EDocumentLog.Validate("Document Type", EDocument."Document Type"); + EDocumentLog.Validate("Document No.", EDocument."Document No."); + EDocumentLog.Validate("E-Doc. Entry No", EDocument."Entry No"); + EDocumentLog.Validate(Status, EDocumentServiceStatus); + EDocumentLog.Validate("Service Integration", EDocumentService."Service Integration"); + EDocumentLog.Validate("Service Code", EDocumentService.Code); + EDocumentLog.Validate("Document Format", EDocumentService."Document Format"); + EDocumentLog.Validate("E-Doc. Data Storage Entry No.", EDocDataStorageEntryNo); + EDocumentLog.Insert(); + + exit(EDocumentLog."Entry No."); + end; + + local procedure UpdateServiceStatus(var EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; EDocumentStatus: Enum "E-Document Service Status") + var + EDocumentServiceStatus: Record "E-Document Service Status"; + Exists: Boolean; + begin + EDocument.Get(EDocument."Entry No"); + Exists := EDocumentServiceStatus.Get(EDocument."Entry No", EDocumentService.Code); + EDocumentServiceStatus.Validate(Status, EDocumentStatus); + if Exists then + EDocumentServiceStatus.Modify() + else begin + EDocumentServiceStatus.Validate("E-Document Entry No", EDocument."Entry No"); + EDocumentServiceStatus.Validate("E-Document Service Code", EDocumentService.Code); + EDocumentServiceStatus.Validate(Status, EDocumentStatus); + EDocumentServiceStatus.Insert(); + end; + + this.UpdateEDocumentStatus(EDocument); + end; + + local procedure SendEDocument(EDocument: Record "E-Document"; TempBlob: Codeunit "Temp Blob"; HttpRequestMessage: HttpRequestMessage; HttpResponseMessage: HttpResponseMessage); + begin + this.Connection.SendFilePostRequest(TempBlob, EDocument, HttpRequestMessage, HttpResponseMessage); + this.SetEDocumentFileID(EDocument."Entry No", this.ParseSendFileResponse(HttpResponseMessage.Content)); + end; + + local procedure ParseReceivedDocument(InputTxt: Text; Index: Integer; var DocumentId: Text): Boolean + var + JsonManagement: Codeunit "JSON Management"; + IncrementalTable, Value : Text; + begin + if not JsonManagement.InitializeFromString(InputTxt) then + exit; + + JsonManagement.GetArrayPropertyValueAsStringByName(this.InboxTxt, Value); + JsonManagement.InitializeCollection(Value); + + if Index = 0 then + Index := 1; + + if Index > JsonManagement.GetCollectionCount() then + exit; + + JsonManagement.GetObjectFromCollectionByIndex(IncrementalTable, Index - 1); + + Clear(JsonManagement); + JsonManagement.InitializeObject(IncrementalTable); + JsonManagement.GetArrayPropertyValueAsStringByName(this.InstanceIdTxt, DocumentId); + + exit(true); + end; + + local procedure GetNumberOfReceivedDocuments(InputTxt: Text): Integer + var + JsonManagement: Codeunit "JSON Management"; + Value: Text; + begin + InputTxt := this.LeaveJustNewLine(InputTxt); + + if not JsonManagement.InitializeFromString(InputTxt) then + exit(0); + + JsonManagement.GetArrayPropertyValueAsStringByName(this.InboxTxt, Value); + JsonManagement.InitializeCollection(Value); + + exit(JsonManagement.GetCollectionCount()); + end; + + local procedure ParseSendFileResponse(HttpContentResponse: HttpContent): Text + var + JsonManagement: Codeunit "JSON Management"; + Result, Value : Text; + begin + Result := this.HelpersImpl.ParseJsonString(HttpContentResponse); + if Result = '' then + exit; + + if not JsonManagement.InitializeFromString(Result) then + exit; + + JsonManagement.GetStringPropertyValueByName(this.PeppolInstanceIdTxt, Value); + exit(Value); + end; + + local procedure SetEDocumentFileID(EDocEntryNo: Integer; FileId: Text) + var + EDocument: Record "E-Document"; + begin + if FileId = '' then + exit; + + if not EDocument.Get(EDocEntryNo) then + exit; + + EDocument."Document Id" := CopyStr(FileId, 1, MaxStrLen(EDocument."Document Id")); + EDocument.Modify(); + end; + + local procedure DocumentHasErrorOrStillInProcessing(EDocument: Record "E-Document"; HttpResponseMessage: HttpResponseMessage; var ErrorDescription: Text): Boolean + var + EDocumentService: Record "E-Document Service"; + EDocumentServiceStatus: Record "E-Document Service Status"; + JsonManagement: Codeunit "JSON Management"; + JobHelperImpl: Codeunit JobHelperImpl; + BlankRecordId: RecordId; + Result, Status : Text; + begin + Result := this.HelpersImpl.ParseJsonString(HttpResponseMessage.Content); + if Result = '' then + exit(true); + + if not JsonManagement.InitializeFromString(Result) then + exit(true); + + Status := this.GetStatus(JsonManagement); + + if Status in [this.SentTxt] then begin + JobHelperImpl.ScheduleEDocumentJob(Codeunit::GetReadyStatusJob, BlankRecordId, 120000); + exit; + end; + + if Status in [this.ReadyTxt] then begin + this.EDocumentHelper.GetEdocumentService(EDocument, EDocumentService); + EDocumentServiceStatus.SetLoadFields(Status); + EDocumentServiceStatus.Get(EDocument."Entry No", EdocumentService.Code); + if EDocumentServiceStatus.Status = EDocumentServiceStatus.Status::Approved then + JobHelperImpl.ScheduleEDocumentJob(Codeunit::PatchSentJob, BlankRecordId, 180000) + else + JobHelperImpl.ScheduleEDocumentJob(Codeunit::GetReadyStatusJob, BlankRecordId, 120000); + exit; + end; + + if Status = this.FailedTxt then begin + JsonManagement.GetArrayPropertyValueAsStringByName(this.DescriptionTxt, ErrorDescription); + exit; + end; + + JsonManagement.GetArrayPropertyValueAsStringByName(this.DescriptionTxt, ErrorDescription); + exit(true); + end; + + local procedure GetStatus(var JsonManagement: Codeunit "Json Management") Status: Text + begin + JsonManagement.GetArrayPropertyValueAsStringByName(this.StatusTxt, Status); + Status := Status.ToLower(); + end; + + local procedure UpdateEDocumentStatus(var EDocument: Record "E-Document") + var + IsHandled: Boolean; + begin + if IsHandled then + exit; + + if this.EDocumentHasErrors(EDocument) then + exit; + + this.SetDocumentStatus(EDocument); + end; + + local procedure EDocumentHasErrors(var EDocument: Record "E-Document"): Boolean + var + EDocumentServiceStatus: Record "E-Document Service Status"; + begin + EDocumentServiceStatus.SetRange("E-Document Entry No", EDocument."Entry No"); + EDocumentServiceStatus.SetFilter(Status, '%1|%2|%3|%4|%5', + EDocumentServiceStatus.Status::"Sending Error", + EDocumentServiceStatus.Status::"Export Error", + EDocumentServiceStatus.Status::"Cancel Error", + EDocumentServiceStatus.Status::"Imported Document Processing Error", + EDocumentServiceStatus.Status::Rejected); + + if EDocumentServiceStatus.IsEmpty() then + exit; + + EDocument.Validate(Status, EDocument.Status::Error); + EDocument.Modify(); + exit(true); + end; + + local procedure InsertIntegrationBlob(var EDocIntegrationLogRecordRef: RecordRef; Data: Text; FieldNo: Integer) + var + TempBlob: Codeunit "Temp Blob"; + begin + TempBlob.CreateOutStream().WriteText(Data); + TempBlob.ToRecordRef(EDocIntegrationLogRecordRef, FieldNo); + end; + + local procedure SetDocumentStatus(var EDocument: Record "E-Document") + var + EDocumentServiceStatus: Record "E-Document Service Status"; + EDocServiceCount: Integer; + begin + EDocumentServiceStatus.SetRange("E-Document Entry No", EDocument."Entry No"); + EDocServiceCount := EDocumentServiceStatus.Count; + + EDocumentServiceStatus.SetFilter(Status, '%1|%2|%3|%4|%5', + EDocumentServiceStatus.Status::Exported, + EDocumentServiceStatus.Status::"Imported Document Created", + EDocumentServiceStatus.Status::"Journal Line Created", + EDocumentServiceStatus.Status::Approved, + EDocumentServiceStatus.Status::Canceled); + if EDocumentServiceStatus.Count() = EDocServiceCount then + EDocument.Status := EDocument.Status::Processed + else + EDocument.Status := EDocument.Status::"In Progress"; + + EDocument.Modify(); + end; + + local procedure LeaveJustNewLine(InputText: Text): Text + var + InputJson, OutputDocumentJsonObject, OutputJsonObject : JsonObject; + InputJsonArray, OutputDocumentJsonArray : JsonArray; + InputJsonToken, DocumentJsonToken : JsonToken; + OutputText: text; + DocumentList: List of [Text]; + i: Integer; + begin + OutputText := InputText; + InputJson.ReadFrom(InputText); + if InputJson.Contains(this.InboxTxt) then begin + InputJson.Get(this.InboxTxt, InputJsonToken); + InputJsonArray := InputJsonToken.AsArray(); + foreach InputJsonToken in InputJsonArray do + if InputJsonToken.AsObject().Get(this.StatusTxt, DocumentJsonToken) then + if DocumentJsonToken.AsValue().AsText().ToLower() = this.NewTxt then begin + InputJsonToken.AsObject().Get(this.InstanceIdTxt, DocumentJsonToken); + DocumentList.Add(DocumentJsonToken.AsValue().AsText()); + end; + + for i := 1 to DocumentList.Count do begin + Clear(OutputDocumentJsonObject); + OutputDocumentJsonObject.Add(this.InstanceIdTxt, DocumentList.Get(i)); + OutputDocumentJsonArray.Add(OutputDocumentJsonObject); + end; + + OutputJsonObject.Add(this.InboxTxt, OutputDocumentJsonArray); + OutputJsonObject.WriteTo(OutputText) + end; + + exit(OutputText); + end; + + local procedure ParseContentData(var InputText: Text): Boolean + var + JsonManagement: Codeunit "JSON Management"; + Base64Convert: Codeunit "Base64 Convert"; + Value: Text; + ParsePosition: Integer; + begin + if not JsonManagement.InitializeFromString(InputText) then + exit; + + JsonManagement.GetArrayPropertyValueAsStringByName(this.DocumentTxt, Value); + InputText := Base64Convert.FromBase64(Value); + ParsePosition := StrPos(InputText, this.StandardBusinessDocumentHeaderTxt); + if ParsePosition > 0 then begin + InputText := CopyStr(InputText, parsePosition, StrLen(InputText)); + ParsePosition := StrPos(InputText, this.InvoiceTxt); + InputText := CopyStr(InputText, parsePosition, StrLen(InputText)); + ParsePosition := StrPos(InputText, this.StandardBusinessDocumentTxt); + InputText := CopyStr(InputText, 1, parsePosition - 1); + end; + + exit(true); + end; + + #endregion + + #region event subscribers + + [EventSubscriber(ObjectType::Codeunit, Codeunit::"E-Doc. Integration Management", OnGetEDocumentApprovalReturnsFalse, '', false, false)] + local procedure OnGetEDocumentApprovalReturnsFalse(EDocuments: Record "E-Document"; EDocumentService: Record "E-Document Service"; HttpRequest: HttpRequestMessage; HttpResponse: HttpResponseMessage; var IsHandled: Boolean) + var + HttpContent: HttpContent; + Status, StatusDescription : Text; + begin + HttpContent := HttpResponse.Content; + if not this.ParseGetADocumentApprovalResponse(HttpContent, Status, StatusDescription) then + IsHandled := true; + end; + + [EventSubscriber(ObjectType::Codeunit, Codeunit::"E-Doc. Import", OnAfterInsertImportedEdocument, '', false, false)] + local procedure OnAfterInsertEdocument(var EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; var TempBlob: Codeunit "Temp Blob"; EDocCount: Integer; HttpRequest: HttpRequestMessage; HttpResponse: HttpResponseMessage) + var + HttpRequestMessage: HttpRequestMessage; + HttpResponseMessage: HttpResponseMessage; + ContentData, DocumentId : Text; + begin + if EDocumentService."Service Integration" <> EDocumentService."Service Integration"::"ExFlow E-Invoicing" then + exit; + + if not HttpResponse.Content.ReadAs(ContentData) then + exit; + + ContentData := this.LeaveJustNewLine(ContentData); + + if not this.ParseReceivedDocument(ContentData, EDocument."Index In Batch", DocumentId) then begin + this.EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, this.DocumentIdNotFoundErr); + exit; + end; + + this.Connection.GetTargetDocumentRequest(DocumentId, HttpRequestMessage, HttpResponseMessage); + this.EDocumentLogHelper.InsertIntegrationLog(EDocument, EDocumentService, HttpRequestMessage, HttpResponseMessage); + + if not HttpResponseMessage.Content.ReadAs(ContentData) then + exit; + + if not this.ParseContentData(ContentData) then + ContentData := ''; + + if ContentData = '' then + this.EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, StrSubstNo(this.CouldNotRetrieveDocumentErr, DocumentId)); + + Clear(TempBlob); + TempBlob.CreateOutStream(TextEncoding::UTF8).WriteText(ContentData); + EDocument."Document Id" := CopyStr(DocumentId, 1, MaxStrLen(EDocument."Document Id")); + this.EDocumentLogHelper.InsertLog(EDocument, EDocumentService, TempBlob, "E-Document Service Status"::Imported); + this.Connection.RemoveDocumentFromReceived(EDocument, HttpRequestMessage, HttpResponseMessage); + this.EDocumentLogHelper.InsertIntegrationLog(EDocument, EDocumentService, HttpRequestMessage, HttpResponseMessage); + end; + + #endregion + +} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/EnvironmentType.Enum.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/EnvironmentType.Enum.al new file mode 100644 index 0000000000..a9ff9166b2 --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/EnvironmentType.Enum.al @@ -0,0 +1,20 @@ +// ------------------------------------------------------------------------------------------------ +// 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; + +enum 6380 EnvironmentType +{ + Access = Internal; + Caption = 'Environment Type', Locked = true; + + value(0; Production) + { + Caption = 'Production', Locked = true; + } + value(1; Test) + { + Caption = 'Test', Locked = true; + } +} \ No newline at end of file From 103aaa8c84602f7bfe39db9f0d9a137eba26d9eb Mon Sep 17 00:00:00 2001 From: geschwint Date: Mon, 28 Oct 2024 14:11:59 +0100 Subject: [PATCH 35/63] Refactor General Overhaul --- .../SignUp/app/src/APIRequests.Codeunit.al | 255 +++----- .../SignUp/app/src/Authentication.Codeunit.al | 331 ++-------- .../SignUp/app/src/Connection.Codeunit.al | 110 ++-- .../SignUp/app/src/HelpersImpl.Codeunit.al | 95 ++- .../Integration/IntegrationImpl.Codeunit.al | 36 +- .../src/Jobs/GetReadyStatusJob.Codeunit.al | 100 +-- .../app/src/Jobs/PatchSentJob.Codeunit.al | 44 +- .../app/src/Permissions/Edit.PermissionSet.al | 5 +- .../src/Permissions/Objects.PermissionSet.al | 18 +- .../app/src/Permissions/Read.PermissionSet.al | 5 +- .../SignUp/app/src/Processing.Codeunit.al | 594 +++--------------- .../app/src/Setup/ConnectionSetup.Table.al | 54 +- .../app/src/Setup/ConnectionSetupCard.Page.al | 93 +-- 13 files changed, 462 insertions(+), 1278 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al index a17bd2d256..74059d2555 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al @@ -5,221 +5,106 @@ 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:///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; + APIRequestsImpl: Codeunit APIRequestsImpl; + + #region public methods + + /// + /// The method sends a file to the API. + /// https://[BASEURL]/api/Peppol + /// + /// TempBlob + /// EDocument table + /// Http Request Message + /// Http Response Message + /// True if successfully completed + procedure SendFilePostRequest(var TempBlob: Codeunit "Temp Blob"; EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean 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)); + exit(this.APIRequestsImpl.SendFilePostRequest(TempBlob, EDocument, HttpRequestMessage, HttpResponseMessage)); end; - // https:///api/Peppol/status?peppolInstanceId= + /// + /// The method checks the status of the sent document. + /// https://[BASE URL]/api/Peppol/status?peppolInstanceId= + /// + /// EDocument table + /// Http Request Message + /// Http Response Message + /// True if successfully completed 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)); + exit(this.APIRequestsImpl.GetSentDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage)); end; - // https:///api/Peppol/outbox?peppolInstanceId= - procedure PatchADocument(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean - var - ConnectionSetup: Record ConnectionSetup; + /// + /// The method modifies the document. + /// https://[BASE URL]/api/Peppol/outbox?peppolInstanceId= + /// + /// EDocument table + /// Http Request Message + /// Http Response Message + /// True if successfully completed + procedure PatchDocument(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean begin - InitRequest(ConnectionSetup, HttpRequestMessage, HttpResponseMessage); - HttpRequestMessage := PrepareRequestMsg("Http Request Type"::PATCH, ConnectionSetup.ServiceURL + '/api/Peppol/outbox?peppolInstanceId=' + EDocument."Document Id"); - exit(SendRequest(HttpRequestMessage, HttpResponseMessage)); + exit(this.APIRequestsImpl.PatchDocument(EDocument, HttpRequestMessage, HttpResponseMessage)); end; - // https:///api/Peppol/Inbox?peppolId= - procedure GetReceivedDocumentsRequest(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage; Parameters: Dictionary of [Text, Text]): Boolean - var - ConnectionSetup: Record ConnectionSetup; + /// + /// The method gets the received document request. + /// https://[BASE URL]/api/Peppol/Inbox?peppolId= + /// + /// Http Request Message + /// Http Response Message + /// True if successfully completed + procedure GetReceivedDocumentsRequest(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean 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)); + exit(this.APIRequestsImpl.GetReceivedDocumentsRequest(HttpRequestMessage, HttpResponseMessage)); end; - // https:///api/Peppol/inbox-document?peppolId= + /// + /// The method gets the target document request. + /// https://[BASE URL]/api/Peppol/inbox-document?peppolId= + /// + /// Document ID + /// Http Request Message + /// Http Response Message + /// True if successfully completed 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)); + exit(this.APIRequestsImpl.GetTargetDocumentRequest(DocumentId, HttpRequestMessage, HttpResponseMessage)); end; - // https:///api/Peppol/inbox?peppolInstanceId= + /// + /// The method modifies the received document. + /// // https://[BASE URL]/api/Peppol/inbox?peppolInstanceId= + /// + /// EDocument table + /// Http Request Message + /// Http Response Message + /// True if successfully completed 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)); + exit(this.APIRequestsImpl.PatchReceivedDocument(EDocument, HttpRequestMessage, HttpResponseMessage)); end; + /// + /// The method gets the marketplace credentials. + /// + /// Http Request Message + /// Http Response Message + /// True if successfully completed 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 - "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"); + exit(this.APIRequestsImpl.GetMarketPlaceCredentials(HttpRequestMessage, HttpResponseMessage)); 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; + #endregion } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Authentication.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Authentication.Codeunit.al index 984108a704..4cab43fe24 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Authentication.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Authentication.Codeunit.al @@ -4,320 +4,95 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -using System.Azure.KeyVault; -using System.Environment; -using System.Reflection; - -codeunit 6381 Auth +codeunit 6381 Authentication { Access = Internal; - procedure InitConnectionSetup() var - LConnectionSetup: Record ConnectionSetup; + AuthenticationImpl: Codeunit AuthenticationImpl; + + /// + /// The method initializes the connection setup. + /// + procedure InitConnectionSetup() begin - if LConnectionSetup.Get() then - exit; - LConnectionSetup."Authentication URL" := AuthURLTxt; - LConnectionSetup.ServiceURL := ProdServiceAPITxt; - StorageSet(LConnectionSetup."Client Tenant", ProdTenantIdTxt); - LConnectionSetup.Insert(); + this.AuthenticationImpl.InitConnectionSetup(); end; + /// + /// The method returns the onboarding URL. + /// + /// Onboarding URL procedure GetRootOnboardingUrl(): Text begin - exit(GetRootUrl() + '/supm/landingpage?EntraTenantId=' + GetBCInstanceIdentifier()); + exit(this.AuthenticationImpl.GetRootOnboardingUrl()); end; + /// + /// The method creates the client credentials. + /// [NonDebuggable] procedure CreateClientCredentials() - var - HttpRequestMessage: HttpRequestMessage; - HttpResponseMessage: HttpResponseMessage; - JText: Text; - ClientId: Text; - ClientSecret: SecretText; - begin - if not GetClientCredentials(HttpRequestMessage, HttpResponseMessage) then - Error(ErrorUnableToCreateClientCredentialsLbl); - if HttpResponseMessage.Content.ReadAs(JText) then begin - ClientId := Helpers.GetJsonValueFromText(JText, 'clientId'); - ClientSecret := Helpers.GetJsonValueFromText(JText, 'clientSecret'); - if (ClientId <> '') and (not ClientSecret.IsEmpty()) then - SaveClientCredentials(ClientId, ClientSecret); - end; - end; - - [NonDebuggable] - local procedure GetClientCredentials(var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean - var - APIRequests: Codeunit APIRequests; - begin - APIRequests.GetMarketPlaceCredentials(HttpRequest, HttpResponse); - if not HttpResponse.IsSuccessStatusCode then - exit(false); - exit(Helpers.ParseJsonString(HttpResponse.Content) <> ''); - end; - - procedure GetBearerAuthText(): SecretText; - begin - exit(secretStrSubstNo(BearerTxt, GetAuthBearerToken())); - end; - - procedure GetRootBearerAuthText(): SecretText; - begin - exit(secretStrSubstNo(BearerTxt, GetRootAuthBearerToken())); - end; - - procedure GetAuthBearerToken(): SecretText; - var - ConnectionAuth: Record ConnectionAuth; - HttpError: Text; - begin - ConnectionAuth.GetRecordOnce(); - if ConnectionAuth."Token Timestamp" < CurrentDateTime() + 60 * 1000 then - if not RefreshAccessToken(HttpError) then - Error(HttpError); - - exit(StorageGet(ConnectionAuth."Access Token", DataScope::Company)); - end; - - procedure GetRootAuthBearerToken() ReturnValue: SecretText; - begin - if not GetRootAccessToken(ReturnValue) then - Error(ErrorTokenLbl); - end; - - [NonDebuggable] - local procedure RefreshAccessToken(var HttpError: Text): Boolean; - var - ConnectionAuth: Record ConnectionAuth; - SecretToken: SecretText; - RefreshToken: SecretText; - begin - ConnectionAuth.GetRecordOnce(); - if not GetClientAccessToken(SecretToken) then begin - HttpError := GetLastErrorText(); - exit(false); - end; - ConnectionAuth."Token Timestamp" := CurrentDateTime(); - SaveTokens(ConnectionAuth, DataScope::Company, SecretToken, RefreshToken); - ConnectionAuth.Modify(); - exit(true); - end; - - [NonDebuggable] - local procedure GetRootAccessToken(var AccessToken: SecretText): Boolean - begin - exit(GetAccessToken(AccessToken, GetRootId(), GetRootSecret(), GetRootTenant())); - end; - - [NonDebuggable] - local procedure GetClientAccessToken(var AccessToken: SecretText): Boolean - begin - ConnectionSetup.GetRecordOnce(); - exit(GetAccessToken( - AccessToken, - StorageGetText(ConnectionSetup."Client ID", DataScope::Module), - StorageGet(ConnectionSetup."Client Secret", DataScope::Module), - StorageGetText(ConnectionSetup."Client Tenant", DataScope::Module))); - end; - - [NonDebuggable] - local procedure GetAccessToken(var AccessToken: SecretText; ClientId: Text; ClientSecret: SecretText; ClientTenant: Text): Boolean - var - TypeHelper: Codeunit "Type Helper"; - HttpClient: HttpClient; - HttpRequestMessage: HttpRequestMessage; - HttpResponseMessage: HttpResponseMessage; - HttpContent: HttpContent; - HttpHeaders: HttpHeaders; - ContentText: SecretText; - JText: Text; - begin - ConnectionSetup.GetRecordOnce(); - ConnectionSetup.TestField("Authentication URL"); - - ContentText := SecretStrSubstNo(ContentTemplateTxt, TypeHelper.UriEscapeDataString(ClientId), ClientSecret, TypeHelper.UriEscapeDataString(ClientId)); - - HttpContent.WriteFrom(ContentText); - - HttpContent.GetHeaders(HttpHeaders); - HttpHeaders.Remove('Content-Type'); - HttpHeaders.Add('Content-Type', 'application/x-www-form-urlencoded'); - - HttpRequestMessage.Method := 'POST'; - HttpRequestMessage.SetRequestUri(StrSubstNo(ConnectionSetup."Authentication URL", ClientTenant)); - HttpRequestMessage.Content(HttpContent); - - Clear(AccessToken); - if HttpClient.Send(HttpRequestMessage, HttpResponseMessage) then - if HttpResponseMessage.IsSuccessStatusCode() then - if HttpResponseMessage.Content.ReadAs(JText) then - AccessToken := Helpers.GetJsonValueFromText(JText, 'access_token'); - exit(not AccessToken.IsEmpty()); - end; - - local procedure SaveTokens(var ConnectionAuth: Record ConnectionAuth; TokenDataScope: DataScope; AccessToken: SecretText; RefreshToken: SecretText) begin - StorageSet(ConnectionAuth."Access Token", AccessToken, TokenDataScope); - StorageSet(ConnectionAuth."Refresh Token", RefreshToken, TokenDataScope); + this.AuthenticationImpl.CreateClientCredentials(); end; - procedure SaveClientCredentials(ClientId: Text; ClientSecret: SecretText) + /// + /// The method returns the bearer authentication text. + /// + /// Bearer authentication token + procedure GetBearerAuthToken(): SecretText; begin - Clear(ConnectionSetup); - ConnectionSetup.GetRecordOnce(); - StorageSet(ConnectionSetup."Client ID", ClientId); - StorageSet(ConnectionSetup."Client Secret", ClientSecret); - ConnectionSetup.Modify(); - Clear(ConnectionSetup); + exit(this.AuthenticationImpl.GetBearerAuthToken()); end; - local procedure StorageGet(TokenKey: Text; TokenDataScope: DataScope) TokenValueAsSecret: SecretText + /// + /// The method returns the root bearer authentication token. + /// + /// Root bearer authentication token + procedure GetRootBearerAuthToken(): SecretText; begin - if not StorageContains(TokenKey, TokenDataScope) then - exit(TokenValueAsSecret); - - IsolatedStorage.Get(TokenKey, TokenDataScope, TokenValueAsSecret); - end; - - [NonDebuggable] - local procedure StorageGetText(TokenKey: Text; TokenDataScope: DataScope) TokenValue: Text - begin - if not StorageContains(TokenKey, TokenDataScope) then - exit(TokenValue); - - IsolatedStorage.Get(TokenKey, TokenDataScope, TokenValue); - end; - - local procedure StorageContains(TokenKey: Text; TokenDataScope: DataScope): Boolean - begin - exit(IsolatedStorage.Contains(TokenKey, TokenDataScope)); + exit(this.AuthenticationImpl.GetRootBearerAuthToken()); end; + /// + /// The mehod saves the token to the storage. + /// + /// Token Key + /// Token [NonDebuggable] procedure StorageSet(var TokenKey: Guid; Value: Text) begin - ValidateValueKey(TokenKey); - if Value = '' then begin - if IsolatedStorage.Contains(TokenKey, DataScope::Module) then - IsolatedStorage.Delete(TokenKey, DataScope::Module) - end else - IsolatedStorage.Set(TokenKey, Value, DataScope::Module); - end; - - procedure StorageSet(var TokenKey: Guid; Value: SecretText) - begin - ValidateValueKey(TokenKey); - if Value.IsEmpty() then begin - if IsolatedStorage.Contains(TokenKey, DataScope::Module) then - IsolatedStorage.Delete(TokenKey, DataScope::Module) - end else - IsolatedStorage.Set(TokenKey, Value, DataScope::Module); - end; - - procedure StorageSet(var TokenKey: Guid; Value: SecretText; TokenDataScope: DataScope) - begin - ValidateValueKey(TokenKey); - if Value.IsEmpty() then begin - if IsolatedStorage.Contains(TokenKey, TokenDataScope) then - IsolatedStorage.Delete(TokenKey, TokenDataScope) - end else - IsolatedStorage.Set(TokenKey, Value, TokenDataScope); - end; - - local procedure ValidateValueKey(var ValueKey: Guid) - begin - if IsNullGuid(ValueKey) then - ValueKey := CreateGuid(); + this.AuthenticationImpl.StorageSet(TokenKey, Value); end; + /// + /// The mehod saves the token to the storage. + /// + /// Token Key + /// Token [NonDebuggable] - local procedure GetRootId() ReturnValue: Text - begin - if FetchSecretFromKeyVault('-root-id', ReturnValue) then - exit; - if ConnectionSetup.GetRecordOnce() then begin - ConnectionSetup.TestField("Root App ID"); - ReturnValue := StorageGetText(ConnectionSetup."Root App ID", DataScope::Module); - end; - end; - - [NonDebuggable] - local procedure GetRootSecret() ReturnValue: Text + procedure StorageSet(var TokenKey: Guid; Value: SecretText) begin - if FetchSecretFromKeyVault('signup-root-secret', ReturnValue) then - exit; - if ConnectionSetup.GetRecordOnce() then begin - ConnectionSetup.TestField("Root Secret"); - ReturnValue := StorageGetText(ConnectionSetup."Root Secret", DataScope::Module); - end; + this.AuthenticationImpl.StorageSet(TokenKey, Value); end; - [NonDebuggable] - local procedure GetRootTenant() ReturnValue: Text + /// + /// The method returns BC instance identifier. + /// + /// Identifier + procedure GetBCInstanceIdentifier() Identifier: Text begin - if FetchSecretFromKeyVault('signup-root-tenant', ReturnValue) then - exit; - if ConnectionSetup.GetRecordOnce() then begin - ConnectionSetup.TestField("Root Tenant"); - ReturnValue := StorageGetText(ConnectionSetup."Root Tenant", DataScope::Module); - end; + exit(this.AuthenticationImpl.GetBCInstanceIdentifier()); end; + /// + /// The method returns the root URL. + /// + /// [NonDebuggable] procedure GetRootUrl() ReturnValue: Text begin - if FetchSecretFromKeyVault('signup-root-url', ReturnValue) then - exit; - if ConnectionSetup.GetRecordOnce() then begin - ConnectionSetup.TestField("Root Market URL"); - ReturnValue := StorageGetText(ConnectionSetup."Root Market URL", DataScope::Module); - end; - end; - - [NonDebuggable] - local procedure FetchSecretFromKeyVault(KeyName: Text; var KeyValue: Text): Boolean - var - AzureKeyVault: Codeunit "Azure Key Vault"; - EnvironmentInfo: Codeunit "Environment Information"; - begin - if EnvironmentInfo.IsSaaSInfrastructure() then - exit(AzureKeyVault.GetAzureKeyVaultSecret(KeyName, KeyValue)); + exit(this.AuthenticationImpl.GetRootUrl()); end; - - procedure GetBCInstanceIdentifier() Identifier: Text - var - AADTenantID, AADDomainName : Text; - begin - Identifier := '10000000-d8ef-4dfb-b761-ffb073057794'; // Hardcoded fake during testing only - if GetAADTenantInformation(AADTenantID, AADDomainName) then - Identifier := AADTenantID; - end; - - local procedure GetAADTenantInformation(var AADTenantID: Text; var AADDomainName: Text): Boolean - var - ErrorSensitive: Codeunit ErrorSensitive; - begin - Clear(ErrorSensitive); - ErrorSensitive.SetParameter('AADDETAILS'); - Commit(); - if ErrorSensitive.Run() then begin - AADTenantID := ErrorSensitive.GetFirstResult(); - AADDomainName := ErrorSensitive.GetSecondResult(); - exit(true); - end; - end; - - var - ConnectionSetup: Record ConnectionSetup; - Helpers: Codeunit Helpers; - BearerTxt: Label 'Bearer %1', Comment = '%1 = text value', Locked = true; - AuthURLTxt: Label 'https://login.microsoftonline.com/%1/oauth2/token', Comment = '%1 Entra Tenant Id', Locked = true; - ProdTenantIdTxt: Label '0d725623-dc26-484f-a090-b09d2003d092', Locked = true; - ProdServiceAPITxt: Label 'https://edoc.exflow.io', Locked = true; - ContentTemplateTxt: Label 'grant_type=client_credentials&client_id=%1&client_secret=%2&resource=%3', Locked = true; - ErrorTokenLbl: Label 'Unable to fetch a root token.'; - ErrorUnableToCreateClientCredentialsLbl: Label 'Unable to create client credentials.'; } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Connection.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Connection.Codeunit.al index 7543cbe345..69d6451946 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Connection.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Connection.Codeunit.al @@ -5,88 +5,72 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.EServices.EDocument; -using Microsoft.Purchases.Document; -using Microsoft.Purchases.Posting; using System.Utilities; codeunit 6382 Connection { Access = Internal; - Permissions = tabledata "E-Document" = m; - procedure HandleSendFilePostRequest(var TempBlob: Codeunit "Temp Blob"; var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean - begin - APIRequests.SendFilePostRequest(TempBlob, EDocument, HttpRequest, HttpResponse); - exit(CheckIfSuccessfulRequest(EDocument, HttpResponse)); - end; - - procedure CheckDocumentStatus(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean - begin - APIRequests.GetSentDocumentStatus(EDocument, HttpRequest, HttpResponse); - exit(CheckIfSuccessfulRequest(EDocument, HttpResponse)); - end; - - procedure GetReceivedDocuments(var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean var - Parameters: Dictionary of [Text, Text]; - begin - APIRequests.GetReceivedDocumentsRequest(HttpRequest, HttpResponse, Parameters); - - if not HttpResponse.IsSuccessStatusCode then - exit(false); + ConnectionImpl: Codeunit ConnectionImpl; - exit(Helpers.ParseJsonString(HttpResponse.Content) <> ''); + /// + /// The methods sends a file to the API. + /// + /// Content + /// E-Document record + /// Http Request Message + /// Http Response Message + /// True - if completed successfully + procedure SendFilePostRequest(var TempBlob: Codeunit "Temp Blob"; var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + begin + exit(this.ConnectionImpl.SendFilePostRequest(TempBlob, EDocument, HttpRequestMessage, HttpResponseMessage)); end; - procedure HandleGetTargetDocumentRequest(DocumentId: Text; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean + /// + /// The method checks the status of the document. + /// + /// E-Document record + /// HttpRequestMessage + /// HttpResponseMessage + /// True - if completed successfully + procedure CheckDocumentStatus(var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean begin - APIRequests.GetTargetDocumentRequest(DocumentId, HttpRequest, HttpResponse); - exit(HttpResponse.IsSuccessStatusCode); + exit(this.ConnectionImpl.CheckDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage)); end; - procedure RemoveDocumentFromReceived(EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean + /// + /// The method gets received documents. + /// + /// HttpRequestMessage + /// HttpResponseMessage + /// True - if completed successfully + procedure GetReceivedDocuments(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean begin - APIRequests.PatchReceivedDocument(EDocument, HttpRequest, HttpResponse); - exit(HttpResponse.IsSuccessStatusCode); + exit(this.ConnectionImpl.GetReceivedDocuments(HttpRequestMessage, HttpResponseMessage)); end; - local procedure CheckIfSuccessfulRequest(EDocument: Record "E-Document"; HttpResponse: HttpResponseMessage): Boolean - var - EDocumentErrorHelper: Codeunit "E-Document Error Helper"; + /// + /// The method gets the target document. + /// + /// DocumentId + /// HttpRequestMessage + /// HttpResponseMessage + /// True - if completed successfully + procedure GetTargetDocumentRequest(DocumentId: Text; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean begin - if HttpResponse.IsSuccessStatusCode then - exit(true); - - if HttpResponse.IsBlockedByEnvironment then - EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, EnvironmentBlocksErr) - else - EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, StrSubstNo(UnsuccessfulResponseErr, HttpResponse.HttpStatusCode, HttpResponse.ReasonPhrase)); + exit(this.ConnectionImpl.GetTargetDocumentRequest(DocumentId, HttpRequestMessage, HttpResponseMessage)); end; - [EventSubscriber(ObjectType::Codeunit, Codeunit::"Purch.-Post", 'OnAfterCheckAndUpdate', '', false, false)] - local procedure CheckOnPosting(var PurchaseHeader: Record "Purchase Header"; CommitIsSuppressed: Boolean; PreviewMode: Boolean) - var - EDocument: Record "E-Document"; - EDocumentService: Record "E-Document Service"; - EDocumentServiceStatus: Record "E-Document Service Status"; + /// + /// The method removes the document from received. + /// + /// E-Document record + /// HttpRequestMessage + /// HttpResponseMessage + /// True - if completed successfully + procedure RemoveDocumentFromReceived(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean begin - EDocument.SetRange("Document Record ID", PurchaseHeader.RecordId); - if not EDocument.FindFirst() then - exit; - - EDocumentService.SetRange("Service Integration", EDocumentService."Service Integration"::"ExFlow E-Invoicing"); - if EDocumentService.FindFirst() then; - EDocumentServiceStatus.SetRange("E-Document Entry No", EDocument."Entry No"); - EDocumentServiceStatus.SetRange("E-Document Service Code", EDocumentService.Code); - if EDocumentServiceStatus.FindSet() then - repeat - EDocumentServiceStatus.TestField(EDocumentServiceStatus.Status, EDocumentServiceStatus.Status::Approved); - until EDocumentServiceStatus.Next() = 0; + exit(this.ConnectionImpl.RemoveDocumentFromReceived(EDocument, HttpRequestMessage, HttpResponseMessage)); end; - - var - APIRequests: Codeunit APIRequests; - Helpers: Codeunit Helpers; - UnsuccessfulResponseErr: Label 'There was an error sending the request. Response code: %1 and error message: %2', Comment = '%1 - http response status code, e.g. 400, %2- error message'; - EnvironmentBlocksErr: Label 'The request to send documents has been blocked. To resolve the problem, enable outgoing HTTP requests for the E-Document apps on the Extension Management page.'; } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/HelpersImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/HelpersImpl.Codeunit.al index 4b1406aba7..d6bb899b42 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/HelpersImpl.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/HelpersImpl.Codeunit.al @@ -4,60 +4,89 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -using System.Text; +using System.Reflection; +using Microsoft.Utilities; +using System.Integration; -codeunit 6385 Helpers +codeunit 6385 HelpersImpl { Access = Internal; + var + ClaimTypeTxt: Label 'exp', Locked = true; + + #region public methods + [NonDebuggable] - procedure ParseJsonString(HttpContentResponse: HttpContent): Text + procedure ParseJsonString(HttpContent: HttpContent): Text var - ResponseJObject: JsonObject; - ResponseJson: Text; - Result: Text; - IsJsonResponse: Boolean; + JsonObject: JsonObject; + Content: Text; begin - HttpContentResponse.ReadAs(Result); - IsJsonResponse := ResponseJObject.ReadFrom(Result); - if IsJsonResponse then - ResponseJObject.WriteTo(ResponseJson) - else - exit(''); + if not HttpContent.ReadAs(Content) then + exit; - if not TryInitJson(ResponseJson) then - exit(''); - - exit(Result); + if JsonObject.ReadFrom(Content) then + exit(Content); end; - [TryFunction] [NonDebuggable] - local procedure TryInitJson(JsonTxt: Text) + procedure GetJsonValueFromText(JsonText: Text; Path: Text): Text var - JsonManagement: Codeunit "JSON Management"; + JsonObject: JsonObject; + JsonToken: JsonToken; begin - JSONManagement.InitializeObject(JsonTxt); + if JsonObject.ReadFrom(JsonText) then + if JsonObject.SelectToken(Path, JsonToken) then + exit(this.GetJsonValue(JsonToken.AsValue())); + end; + + procedure IsTokenValid(InToken: SecretText): Boolean + begin + exit(this.GetTokenDateTimeValue(InToken, this.ClaimTypeTxt) > CurrentDateTime()); + end; + + #endregion + + #region local methods + + local procedure GetTokenDateTimeValue(InToken: SecretText; ClaimType: Text): DateTime + var + TypeHelper: Codeunit "Type Helper"; + Timestamp: Decimal; + begin + if Evaluate(Timestamp, this.GetValueFromToken(InToken, ClaimType)) then + exit(TypeHelper.EvaluateUnixTimestamp(Timestamp)); end; [NonDebuggable] - procedure GetJsonValueFromText(JsonText: Text; Path: Text) return: Text + local procedure GetValueFromToken(InToken: SecretText; ClaimType: Text): Text var - JObject: JsonObject; - JToken: JsonToken; + TempNameValueBuffer: Record "Name/Value Buffer" temporary; + SOAPWebServiceRequestMgt: Codeunit "SOAP Web Service Request Mgt."; begin - if JObject.ReadFrom(JsonText) then - if JObject.SelectToken(Path, JToken) then - return := GetJsonValue(JToken.AsValue()); + if InToken.IsEmpty() then + exit; + + TempNameValueBuffer.DeleteAll(); + SOAPWebServiceRequestMgt.GetTokenDetailsAsNameBuffer(InToken, TempNameValueBuffer); + TempNameValueBuffer.Reset(); + TempNameValueBuffer.SetRange(Name, ClaimType); + if TempNameValueBuffer.FindFirst() then + exit(TempNameValueBuffer.Value); end; [NonDebuggable] - procedure GetJsonValue(JValue: JsonValue): Text + local procedure GetJsonValue(JsonValue: JsonValue): Text begin - if JValue.IsNull then - exit(''); - if JValue.IsUndefined then - exit(''); - exit(JValue.AsText()); + if JsonValue.IsNull() then + exit; + + if JsonValue.IsUndefined() then + exit; + + exit(JsonValue.AsText()); end; + + #endregion } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/IntegrationImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/IntegrationImpl.Codeunit.al index 55d28f88d0..019ad06a32 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/IntegrationImpl.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/IntegrationImpl.Codeunit.al @@ -11,41 +11,46 @@ codeunit 6386 IntegrationImpl implements "E-Document Integration" { Access = Internal; - procedure Send(var EDocument: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) + var + Processing: Codeunit Processing; + BatchSendNotSupportedErr: Label 'Batch sending is not supported in this version'; + CancelNotSupportedErr: Label 'Cancel is not supported in this version'; + + procedure Send(var EDocument: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) var begin - Processing.SendEDocument(EDocument, TempBlob, IsAsync, HttpRequest, HttpResponse); + this.Processing.SendEDocument(EDocument, TempBlob, IsAsync, HttpRequestMessage, HttpResponseMessage); end; - procedure SendBatch(var EDocuments: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) + procedure SendBatch(var EDocuments: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) begin IsAsync := false; - Error(BatchSendNotSupportedErr); + Error(this.BatchSendNotSupportedErr); end; - procedure GetResponse(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean + procedure GetResponse(var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean begin - exit(Processing.GetDocumentResponse(EDocument, HttpRequest, HttpResponse)); + exit(this.Processing.GetDocumentResponse(EDocument, HttpRequestMessage, HttpResponseMessage)); end; - procedure GetApproval(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean + procedure GetApproval(var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean begin - exit(Processing.GetDocumentApproval(EDocument, HttpRequest, HttpResponse)); + exit(this.Processing.GetDocumentApproval(EDocument, HttpRequestMessage, HttpResponseMessage)); end; - procedure Cancel(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean + procedure Cancel(var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean begin - Error(CancelNotSupportedErr); + Error(this.CancelNotSupportedErr); end; - procedure ReceiveDocument(var TempBlob: Codeunit "Temp Blob"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) + procedure ReceiveDocument(var TempBlob: Codeunit "Temp Blob"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) begin - Processing.ReceiveDocument(TempBlob, HttpRequest, HttpResponse); + this.Processing.ReceiveDocument(TempBlob, HttpRequestMessage, HttpResponseMessage); end; procedure GetDocumentCountInBatch(var TempBlob: Codeunit "Temp Blob"): Integer begin - exit(Processing.GetDocumentCountInBatch(TempBlob)); + exit(this.Processing.GetDocumentCountInBatch(TempBlob)); end; procedure GetIntegrationSetup(var SetupPage: Integer; var SetupTable: Integer) @@ -53,9 +58,4 @@ codeunit 6386 IntegrationImpl implements "E-Document Integration" SetupPage := Page::ConnectionSetupCard; SetupTable := Database::ConnectionSetup; end; - - var - Processing: Codeunit Processing; - BatchSendNotSupportedErr: Label 'Batch sending is not supported in this version'; - CancelNotSupportedErr: Label 'Cancel is not supported in this version'; } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/GetReadyStatusJob.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/GetReadyStatusJob.Codeunit.al index 92cb4f7474..64b10485a4 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/GetReadyStatusJob.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/GetReadyStatusJob.Codeunit.al @@ -8,22 +8,29 @@ using System.Telemetry; using System.Threading; using Microsoft.EServices.EDocument; -codeunit 6384 GetReadyStatus +codeunit 6384 GetReadyStatusJob { TableNo = "Job Queue Entry"; Access = Internal; + InherentEntitlements = X; + InherentPermissions = X; + + var + EDocTelemetryGetResponseScopeStartLbl: Label 'E-Document Get Response: Start Scope', Locked = true; + EDocTelemetryGetResponseScopeEndLbl: Label 'E-Document Get Response: End Scope', Locked = true; trigger OnRun() var + JobHelperImpl: Codeunit JobHelperImpl; BlankRecordId: RecordId; begin - if not IsEDocumentStatusSent() then + if not this.IsEDocumentStatusSent() then exit; - ProcessSentDocuments(); + this.ProcessSentDocuments(); - if IsEDocumentStatusSent() then - ScheduleEDocumentJob(Codeunit::GetReadyStatus, BlankRecordId, 300000); + if this.IsEDocumentStatusSent() then + JobHelperImpl.ScheduleEDocumentJob(Codeunit::GetReadyStatusJob, BlankRecordId, 300000); end; local procedure ProcessSentDocuments() @@ -31,52 +38,46 @@ codeunit 6384 GetReadyStatus EDocumentServiceStatus: Record "E-Document Service Status"; EDocumentService: Record "E-Document Service"; EDocument: Record "E-Document"; + JobHelperImpl: Codeunit JobHelperImpl; begin + EDocumentServiceStatus.SetLoadFields("E-Document Service Code", "E-Document Entry No"); EDocumentServiceStatus.SetRange(Status, EDocumentServiceStatus.Status::Sent); if EDocumentServiceStatus.FindSet() then repeat - FetchEDocumentAndService(EDocument, EDocumentService, EDocumentServiceStatus); - HandleResponse(EDocument, EDocumentService, EDocumentServiceStatus); - FetchEDocumentAndService(EDocument, EDocumentService, EDocumentServiceStatus); + JobHelperImpl.FetchEDocumentAndService(EDocument, EDocumentService, EDocumentServiceStatus); + this.HandleResponse(EDocument, EDocumentService); until EDocumentServiceStatus.Next() = 0; end; - local procedure FetchEDocumentAndService(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; var EDocumentServiceStatus: Record "E-Document Service Status") - begin - EDocumentService.Get(EDocumentServiceStatus."E-Document Service Code"); - EDocument.Get(EDocumentServiceStatus."E-Document Entry No"); - end; - - local procedure HandleResponse(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; var EDocumentServiceStatus: Record "E-Document Service Status") + local procedure HandleResponse(var EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service") var Processing: Codeunit Processing; + JobHelperImpl: Codeunit JobHelperImpl; BlankRecordId: RecordId; - HttpResponse: HttpResponseMessage; - HttpRequest: HttpRequestMessage; + HttpResponseMessage: HttpResponseMessage; + HttpRequestMessage: HttpRequestMessage; begin - if GetResponse(EDocumentServiceStatus, HttpRequest, HttpResponse) then begin - Processing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Approved, 0, HttpRequest, HttpResponse); - ScheduleEDocumentJob(Codeunit::PatchSent, BlankRecordId, 300000); + if this.GetResponse(EDocument, HttpRequestMessage, HttpResponseMessage) then begin + Processing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Approved, 0, HttpRequestMessage, HttpResponseMessage); + JobHelperImpl.ScheduleEDocumentJob(Codeunit::PatchSentJob, BlankRecordId, 300000); end; - end; - local procedure GetResponse(var EDocumentServiceStatus: Record "E-Document Service Status"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) ReturnStatus: Boolean + local procedure GetResponse(var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) ReturnStatus: Boolean var - EDocument: Record "E-Document"; Processing: Codeunit Processing; + Telemetry: Codeunit Telemetry; TelemetryDimensions: Dictionary of [Text, Text]; begin // Commit before create document with error handling Commit(); - Telemetry.LogMessage('', EDocTelemetryGetResponseScopeStartLbl, Verbosity::Normal, DataClassification::OrganizationIdentifiableInformation, TelemetryScope::All, TelemetryDimensions); - EDocument.Get(EDocumentServiceStatus."E-Document Entry No"); + Telemetry.LogMessage('', this.EDocTelemetryGetResponseScopeStartLbl, Verbosity::Normal, DataClassification::OrganizationIdentifiableInformation, TelemetryScope::All, TelemetryDimensions); - if Processing.GetDocumentSentResponse(EDocument, HttpRequest, HttpResponse) then + if Processing.GetDocumentSentResponse(EDocument, HttpRequestMessage, HttpResponseMessage) then ReturnStatus := true; - Telemetry.LogMessage('', EDocTelemetryGetResponseScopeEndLbl, Verbosity::Normal, DataClassification::OrganizationIdentifiableInformation, TelemetryScope::All); + Telemetry.LogMessage('', this.EDocTelemetryGetResponseScopeEndLbl, Verbosity::Normal, DataClassification::OrganizationIdentifiableInformation, TelemetryScope::All); end; local procedure IsEDocumentStatusSent(): Boolean @@ -86,49 +87,4 @@ codeunit 6384 GetReadyStatus EdocumentServiceStatus.SetRange(Status, EdocumentServiceStatus.Status::Sent); exit(not EdocumentServiceStatus.IsEmpty()); end; - - procedure ScheduleEDocumentJob(CodeunitId: Integer; JobRecordId: RecordId; EarliestStartDateTime: Integer): Guid - var - JobQueueEntry: Record "Job Queue Entry"; - TelemetryDimensions: Dictionary of [Text, Text]; - begin - if IsJobQueueScheduled(CodeunitId) then - exit; - - JobQueueEntry.Init(); - JobQueueEntry."Object Type to Run" := JobQueueEntry."Object Type to Run"::Codeunit; - JobQueueEntry."Object ID to Run" := CodeunitId; - JobQueueEntry."Record ID to Process" := JobRecordId; - JobQueueEntry."User Session ID" := SessionId(); - JobQueueEntry."Job Queue Category Code" := JobQueueCategoryTok; - JobQueueEntry."No. of Attempts to Run" := 0; - JobQueueEntry."Earliest Start Date/Time" := CurrentDateTime + EarliestStartDateTime; - - TelemetryDimensions.Add('Job Queue Id', JobQueueEntry.ID); - TelemetryDimensions.Add('Codeunit Id', Format(CodeunitId)); - TelemetryDimensions.Add('Record Id', Format(JobRecordId)); - TelemetryDimensions.Add('User Session ID', Format(JobQueueEntry."User Session ID")); - TelemetryDimensions.Add('Earliest Start Date/Time', Format(JobQueueEntry."Earliest Start Date/Time")); - Telemetry.LogMessage('', EDocumentJobTelemetryLbl, Verbosity::Normal, DataClassification::OrganizationIdentifiableInformation, TelemetryScope::All, TelemetryDimensions); - Codeunit.Run(Codeunit::"Job Queue - Enqueue", JobQueueEntry); - exit(JobQueueEntry.ID); - end; - - local procedure IsJobQueueScheduled(CodeunitId: Integer): Boolean - var - JobQueueEntry: Record "Job Queue Entry"; - begin - JobQueueEntry.SetRange("Object Type to Run", JobQueueEntry."Object Type to Run"::Codeunit); - JobQueueEntry.SetRange("Object ID to Run", CodeunitId); - JobQueueEntry.SetFilter(Status, '%1|%2', JobQueueEntry.Status::Ready, JobQueueEntry.Status::"In Process"); - if not JobQueueEntry.IsEmpty() then - exit(true); - end; - - var - Telemetry: Codeunit Telemetry; - EDocTelemetryGetResponseScopeStartLbl: Label 'E-Document Get Response: Start Scope', Locked = true; - EDocTelemetryGetResponseScopeEndLbl: Label 'E-Document Get Response: End Scope', Locked = true; - JobQueueCategoryTok: Label 'EDocument', Locked = true, Comment = 'Max Length 10'; - EDocumentJobTelemetryLbl: Label 'E-Document Background Job Scheduled', Locked = true; } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/PatchSentJob.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/PatchSentJob.Codeunit.al index c7994b9648..69e07127ba 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/PatchSentJob.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/PatchSentJob.Codeunit.al @@ -6,24 +6,27 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using System.Threading; using Microsoft.EServices.EDocument; +using System.Security.Authentication; -codeunit 6387 PatchSent +codeunit 6387 PatchSentJob { TableNo = "Job Queue Entry"; Access = Internal; + InherentEntitlements = X; + InherentPermissions = X; trigger OnRun() var - GetReadyStatus: Codeunit GetReadyStatus; + JobHelperImpl: Codeunit JobHelperImpl; BlankRecordId: RecordId; begin - if not IsEDocumentApproved() then + if not this.IsEDocumentApproved() then exit; - ProcessApprovedDocuments(); + this.ProcessApprovedDocuments(); - if IsEDocumentApproved() then - GetReadyStatus.ScheduleEDocumentJob(Codeunit::PatchSent, BlankRecordId, 300000); + if this.IsEDocumentApproved() then + JobHelperImpl.ScheduleEDocumentJob(Codeunit::PatchSentJob, BlankRecordId, 300000); end; local procedure ProcessApprovedDocuments() @@ -34,46 +37,41 @@ codeunit 6387 PatchSent EDocument: Record "E-Document"; APIRequests: Codeunit APIRequests; Processing: Codeunit Processing; - HttpResponse: HttpResponseMessage; - HttpRequest: HttpRequestMessage; + JobHelperImpl: Codeunit JobHelperImpl; + HttpResponseMessage: HttpResponseMessage; + HttpRequestMessage: HttpRequestMessage; begin + EDocumentServiceStatus.SetLoadFields("E-Document Service Code", "E-Document Entry No"); EDocumentServiceStatus.SetRange(Status, EDocumentServiceStatus.Status::Approved); if EDocumentServiceStatus.FindSet() then repeat - FetchEDocumentAndService(EDocument, EDocumentService, EDocumentServiceStatus); + JobHelperImpl.FetchEDocumentAndService(EDocument, EDocumentService, EDocumentServiceStatus); EDocumentIntegrationLog.Reset(); EDocumentIntegrationLog.SetRange("E-Doc. Entry No", EDocument."Entry No"); EDocumentIntegrationLog.SetRange("Response Status", 204); - EDocumentIntegrationLog.SetRange(Method, 'PATCH'); - if EDocumentIntegrationLog.IsEmpty then - if APIRequests.PatchADocument(EDocument, HttpRequest, HttpResponse) then - Processing.InsertIntegrationLog(EDocument, EDocumentService, HttpRequest, HttpResponse); + EDocumentIntegrationLog.SetRange(Method, Format("Http Request Type"::PATCH)); + if EDocumentIntegrationLog.IsEmpty() then + if APIRequests.PatchDocument(EDocument, HttpRequestMessage, HttpResponseMessage) then + Processing.InsertIntegrationLog(EDocument, EDocumentService, HttpRequestMessage, HttpResponseMessage); until EDocumentServiceStatus.Next() = 0; end; - local procedure FetchEDocumentAndService(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; var EDocumentServiceStatus: Record "E-Document Service Status") - begin - EDocumentService.Get(EDocumentServiceStatus."E-Document Service Code"); - EDocument.Get(EDocumentServiceStatus."E-Document Entry No"); - end; - local procedure IsEDocumentApproved(): Boolean var EdocumentServiceStatus: Record "E-Document Service Status"; EDocumentIntegrationLog: Record "E-Document Integration Log"; HasRecords: Boolean; begin + EdocumentServiceStatus.SetLoadFields("E-Document Entry No"); EdocumentServiceStatus.SetRange(Status, EdocumentServiceStatus.Status::Approved); if EdocumentServiceStatus.FindSet() then repeat EDocumentIntegrationLog.Reset(); EDocumentIntegrationLog.SetRange("E-Doc. Entry No", EdocumentServiceStatus."E-Document Entry No"); EDocumentIntegrationLog.SetRange("Response Status", 204); - EDocumentIntegrationLog.SetRange(Method, 'PATCH'); - if EDocumentIntegrationLog.IsEmpty then - HasRecords := true; - + EDocumentIntegrationLog.SetRange(Method, Format("Http Request Type"::PATCH)); + HasRecords := EDocumentIntegrationLog.IsEmpty(); until (EdocumentServiceStatus.Next() = 0) or (HasRecords); exit(HasRecords); diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Edit.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Edit.PermissionSet.al index b017d9b5e7..a2d386e6b3 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Edit.PermissionSet.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Edit.PermissionSet.al @@ -8,9 +8,8 @@ permissionset 6382 Edit { Access = Internal; Assignable = false; - Caption = 'SignUp E-Document Connector - Edit'; + Caption = 'SignUp E-Doc. Connector - Edit', MaxLength = 30; IncludedPermissionSets = Read; - Permissions = tabledata ConnectionSetup = imd, - tabledata ConnectionAuth = imd; + Permissions = tabledata ConnectionSetup = imd; } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Objects.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Objects.PermissionSet.al index e0f855fc66..9ade56ad84 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Objects.PermissionSet.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Objects.PermissionSet.al @@ -8,16 +8,22 @@ permissionset 6380 Objects { Access = Internal; Assignable = false; - Caption = 'SignUp E-Document Connector - Objects'; + Caption = 'SignUp E-Doc. Connector - Obj.', MaxLength = 30; Permissions = table ConnectionSetup = X, - table ConnectionAuth = X, page ConnectionSetupCard = X, codeunit IntegrationImpl = X, - codeunit Processing = X, - codeunit Auth = X, + codeunit PatchSentJob = X, + codeunit JobHelperImpl = X, + codeunit GetReadyStatusJob = X, codeunit APIRequests = X, + codeunit APIRequestsImpl = X, + codeunit Authentication = X, + codeunit AuthenticationImpl = X, codeunit Connection = X, - codeunit PatchSent = X, - codeunit GetReadyStatus = X; + codeunit ConnectionImpl = X, + codeunit HelpersImpl = X, + codeunit Processing = X, + codeunit ProcessingImpl = X; + } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Read.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Read.PermissionSet.al index 1a9b95afc2..2129fcf1a1 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Read.PermissionSet.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Read.PermissionSet.al @@ -8,9 +8,8 @@ permissionset 6381 Read { Access = Internal; Assignable = false; - Caption = 'SignUp E-Document Connector - Read'; + Caption = 'SignUp E-Doc. Connector - Read', MaxLength = 30; IncludedPermissionSets = Objects; - Permissions = tabledata ConnectionSetup = r, - tabledata ConnectionAuth = r; + Permissions = tabledata ConnectionSetup = r; } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al index df0dd30acd..a19c17812c 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al @@ -5,556 +5,116 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.EServices.EDocument; -using System.Telemetry; -using System.Text; using System.Utilities; codeunit 6388 Processing { Access = Internal; - Permissions = tabledata "E-Document" = m, - tabledata "E-Document Service Status" = m; - procedure SendEDocument(var EDocument: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) + #region variables var - EDocumentServiceStatus: Record "E-Document Service Status"; - EdocumentService: Record "E-Document Service"; - FeatureTelemetry: Codeunit "Feature Telemetry"; - begin - IsAsync := true; + ProcessingImpl: Codeunit ProcessingImpl; - EDocumentHelper.GetEdocumentService(EDocument, EdocumentService); - EDocumentServiceStatus.Get(EDocument."Entry No", EdocumentService.Code); + #endregion - case EDocumentServiceStatus.Status of - EDocumentServiceStatus.Status::Exported: - SendEDocument(EDocument, TempBlob, HttpRequest, HttpResponse); - EDocumentServiceStatus.Status::"Sending Error": - if EDocument."Document Id" = '' then - SendEDocument(EDocument, TempBlob, HttpRequest, HttpResponse); - end; + #region public methods - FeatureTelemetry.LogUptake('', ExternalServiceTok, Enum::"Feature Uptake Status"::Used); + /// + /// The method sends the E-Document to the API. + /// + /// E-Document record + /// TempBlob + /// IsAsync + /// HttpRequestMessage + /// HttpResponseMessage + procedure SendEDocument(var EDocument: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) + begin + this.ProcessingImpl.SendEDocument(EDocument, TempBlob, IsAsync, HttpRequestMessage, HttpResponseMessage); end; - procedure GetDocumentResponse(var EDocument: Record "E-Document"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage): Boolean - var - ErrorDescription: Text; + /// + /// The method gets the E-Document response. + /// + /// E-Document record + /// HttpRequestMessage + /// HttpResponseMessage + /// True - if completed successfully + procedure GetDocumentResponse(var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean begin - if not Connection.CheckDocumentStatus(EDocument, HttpRequest, HttpResponse) then - exit; - exit(not DocumentHasErrorOrStillInProcessing(EDocument, HttpResponse, ErrorDescription)); + exit(this.ProcessingImpl.GetDocumentResponse(EDocument, HttpRequestMessage, HttpResponseMessage)); end; - procedure GetDocumentSentResponse(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean - var - EDocumentService: Record "E-Document Service"; - EDocumentServiceStatus: Record "E-Document Service Status"; - APIRequests: Codeunit APIRequests; - Processing: Codeunit Processing; - HttpContentResponse: HttpContent; - Status, StatusDescription : Text; + /// + /// The method gets the E-Document sent response. + /// + /// E-Document record + /// HttpRequestMessage + /// HttpResponseMessage + /// True - if completed successfully + procedure GetDocumentSentResponse(var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean begin - EDocumentHelper.GetEdocumentService(EDocument, EdocumentService); - EDocumentServiceStatus.Get(EDocument."Entry No", EdocumentService.Code); - APIRequests.GetSentDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage); - HttpContentResponse := HttpResponseMessage.Content; - if ParseGetADocumentApprovalResponse(HttpContentResponse, Status, StatusDescription) then - case Status of - 'Ready': - exit(true); - 'Failed': - begin - if StatusDescription <> '' then - EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, 'Reason: ' + StatusDescription); - Processing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Rejected, 0, HttpRequestMessage, HttpResponseMessage); - exit(false); - end; - end; - exit(false); + exit(this.ProcessingImpl.GetDocumentSentResponse(EDocument, HttpRequestMessage, HttpResponseMessage)); end; + /// + /// The method gets the E-Document approval. + /// + /// E-Document record + /// HttpRequestMessage + /// HttpResponseMessage + /// True - if completed successfully procedure GetDocumentApproval(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean - var - EDocumentService: Record "E-Document Service"; - EDocumentServiceStatus: Record "E-Document Service Status"; - APIRequests: Codeunit APIRequests; - GetReadyStatus: Codeunit GetReadyStatus; - Processing: Codeunit Processing; - BlankRecordId: RecordId; - HttpContentResponse: HttpContent; - Status, StatusDescription : Text; begin - EDocumentHelper.GetEdocumentService(EDocument, EdocumentService); - EDocumentServiceStatus.Get(EDocument."Entry No", EdocumentService.Code); - if not (EDocumentServiceStatus.Status in [EDocumentServiceStatus.Status::Sent, EDocumentServiceStatus.Status::"Pending Response"]) then - Error(GetApprovalCheckStatusErr, EDocumentServiceStatus.Status); - - APIRequests.GetSentDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage); - HttpContentResponse := HttpResponseMessage.Content; - if ParseGetADocumentApprovalResponse(HttpContentResponse, Status, StatusDescription) then - case Status of - 'Ready': - begin - if EDocumentServiceStatus.Status = EDocumentServiceStatus.Status::Approved then - GetReadyStatus.ScheduleEDocumentJob(Codeunit::PatchSent, BlankRecordId, 300000) - else - GetReadyStatus.ScheduleEDocumentJob(Codeunit::GetReadyStatus, BlankRecordId, 300000); - exit(true); - end; - 'Failed': - begin - if StatusDescription <> '' then - EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, 'Reason: ' + StatusDescription); - Processing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Rejected, 0, HttpRequestMessage, HttpResponseMessage); - exit(false); - end; - end; - exit(false); + exit(this.ProcessingImpl.GetDocumentApproval(EDocument, HttpRequestMessage, HttpResponseMessage)); end; - procedure ReceiveDocument(var TempBlob: Codeunit "Temp Blob"; var HttpRequest: HttpRequestMessage; var HttpResponse: HttpResponseMessage) - var - ContentData: Text; - OutStream: OutStream; + /// + /// The method receives the document. + /// + /// TempBlob + /// HttpRequestMessage + /// HttpResponseMessage + procedure ReceiveDocument(var TempBlob: Codeunit "Temp Blob"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) begin - if not Connection.GetReceivedDocuments(HttpRequest, HttpResponse) then - exit; - - HttpResponse.Content.ReadAs(ContentData); - - TempBlob.CreateOutStream(OutStream, TextEncoding::UTF8); - OutStream.WriteText(ContentData); + this.ProcessingImpl.ReceiveDocument(TempBlob, HttpRequestMessage, HttpResponseMessage); end; + /// + /// The method gets the document count in batch. + /// + /// TempBlob + /// True - if completed successfully procedure GetDocumentCountInBatch(var TempBlob: Codeunit "Temp Blob"): Integer - var - ResponseInstream: InStream; - ResponseTxt: Text; - begin - TempBlob.CreateInStream(ResponseInstream); - ResponseInstream.ReadText(ResponseTxt); - - exit(GetNumberOfReceivedDocuments(ResponseTxt)); - end; - - local procedure SendEDocument(EDocument: Record "E-Document"; TempBlob: Codeunit "Temp Blob"; HttpRequest: HttpRequestMessage; HttpResponse: HttpResponseMessage); - var - HttpContentResponse: HttpContent; - begin - Connection.HandleSendFilePostRequest(TempBlob, EDocument, HttpRequest, HttpResponse); - HttpContentResponse := HttpResponse.Content; - SetEDocumentFileID(EDocument."Entry No", ParseSendFileResponse(HttpContentResponse)); - end; - - local procedure ParseReceivedDocument(InputTxt: Text; Index: Integer; var DocumentId: Text): Boolean - var - JsonManagement: Codeunit "JSON Management"; - JsonManagement2: Codeunit "JSON Management"; - IncrementalTable: Text; - Value: Text; - begin - if not JsonManagement.InitializeFromString(InputTxt) then - exit(false); - - JsonManagement.GetArrayPropertyValueAsStringByName('inbox', Value); - JsonManagement.InitializeCollection(Value); - - if Index = 0 then - Index := 1; - - if Index > JsonManagement.GetCollectionCount() then - exit(false); - - JsonManagement.GetObjectFromCollectionByIndex(IncrementalTable, Index - 1); - JsonManagement2.InitializeObject(IncrementalTable); - JsonManagement2.GetArrayPropertyValueAsStringByName('instanceId', DocumentId); - exit(true); - end; - - local procedure GetNumberOfReceivedDocuments(InputTxt: Text): Integer - var - JsonManagement: Codeunit "JSON Management"; - Value: Text; - begin - InputTxt := LeaveJustNewLine(InputTxt); - - if not JsonManagement.InitializeFromString(InputTxt) then - exit(0); - - JsonManagement.GetArrayPropertyValueAsStringByName('inbox', Value); - JsonManagement.InitializeCollection(Value); - - exit(JsonManagement.GetCollectionCount()); - end; - - local procedure ParseSendFileResponse(HttpContentResponse: HttpContent): Text - var - JsonManagement: Codeunit "JSON Management"; - Result: Text; - Value: Text; - begin - Result := Helpers.ParseJsonString(HttpContentResponse); - if Result = '' then - exit(''); - - if not JsonManagement.InitializeFromString(Result) then - exit(''); - - JsonManagement.GetStringPropertyValueByName('peppolInstanceId', Value); - exit(Value); - end; - - local procedure SetEDocumentFileID(EDocEntryNo: Integer; FileId: Text) - var - EDocument: Record "E-Document"; - begin - if FileId = '' then - exit; - if not EDocument.Get(EDocEntryNo) then - exit; - - EDocument."Document Id" := CopyStr(FileId, 1, MaxStrLen(EDocument."Document Id")); - EDocument.Modify(); - end; - - local procedure DocumentHasErrorOrStillInProcessing(EDocument: Record "E-Document"; HttpResponse: HttpResponseMessage; var ErrorDescription: Text): Boolean - var - EDocumentService: Record "E-Document Service"; - EDocumentServiceStatus: Record "E-Document Service Status"; - JsonManagement: Codeunit "JSON Management"; - GetReadyStatus: Codeunit GetReadyStatus; - BlankRecordId: RecordId; - HttpContentResponse: HttpContent; - Result, Value : Text; - begin - HttpContentResponse := HttpResponse.Content; - Result := Helpers.ParseJsonString(HttpContentResponse); - if Result = '' then - exit(true); - - if not JsonManagement.InitializeFromString(Result) then - exit(true); - - JsonManagement.GetArrayPropertyValueAsStringByName('status', Value); - - if Value in ['Sent'] then begin - GetReadyStatus.ScheduleEDocumentJob(Codeunit::GetReadyStatus, BlankRecordId, 120000); - exit(false); - end; - - if Value in ['Ready'] then begin - EDocumentHelper.GetEdocumentService(EDocument, EDocumentService); - EDocumentServiceStatus.Get(EDocument."Entry No", EdocumentService.Code); - if EDocumentServiceStatus.Status = EDocumentServiceStatus.Status::Approved then - GetReadyStatus.ScheduleEDocumentJob(Codeunit::PatchSent, BlankRecordId, 180000) - else - GetReadyStatus.ScheduleEDocumentJob(Codeunit::GetReadyStatus, BlankRecordId, 120000); - exit(false); - end; - - if Value = 'Failed' then begin - JsonManagement.GetArrayPropertyValueAsStringByName('description', ErrorDescription); - exit(false); - end; - - JsonManagement.GetArrayPropertyValueAsStringByName('description', ErrorDescription); - exit(true); - end; - - procedure ParseGetADocumentApprovalResponse(HttpContentResponse: HttpContent; var Status: Text; var StatusDescription: Text): Boolean - var - JsonManagement: Codeunit "JSON Management"; - Result: Text; - begin - Result := Helpers.ParseJsonString(HttpContentResponse); - if Result = '' then - exit(false); - - if not JsonManagement.InitializeFromString(Result) then - exit(false); - - JsonManagement.GetArrayPropertyValueAsStringByName('status', Status); - - if Status in ['Ready', 'Sent'] then - exit(true); - - if Status = 'Failed' then begin - JsonManagement.GetArrayPropertyValueAsStringByName('description', StatusDescription); - exit(true); - end; - - exit(false); - end; - - [EventSubscriber(ObjectType::Codeunit, Codeunit::"E-Doc. Integration Management", 'OnGetEDocumentApprovalReturnsFalse', '', false, false)] - local procedure OnGetEDocumentApprovalReturnsFalse(EDocuments: Record "E-Document"; EDocumentService: Record "E-Document Service"; HttpRequest: HttpRequestMessage; HttpResponse: HttpResponseMessage; var IsHandled: Boolean) - var - HttpContentResponse: HttpContent; - Status, StatusDescription : Text; - begin - HttpContentResponse := HttpResponse.Content; - if not ParseGetADocumentApprovalResponse(HttpContentResponse, Status, StatusDescription) then - IsHandled := true; - end; - - [EventSubscriber(ObjectType::Codeunit, Codeunit::"E-Doc. Import", 'OnAfterInsertImportedEdocument', '', false, false)] - local procedure OnAfterInsertEdocument(var EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; var TempBlob: Codeunit "Temp Blob"; EDocCount: Integer; HttpRequest: HttpRequestMessage; HttpResponse: HttpResponseMessage) - var - LocalHttpRequest: HttpRequestMessage; - LocalHttpResponse: HttpResponseMessage; - DocumentOutStream: OutStream; - ContentData, DocumentId : Text; - begin - - if EDocumentService."Service Integration" <> EDocumentService."Service Integration"::"ExFlow E-Invoicing" then - exit; - - HttpResponse.Content.ReadAs(ContentData); - - ContentData := LeaveJustNewLine(ContentData); - - if not ParseReceivedDocument(ContentData, EDocument."Index In Batch", DocumentId) then begin - EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, DocumentIdNotFoundErr); - exit; - end; - - Connection.HandleGetTargetDocumentRequest(DocumentId, LocalHttpRequest, LocalHttpResponse); - EDocumentLogHelper.InsertIntegrationLog(EDocument, EDocumentService, LocalHttpRequest, LocalHttpResponse); - - LocalHttpResponse.Content.ReadAs(ContentData); - - if not ParseContentData(ContentData) then - ContentData := ''; - - if ContentData = '' then - EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, StrSubstNo(CouldNotRetrieveDocumentErr, DocumentId)); - - Clear(TempBlob); - TempBlob.CreateOutStream(DocumentOutStream, TextEncoding::UTF8); - DocumentOutStream.WriteText(ContentData); - EDocument."Document Id" := CopyStr(DocumentId, 1, MaxStrLen(EDocument."Document Id")); - EDocumentLogHelper.InsertLog(EDocument, EDocumentService, TempBlob, "E-Document Service Status"::Imported); - Connection.RemoveDocumentFromReceived(EDocument, LocalHttpRequest, LocalHttpResponse); - EDocumentLogHelper.InsertIntegrationLog(EDocument, EDocumentService, LocalHttpRequest, LocalHttpResponse); - end; - - - internal procedure InsertIntegrationLog(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; HttpRequest: HttpRequestMessage; HttpResponse: HttpResponseMessage) - var - EDocumentIntegrationLog: Record "E-Document Integration Log"; - EDocumentIntegrationLogRecRef: RecordRef; - RequestTxt: Text; - begin - if EDocumentService."Service Integration" = EDocumentService."Service Integration"::"No Integration" then - exit; - - EDocumentIntegrationLog.Validate("E-Doc. Entry No", EDocument."Entry No"); - EDocumentIntegrationLog.Validate("Service Code", EDocumentService.Code); - EDocumentIntegrationLog.Validate("Response Status", HttpResponse.HttpStatusCode()); - EDocumentIntegrationLog.Validate("Request URL", HttpRequest.GetRequestUri()); - EDocumentIntegrationLog.Validate(Method, HttpRequest.Method()); - EDocumentIntegrationLog.Insert(); - - EDocumentIntegrationLogRecRef.GetTable(EDocumentIntegrationLog); - - if HttpRequest.Content.ReadAs(RequestTxt) then begin - InsertIntegrationBlob(EDocumentIntegrationLogRecRef, RequestTxt, EDocumentIntegrationLog.FieldNo(EDocumentIntegrationLog."Request Blob")); - EDocumentIntegrationLogRecRef.Modify(); - end; - - if HttpResponse.Content.ReadAs(RequestTxt) then begin - InsertIntegrationBlob(EDocumentIntegrationLogRecRef, RequestTxt, EDocumentIntegrationLog.FieldNo(EDocumentIntegrationLog."Response Blob")); - EDocumentIntegrationLogRecRef.Modify(); - end; - end; - - - internal procedure InsertLog(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; EDocDataStorageEntryNo: Integer; EDocumentServiceStatus: Enum "E-Document Service Status"): Integer - var - EDocumentLog: Record "E-Document Log"; - begin - if EDocumentService.Code <> '' then - UpdateServiceStatus(EDocument, EDocumentService, EDocumentServiceStatus); - - EDocumentLog.Validate("Document Type", EDocument."Document Type"); - EDocumentLog.Validate("Document No.", EDocument."Document No."); - EDocumentLog.Validate("E-Doc. Entry No", EDocument."Entry No"); - EDocumentLog.Validate(Status, EDocumentServiceStatus); - EDocumentLog.Validate("Service Integration", EDocumentService."Service Integration"); - EDocumentLog.Validate("Service Code", EDocumentService.Code); - EDocumentLog.Validate("Document Format", EDocumentService."Document Format"); - EDocumentLog.Validate("E-Doc. Data Storage Entry No.", EDocDataStorageEntryNo); - - EDocumentLog.Insert(); - exit(EDocumentLog."Entry No."); - end; - - internal procedure UpdateServiceStatus(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; EDocumentStatus: Enum "E-Document Service Status") - var - EDocumentServiceStatus: Record "E-Document Service Status"; - Exists: Boolean; - begin - EDocument.Get(EDocument."Entry No"); - Exists := EDocumentServiceStatus.Get(EDocument."Entry No", EDocumentService.Code); - EDocumentServiceStatus.Validate(Status, EDocumentStatus); - if Exists then - EDocumentServiceStatus.Modify() - else begin - EDocumentServiceStatus.Validate("E-Document Entry No", EDocument."Entry No"); - EDocumentServiceStatus.Validate("E-Document Service Code", EDocumentService.Code); - EDocumentServiceStatus.Validate(Status, EDocumentStatus); - EDocumentServiceStatus.Insert(); - end; - - UpdateEDocumentStatus(EDocument); - end; - - local procedure UpdateEDocumentStatus(var EDocument: Record "E-Document") - var - IsHandled: Boolean; begin - if IsHandled then - exit; - - if EDocumentHasErrors(EDocument) then - exit; - - SetDocumentStatus(EDocument); + exit(this.ProcessingImpl.GetDocumentCountInBatch(TempBlob)); end; - local procedure EDocumentHasErrors(var EDocument: Record "E-Document"): Boolean - var - EDocumentServiceStatus: Record "E-Document Service Status"; + /// + /// The method inserts the integration log. + /// + /// E-Document record + /// E-Document Service record + /// HttpRequestMessage + /// HttpResponseMessage + procedure InsertIntegrationLog(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; HttpRequestMessage: HttpRequestMessage; HttpResponseMessage: HttpResponseMessage) begin - EDocumentServiceStatus.SetRange("E-Document Entry No", EDocument."Entry No"); - EDocumentServiceStatus.SetFilter(Status, '%1|%2|%3|%4|%5', - EDocumentServiceStatus.Status::"Sending Error", - EDocumentServiceStatus.Status::"Export Error", - EDocumentServiceStatus.Status::"Cancel Error", - EDocumentServiceStatus.Status::"Imported Document Processing Error", - EDocumentServiceStatus.Status::Rejected); - - if EDocumentServiceStatus.IsEmpty() then - exit(false); - - EDocument.Validate(Status, EDocument.Status::Error); - EDocument.Modify(); - exit(true); + this.ProcessingImpl.InsertIntegrationLog(EDocument, EDocumentService, HttpRequestMessage, HttpResponseMessage); end; - local procedure InsertIntegrationBlob(var EDocumentIntegrationLogRecRef: RecordRef; Data: Text; FieldNo: Integer) - var - TempBlob: Codeunit "Temp Blob"; - OutStreamObj: OutStream; + /// + /// The method inserts the log with integration. + /// + /// E-Document record + /// E-Document Service record + /// E-Document Service Status + /// E-Document Data Storage Entry No. + /// HttpRequestMessage + /// HttpResponseMessage + procedure InsertLogWithIntegration(var EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; + EDocumentServiceStatus: Enum "E-Document Service Status"; EDocDataStorageEntryNo: Integer; HttpRequestMessage: HttpRequestMessage; HttpResponseMessage: HttpResponseMessage) begin - TempBlob.CreateOutStream(OutStreamObj); - OutStreamObj.WriteText(Data); - - TempBlob.ToRecordRef(EDocumentIntegrationLogRecRef, FieldNo); - end; - - local procedure SetDocumentStatus(var EDocument: Record "E-Document") - var - EDocumentServiceStatus: Record "E-Document Service Status"; - EDocServiceCount: Integer; - begin - EDocumentServiceStatus.SetRange("E-Document Entry No", EDocument."Entry No"); - EDocServiceCount := EDocumentServiceStatus.Count; - - EDocumentServiceStatus.SetFilter(Status, '%1|%2|%3|%4|%5', - EDocumentServiceStatus.Status::Exported, - EDocumentServiceStatus.Status::"Imported Document Created", - EDocumentServiceStatus.Status::"Journal Line Created", - EDocumentServiceStatus.Status::Approved, - EDocumentServiceStatus.Status::Canceled); - if EDocumentServiceStatus.Count = EDocServiceCount then - EDocument.Status := EDocument.Status::Processed - else - EDocument.Status := EDocument.Status::"In Progress"; - - EDocument.Modify(); + this.ProcessingImpl.InsertLogWithIntegration(EDocument, EDocumentService, EDocumentServiceStatus, EDocDataStorageEntryNo, HttpRequestMessage, HttpResponseMessage); end; - internal procedure InsertLogWithIntegration(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; EDocumentServiceStatus: Enum "E-Document Service Status"; EDocDataStorageEntryNo: Integer; - HttpRequest: HttpRequestMessage; - HttpResponse: HttpResponseMessage) - begin - InsertLog(EDocument, EDocumentService, EDocDataStorageEntryNo, EDocumentServiceStatus); - if (HttpRequest.GetRequestUri() <> '') and (HttpResponse.Headers.Keys().Count > 0) then - InsertIntegrationLog(EDocument, EDocumentService, HttpRequest, HttpResponse); - end; - - local procedure LeaveJustNewLine(InputText: Text): Text - var - InputJson: JsonObject; - InputJsonArray: JsonArray; - InputJsonToken: JsonToken; - DocumentJsonToken: JsonToken; - OutputDocumentJsonArray: JsonArray; - OutputDocumentJsonObject: JsonObject; - OutputJsonObject: JsonObject; - OutputText: text; - DocumentList: List of [Text]; - i: Integer; - begin - OutputText := InputText; - InputJson.ReadFrom(InputText); - if InputJson.Contains('inbox') then begin - InputJson.Get('inbox', InputJsonToken); - InputJsonArray := InputJsonToken.AsArray(); - foreach InputJsonToken in InputJsonArray do - if InputJsonToken.AsObject().Get('status', DocumentJsonToken) then - if DocumentJsonToken.AsValue().AsText() = 'New' then begin - InputJsonToken.AsObject().Get('instanceId', DocumentJsonToken); - DocumentList.Add(DocumentJsonToken.AsValue().AsText()); - end; - - for i := 1 to DocumentList.Count do begin - Clear(OutputDocumentJsonObject); - OutputDocumentJsonObject.Add('instanceId', DocumentList.Get(i)); - OutputDocumentJsonArray.Add(OutputDocumentJsonObject); - end; - - OutputJsonObject.Add('inbox', OutputDocumentJsonArray); - OutputJsonObject.WriteTo(OutputText) - - end; - exit(OutputText); - end; - - local procedure ParseContentData(var InputText: Text): Boolean - var - JsonManagement: Codeunit "JSON Management"; - Base64Convert: Codeunit "Base64 Convert"; - Value: Text; - ParsePosition: Integer; - begin - if not JsonManagement.InitializeFromString(InputText) then - exit(false); - - JsonManagement.GetArrayPropertyValueAsStringByName('document', Value); - InputText := Base64Convert.FromBase64(Value); - ParsePosition := StrPos(InputText, ''); - if ParsePosition > 0 then begin - InputText := CopyStr(InputText, parsePosition, StrLen(InputText)); - ParsePosition := StrPos(InputText, ''); - InputText := CopyStr(InputText, 1, parsePosition - 1); - end; - - exit(true); - end; - - var - Connection: Codeunit Connection; - Helpers: Codeunit Helpers; - EDocumentHelper: Codeunit "E-Document Helper"; - EDocumentLogHelper: Codeunit "E-Document Log Helper"; - EDocumentErrorHelper: Codeunit "E-Document Error Helper"; - GetApprovalCheckStatusErr: Label 'You cannot ask for approval with the E-Document in this current status %1. You can request for approval when E-document status is Sent or Pending Response.', Comment = '%1 - Status'; - CouldNotRetrieveDocumentErr: Label 'Could not retrieve document with id: %1 from the service', Comment = '%1 - Document ID'; - DocumentIdNotFoundErr: Label 'Document ID not found in response'; - ExternalServiceTok: Label 'E-Document - SignUp', Locked = true; + #endregion } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetup.Table.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetup.Table.al index af59bc6a08..7c07b7eec2 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetup.Table.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetup.Table.al @@ -8,77 +8,69 @@ table 6381 ConnectionSetup { Access = Internal; DataPerCompany = false; + DataClassification = CustomerContent; fields { field(1; PK; Code[10]) { - DataClassification = CustomerContent; + Caption = 'PK', Locked = true; + ToolTip = 'PK', Locked = true; } field(4; "Authentication URL"; Text[250]) { Caption = 'Authentication URL'; - DataClassification = CustomerContent; + ToolTip = 'Specifies the URL to connect Microsoft Entra.'; } field(9; "Company Id"; Text[100]) { Caption = 'Company ID'; - DataClassification = CustomerContent; + ToolTip = 'Specifies the company ID.'; } field(10; "Client ID"; Guid) { Caption = 'Client ID'; - DataClassification = CustomerContent; + ToolTip = 'Specifies the client ID.'; } field(11; "Client Secret"; Guid) { Caption = 'Client Secret'; - DataClassification = CustomerContent; + ToolTip = 'Specifies the client secret.'; } - field(12; "Send Mode"; Enum SendMode) + field(12; "Environment Type"; Enum EnvironmentType) { - Caption = 'Send Mode'; - DataClassification = CustomerContent; + Caption = 'Environment Type'; + ToolTip = 'Specifies the environment type.'; } field(13; ServiceURL; Text[250]) { Caption = 'Service URL'; - DataClassification = CustomerContent; + ToolTip = 'Specifies the service URL.'; } field(20; "Root App ID"; Guid) { Caption = 'Root App ID'; - DataClassification = CustomerContent; + ToolTip = 'Specifies the root app ID.'; } field(21; "Root Secret"; Guid) { Caption = 'Root App Secret'; - DataClassification = CustomerContent; + ToolTip = 'Specifies the root application secret.'; } field(22; "Root Tenant"; Guid) { Caption = 'Root App Tenant'; - DataClassification = CustomerContent; + ToolTip = 'Specifies the root application tenant.'; } field(23; "Root Market URL"; Guid) { Caption = 'Root Market URL'; - DataClassification = CustomerContent; + ToolTip = 'Specifies the root market URL.'; } field(24; "Client Tenant"; Guid) { Caption = 'Client App Tenant'; - DataClassification = CustomerContent; - } - field(30; "Client Token Due DateTime"; DateTime) - { - Caption = 'Client Token Timestamp'; - DataClassification = SystemMetadata; - } - field(31; "Root Token Due DateTime"; DateTime) - { - Caption = 'Root Token Timestamp'; - DataClassification = SystemMetadata; + ToolTip = 'Specifies the client application tenant.'; } } @@ -90,15 +82,11 @@ table 6381 ConnectionSetup } } - var - RecordHasBeenRead: Boolean; - - procedure GetRecordOnce(): Boolean + procedure GetSetup(): Boolean begin - if RecordHasBeenRead then - exit(RecordHasBeenRead); - Clear(Rec); - RecordHasBeenRead := Get(); - exit(RecordHasBeenRead); + if not IsNullGuid(Rec.SystemId) then + exit(true); + + exit(Rec.Get()); end; } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetupCard.Page.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetupCard.Page.al index 859575abb5..2d804b4c11 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetupCard.Page.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetupCard.Page.al @@ -9,6 +9,7 @@ using System.Environment; page 6380 ConnectionSetupCard { + AdditionalSearchTerms = 'SignUp,electronic document,e-invoice,e-document,external,connection,connector'; PageType = Card; SourceTable = ConnectionSetup; ApplicationArea = Basic, Suite; @@ -16,125 +17,122 @@ page 6380 ConnectionSetupCard Caption = 'E-Document External Connection Setup'; Extensible = false; + layout { area(Content) { group(General) { - field(ClientID; ClientID) + field(ClientID; this.ClientID) { Caption = 'Client ID'; ToolTip = 'Specifies the client ID token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; - Visible = not IsSaaSInfrastructure; + Visible = not this.IsSaaSInfrastructure; ShowMandatory = true; trigger OnValidate() begin - Auth.StorageSet(Rec."Client ID", ClientID); + this.Authentication.StorageSet(Rec."Client ID", this.ClientID); end; } - field(ClientSecret; ClientSecret) + field(ClientSecret; this.ClientSecret) { Caption = 'Client Secret'; ToolTip = 'Specifies the client secret token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; - Visible = not IsSaaSInfrastructure; + Visible = not this.IsSaaSInfrastructure; ShowMandatory = true; trigger OnValidate() begin - Auth.StorageSet(Rec."Client Secret", ClientSecret); + this.SaveSecret(Rec."Client Secret", this.ClientSecret) end; } - field(ClientTenant; ClientTenant) + field(ClientTenant; this.ClientTenant) { Caption = 'Client Tenant ID'; ToolTip = 'Specifies the client tenant id token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; - Visible = not IsSaaSInfrastructure; + Visible = not this.IsSaaSInfrastructure; trigger OnValidate() begin - Auth.StorageSet(Rec."Client Tenant", ClientTenant); + this.Authentication.StorageSet(Rec."Client Tenant", this.ClientTenant); end; } - field(RootID; RootID) + field(RootID; this.RootID) { Caption = 'Root App ID'; ToolTip = 'Specifies the root app id token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; - Visible = not IsSaaSInfrastructure; + Visible = not this.IsSaaSInfrastructure; trigger OnValidate() begin - Auth.StorageSet(Rec."Root App ID", RootID); + this.Authentication.StorageSet(Rec."Root App ID", this.RootID); end; } - field(RootSecret; RootSecret) + field(RootSecret; this.RootSecret) { Caption = 'Root Secret'; ToolTip = 'Specifies the root secret token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; - Visible = not IsSaaSInfrastructure; + Visible = not this.IsSaaSInfrastructure; trigger OnValidate() begin - Auth.StorageSet(Rec."Root Secret", RootSecret); + this.SaveSecret(Rec."Root Secret", this.RootSecret) end; } - field(RootTenant; RootTenant) + field(RootTenant; this.RootTenant) { Caption = 'Root Tenant ID'; ToolTip = 'Specifies the root tenant id token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; - Visible = not IsSaaSInfrastructure; + Visible = not this.IsSaaSInfrastructure; trigger OnValidate() begin - Auth.StorageSet(Rec."Root Tenant", RootTenant); + this.Authentication.StorageSet(Rec."Root Tenant", this.RootTenant); end; } - field(RootUrl; RootUrl) + field(RootUrl; this.RootUrl) { Caption = 'Root Url'; ToolTip = 'Specifies the root url token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; - Visible = not IsSaaSInfrastructure; + Visible = not this.IsSaaSInfrastructure; trigger OnValidate() begin - Auth.StorageSet(Rec."Root Market URL", RootUrl); + this.Authentication.StorageSet(Rec."Root Market URL", this.RootUrl); end; } field("Authentication URL"; Rec."Authentication URL") { ApplicationArea = Basic, Suite; - ToolTip = 'Specifies the URL to connect Microsoft Entra.'; } field(ServiceURL; Rec.ServiceURL) { ApplicationArea = Basic, Suite; - ToolTip = 'Specifies the service URL.'; } field("Company Id"; Rec."Company Id") { ApplicationArea = Basic, Suite; - ToolTip = 'Specifies the company ID.'; ShowMandatory = true; } - field("Send Mode"; Rec."Send Mode") + field("Environment Type"; Rec."Environment Type") { ApplicationArea = Basic, Suite; - ToolTip = 'Specifies the send mode.'; ShowMandatory = true; } } @@ -153,16 +151,16 @@ page 6380 ConnectionSetupCard Promoted = true; PromotedCategory = Process; PromotedOnly = true; - Visible = IsSaaSInfrastructure; + Visible = this.IsSaaSInfrastructure; ToolTip = 'Create client credentials and open the onboarding process in a web browser.'; trigger OnAction() begin - Auth.CreateClientCredentials(); + this.Authentication.CreateClientCredentials(); CurrPage.Update(); - SetPageVariables(); - Hyperlink(Auth.GetRootOnboardingUrl()); - FeatureTelemetry.LogUptake('', ExternalServiceTok, Enum::"Feature Uptake Status"::"Set up"); + this.SetPageVariables(); + Hyperlink(this.Authentication.GetRootOnboardingUrl()); + this.FeatureTelemetry.LogUptake('', this.ExternalServiceTok, Enum::"Feature Uptake Status"::"Set up"); end; } } @@ -170,39 +168,46 @@ page 6380 ConnectionSetupCard trigger OnOpenPage() var - EnvironmentInfo: Codeunit "Environment Information"; + EnvironmentInformation: Codeunit "Environment Information"; begin - IsSaaSInfrastructure := EnvironmentInfo.IsSaaSInfrastructure(); - Auth.InitConnectionSetup(); + this.IsSaaSInfrastructure := EnvironmentInformation.IsSaaSInfrastructure(); + this.Authentication.InitConnectionSetup(); if Rec.Get() then ; - SetPageVariables(); - FeatureTelemetry.LogUptake('', ExternalServiceTok, Enum::"Feature Uptake Status"::Discovered); + this.SetPageVariables(); + this.FeatureTelemetry.LogUptake('', this.ExternalServiceTok, Enum::"Feature Uptake Status"::Discovered); end; local procedure SetPageVariables() begin if not IsNullGuid(Rec."Client ID") then - ClientID := '*'; + this.ClientID := this.MaskTxt; if not IsNullGuid(Rec."Client Secret") then - ClientSecret := '*'; + this.ClientSecret := this.MaskTxt; if not IsNullGuid(Rec."Client Tenant") then - ClientTenant := '*'; + this.ClientTenant := this.MaskTxt; if not IsNullGuid(Rec."Root App ID") then - RootID := '*'; + this.RootID := this.MaskTxt; if not IsNullGuid(Rec."Root Secret") then - RootSecret := '*'; + this.RootSecret := this.MaskTxt; if not IsNullGuid(Rec."Root Tenant") then - RootTenant := '*'; + this.RootTenant := this.MaskTxt; if not IsNullGuid(Rec."Root Market URL") then - RootUrl := '*'; + this.RootUrl := this.MaskTxt; + end; + + [NonDebuggable] + local procedure SaveSecret(var TokenKey: Guid; Value: SecretText) + begin + this.Authentication.StorageSet(TokenKey, Value); end; var - Auth: Codeunit Auth; + Authentication: Codeunit Authentication; FeatureTelemetry: Codeunit "Feature Telemetry"; [NonDebuggable] ClientID, ClientSecret, ClientTenant, ClientUrl, RootID, RootSecret, RootTenant, RootUrl : Text; IsSaaSInfrastructure: Boolean; ExternalServiceTok: Label 'E-Document - SignUp', Locked = true; + MaskTxt: Label '*', Locked = true; } \ No newline at end of file From 95a5e65925188c061125b2ee197d58c729297abd Mon Sep 17 00:00:00 2001 From: geschwint Date: Tue, 4 Feb 2025 18:29:10 +0100 Subject: [PATCH 36/63] Files deleted, not in use --- .../app/src/APIRequestsImpl.Codeunit.al | 286 --------- .../app/src/AuthenticationImpl.Codeunit.al | 344 ----------- .../SignUp/app/src/ConnectionImpl.Codeunit.al | 116 ---- .../SignUp/app/src/HelpersImpl.Codeunit.al | 92 --- .../src/Jobs/GetReadyStatusJob.Codeunit.al | 90 --- .../app/src/Jobs/JobHelperImpl.Codeunit.al | 83 --- .../app/src/Jobs/PatchSentJob.Codeunit.al | 79 --- .../app/src/Permissions/Edit.PermissionSet.al | 15 - .../src/Permissions/Objects.PermissionSet.al | 29 - .../app/src/Permissions/Read.PermissionSet.al | 15 - ...ignUpEDocConnectorEdit.PermissionSetExt.al | 11 - ...ignUpEDocConnectorRead.PermissionSetExt.al | 11 - .../SignUp/app/src/ProcessingImpl.Codeunit.al | 580 ------------------ 13 files changed, 1751 deletions(-) delete mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequestsImpl.Codeunit.al delete mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/AuthenticationImpl.Codeunit.al delete mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionImpl.Codeunit.al delete mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/HelpersImpl.Codeunit.al delete mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/GetReadyStatusJob.Codeunit.al delete mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/JobHelperImpl.Codeunit.al delete mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/PatchSentJob.Codeunit.al delete mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Edit.PermissionSet.al delete mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Objects.PermissionSet.al delete mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Read.PermissionSet.al delete mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocConnectorEdit.PermissionSetExt.al delete mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocConnectorRead.PermissionSetExt.al delete mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/ProcessingImpl.Codeunit.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequestsImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequestsImpl.Codeunit.al deleted file mode 100644 index bb47a40cff..0000000000 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequestsImpl.Codeunit.al +++ /dev/null @@ -1,286 +0,0 @@ -// ------------------------------------------------------------------------------------------------ -// 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 6389 APIRequestsImpl -{ - Access = Internal; - InherentEntitlements = X; - InherentPermissions = X; - - #region variables - - var - MissingSetupErr: Label 'Connection Setup is missing'; - MissingSetupMessageErr: Label 'You must set up service integration in the e-document service card.'; - MissingSetupNavigationActionErr: Label 'Show E-Document Services'; - UnSupportedDocumentTypeTxt: Label 'Document %1 is not supported.', Comment = '%1 = EDocument Type', Locked = true; - SenderReceiverPrefixTxt: Label 'iso6523-actorid-upis::', Locked = true; - ContentTypeTxt: Label 'Content-Type', Locked = true; - ApplicationJsonTxt: Label 'application/json', Locked = true; - AuthorizationTxt: Label 'Authorization', Locked = true; - AcceptTxt: Label 'Accept', Locked = true; - AllTxt: Label '*/*', Locked = true; - ApplicationResponseTxt: Label 'ApplicationResponse', Locked = true; - InvoiceTxt: Label 'Invoice', Locked = true; - PaymentReminderTxt: Label 'PaymentReminder', Locked = true; - DocumentTypeTxt: Label 'documentType', Locked = true; - ReceiverTxt: Label 'receiver', Locked = true; - SenderTxt: Label 'sender', Locked = true; - SenderCountryCodeTxt: Label 'senderCountryCode', Locked = true; - DocumentIdTxt: Label 'documentId', Locked = true; - DocumentIdValueTxt: Label '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', Locked = true; - DocumentIdSchemeTxt: Label 'documentIdScheme', Locked = true; - BusdoxDocIdQNSTxt: Label 'busdox-docid-qns', Locked = true; - ProcessIdTxt: Label 'processId', Locked = true; - ProcessIdValueTxt: Label 'urn:fdc:peppol.eu:2017:poacc:billing:01:1.0', Locked = true; - ProcessIdSchemeTxt: Label 'processIdScheme', Locked = true; - ProcessIdSchemeValueTxt: Label 'cenbii-procid-ubl', Locked = true; - SendModeTxt: Label 'sendMode', Locked = true; - DocumentTxt: Label 'document', Locked = true; - - #endregion - - #region public methods - - // https:///api/Peppol - procedure SendFilePostRequest(var TempBlob: Codeunit "Temp Blob"; EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean - var - ConnectionSetup: Record ConnectionSetup; - HttpContent: HttpContent; - Payload: Text; - begin - Payload := this.XmlToTxt(TempBlob); - if Payload = '' then - exit; - - this.InitRequest(HttpRequestMessage, HttpResponseMessage); - ConnectionSetup.SetLoadFields("Company Id", "Environment Type", ServiceURL); - this.GetSetup(ConnectionSetup); - - HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::POST, ConnectionSetup.ServiceURL + '/api/Peppol'); - this.PrepareContent(HttpContent, Payload, EDocument, ConnectionSetup); - HttpRequestMessage.Content(HttpContent); - exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); - end; - - // https:///api/Peppol/status?peppolInstanceId= - procedure GetSentDocumentStatus(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean - var - ConnectionSetup: Record ConnectionSetup; - begin - this.InitRequest(HttpRequestMessage, HttpResponseMessage); - ConnectionSetup.SetLoadFields(ServiceURL); - this.GetSetup(ConnectionSetup); - - HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::GET, ConnectionSetup.ServiceURL + '/api/Peppol/status?peppolInstanceId=' + EDocument."Document Id"); - exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); - end; - - // https:///api/Peppol/outbox?peppolInstanceId= - procedure PatchDocument(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean - var - ConnectionSetup: Record ConnectionSetup; - begin - this.InitRequest(HttpRequestMessage, HttpResponseMessage); - ConnectionSetup.SetLoadFields(ServiceURL); - this.GetSetup(ConnectionSetup); - - HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::PATCH, ConnectionSetup.ServiceURL + '/api/Peppol/outbox?peppolInstanceId=' + EDocument."Document Id"); - exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); - end; - - // https:///api/Peppol/Inbox?peppolId= - procedure GetReceivedDocumentsRequest(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean - var - ConnectionSetup: Record ConnectionSetup; - begin - this.InitRequest(HttpRequestMessage, HttpResponseMessage); - ConnectionSetup.SetLoadFields(ServiceURL, "Company Id"); - this.GetSetup(ConnectionSetup); - - HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::GET, ConnectionSetup.ServiceURL + '/api/Peppol/Inbox?peppolId=' + this.SenderReceiverPrefixTxt + ConnectionSetup."Company Id"); - exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); - end; - - // https:///api/Peppol/inbox-document?peppolId= - procedure GetTargetDocumentRequest(DocumentId: Text; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean - var - ConnectionSetup: Record ConnectionSetup; - begin - this.InitRequest(HttpRequestMessage, HttpResponseMessage); - ConnectionSetup.SetLoadFields(ServiceURL, "Company Id"); - this.GetSetup(ConnectionSetup); - - HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::GET, ConnectionSetup.ServiceURL + '/api/Peppol/inbox-document?peppolId=' + this.SenderReceiverPrefixTxt + ConnectionSetup."Company Id" + '&peppolInstanceId=' + DocumentId); - exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); - end; - - // https:///api/Peppol/inbox?peppolInstanceId= - procedure PatchReceivedDocument(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean - var - ConnectionSetup: Record ConnectionSetup; - begin - this.InitRequest(HttpRequestMessage, HttpResponseMessage); - ConnectionSetup.SetLoadFields(ServiceURL); - this.GetSetup(ConnectionSetup); - - HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::PATCH, ConnectionSetup.ServiceURL + '/api/Peppol/inbox?peppolInstanceId=' + EDocument."Document Id"); - exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); - end; - - procedure GetMarketPlaceCredentials(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean - var - Authentication: Codeunit Authentication; - begin - this.InitRequest(HttpRequestMessage, HttpResponseMessage); - - HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::POST, Authentication.GetRootUrl() + '/api/Registration/init?EntraTenantId=' + Authentication.GetBCInstanceIdentifier()); - exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage, true)); - end; - - #endregion - - #region local methods - - local procedure InitRequest(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) - begin - Clear(HttpRequestMessage); - Clear(HttpResponseMessage); - end; - - local procedure GetSetup(var ConnectionSetup: Record ConnectionSetup) - var - MissingSetupErrorInfo: ErrorInfo; - begin - if not IsNullGuid(ConnectionSetup.SystemId) then - exit; - - if not ConnectionSetup.Get() then begin - MissingSetupErrorInfo.Title := this.MissingSetupErr; - MissingSetupErrorInfo.Message := this.MissingSetupMessageErr; - MissingSetupErrorInfo.PageNo := Page::"E-Document Services"; - MissingSetupErrorInfo.AddNavigationAction(this.MissingSetupNavigationActionErr); - Error(MissingSetupErrorInfo); - end; - end; - - local procedure PrepareContent(var HttpContent: HttpContent; Payload: Text; EDocument: Record "E-Document"; ConnectionSetup: Record ConnectionSetup) - var - ContentText: Text; - HttpHeaders: HttpHeaders; - begin - Clear(HttpContent); - ContentText := this.PrepareContentForSend(this.GetDocumentType(EDocument), ConnectionSetup."Company Id", this.GetCustomerID(EDocument), this.GetSenderCountryCode(), Payload, ConnectionSetup."Environment Type"); - HttpContent.WriteFrom(ContentText); - HttpContent.GetHeaders(HttpHeaders); - if HttpHeaders.Contains(this.ContentTypeTxt) then - HttpHeaders.Remove(this.ContentTypeTxt); - HttpHeaders.Add(this.ContentTypeTxt, this.ApplicationJsonTxt); - end; - - local procedure SendRequest(HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean - begin - this.SendRequest(HttpRequestMessage, HttpResponseMessage, false); - end; - - local procedure SendRequest(HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage; RootRequest: Boolean): Boolean - var - Authentication: Codeunit Authentication; - HttpClient: HttpClient; - HttpHeaders: HttpHeaders; - begin - HttpRequestMessage.GetHeaders(HttpHeaders); - if RootRequest then - HttpHeaders.Add(this.AuthorizationTxt, Authentication.GetRootBearerAuthToken()) - else - HttpHeaders.Add(this.AuthorizationTxt, Authentication.GetBearerAuthToken()); - exit(HttpClient.Send(HttpRequestMessage, HttpResponseMessage)); - end; - - local procedure PrepareRequestMsg(HttpRequestType: Enum "Http Request Type"; Uri: Text) RequestMessage: HttpRequestMessage - var - HttpHeaders: HttpHeaders; - begin - RequestMessage.Method(Format(HttpRequestType)); - RequestMessage.SetRequestUri(Uri); - RequestMessage.GetHeaders(HttpHeaders); - HttpHeaders.Add(this.AcceptTxt, this.AllTxt); - end; - - local procedure XmlToTxt(var TempBlob: Codeunit "Temp Blob"): Text - var - XMLDOMManagement: Codeunit "XML DOM Management"; - Content: Text; - begin - XMLDOMManagement.TryGetXMLAsText(TempBlob.CreateInStream(TextEncoding::UTF8), Content); - exit(Content); - end; - - local procedure GetDocumentType(EDocument: Record "E-Document"): Text - begin - if EDocument.Direction = EDocument.Direction::Incoming then - exit(this.ApplicationResponseTxt); - - 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(this.InvoiceTxt); - "E-Document Type"::"Issued Finance Charge Memo", "E-Document Type"::"Issued Reminder": - exit(this.PaymentReminderTxt); - else - Error(this.UnSupportedDocumentTypeTxt, EDocument."Document Type"); - end; - end; - - local procedure GetCustomerID(EDocument: Record "E-Document"): Text[50] - var - Customer: Record Customer; - begin - Customer.SetLoadFields("Service Participant Id"); - 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.SetLoadFields("Country/Region Code"); - 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 EnvironmentType): Text - var - Base64Convert: Codeunit "Base64 Convert"; - JsonObject: JsonObject; - ContentText: Text; - begin - JsonObject.Add(this.DocumentTypeTxt, DocumentType); - JsonObject.Add(this.ReceiverTxt, this.SenderReceiverPrefixTxt + RecieverCompanyID); - JsonObject.Add(this.SenderTxt, this.SenderReceiverPrefixTxt + SendingCompanyID); - JsonObject.Add(this.SenderCountryCodeTxt, SenderCountryCode); - JsonObject.Add(this.DocumentIdTxt, this.DocumentIdValueTxt); - JsonObject.Add(this.DocumentIdSchemeTxt, this.BusdoxDocIdQNSTxt); - JsonObject.Add(this.ProcessIdTxt, this.ProcessIdValueTxt); - JsonObject.Add(this.ProcessIdSchemeTxt, this.ProcessIdSchemeValueTxt); - JsonObject.Add(this.SendModeTxt, Format(SendMode)); - JsonObject.Add(this.DocumentTxt, Base64Convert.ToBase64(Payload)); - JsonObject.WriteTo(ContentText); - exit(ContentText); - end; - - #endregion -} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/AuthenticationImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/AuthenticationImpl.Codeunit.al deleted file mode 100644 index eb67cae275..0000000000 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/AuthenticationImpl.Codeunit.al +++ /dev/null @@ -1,344 +0,0 @@ -// ------------------------------------------------------------------------------------------------ -// 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 System.Azure.KeyVault; -using System.Environment; -using System.Security.Authentication; -using System.Azure.Identity; - -codeunit 6390 AuthenticationImpl -{ - Access = Internal; - InherentEntitlements = X; - InherentPermissions = X; - - #region variables - var - ConnectionSetup: Record ConnectionSetup; - HelpersImpl: Codeunit HelpersImpl; - BearerTxt: Label 'Bearer %1', Comment = '%1 = text value', Locked = true; - AuthURLTxt: Label 'https://login.microsoftonline.com/%1/oauth2/token', Comment = '%1 Entra Tenant Id', Locked = true; - ProdTenantIdTxt: Label '0d725623-dc26-484f-a090-b09d2003d092', Locked = true; - ProdServiceAPITxt: Label 'https://edoc.exflow.io', Locked = true; - ErrorTokenLbl: Label 'Unable to fetch a root token.'; - ErrorUnableToCreateClientCredentialsLbl: Label 'Unable to create client credentials.'; - ClientIdTxt: Label 'clientId', Locked = true; - ClientSecretTxt: Label 'clientSecret', Locked = true; - SignupRootUrlTxt: Label 'signup-root-url', Locked = true; - RootIdTxt: Label '-root-id', Locked = true; - SignUpRootSecretTxt: Label 'signup-root-secret', Locked = true; - SignUpRootTenantTxt: Label 'signup-root-tenant', Locked = true; - SignUpAccessTokenKeyTxt: Label '{E45BB975-E67B-4A87-AC24-D409A5EF8301}', Locked = true; - - #endregion - - #region public methods - - procedure InitConnectionSetup() - begin - if this.ConnectionSetup.Get() then - exit; - - this.ConnectionSetup."Authentication URL" := this.AuthURLTxt; - this.ConnectionSetup.ServiceURL := this.ProdServiceAPITxt; - this.StorageSet(this.ConnectionSetup."Client Tenant", this.ProdTenantIdTxt); - this.ConnectionSetup.Insert(); - end; - - procedure GetRootOnboardingUrl(): Text - begin - exit(this.GetRootUrl() + '/supm/landingpage?EntraTenantId=' + this.GetBCInstanceIdentifier()); - end; - - [NonDebuggable] - procedure CreateClientCredentials() - var - HttpRequestMessage: HttpRequestMessage; - HttpResponseMessage: HttpResponseMessage; - ClientId, Response : Text; - ClientSecret: SecretText; - begin - if not this.GetClientCredentials(HttpRequestMessage, HttpResponseMessage) then - Error(this.ErrorUnableToCreateClientCredentialsLbl); - - if not HttpResponseMessage.Content.ReadAs(Response) then - exit; - - ClientId := this.HelpersImpl.GetJsonValueFromText(Response, this.ClientIdTxt); - ClientSecret := this.HelpersImpl.GetJsonValueFromText(Response, this.ClientSecretTxt); - - if (ClientId <> '') and (not ClientSecret.IsEmpty()) then - this.SaveClientCredentials(ClientId, ClientSecret); - end; - - procedure GetBearerAuthToken(): SecretText; - begin - exit(SecretStrSubstNo(this.BearerTxt, this.GetAuthToken())); - end; - - procedure GetRootBearerAuthToken(): SecretText; - begin - exit(SecretStrSubstNo(this.BearerTxt, this.GetRootAuthToken())); - end; - - [NonDebuggable] - procedure StorageSet(var TokenKey: Guid; Value: Text): Boolean - var - ModuleDataScope: DataScope; - begin - ModuleDataScope := ModuleDataScope::Module; - this.ValidateValueKey(TokenKey); - - if Value = '' then begin - if IsolatedStorage.Contains(TokenKey, ModuleDataScope) then - exit(IsolatedStorage.Delete(TokenKey, ModuleDataScope)) - end else - exit(IsolatedStorage.Set(TokenKey, Value, ModuleDataScope)); - end; - - procedure StorageSet(var TokenKey: Guid; Value: SecretText): Boolean - begin - exit(this.StorageSet(TokenKey, Value, DataScope::Module)); - end; - - procedure GetBCInstanceIdentifier() Identifier: Text - var - AADTenantID, AADDomainName : Text; - begin - Identifier := '10000000-d8ef-4dfb-b761-ffb073057794'; // Hardcoded fake during testing only - - if this.GetAADTenantInformation(AADTenantID, AADDomainName) then - Identifier := AADTenantID; - end; - - [NonDebuggable] - procedure GetRootUrl() ReturnValue: Text - begin - if this.FetchSecretFromKeyVault(this.SignupRootUrlTxt, ReturnValue) then - exit; - - if not this.ConnectionSetup.GetSetup() then - exit; - - this.ConnectionSetup.TestField("Root Market URL"); - ReturnValue := this.StorageGetText(this.ConnectionSetup."Root Market URL", DataScope::Module); - end; - - #endregion - - #region local methods - - local procedure GetAuthToken() AccessToken: SecretText; - var - HttpError: Text; - begin - AccessToken := this.StorageGet(this.SignUpAccessTokenKeyTxt, DataScope::Company); - - if this.HelpersImpl.IsTokenValid(AccessToken) then - exit; - - if not this.RefreshAccessToken(HttpError) then - Error(HttpError); - - exit(this.StorageGet(this.SignUpAccessTokenKeyTxt, DataScope::Company)); - end; - - local procedure GetRootAuthToken() ReturnValue: SecretText; - begin - if not this.GetRootAccessToken(ReturnValue) then - Error(this.ErrorTokenLbl); - end; - - local procedure SaveClientCredentials(ClientId: Text; ClientSecret: SecretText) - begin - Clear(this.ConnectionSetup); - - this.ConnectionSetup.GetSetup(); - this.StorageSet(this.ConnectionSetup."Client ID", ClientId); - this.StorageSet(this.ConnectionSetup."Client Secret", ClientSecret); - this.ConnectionSetup.Modify(); - - Clear(this.ConnectionSetup); - end; - - [NonDebuggable] - local procedure GetClientCredentials(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean - var - APIRequests: Codeunit APIRequests; - begin - APIRequests.GetMarketPlaceCredentials(HttpRequestMessage, HttpResponseMessage); - - if not HttpResponseMessage.IsSuccessStatusCode() then - exit; - - exit(this.HelpersImpl.ParseJsonString(HttpResponseMessage.Content) <> ''); - end; - - [NonDebuggable] - local procedure RefreshAccessToken(var HttpError: Text): Boolean; - var - SecretToken: SecretText; - begin - if not this.GetClientAccessToken(SecretToken) then begin - HttpError := GetLastErrorText(); - exit; - end; - - exit(this.SaveSignUpAccessToken(DataScope::Company, SecretToken)); - end; - - [NonDebuggable] - local procedure GetRootAccessToken(var AccessToken: SecretText): Boolean - begin - exit(this.GetAccessToken(AccessToken, this.GetRootId(), this.GetRootSecret(), this.GetRootTenant())); - end; - - [NonDebuggable] - local procedure GetClientAccessToken(var AccessToken: SecretText): Boolean - var - ModuleDataScope: DataScope; - begin - ModuleDataScope := ModuleDataScope::Module; - this.ConnectionSetup.GetSetup(); - - exit(this.GetAccessToken(AccessToken, this.StorageGetText(this.ConnectionSetup."Client ID", ModuleDataScope), - this.StorageGet(this.ConnectionSetup."Client Secret", ModuleDataScope), - this.StorageGetText(this.ConnectionSetup."Client Tenant", ModuleDataScope))); - end; - - [NonDebuggable] - local procedure GetAccessToken(var AccessToken: SecretText; ClientId: Text; ClientSecret: SecretText; ClientTenant: Text) Success: Boolean - var - OAuth2: Codeunit OAuth2; - begin - Success := OAuth2.AcquireTokenWithClientCredentials(ClientId, ClientSecret, StrSubstNo(this.ConnectionSetup."Authentication URL", ClientTenant), '', ClientId, AccessToken); - exit(Success and not AccessToken.IsEmpty()); - end; - - local procedure StorageSet(var TokenKey: Guid; Value: SecretText; TokenDataScope: DataScope): Boolean - begin - this.ValidateValueKey(TokenKey); - - if Value.IsEmpty() then begin - if IsolatedStorage.Contains(TokenKey, TokenDataScope) then - exit(IsolatedStorage.Delete(TokenKey, TokenDataScope)) - end else - exit(IsolatedStorage.Set(TokenKey, Value, TokenDataScope)); - end; - - local procedure StorageGet(TokenKey: Text; TokenDataScope: DataScope) TokenValueAsSecret: SecretText - begin - if not this.StorageContains(TokenKey, TokenDataScope) then - exit(TokenValueAsSecret); - - IsolatedStorage.Get(TokenKey, TokenDataScope, TokenValueAsSecret); - end; - - [NonDebuggable] - local procedure StorageGetText(TokenKey: Text; TokenDataScope: DataScope) TokenValue: Text - begin - if not this.StorageContains(TokenKey, TokenDataScope) then - exit(TokenValue); - - IsolatedStorage.Get(TokenKey, TokenDataScope, TokenValue); - end; - - local procedure SaveSignUpAccessToken(TokenDataScope: DataScope; AccessToken: SecretText): Boolean - var - SignUpAccessTokenKey: Guid; - begin - SignUpAccessTokenKey := this.GetSignUpAccessTokenKey(); - exit(this.StorageSet(SignUpAccessTokenKey, AccessToken, TokenDataScope)); - end; - - local procedure StorageContains(TokenKey: Text; TokenDataScope: DataScope): Boolean - begin - exit(IsolatedStorage.Contains(TokenKey, TokenDataScope)); - end; - - local procedure ValidateValueKey(var ValueKey: Guid) - begin - if IsNullGuid(ValueKey) then - ValueKey := CreateGuid(); - end; - - local procedure GetSignUpAccessTokenKey() SignUpAccessTokenKey: Guid - begin - Evaluate(SignUpAccessTokenKey, this.SignUpAccessTokenKeyTxt); - end; - - [NonDebuggable] - local procedure GetRootId() ReturnValue: Text - begin - if this.FetchSecretFromKeyVault(this.RootIdTxt, ReturnValue) then - exit; - - if not this.ConnectionSetup.GetSetup() then - exit; - - this.ConnectionSetup.TestField("Root App ID"); - ReturnValue := this.StorageGetText(this.ConnectionSetup."Root App ID", DataScope::Module); - end; - - [NonDebuggable] - local procedure GetRootSecret() ReturnValue: Text - begin - if this.FetchSecretFromKeyVault(this.SignUpRootSecretTxt, ReturnValue) then - exit; - - if not this.ConnectionSetup.GetSetup() then - exit; - - this.ConnectionSetup.TestField("Root Secret"); - ReturnValue := this.StorageGetText(this.ConnectionSetup."Root Secret", DataScope::Module); - end; - - [NonDebuggable] - local procedure GetRootTenant() ReturnValue: Text - begin - if this.FetchSecretFromKeyVault(this.SignUpRootTenantTxt, ReturnValue) then - exit; - - if not this.ConnectionSetup.GetSetup() then - exit; - - this.ConnectionSetup.TestField("Root Tenant"); - ReturnValue := this.StorageGetText(this.ConnectionSetup."Root Tenant", DataScope::Module); - end; - - [NonDebuggable] - local procedure FetchSecretFromKeyVault(KeyName: Text; var KeyValue: Text): Boolean - var - AzureKeyVault: Codeunit "Azure Key Vault"; - EnvironmentInformation: Codeunit "Environment Information"; - begin - if EnvironmentInformation.IsSaaSInfrastructure() then - exit(AzureKeyVault.GetAzureKeyVaultSecret(KeyName, KeyValue)); - end; - - local procedure GetAADTenantInformation(var AADTenantID: Text; var AADDomainName: Text): Boolean - begin - exit(this.GetAADTenantID(AADTenantID) and this.GetAADDomainName(AADDomainName)); - end; - - [TryFunction] - local procedure GetAADTenantID(var AADTenantID: Text) - var - AzureADTenant: Codeunit "Azure AD Tenant"; - begin - AADTenantID := AzureADTenant.GetAadTenantId(); - end; - - [TryFunction] - local procedure GetAADDomainName(var AADDomainName: Text) - var - AzureADTenant: Codeunit "Azure AD Tenant"; - begin - AADDomainName := AzureADTenant.GetAadTenantId(); - end; - - #endregion -} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionImpl.Codeunit.al deleted file mode 100644 index 520cd055c6..0000000000 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/ConnectionImpl.Codeunit.al +++ /dev/null @@ -1,116 +0,0 @@ -// ------------------------------------------------------------------------------------------------ -// 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.Purchases.Document; -using Microsoft.Purchases.Posting; -using System.Utilities; - -codeunit 6391 ConnectionImpl -{ - Access = Internal; - InherentEntitlements = X; - InherentPermissions = X; - Permissions = tabledata "E-Document" = m; - - #region variables - - var - APIRequests: Codeunit APIRequests; - HelpersImpl: Codeunit HelpersImpl; - UnsuccessfulResponseErr: Label 'There was an error sending the request. Response code: %1 and error message: %2', Comment = '%1 - http response status code, e.g. 400, %2- error message'; - EnvironmentBlocksErr: Label 'The request to send documents has been blocked. To resolve the problem, enable outgoing HTTP requests for the E-Document apps on the Extension Management page.'; - - #endregion - - #region public methods - - procedure SendFilePostRequest(var TempBlob: Codeunit "Temp Blob"; var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean - begin - this.APIRequests.SendFilePostRequest(TempBlob, EDocument, HttpRequestMessage, HttpResponseMessage); - exit(this.CheckIfSuccessfulRequest(EDocument, HttpResponseMessage)); - end; - - procedure CheckDocumentStatus(var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean - begin - this.APIRequests.GetSentDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage); - exit(this.CheckIfSuccessfulRequest(EDocument, HttpResponseMessage)); - end; - - procedure GetReceivedDocuments(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean - begin - this.APIRequests.GetReceivedDocumentsRequest(HttpRequestMessage, HttpResponseMessage); - - if not HttpResponseMessage.IsSuccessStatusCode() then - exit; - - exit(this.HelpersImpl.ParseJsonString(HttpResponseMessage.Content) <> ''); - end; - - procedure GetTargetDocumentRequest(DocumentId: Text; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean - begin - this.APIRequests.GetTargetDocumentRequest(DocumentId, HttpRequestMessage, HttpResponseMessage); - exit(HttpResponseMessage.IsSuccessStatusCode()); - end; - - procedure RemoveDocumentFromReceived(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean - begin - this.APIRequests.PatchReceivedDocument(EDocument, HttpRequestMessage, HttpResponseMessage); - exit(HttpResponseMessage.IsSuccessStatusCode()); - end; - - #endregion - - #region local methods - - local procedure CheckIfSuccessfulRequest(EDocument: Record "E-Document"; HttpResponseMessage: HttpResponseMessage): Boolean - var - EDocumentErrorHelper: Codeunit "E-Document Error Helper"; - begin - if HttpResponseMessage.IsSuccessStatusCode() then - exit(true); - - if HttpResponseMessage.IsBlockedByEnvironment() then - EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, this.EnvironmentBlocksErr) - else - EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, StrSubstNo(this.UnsuccessfulResponseErr, HttpResponseMessage.HttpStatusCode, HttpResponseMessage.ReasonPhrase)); - end; - - #endregion - - #region event subscribers - - [EventSubscriber(ObjectType::Codeunit, Codeunit::"Purch.-Post", OnAfterCheckAndUpdate, '', false, false)] - local procedure CheckOnPosting(var PurchaseHeader: Record "Purchase Header"; CommitIsSuppressed: Boolean; PreviewMode: Boolean) - var - EDocument: Record "E-Document"; - EDocumentService: Record "E-Document Service"; - EDocumentServiceStatus: Record "E-Document Service Status"; - begin - if PurchaseHeader.IsTemporary() then - exit; - - EDocument.SetLoadFields("Entry No"); - EDocument.SetRange("Document Record ID", PurchaseHeader.RecordId); - if not EDocument.FindFirst() then - exit; - - EDocumentService.SetLoadFields(Code); - EDocumentService.SetRange("Service Integration", EDocumentService."Service Integration"::"ExFlow E-Invoicing"); - if not EDocumentService.FindFirst() then - exit; - - EDocumentServiceStatus.SetLoadFields(Status); - EDocumentServiceStatus.SetRange("E-Document Entry No", EDocument."Entry No"); - EDocumentServiceStatus.SetRange("E-Document Service Code", EDocumentService.Code); - if EDocumentServiceStatus.FindSet() then - repeat - EDocumentServiceStatus.TestField(EDocumentServiceStatus.Status, EDocumentServiceStatus.Status::Approved); - until EDocumentServiceStatus.Next() = 0; - end; - - #endregion -} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/HelpersImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/HelpersImpl.Codeunit.al deleted file mode 100644 index d6bb899b42..0000000000 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/HelpersImpl.Codeunit.al +++ /dev/null @@ -1,92 +0,0 @@ -// ------------------------------------------------------------------------------------------------ -// 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 System.Reflection; -using Microsoft.Utilities; -using System.Integration; - -codeunit 6385 HelpersImpl -{ - Access = Internal; - - var - ClaimTypeTxt: Label 'exp', Locked = true; - - #region public methods - - [NonDebuggable] - procedure ParseJsonString(HttpContent: HttpContent): Text - var - JsonObject: JsonObject; - Content: Text; - begin - if not HttpContent.ReadAs(Content) then - exit; - - if JsonObject.ReadFrom(Content) then - exit(Content); - end; - - [NonDebuggable] - procedure GetJsonValueFromText(JsonText: Text; Path: Text): Text - var - JsonObject: JsonObject; - JsonToken: JsonToken; - begin - if JsonObject.ReadFrom(JsonText) then - if JsonObject.SelectToken(Path, JsonToken) then - exit(this.GetJsonValue(JsonToken.AsValue())); - end; - - procedure IsTokenValid(InToken: SecretText): Boolean - begin - exit(this.GetTokenDateTimeValue(InToken, this.ClaimTypeTxt) > CurrentDateTime()); - end; - - #endregion - - #region local methods - - local procedure GetTokenDateTimeValue(InToken: SecretText; ClaimType: Text): DateTime - var - TypeHelper: Codeunit "Type Helper"; - Timestamp: Decimal; - begin - if Evaluate(Timestamp, this.GetValueFromToken(InToken, ClaimType)) then - exit(TypeHelper.EvaluateUnixTimestamp(Timestamp)); - end; - - [NonDebuggable] - local procedure GetValueFromToken(InToken: SecretText; ClaimType: Text): Text - var - TempNameValueBuffer: Record "Name/Value Buffer" temporary; - SOAPWebServiceRequestMgt: Codeunit "SOAP Web Service Request Mgt."; - begin - if InToken.IsEmpty() then - exit; - - TempNameValueBuffer.DeleteAll(); - SOAPWebServiceRequestMgt.GetTokenDetailsAsNameBuffer(InToken, TempNameValueBuffer); - TempNameValueBuffer.Reset(); - TempNameValueBuffer.SetRange(Name, ClaimType); - if TempNameValueBuffer.FindFirst() then - exit(TempNameValueBuffer.Value); - end; - - [NonDebuggable] - local procedure GetJsonValue(JsonValue: JsonValue): Text - begin - if JsonValue.IsNull() then - exit; - - if JsonValue.IsUndefined() then - exit; - - exit(JsonValue.AsText()); - end; - - #endregion -} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/GetReadyStatusJob.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/GetReadyStatusJob.Codeunit.al deleted file mode 100644 index 64b10485a4..0000000000 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/GetReadyStatusJob.Codeunit.al +++ /dev/null @@ -1,90 +0,0 @@ -// ------------------------------------------------------------------------------------------------ -// 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 System.Telemetry; -using System.Threading; -using Microsoft.EServices.EDocument; - -codeunit 6384 GetReadyStatusJob -{ - TableNo = "Job Queue Entry"; - Access = Internal; - InherentEntitlements = X; - InherentPermissions = X; - - var - EDocTelemetryGetResponseScopeStartLbl: Label 'E-Document Get Response: Start Scope', Locked = true; - EDocTelemetryGetResponseScopeEndLbl: Label 'E-Document Get Response: End Scope', Locked = true; - - trigger OnRun() - var - JobHelperImpl: Codeunit JobHelperImpl; - BlankRecordId: RecordId; - begin - if not this.IsEDocumentStatusSent() then - exit; - - this.ProcessSentDocuments(); - - if this.IsEDocumentStatusSent() then - JobHelperImpl.ScheduleEDocumentJob(Codeunit::GetReadyStatusJob, BlankRecordId, 300000); - end; - - local procedure ProcessSentDocuments() - var - EDocumentServiceStatus: Record "E-Document Service Status"; - EDocumentService: Record "E-Document Service"; - EDocument: Record "E-Document"; - JobHelperImpl: Codeunit JobHelperImpl; - begin - EDocumentServiceStatus.SetLoadFields("E-Document Service Code", "E-Document Entry No"); - EDocumentServiceStatus.SetRange(Status, EDocumentServiceStatus.Status::Sent); - if EDocumentServiceStatus.FindSet() then - repeat - JobHelperImpl.FetchEDocumentAndService(EDocument, EDocumentService, EDocumentServiceStatus); - this.HandleResponse(EDocument, EDocumentService); - until EDocumentServiceStatus.Next() = 0; - end; - - local procedure HandleResponse(var EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service") - var - Processing: Codeunit Processing; - JobHelperImpl: Codeunit JobHelperImpl; - BlankRecordId: RecordId; - HttpResponseMessage: HttpResponseMessage; - HttpRequestMessage: HttpRequestMessage; - begin - if this.GetResponse(EDocument, HttpRequestMessage, HttpResponseMessage) then begin - Processing.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Approved, 0, HttpRequestMessage, HttpResponseMessage); - JobHelperImpl.ScheduleEDocumentJob(Codeunit::PatchSentJob, BlankRecordId, 300000); - end; - end; - - local procedure GetResponse(var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) ReturnStatus: Boolean - var - Processing: Codeunit Processing; - Telemetry: Codeunit Telemetry; - TelemetryDimensions: Dictionary of [Text, Text]; - begin - // Commit before create document with error handling - Commit(); - - Telemetry.LogMessage('', this.EDocTelemetryGetResponseScopeStartLbl, Verbosity::Normal, DataClassification::OrganizationIdentifiableInformation, TelemetryScope::All, TelemetryDimensions); - - if Processing.GetDocumentSentResponse(EDocument, HttpRequestMessage, HttpResponseMessage) then - ReturnStatus := true; - - Telemetry.LogMessage('', this.EDocTelemetryGetResponseScopeEndLbl, Verbosity::Normal, DataClassification::OrganizationIdentifiableInformation, TelemetryScope::All); - end; - - local procedure IsEDocumentStatusSent(): Boolean - var - EdocumentServiceStatus: Record "E-Document Service Status"; - begin - EdocumentServiceStatus.SetRange(Status, EdocumentServiceStatus.Status::Sent); - exit(not EdocumentServiceStatus.IsEmpty()); - end; -} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/JobHelperImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/JobHelperImpl.Codeunit.al deleted file mode 100644 index fac63284e2..0000000000 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/JobHelperImpl.Codeunit.al +++ /dev/null @@ -1,83 +0,0 @@ -// ------------------------------------------------------------------------------------------------ -// 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 System.Telemetry; -using System.Threading; -using Microsoft.EServices.EDocument; - -codeunit 6392 JobHelperImpl -{ - TableNo = "Job Queue Entry"; - Access = Internal; - InherentEntitlements = X; - InherentPermissions = X; - - #region variables - - var - Telemetry: Codeunit Telemetry; - JobQueueCategoryTok: Label 'EDocument', Locked = true, Comment = 'Max Length 10'; - EDocumentJobTelemetryLbl: Label 'E-Document Background Job Scheduled', Locked = true; - JobQueueIdTxt: Label 'Job Queue Id', Locked = true; - CodeunitIsTxt: Label 'Codeunit Id', Locked = true; - RecordIdTxt: Label 'Record Id', Locked = true; - UserSessionIdTxt: Label 'User Session ID', Locked = true; - EarliestStartDateTimeTxt: Label 'Earliest Start Date/Time', Locked = true; - - #endregion - - #region public methods - - procedure ScheduleEDocumentJob(CodeunitId: Integer; JobRecordId: RecordId; EarliestStartDateTime: Integer): Guid - var - JobQueueEntry: Record "Job Queue Entry"; - TelemetryDimensions: Dictionary of [Text, Text]; - begin - if this.IsJobQueueScheduled(CodeunitId) then - exit; - - JobQueueEntry.Init(); - JobQueueEntry."Object Type to Run" := JobQueueEntry."Object Type to Run"::Codeunit; - JobQueueEntry."Object ID to Run" := CodeunitId; - JobQueueEntry."Record ID to Process" := JobRecordId; - JobQueueEntry."User Session ID" := SessionId(); - JobQueueEntry."Job Queue Category Code" := this.JobQueueCategoryTok; - JobQueueEntry."No. of Attempts to Run" := 0; - JobQueueEntry."Earliest Start Date/Time" := CurrentDateTime + EarliestStartDateTime; - - TelemetryDimensions.Add(this.JobQueueIdTxt, JobQueueEntry.ID); - TelemetryDimensions.Add(this.CodeunitIsTxt, Format(CodeunitId)); - TelemetryDimensions.Add(this.RecordIdTxt, Format(JobRecordId)); - TelemetryDimensions.Add(this.UserSessionIdTxt, Format(JobQueueEntry."User Session ID")); - TelemetryDimensions.Add(this.EarliestStartDateTimeTxt, Format(JobQueueEntry."Earliest Start Date/Time")); - this.Telemetry.LogMessage('', this.EDocumentJobTelemetryLbl, Verbosity::Normal, DataClassification::OrganizationIdentifiableInformation, TelemetryScope::All, TelemetryDimensions); - Codeunit.Run(Codeunit::"Job Queue - Enqueue", JobQueueEntry); - exit(JobQueueEntry.ID); - end; - - procedure FetchEDocumentAndService(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; EDocumentServiceStatus: Record "E-Document Service Status") - begin - EDocumentService.SetLoadFields("Service Integration", "Document Format"); - EDocumentService.Get(EDocumentServiceStatus."E-Document Service Code"); - EDocument.Get(EDocumentServiceStatus."E-Document Entry No"); - end; - - #endregion - - #region local methods - - local procedure IsJobQueueScheduled(CodeunitId: Integer): Boolean - var - JobQueueEntry: Record "Job Queue Entry"; - begin - JobQueueEntry.SetRange("Object Type to Run", JobQueueEntry."Object Type to Run"::Codeunit); - JobQueueEntry.SetRange("Object ID to Run", CodeunitId); - JobQueueEntry.SetFilter(Status, '%1|%2', JobQueueEntry.Status::Ready, JobQueueEntry.Status::"In Process"); - exit(not JobQueueEntry.IsEmpty()); - end; - - #endregion -} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/PatchSentJob.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/PatchSentJob.Codeunit.al deleted file mode 100644 index 69e07127ba..0000000000 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Jobs/PatchSentJob.Codeunit.al +++ /dev/null @@ -1,79 +0,0 @@ -// ------------------------------------------------------------------------------------------------ -// 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 System.Threading; -using Microsoft.EServices.EDocument; -using System.Security.Authentication; - -codeunit 6387 PatchSentJob -{ - TableNo = "Job Queue Entry"; - Access = Internal; - InherentEntitlements = X; - InherentPermissions = X; - - trigger OnRun() - var - JobHelperImpl: Codeunit JobHelperImpl; - BlankRecordId: RecordId; - begin - if not this.IsEDocumentApproved() then - exit; - - this.ProcessApprovedDocuments(); - - if this.IsEDocumentApproved() then - JobHelperImpl.ScheduleEDocumentJob(Codeunit::PatchSentJob, BlankRecordId, 300000); - end; - - local procedure ProcessApprovedDocuments() - var - EDocumentServiceStatus: Record "E-Document Service Status"; - EDocumentService: Record "E-Document Service"; - EDocumentIntegrationLog: Record "E-Document Integration Log"; - EDocument: Record "E-Document"; - APIRequests: Codeunit APIRequests; - Processing: Codeunit Processing; - JobHelperImpl: Codeunit JobHelperImpl; - HttpResponseMessage: HttpResponseMessage; - HttpRequestMessage: HttpRequestMessage; - begin - EDocumentServiceStatus.SetLoadFields("E-Document Service Code", "E-Document Entry No"); - EDocumentServiceStatus.SetRange(Status, EDocumentServiceStatus.Status::Approved); - if EDocumentServiceStatus.FindSet() then - repeat - JobHelperImpl.FetchEDocumentAndService(EDocument, EDocumentService, EDocumentServiceStatus); - - EDocumentIntegrationLog.Reset(); - EDocumentIntegrationLog.SetRange("E-Doc. Entry No", EDocument."Entry No"); - EDocumentIntegrationLog.SetRange("Response Status", 204); - EDocumentIntegrationLog.SetRange(Method, Format("Http Request Type"::PATCH)); - if EDocumentIntegrationLog.IsEmpty() then - if APIRequests.PatchDocument(EDocument, HttpRequestMessage, HttpResponseMessage) then - Processing.InsertIntegrationLog(EDocument, EDocumentService, HttpRequestMessage, HttpResponseMessage); - until EDocumentServiceStatus.Next() = 0; - end; - - local procedure IsEDocumentApproved(): Boolean - var - EdocumentServiceStatus: Record "E-Document Service Status"; - EDocumentIntegrationLog: Record "E-Document Integration Log"; - HasRecords: Boolean; - begin - EdocumentServiceStatus.SetLoadFields("E-Document Entry No"); - EdocumentServiceStatus.SetRange(Status, EdocumentServiceStatus.Status::Approved); - if EdocumentServiceStatus.FindSet() then - repeat - EDocumentIntegrationLog.Reset(); - EDocumentIntegrationLog.SetRange("E-Doc. Entry No", EdocumentServiceStatus."E-Document Entry No"); - EDocumentIntegrationLog.SetRange("Response Status", 204); - EDocumentIntegrationLog.SetRange(Method, Format("Http Request Type"::PATCH)); - HasRecords := EDocumentIntegrationLog.IsEmpty(); - until (EdocumentServiceStatus.Next() = 0) or (HasRecords); - - exit(HasRecords); - end; -} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Edit.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Edit.PermissionSet.al deleted file mode 100644 index a2d386e6b3..0000000000 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Edit.PermissionSet.al +++ /dev/null @@ -1,15 +0,0 @@ -// ------------------------------------------------------------------------------------------------ -// 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 Edit -{ - Access = Internal; - Assignable = false; - Caption = 'SignUp E-Doc. Connector - Edit', MaxLength = 30; - IncludedPermissionSets = Read; - - Permissions = tabledata ConnectionSetup = imd; -} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Objects.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Objects.PermissionSet.al deleted file mode 100644 index 9ade56ad84..0000000000 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Objects.PermissionSet.al +++ /dev/null @@ -1,29 +0,0 @@ -// ------------------------------------------------------------------------------------------------ -// 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 Objects -{ - Access = Internal; - Assignable = false; - Caption = 'SignUp E-Doc. Connector - Obj.', MaxLength = 30; - - Permissions = table ConnectionSetup = X, - page ConnectionSetupCard = X, - codeunit IntegrationImpl = X, - codeunit PatchSentJob = X, - codeunit JobHelperImpl = X, - codeunit GetReadyStatusJob = X, - codeunit APIRequests = X, - codeunit APIRequestsImpl = X, - codeunit Authentication = X, - codeunit AuthenticationImpl = X, - codeunit Connection = X, - codeunit ConnectionImpl = X, - codeunit HelpersImpl = X, - codeunit Processing = X, - codeunit ProcessingImpl = X; - -} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Read.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Read.PermissionSet.al deleted file mode 100644 index 2129fcf1a1..0000000000 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/Read.PermissionSet.al +++ /dev/null @@ -1,15 +0,0 @@ -// ------------------------------------------------------------------------------------------------ -// 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 Read -{ - Access = Internal; - Assignable = false; - Caption = 'SignUp E-Doc. Connector - Read', MaxLength = 30; - IncludedPermissionSets = Objects; - - Permissions = tabledata ConnectionSetup = r; -} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocConnectorEdit.PermissionSetExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocConnectorEdit.PermissionSetExt.al deleted file mode 100644 index 94cbf00cde..0000000000 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocConnectorEdit.PermissionSetExt.al +++ /dev/null @@ -1,11 +0,0 @@ -// ------------------------------------------------------------------------------------------------ -// 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.EDocumentConnector; - -permissionsetextension 6380 "SignUp EDoc. Connector - Edit" extends "EDocConnector - Edit" -{ - IncludedPermissionSets = Edit; -} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocConnectorRead.PermissionSetExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocConnectorRead.PermissionSetExt.al deleted file mode 100644 index 9c27703bce..0000000000 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocConnectorRead.PermissionSetExt.al +++ /dev/null @@ -1,11 +0,0 @@ -// ------------------------------------------------------------------------------------------------ -// 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.EDocumentConnector; - -permissionsetextension 6381 "SignUp EDoc. Connector - Read" extends "EDocConnector - Read" -{ - IncludedPermissionSets = Read; -} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/ProcessingImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/ProcessingImpl.Codeunit.al deleted file mode 100644 index 0412890010..0000000000 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/ProcessingImpl.Codeunit.al +++ /dev/null @@ -1,580 +0,0 @@ -// ------------------------------------------------------------------------------------------------ -// 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 System.Telemetry; -using System.Text; -using System.Utilities; - -codeunit 6383 ProcessingImpl -{ - Access = Internal; - InherentEntitlements = X; - InherentPermissions = X; - Permissions = tabledata "E-Document" = rim, - tabledata "E-Document Service Status" = rm, - tabledata "E-Document Service" = r, - tabledata "E-Document Integration Log" = ri, - tabledata "E-Document Log" = ri; - - #region variables - var - Connection: Codeunit Connection; - HelpersImpl: Codeunit HelpersImpl; - EDocumentHelper: Codeunit "E-Document Helper"; - EDocumentLogHelper: Codeunit "E-Document Log Helper"; - EDocumentErrorHelper: Codeunit "E-Document Error Helper"; - GetApprovalCheckStatusErr: Label 'You cannot ask for approval with the E-Document in this current status %1. You can request for approval when E-document status is Sent or Pending Response.', Comment = '%1 - Status'; - CouldNotRetrieveDocumentErr: Label 'Could not retrieve document with id: %1 from the service', Comment = '%1 - Document ID'; - DocumentIdNotFoundErr: Label 'Document ID not found in response'; - ExternalServiceTok: Label 'E-Document - SignUp', Locked = true; - InboxTxt: Label 'inbox', Locked = true; - InstanceIdTxt: Label 'instanceId', Locked = true; - PeppolInstanceIdTxt: Label 'peppolInstanceId', Locked = true; - StatusTxt: Label 'status', Locked = true; - SentTxt: Label 'sent', Locked = true; - ReadyTxt: Label 'ready', Locked = true; - FailedTxt: Label 'failed', Locked = true; - DescriptionTxt: Label 'description', Locked = true; - ReasonTxt: Label 'Reason: ', Locked = true; - NewTxt: Label 'new', Locked = true; - DocumentTxt: Label 'document', Locked = true; - StandardBusinessDocumentHeaderTxt: Label '', Locked = true; - InvoiceTxt: Label '', Locked = true; - - - #endregion - - #region public methods - - procedure SendEDocument(var EDocument: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) - var - EDocumentServiceStatus: Record "E-Document Service Status"; - EDocumentService: Record "E-Document Service"; - FeatureTelemetry: Codeunit "Feature Telemetry"; - begin - IsAsync := true; - - this.EDocumentHelper.GetEdocumentService(EDocument, EDocumentService); - EDocumentServiceStatus.Get(EDocument."Entry No", EDocumentService.Code); - - case EDocumentServiceStatus.Status of - EDocumentServiceStatus.Status::Exported: - this.SendEDocument(EDocument, TempBlob, HttpRequestMessage, HttpResponseMessage); - EDocumentServiceStatus.Status::"Sending Error": - if EDocument."Document Id" = '' then - this.SendEDocument(EDocument, TempBlob, HttpRequestMessage, HttpResponseMessage); - end; - - FeatureTelemetry.LogUptake('', this.ExternalServiceTok, Enum::"Feature Uptake Status"::Used); - end; - - procedure GetDocumentResponse(var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean - var - ErrorDescription: Text; - begin - if not this.Connection.CheckDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage) then - exit; - exit(not this.DocumentHasErrorOrStillInProcessing(EDocument, HttpResponseMessage, ErrorDescription)); - end; - - procedure GetDocumentSentResponse(var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean - var - EDocumentService: Record "E-Document Service"; - APIRequests: Codeunit APIRequests; - Status, StatusDescription : Text; - begin - this.EDocumentHelper.GetEdocumentService(EDocument, EdocumentService); - APIRequests.GetSentDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage); - if not this.ParseGetADocumentApprovalResponse(HttpResponseMessage.Content, Status, StatusDescription) then - exit; - - case Status of - this.ReadyTxt: - exit(true); - this.FailedTxt: - begin - if StatusDescription <> '' then - this.EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, this.ReasonTxt + StatusDescription); - this.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Rejected, 0, HttpRequestMessage, HttpResponseMessage); - exit; - end; - end; - end; - - procedure GetDocumentApproval(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean - var - EDocumentService: Record "E-Document Service"; - EDocumentServiceStatus: Record "E-Document Service Status"; - APIRequests: Codeunit APIRequests; - JobHelperImpl: Codeunit JobHelperImpl; - BlankRecordId: RecordId; - Status, StatusDescription : Text; - begin - this.EDocumentHelper.GetEdocumentService(EDocument, EdocumentService); - EDocumentServiceStatus.SetLoadFields(Status); - EDocumentServiceStatus.Get(EDocument."Entry No", EdocumentService.Code); - if not (EDocumentServiceStatus.Status in [EDocumentServiceStatus.Status::Sent, EDocumentServiceStatus.Status::"Pending Response"]) then - Error(this.GetApprovalCheckStatusErr, EDocumentServiceStatus.Status); - - APIRequests.GetSentDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage); - if not this.ParseGetADocumentApprovalResponse(HttpResponseMessage.Content, Status, StatusDescription) then - exit; - - case Status of - this.ReadyTxt: - begin - if EDocumentServiceStatus.Status = EDocumentServiceStatus.Status::Approved then - JobHelperImpl.ScheduleEDocumentJob(Codeunit::PatchSentJob, BlankRecordId, 300000) - else - JobHelperImpl.ScheduleEDocumentJob(Codeunit::GetReadyStatusJob, BlankRecordId, 300000); - exit(true); - end; - this.FailedTxt: - begin - if StatusDescription <> '' then - this.EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, this.ReasonTxt + StatusDescription); - this.InsertLogWithIntegration(EDocument, EDocumentService, Enum::"E-Document Service Status"::Rejected, 0, HttpRequestMessage, HttpResponseMessage); - exit; - end; - end; - end; - - procedure ReceiveDocument(var TempBlob: Codeunit "Temp Blob"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) - var - ContentData: Text; - begin - if not this.Connection.GetReceivedDocuments(HttpRequestMessage, HttpResponseMessage) then - exit; - - if not HttpResponseMessage.Content.ReadAs(ContentData) then - exit; - - TempBlob.CreateOutStream(TextEncoding::UTF8).WriteText(ContentData); - end; - - procedure GetDocumentCountInBatch(var TempBlob: Codeunit "Temp Blob"): Integer - var - ResponseTxt: Text; - begin - TempBlob.CreateInStream().ReadText(ResponseTxt); - exit(this.GetNumberOfReceivedDocuments(ResponseTxt)); - end; - - procedure InsertIntegrationLog(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; HttpRequestMessage: HttpRequestMessage; HttpResponseMessage: HttpResponseMessage) - var - EDocumentIntegrationLog: Record "E-Document Integration Log"; - EDocIntegrationLogRecordRef: RecordRef; - RequestTxt: Text; - begin - if EDocumentService."Service Integration" = EDocumentService."Service Integration"::"No Integration" then - exit; - - EDocumentIntegrationLog.Validate("E-Doc. Entry No", EDocument."Entry No"); - EDocumentIntegrationLog.Validate("Service Code", EDocumentService.Code); - EDocumentIntegrationLog.Validate("Response Status", HttpResponseMessage.HttpStatusCode()); - EDocumentIntegrationLog.Validate("Request URL", HttpRequestMessage.GetRequestUri()); - EDocumentIntegrationLog.Validate(Method, HttpRequestMessage.Method()); - EDocumentIntegrationLog.Insert(); - - EDocIntegrationLogRecordRef.GetTable(EDocumentIntegrationLog); - - if HttpRequestMessage.Content.ReadAs(RequestTxt) then begin - this.InsertIntegrationBlob(EDocIntegrationLogRecordRef, RequestTxt, EDocumentIntegrationLog.FieldNo(EDocumentIntegrationLog."Request Blob")); - EDocIntegrationLogRecordRef.Modify(); - end; - - if HttpResponseMessage.Content.ReadAs(RequestTxt) then begin - this.InsertIntegrationBlob(EDocIntegrationLogRecordRef, RequestTxt, EDocumentIntegrationLog.FieldNo(EDocumentIntegrationLog."Response Blob")); - EDocIntegrationLogRecordRef.Modify(); - end; - end; - - procedure InsertLogWithIntegration(var EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; - EDocumentServiceStatus: Enum "E-Document Service Status"; EDocDataStorageEntryNo: Integer; HttpRequestMessage: HttpRequestMessage; HttpResponseMessage: HttpResponseMessage) - begin - this.InsertLog(EDocument, EDocumentService, EDocDataStorageEntryNo, EDocumentServiceStatus); - - if (HttpRequestMessage.GetRequestUri() <> '') and (HttpResponseMessage.Headers.Keys().Count > 0) then - this.InsertIntegrationLog(EDocument, EDocumentService, HttpRequestMessage, HttpResponseMessage); - end; - - #endregion - - #region local methods - - local procedure ParseGetADocumentApprovalResponse(HttpContentResponse: HttpContent; var Status: Text; var StatusDescription: Text): Boolean - var - JsonManagement: Codeunit "JSON Management"; - Result: Text; - begin - Result := this.HelpersImpl.ParseJsonString(HttpContentResponse); - if Result = '' then - exit; - - if not JsonManagement.InitializeFromString(Result) then - exit; - - Status := this.GetStatus(JsonManagement); - - if Status in [this.ReadyTxt, this.SentTxt] then - exit(true); - - if Status = this.FailedTxt then begin - JsonManagement.GetArrayPropertyValueAsStringByName(this.DescriptionTxt, StatusDescription); - exit(true); - end; - - exit; - end; - - local procedure InsertLog(var EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; EDocDataStorageEntryNo: Integer; EDocumentServiceStatus: Enum "E-Document Service Status"): Integer - var - EDocumentLog: Record "E-Document Log"; - begin - if EDocumentService.Code <> '' then - this.UpdateServiceStatus(EDocument, EDocumentService, EDocumentServiceStatus); - - EDocumentLog.Validate("Document Type", EDocument."Document Type"); - EDocumentLog.Validate("Document No.", EDocument."Document No."); - EDocumentLog.Validate("E-Doc. Entry No", EDocument."Entry No"); - EDocumentLog.Validate(Status, EDocumentServiceStatus); - EDocumentLog.Validate("Service Integration", EDocumentService."Service Integration"); - EDocumentLog.Validate("Service Code", EDocumentService.Code); - EDocumentLog.Validate("Document Format", EDocumentService."Document Format"); - EDocumentLog.Validate("E-Doc. Data Storage Entry No.", EDocDataStorageEntryNo); - EDocumentLog.Insert(); - - exit(EDocumentLog."Entry No."); - end; - - local procedure UpdateServiceStatus(var EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; EDocumentStatus: Enum "E-Document Service Status") - var - EDocumentServiceStatus: Record "E-Document Service Status"; - Exists: Boolean; - begin - EDocument.Get(EDocument."Entry No"); - Exists := EDocumentServiceStatus.Get(EDocument."Entry No", EDocumentService.Code); - EDocumentServiceStatus.Validate(Status, EDocumentStatus); - if Exists then - EDocumentServiceStatus.Modify() - else begin - EDocumentServiceStatus.Validate("E-Document Entry No", EDocument."Entry No"); - EDocumentServiceStatus.Validate("E-Document Service Code", EDocumentService.Code); - EDocumentServiceStatus.Validate(Status, EDocumentStatus); - EDocumentServiceStatus.Insert(); - end; - - this.UpdateEDocumentStatus(EDocument); - end; - - local procedure SendEDocument(EDocument: Record "E-Document"; TempBlob: Codeunit "Temp Blob"; HttpRequestMessage: HttpRequestMessage; HttpResponseMessage: HttpResponseMessage); - begin - this.Connection.SendFilePostRequest(TempBlob, EDocument, HttpRequestMessage, HttpResponseMessage); - this.SetEDocumentFileID(EDocument."Entry No", this.ParseSendFileResponse(HttpResponseMessage.Content)); - end; - - local procedure ParseReceivedDocument(InputTxt: Text; Index: Integer; var DocumentId: Text): Boolean - var - JsonManagement: Codeunit "JSON Management"; - IncrementalTable, Value : Text; - begin - if not JsonManagement.InitializeFromString(InputTxt) then - exit; - - JsonManagement.GetArrayPropertyValueAsStringByName(this.InboxTxt, Value); - JsonManagement.InitializeCollection(Value); - - if Index = 0 then - Index := 1; - - if Index > JsonManagement.GetCollectionCount() then - exit; - - JsonManagement.GetObjectFromCollectionByIndex(IncrementalTable, Index - 1); - - Clear(JsonManagement); - JsonManagement.InitializeObject(IncrementalTable); - JsonManagement.GetArrayPropertyValueAsStringByName(this.InstanceIdTxt, DocumentId); - - exit(true); - end; - - local procedure GetNumberOfReceivedDocuments(InputTxt: Text): Integer - var - JsonManagement: Codeunit "JSON Management"; - Value: Text; - begin - InputTxt := this.LeaveJustNewLine(InputTxt); - - if not JsonManagement.InitializeFromString(InputTxt) then - exit(0); - - JsonManagement.GetArrayPropertyValueAsStringByName(this.InboxTxt, Value); - JsonManagement.InitializeCollection(Value); - - exit(JsonManagement.GetCollectionCount()); - end; - - local procedure ParseSendFileResponse(HttpContentResponse: HttpContent): Text - var - JsonManagement: Codeunit "JSON Management"; - Result, Value : Text; - begin - Result := this.HelpersImpl.ParseJsonString(HttpContentResponse); - if Result = '' then - exit; - - if not JsonManagement.InitializeFromString(Result) then - exit; - - JsonManagement.GetStringPropertyValueByName(this.PeppolInstanceIdTxt, Value); - exit(Value); - end; - - local procedure SetEDocumentFileID(EDocEntryNo: Integer; FileId: Text) - var - EDocument: Record "E-Document"; - begin - if FileId = '' then - exit; - - if not EDocument.Get(EDocEntryNo) then - exit; - - EDocument."Document Id" := CopyStr(FileId, 1, MaxStrLen(EDocument."Document Id")); - EDocument.Modify(); - end; - - local procedure DocumentHasErrorOrStillInProcessing(EDocument: Record "E-Document"; HttpResponseMessage: HttpResponseMessage; var ErrorDescription: Text): Boolean - var - EDocumentService: Record "E-Document Service"; - EDocumentServiceStatus: Record "E-Document Service Status"; - JsonManagement: Codeunit "JSON Management"; - JobHelperImpl: Codeunit JobHelperImpl; - BlankRecordId: RecordId; - Result, Status : Text; - begin - Result := this.HelpersImpl.ParseJsonString(HttpResponseMessage.Content); - if Result = '' then - exit(true); - - if not JsonManagement.InitializeFromString(Result) then - exit(true); - - Status := this.GetStatus(JsonManagement); - - if Status in [this.SentTxt] then begin - JobHelperImpl.ScheduleEDocumentJob(Codeunit::GetReadyStatusJob, BlankRecordId, 120000); - exit; - end; - - if Status in [this.ReadyTxt] then begin - this.EDocumentHelper.GetEdocumentService(EDocument, EDocumentService); - EDocumentServiceStatus.SetLoadFields(Status); - EDocumentServiceStatus.Get(EDocument."Entry No", EdocumentService.Code); - if EDocumentServiceStatus.Status = EDocumentServiceStatus.Status::Approved then - JobHelperImpl.ScheduleEDocumentJob(Codeunit::PatchSentJob, BlankRecordId, 180000) - else - JobHelperImpl.ScheduleEDocumentJob(Codeunit::GetReadyStatusJob, BlankRecordId, 120000); - exit; - end; - - if Status = this.FailedTxt then begin - JsonManagement.GetArrayPropertyValueAsStringByName(this.DescriptionTxt, ErrorDescription); - exit; - end; - - JsonManagement.GetArrayPropertyValueAsStringByName(this.DescriptionTxt, ErrorDescription); - exit(true); - end; - - local procedure GetStatus(var JsonManagement: Codeunit "Json Management") Status: Text - begin - JsonManagement.GetArrayPropertyValueAsStringByName(this.StatusTxt, Status); - Status := Status.ToLower(); - end; - - local procedure UpdateEDocumentStatus(var EDocument: Record "E-Document") - var - IsHandled: Boolean; - begin - if IsHandled then - exit; - - if this.EDocumentHasErrors(EDocument) then - exit; - - this.SetDocumentStatus(EDocument); - end; - - local procedure EDocumentHasErrors(var EDocument: Record "E-Document"): Boolean - var - EDocumentServiceStatus: Record "E-Document Service Status"; - begin - EDocumentServiceStatus.SetRange("E-Document Entry No", EDocument."Entry No"); - EDocumentServiceStatus.SetFilter(Status, '%1|%2|%3|%4|%5', - EDocumentServiceStatus.Status::"Sending Error", - EDocumentServiceStatus.Status::"Export Error", - EDocumentServiceStatus.Status::"Cancel Error", - EDocumentServiceStatus.Status::"Imported Document Processing Error", - EDocumentServiceStatus.Status::Rejected); - - if EDocumentServiceStatus.IsEmpty() then - exit; - - EDocument.Validate(Status, EDocument.Status::Error); - EDocument.Modify(); - exit(true); - end; - - local procedure InsertIntegrationBlob(var EDocIntegrationLogRecordRef: RecordRef; Data: Text; FieldNo: Integer) - var - TempBlob: Codeunit "Temp Blob"; - begin - TempBlob.CreateOutStream().WriteText(Data); - TempBlob.ToRecordRef(EDocIntegrationLogRecordRef, FieldNo); - end; - - local procedure SetDocumentStatus(var EDocument: Record "E-Document") - var - EDocumentServiceStatus: Record "E-Document Service Status"; - EDocServiceCount: Integer; - begin - EDocumentServiceStatus.SetRange("E-Document Entry No", EDocument."Entry No"); - EDocServiceCount := EDocumentServiceStatus.Count; - - EDocumentServiceStatus.SetFilter(Status, '%1|%2|%3|%4|%5', - EDocumentServiceStatus.Status::Exported, - EDocumentServiceStatus.Status::"Imported Document Created", - EDocumentServiceStatus.Status::"Journal Line Created", - EDocumentServiceStatus.Status::Approved, - EDocumentServiceStatus.Status::Canceled); - if EDocumentServiceStatus.Count() = EDocServiceCount then - EDocument.Status := EDocument.Status::Processed - else - EDocument.Status := EDocument.Status::"In Progress"; - - EDocument.Modify(); - end; - - local procedure LeaveJustNewLine(InputText: Text): Text - var - InputJson, OutputDocumentJsonObject, OutputJsonObject : JsonObject; - InputJsonArray, OutputDocumentJsonArray : JsonArray; - InputJsonToken, DocumentJsonToken : JsonToken; - OutputText: text; - DocumentList: List of [Text]; - i: Integer; - begin - OutputText := InputText; - InputJson.ReadFrom(InputText); - if InputJson.Contains(this.InboxTxt) then begin - InputJson.Get(this.InboxTxt, InputJsonToken); - InputJsonArray := InputJsonToken.AsArray(); - foreach InputJsonToken in InputJsonArray do - if InputJsonToken.AsObject().Get(this.StatusTxt, DocumentJsonToken) then - if DocumentJsonToken.AsValue().AsText().ToLower() = this.NewTxt then begin - InputJsonToken.AsObject().Get(this.InstanceIdTxt, DocumentJsonToken); - DocumentList.Add(DocumentJsonToken.AsValue().AsText()); - end; - - for i := 1 to DocumentList.Count do begin - Clear(OutputDocumentJsonObject); - OutputDocumentJsonObject.Add(this.InstanceIdTxt, DocumentList.Get(i)); - OutputDocumentJsonArray.Add(OutputDocumentJsonObject); - end; - - OutputJsonObject.Add(this.InboxTxt, OutputDocumentJsonArray); - OutputJsonObject.WriteTo(OutputText) - end; - - exit(OutputText); - end; - - local procedure ParseContentData(var InputText: Text): Boolean - var - JsonManagement: Codeunit "JSON Management"; - Base64Convert: Codeunit "Base64 Convert"; - Value: Text; - ParsePosition: Integer; - begin - if not JsonManagement.InitializeFromString(InputText) then - exit; - - JsonManagement.GetArrayPropertyValueAsStringByName(this.DocumentTxt, Value); - InputText := Base64Convert.FromBase64(Value); - ParsePosition := StrPos(InputText, this.StandardBusinessDocumentHeaderTxt); - if ParsePosition > 0 then begin - InputText := CopyStr(InputText, parsePosition, StrLen(InputText)); - ParsePosition := StrPos(InputText, this.InvoiceTxt); - InputText := CopyStr(InputText, parsePosition, StrLen(InputText)); - ParsePosition := StrPos(InputText, this.StandardBusinessDocumentTxt); - InputText := CopyStr(InputText, 1, parsePosition - 1); - end; - - exit(true); - end; - - #endregion - - #region event subscribers - - [EventSubscriber(ObjectType::Codeunit, Codeunit::"E-Doc. Integration Management", OnGetEDocumentApprovalReturnsFalse, '', false, false)] - local procedure OnGetEDocumentApprovalReturnsFalse(EDocuments: Record "E-Document"; EDocumentService: Record "E-Document Service"; HttpRequest: HttpRequestMessage; HttpResponse: HttpResponseMessage; var IsHandled: Boolean) - var - HttpContent: HttpContent; - Status, StatusDescription : Text; - begin - HttpContent := HttpResponse.Content; - if not this.ParseGetADocumentApprovalResponse(HttpContent, Status, StatusDescription) then - IsHandled := true; - end; - - [EventSubscriber(ObjectType::Codeunit, Codeunit::"E-Doc. Import", OnAfterInsertImportedEdocument, '', false, false)] - local procedure OnAfterInsertEdocument(var EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; var TempBlob: Codeunit "Temp Blob"; EDocCount: Integer; HttpRequest: HttpRequestMessage; HttpResponse: HttpResponseMessage) - var - HttpRequestMessage: HttpRequestMessage; - HttpResponseMessage: HttpResponseMessage; - ContentData, DocumentId : Text; - begin - if EDocumentService."Service Integration" <> EDocumentService."Service Integration"::"ExFlow E-Invoicing" then - exit; - - if not HttpResponse.Content.ReadAs(ContentData) then - exit; - - ContentData := this.LeaveJustNewLine(ContentData); - - if not this.ParseReceivedDocument(ContentData, EDocument."Index In Batch", DocumentId) then begin - this.EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, this.DocumentIdNotFoundErr); - exit; - end; - - this.Connection.GetTargetDocumentRequest(DocumentId, HttpRequestMessage, HttpResponseMessage); - this.EDocumentLogHelper.InsertIntegrationLog(EDocument, EDocumentService, HttpRequestMessage, HttpResponseMessage); - - if not HttpResponseMessage.Content.ReadAs(ContentData) then - exit; - - if not this.ParseContentData(ContentData) then - ContentData := ''; - - if ContentData = '' then - this.EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, StrSubstNo(this.CouldNotRetrieveDocumentErr, DocumentId)); - - Clear(TempBlob); - TempBlob.CreateOutStream(TextEncoding::UTF8).WriteText(ContentData); - EDocument."Document Id" := CopyStr(DocumentId, 1, MaxStrLen(EDocument."Document Id")); - this.EDocumentLogHelper.InsertLog(EDocument, EDocumentService, TempBlob, "E-Document Service Status"::Imported); - this.Connection.RemoveDocumentFromReceived(EDocument, HttpRequestMessage, HttpResponseMessage); - this.EDocumentLogHelper.InsertIntegrationLog(EDocument, EDocumentService, HttpRequestMessage, HttpResponseMessage); - end; - - #endregion - -} \ No newline at end of file From 998acccb9e0c43aa2e12d4decf8a3dcd1c8cec45 Mon Sep 17 00:00:00 2001 From: geschwint Date: Tue, 4 Feb 2025 18:50:19 +0100 Subject: [PATCH 37/63] Total overhaul --- .../SignUp/app/src/APIRequests.Codeunit.al | 342 +++++++++++- .../SignUp/app/src/Authentication.Codeunit.al | 401 +++++++++++++- .../SignUp/app/src/Connection.Codeunit.al | 189 ++++++- .../SignUp/app/src/Helpers.Codeunit.al | 106 ++++ .../CompanyInformationExt.PageExt.al | 38 ++ .../CompanyInformationExt.TableExt.al | 19 + .../EDocServSuppTypeExtPageExt.PageExt.al | 64 +++ .../EDocServiceSupportedTypeExt.TableExt.al | 35 ++ .../src/Integration/EDocumentExt.TableExt.al | 19 + .../Integration/IntegrationEnumExt.EnumExt.al | 8 +- .../Integration/IntegrationImpl.Codeunit.al | 59 ++- .../SignUp/app/src/MetadataProfile.Table.al | 62 +++ .../SignUp/app/src/MetadataProfiles.Page.al | 47 ++ .../SignUpEDCOEdit.PermissionSet.al | 16 + .../SignUpEDCOObjects.PermissionSet.al | 26 + .../SignUpEDCORead.PermissionSet.al | 20 + .../SignUp/app/src/Processing.Codeunit.al | 492 +++++++++++++++--- .../app/src/Setup/ConnectionSetup.Table.al | 37 +- .../app/src/Setup/ConnectionSetupCard.Page.al | 49 +- 19 files changed, 1847 insertions(+), 182 deletions(-) create mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/Helpers.Codeunit.al create mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/CompanyInformationExt.PageExt.al create mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/CompanyInformationExt.TableExt.al create mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/EDocServSuppTypeExtPageExt.PageExt.al create mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/EDocServiceSupportedTypeExt.TableExt.al create mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/EDocumentExt.TableExt.al create mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/MetadataProfile.Table.al create mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/MetadataProfiles.Page.al create mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al create mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOObjects.PermissionSet.al create mode 100644 Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al index 74059d2555..35d65ae20d 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al @@ -5,21 +5,62 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.EServices.EDocument; +using Microsoft.EServices.EDocument.Service.Participant; +using Microsoft.Foundation.Company; +using System.Security.Authentication; +using System.Text; using System.Utilities; +using System.Xml; +using System.Environment; - -codeunit 6380 APIRequests +codeunit 6389 APIRequests { Access = Internal; + InherentEntitlements = X; + InherentPermissions = X; + + #region variables var - APIRequestsImpl: Codeunit APIRequestsImpl; + CompanyId: Text[100]; + MissingSetupErr: Label 'Connection Setup is missing'; + MissingSetupMessageErr: Label 'You must set up service integration in the e-document service card.'; + MissingSetupNavigationActionErr: Label 'Show E-Document Services'; + MissingSetupCompanyIdErr: Label '%1 in %2 is missing', Comment = '%1 = Field Name, %2 = Table Name'; + MissingSetupCompanyIdMessageErr: Label 'You must set up %1 in %2.', Comment = '%1 = Field Name, %2 = Table Name'; + MissingSetupCompanyIdActionErr: Label 'Show %1', Comment = '%1 = Table Name'; + UnSupportedDocumentTypeTxt: Label 'Document %1 is not supported.', Comment = '%1 = EDocument Type', Locked = true; + UnSupportedDocumentTypeProfileMissingTxt: Label 'Document %1 is not supported since %2 is missing in %3 %4', Comment = '%1 = EDocument Type; %2 = Profile Id; %3 = E-Document Service; %4 = Supported Document Types', Locked = true; + SupportedDocumentTypesTxt: Label 'Supported Document Types'; + SenderReceiverPrefixTxt: Label 'iso6523-actorid-upis::', Locked = true; + ContentTypeTxt: Label 'Content-Type', Locked = true; + ApplicationJsonTxt: Label 'application/json', Locked = true; + AuthorizationTxt: Label 'Authorization', Locked = true; + AcceptTxt: Label 'Accept', Locked = true; + AllTxt: Label '*/*', Locked = true; + ApplicationResponseTxt: Label 'ApplicationResponse', Locked = true; + InvoiceTxt: Label 'Invoice', Locked = true; + CrMemoTxt: Label 'CreditNote', Locked = true; + PaymentReminderTxt: Label 'PaymentReminder', Locked = true; + DocumentTypeTxt: Label 'documentType', Locked = true; + ReceiverTxt: Label 'receiver', Locked = true; + SenderTxt: Label 'sender', Locked = true; + SenderCountryCodeTxt: Label 'senderCountryCode', Locked = true; + DocumentIdTxt: Label 'documentId', Locked = true; + DocumentIdSchemeTxt: Label 'documentIdScheme', Locked = true; + ProcessIdTxt: Label 'processId', Locked = true; + ProcessIdSchemeTxt: Label 'processIdScheme', Locked = true; + SendModeTxt: Label 'sendMode', Locked = true; + DocumentTxt: Label 'document', Locked = true; + + + #endregion #region public methods /// /// The method sends a file to the API. - /// https://[BASEURL]/api/Peppol + /// https://[BASEURL]/api/v2/Peppol/outbox/transactions /// /// TempBlob /// EDocument table @@ -27,83 +68,350 @@ codeunit 6380 APIRequests /// Http Response Message /// True if successfully completed procedure SendFilePostRequest(var TempBlob: Codeunit "Temp Blob"; EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + ConnectionSetup: Record ConnectionSetup; + HttpContent: HttpContent; + Payload: Text; begin - exit(this.APIRequestsImpl.SendFilePostRequest(TempBlob, EDocument, HttpRequestMessage, HttpResponseMessage)); + Payload := this.XmlToTxt(TempBlob); + if Payload = '' then + exit; + + this.InitRequest(HttpRequestMessage, HttpResponseMessage); + ConnectionSetup.SetLoadFields("Environment Type", "Service URL"); + this.GetSetup(ConnectionSetup); + + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::POST, ConnectionSetup."Service URL" + '/api/v2/Peppol/outbox/transactions'); + this.PrepareContent(HttpContent, Payload, EDocument, ConnectionSetup); + HttpRequestMessage.Content(HttpContent); + exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); end; /// /// The method checks the status of the sent document. - /// https://[BASE URL]/api/Peppol/status?peppolInstanceId= + /// https://[BASE URL]/api/v2/Peppol/outbox/transactions/{transactionId}/status /// /// EDocument table /// Http Request Message /// Http Response Message /// True if successfully completed procedure GetSentDocumentStatus(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + ConnectionSetup: Record ConnectionSetup; begin - exit(this.APIRequestsImpl.GetSentDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage)); + this.InitRequest(HttpRequestMessage, HttpResponseMessage); + ConnectionSetup.SetLoadFields("Service URL"); + this.GetSetup(ConnectionSetup); + + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::GET, ConnectionSetup."Service URL" + '/api/v2/Peppol/outbox/transactions/' + EDocument."SignUp Document Id" + '/status'); + exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); end; /// /// The method modifies the document. - /// https://[BASE URL]/api/Peppol/outbox?peppolInstanceId= + /// https://[BASE URL]/api/v2/Peppol/outbox/transactions/{transactionId}/acknowledge /// /// EDocument table /// Http Request Message /// Http Response Message /// True if successfully completed procedure PatchDocument(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + ConnectionSetup: Record ConnectionSetup; begin - exit(this.APIRequestsImpl.PatchDocument(EDocument, HttpRequestMessage, HttpResponseMessage)); + this.InitRequest(HttpRequestMessage, HttpResponseMessage); + ConnectionSetup.SetLoadFields("Service URL"); + this.GetSetup(ConnectionSetup); + + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::PATCH, ConnectionSetup."Service URL" + '/api/v2/Peppol/outbox/transactions/' + EDocument."SignUp Document Id" + '/acknowledge'); + exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); end; /// /// The method gets the received document request. - /// https://[BASE URL]/api/Peppol/Inbox?peppolId= + /// https://[BASE URL]/api/v2/Peppol/inbox/transactions /// /// Http Request Message /// Http Response Message /// True if successfully completed procedure GetReceivedDocumentsRequest(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + ConnectionSetup: Record ConnectionSetup; begin - exit(this.APIRequestsImpl.GetReceivedDocumentsRequest(HttpRequestMessage, HttpResponseMessage)); + this.InitRequest(HttpRequestMessage, HttpResponseMessage); + ConnectionSetup.SetLoadFields("Service URL"); + this.GetSetup(ConnectionSetup); + + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::GET, ConnectionSetup."Service URL" + '/api/v2/Peppol/inbox/transactions?partyId=' + this.SenderReceiverPrefixTxt + this.GetCompanyId()); + exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); end; /// /// The method gets the target document request. - /// https://[BASE URL]/api/Peppol/inbox-document?peppolId= + /// https://[BASE URL]/api/v2/Peppol/inbox/transactions/{transactionId} /// /// Document ID /// Http Request Message /// Http Response Message /// True if successfully completed procedure GetTargetDocumentRequest(DocumentId: Text; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + ConnectionSetup: Record ConnectionSetup; begin - exit(this.APIRequestsImpl.GetTargetDocumentRequest(DocumentId, HttpRequestMessage, HttpResponseMessage)); + this.InitRequest(HttpRequestMessage, HttpResponseMessage); + ConnectionSetup.SetLoadFields("Service URL"); + this.GetSetup(ConnectionSetup); + + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::GET, ConnectionSetup."Service URL" + '/api/v2/Peppol/inbox/transactions/' + DocumentId); + exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); end; /// /// The method modifies the received document. - /// // https://[BASE URL]/api/Peppol/inbox?peppolInstanceId= + /// https://[BASE URL]/api/v2/Peppol/inbox/transactions/{transactionId}/acknowledge /// /// EDocument table /// Http Request Message /// Http Response Message + /// Http Response Message /// True if successfully completed procedure PatchReceivedDocument(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + ConnectionSetup: Record ConnectionSetup; + begin + this.InitRequest(HttpRequestMessage, HttpResponseMessage); + ConnectionSetup.SetLoadFields("Service URL"); + this.GetSetup(ConnectionSetup); + + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::PATCH, ConnectionSetup."Service URL" + '/api/v2/Peppol/inbox/transactions/' + EDocument."SignUp Document Id" + '/acknowledge'); + exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); + end; + + /// + /// The method fetches metadata profiles. + /// https://[BASE URL]/api/v2/Peppol/metadataprofile + /// + /// The HTTP request message to be sent. + /// The HTTP response message received. + /// Returns true if the metadata profiles were successfully fetched, otherwise false. + procedure FetchMetaDataProfiles(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + ConnectionSetup: Record ConnectionSetup; begin - exit(this.APIRequestsImpl.PatchReceivedDocument(EDocument, HttpRequestMessage, HttpResponseMessage)); + this.InitRequest(HttpRequestMessage, HttpResponseMessage); + ConnectionSetup.SetLoadFields("Service URL"); + this.GetSetup(ConnectionSetup); + + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::GET, ConnectionSetup."Service URL" + '/api/v2/Peppol/metadataprofile'); + exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage, false)); end; + /// /// The method gets the marketplace credentials. /// /// Http Request Message /// Http Response Message - /// True if successfully completed + /// True if successfully completed procedure GetMarketPlaceCredentials(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + Authentication: Codeunit Authentication; + begin + this.InitRequest(HttpRequestMessage, HttpResponseMessage); + + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::POST, Authentication.GetRootUrl() + '/api/Registration/init?EntraTenantId=' + Authentication.GetBCInstanceIdentifier() + '&EnvironmentName=' + this.GetEnvironmentName()); + exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage, true)); + end; + + #endregion + + #region local methods + local procedure GetEnvironmentName(): Text + var + EnvironmentInformation: Codeunit "Environment Information"; + begin + if EnvironmentInformation.IsSaaSInfrastructure() then + exit(EnvironmentInformation.GetEnvironmentName()) + else + exit(EnvironmentInformation.GetEnvironmentName()); //Change if OnPrem should be supported + end; + + local procedure InitRequest(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) begin - exit(this.APIRequestsImpl.GetMarketPlaceCredentials(HttpRequestMessage, HttpResponseMessage)); + Clear(HttpRequestMessage); + Clear(HttpResponseMessage); + end; + + local procedure GetSetup(var ConnectionSetup: Record ConnectionSetup) + var + MissingSetupErrorInfo: ErrorInfo; + begin + if not IsNullGuid(ConnectionSetup.SystemId) then + exit; + + if not ConnectionSetup.Get() then begin + MissingSetupErrorInfo.Title := this.MissingSetupErr; + MissingSetupErrorInfo.Message := this.MissingSetupMessageErr; + MissingSetupErrorInfo.PageNo := Page::"E-Document Services"; + MissingSetupErrorInfo.AddNavigationAction(this.MissingSetupNavigationActionErr); + Error(MissingSetupErrorInfo); + end; + end; + + local procedure GetCompanyId(): Text[100] + var + CompanyInformation: Record "Company Information"; + MissingSetupErrorInfo: ErrorInfo; + begin + if this.CompanyId <> '' then + exit(this.CompanyId); + + CompanyInformation.SetLoadFields("SignUp Service Participant Id"); + if not CompanyInformation.Get() or (CompanyInformation."SignUp Service Participant Id" = '') then begin + MissingSetupErrorInfo.Title := StrSubstNo(this.MissingSetupCompanyIdErr, CompanyInformation.FieldName("SignUp Service Participant Id"), CompanyInformation.TableName); + MissingSetupErrorInfo.Message := StrSubstNo(this.MissingSetupCompanyIdMessageErr, CompanyInformation.FieldName("SignUp Service Participant Id"), CompanyInformation.TableName); + MissingSetupErrorInfo.PageNo := Page::"Company Information"; + MissingSetupErrorInfo.AddNavigationAction(StrSubstNo(this.MissingSetupCompanyIdActionErr, CompanyInformation.TableName)); + Error(MissingSetupErrorInfo); + end; + this.CompanyId := CompanyInformation."SignUp Service Participant Id"; + exit(this.CompanyId); + end; + + local procedure PrepareContent(var HttpContent: HttpContent; Payload: Text; EDocument: Record "E-Document"; ConnectionSetup: Record ConnectionSetup) + var + ContentText: Text; + HttpHeaders: HttpHeaders; + begin + Clear(HttpContent); + ContentText := this.PrepareContentForSend(EDocument, this.GetCompanyId(), this.GetSenderCountryCode(), Payload, ConnectionSetup."Environment Type"); + HttpContent.WriteFrom(ContentText); + HttpContent.GetHeaders(HttpHeaders); + if HttpHeaders.Contains(this.ContentTypeTxt) then + HttpHeaders.Remove(this.ContentTypeTxt); + HttpHeaders.Add(this.ContentTypeTxt, this.ApplicationJsonTxt); + end; + + local procedure SendRequest(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + begin + exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage, false)); + end; + + local procedure SendRequest(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage; RootRequest: Boolean): Boolean + var + Authentication: Codeunit Authentication; + HttpClient: HttpClient; + HttpHeaders: HttpHeaders; + begin + HttpRequestMessage.GetHeaders(HttpHeaders); + if RootRequest then + HttpHeaders.Add(this.AuthorizationTxt, Authentication.GetRootBearerAuthToken()) + else + HttpHeaders.Add(this.AuthorizationTxt, Authentication.GetBearerAuthToken()); + exit(HttpClient.Send(HttpRequestMessage, HttpResponseMessage)); + end; + + local procedure PrepareRequestMsg(HttpRequestType: Enum "Http Request Type"; Uri: Text) RequestMessage: HttpRequestMessage + var + HttpHeaders: HttpHeaders; + begin + RequestMessage.Method(Format(HttpRequestType)); + RequestMessage.SetRequestUri(Uri); + RequestMessage.GetHeaders(HttpHeaders); + HttpHeaders.Add(this.AcceptTxt, this.AllTxt); + end; + + local procedure XmlToTxt(var TempBlob: Codeunit "Temp Blob"): Text + var + XMLDOMManagement: Codeunit "XML DOM Management"; + Content: Text; + begin + XMLDOMManagement.TryGetXMLAsText(TempBlob.CreateInStream(TextEncoding::UTF8), Content); + exit(Content); + end; + + local procedure GetDocumentType(EDocument: Record "E-Document"): Text + begin + if EDocument.Direction = EDocument.Direction::Incoming then + exit(this.ApplicationResponseTxt); + + case EDocument."Document Type" of + "E-Document Type"::"Sales Invoice": + exit(this.InvoiceTxt); + "E-Document Type"::"Sales Credit Memo": + exit(this.CrMemoTxt); + "E-Document Type"::"Issued Finance Charge Memo", + "E-Document Type"::"Issued Reminder": + exit(this.PaymentReminderTxt); + else + Error(this.UnSupportedDocumentTypeTxt, EDocument."Document Type"); + end; + end; + + local procedure GetCustomerID(EDocument: Record "E-Document") Return: Text[50] + var + ServiceParticipant: Record "Service Participant"; + EDocumentServiceStatus: Record "E-Document Service Status"; + begin + EDocumentServiceStatus.SetLoadFields("E-Document Service Code"); + EDocumentServiceStatus.SetRange("E-Document Entry No", EDocument."Entry No"); + EDocumentServiceStatus.FindFirst(); + ServiceParticipant.SetLoadFields("Participant Identifier"); + ServiceParticipant.Get(EDocumentServiceStatus."E-Document Service Code", ServiceParticipant."Participant Type"::Customer, EDocument."Bill-to/Pay-to No."); + Return := CopyStr(ServiceParticipant."Participant Identifier", 1, MaxStrLen(Return)); + end; + + local procedure GetSenderCountryCode(): Text + var + CompanyInformation: Record "Company Information"; + begin + CompanyInformation.SetLoadFields("Country/Region Code"); + CompanyInformation.Get(); + CompanyInformation.TestField("Country/Region Code"); + exit(CompanyInformation."Country/Region Code"); + end; + + local procedure PrepareContentForSend(EDocument: Record "E-Document"; SendingCompanyID: Text; SenderCountryCode: Text; Payload: Text; SendMode: Enum EnvironmentType): Text + var + EDocumentService: Record "E-Document Service"; + EDocumentServiceStatus: Record "E-Document Service Status"; + EDocServiceSupportedType: Record "E-Doc. Service Supported Type"; + MetadataProfile: Record MetadataProfile; + EDocumentHelper: Codeunit "E-Document Helper"; + Base64Convert: Codeunit "Base64 Convert"; + JsonObject: JsonObject; + ContentText: Text; + begin + EDocumentHelper.GetEdocumentService(EDocument, EDocumentService); + + if EDocumentService.Code = '' then begin + EDocumentServiceStatus.SetRange("E-Document Entry No", Edocument."Entry No"); + if EDocumentServiceStatus.FindLast() then + EDocumentService.Get(EDocumentServiceStatus."E-Document Service Code"); + end; + + EDocServiceSupportedType.SetRange("E-Document Service Code", EDocumentService.Code); + EDocServiceSupportedType.SetRange("Source Document Type", EDocument."Document Type"); + if not EDocServiceSupportedType.FindFirst() then + Error(this.UnSupportedDocumentTypeProfileMissingTxt, EDocument."Document Type", EDocServiceSupportedType.FieldCaption("Profile Id"), EDocumentService.TableCaption, this.SupportedDocumentTypesTxt); + if (EDocServiceSupportedType."Profile Id" = 0) or (not MetadataProfile.Get(EDocServiceSupportedType."Profile Id")) then + Error(this.UnSupportedDocumentTypeProfileMissingTxt, EDocument."Document Type", EDocServiceSupportedType.FieldCaption("Profile Id"), EDocumentService.TableCaption, this.SupportedDocumentTypesTxt); + + JsonObject.Add(this.DocumentTypeTxt, this.GetDocumentType(EDocument)); + JsonObject.Add(this.ReceiverTxt, this.SenderReceiverPrefixTxt + this.GetCustomerID(EDocument)); + JsonObject.Add(this.SenderTxt, this.SenderReceiverPrefixTxt + SendingCompanyID); + JsonObject.Add(this.SenderCountryCodeTxt, SenderCountryCode); + if EDocument.Direction = EDocument.Direction::Incoming then + JsonObject.Add(this.DocumentIdTxt, this.ApplicationResponseTxt) + else + JsonObject.Add(this.DocumentIdTxt, MetadataProfile."Document Identifier Value"); + JsonObject.Add(this.DocumentIdSchemeTxt, MetadataProfile."Document Identifier Scheme"); + JsonObject.Add(this.ProcessIdTxt, MetadataProfile."Process Identifier Value"); + JsonObject.Add(this.ProcessIdSchemeTxt, MetadataProfile."Process Identifier Scheme"); + JsonObject.Add(this.SendModeTxt, Format(SendMode)); + JsonObject.Add(this.DocumentTxt, Base64Convert.ToBase64(Payload)); + JsonObject.WriteTo(ContentText); + exit(ContentText); end; #endregion diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Authentication.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Authentication.Codeunit.al index 4cab43fe24..f95638b689 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Authentication.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Authentication.Codeunit.al @@ -4,19 +4,60 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -codeunit 6381 Authentication +using System.Azure.Identity; +using System.Reflection; +using System.Security.Authentication; +using System.Azure.KeyVault; +using System.Environment; + +codeunit 6390 Authentication { Access = Internal; + InherentEntitlements = X; + InherentPermissions = X; + #region variables var - AuthenticationImpl: Codeunit AuthenticationImpl; + ConnectionSetup: Record ConnectionSetup; + HelpersImpl: Codeunit Helpers; + BearerTxt: Label 'Bearer %1', Comment = '%1 = text value', Locked = true; + AuthURLTxt: Label 'https://login.microsoftonline.com/%1/oauth2/token', Comment = '%1 Entra Tenant Id', Locked = true; + AuthTemplateTxt: Label 'grant_type=client_credentials&client_id=%1&client_secret=%2&resource=%3', Locked = true; + ProdRootTenantIdTxt: Label '0d725623-dc26-484f-a090-b09d2003d092', Locked = true; + ProdClientTenantIdTxt: Label 'eef4ab2c-2b10-4380-bf4b-214157971162', Locked = true; + ProdServiceAPITxt: Label 'https://edoc.exflow.io', Locked = true; + ErrorTokenLbl: Label 'Unable to fetch a root token.'; + ErrorUnableToCreateClientCredentialsLbl: Label 'Unable to create client credentials.'; + ClientIdTxt: Label 'clientId', Locked = true; + ClientSecretTxt: Label 'clientSecret', Locked = true; + SignupRootUrlTxt: Label 'signup-root-url', Locked = true; + SignUpRootIdTxt: Label 'signup-root-id', Locked = true; + SignUpRootSecretTxt: Label 'signup-root-secret', Locked = true; + SignUpRootTenantTxt: Label 'signup-root-tenant', Locked = true; + SignUpClientTenantTxt: Label 'signup-client-tenant', Locked = true; + SignUpServiceAPITxt: Label 'signup-service-api', Locked = true; + SignUpAccessTokenKeyTxt: Label '{E45BB975-E67B-4A87-AC24-D409A5EF8301}', Locked = true; + ContentTypeTxt: Label 'Content-Type', Locked = true; + FormUrlEncodedTxt: Label 'application/x-www-form-urlencoded', Locked = true; + AccessTokenTxt: Label 'access_token', Locked = true; + + #endregion + + #region public methods /// /// The method initializes the connection setup. /// procedure InitConnectionSetup() begin - this.AuthenticationImpl.InitConnectionSetup(); + if this.ConnectionSetup.Get() then + exit; + + this.ConnectionSetup."Authentication URL" := this.AuthURLTxt; + this.ConnectionSetup."Service URL" := this.GetServiceApi(); + this.StorageSet(this.ConnectionSetup."Root Tenant", this.GetRootTenant()); + this.StorageSet(this.ConnectionSetup."Client Tenant", this.GetClientTenant()); + this.ConnectionSetup.Insert(); end; /// @@ -25,7 +66,7 @@ codeunit 6381 Authentication /// Onboarding URL procedure GetRootOnboardingUrl(): Text begin - exit(this.AuthenticationImpl.GetRootOnboardingUrl()); + exit(this.GetRootUrl() + '/supm/landingpage?EntraTenantId=' + this.GetBCInstanceIdentifier()); end; /// @@ -33,8 +74,23 @@ codeunit 6381 Authentication /// [NonDebuggable] procedure CreateClientCredentials() + var + HttpRequestMessage: HttpRequestMessage; + HttpResponseMessage: HttpResponseMessage; + ClientId, Response : Text; + ClientSecret: SecretText; begin - this.AuthenticationImpl.CreateClientCredentials(); + if not this.GetClientCredentials(HttpRequestMessage, HttpResponseMessage) then + this.ShowErrorMessage(HttpResponseMessage); + + if not HttpResponseMessage.Content.ReadAs(Response) then + exit; + + ClientId := this.HelpersImpl.GetJsonValueFromText(Response, this.ClientIdTxt); + ClientSecret := this.HelpersImpl.GetJsonValueFromText(Response, this.ClientSecretTxt); + + if (ClientId <> '') and (not ClientSecret.IsEmpty()) then + this.SaveClientCredentials(ClientId, ClientSecret); end; /// @@ -43,16 +99,16 @@ codeunit 6381 Authentication /// Bearer authentication token procedure GetBearerAuthToken(): SecretText; begin - exit(this.AuthenticationImpl.GetBearerAuthToken()); + exit(SecretStrSubstNo(this.BearerTxt, this.GetAuthToken())); end; /// /// The method returns the root bearer authentication token. /// - /// Root bearer authentication token + /// Root bearer authentication token procedure GetRootBearerAuthToken(): SecretText; begin - exit(this.AuthenticationImpl.GetRootBearerAuthToken()); + exit(SecretStrSubstNo(this.BearerTxt, this.GetRootAuthToken())); end; /// @@ -61,9 +117,18 @@ codeunit 6381 Authentication /// Token Key /// Token [NonDebuggable] - procedure StorageSet(var TokenKey: Guid; Value: Text) + procedure StorageSet(var TokenKey: Guid; Value: Text): Boolean + var + ModuleDataScope: DataScope; begin - this.AuthenticationImpl.StorageSet(TokenKey, Value); + ModuleDataScope := ModuleDataScope::Module; + this.ValidateValueKey(TokenKey); + + if Value = '' then begin + if IsolatedStorage.Contains(TokenKey, ModuleDataScope) then + exit(IsolatedStorage.Delete(TokenKey, ModuleDataScope)) + end else + exit(IsolatedStorage.Set(TokenKey, Value, ModuleDataScope)); end; /// @@ -72,9 +137,9 @@ codeunit 6381 Authentication /// Token Key /// Token [NonDebuggable] - procedure StorageSet(var TokenKey: Guid; Value: SecretText) + procedure StorageSet(var TokenKey: Guid; Value: SecretText): Boolean begin - this.AuthenticationImpl.StorageSet(TokenKey, Value); + exit(this.StorageSet(TokenKey, Value, DataScope::Module)); end; /// @@ -82,8 +147,13 @@ codeunit 6381 Authentication /// /// Identifier procedure GetBCInstanceIdentifier() Identifier: Text + var + AADTenantID, AADDomainName : Text; begin - exit(this.AuthenticationImpl.GetBCInstanceIdentifier()); + Identifier := '10000000-d8ef-4dfb-b761-ffb073057794'; // Hardcoded fake during testing only + + if this.GetAADTenantInformation(AADTenantID, AADDomainName) then + Identifier := AADTenantID; end; /// @@ -93,6 +163,309 @@ codeunit 6381 Authentication [NonDebuggable] procedure GetRootUrl() ReturnValue: Text begin - exit(this.AuthenticationImpl.GetRootUrl()); + if this.FetchSecretFromKeyVault(this.SignupRootUrlTxt, ReturnValue) then + exit; + + if not this.ConnectionSetup.GetSetup() then + exit; + + this.ConnectionSetup.TestField("Root Market URL"); + ReturnValue := this.ConnectionSetup."Root Market URL"; + end; + + #endregion + + #region local methods + + local procedure GetAuthToken() AccessToken: SecretText; + var + HttpError: Text; + begin + AccessToken := this.StorageGet(this.SignUpAccessTokenKeyTxt, DataScope::Company); + + if this.HelpersImpl.IsTokenValid(AccessToken) then + exit; + + if not this.RefreshAccessToken(HttpError) then + Error(HttpError); + + exit(this.StorageGet(this.SignUpAccessTokenKeyTxt, DataScope::Company)); + end; + + local procedure GetRootAuthToken() ReturnValue: SecretText; + begin + if not this.GetRootAccessToken(ReturnValue) then + Error(this.ErrorTokenLbl); + end; + + local procedure SaveClientCredentials(ClientId: Text; ClientSecret: SecretText) + begin + Clear(this.ConnectionSetup); + + this.ConnectionSetup.GetSetup(); + this.StorageSet(this.ConnectionSetup."Client ID", ClientId); + this.StorageSet(this.ConnectionSetup."Client Secret", ClientSecret); + this.ConnectionSetup.Modify(); + + Clear(this.ConnectionSetup); + end; + + [NonDebuggable] + local procedure GetClientCredentials(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + var + APIRequests: Codeunit APIRequests; + begin + APIRequests.GetMarketPlaceCredentials(HttpRequestMessage, HttpResponseMessage); + + if not HttpResponseMessage.IsSuccessStatusCode() then + exit; + + exit(this.HelpersImpl.ParseJsonString(HttpResponseMessage.Content) <> ''); + end; + + [NonDebuggable] + local procedure RefreshAccessToken(var HttpError: Text): Boolean; + var + SecretToken: SecretText; + begin + if not this.GetClientAccessToken(SecretToken) then begin + HttpError := GetLastErrorText(); + exit; + end; + + exit(this.SaveSignUpAccessToken(DataScope::Company, SecretToken)); + end; + + [NonDebuggable] + local procedure GetRootAccessToken(var AccessToken: SecretText): Boolean + var + ModuleDataScope: DataScope; + begin + ModuleDataScope := ModuleDataScope::Module; + this.ConnectionSetup.GetSetup(); + + exit(this.GetAccessToken(AccessToken, this.GetRootId(), + this.GetRootSecret(), + this.StorageGetText(this.ConnectionSetup."Root Tenant", ModuleDataScope))); + end; + + [NonDebuggable] + local procedure GetClientAccessToken(var AccessToken: SecretText): Boolean + var + ModuleDataScope: DataScope; + begin + ModuleDataScope := ModuleDataScope::Module; + this.ConnectionSetup.GetSetup(); + + exit(this.GetAccessToken(AccessToken, this.StorageGetText(this.ConnectionSetup."Client ID", ModuleDataScope), + this.StorageGet(this.ConnectionSetup."Client Secret", ModuleDataScope), + this.StorageGetText(this.ConnectionSetup."Client Tenant", ModuleDataScope))); + end; + + [NonDebuggable] + local procedure GetAccessToken(var AccessToken: SecretText; ClientId: Text; ClientSecret: SecretText; ClientTenant: Text): Boolean + var + TypeHelper: Codeunit "Type Helper"; + HttpRequestMessage: HttpRequestMessage; + Response: Text; + begin + Clear(AccessToken); + this.ConnectionSetup.GetSetup(); + this.ConnectionSetup.TestField("Authentication URL"); + + HttpRequestMessage := this.PrepareRequest(SecretStrSubstNo(this.AuthTemplateTxt, TypeHelper.UriEscapeDataString(ClientId), ClientSecret, TypeHelper.UriEscapeDataString(ClientId)), + StrSubstNo(this.ConnectionSetup."Authentication URL", ClientTenant)); + + if not this.SendRequest(HttpRequestMessage, Response) then + exit; + + AccessToken := this.HelpersImpl.GetJsonValueFromText(Response, this.AccessTokenTxt); + exit(not AccessToken.IsEmpty()); end; + + + local procedure PrepareRequest(Content: SecretText; Url: text) HttpRequestMessage: HttpRequestMessage + var + HttpContent: HttpContent; + HttpHeaders: HttpHeaders; + begin + HttpContent.WriteFrom(Content); + HttpContent.GetHeaders(HttpHeaders); + + HttpHeaders.Remove(this.ContentTypeTxt); + HttpHeaders.Add(this.ContentTypeTxt, this.FormUrlEncodedTxt); + + HttpRequestMessage.Method := Format(Enum::"Http Request Type"::POST); + HttpRequestMessage.SetRequestUri(Url); + HttpRequestMessage.Content(HttpContent); + end; + + [NonDebuggable] + local procedure SendRequest(HttpRequestMessage: HttpRequestMessage; var Response: Text): Boolean + var + HttpClient: HttpClient; + HttpResponseMessage: HttpResponseMessage; + begin + if not HttpClient.Send(HttpRequestMessage, HttpResponseMessage) then + exit; + if not HttpResponseMessage.IsSuccessStatusCode() then + exit; + + exit(HttpResponseMessage.Content.ReadAs(Response)); + end; + + local procedure StorageSet(var TokenKey: Guid; Value: SecretText; TokenDataScope: DataScope): Boolean + begin + this.ValidateValueKey(TokenKey); + + if Value.IsEmpty() then begin + if IsolatedStorage.Contains(TokenKey, TokenDataScope) then + exit(IsolatedStorage.Delete(TokenKey, TokenDataScope)) + end else + exit(IsolatedStorage.Set(TokenKey, Value, TokenDataScope)); + end; + + local procedure StorageGet(TokenKey: Text; TokenDataScope: DataScope) TokenValueAsSecret: SecretText + begin + if not this.StorageContains(TokenKey, TokenDataScope) then + exit(TokenValueAsSecret); + + IsolatedStorage.Get(TokenKey, TokenDataScope, TokenValueAsSecret); + end; + + [NonDebuggable] + local procedure StorageGetText(TokenKey: Text; TokenDataScope: DataScope) TokenValue: Text + begin + if not this.StorageContains(TokenKey, TokenDataScope) then + exit(TokenValue); + + IsolatedStorage.Get(TokenKey, TokenDataScope, TokenValue); + end; + + local procedure SaveSignUpAccessToken(TokenDataScope: DataScope; AccessToken: SecretText): Boolean + var + SignUpAccessTokenKey: Guid; + begin + SignUpAccessTokenKey := this.GetSignUpAccessTokenKey(); + exit(this.StorageSet(SignUpAccessTokenKey, AccessToken, TokenDataScope)); + end; + + local procedure StorageContains(TokenKey: Text; TokenDataScope: DataScope): Boolean + begin + exit(IsolatedStorage.Contains(TokenKey, TokenDataScope)); + end; + + local procedure ValidateValueKey(var ValueKey: Guid) + begin + if IsNullGuid(ValueKey) then + ValueKey := CreateGuid(); + end; + + local procedure GetSignUpAccessTokenKey() SignUpAccessTokenKey: Guid + begin + Evaluate(SignUpAccessTokenKey, this.SignUpAccessTokenKeyTxt); + end; + + local procedure ShowErrorMessage(HttpResponseMessage: HttpResponseMessage) + var + UnsuccessfulResponseErr: Label 'There was an error sending the request. Response code: %1 and error message: %2', Comment = '%1 - http response status code, e.g. 400, %2- error message'; + begin + if HttpResponseMessage.ReasonPhrase() <> '' then + Error(UnsuccessfulResponseErr, HttpResponseMessage.HttpStatusCode, HttpResponseMessage.ReasonPhrase()); + + Error(this.ErrorUnableToCreateClientCredentialsLbl); + end; + + [NonDebuggable] + local procedure GetRootId() ReturnValue: Text + begin + if this.FetchSecretFromKeyVault(this.SignUpRootIdTxt, ReturnValue) then + exit; + + if not this.ConnectionSetup.GetSetup() then + exit; + + this.ConnectionSetup.TestField("Root App ID"); + ReturnValue := this.StorageGetText(this.ConnectionSetup."Root App ID", DataScope::Module); + end; + + local procedure GetRootSecret() ReturnValue: SecretText + begin + if this.FetchSecretFromKeyVault(this.SignUpRootSecretTxt, ReturnValue) then + exit; + + if not this.ConnectionSetup.GetSetup() then + exit; + + this.ConnectionSetup.TestField("Root Secret"); + ReturnValue := this.StorageGet(this.ConnectionSetup."Root Secret", DataScope::Module); + end; + + [NonDebuggable] + local procedure GetRootTenant() ReturnValue: Text + begin + if this.FetchSecretFromKeyVault(this.SignUpRootTenantTxt, ReturnValue) then + exit; + ReturnValue := this.ProdRootTenantIdTxt; + end; + + local procedure GetClientTenant() ReturnValue: Text + begin + if this.FetchSecretFromKeyVault(this.SignUpClientTenantTxt, ReturnValue) then + exit; + ReturnValue := this.ProdClientTenantIdTxt; + end; + + local procedure GetServiceApi() ReturnValue: Text[2048] + var + KeyVaultReturn: Text; + begin + if this.FetchSecretFromKeyVault(this.SignUpServiceAPITxt, KeyVaultReturn) then begin + ReturnValue := CopyStr(KeyVaultReturn, 1, MaxStrLen(ReturnValue)); + exit; + end; + ReturnValue := this.ProdServiceAPITxt; + end; + + local procedure FetchSecretFromKeyVault(KeyName: Text; var KeyValue: SecretText): Boolean + var + AzureKeyVault: Codeunit "Azure Key Vault"; + EnvironmentInformation: Codeunit "Environment Information"; + begin + if EnvironmentInformation.IsSaaSInfrastructure() then + exit(AzureKeyVault.GetAzureKeyVaultSecret(KeyName, KeyValue)); + end; + + [NonDebuggable] + local procedure FetchSecretFromKeyVault(KeyName: Text; var KeyValue: Text): Boolean + var + AzureKeyVault: Codeunit "Azure Key Vault"; + EnvironmentInformation: Codeunit "Environment Information"; + begin + if EnvironmentInformation.IsSaaSInfrastructure() then + exit(AzureKeyVault.GetAzureKeyVaultSecret(KeyName, KeyValue)); + end; + + local procedure GetAADTenantInformation(var AADTenantID: Text; var AADDomainName: Text): Boolean + begin + exit(this.GetAADTenantID(AADTenantID) and this.GetAADDomainName(AADDomainName)); + end; + + [TryFunction] + local procedure GetAADTenantID(var AADTenantID: Text) + var + AzureADTenant: Codeunit "Azure AD Tenant"; + begin + AADTenantID := AzureADTenant.GetAadTenantId(); + end; + + [TryFunction] + local procedure GetAADDomainName(var AADDomainName: Text) + var + AzureADTenant: Codeunit "Azure AD Tenant"; + begin + AADDomainName := AzureADTenant.GetAadTenantDomainName() + end; + + #endregion } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Connection.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Connection.Codeunit.al index 69d6451946..1382272ac5 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Connection.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Connection.Codeunit.al @@ -7,12 +7,33 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.EServices.EDocument; using System.Utilities; -codeunit 6382 Connection +codeunit 6391 Connection { Access = Internal; + InherentEntitlements = X; + InherentPermissions = X; + Permissions = tabledata "E-Document" = m; + + #region variables var - ConnectionImpl: Codeunit ConnectionImpl; + APIRequests: Codeunit APIRequests; + HelpersImpl: Codeunit Helpers; + UnsuccessfulResponseErr: Label 'There was an error sending the request. Response code: %1 and error message: %2', Comment = '%1 - http response status code, e.g. 400, %2- error message'; + EnvironmentBlocksErr: Label 'The request to send documents has been blocked. To resolve the problem, enable outgoing HTTP requests for the E-Document apps on the Extension Management page.'; + FourZeroThreeErr: Label 'You do not have a valid subscription.'; + MetadataProfileLbl: Label 'metadataProfile', Locked = true; + ProfileIdLbl: Label 'profileId', Locked = true; + CommonNameLbl: Label 'commonName', Locked = true; + ProcessIdentifierLbl: Label 'processIdentifier', Locked = true; + SchemeLbl: Label 'scheme', Locked = true; + ValueLbl: Label 'value', Locked = true; + DocumentIdentifierLbl: Label 'documentIdentifier', Locked = true; + + + #endregion + + #region public methods /// /// The methods sends a file to the API. @@ -24,7 +45,8 @@ codeunit 6382 Connection /// True - if completed successfully procedure SendFilePostRequest(var TempBlob: Codeunit "Temp Blob"; var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean begin - exit(this.ConnectionImpl.SendFilePostRequest(TempBlob, EDocument, HttpRequestMessage, HttpResponseMessage)); + this.APIRequests.SendFilePostRequest(TempBlob, EDocument, HttpRequestMessage, HttpResponseMessage); + exit(this.CheckIfSuccessfulRequest(EDocument, HttpResponseMessage)); end; /// @@ -36,7 +58,8 @@ codeunit 6382 Connection /// True - if completed successfully procedure CheckDocumentStatus(var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean begin - exit(this.ConnectionImpl.CheckDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage)); + this.APIRequests.GetSentDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage); + exit(this.CheckIfSuccessfulRequest(EDocument, HttpResponseMessage)); end; /// @@ -47,7 +70,16 @@ codeunit 6382 Connection /// True - if completed successfully procedure GetReceivedDocuments(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean begin - exit(this.ConnectionImpl.GetReceivedDocuments(HttpRequestMessage, HttpResponseMessage)); + if not this.APIRequests.GetReceivedDocumentsRequest(HttpRequestMessage, HttpResponseMessage) then + exit; + + if not HttpResponseMessage.IsSuccessStatusCode() then + if HttpResponseMessage.HttpStatusCode = 403 then + Error(this.FourZeroThreeErr) + else + exit; + + exit(this.HelpersImpl.ParseJsonString(HttpResponseMessage.Content) <> ''); end; /// @@ -59,7 +91,8 @@ codeunit 6382 Connection /// True - if completed successfully procedure GetTargetDocumentRequest(DocumentId: Text; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean begin - exit(this.ConnectionImpl.GetTargetDocumentRequest(DocumentId, HttpRequestMessage, HttpResponseMessage)); + this.APIRequests.GetTargetDocumentRequest(DocumentId, HttpRequestMessage, HttpResponseMessage); + exit(HttpResponseMessage.IsSuccessStatusCode()); end; /// @@ -71,6 +104,148 @@ codeunit 6382 Connection /// True - if completed successfully procedure RemoveDocumentFromReceived(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean begin - exit(this.ConnectionImpl.RemoveDocumentFromReceived(EDocument, HttpRequestMessage, HttpResponseMessage)); + this.APIRequests.PatchReceivedDocument(EDocument, HttpRequestMessage, HttpResponseMessage); + exit(HttpResponseMessage.IsSuccessStatusCode()); + end; + + /// + /// Updates the Metadata Profile table. + /// If the data is Fectched, the current Metadata Profile table will be deleted and the new data will be inserted. + /// If any Metadata Profiles have been removed, references to them will be set to 0. + /// + /// + /// This procedure retrieves and updates the metadata profile information from an external service. + /// + procedure UpdateMetadataProfile() + var + MetadataProfile: Record MetadataProfile; + HttpRequestMessage: HttpRequestMessage; + HttpResponseMessage: HttpResponseMessage; + MetadataProfileContent: Text; + begin + this.APIRequests.FetchMetaDataProfiles(HttpRequestMessage, HttpResponseMessage); + if not HttpResponseMessage.IsSuccessStatusCode() then begin + if HttpResponseMessage.HttpStatusCode = 403 then + Message(this.FourZeroThreeErr) + else + Message(HttpResponseMessage.ReasonPhrase); + exit; + end; + + if not HttpResponseMessage.Content.ReadAs(MetadataProfileContent) then + exit; + + MetadataProfile.Reset(); + MetadataProfile.DeleteAll(); + + if this.MetadataProfileJsonToTable(MetadataProfileContent, MetadataProfile) then + this.DeleteUnusedMetadataProfileReferenses(MetadataProfile); + end; + #endregion + + #region local methods + local procedure CheckIfSuccessfulRequest(EDocument: Record "E-Document"; HttpResponseMessage: HttpResponseMessage): Boolean + var + EDocumentErrorHelper: Codeunit "E-Document Error Helper"; + begin + if HttpResponseMessage.IsSuccessStatusCode() then + exit(true); + + if HttpResponseMessage.IsBlockedByEnvironment() then + EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, this.EnvironmentBlocksErr) + else + if HttpResponseMessage.HttpStatusCode = 403 then + EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, this.FourZeroThreeErr) + else + EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, StrSubstNo(this.UnsuccessfulResponseErr, HttpResponseMessage.HttpStatusCode, HttpResponseMessage.ReasonPhrase)); + end; + + local procedure MetadataProfileJsonToTable(JsonText: Text; var MetadataProfile: Record MetadataProfile): Boolean + var + JsonObject, ProfileJsonObject, ProcessIdentifierJsonObject, DocumentIdentifierJsonObject : JsonObject; + JsonArray: JsonArray; + JsonToken: JsonToken; + begin + if JsonObject.ReadFrom(JsonText) then + if JsonObject.Get(this.MetadataProfileLbl, JsonToken) then + if JsonToken.IsArray() then begin + JsonArray := JsonToken.AsArray(); + foreach JsonToken in JsonArray do + if JsonToken.IsObject() then begin + ProfileJsonObject := JsonToken.AsObject(); + MetadataProfile.Init(); + + if ProfileJsonObject.SelectToken(this.ProfileIdLbl, JsonToken) then + MetadataProfile."Profile ID" := this.GetJsonValueAsInteger(JsonToken.AsValue()); + + if ProfileJsonObject.SelectToken(this.CommonNameLbl, JsonToken) then + MetadataProfile."Profile Name" := CopyStr(this.GetJsonValueAsText(JsonToken.AsValue()), 1, MaxStrLen(MetadataProfile."Profile Name")); + + if ProfileJsonObject.SelectToken(this.ProcessIdentifierLbl, JsonToken) then begin + ProcessIdentifierJsonObject := JsonToken.AsObject(); + + if ProcessIdentifierJsonObject.SelectToken(this.SchemeLbl, JsonToken) then + MetadataProfile."Process Identifier Scheme" := CopyStr(this.GetJsonValueAsText(JsonToken.AsValue()), 1, MaxStrLen(MetadataProfile."Process Identifier Scheme")); + + if ProcessIdentifierJsonObject.SelectToken(this.ValueLbl, JsonToken) then + MetadataProfile."Process Identifier Value" := CopyStr(this.GetJsonValueAsText(JsonToken.AsValue()), 1, MaxStrLen(MetadataProfile."Process Identifier Value")); + end; + + if ProfileJsonObject.SelectToken(this.DocumentIdentifierLbl, JsonToken) then begin + DocumentIdentifierJsonObject := JsonToken.AsObject(); + + if DocumentIdentifierJsonObject.SelectToken(this.SchemeLbl, JsonToken) then + MetadataProfile."Document Identifier Scheme" := CopyStr(this.GetJsonValueAsText(JsonToken.AsValue()), 1, MaxStrLen(MetadataProfile."Document Identifier Scheme")); + + if DocumentIdentifierJsonObject.SelectToken(this.ValueLbl, JsonToken) then + MetadataProfile."Document Identifier Value" := CopyStr(this.GetJsonValueAsText(JsonToken.AsValue()), 1, MaxStrLen(MetadataProfile."Document Identifier Value")); + end; + + MetadataProfile.Insert(); + end; + end; + exit(not MetadataProfile.IsEmpty()); + end; + + local procedure DeleteUnusedMetadataProfileReferenses(var MetadataProfile: Record MetadataProfile) + var + EDocumentService: Record "E-Document Service"; + EDocServiceSupportedType: Record "E-Doc. Service Supported Type"; + begin + EDocumentService.SetLoadFields("Service Integration V2"); + EDocumentService.Reset(); + EDocumentService.SetRange("Service Integration V2", EDocumentService."Service Integration V2"::"ExFlow E-Invoicing"); + if EDocumentService.FindSet() then + repeat + EDocServiceSupportedType.Reset(); + EDocServiceSupportedType.SetRange("E-Document Service Code", EDocumentService.Code); + if not EDocServiceSupportedType.FindSet() then + repeat + if EDocServiceSupportedType."Profile Id" <> 0 then + if not MetadataProfile.Get(EDocServiceSupportedType."Profile Id") then begin + EDocServiceSupportedType."Profile Id" := 0; + EDocServiceSupportedType.Modify(); + end; + until EDocServiceSupportedType.Next() = 0; + until EDocumentService.Next() = 0; + end; + + local procedure GetJsonValueAsInteger(JValue: JsonValue): Integer + begin + if JValue.IsNull then + exit(0); + if JValue.IsUndefined then + exit(0); + exit(JValue.AsInteger()); + end; + + local procedure GetJsonValueAsText(JValue: JsonValue): Text + begin + if JValue.IsNull then + exit(''); + if JValue.IsUndefined then + exit(''); + exit(JValue.AsText()); end; + #endregion } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Helpers.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Helpers.Codeunit.al new file mode 100644 index 0000000000..e6c72f6d98 --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Helpers.Codeunit.al @@ -0,0 +1,106 @@ +// ------------------------------------------------------------------------------------------------ +// 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 System.Reflection; +using Microsoft.Utilities; +using System.Integration; +using Microsoft.eServices.EDocument; + +codeunit 6385 Helpers +{ + Access = Internal; + + var + ClaimTypeTxt: Label 'exp', Locked = true; + + #region public methods + + [NonDebuggable] + procedure ParseJsonString(HttpContent: HttpContent): Text + var + JsonObject: JsonObject; + Content: Text; + begin + if not HttpContent.ReadAs(Content) then + exit; + + if JsonObject.ReadFrom(Content) then + exit(Content); + end; + + [NonDebuggable] + procedure GetJsonValueFromText(JsonText: Text; Path: Text): Text + var + JsonObject: JsonObject; + JsonToken: JsonToken; + begin + if JsonObject.ReadFrom(JsonText) then + if JsonObject.SelectToken(Path, JsonToken) then + exit(this.GetJsonValue(JsonToken.AsValue())); + end; + + procedure IsTokenValid(InToken: SecretText): Boolean + begin + exit(this.GetTokenDateTimeValue(InToken, this.ClaimTypeTxt) > CurrentDateTime()); + end; + + procedure IsExFlowEInvoicing(EDocumentServiceCodeFilter: Text): Boolean + var + EDocumentService: Record "E-Document Service"; + begin + if EDocumentServiceCodeFilter = '' then + exit; + + + EDocumentService.SetFilter(Code, EDocumentServiceCodeFilter); + EDocumentService.SetRange("Service Integration V2", EDocumentService."Service Integration V2"::"ExFlow E-Invoicing"); + exit(not EDocumentService.IsEmpty()); + end; + + #endregion + + #region local methods + + local procedure GetTokenDateTimeValue(InToken: SecretText; ClaimType: Text): DateTime + var + TypeHelper: Codeunit "Type Helper"; + Timestamp: Decimal; + begin + if Evaluate(Timestamp, this.GetValueFromToken(InToken, ClaimType)) then + exit(TypeHelper.EvaluateUnixTimestamp(Timestamp)); + end; + + [NonDebuggable] + local procedure GetValueFromToken(InToken: SecretText; ClaimType: Text): Text + var + TempNameValueBuffer: Record "Name/Value Buffer" temporary; + SOAPWebServiceRequestMgt: Codeunit "SOAP Web Service Request Mgt."; + begin + if InToken.IsEmpty() then + exit; + + TempNameValueBuffer.DeleteAll(); + SOAPWebServiceRequestMgt.GetTokenDetailsAsNameBuffer(InToken, TempNameValueBuffer); + TempNameValueBuffer.Reset(); + TempNameValueBuffer.SetRange(Name, ClaimType); + if TempNameValueBuffer.FindFirst() then + exit(TempNameValueBuffer.Value); + end; + + [NonDebuggable] + local procedure GetJsonValue(JsonValue: JsonValue): Text + begin + if JsonValue.IsNull() then + exit; + + if JsonValue.IsUndefined() then + exit; + + exit(JsonValue.AsText()); + end; + + #endregion +} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/CompanyInformationExt.PageExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/CompanyInformationExt.PageExt.al new file mode 100644 index 0000000000..7b814a3494 --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/CompanyInformationExt.PageExt.al @@ -0,0 +1,38 @@ +// ------------------------------------------------------------------------------------------------ +// 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.Foundation.Company; +using Microsoft.eServices.EDocument; + +pageextension 6381 CompanyInformationExt extends "Company Information" +{ + layout + { + addafter(General) + { + group(ExFlowEInvoicing) + { + Caption = 'ExFlow E-Invoicing'; + Visible = ExFlowEInvoicingVisible; + + field("SignUp Service Participant Id"; Rec."SignUp Service Participant Id") + { + ApplicationArea = Basic, Suite; + } + } + } + } + + var + ExFlowEInvoicingVisible: Boolean; + + trigger OnAfterGetRecord() + var + EDocumentService: Record "E-Document Service"; + begin + EDocumentService.SetRange("Service Integration V2", EDocumentService."Service Integration V2"::"ExFlow E-Invoicing"); + ExFlowEInvoicingVisible := not EDocumentService.IsEmpty(); + end; +} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/CompanyInformationExt.TableExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/CompanyInformationExt.TableExt.al new file mode 100644 index 0000000000..f02165966f --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/CompanyInformationExt.TableExt.al @@ -0,0 +1,19 @@ +// ------------------------------------------------------------------------------------------------ +// 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.Foundation.Company; + +tableextension 6381 CompanyInformationExt extends "Company Information" +{ + fields + { + field(6381; "SignUp Service Participant Id"; Text[100]) + { + Caption = 'Service Participant Id'; + ToolTip = 'ExFlow E-Invoicing Service Participant Id.'; + } + } + +} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/EDocServSuppTypeExtPageExt.PageExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/EDocServSuppTypeExtPageExt.PageExt.al new file mode 100644 index 0000000000..5bfc5020a3 --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/EDocServSuppTypeExtPageExt.PageExt.al @@ -0,0 +1,64 @@ +// ------------------------------------------------------------------------------------------------ +// 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; + +pageextension 6383 EDocServSuppTypeExtPageExt extends "E-Doc Service Supported Types" +{ + + layout + { + addlast(General) + { + field("Profile Id"; Rec."Profile Id") + { + ApplicationArea = All; + Visible = ExFlowEInvoicingVisible; + } + field("Profile Name"; Rec."Profile Name") + { + ApplicationArea = All; + Visible = ExFlowEInvoicingVisible; + } + } + + } + + actions + { + addlast(Processing) + { + action(PopulateMetaData) + { + ApplicationArea = All; + Caption = 'Retreieve Metadata Profiles'; + ToolTip = 'Retreieves Metadata Profiles from service'; + Promoted = true; + PromotedCategory = Process; + Visible = ExFlowEInvoicingVisible; + Image = Refresh; + + trigger OnAction() + var + Connection: Codeunit Connection; + begin + Connection.UpdateMetadataProfile(); + end; + } + } + } + + trigger OnOpenPage() + var + Helpers: Codeunit Helpers; + begin + ExFlowEInvoicingVisible := Helpers.IsExFlowEInvoicing(Rec.GetFilter("E-Document Service Code")); + end; + + var + ExFlowEInvoicingVisible: Boolean; + +} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/EDocServiceSupportedTypeExt.TableExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/EDocServiceSupportedTypeExt.TableExt.al new file mode 100644 index 0000000000..5ec8cf37f4 --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/EDocServiceSupportedTypeExt.TableExt.al @@ -0,0 +1,35 @@ +// ------------------------------------------------------------------------------------------------ +// 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; + +tableextension 6383 EDocServiceSupportedTypeExt extends "E-Doc. Service Supported Type" +{ + fields + { + field(6381; "Profile Id"; Integer) + { + Caption = 'Profile Id'; + ToolTip = 'The unique identifier for the metadata profile.'; + DataClassification = CustomerContent; + TableRelation = MetadataProfile; + BlankZero = true; + + trigger OnValidate() + begin + Rec.CalcFields("Profile Name"); + end; + } + field(6382; "Profile Name"; Text[250]) + { + Caption = 'Profile Name'; + ToolTip = 'The common name of the metadata profile.'; + FieldClass = FlowField; + Editable = false; + CalcFormula = lookup(MetadataProfile."Profile Name" where("Profile ID" = field("Profile Id"))); + } + } +} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/EDocumentExt.TableExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/EDocumentExt.TableExt.al new file mode 100644 index 0000000000..5ac14ecd52 --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/EDocumentExt.TableExt.al @@ -0,0 +1,19 @@ +// ------------------------------------------------------------------------------------------------ +// 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; + +tableextension 6382 EDocumentExt extends "E-Document" +{ + fields + { + field(6381; "SignUp Document Id"; Text[50]) + { + Caption = 'SignUp Document ID'; + ToolTip = 'This value is used by ExFlow E-Invoicing'; + } + } +} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/IntegrationEnumExt.EnumExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/IntegrationEnumExt.EnumExt.al index db4953f886..76b52fe1b4 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/IntegrationEnumExt.EnumExt.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/IntegrationEnumExt.EnumExt.al @@ -3,14 +3,14 @@ // Licensed under the MIT License. See License.txt in the project root for license information. // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; +using Microsoft.eServices.EDocument.Integration; +using Microsoft.eServices.EDocument.Integration.Interfaces; -using Microsoft.EServices.EDocument; - -enumextension 6380 IntegrationEnumExt extends "E-Document Integration" +enumextension 6380 IntegrationEnumExt extends "Service Integration" { value(6380; "ExFlow E-Invoicing") { Caption = 'ExFlow E-Invoicing'; - Implementation = "E-Document Integration" = IntegrationImpl; + Implementation = IDocumentSender = IntegrationImpl, IDocumentReceiver = IntegrationImpl; } } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/IntegrationImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/IntegrationImpl.Codeunit.al index 019ad06a32..59b59358eb 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/IntegrationImpl.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/IntegrationImpl.Codeunit.al @@ -5,57 +5,64 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using System.Utilities; -using Microsoft.EServices.EDocument; +using Microsoft.eServices.EDocument; +using Microsoft.eServices.EDocument.Integration.Interfaces; +using Microsoft.eServices.EDocument.Integration.Send; +using Microsoft.eServices.EDocument.Integration.Receive; -codeunit 6386 IntegrationImpl implements "E-Document Integration" + +codeunit 6386 IntegrationImpl implements IDocumentSender, IDocumentReceiver, IDocumentResponseHandler, IReceivedDocumentMarker { Access = Internal; var Processing: Codeunit Processing; - BatchSendNotSupportedErr: Label 'Batch sending is not supported in this version'; - CancelNotSupportedErr: Label 'Cancel is not supported in this version'; - procedure Send(var EDocument: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) + #region IDocumentSender + procedure Send(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; SendContext: Codeunit SendContext); var begin - this.Processing.SendEDocument(EDocument, TempBlob, IsAsync, HttpRequestMessage, HttpResponseMessage); + this.Processing.Send(EDocument, EDocumentService, SendContext); end; + #endregion - procedure SendBatch(var EDocuments: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) + #region IDocumentResponseHandler + procedure GetResponse(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; SendContext: Codeunit SendContext): Boolean; begin - IsAsync := false; - Error(this.BatchSendNotSupportedErr); + exit(this.Processing.GetResponse(EDocument, EDocumentService, SendContext)); end; + #endregion - procedure GetResponse(var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + #region IDocumentReceiver + procedure ReceiveDocuments(var EDocumentService: Record "E-Document Service"; DocumentsMetadataTempBlobList: Codeunit "Temp Blob List"; ReceiveContext: Codeunit ReceiveContext) begin - exit(this.Processing.GetDocumentResponse(EDocument, HttpRequestMessage, HttpResponseMessage)); + this.Processing.ReceiveDocuments(EDocumentService, DocumentsMetadataTempBlobList, ReceiveContext); end; - procedure GetApproval(var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + procedure DownloadDocument(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; DocumentMetadataTempBlob: Codeunit "Temp Blob"; ReceiveContext: Codeunit ReceiveContext) begin - exit(this.Processing.GetDocumentApproval(EDocument, HttpRequestMessage, HttpResponseMessage)); + this.Processing.DownloadDocument(EDocument, EDocumentService, DocumentMetadataTempBlob, ReceiveContext); end; + #endregion - procedure Cancel(var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean - begin - Error(this.CancelNotSupportedErr); - end; - procedure ReceiveDocument(var TempBlob: Codeunit "Temp Blob"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) + #region IReceivedDocumentMarker + procedure MarkFetched(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; var DocumentTempBlob: Codeunit "Temp Blob"; ReceiveContext: Codeunit ReceiveContext) begin - this.Processing.ReceiveDocument(TempBlob, HttpRequestMessage, HttpResponseMessage); + this.Processing.MarkFetched(EDocument, EDocumentService, DocumentTempBlob, ReceiveContext); end; + #endregion - procedure GetDocumentCountInBatch(var TempBlob: Codeunit "Temp Blob"): Integer - begin - exit(this.Processing.GetDocumentCountInBatch(TempBlob)); - end; - procedure GetIntegrationSetup(var SetupPage: Integer; var SetupTable: Integer) + [EventSubscriber(ObjectType::Page, Page::"E-Document Service", OnBeforeOpenServiceIntegrationSetupPage, '', false, false)] + local procedure OnBeforeOpenServiceIntegrationSetupPage(EDocumentService: Record "E-Document Service"; var IsServiceIntegrationSetupRun: Boolean) + var + ConnectionSetupCard: Page ConnectionSetupCard; begin - SetupPage := Page::ConnectionSetupCard; - SetupTable := Database::ConnectionSetup; + if EDocumentService."Service Integration V2" <> EDocumentService."Service Integration V2"::"ExFlow E-Invoicing" then + exit; + + ConnectionSetupCard.RunModal(); + IsServiceIntegrationSetupRun := true; end; } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/MetadataProfile.Table.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/MetadataProfile.Table.al new file mode 100644 index 0000000000..884e563a32 --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/MetadataProfile.Table.al @@ -0,0 +1,62 @@ +// ------------------------------------------------------------------------------------------------ +// 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; + +table 6382 MetadataProfile +{ + Caption = 'MetadataProfile'; + Access = Internal; + DataClassification = CustomerContent; + LookupPageId = 6381; + + fields + { + field(1; "Profile ID"; Integer) + { + Caption = 'Profile ID'; + Tooltip = 'The unique identifier for the metadata profile.'; + } + field(2; "Profile Name"; Text[250]) + { + Caption = 'Profile Name'; + Tooltip = 'The common name of the metadata profile.'; + } + field(3; "Process Identifier Scheme"; Text[250]) + { + Caption = 'Process Identifier Scheme'; + Tooltip = 'The scheme of the process identifier.'; + } + field(4; "Process Identifier Value"; Text[2048]) + { + Caption = 'Process Identifier Value'; + Tooltip = 'The value of the process identifier.'; + } + field(5; "Document Identifier Scheme"; Text[250]) + { + Caption = 'Document Identifier Scheme'; + Tooltip = 'The scheme of the document identifier.'; + } + field(6; "Document Identifier Value"; Text[2048]) + { + Caption = 'Document Identifier Value'; + Tooltip = 'The value of the document identifier.'; + } + } + + keys + { + key(PK; "Profile ID") + { + Clustered = true; + } + } + + fieldgroups + { + fieldgroup(DropDown; "Profile Id", "Profile Name") + { + } + } +} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/MetadataProfiles.Page.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/MetadataProfiles.Page.al new file mode 100644 index 0000000000..2415c1ca71 --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/MetadataProfiles.Page.al @@ -0,0 +1,47 @@ +// ------------------------------------------------------------------------------------------------ +// 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; + +page 6381 MetadataProfiles +{ + PageType = List; + SourceTable = MetadataProfile; + ApplicationArea = All; + UsageCategory = None; + + layout + { + area(content) + { + repeater(Group) + { + field("Profile ID"; Rec."Profile ID") + { + ApplicationArea = All; + } + field(Name; Rec."Profile Name") + { + ApplicationArea = All; + } + field("Process Identifier Scheme"; Rec."Process Identifier Scheme") + { + ApplicationArea = All; + } + field("Process Identifier Value"; Rec."Process Identifier Value") + { + ApplicationArea = All; + } + field("Document Identifier Scheme"; Rec."Document Identifier Scheme") + { + ApplicationArea = All; + } + field("Document Identifier Value"; Rec."Document Identifier Value") + { + ApplicationArea = All; + } + } + } + } +} diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al new file mode 100644 index 0000000000..5de0a205a2 --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al @@ -0,0 +1,16 @@ +// ------------------------------------------------------------------------------------------------ +// 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 SignUpEDCOEdit +{ + Access = Internal; + Assignable = false; + Caption = 'SignUp E-Doc. Connector - Edit', MaxLength = 30; + IncludedPermissionSets = SignUpEDCORead; + Permissions = tabledata ConnectionSetup = IMD, + tabledata MetadataProfile = IMD; + +} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOObjects.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOObjects.PermissionSet.al new file mode 100644 index 0000000000..c87e75db81 --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOObjects.PermissionSet.al @@ -0,0 +1,26 @@ +// ------------------------------------------------------------------------------------------------ +// 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; + +permissionset 6380 SignUpEDCOObjects +{ + Access = Internal; + Assignable = false; + Caption = 'SignUp E-Doc. Connector - Obj.', MaxLength = 30; + + Permissions = table ConnectionSetup = X, + table MetadataProfile = X, + table "E-Document Integration Log" = X, + page ConnectionSetupCard = X, + page MetadataProfiles = X, + codeunit APIRequests = X, + codeunit Authentication = X, + codeunit Connection = X, + codeunit Helpers = X, + codeunit IntegrationImpl = X, + codeunit Processing = X; +} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al new file mode 100644 index 0000000000..e598cf51fe --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al @@ -0,0 +1,20 @@ +// ------------------------------------------------------------------------------------------------ +// 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; + +permissionset 6381 SignUpEDCORead +{ + Access = Internal; + Assignable = false; + Caption = 'SignUp E-Doc. Connector - Read', MaxLength = 30; + IncludedPermissionSets = SignUpEDCOObjects; + Permissions = tabledata ConnectionSetup = R, + tabledata MetadataProfile = R, + tabledata "E-Document Integration Log" = rim; + + +} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al index a19c17812c..cdae0fc217 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al @@ -5,15 +5,46 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.EServices.EDocument; +using System.Text; using System.Utilities; +using Microsoft.eServices.EDocument.Integration.Send; +using Microsoft.eServices.EDocument.Integration.Receive; -codeunit 6388 Processing +codeunit 6383 Processing { Access = Internal; + InherentEntitlements = X; + InherentPermissions = X; + Permissions = tabledata "E-Document" = rim, + tabledata "E-Document Service Status" = rm, + tabledata "E-Document Service" = r, + tabledata "E-Document Integration Log" = rim, + tabledata "E-Document Log" = ri; #region variables var - ProcessingImpl: Codeunit ProcessingImpl; + Connection: Codeunit Connection; + HelpersImpl: Codeunit Helpers; + EDocumentErrorHelper: Codeunit "E-Document Error Helper"; + CouldNotRetrieveDocumentErr: Label 'Could not retrieve document with id: %1 from the service', Comment = '%1 - Document ID'; + CouldNotSendPatchErr: Label 'Could not Send Patch for document with id: %1', Comment = '%1 - Document ID'; + CouldNotRetrieveStatusFromResponseLbl: Label 'Could not retrieve status from response'; + DocumentIdNotFoundErr: Label 'Document ID not found in response'; + ErrorMessageMissingErr: Label 'Error message is missing or could not be parsed in the response'; + InboxTxt: Label 'inbox', Locked = true; + InstanceIdTxt: Label 'instanceId', Locked = true; + TransactionIdTxt: Label 'transactionId', Locked = true; + StatusTxt: Label 'status', Locked = true; + SentTxt: Label 'sent', Locked = true; + ProcessingTxt: Label 'processing', Locked = true; + FailedTxt: Label 'failed', Locked = true; + DescriptionTxt: Label 'description', Locked = true; + ResponseErrorTxt: Label 'ERROR', Locked = true; + LevelTxt: Label 'level', Locked = true; + EventsTxt: Label 'events', Locked = true; + ReasonTxt: Label 'Reason: ', Locked = true; + NewTxt: Label 'new', Locked = true; + DocumentTxt: Label 'document', Locked = true; #endregion @@ -22,98 +53,421 @@ codeunit 6388 Processing /// /// The method sends the E-Document to the API. /// - /// E-Document record - /// TempBlob - /// IsAsync - /// HttpRequestMessage - /// HttpResponseMessage - procedure SendEDocument(var EDocument: Record "E-Document"; var TempBlob: Codeunit "Temp Blob"; var IsAsync: Boolean; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) + /// The E-Document record to be sent. + /// The E-Document Service record associated with the E-Document. + /// The context in which the document is being sent, encapsulated in a SendContext codeunit. + procedure Send(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; SendContext: Codeunit SendContext); + var + EDocumentServiceStatus: Record "E-Document Service Status"; + TempBlob: Codeunit "Temp Blob"; + HttpRequestMessage: HttpRequestMessage; + HttpResponseMessage: HttpResponseMessage; begin - this.ProcessingImpl.SendEDocument(EDocument, TempBlob, IsAsync, HttpRequestMessage, HttpResponseMessage); + TempBlob := SendContext.GetTempBlob(); + + EDocumentServiceStatus.Get(EDocument."Entry No", EDocumentService.Code); + + case EDocumentServiceStatus.Status of + EDocumentServiceStatus.Status::Exported: + this.SendEDocument(EDocument, TempBlob, HttpRequestMessage, HttpResponseMessage); + EDocumentServiceStatus.Status::"Sending Error": + if EDocument."SignUp Document Id" = '' then + this.SendEDocument(EDocument, TempBlob, HttpRequestMessage, HttpResponseMessage); + end; + + SendContext.SetTempBlob(TempBlob); + SendContext.Http().SetHttpRequestMessage(HttpRequestMessage); + SendContext.Http().SetHttpResponseMessage(HttpResponseMessage); + end; /// - /// The method gets the E-Document response. + /// The method retrieves the response for the sent E-Document from the API. /// - /// E-Document record - /// HttpRequestMessage - /// HttpResponseMessage - /// True - if completed successfully - procedure GetDocumentResponse(var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + /// The E-Document record for which the response is being retrieved. + /// The E-Document Service record associated with the E-Document. + /// The context in which the document was sent, encapsulated in a SendContext codeunit. + /// Returns true if the response was successfully retrieved, otherwise false. + procedure GetResponse(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; SendContext: Codeunit SendContext): Boolean; + var + Status, ErrorDescription : Text; + HttpRequestMessage: HttpRequestMessage; + HttpResponseMessage: HttpResponseMessage; begin - exit(this.ProcessingImpl.GetDocumentResponse(EDocument, HttpRequestMessage, HttpResponseMessage)); + if EDocument."SignUp Document Id" = '' then + exit; + + if not this.Connection.CheckDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage) then + exit; + + SendContext.Http().SetHttpRequestMessage(HttpRequestMessage); + SendContext.Http().SetHttpResponseMessage(HttpResponseMessage); + + if not this.ParseDocumentResponse(HttpResponseMessage.Content, Status, ErrorDescription) then begin + this.EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, this.CouldNotRetrieveStatusFromResponseLbl); + exit; + end; + + + case Status of + this.SentTxt: + exit(this.SendAcknowledgePatch(EDocument, EDocumentService)); + this.ProcessingTxt: + exit(false); + this.FailedTxt: + begin + if ErrorDescription <> '' then + this.EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, this.ReasonTxt + ErrorDescription) + else + this.EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, this.ErrorMessageMissingErr); + exit(this.SendAcknowledgePatch(EDocument, EDocumentService)); + end; + end; + end; /// - /// The method gets the E-Document sent response. + /// The method receives documents from the API. /// - /// E-Document record - /// HttpRequestMessage - /// HttpResponseMessage - /// True - if completed successfully - procedure GetDocumentSentResponse(var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + /// The E-Document Service record associated with the documents being received. + /// A codeunit containing metadata for the received documents. + /// The context in which the documents are being received, encapsulated in a ReceiveContext codeunit. + procedure ReceiveDocuments(var EDocumentService: Record "E-Document Service"; DocumentsMetadataTempBlobList: Codeunit "Temp Blob List"; ReceiveContext: Codeunit ReceiveContext) + var + TempBlob: Codeunit "Temp Blob"; + JSONManagement: Codeunit "JSON Management"; + ContentData: Text; + HttpRequestMessage: HttpRequestMessage; + HttpResponseMessage: HttpResponseMessage; + JsonArray: JsonArray; + JsonToken: JsonToken; + ReceiveSucced: Boolean; begin - exit(this.ProcessingImpl.GetDocumentSentResponse(EDocument, HttpRequestMessage, HttpResponseMessage)); + ReceiveSucced := this.Connection.GetReceivedDocuments(HttpRequestMessage, HttpResponseMessage); + ReceiveContext.Http().SetHttpRequestMessage(HttpRequestMessage); + ReceiveContext.Http().SetHttpResponseMessage(HttpResponseMessage); + if not ReceiveSucced then + exit; + + if not HttpResponseMessage.Content.ReadAs(ContentData) then + exit; + + if not JsonManagement.InitializeFromString(ContentData) then + exit; + + JsonManagement.GetArrayPropertyValueAsStringByName(this.InboxTxt, ContentData); + JsonArray.ReadFrom(ContentData); + + foreach JsonToken in JsonArray do begin + Clear(TempBlob); + JsonToken.WriteTo(TempBlob.CreateOutStream(TextEncoding::UTF8)); + DocumentsMetadataTempBlobList.Add(TempBlob); + end; end; - /// - /// The method gets the E-Document approval. - /// - /// E-Document record - /// HttpRequestMessage - /// HttpResponseMessage - /// True - if completed successfully - procedure GetDocumentApproval(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean + procedure GetDocumentCountInBatch(var TempBlob: Codeunit "Temp Blob"): Integer + var + ResponseTxt: Text; begin - exit(this.ProcessingImpl.GetDocumentApproval(EDocument, HttpRequestMessage, HttpResponseMessage)); + TempBlob.CreateInStream().ReadText(ResponseTxt); + exit(this.GetNumberOfReceivedDocuments(ResponseTxt)); end; - /// - /// The method receives the document. - /// - /// TempBlob - /// HttpRequestMessage - /// HttpResponseMessage - procedure ReceiveDocument(var TempBlob: Codeunit "Temp Blob"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage) + procedure DownloadDocument(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; DocumentMetadataTempBlob: Codeunit "Temp Blob"; ReceiveContext: Codeunit ReceiveContext) + var + HttpRequestMessage: HttpRequestMessage; + HttpResponseMessage: HttpResponseMessage; + ContentData, DocumentId : Text; begin - this.ProcessingImpl.ReceiveDocument(TempBlob, HttpRequestMessage, HttpResponseMessage); + if EDocumentService."Service Integration V2" <> EDocumentService."Service Integration V2"::"ExFlow E-Invoicing" then + exit; + + DocumentMetadataTempBlob.CreateInStream(TextEncoding::UTF8).ReadText(ContentData); + + ContentData := this.LeaveJustNewLine(ContentData); + + if not this.ParseReceivedDocument(ContentData, DocumentId) then begin + this.EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, this.DocumentIdNotFoundErr); + exit; + end; + + EDocument."SignUp Document Id" := CopyStr(DocumentId, 1, MaxStrLen(EDocument."SignUp Document Id")); + EDocument.Modify(); + + Clear(ContentData); + this.OnBeforeGetTargetDocumentRequest(); + + this.Connection.GetTargetDocumentRequest(EDocument."SignUp Document Id", HttpRequestMessage, HttpResponseMessage); + ReceiveContext.Http().SetHttpRequestMessage(HttpRequestMessage); + ReceiveContext.Http().SetHttpResponseMessage(HttpResponseMessage); + + if not HttpResponseMessage.Content.ReadAs(ContentData) then + exit; + + if not this.ParseContentData(ContentData) then + ContentData := ''; + + if ContentData = '' then + this.EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, StrSubstNo(this.CouldNotRetrieveDocumentErr, DocumentId)) + else + ReceiveContext.GetTempBlob().CreateOutStream(TextEncoding::UTF8).WriteText(ContentData); end; - /// - /// The method gets the document count in batch. - /// - /// TempBlob - /// True - if completed successfully - procedure GetDocumentCountInBatch(var TempBlob: Codeunit "Temp Blob"): Integer + procedure MarkFetched(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; var TempBlob: Codeunit "Temp Blob"; ReceiveContext: Codeunit ReceiveContext) + var + HttpRequestMessage: HttpRequestMessage; + HttpResponseMessage: HttpResponseMessage; begin - exit(this.ProcessingImpl.GetDocumentCountInBatch(TempBlob)); + this.OnBeforeMarkFetched(); + this.Connection.RemoveDocumentFromReceived(EDocument, HttpRequestMessage, HttpResponseMessage); + + ReceiveContext.Http().SetHttpRequestMessage(HttpRequestMessage); + ReceiveContext.Http().SetHttpResponseMessage(HttpResponseMessage); + end; + #endregion - /// - /// The method inserts the integration log. - /// - /// E-Document record - /// E-Document Service record - /// HttpRequestMessage - /// HttpResponseMessage - procedure InsertIntegrationLog(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; HttpRequestMessage: HttpRequestMessage; HttpResponseMessage: HttpResponseMessage) + #region local methods + + local procedure InsertIntegrationLog(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; HttpRequestMessage: HttpRequestMessage; HttpResponseMessage: HttpResponseMessage) + var + EDocumentIntegrationLog: Record "E-Document Integration Log"; + EDocIntegrationLogRecordRef: RecordRef; + RequestTxt: Text; + begin + if EDocumentService."Service Integration V2" = EDocumentService."Service Integration V2"::"No Integration" then + exit; + + EDocumentIntegrationLog.Validate("E-Doc. Entry No", EDocument."Entry No"); + EDocumentIntegrationLog.Validate("Service Code", EDocumentService.Code); + EDocumentIntegrationLog.Validate("Response Status", HttpResponseMessage.HttpStatusCode()); + EDocumentIntegrationLog.Validate("Request URL", HttpRequestMessage.GetRequestUri()); + EDocumentIntegrationLog.Validate(Method, HttpRequestMessage.Method()); + EDocumentIntegrationLog.Insert(); + + EDocIntegrationLogRecordRef.GetTable(EDocumentIntegrationLog); + + if HttpRequestMessage.Content.ReadAs(RequestTxt) then begin + this.InsertIntegrationBlob(EDocIntegrationLogRecordRef, RequestTxt, EDocumentIntegrationLog.FieldNo(EDocumentIntegrationLog."Request Blob")); + EDocIntegrationLogRecordRef.Modify(); + end; + + if HttpResponseMessage.Content.ReadAs(RequestTxt) then begin + this.InsertIntegrationBlob(EDocIntegrationLogRecordRef, RequestTxt, EDocumentIntegrationLog.FieldNo(EDocumentIntegrationLog."Response Blob")); + EDocIntegrationLogRecordRef.Modify(); + end; + end; + + local procedure ParseDocumentResponse(HttpContentResponse: HttpContent; var Status: Text; var StatusDescription: Text): Boolean + var + JsonManagement: Codeunit "JSON Management"; + Result: Text; begin - this.ProcessingImpl.InsertIntegrationLog(EDocument, EDocumentService, HttpRequestMessage, HttpResponseMessage); + Status := ''; + StatusDescription := ''; + + Result := this.HelpersImpl.ParseJsonString(HttpContentResponse); + if Result = '' then + exit; + + if not JsonManagement.InitializeFromString(Result) then + exit; + + if not this.GetStatus(JsonManagement, Status) then + exit; + + case Status of + this.FailedTxt: + StatusDescription := this.GetErrorDescriptionFromJson(Result); + end; + + exit(true); end; - /// - /// The method inserts the log with integration. - /// - /// E-Document record - /// E-Document Service record - /// E-Document Service Status - /// E-Document Data Storage Entry No. - /// HttpRequestMessage - /// HttpResponseMessage - procedure InsertLogWithIntegration(var EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; - EDocumentServiceStatus: Enum "E-Document Service Status"; EDocDataStorageEntryNo: Integer; HttpRequestMessage: HttpRequestMessage; HttpResponseMessage: HttpResponseMessage) - begin - this.ProcessingImpl.InsertLogWithIntegration(EDocument, EDocumentService, EDocumentServiceStatus, EDocDataStorageEntryNo, HttpRequestMessage, HttpResponseMessage); + local procedure GetErrorDescriptionFromJson(JsonText: Text): Text + var + JsonObject: JsonObject; + JsonArray: JsonArray; + JsonToken: JsonToken; + EventObject: JsonObject; + ErrorDescription: Text; + begin + if JsonObject.ReadFrom(JsonText) then + if JsonObject.Get(this.EventsTxt, JsonToken) then + if JsonToken.IsArray() then begin + JsonArray := JsonToken.AsArray(); + foreach JsonToken in JsonArray do + if JsonToken.IsObject then begin + EventObject := JsonToken.AsObject(); + if EventObject.Get(this.LevelTxt, JsonToken) then + if (JsonToken.AsValue().AsText() = this.ResponseErrorTxt) then + if EventObject.Get(this.DescriptionTxt, JsonToken) then + if JsonToken.AsValue().AsText() <> '' then + ErrorDescription += JsonToken.AsValue().AsText() + ', '; + end; + end; + if ErrorDescription <> '' then + ErrorDescription := ErrorDescription.TrimEnd(', '); + exit(ErrorDescription); + end; + + local procedure SendEDocument(EDocument: Record "E-Document"; TempBlob: Codeunit "Temp Blob"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage); + begin + this.Connection.SendFilePostRequest(TempBlob, EDocument, HttpRequestMessage, HttpResponseMessage); + this.SetEDocumentFileID(EDocument."Entry No", this.ParseSendFileResponse(HttpResponseMessage.Content)); + end; + + local procedure ParseReceivedDocument(InputTxt: Text; var DocumentId: Text): Boolean + var + Helpers: Codeunit Helpers; + begin + DocumentId := Helpers.GetJsonValueFromText(InputTxt, this.TransactionIdTxt); + exit(DocumentId <> ''); + end; + + local procedure GetNumberOfReceivedDocuments(InputTxt: Text): Integer + var + JsonManagement: Codeunit "JSON Management"; + Value: Text; + begin + InputTxt := this.LeaveJustNewLine(InputTxt); + + if not JsonManagement.InitializeFromString(InputTxt) then + exit(0); + + JsonManagement.GetArrayPropertyValueAsStringByName(this.InboxTxt, Value); + JsonManagement.InitializeCollection(Value); + + exit(JsonManagement.GetCollectionCount()); + end; + + local procedure ParseSendFileResponse(HttpContentResponse: HttpContent): Text + var + JsonManagement: Codeunit "JSON Management"; + Result, Value : Text; + begin + Result := this.HelpersImpl.ParseJsonString(HttpContentResponse); + if Result = '' then + exit; + + if not JsonManagement.InitializeFromString(Result) then + exit; + + JsonManagement.GetStringPropertyValueByName(this.TransactionIdTxt, Value); + exit(Value); + end; + + local procedure SetEDocumentFileID(EDocEntryNo: Integer; FileId: Text) + var + EDocument: Record "E-Document"; + begin + if FileId = '' then + exit; + + if not EDocument.Get(EDocEntryNo) then + exit; + + EDocument."SignUp Document Id" := CopyStr(FileId, 1, MaxStrLen(EDocument."SignUp Document Id")); + EDocument.Modify(); + end; + + local procedure GetStatus(var JsonManagement: Codeunit "Json Management"; var Status: Text): Boolean + begin + if not JsonManagement.GetArrayPropertyValueAsStringByName(this.StatusTxt, Status) then + exit; + + Status := Status.ToLower(); + exit(true); + end; + + local procedure InsertIntegrationBlob(var EDocIntegrationLogRecordRef: RecordRef; Data: Text; FieldNo: Integer) + var + TempBlob: Codeunit "Temp Blob"; + begin + TempBlob.CreateOutStream().WriteText(Data); + TempBlob.ToRecordRef(EDocIntegrationLogRecordRef, FieldNo); + end; + + local procedure LeaveJustNewLine(InputText: Text): Text + var + InputJson, OutputDocumentJsonObject, OutputJsonObject : JsonObject; + InputJsonArray, OutputDocumentJsonArray : JsonArray; + InputJsonToken, DocumentJsonToken : JsonToken; + OutputText: text; + DocumentList: List of [Text]; + i: Integer; + begin + OutputText := InputText; + InputJson.ReadFrom(InputText); + if InputJson.Contains(this.InboxTxt) then begin + InputJson.Get(this.InboxTxt, InputJsonToken); + InputJsonArray := InputJsonToken.AsArray(); + foreach InputJsonToken in InputJsonArray do + if InputJsonToken.AsObject().Get(this.StatusTxt, DocumentJsonToken) then + if DocumentJsonToken.AsValue().AsText().ToLower() = this.NewTxt then begin + InputJsonToken.AsObject().Get(this.InstanceIdTxt, DocumentJsonToken); + DocumentList.Add(DocumentJsonToken.AsValue().AsText()); + end; + + for i := 1 to DocumentList.Count do begin + Clear(OutputDocumentJsonObject); + OutputDocumentJsonObject.Add(this.InstanceIdTxt, DocumentList.Get(i)); + OutputDocumentJsonArray.Add(OutputDocumentJsonObject); + end; + + OutputJsonObject.Add(this.InboxTxt, OutputDocumentJsonArray); + OutputJsonObject.WriteTo(OutputText) + end; + + exit(OutputText); + end; + + local procedure ParseContentData(var InputText: Text): Boolean + var + JsonManagement: Codeunit "JSON Management"; + Base64Convert: Codeunit "Base64 Convert"; + Value: Text; + begin + if not JsonManagement.InitializeFromString(InputText) then + exit; + + JsonManagement.GetArrayPropertyValueAsStringByName(this.DocumentTxt, Value); + InputText := Base64Convert.FromBase64(Value); + exit(true); + end; + + local procedure SendAcknowledgePatch(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"): Boolean + var + EDocumentServiceStatus: Record "E-Document Service Status"; + APIRequests: Codeunit APIRequests; + HttpResponseMessage: HttpResponseMessage; + HttpRequestMessage: HttpRequestMessage; + begin + EDocumentServiceStatus.SetLoadFields(Status); + EDocumentServiceStatus.Get(EDocument."Entry No", EDocumentService.Code); + if not (EDocumentServiceStatus.Status in [EDocumentServiceStatus.Status::Sent, EDocumentServiceStatus.Status::"Pending Response", EDocumentServiceStatus.Status::"Pending Batch"]) then + exit; + + if APIRequests.PatchDocument(EDocument, HttpRequestMessage, HttpResponseMessage) then begin + this.InsertIntegrationLog(EDocument, EDocumentService, HttpRequestMessage, HttpResponseMessage); + exit(true); + end else + this.EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, StrSubstNo(this.CouldNotSendPatchErr, EDocument."SignUp Document Id")); + end; + + #endregion + + #region event publishers + + [IntegrationEvent(false, false)] + local procedure OnBeforeGetTargetDocumentRequest() + begin + end; + + [IntegrationEvent(false, false)] + local procedure OnBeforeMarkFetched() + begin + end; #endregion diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetup.Table.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetup.Table.al index 7c07b7eec2..cf5e1430d2 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetup.Table.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetup.Table.al @@ -17,57 +17,64 @@ table 6381 ConnectionSetup Caption = 'PK', Locked = true; ToolTip = 'PK', Locked = true; } - field(4; "Authentication URL"; Text[250]) + field(2; "Authentication URL"; Text[2048]) { Caption = 'Authentication URL'; ToolTip = 'Specifies the URL to connect Microsoft Entra.'; } - field(9; "Company Id"; Text[100]) - { - Caption = 'Company ID'; - ToolTip = 'Specifies the company ID.'; - } - field(10; "Client ID"; Guid) + field(3; "Client ID"; Guid) { Caption = 'Client ID'; ToolTip = 'Specifies the client ID.'; } - field(11; "Client Secret"; Guid) + field(4; "Client Secret"; Guid) { Caption = 'Client Secret'; ToolTip = 'Specifies the client secret.'; } - field(12; "Environment Type"; Enum EnvironmentType) + field(5; "Environment Type"; Enum EnvironmentType) { Caption = 'Environment Type'; ToolTip = 'Specifies the environment type.'; } - field(13; ServiceURL; Text[250]) + field(6; "Service URL"; Text[2048]) { Caption = 'Service URL'; ToolTip = 'Specifies the service URL.'; + + trigger OnValidate() + begin + if Rec."Service URL" <> '' then + Rec."Service URL" := CopyStr(Rec."Service URL".TrimEnd('/'), 1, MaxStrLen(Rec."Service URL")); + end; } - field(20; "Root App ID"; Guid) + field(7; "Root App ID"; Guid) { Caption = 'Root App ID'; ToolTip = 'Specifies the root app ID.'; } - field(21; "Root Secret"; Guid) + field(8; "Root Secret"; Guid) { Caption = 'Root App Secret'; ToolTip = 'Specifies the root application secret.'; } - field(22; "Root Tenant"; Guid) + field(9; "Root Tenant"; Guid) { Caption = 'Root App Tenant'; ToolTip = 'Specifies the root application tenant.'; } - field(23; "Root Market URL"; Guid) + field(10; "Root Market URL"; Text[2048]) { Caption = 'Root Market URL'; ToolTip = 'Specifies the root market URL.'; + + trigger OnValidate() + begin + if Rec."Root Market URL" <> '' then + Rec."Root Market URL" := CopyStr(Rec."Root Market URL".TrimEnd('/'), 1, MaxStrLen("Root Market URL")); + end; } - field(24; "Client Tenant"; Guid) + field(11; "Client Tenant"; Guid) { Caption = 'Client App Tenant'; ToolTip = 'Specifies the client application tenant.'; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetupCard.Page.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetupCard.Page.al index 2d804b4c11..58620239ca 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetupCard.Page.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetupCard.Page.al @@ -5,6 +5,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using System.Telemetry; +using Microsoft.Foundation.Company; using System.Environment; page 6380 ConnectionSetupCard @@ -30,7 +31,7 @@ page 6380 ConnectionSetupCard ToolTip = 'Specifies the client ID token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; - Visible = not this.IsSaaSInfrastructure; + Visible = this.FieldsVisible; ShowMandatory = true; trigger OnValidate() @@ -44,21 +45,22 @@ page 6380 ConnectionSetupCard ToolTip = 'Specifies the client secret token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; - Visible = not this.IsSaaSInfrastructure; + Visible = this.FieldsVisible; ShowMandatory = true; trigger OnValidate() begin - this.SaveSecret(Rec."Client Secret", this.ClientSecret) + this.SaveSecret(Rec."Client Secret", this.ClientSecret); end; } field(ClientTenant; this.ClientTenant) { - Caption = 'Client Tenant ID'; - ToolTip = 'Specifies the client tenant id token.'; + Caption = 'Client Tenant'; + ToolTip = 'Specifies the client tenant.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; - Visible = not this.IsSaaSInfrastructure; + Visible = this.FieldsVisible; + ShowMandatory = true; trigger OnValidate() begin @@ -71,7 +73,7 @@ page 6380 ConnectionSetupCard ToolTip = 'Specifies the root app id token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; - Visible = not this.IsSaaSInfrastructure; + Visible = this.FieldsVisible; trigger OnValidate() begin @@ -84,7 +86,7 @@ page 6380 ConnectionSetupCard ToolTip = 'Specifies the root secret token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; - Visible = not this.IsSaaSInfrastructure; + Visible = this.FieldsVisible; trigger OnValidate() begin @@ -97,39 +99,29 @@ page 6380 ConnectionSetupCard ToolTip = 'Specifies the root tenant id token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; - Visible = not this.IsSaaSInfrastructure; + Visible = this.FieldsVisible; trigger OnValidate() begin this.Authentication.StorageSet(Rec."Root Tenant", this.RootTenant); end; } - field(RootUrl; this.RootUrl) + field(RootUrl; Rec."Root Market URL") { - Caption = 'Root Url'; + Caption = 'Root URL'; ToolTip = 'Specifies the root url token.'; ApplicationArea = Basic, Suite; - ExtendedDatatype = Masked; - Visible = not this.IsSaaSInfrastructure; + Visible = this.FieldsVisible; - trigger OnValidate() - begin - this.Authentication.StorageSet(Rec."Root Market URL", this.RootUrl); - end; } field("Authentication URL"; Rec."Authentication URL") { ApplicationArea = Basic, Suite; } - field(ServiceURL; Rec.ServiceURL) + field(ServiceURL; Rec."Service URL") { ApplicationArea = Basic, Suite; } - field("Company Id"; Rec."Company Id") - { - ApplicationArea = Basic, Suite; - ShowMandatory = true; - } field("Environment Type"; Rec."Environment Type") { ApplicationArea = Basic, Suite; @@ -151,7 +143,6 @@ page 6380 ConnectionSetupCard Promoted = true; PromotedCategory = Process; PromotedOnly = true; - Visible = this.IsSaaSInfrastructure; ToolTip = 'Create client credentials and open the onboarding process in a web browser.'; trigger OnAction() @@ -170,7 +161,7 @@ page 6380 ConnectionSetupCard var EnvironmentInformation: Codeunit "Environment Information"; begin - this.IsSaaSInfrastructure := EnvironmentInformation.IsSaaSInfrastructure(); + this.FieldsVisible := not EnvironmentInformation.IsSaaSInfrastructure(); this.Authentication.InitConnectionSetup(); if Rec.Get() then ; @@ -192,11 +183,9 @@ page 6380 ConnectionSetupCard this.RootSecret := this.MaskTxt; if not IsNullGuid(Rec."Root Tenant") then this.RootTenant := this.MaskTxt; - if not IsNullGuid(Rec."Root Market URL") then - this.RootUrl := this.MaskTxt; end; - [NonDebuggable] + [NonDebuggable] local procedure SaveSecret(var TokenKey: Guid; Value: SecretText) begin this.Authentication.StorageSet(TokenKey, Value); @@ -206,8 +195,8 @@ page 6380 ConnectionSetupCard Authentication: Codeunit Authentication; FeatureTelemetry: Codeunit "Feature Telemetry"; [NonDebuggable] - ClientID, ClientSecret, ClientTenant, ClientUrl, RootID, RootSecret, RootTenant, RootUrl : Text; - IsSaaSInfrastructure: Boolean; + ClientID, ClientSecret, ClientTenant, RootID, RootSecret, RootTenant : Text; + FieldsVisible: Boolean; ExternalServiceTok: Label 'E-Document - SignUp', Locked = true; MaskTxt: Label '*', Locked = true; } \ No newline at end of file From d7fd5536c3376ce9c48c1d2124011f9b65569345 Mon Sep 17 00:00:00 2001 From: geschwint Date: Wed, 5 Feb 2025 12:18:24 +0100 Subject: [PATCH 38/63] Automated Tests --- .../EDocumentConnectors/SignUp/app/app.json | 82 +-- .../SignUp/test/ExtensionLogo.png | Bin 0 -> 5446 bytes .../EDocumentConnectors/SignUp/test/app.json | 113 ++++ .../test/src/IntegrationEvents.Codeunit.al | 27 + .../test/src/IntegrationHelpers.Codeunit.al | 67 ++ .../test/src/IntegrationTests.Codeunit.al | 633 ++++++++++++++++++ 6 files changed, 881 insertions(+), 41 deletions(-) create mode 100644 Apps/W1/EDocumentConnectors/SignUp/test/ExtensionLogo.png create mode 100644 Apps/W1/EDocumentConnectors/SignUp/test/app.json create mode 100644 Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationEvents.Codeunit.al create mode 100644 Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationHelpers.Codeunit.al create mode 100644 Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/app.json b/Apps/W1/EDocumentConnectors/SignUp/app/app.json index 5d02eb4470..2e3e8b9e5d 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/app.json +++ b/Apps/W1/EDocumentConnectors/SignUp/app/app.json @@ -1,46 +1,46 @@ { - "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" - } - ], + "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", + "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" ] diff --git a/Apps/W1/EDocumentConnectors/SignUp/test/ExtensionLogo.png b/Apps/W1/EDocumentConnectors/SignUp/test/ExtensionLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..4d2c9a626cb9617350617c40cd73904129d4c108 GIT binary patch literal 5446 zcma)=S5VVywD$iAMIcgC2u+$uktV%J6$Dhev_NQrfC^Fsq!|cJ=^|Z`P&U*^N-uuwi#_w5i!*aB*89x5SkKKnv*ua91anhEW+omc005Zp+`e`1 zOsW4C1O3^nWxbYuCX9Z!?E(M*a`E2+jm<_J0|5K}om)4pLZ&wJ&3t(K(|ffcq#?ky z#^aeQO#|lO9vyUeb0ezqQtpipl3Sj#-xy!eh7lu@5+BnW zNhL-~3Zpw&1u=bMN*Q(sgYksq4dM>Iw7p&Qk_Su~b*PgEs#LK~^K}aDaTG_6Q?_tM<8wOS}`Z+?~Et8GB>T%(k7$9`DL!d5)f!ZoXco-vj+s_QLEs2cf zKM&F>#c9w|TmM9MFtl8L*cYQgl9khf5CYMR)DJOUf;M~a9|+ys@RYR zCusNC(CSlUk|r`qdS&ZKh$O=@#&e0>;W~S#|KjHdfLx!-J9r1JtP4RGIhS|Rm0eZ6 z7eOE~Zfo4Li~K^|&)d^-r?8Rh2Q}#ZjL=?VJZ7~hlp4(!U!0K%679I`OR&x54*0&4 znho|hKu)WR)4PUVA1}N;jXHg}AG+gSKQ6O_fEP^Y51!LwBERH09|t!GNx2KH4co>r zA%cgSHxh2Sezx-w!S5DTG#0zVCbnLM6BP}2P-G{8 zh**wJHj<652FS05bSQNx-0fS7^(wREYvZwpt;$!!k4H0U*iyhS8(syBDMv>L<)~LI zPl!Y^-cM{_J@{hY1=XJ#T=Ef(FD!I^r1^lca3c0ftVuvo-(%!Zn)C1bK{}-i*Jc); zIIc+o&iMgvboj&4`@5sF23MV!*zIVmA0>{1;*H*faMAG6EZ7XydTfaGyABAGx>)yl z@Y+|)SVxCx@!GWqspay7GBetK*s2@CJ?s{8v!(b|ShLb|O;3T1rAMB?DJ?Z`@013q zoyIvV84eYiS+?kRJOz`3AFcR~ZQ1Uq7wCnbSJ%-HZwhAnJ^4zDp2W8I)~WI7ush5> z&f3O)rj~2ZGr!c@=p3!n>jG-O#9`$7&WyF7bB}(rq4ldokUp5TY?E62r+YJbJp8Jf znDW3fYZ^nBQ9O}3?zH_*mZ9+G#HHnwop1Vfm!Df~{Z%D?5KzMN&RA>&#q8iCzTfAt zV#TyMeyyh8=M$8tyA|KeUwo_Q6Si)P)%n(W-*QE~08BG|>J!sQPq?IF;;%1ypP?Z` zK_0Un>p;9=9d675ELHboC0+fNMY&(;k(|=0TS>ka)BKI3q#)zx!Jp@zv0QfeEAjU< z=vI5@-d^A^-*#|P+b2QFiGxk4z<8Tp4p6{aOp88x>SQEa0M`VxX%IUb$bya!5EgRf6$fFw zp}jNTKUXjNe0x(;)Nu)Ij5K?QD0u6~mRHQ-!;6m#VP>)}=irAqy;f$e{W-EWnR75~ zm2b0u@r7ASk4x0oTqs9{f&F|eAmD*Gf^A;te7f}J{dXqLaH_4%D_(mnp0VmWhq>^E z&7>5*-mh>FX{w5SJf^#th&GrpOQk58U-+4 zq3$q~C4ySH7@lr>W+|c0`UF*ieC+3vC1$4m}F(ic|G7}QDt(t z7`#>$c4U-4LU_;nWHhdN9Fcv~L8h6M_}nW&EGTjgW(=c}uD9>eU^rDOrkNg_effOV z^8z_y=vNIt{`wOfgG2o^3ey`R!aP1=t7Mz@&MKK3>_BH_QkgNO@4IoQ-2d8EqsDg) zTMb-5lqlubRot-7!RD@+udO?O9_Da3XV5bvjW zXTb2psHUdeiIaI(lknQE_<+YlY31}R!VfoM_BuILQ{>Q89=LB5j;V|-yAW2gY82+~ zYlu~#*R(cHw2NO1h5xaiAD2oiIEQ-aQyA-D^y^z2ZHNfM{o(3M#SbqOP3>k9FOdDO z(t%c9hk)NCPe_8>=Y^U-_-6IwS-D0cE=pwdyLp!;r-fWiXtbUS$<dl!~WV$TR8 zP$KU?K>m?*O)mSGccn&kn|nj7NXFeo<0D=ue8s^~BK#P?J~gB}v5<0nK9GPipjT#9 zkm6yXFyLlgoUIDEVxw*0Z-WDqp8swCs(bcjAqdDLl1oUqYf#a`NjT6IO3?=P`FvUZ zlWC&lWb9_dexSz%N~-oscM`oC%b#KS|KS7AptwRX5h&1VDCKWzP{&??TFdF3h53&c zU(v)WhOr)#!V6Y6d7CzOO-@KF%@67>kh34@Exj7Rh}p5_0?yUeyC7@c7DHf+mW=~wpLeLYDA9#W-Ri*S|M@g zjPHH@qHrPuzq(+5y$V*UoFEg(g$$mRNUEF!C{IN3Rig{tU54W|OD_`M0G3u)B{WhC z*D?hTF7J+YdF8-Z-Uuw{3jBx`_!aus`uDDBecwuu&tsVpj2~DZJb2-!a2l??m{}er}lR6Lqu)-2+Vm)jr(g{nfQPx9-<^1d;k-d zkU{E^g7qwp+D`b+QtU5@+swaVKp9<`>sT~U)O!EEMBo!*)~s_<`6Yl z7fX2;ki>kVDfdietW1k;TYvaY({>?5X)&(d&_y<-J7Qa@b z(zwGCI=`P#^b>1>2#Y!9T5|AdtaU|zXxw9^KpIu6CAmQf$GzaeOJmYVsc3eh5%6lb z)t~(Ak2J`;KW_L6psME-h?xF6ryr4d{q;>-b`Q$L43T{r`{N?U6cqP(Q3f%kA8`c@ z<82KXjte|7u_Lo~MV!d%y$tYi(hzU$6t+*ml~Z&Mg{eK?@}^XEBK+-&j`Uv95x)=_ zZLs=Mpg_IuZenjm(~}b8Aggaaje8NX$A_7^G%-)!xtu)C{N|S<3hVOmU;{|i+q6zn zfr(1Ua*jF!%-dU3L}O2fvWAe%-4kxtXo_vJHF(AxSx)4AI8-$^uBQO_86Z_y%RZX4 zJpu5`pOAztxv?jXv9yx|r>#9!0|`71C-fli@v${6r+V$hgvcr|W_I`{=7*0s(PKQH zzn8r2+tSeD15stz|DIJ3%X%8EkyN?bsHhuq4(5D0Oewn_)-o)Nx$eNs{0V*ZTSVt4 z3ifXGGw5fBv+9b6d~Nl+08L4VbbZqf3DL^e?l@!uZVdWkdOpJPaE?{zF!ZI?c(vF3 zvX~OK4vktvm&R$MgNpiKA~&zT!1#H7!q1h7AQiuSNG9<=$64)Zym(UQ``(j#^hDzt}{aur0pS?mmBi&z4I0Jfieqh%Pa_A%N?_1OZHm-S{ zQ*)4(N_J;y7tRh0o>xs25-s9!M-)i;@I68#SGXB2XgS}N zx_r3%V)z1jLA_M&?)E^DT$kzdHMJF%e2w6BH@iI5tKWM+zcuhCsz@N0a_1RBvrdZx zjzD>V%;c4*$RkEv{zHuVyaB+ANl(iT8w{pJdziC7YcO2&(ciqGLhs@q-dNh! zkV_V_(_~$*>ND}j1yozMedYnu-_GKMh?IpP<@D+edeB4M%3@xr3oj{@mdFKoBVpm^)1_}Y^}rOWBSB|Uv)*-pTdiU ztW9~{qq5@iB+$QpbeJVKH^n^9vV})i>Z@2CHoY2$PC888c;#Yz-pHRK@EVheWhE!> zZzjPmy?0Ni8#=o_k6_s3DY7nS^&Bm}BW&ZfAuF7bQbDgAGM$dE)RM6RvdobKb&MhsYD4exRm9*jcHPjbz#rI?vj$u zPLF5Gjv|8}?ta9`&^H}Va3H;llghU-BC7pxo6?-eTP`7CUZHJrw{5 zhkDYeIYlhL%brQJ1X#<#fz#E}Z87Kj=Hde*f{l|A`9E my8jz0{9hgZgN;Rh%;ug!HJ{lE_@04L;EulOt!iDD=>G@$cU!Ii literal 0 HcmV?d00001 diff --git a/Apps/W1/EDocumentConnectors/SignUp/test/app.json b/Apps/W1/EDocumentConnectors/SignUp/test/app.json new file mode 100644 index 0000000000..a244074d48 --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/test/app.json @@ -0,0 +1,113 @@ +{ + "id": "b56171bd-9a8e-47ad-a527-99f476d5af83", + "name": "E-Document Connector - SignUp Tests", + "publisher": "Microsoft", + "brief": "E-Document Connector - SignUp Tests", + "description": "E-Document Connector - SignUp Tests", + "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": "b56171bd-9a8e-47ad-a527-99f476d5af83", + "name": "E-Document Connector - SignUp", + "publisher": "SignUp Software AB", + "version": "26.0.0.0" + }, + { + "id": "e1d97edc-c239-46b4-8d84-6368bdf67c8b", + "name": "E-Document Core", + "publisher": "Microsoft", + "version": "26.0.0.0" + }, + { + "id": "de0dddf3-9917-430d-8d20-6e7679a08500", + "name": "E-Document Core Demo Data", + "publisher": "Microsoft", + "version": "26.0.0.0" + }, + { + "id": "5a0b41e9-7a42-4123-d521-2265186cfb31", + "name": "Contoso Coffee Demo Dataset", + "publisher": "Microsoft", + "version": "26.0.0.0" + }, + { + "id": "e1d97edc-c239-46b4-8d84-6368bdf67c8c", + "name": "E-Document Core Tests", + "publisher": "Microsoft", + "version": "26.0.0.0" + }, + { + "id": "dd0be2ea-f733-4d65-bb34-a28f4624fb14", + "name": "Library Assert", + "publisher": "Microsoft", + "version": "26.0.0.0" + }, + { + "id": "e7320ebb-08b3-4406-b1ec-b4927d3e280b", + "name": "Any", + "publisher": "Microsoft", + "version": "26.0.0.0" + }, + { + "id": "5d86850b-0d76-4eca-bd7b-951ad998e997", + "name": "Tests-TestLibraries", + "publisher": "Microsoft", + "version": "26.0.0.0" + }, + { + "id": "9856ae4f-d1a7-46ef-89bb-6ef056398228", + "name": "System Application Test Library", + "publisher": "Microsoft", + "version": "26.0.0.0" + }, + { + "id": "23de40a6-dfe8-4f80-80db-d70f83ce8caf", + "name": "Test Runner", + "publisher": "Microsoft", + "version": "26.0.0.0" + }, + { + "id": "5095f467-0a01-4b99-99d1-9ff1237d286f", + "name": "Library Variable Storage", + "publisher": "Microsoft", + "version": "26.0.0.0" + }, + { + "id": "bee8cf2f-494a-42f4-aabd-650e87934d39", + "name": "Business Foundation Test Libraries", + "publisher": "Microsoft", + "version": "26.0.0.0" + }, + { + "id": "40860557-a18d-42ad-aecb-22b7dd80dc80", + "name": "Permissions Mock", + "publisher": "Microsoft", + "version": "26.0.0.0" + } + ], + "screenshots": [], + "platform": "26.0.0.0", + "application": "26.0.0.0", + "idRanges": [ + { + "from": 148195, + "to": 148199 + } + ], + "resourceExposurePolicy": { + "allowDebugging": true, + "allowDownloadingSource": true, + "includeSourceInSymbolFile": true + }, + "runtime": "15.0", + "features": [ + "TranslationFile" + ], + "target": "OnPrem" +} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationEvents.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationEvents.Codeunit.al new file mode 100644 index 0000000000..6708ef7364 --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationEvents.Codeunit.al @@ -0,0 +1,27 @@ +namespace Microsoft.EServices.EDocumentConnector.SignUp; + + +codeunit 148197 IntegrationEvents +{ + EventSubscriberInstance = Manual; + + var + LibraryLowerPermissions: Codeunit "Library - Lower Permissions"; + IntegrationHelpers: Codeunit IntegrationHelpers; + + [EventSubscriber(ObjectType::Codeunit, Codeunit::Processing, OnBeforeGetTargetDocumentRequest, '', true, true)] + local procedure ProcessingOnBeforeGetTargetDocumentRequest() + begin + this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCOEdit'); + this.IntegrationHelpers.SetAPICode('/signup/200/download'); + this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCORead'); + end; + + [EventSubscriber(ObjectType::Codeunit, Codeunit::Processing, OnBeforeGetTargetDocumentRequest, '', true, true)] + local procedure ProcessingOnBeforeMarkFetched() + begin + this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCOEdit'); + this.IntegrationHelpers.SetAPICode('/signup/200/markdownloaded'); + this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCORead'); + end; +} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationHelpers.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationHelpers.Codeunit.al new file mode 100644 index 0000000000..427b124aa3 --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationHelpers.Codeunit.al @@ -0,0 +1,67 @@ +namespace Microsoft.EServices.EDocumentConnector.SignUp; + + +codeunit 148196 IntegrationHelpers +{ + internal procedure SetAPIWith200Code() + begin + this.SetAPICode('/signup/200'); + end; + + internal procedure SetAPIWith500Code() + begin + this.SetAPICode('/signup/500'); + end; + + internal procedure SetAPICode(Path: Text) + var + ConnectionSetup: Record ConnectionSetup; + begin + ConnectionSetup.Get(); + ConnectionSetup."Service URL" := this.SetMockServiceUrl(Path); + ConnectionSetup.Modify(true); + end; + + internal procedure SetCommonConnectionSetup() + var + ConnectionSetup: Record ConnectionSetup; + Authentication: Codeunit Authentication; + begin + ConnectionSetup.Get(); + Authentication.StorageSet(ConnectionSetup."Root App ID", this.DummyId()); + Authentication.StorageSet(ConnectionSetup."Root Secret", this.DummyId()); + Authentication.StorageSet(ConnectionSetup."Root Tenant", this.DummyId()); + Authentication.StorageSet(ConnectionSetup."Client ID", this.DummyId()); + Authentication.StorageSet(ConnectionSetup."Client Secret", this.DummyId()); + Authentication.StorageSet(ConnectionSetup."Client Tenant", this.ClientTenantId()); + + ConnectionSetup."Authentication URL" := this.SetMockServiceUrl('/%1/oauth2/token'); + ConnectionSetup."Environment Type" := ConnectionSetup."Environment Type"::Test; + ConnectionSetup.Modify(true); + end; + + internal procedure SetMockServiceUrl(Path: Text): Text[250] + begin + exit('http://localhost:8080' + Path); + end; + + local procedure ClientTenantId(): Text + begin + exit('signup'); + end; + + local procedure DummyId(): Text[100] + begin + exit('0a4b7f70-452a-4883-844f-296443704124'); + end; + + internal procedure MockServiceDocumentId(): Text + begin + exit('485959a5-4a96-4a41-a208-13c30bb7e4d3'); + end; + + internal procedure MockCompanyId(): Text[100] + begin + exit('0007:SIGNUPSOFTWARE'); + end; +} \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al new file mode 100644 index 0000000000..1df14aaed1 --- /dev/null +++ b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al @@ -0,0 +1,633 @@ +// ------------------------------------------------------------------------------------------------ +// 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.Inventory.Item; +using Microsoft.EServices.EDocument.Service.Participant; +using Microsoft.Foundation.Company; +//using Microsoft.Purchases.Document; +using Microsoft.Purchases.Vendor; +using Microsoft.Sales.Customer; +using System.Threading; +using Microsoft.eServices.EDocument.Integration; + +codeunit 148195 IntegrationTests +{ + Subtype = Test; + + Permissions = tabledata ConnectionSetup = rimd, + tabledata "E-Document" = r; + + var + Customer: Record Customer; + Vendor: Record Vendor; + Item: Record Item; + EDocumentService: Record "E-Document Service"; + LibraryEDocument: Codeunit "Library - E-Document"; + LibraryInventory: Codeunit "Library - Inventory"; + LibraryLowerPermissions: Codeunit "Library - Lower Permissions"; + LibraryJobQueue: Codeunit "Library - Job Queue"; + IntegrationHelpers: Codeunit IntegrationHelpers; + Assert: Codeunit Assert; + IsInitialized: Boolean; + IncorrectValueErr: Label 'Wrong value', Locked = true; + + /// + /// Test needs MockService running to work. + /// + [Test] + [HandlerFunctions('ExternalHttpRequestHandler')] + procedure SubmitDocument() + var + EDocument: Record "E-Document"; + JobQueueEntry: Record "Job Queue Entry"; + EDocumentPage: TestPage "E-Document"; + EDocLogList: List of [Enum "E-Document Service Status"]; + begin + // Steps: + // Pending response -> Sent + this.Initialize(); + + // [Given] Team member + this.LibraryLowerPermissions.SetTeamMember(); + this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCORead'); + + // [When] Posting invoice and EDocument is created + this.LibraryEDocument.PostInvoice(this.Customer); + EDocument.FindLast(); + this.LibraryEDocument.RunEDocumentJobQueue(EDocument); + + // [When] EDocument is fetched after running ExFlow SubmitDocument + EDocument.FindLast(); + + // [Then] Document Id has been correctly set on E-Document, parsed from Integration response. + this.Assert.AreEqual(this.IntegrationHelpers.MockServiceDocumentId(), EDocument."Signup Document Id", 'ExFlow integration failed to set Document Id on E-Document'); + this.Assert.AreEqual(Enum::"E-Document Status"::"In Progress", EDocument.Status, 'E-Document should be set to in progress'); + + // [THEN] Open E-Document page + EDocumentPage.OpenView(); + EDocumentPage.GoToRecord(EDocument); + this.Assert.AreEqual(Format(EDocument.Direction::Outgoing), EDocumentPage.Direction.Value(), this.IncorrectValueErr); + this.Assert.AreEqual(EDocument."Document No.", EDocumentPage."Document No.".Value(), this.IncorrectValueErr); + + // [THEN] E-Document Service Status has "Pending Response" + this.Assert.AreEqual(this.EDocumentService.Code, EDocumentPage.EdocoumentServiceStatus."E-Document Service Code".Value(), this.IncorrectValueErr); + this.Assert.AreEqual(Format(Enum::"E-Document Service Status"::"Pending Response"), EDocumentPage.EdocoumentServiceStatus.Status.Value(), this.IncorrectValueErr); + this.Assert.AreEqual('2', EDocumentPage.EdocoumentServiceStatus.Logs.Value(), this.IncorrectValueErr); + + Clear(EDocLogList); + EDocLogList.Add(Enum::"E-Document Service Status"::"Exported"); + EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response"); + this.LibraryEDocument.AssertEDocumentLogs(EDocument, this.EDocumentService, EDocLogList); + + // [THEN] E-Document Errors and Warnings has correct status + this.Assert.AreEqual('', EDocumentPage.ErrorMessagesPart."Message Type".Value(), this.IncorrectValueErr); + this.Assert.AreEqual('', EDocumentPage.ErrorMessagesPart.Description.Value(), this.IncorrectValueErr); + EDocumentPage.Close(); + + // [WHEN] Executing Get Response succesfully + JobQueueEntry.FindJobQueueEntry(JobQueueEntry."Object Type to Run"::Codeunit, Codeunit::"E-Document Get Response"); + this.LibraryJobQueue.RunJobQueueDispatcher(JobQueueEntry); + + // [When] EDocument is fetched after running ExFlow GetResponse + EDocument.FindLast(); + + // [Then] E-Document is considered processed + this.Assert.AreEqual(Enum::"E-Document Status"::"In Progress", EDocument.Status, 'E-Document should be set to in progress'); + + // [THEN] Open E-Document page + EDocumentPage.OpenView(); + EDocumentPage.GoToRecord(EDocument); + this.Assert.AreEqual(Format(EDocument.Direction::Outgoing), EDocumentPage.Direction.Value(), this.IncorrectValueErr); + this.Assert.AreEqual(EDocument."Document No.", EDocumentPage."Document No.".Value(), this.IncorrectValueErr); + + // [THEN] E-Document Service Status has Sent + this.Assert.AreEqual(this.EDocumentService.Code, EDocumentPage.EdocoumentServiceStatus."E-Document Service Code".Value(), this.IncorrectValueErr); + this.Assert.AreEqual(Format(Enum::"E-Document Service Status"::"Pending Response"), EDocumentPage.EdocoumentServiceStatus.Status.Value(), this.IncorrectValueErr); + this.Assert.AreEqual('3', EDocumentPage.EdocoumentServiceStatus.Logs.Value(), this.IncorrectValueErr); + + Clear(EDocLogList); + EDocLogList.Add(Enum::"E-Document Service Status"::"Exported"); + EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response"); + EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response"); + this.LibraryEDocument.AssertEDocumentLogs(EDocument, this.EDocumentService, EDocLogList); + + // [THEN] E-Document Errors and Warnings has correct status + this.Assert.AreEqual('', EDocumentPage.ErrorMessagesPart."Message Type".Value(), this.IncorrectValueErr); + this.Assert.AreEqual('', EDocumentPage.ErrorMessagesPart.Description.Value(), this.IncorrectValueErr); + EDocumentPage.Close(); + end; + + /// + /// Test needs MockService running to work. + /// + [Test] + procedure SubmitDocument_Pending_Sent() + var + EDocument: Record "E-Document"; + JobQueueEntry: Record "Job Queue Entry"; + EDocumentPage: TestPage "E-Document"; + EDocLogList: List of [Enum "E-Document Service Status"]; + begin + // Steps: + // Pending response -> Pending response -> Sent + this.Initialize(); + this.IntegrationHelpers.SetAPIWith200Code(); + + // [Given] Team member + this.LibraryLowerPermissions.SetTeamMember(); + this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCORead'); + + // [When] Posting invoice and EDocument is created + this.LibraryEDocument.PostInvoice(this.Customer); + EDocument.FindLast(); + this.LibraryEDocument.RunEDocumentJobQueue(EDocument); + + // [When] EDocument is fetched after running ExFlow SubmitDocument + EDocument.FindLast(); + + // [Then] Document Id has been correctly set on E-Document, parsed from Integration response + this.Assert.AreEqual(this.IntegrationHelpers.MockServiceDocumentId(), EDocument."Signup Document Id", 'ExFlow integration failed to set Document Id on E-Document'); + + // [Then] E-Document is pending response as ExFlow is async + this.Assert.AreEqual(Enum::"E-Document Status"::"In Progress", EDocument.Status, 'E-Document should be set to in progress'); + + // [THEN] Open E-Document page + EDocumentPage.OpenView(); + EDocumentPage.GoToRecord(EDocument); + this.Assert.AreEqual(Format(EDocument.Direction::Outgoing), EDocumentPage.Direction.Value(), this.IncorrectValueErr); + this.Assert.AreEqual(EDocument."Document No.", EDocumentPage."Document No.".Value(), this.IncorrectValueErr); + + // [THEN] E-Document Service Status has pending response + this.Assert.AreEqual(this.EDocumentService.Code, EDocumentPage.EdocoumentServiceStatus."E-Document Service Code".Value(), this.IncorrectValueErr); + this.Assert.AreEqual(Format(Enum::"E-Document Service Status"::"Pending Response"), EDocumentPage.EdocoumentServiceStatus.Status.Value(), this.IncorrectValueErr); + this.Assert.AreEqual('2', EDocumentPage.EdocoumentServiceStatus.Logs.Value(), this.IncorrectValueErr); + Clear(EDocLogList); + EDocLogList.Add(Enum::"E-Document Service Status"::"Exported"); + EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response"); + this.LibraryEDocument.AssertEDocumentLogs(EDocument, this.EDocumentService, EDocLogList); + + // [THEN] E-Document Errors and Warnings has correct status + this.Assert.AreEqual('', EDocumentPage.ErrorMessagesPart."Message Type".Value(), this.IncorrectValueErr); + this.Assert.AreEqual('', EDocumentPage.ErrorMessagesPart.Description.Value(), this.IncorrectValueErr); + EDocumentPage.Close(); + + // [WHEN] Executing Get Response succesfully + this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCOEdit'); + this.IntegrationHelpers.SetAPICode('/signup/200/response-pending'); + this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCORead'); + JobQueueEntry.FindJobQueueEntry(JobQueueEntry."Object Type to Run"::Codeunit, Codeunit::"E-Document Get Response"); + this.LibraryJobQueue.RunJobQueueDispatcher(JobQueueEntry); + + // [When] EDocument is fetched after running ExFlow GetResponse + EDocument.FindLast(); + + // [Then] E-Document is pending response as ExFlow is async + this.Assert.AreEqual(Enum::"E-Document Status"::"In Progress", EDocument.Status, 'E-Document should be set to in progress'); + + // [THEN] Open E-Document page + EDocumentPage.OpenView(); + EDocumentPage.GoToRecord(EDocument); + this.Assert.AreEqual(Format(EDocument.Direction::Outgoing), EDocumentPage.Direction.Value(), this.IncorrectValueErr); + this.Assert.AreEqual(EDocument."Document No.", EDocumentPage."Document No.".Value(), this.IncorrectValueErr); + + // [THEN] E-Document Service Status has pending response + this.Assert.AreEqual(this.EDocumentService.Code, EDocumentPage.EdocoumentServiceStatus."E-Document Service Code".Value(), this.IncorrectValueErr); + this.Assert.AreEqual(Format(Enum::"E-Document Service Status"::"Pending Response"), EDocumentPage.EdocoumentServiceStatus.Status.Value(), this.IncorrectValueErr); + this.Assert.AreEqual('3', EDocumentPage.EdocoumentServiceStatus.Logs.Value(), this.IncorrectValueErr); + + Clear(EDocLogList); + EDocLogList.Add(Enum::"E-Document Service Status"::"Exported"); + EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response"); + EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response"); + this.LibraryEDocument.AssertEDocumentLogs(EDocument, this.EDocumentService, EDocLogList); + + // [THEN] E-Document Errors and Warnings has correct status + this.Assert.AreEqual('', EDocumentPage.ErrorMessagesPart."Message Type".Value(), this.IncorrectValueErr); + this.Assert.AreEqual('', EDocumentPage.ErrorMessagesPart.Description.Value(), this.IncorrectValueErr); + EDocumentPage.Close(); + + // [WHEN] Executing Get Response succesfully + this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCOEdit'); + this.IntegrationHelpers.SetAPIWith200Code(); + this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCORead'); + JobQueueEntry.FindJobQueueEntry(JobQueueEntry."Object Type to Run"::Codeunit, Codeunit::"E-Document Get Response"); + this.LibraryJobQueue.RunJobQueueDispatcher(JobQueueEntry); + + // [When] EDocument is fetched after running ExFlow GetResponse + EDocument.FindLast(); + + // [Then] E-Document is pending response as ExFlow is async + this.Assert.AreEqual(Enum::"E-Document Status"::"In Progress", EDocument.Status, 'E-Document should be set to processed'); + + // [THEN] Open E-Document page + EDocumentPage.OpenView(); + EDocumentPage.GoToRecord(EDocument); + this.Assert.AreEqual(Format(EDocument.Direction::Outgoing), EDocumentPage.Direction.Value(), this.IncorrectValueErr); + this.Assert.AreEqual(EDocument."Document No.", EDocumentPage."Document No.".Value(), this.IncorrectValueErr); + + // [THEN] E-Document Service Status has pending response + this.Assert.AreEqual(this.EDocumentService.Code, EDocumentPage.EdocoumentServiceStatus."E-Document Service Code".Value(), this.IncorrectValueErr); + this.Assert.AreEqual(Format(Enum::"E-Document Service Status"::"Pending Response"), EDocumentPage.EdocoumentServiceStatus.Status.Value(), this.IncorrectValueErr); + this.Assert.AreEqual('4', EDocumentPage.EdocoumentServiceStatus.Logs.Value(), this.IncorrectValueErr); + + Clear(EDocLogList); + EDocLogList.Add(Enum::"E-Document Service Status"::"Exported"); + EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response"); + EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response"); + EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response"); + this.LibraryEDocument.AssertEDocumentLogs(EDocument, this.EDocumentService, EDocLogList); + + // [THEN] E-Document Errors and Warnings has correct status + this.Assert.AreEqual('', EDocumentPage.ErrorMessagesPart."Message Type".Value(), this.IncorrectValueErr); + this.Assert.AreEqual('', EDocumentPage.ErrorMessagesPart.Description.Value(), this.IncorrectValueErr); + EDocumentPage.Close(); + end; + + /// + /// Test needs MockService running to work. + /// + [Test] + [HandlerFunctions('EDocServicesPageHandler')] + procedure SubmitDocument_Error_Sent() + var + EDocument: Record "E-Document"; + JobQueueEntry: Record "Job Queue Entry"; + EDocumentPage: TestPage "E-Document"; + EDocLogList: List of [Enum "E-Document Service Status"]; + begin + // Steps: + // Pending response -> Error -> Pending response -> Sent + this.Initialize(); + this.IntegrationHelpers.SetAPIWith200Code(); + + // [Given] Team member + this.LibraryLowerPermissions.SetTeamMember(); + this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCORead'); + + // [When] Posting invoice and EDocument is created + this.LibraryEDocument.PostInvoice(this.Customer); + EDocument.FindLast(); + this.LibraryEDocument.RunEDocumentJobQueue(EDocument); + + // [When] EDocument is fetched after running ExFlow SubmitDocument + EDocument.FindLast(); + + // [Then] Document Id has been correctly set on E-Document, parsed from Integration response + this.Assert.AreEqual(this.IntegrationHelpers.MockServiceDocumentId(), EDocument."Signup Document Id", 'ExFlow integration failed to set Document Id on E-Document'); + + // [Then] E-Document is pending response as ExFlow is async + this.Assert.AreEqual(Enum::"E-Document Status"::"In Progress", EDocument.Status, 'E-Document should be set to in progress'); + + // [THEN] Open E-Document page + EDocumentPage.OpenView(); + EDocumentPage.GoToRecord(EDocument); + this.Assert.AreEqual(Format(EDocument.Direction::Outgoing), EDocumentPage.Direction.Value(), this.IncorrectValueErr); + this.Assert.AreEqual(EDocument."Document No.", EDocumentPage."Document No.".Value(), this.IncorrectValueErr); + + // [THEN] E-Document Service Status has pending response + this.Assert.AreEqual(this.EDocumentService.Code, EDocumentPage.EdocoumentServiceStatus."E-Document Service Code".Value(), this.IncorrectValueErr); + this.Assert.AreEqual(Format(Enum::"E-Document Service Status"::"Pending Response"), EDocumentPage.EdocoumentServiceStatus.Status.Value(), this.IncorrectValueErr); + this.Assert.AreEqual('2', EDocumentPage.EdocoumentServiceStatus.Logs.Value(), this.IncorrectValueErr); + + Clear(EDocLogList); + EDocLogList.Add(Enum::"E-Document Service Status"::"Exported"); + EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response"); + this.LibraryEDocument.AssertEDocumentLogs(EDocument, this.EDocumentService, EDocLogList); + + // [THEN] E-Document Errors and Warnings has correct status + this.Assert.AreEqual('', EDocumentPage.ErrorMessagesPart."Message Type".Value(), this.IncorrectValueErr); + this.Assert.AreEqual('', EDocumentPage.ErrorMessagesPart.Description.Value(), this.IncorrectValueErr); + EDocumentPage.Close(); + + // [WHEN] Executing Get Response succesfully + this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCOEdit'); + this.IntegrationHelpers.SetAPICode('/signup/200/response-error'); + this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCORead'); + JobQueueEntry.FindJobQueueEntry(JobQueueEntry."Object Type to Run"::Codeunit, Codeunit::"E-Document Get Response"); + this.LibraryJobQueue.RunJobQueueDispatcher(JobQueueEntry); + + // [When] EDocument is fetched after running ExFlow GetResponse + EDocument.FindLast(); + + // [Then] E-Document is in error state + this.Assert.AreEqual(Enum::"E-Document Status"::Error, EDocument.Status, 'E-Document should be set to error'); + + // [THEN] Open E-Document page + EDocumentPage.OpenView(); + EDocumentPage.GoToRecord(EDocument); + this.Assert.AreEqual(Format(EDocument.Direction::Outgoing), EDocumentPage.Direction.Value(), this.IncorrectValueErr); + this.Assert.AreEqual(EDocument."Document No.", EDocumentPage."Document No.".Value(), this.IncorrectValueErr); + + // [THEN] E-Document Service Status has sending error + this.Assert.AreEqual(this.EDocumentService.Code, EDocumentPage.EdocoumentServiceStatus."E-Document Service Code".Value(), this.IncorrectValueErr); + this.Assert.AreEqual(Format(Enum::"E-Document Service Status"::"Sending Error"), EDocumentPage.EdocoumentServiceStatus.Status.Value(), this.IncorrectValueErr); + this.Assert.AreEqual('3', EDocumentPage.EdocoumentServiceStatus.Logs.Value(), this.IncorrectValueErr); + + Clear(EDocLogList); + EDocLogList.Add(Enum::"E-Document Service Status"::"Exported"); + EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response"); + EDocLogList.Add(Enum::"E-Document Service Status"::"Sending Error"); + this.LibraryEDocument.AssertEDocumentLogs(EDocument, this.EDocumentService, EDocLogList); + + EDocumentPage.ErrorMessagesPart.First(); + // [THEN] E-Document Errors and Warnings has correct status + this.Assert.AreEqual('Error', EDocumentPage.ErrorMessagesPart."Message Type".Value(), this.IncorrectValueErr); + this.Assert.AreEqual('Reason: Http error 404 document identifier not found', EDocumentPage.ErrorMessagesPart.Description.Value(), this.IncorrectValueErr); + + EDocumentPage.Close(); + + // Then user manually send + this.IntegrationHelpers.SetAPIWith200Code(); + EDocument.FindLast(); + + // [THEN] Open E-Document page and resend + EDocumentPage.OpenView(); + EDocumentPage.GoToRecord(EDocument); + EDocumentPage.Send_Promoted.Invoke(); + EDocumentPage.Close(); + + EDocument.FindLast(); + EDocumentPage.OpenView(); + EDocumentPage.GoToRecord(EDocument); + + // [Then] E-Document is pending response as ExFlow is async + this.Assert.AreEqual(Enum::"E-Document Status"::"In Progress", EDocument.Status, 'E-Document should be set to in progress'); + + this.Assert.AreEqual(Format(EDocument.Direction::Outgoing), EDocumentPage.Direction.Value(), this.IncorrectValueErr); + this.Assert.AreEqual(EDocument."Document No.", EDocumentPage."Document No.".Value(), this.IncorrectValueErr); + + // [THEN] E-Document Service Status has pending response + this.Assert.AreEqual(this.EDocumentService.Code, EDocumentPage.EdocoumentServiceStatus."E-Document Service Code".Value(), this.IncorrectValueErr); + this.Assert.AreEqual(Format(Enum::"E-Document Service Status"::"Pending Response"), EDocumentPage.EdocoumentServiceStatus.Status.Value(), this.IncorrectValueErr); + this.Assert.AreEqual('4', EDocumentPage.EdocoumentServiceStatus.Logs.Value(), this.IncorrectValueErr); + + Clear(EDocLogList); + EDocLogList.Add(Enum::"E-Document Service Status"::"Exported"); + EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response"); + EDocLogList.Add(Enum::"E-Document Service Status"::"Sending Error"); + EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response"); + this.LibraryEDocument.AssertEDocumentLogs(EDocument, this.EDocumentService, EDocLogList); + + // [THEN] E-Document Errors and Warnings has correct status + this.Assert.AreEqual('', EDocumentPage.ErrorMessagesPart."Message Type".Value(), this.IncorrectValueErr); + this.Assert.AreEqual('', EDocumentPage.ErrorMessagesPart.Description.Value(), this.IncorrectValueErr); + EDocumentPage.Close(); + + this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCOEdit'); + this.IntegrationHelpers.SetAPIWith200Code(); + this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCORead'); + + JobQueueEntry.FindJobQueueEntry(JobQueueEntry."Object Type to Run"::Codeunit, Codeunit::"E-Document Get Response"); + this.LibraryJobQueue.RunJobQueueDispatcher(JobQueueEntry); + + // [When] EDocument is fetched after running ExFlow GetResponse + EDocument.FindLast(); + + // [Then] E-Document is pending response as ExFlow is async + this.Assert.AreEqual(Enum::"E-Document Status"::"In Progress", EDocument.Status, 'E-Document should be set to processed'); + + // [THEN] Open E-Document page + EDocumentPage.OpenView(); + EDocumentPage.GoToRecord(EDocument); + this.Assert.AreEqual(Format(EDocument.Direction::Outgoing), EDocumentPage.Direction.Value(), this.IncorrectValueErr); + this.Assert.AreEqual(EDocument."Document No.", EDocumentPage."Document No.".Value(), this.IncorrectValueErr); + + // [THEN] E-Document Service Status has pending response + this.Assert.AreEqual(this.EDocumentService.Code, EDocumentPage.EdocoumentServiceStatus."E-Document Service Code".Value(), this.IncorrectValueErr); + this.Assert.AreEqual(Format(Enum::"E-Document Service Status"::"Pending Response"), EDocumentPage.EdocoumentServiceStatus.Status.Value(), this.IncorrectValueErr); + this.Assert.AreEqual('5', EDocumentPage.EdocoumentServiceStatus.Logs.Value(), this.IncorrectValueErr); + + Clear(EDocLogList); + EDocLogList.Add(Enum::"E-Document Service Status"::"Exported"); + EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response"); + EDocLogList.Add(Enum::"E-Document Service Status"::"Sending Error"); + EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response"); + EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response"); + this.LibraryEDocument.AssertEDocumentLogs(EDocument, this.EDocumentService, EDocLogList); + + // [THEN] E-Document Errors and Warnings has correct status + this.Assert.AreEqual('', EDocumentPage.ErrorMessagesPart."Message Type".Value(), this.IncorrectValueErr); + this.Assert.AreEqual('', EDocumentPage.ErrorMessagesPart.Description.Value(), this.IncorrectValueErr); + EDocumentPage.Close(); + end; + + /// + /// Test needs MockService running to work. + /// + [Test] + procedure SubmitDocumentServiceDown() + var + EDocument: Record "E-Document"; + EDocumentPage: TestPage "E-Document"; + EDocLogList: List of [Enum "E-Document Service Status"]; + begin + this.Initialize(); + this.IntegrationHelpers.SetAPIWith500Code(); + + // [Given] Team member + this.LibraryLowerPermissions.SetTeamMember(); + this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCORead'); + + // [When] Posting invoice and EDocument is created + this.LibraryEDocument.PostInvoice(this.Customer); + EDocument.FindLast(); + this.LibraryEDocument.RunEDocumentJobQueue(EDocument); + + // [When] EDocument is fetched after running Avalara SubmitDocument + EDocument.FindLast(); + + this.Assert.AreEqual(Enum::"E-Document Status"::Error, EDocument.Status, 'E-Document should be set to error state when service is down.'); + this.Assert.AreEqual('', EDocument."Signup Document Id", 'Document Id on E-Document should not be set.'); + + EDocumentPage.OpenView(); + EDocumentPage.GoToRecord(EDocument); + + // [THEN] E-Document has correct error status + this.Assert.AreEqual(Format(EDocument.Status::Error), EDocumentPage."Electronic Document Status".Value(), this.IncorrectValueErr); + this.Assert.AreEqual(Format(EDocument.Direction::Outgoing), EDocumentPage.Direction.Value(), this.IncorrectValueErr); + this.Assert.AreEqual(EDocument."Document No.", EDocumentPage."Document No.".Value(), this.IncorrectValueErr); + + // [THEN] E-Document Service Status has correct error status + this.Assert.AreEqual(this.EDocumentService.Code, EDocumentPage.EdocoumentServiceStatus."E-Document Service Code".Value(), this.IncorrectValueErr); + this.Assert.AreEqual(Format(Enum::"E-Document Service Status"::"Sending Error"), EDocumentPage.EdocoumentServiceStatus.Status.Value(), this.IncorrectValueErr); + this.Assert.AreEqual('2', EDocumentPage.EdocoumentServiceStatus.Logs.Value(), this.IncorrectValueErr); + + Clear(EDocLogList); + EDocLogList.Add(Enum::"E-Document Service Status"::"Exported"); + EDocLogList.Add(Enum::"E-Document Service Status"::"Sending Error"); + this.LibraryEDocument.AssertEDocumentLogs(EDocument, this.EDocumentService, EDocLogList); + + // [THEN] E-Document Errors and Warnings has correct status + this.Assert.AreEqual('Error', EDocumentPage.ErrorMessagesPart."Message Type".Value(), this.IncorrectValueErr); + this.Assert.AreEqual('There was an error sending the request. Response code: 500 and error message: Internal Server Error', EDocumentPage.ErrorMessagesPart.Description.Value(), this.IncorrectValueErr); + end; + + /// + /// Test needs MockService running to work. + /// + [Test] + procedure SubmitGetDocuments() + var + EDocument: Record "E-Document"; + //PurchaseHeader: Record "Purchase Header"; + IntegrationEvents: Codeunit IntegrationEvents; + EDocumentServicesPage: TestPage "E-Document Service"; + TmpDocCount: Integer; + begin + this.Initialize(); + + // Open and close E-Doc page creates auto import job due to setting + EDocumentServicesPage.OpenView(); + EDocumentServicesPage.GoToRecord(this.EDocumentService); + EDocumentServicesPage."Resolve Unit Of Measure".SetValue(false); + EDocumentServicesPage."Lookup Item Reference".SetValue(true); + EDocumentServicesPage."Lookup Item GTIN".SetValue(false); + EDocumentServicesPage."Lookup Account Mapping".SetValue(false); + EDocumentServicesPage."Validate Line Discount".SetValue(false); + EDocumentServicesPage."Auto Import".SetValue(true); + EDocumentServicesPage.Close(); + + TmpDocCount := EDocument.Count(); + BindSubscription(IntegrationEvents); + // Manually fire job queue job to import + this.LibraryEDocument.RunImportJob(); + UnbindSubscription(IntegrationEvents); + + // Assert that we have Purchase Invoice created + this.Assert.AreEqual(EDocument.Count(), TmpDocCount + 1, 'The document was not imported!'); + end; + + /// + /// Test needs MockService running to work. + /// + [Test] + procedure GetMetadataProfiles() + var + MetadataProfile: Record MetadataProfile; + EDocServiceSupportedTypes: TestPage "E-Doc Service Supported Types"; + begin + this.Initialize(); + + MetadataProfile.Reset(); + MetadataProfile.DeleteAll(); + + // Populate metadata profiles + EDocServiceSupportedTypes.OpenView(); + EDocServiceSupportedTypes.PopulateMetaData.Invoke(); + EDocServiceSupportedTypes.Close(); + + this.Assert.TableIsNotEmpty(Database::MetadataProfile); + end; + + local procedure Initialize() + var + ConnectionSetup: Record ConnectionSetup; + CompanyInformation: Record "Company Information"; + ServiceParticipant: Record "Service Participant"; + Authentication: Codeunit Authentication; + begin + this.LibraryLowerPermissions.SetOutsideO365Scope(); + + ConnectionSetup.DeleteAll(); + Authentication.InitConnectionSetup(); + this.IntegrationHelpers.SetCommonConnectionSetup(); + this.IntegrationHelpers.SetAPIWith200Code(); + + if this.IsInitialized then + exit; + + this.CreateDefaultMetadataProfile(); + this.LibraryEDocument.SetupStandardVAT(); + this.LibraryEDocument.SetupStandardSalesScenario(this.Customer, this.EDocumentService, Enum::"E-Document Format"::"PEPPOL BIS 3.0", Enum::"Service Integration"::"ExFlow E-Invoicing PTE"); + this.LibraryEDocument.SetupStandardPurchaseScenario(this.Vendor, this.EDocumentService, Enum::"E-Document Format"::"PEPPOL BIS 3.0", Enum::"Service Integration"::"ExFlow E-Invoicing PTE"); + this.EDocumentService."Auto Import" := true; + this.EDocumentService."Import Minutes between runs" := 5; + this.EDocumentService."Import Start Time" := Time(); + this.EDocumentService.Modify(); + + this.LibraryInventory.CreateItem(this.Item); + + this.Vendor.Name := 'CRONUS GB SELLER'; + this.Vendor."VAT Registration No." := '777777777'; // GB777777771 + this.Vendor."Receive E-Document To" := Enum::"E-Document Type"::"Purchase Invoice"; + this.Vendor.Modify(); + + // Vendor to get invoices from + Clear(ServiceParticipant); + ServiceParticipant.Service := this.EDocumentService.Code; + ServiceParticipant."Participant Type" := ServiceParticipant."Participant Type"::Vendor; + ServiceParticipant.Participant := this.Vendor."No."; + ServiceParticipant."Participant Identifier" := this.IntegrationHelpers.MockCompanyId(); + ServiceParticipant.Insert(); + + // Customer to send invoice to + Clear(ServiceParticipant); + ServiceParticipant.Service := this.EDocumentService.Code; + ServiceParticipant."Participant Type" := ServiceParticipant."Participant Type"::Customer; + ServiceParticipant.Participant := this.Customer."No."; + ServiceParticipant."Participant Identifier" := this.IntegrationHelpers.MockCompanyId(); + ServiceParticipant.Insert(); + + CompanyInformation.Get(); + CompanyInformation."VAT Registration No." := '777777777'; // GB777777771 + CompanyInformation."SignUp Service Participant Id" := this.IntegrationHelpers.MockCompanyId(); + CompanyInformation.Modify(); + + this.ApplyMetadataProfile(this.GetMetadataProfileId()); + + this.IsInitialized := true; + end; + + local procedure CreateDefaultMetadataProfile() + var + MetadataProfile: Record MetadataProfile; + begin + if not MetadataProfile.IsEmpty() then + MetadataProfile.DeleteAll(true); + + MetadataProfile.Init(); + MetadataProfile.Validate("Profile ID", this.GetMetadataProfileId()); + MetadataProfile.Validate("Profile Name", 'PEPPOL BIS Billing v 3 Invoice UBL'); + MetadataProfile.Validate("Process Identifier Scheme", 'cenbii-procid-ubl'); + MetadataProfile.Validate("Process Identifier Value", 'urn:fdc:peppol.eu:2017:poacc:billing:01:1.0'); + MetadataProfile.Validate("Document Identifier Scheme", 'busdox-docid-qns'); + MetadataProfile.Validate("Document Identifier Value", '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'); + MetadataProfile.Insert(true); + end; + + local procedure ApplyMetadataProfile(ProfileID: Integer) + var + EDocServiceSupportedType: Record "E-Doc. Service Supported Type"; + begin + if EDocServiceSupportedType.FindSet(true) then + repeat + EDocServiceSupportedType.Validate("Profile Id", ProfileID); + EDocServiceSupportedType.Modify(true); + until EDocServiceSupportedType.Next() = 0; + end; + + local procedure GetMetadataProfileId(): Integer + begin + exit(158); + end; + + [ModalPageHandler] + internal procedure EDocServicesPageHandler(var EDocumentServicesPage: TestPage "E-Document Services") + begin + EDocumentServicesPage.Filter.SetFilter(Code, this.EDocumentService.Code); + EDocumentServicesPage.OK().Invoke(); + end; + + [StrMenuHandler] + internal procedure ExternalHttpRequestHandler(Options: Text[1024]; var Choice: Integer; Instruction: Text[1024]) + var + ExternalHttpRequestChoice: Option " ","Allow Always","Allow Once","Block Always","Block Once"; + begin + Choice := ExternalHttpRequestChoice::"Allow Always"; + end; +} \ No newline at end of file From db8f136a2a38a6f20b6f75d773d210058b2aabb0 Mon Sep 17 00:00:00 2001 From: geschwint Date: Mon, 10 Feb 2025 11:15:06 +0100 Subject: [PATCH 39/63] Make masked fields Client ID and Client Secret visible in Connection Setup Card --- .../SignUp/app/src/Setup/ConnectionSetupCard.Page.al | 3 --- 1 file changed, 3 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetupCard.Page.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetupCard.Page.al index 58620239ca..6d540e18f4 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetupCard.Page.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetupCard.Page.al @@ -31,7 +31,6 @@ page 6380 ConnectionSetupCard ToolTip = 'Specifies the client ID token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; - Visible = this.FieldsVisible; ShowMandatory = true; trigger OnValidate() @@ -45,7 +44,6 @@ page 6380 ConnectionSetupCard ToolTip = 'Specifies the client secret token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; - Visible = this.FieldsVisible; ShowMandatory = true; trigger OnValidate() @@ -112,7 +110,6 @@ page 6380 ConnectionSetupCard ToolTip = 'Specifies the root url token.'; ApplicationArea = Basic, Suite; Visible = this.FieldsVisible; - } field("Authentication URL"; Rec."Authentication URL") { From 8072d8ba1c690012306c63a3e2344f47c9706186 Mon Sep 17 00:00:00 2001 From: geschwint Date: Tue, 11 Feb 2025 10:44:58 +0100 Subject: [PATCH 40/63] Cloud and remove dependency --- Apps/W1/EDocumentConnectors/SignUp/app/app.json | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/app.json b/Apps/W1/EDocumentConnectors/SignUp/app/app.json index 2e3e8b9e5d..3e80be6107 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/app.json +++ b/Apps/W1/EDocumentConnectors/SignUp/app/app.json @@ -17,12 +17,6 @@ "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": [], @@ -40,7 +34,7 @@ "includeSourceInSymbolFile": true }, "application": "26.0.0.0", - "target": "OnPrem", + "target": "Cloud", "features": [ "TranslationFile" ] From 00e20bce6bed7df34912382c75c5eae7abb2da00 Mon Sep 17 00:00:00 2001 From: geschwint Date: Tue, 11 Feb 2025 11:08:33 +0100 Subject: [PATCH 41/63] Refactor Objectnames - Rename files --- ...ationExt.PageExt.al => SignUpCompanyInformationExt.PageExt.al} | 0 ...ionExt.TableExt.al => SignUpCompanyInformationExt.TableExt.al} | 0 ...geExt.PageExt.al => SignUpEDocSvcSupTypeExtPageExt.PageExt.al} | 0 ...eExt.TableExt.al => SignUpEDocSvcSupportedTypeExt.TableExt.al} | 0 .../{EDocumentExt.TableExt.al => SignUpEDocumentExt.TableExt.al} | 0 ...tionEnumExt.EnumExt.al => SignUpIntegrationEnumExt.EnumExt.al} | 0 ...egrationImpl.Codeunit.al => SignUpIntegrationImpl.Codeunit.al} | 0 .../{ConnectionSetup.Table.al => SignUpConnectionSetup.Table.al} | 0 ...nectionSetupCard.Page.al => SignUpConnectionSetupCard.Page.al} | 0 .../{EnvironmentType.Enum.al => SignUpEnvironmentType.Enum.al} | 0 .../{APIRequests.Codeunit.al => SignUpAPIRequests.Codeunit.al} | 0 ...uthentication.Codeunit.al => SignUpAuthentication.Codeunit.al} | 0 .../src/{Connection.Codeunit.al => SignUpConnection.Codeunit.al} | 0 .../app/src/{Helpers.Codeunit.al => SignUpHelpers.Codeunit.al} | 0 .../{MetadataProfile.Table.al => SignUpMetadataProfile.Table.al} | 0 .../{MetadataProfiles.Page.al => SignUpMetadataProfiles.Page.al} | 0 .../src/{Processing.Codeunit.al => SignUpProcessing.Codeunit.al} | 0 17 files changed, 0 insertions(+), 0 deletions(-) rename Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/{CompanyInformationExt.PageExt.al => SignUpCompanyInformationExt.PageExt.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/{CompanyInformationExt.TableExt.al => SignUpCompanyInformationExt.TableExt.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/{EDocServSuppTypeExtPageExt.PageExt.al => SignUpEDocSvcSupTypeExtPageExt.PageExt.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/{EDocServiceSupportedTypeExt.TableExt.al => SignUpEDocSvcSupportedTypeExt.TableExt.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/{EDocumentExt.TableExt.al => SignUpEDocumentExt.TableExt.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/{IntegrationEnumExt.EnumExt.al => SignUpIntegrationEnumExt.EnumExt.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/{IntegrationImpl.Codeunit.al => SignUpIntegrationImpl.Codeunit.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/{ConnectionSetup.Table.al => SignUpConnectionSetup.Table.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/{ConnectionSetupCard.Page.al => SignUpConnectionSetupCard.Page.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/{EnvironmentType.Enum.al => SignUpEnvironmentType.Enum.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/{APIRequests.Codeunit.al => SignUpAPIRequests.Codeunit.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/{Authentication.Codeunit.al => SignUpAuthentication.Codeunit.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/{Connection.Codeunit.al => SignUpConnection.Codeunit.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/{Helpers.Codeunit.al => SignUpHelpers.Codeunit.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/{MetadataProfile.Table.al => SignUpMetadataProfile.Table.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/{MetadataProfiles.Page.al => SignUpMetadataProfiles.Page.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/{Processing.Codeunit.al => SignUpProcessing.Codeunit.al} (100%) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/CompanyInformationExt.PageExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.PageExt.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/CompanyInformationExt.PageExt.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.PageExt.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/CompanyInformationExt.TableExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.TableExt.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/CompanyInformationExt.TableExt.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.TableExt.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/EDocServSuppTypeExtPageExt.PageExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcSupTypeExtPageExt.PageExt.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/EDocServSuppTypeExtPageExt.PageExt.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcSupTypeExtPageExt.PageExt.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/EDocServiceSupportedTypeExt.TableExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcSupportedTypeExt.TableExt.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/EDocServiceSupportedTypeExt.TableExt.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcSupportedTypeExt.TableExt.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/EDocumentExt.TableExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocumentExt.TableExt.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/EDocumentExt.TableExt.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocumentExt.TableExt.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/IntegrationEnumExt.EnumExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationEnumExt.EnumExt.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/IntegrationEnumExt.EnumExt.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationEnumExt.EnumExt.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/IntegrationImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationImpl.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/IntegrationImpl.Codeunit.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationImpl.Codeunit.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetup.Table.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetup.Table.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetupCard.Page.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/ConnectionSetupCard.Page.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/EnvironmentType.Enum.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpEnvironmentType.Enum.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/EnvironmentType.Enum.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpEnvironmentType.Enum.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAPIRequests.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/APIRequests.Codeunit.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAPIRequests.Codeunit.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Authentication.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Authentication.Codeunit.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Connection.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpConnection.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Connection.Codeunit.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpConnection.Codeunit.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Helpers.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpHelpers.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Helpers.Codeunit.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpHelpers.Codeunit.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/MetadataProfile.Table.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfile.Table.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/MetadataProfile.Table.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfile.Table.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/MetadataProfiles.Page.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfiles.Page.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/MetadataProfiles.Page.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfiles.Page.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Processing.Codeunit.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al From 4f115fd00174b30ff784ab26b3d1fa992e0a311d Mon Sep 17 00:00:00 2001 From: geschwint Date: Tue, 11 Feb 2025 11:08:58 +0100 Subject: [PATCH 42/63] Refactor Objectnames - Code --- .../SignUpCompanyInformationExt.PageExt.al | 2 +- .../SignUpCompanyInformationExt.TableExt.al | 2 +- .../SignUpEDocSvcSupTypeExtPageExt.PageExt.al | 10 +- .../SignUpEDocSvcSupportedTypeExt.TableExt.al | 6 +- .../SignUpEDocumentExt.TableExt.al | 2 +- .../SignUpIntegrationEnumExt.EnumExt.al | 4 +- .../SignUpIntegrationImpl.Codeunit.al | 18 ++-- .../SignUpEDCOEdit.PermissionSet.al | 4 +- .../SignUpEDCOObjects.PermissionSet.al | 20 ++-- .../SignUpEDCORead.PermissionSet.al | 4 +- .../src/Setup/SignUpConnectionSetup.Table.al | 4 +- .../Setup/SignUpConnectionSetupCard.Page.al | 22 ++--- .../src/Setup/SignUpEnvironmentType.Enum.al | 2 +- .../app/src/SignUpAPIRequests.Codeunit.al | 94 +++++++++---------- .../app/src/SignUpAuthentication.Codeunit.al | 80 ++++++++-------- .../app/src/SignUpConnection.Codeunit.al | 54 +++++------ .../SignUp/app/src/SignUpHelpers.Codeunit.al | 2 +- .../app/src/SignUpMetadataProfile.Table.al | 2 +- .../app/src/SignUpMetadataProfiles.Page.al | 4 +- .../app/src/SignUpProcessing.Codeunit.al | 28 +++--- 20 files changed, 182 insertions(+), 182 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.PageExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.PageExt.al index 7b814a3494..ea4cb5b240 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.PageExt.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.PageExt.al @@ -6,7 +6,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.Foundation.Company; using Microsoft.eServices.EDocument; -pageextension 6381 CompanyInformationExt extends "Company Information" +pageextension 6381 SignUpCompanyInformationExt extends "Company Information" { layout { diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.TableExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.TableExt.al index f02165966f..84fa797c5e 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.TableExt.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.TableExt.al @@ -5,7 +5,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.Foundation.Company; -tableextension 6381 CompanyInformationExt extends "Company Information" +tableextension 6381 SignUpCompanyInformationExt extends "Company Information" { fields { diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcSupTypeExtPageExt.PageExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcSupTypeExtPageExt.PageExt.al index 5bfc5020a3..5e15aa9ff2 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcSupTypeExtPageExt.PageExt.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcSupTypeExtPageExt.PageExt.al @@ -6,7 +6,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.eServices.EDocument; -pageextension 6383 EDocServSuppTypeExtPageExt extends "E-Doc Service Supported Types" +pageextension 6383 SignUpEDocSvcSupTypeExtPageExt extends "E-Doc Service Supported Types" { layout @@ -43,9 +43,9 @@ pageextension 6383 EDocServSuppTypeExtPageExt extends "E-Doc Service Supported T trigger OnAction() var - Connection: Codeunit Connection; + SignUpConnection: Codeunit SignUpConnection; begin - Connection.UpdateMetadataProfile(); + SignUpConnection.UpdateMetadataProfile(); end; } } @@ -53,9 +53,9 @@ pageextension 6383 EDocServSuppTypeExtPageExt extends "E-Doc Service Supported T trigger OnOpenPage() var - Helpers: Codeunit Helpers; + SignUpHelpers: Codeunit SignUpHelpers; begin - ExFlowEInvoicingVisible := Helpers.IsExFlowEInvoicing(Rec.GetFilter("E-Document Service Code")); + ExFlowEInvoicingVisible := SignUpHelpers.IsExFlowEInvoicing(Rec.GetFilter("E-Document Service Code")); end; var diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcSupportedTypeExt.TableExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcSupportedTypeExt.TableExt.al index 5ec8cf37f4..8377a775ca 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcSupportedTypeExt.TableExt.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcSupportedTypeExt.TableExt.al @@ -6,7 +6,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.eServices.EDocument; -tableextension 6383 EDocServiceSupportedTypeExt extends "E-Doc. Service Supported Type" +tableextension 6383 SignUpEDocSvcSupportedTypeExt extends "E-Doc. Service Supported Type" { fields { @@ -15,7 +15,7 @@ tableextension 6383 EDocServiceSupportedTypeExt extends "E-Doc. Service Supporte Caption = 'Profile Id'; ToolTip = 'The unique identifier for the metadata profile.'; DataClassification = CustomerContent; - TableRelation = MetadataProfile; + TableRelation = SignUpMetadataProfile; BlankZero = true; trigger OnValidate() @@ -29,7 +29,7 @@ tableextension 6383 EDocServiceSupportedTypeExt extends "E-Doc. Service Supporte ToolTip = 'The common name of the metadata profile.'; FieldClass = FlowField; Editable = false; - CalcFormula = lookup(MetadataProfile."Profile Name" where("Profile ID" = field("Profile Id"))); + CalcFormula = lookup(SignUpMetadataProfile."Profile Name" where("Profile ID" = field("Profile Id"))); } } } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocumentExt.TableExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocumentExt.TableExt.al index 5ac14ecd52..45f308d810 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocumentExt.TableExt.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocumentExt.TableExt.al @@ -6,7 +6,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.eServices.EDocument; -tableextension 6382 EDocumentExt extends "E-Document" +tableextension 6382 SignUpEDocumentExt extends "E-Document" { fields { diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationEnumExt.EnumExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationEnumExt.EnumExt.al index 76b52fe1b4..cd2778e9c0 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationEnumExt.EnumExt.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationEnumExt.EnumExt.al @@ -6,11 +6,11 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.eServices.EDocument.Integration; using Microsoft.eServices.EDocument.Integration.Interfaces; -enumextension 6380 IntegrationEnumExt extends "Service Integration" +enumextension 6380 SignUpIntegrationEnumExt extends "Service Integration" { value(6380; "ExFlow E-Invoicing") { Caption = 'ExFlow E-Invoicing'; - Implementation = IDocumentSender = IntegrationImpl, IDocumentReceiver = IntegrationImpl; + Implementation = IDocumentSender = SignUpIntegrationImpl, IDocumentReceiver = SignUpIntegrationImpl; } } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationImpl.Codeunit.al index 59b59358eb..a5e5ad50c9 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationImpl.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationImpl.Codeunit.al @@ -11,37 +11,37 @@ using Microsoft.eServices.EDocument.Integration.Send; using Microsoft.eServices.EDocument.Integration.Receive; -codeunit 6386 IntegrationImpl implements IDocumentSender, IDocumentReceiver, IDocumentResponseHandler, IReceivedDocumentMarker +codeunit 6386 SignUpIntegrationImpl implements IDocumentSender, IDocumentReceiver, IDocumentResponseHandler, IReceivedDocumentMarker { Access = Internal; var - Processing: Codeunit Processing; + SignUpProcessing: Codeunit SignUpProcessing; #region IDocumentSender procedure Send(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; SendContext: Codeunit SendContext); var begin - this.Processing.Send(EDocument, EDocumentService, SendContext); + this.SignUpProcessing.Send(EDocument, EDocumentService, SendContext); end; #endregion #region IDocumentResponseHandler procedure GetResponse(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; SendContext: Codeunit SendContext): Boolean; begin - exit(this.Processing.GetResponse(EDocument, EDocumentService, SendContext)); + exit(this.SignUpProcessing.GetResponse(EDocument, EDocumentService, SendContext)); end; #endregion #region IDocumentReceiver procedure ReceiveDocuments(var EDocumentService: Record "E-Document Service"; DocumentsMetadataTempBlobList: Codeunit "Temp Blob List"; ReceiveContext: Codeunit ReceiveContext) begin - this.Processing.ReceiveDocuments(EDocumentService, DocumentsMetadataTempBlobList, ReceiveContext); + this.SignUpProcessing.ReceiveDocuments(EDocumentService, DocumentsMetadataTempBlobList, ReceiveContext); end; procedure DownloadDocument(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; DocumentMetadataTempBlob: Codeunit "Temp Blob"; ReceiveContext: Codeunit ReceiveContext) begin - this.Processing.DownloadDocument(EDocument, EDocumentService, DocumentMetadataTempBlob, ReceiveContext); + this.SignUpProcessing.DownloadDocument(EDocument, EDocumentService, DocumentMetadataTempBlob, ReceiveContext); end; #endregion @@ -49,7 +49,7 @@ codeunit 6386 IntegrationImpl implements IDocumentSender, IDocumentReceiver, IDo #region IReceivedDocumentMarker procedure MarkFetched(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; var DocumentTempBlob: Codeunit "Temp Blob"; ReceiveContext: Codeunit ReceiveContext) begin - this.Processing.MarkFetched(EDocument, EDocumentService, DocumentTempBlob, ReceiveContext); + this.SignUpProcessing.MarkFetched(EDocument, EDocumentService, DocumentTempBlob, ReceiveContext); end; #endregion @@ -57,12 +57,12 @@ codeunit 6386 IntegrationImpl implements IDocumentSender, IDocumentReceiver, IDo [EventSubscriber(ObjectType::Page, Page::"E-Document Service", OnBeforeOpenServiceIntegrationSetupPage, '', false, false)] local procedure OnBeforeOpenServiceIntegrationSetupPage(EDocumentService: Record "E-Document Service"; var IsServiceIntegrationSetupRun: Boolean) var - ConnectionSetupCard: Page ConnectionSetupCard; + SignUpConnectionSetupCard: Page SignUpConnectionSetupCard; begin if EDocumentService."Service Integration V2" <> EDocumentService."Service Integration V2"::"ExFlow E-Invoicing" then exit; - ConnectionSetupCard.RunModal(); + SignUpConnectionSetupCard.RunModal(); IsServiceIntegrationSetupRun := true; end; } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al index 5de0a205a2..8197ae8d43 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al @@ -10,7 +10,7 @@ permissionset 6382 SignUpEDCOEdit Assignable = false; Caption = 'SignUp E-Doc. Connector - Edit', MaxLength = 30; IncludedPermissionSets = SignUpEDCORead; - Permissions = tabledata ConnectionSetup = IMD, - tabledata MetadataProfile = IMD; + Permissions = tabledata SignUpConnectionSetup = IMD, + tabledata SignUpMetadataProfile = IMD; } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOObjects.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOObjects.PermissionSet.al index c87e75db81..d59f0bfbc4 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOObjects.PermissionSet.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOObjects.PermissionSet.al @@ -12,15 +12,15 @@ permissionset 6380 SignUpEDCOObjects Assignable = false; Caption = 'SignUp E-Doc. Connector - Obj.', MaxLength = 30; - Permissions = table ConnectionSetup = X, - table MetadataProfile = X, + Permissions = table SignUpConnectionSetup = X, + table SignUpMetadataProfile = X, table "E-Document Integration Log" = X, - page ConnectionSetupCard = X, - page MetadataProfiles = X, - codeunit APIRequests = X, - codeunit Authentication = X, - codeunit Connection = X, - codeunit Helpers = X, - codeunit IntegrationImpl = X, - codeunit Processing = X; + page SignUpConnectionSetupCard = X, + page SignUpMetadataProfiles = X, + codeunit SignUpAPIRequests = X, + codeunit SignUpAuthentication = X, + codeunit SignUpConnection = X, + codeunit SignUpHelpers = X, + codeunit SignUpIntegrationImpl = X, + codeunit SignUpProcessing = X; } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al index e598cf51fe..1c0a7c576b 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al @@ -12,8 +12,8 @@ permissionset 6381 SignUpEDCORead Assignable = false; Caption = 'SignUp E-Doc. Connector - Read', MaxLength = 30; IncludedPermissionSets = SignUpEDCOObjects; - Permissions = tabledata ConnectionSetup = R, - tabledata MetadataProfile = R, + Permissions = tabledata SignUpConnectionSetup = R, + tabledata SignUpMetadataProfile = R, tabledata "E-Document Integration Log" = rim; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al index cf5e1430d2..719e991325 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al @@ -4,7 +4,7 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -table 6381 ConnectionSetup +table 6381 SignUpConnectionSetup { Access = Internal; DataPerCompany = false; @@ -32,7 +32,7 @@ table 6381 ConnectionSetup Caption = 'Client Secret'; ToolTip = 'Specifies the client secret.'; } - field(5; "Environment Type"; Enum EnvironmentType) + field(5; "Environment Type"; Enum SignUpEnvironmentType) { Caption = 'Environment Type'; ToolTip = 'Specifies the environment type.'; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al index 6d540e18f4..39f0550383 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al @@ -8,11 +8,11 @@ using System.Telemetry; using Microsoft.Foundation.Company; using System.Environment; -page 6380 ConnectionSetupCard +page 6380 SignUpConnectionSetupCard { AdditionalSearchTerms = 'SignUp,electronic document,e-invoice,e-document,external,connection,connector'; PageType = Card; - SourceTable = ConnectionSetup; + SourceTable = SignUpConnectionSetup; ApplicationArea = Basic, Suite; UsageCategory = None; Caption = 'E-Document External Connection Setup'; @@ -35,7 +35,7 @@ page 6380 ConnectionSetupCard trigger OnValidate() begin - this.Authentication.StorageSet(Rec."Client ID", this.ClientID); + this.SignUpAuthentication.StorageSet(Rec."Client ID", this.ClientID); end; } field(ClientSecret; this.ClientSecret) @@ -62,7 +62,7 @@ page 6380 ConnectionSetupCard trigger OnValidate() begin - this.Authentication.StorageSet(Rec."Client Tenant", this.ClientTenant); + this.SignUpAuthentication.StorageSet(Rec."Client Tenant", this.ClientTenant); end; } field(RootID; this.RootID) @@ -75,7 +75,7 @@ page 6380 ConnectionSetupCard trigger OnValidate() begin - this.Authentication.StorageSet(Rec."Root App ID", this.RootID); + this.SignUpAuthentication.StorageSet(Rec."Root App ID", this.RootID); end; } field(RootSecret; this.RootSecret) @@ -101,7 +101,7 @@ page 6380 ConnectionSetupCard trigger OnValidate() begin - this.Authentication.StorageSet(Rec."Root Tenant", this.RootTenant); + this.SignUpAuthentication.StorageSet(Rec."Root Tenant", this.RootTenant); end; } field(RootUrl; Rec."Root Market URL") @@ -144,10 +144,10 @@ page 6380 ConnectionSetupCard trigger OnAction() begin - this.Authentication.CreateClientCredentials(); + this.SignUpAuthentication.CreateClientCredentials(); CurrPage.Update(); this.SetPageVariables(); - Hyperlink(this.Authentication.GetRootOnboardingUrl()); + Hyperlink(this.SignUpAuthentication.GetRootOnboardingUrl()); this.FeatureTelemetry.LogUptake('', this.ExternalServiceTok, Enum::"Feature Uptake Status"::"Set up"); end; } @@ -159,7 +159,7 @@ page 6380 ConnectionSetupCard EnvironmentInformation: Codeunit "Environment Information"; begin this.FieldsVisible := not EnvironmentInformation.IsSaaSInfrastructure(); - this.Authentication.InitConnectionSetup(); + this.SignUpAuthentication.InitConnectionSetup(); if Rec.Get() then ; this.SetPageVariables(); @@ -185,11 +185,11 @@ page 6380 ConnectionSetupCard [NonDebuggable] local procedure SaveSecret(var TokenKey: Guid; Value: SecretText) begin - this.Authentication.StorageSet(TokenKey, Value); + this.SignUpAuthentication.StorageSet(TokenKey, Value); end; var - Authentication: Codeunit Authentication; + SignUpAuthentication: Codeunit SignUpAuthentication; FeatureTelemetry: Codeunit "Feature Telemetry"; [NonDebuggable] ClientID, ClientSecret, ClientTenant, RootID, RootSecret, RootTenant : Text; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpEnvironmentType.Enum.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpEnvironmentType.Enum.al index a9ff9166b2..a4383312f7 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpEnvironmentType.Enum.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpEnvironmentType.Enum.al @@ -4,7 +4,7 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -enum 6380 EnvironmentType +enum 6380 SignUpEnvironmentType { Access = Internal; Caption = 'Environment Type', Locked = true; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAPIRequests.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAPIRequests.Codeunit.al index 35d65ae20d..23f7eaac67 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAPIRequests.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAPIRequests.Codeunit.al @@ -13,7 +13,7 @@ using System.Utilities; using System.Xml; using System.Environment; -codeunit 6389 APIRequests +codeunit 6389 SignUpAPIRequests { Access = Internal; InherentEntitlements = X; @@ -69,7 +69,7 @@ codeunit 6389 APIRequests /// True if successfully completed procedure SendFilePostRequest(var TempBlob: Codeunit "Temp Blob"; EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - ConnectionSetup: Record ConnectionSetup; + SignUpConnectionSetup: Record SignUpConnectionSetup; HttpContent: HttpContent; Payload: Text; begin @@ -78,11 +78,11 @@ codeunit 6389 APIRequests exit; this.InitRequest(HttpRequestMessage, HttpResponseMessage); - ConnectionSetup.SetLoadFields("Environment Type", "Service URL"); - this.GetSetup(ConnectionSetup); + SignUpConnectionSetup.SetLoadFields("Environment Type", "Service URL"); + this.GetSetup(SignUpConnectionSetup); - HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::POST, ConnectionSetup."Service URL" + '/api/v2/Peppol/outbox/transactions'); - this.PrepareContent(HttpContent, Payload, EDocument, ConnectionSetup); + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::POST, SignUpConnectionSetup."Service URL" + '/api/v2/Peppol/outbox/transactions'); + this.PrepareContent(HttpContent, Payload, EDocument, SignUpConnectionSetup); HttpRequestMessage.Content(HttpContent); exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); end; @@ -97,13 +97,13 @@ codeunit 6389 APIRequests /// True if successfully completed procedure GetSentDocumentStatus(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - ConnectionSetup: Record ConnectionSetup; + SignUpConnectionSetup: Record SignUpConnectionSetup; begin this.InitRequest(HttpRequestMessage, HttpResponseMessage); - ConnectionSetup.SetLoadFields("Service URL"); - this.GetSetup(ConnectionSetup); + SignUpConnectionSetup.SetLoadFields("Service URL"); + this.GetSetup(SignUpConnectionSetup); - HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::GET, ConnectionSetup."Service URL" + '/api/v2/Peppol/outbox/transactions/' + EDocument."SignUp Document Id" + '/status'); + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::GET, SignUpConnectionSetup."Service URL" + '/api/v2/Peppol/outbox/transactions/' + EDocument."SignUp Document Id" + '/status'); exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); end; @@ -117,13 +117,13 @@ codeunit 6389 APIRequests /// True if successfully completed procedure PatchDocument(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - ConnectionSetup: Record ConnectionSetup; + SignUpConnectionSetup: Record SignUpConnectionSetup; begin this.InitRequest(HttpRequestMessage, HttpResponseMessage); - ConnectionSetup.SetLoadFields("Service URL"); - this.GetSetup(ConnectionSetup); + SignUpConnectionSetup.SetLoadFields("Service URL"); + this.GetSetup(SignUpConnectionSetup); - HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::PATCH, ConnectionSetup."Service URL" + '/api/v2/Peppol/outbox/transactions/' + EDocument."SignUp Document Id" + '/acknowledge'); + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::PATCH, SignUpConnectionSetup."Service URL" + '/api/v2/Peppol/outbox/transactions/' + EDocument."SignUp Document Id" + '/acknowledge'); exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); end; @@ -136,13 +136,13 @@ codeunit 6389 APIRequests /// True if successfully completed procedure GetReceivedDocumentsRequest(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - ConnectionSetup: Record ConnectionSetup; + SignUpConnectionSetup: Record SignUpConnectionSetup; begin this.InitRequest(HttpRequestMessage, HttpResponseMessage); - ConnectionSetup.SetLoadFields("Service URL"); - this.GetSetup(ConnectionSetup); + SignUpConnectionSetup.SetLoadFields("Service URL"); + this.GetSetup(SignUpConnectionSetup); - HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::GET, ConnectionSetup."Service URL" + '/api/v2/Peppol/inbox/transactions?partyId=' + this.SenderReceiverPrefixTxt + this.GetCompanyId()); + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::GET, SignUpConnectionSetup."Service URL" + '/api/v2/Peppol/inbox/transactions?partyId=' + this.SenderReceiverPrefixTxt + this.GetCompanyId()); exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); end; @@ -156,13 +156,13 @@ codeunit 6389 APIRequests /// True if successfully completed procedure GetTargetDocumentRequest(DocumentId: Text; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - ConnectionSetup: Record ConnectionSetup; + SignUpConnectionSetup: Record SignUpConnectionSetup; begin this.InitRequest(HttpRequestMessage, HttpResponseMessage); - ConnectionSetup.SetLoadFields("Service URL"); - this.GetSetup(ConnectionSetup); + SignUpConnectionSetup.SetLoadFields("Service URL"); + this.GetSetup(SignUpConnectionSetup); - HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::GET, ConnectionSetup."Service URL" + '/api/v2/Peppol/inbox/transactions/' + DocumentId); + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::GET, SignUpConnectionSetup."Service URL" + '/api/v2/Peppol/inbox/transactions/' + DocumentId); exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); end; @@ -177,13 +177,13 @@ codeunit 6389 APIRequests /// True if successfully completed procedure PatchReceivedDocument(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - ConnectionSetup: Record ConnectionSetup; + SignUpConnectionSetup: Record SignUpConnectionSetup; begin this.InitRequest(HttpRequestMessage, HttpResponseMessage); - ConnectionSetup.SetLoadFields("Service URL"); - this.GetSetup(ConnectionSetup); + SignUpConnectionSetup.SetLoadFields("Service URL"); + this.GetSetup(SignUpConnectionSetup); - HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::PATCH, ConnectionSetup."Service URL" + '/api/v2/Peppol/inbox/transactions/' + EDocument."SignUp Document Id" + '/acknowledge'); + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::PATCH, SignUpConnectionSetup."Service URL" + '/api/v2/Peppol/inbox/transactions/' + EDocument."SignUp Document Id" + '/acknowledge'); exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage)); end; @@ -196,13 +196,13 @@ codeunit 6389 APIRequests /// Returns true if the metadata profiles were successfully fetched, otherwise false. procedure FetchMetaDataProfiles(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - ConnectionSetup: Record ConnectionSetup; + SignUpConnectionSetup: Record SignUpConnectionSetup; begin this.InitRequest(HttpRequestMessage, HttpResponseMessage); - ConnectionSetup.SetLoadFields("Service URL"); - this.GetSetup(ConnectionSetup); + SignUpConnectionSetup.SetLoadFields("Service URL"); + this.GetSetup(SignUpConnectionSetup); - HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::GET, ConnectionSetup."Service URL" + '/api/v2/Peppol/metadataprofile'); + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::GET, SignUpConnectionSetup."Service URL" + '/api/v2/Peppol/metadataprofile'); exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage, false)); end; @@ -215,11 +215,11 @@ codeunit 6389 APIRequests /// True if successfully completed procedure GetMarketPlaceCredentials(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - Authentication: Codeunit Authentication; + SignUpAuthentication: Codeunit SignUpAuthentication; begin this.InitRequest(HttpRequestMessage, HttpResponseMessage); - HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::POST, Authentication.GetRootUrl() + '/api/Registration/init?EntraTenantId=' + Authentication.GetBCInstanceIdentifier() + '&EnvironmentName=' + this.GetEnvironmentName()); + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::POST, SignUpAuthentication.GetRootUrl() + '/api/Registration/init?EntraTenantId=' + SignUpAuthentication.GetBCInstanceIdentifier() + '&EnvironmentName=' + this.GetEnvironmentName()); exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage, true)); end; @@ -242,14 +242,14 @@ codeunit 6389 APIRequests Clear(HttpResponseMessage); end; - local procedure GetSetup(var ConnectionSetup: Record ConnectionSetup) + local procedure GetSetup(var SignUpConnectionSetup: Record SignUpConnectionSetup) var MissingSetupErrorInfo: ErrorInfo; begin - if not IsNullGuid(ConnectionSetup.SystemId) then + if not IsNullGuid(SignUpConnectionSetup.SystemId) then exit; - if not ConnectionSetup.Get() then begin + if not SignUpConnectionSetup.Get() then begin MissingSetupErrorInfo.Title := this.MissingSetupErr; MissingSetupErrorInfo.Message := this.MissingSetupMessageErr; MissingSetupErrorInfo.PageNo := Page::"E-Document Services"; @@ -278,13 +278,13 @@ codeunit 6389 APIRequests exit(this.CompanyId); end; - local procedure PrepareContent(var HttpContent: HttpContent; Payload: Text; EDocument: Record "E-Document"; ConnectionSetup: Record ConnectionSetup) + local procedure PrepareContent(var HttpContent: HttpContent; Payload: Text; EDocument: Record "E-Document"; SignUpConnectionSetup: Record SignUpConnectionSetup) var ContentText: Text; HttpHeaders: HttpHeaders; begin Clear(HttpContent); - ContentText := this.PrepareContentForSend(EDocument, this.GetCompanyId(), this.GetSenderCountryCode(), Payload, ConnectionSetup."Environment Type"); + ContentText := this.PrepareContentForSend(EDocument, this.GetCompanyId(), this.GetSenderCountryCode(), Payload, SignUpConnectionSetup."Environment Type"); HttpContent.WriteFrom(ContentText); HttpContent.GetHeaders(HttpHeaders); if HttpHeaders.Contains(this.ContentTypeTxt) then @@ -299,15 +299,15 @@ codeunit 6389 APIRequests local procedure SendRequest(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage; RootRequest: Boolean): Boolean var - Authentication: Codeunit Authentication; + SignUpAuthentication: Codeunit SignUpAuthentication; HttpClient: HttpClient; HttpHeaders: HttpHeaders; begin HttpRequestMessage.GetHeaders(HttpHeaders); if RootRequest then - HttpHeaders.Add(this.AuthorizationTxt, Authentication.GetRootBearerAuthToken()) + HttpHeaders.Add(this.AuthorizationTxt, SignUpAuthentication.GetRootBearerAuthToken()) else - HttpHeaders.Add(this.AuthorizationTxt, Authentication.GetBearerAuthToken()); + HttpHeaders.Add(this.AuthorizationTxt, SignUpAuthentication.GetBearerAuthToken()); exit(HttpClient.Send(HttpRequestMessage, HttpResponseMessage)); end; @@ -371,12 +371,12 @@ codeunit 6389 APIRequests exit(CompanyInformation."Country/Region Code"); end; - local procedure PrepareContentForSend(EDocument: Record "E-Document"; SendingCompanyID: Text; SenderCountryCode: Text; Payload: Text; SendMode: Enum EnvironmentType): Text + local procedure PrepareContentForSend(EDocument: Record "E-Document"; SendingCompanyID: Text; SenderCountryCode: Text; Payload: Text; SendMode: Enum SignUpEnvironmentType): Text var EDocumentService: Record "E-Document Service"; EDocumentServiceStatus: Record "E-Document Service Status"; EDocServiceSupportedType: Record "E-Doc. Service Supported Type"; - MetadataProfile: Record MetadataProfile; + SignUpMetadataProfile: Record SignUpMetadataProfile; EDocumentHelper: Codeunit "E-Document Helper"; Base64Convert: Codeunit "Base64 Convert"; JsonObject: JsonObject; @@ -394,7 +394,7 @@ codeunit 6389 APIRequests EDocServiceSupportedType.SetRange("Source Document Type", EDocument."Document Type"); if not EDocServiceSupportedType.FindFirst() then Error(this.UnSupportedDocumentTypeProfileMissingTxt, EDocument."Document Type", EDocServiceSupportedType.FieldCaption("Profile Id"), EDocumentService.TableCaption, this.SupportedDocumentTypesTxt); - if (EDocServiceSupportedType."Profile Id" = 0) or (not MetadataProfile.Get(EDocServiceSupportedType."Profile Id")) then + if (EDocServiceSupportedType."Profile Id" = 0) or (not SignUpMetadataProfile.Get(EDocServiceSupportedType."Profile Id")) then Error(this.UnSupportedDocumentTypeProfileMissingTxt, EDocument."Document Type", EDocServiceSupportedType.FieldCaption("Profile Id"), EDocumentService.TableCaption, this.SupportedDocumentTypesTxt); JsonObject.Add(this.DocumentTypeTxt, this.GetDocumentType(EDocument)); @@ -404,10 +404,10 @@ codeunit 6389 APIRequests if EDocument.Direction = EDocument.Direction::Incoming then JsonObject.Add(this.DocumentIdTxt, this.ApplicationResponseTxt) else - JsonObject.Add(this.DocumentIdTxt, MetadataProfile."Document Identifier Value"); - JsonObject.Add(this.DocumentIdSchemeTxt, MetadataProfile."Document Identifier Scheme"); - JsonObject.Add(this.ProcessIdTxt, MetadataProfile."Process Identifier Value"); - JsonObject.Add(this.ProcessIdSchemeTxt, MetadataProfile."Process Identifier Scheme"); + JsonObject.Add(this.DocumentIdTxt, SignUpMetadataProfile."Document Identifier Value"); + JsonObject.Add(this.DocumentIdSchemeTxt, SignUpMetadataProfile."Document Identifier Scheme"); + JsonObject.Add(this.ProcessIdTxt, SignUpMetadataProfile."Process Identifier Value"); + JsonObject.Add(this.ProcessIdSchemeTxt, SignUpMetadataProfile."Process Identifier Scheme"); JsonObject.Add(this.SendModeTxt, Format(SendMode)); JsonObject.Add(this.DocumentTxt, Base64Convert.ToBase64(Payload)); JsonObject.WriteTo(ContentText); diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al index f95638b689..af28d075ab 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al @@ -10,7 +10,7 @@ using System.Security.Authentication; using System.Azure.KeyVault; using System.Environment; -codeunit 6390 Authentication +codeunit 6390 SignUpAuthentication { Access = Internal; InherentEntitlements = X; @@ -18,8 +18,8 @@ codeunit 6390 Authentication #region variables var - ConnectionSetup: Record ConnectionSetup; - HelpersImpl: Codeunit Helpers; + SignUpConnectionSetup: Record SignUpConnectionSetup; + SignUpHelpersImpl: Codeunit SignUpHelpers; BearerTxt: Label 'Bearer %1', Comment = '%1 = text value', Locked = true; AuthURLTxt: Label 'https://login.microsoftonline.com/%1/oauth2/token', Comment = '%1 Entra Tenant Id', Locked = true; AuthTemplateTxt: Label 'grant_type=client_credentials&client_id=%1&client_secret=%2&resource=%3', Locked = true; @@ -50,14 +50,14 @@ codeunit 6390 Authentication /// procedure InitConnectionSetup() begin - if this.ConnectionSetup.Get() then + if this.SignUpConnectionSetup.Get() then exit; - this.ConnectionSetup."Authentication URL" := this.AuthURLTxt; - this.ConnectionSetup."Service URL" := this.GetServiceApi(); - this.StorageSet(this.ConnectionSetup."Root Tenant", this.GetRootTenant()); - this.StorageSet(this.ConnectionSetup."Client Tenant", this.GetClientTenant()); - this.ConnectionSetup.Insert(); + this.SignUpConnectionSetup."Authentication URL" := this.AuthURLTxt; + this.SignUpConnectionSetup."Service URL" := this.GetServiceApi(); + this.StorageSet(this.SignUpConnectionSetup."Root Tenant", this.GetRootTenant()); + this.StorageSet(this.SignUpConnectionSetup."Client Tenant", this.GetClientTenant()); + this.SignUpConnectionSetup.Insert(); end; /// @@ -86,8 +86,8 @@ codeunit 6390 Authentication if not HttpResponseMessage.Content.ReadAs(Response) then exit; - ClientId := this.HelpersImpl.GetJsonValueFromText(Response, this.ClientIdTxt); - ClientSecret := this.HelpersImpl.GetJsonValueFromText(Response, this.ClientSecretTxt); + ClientId := this.SignUpHelpersImpl.GetJsonValueFromText(Response, this.ClientIdTxt); + ClientSecret := this.SignUpHelpersImpl.GetJsonValueFromText(Response, this.ClientSecretTxt); if (ClientId <> '') and (not ClientSecret.IsEmpty()) then this.SaveClientCredentials(ClientId, ClientSecret); @@ -166,11 +166,11 @@ codeunit 6390 Authentication if this.FetchSecretFromKeyVault(this.SignupRootUrlTxt, ReturnValue) then exit; - if not this.ConnectionSetup.GetSetup() then + if not this.SignUpConnectionSetup.GetSetup() then exit; - this.ConnectionSetup.TestField("Root Market URL"); - ReturnValue := this.ConnectionSetup."Root Market URL"; + this.SignUpConnectionSetup.TestField("Root Market URL"); + ReturnValue := this.SignUpConnectionSetup."Root Market URL"; end; #endregion @@ -183,7 +183,7 @@ codeunit 6390 Authentication begin AccessToken := this.StorageGet(this.SignUpAccessTokenKeyTxt, DataScope::Company); - if this.HelpersImpl.IsTokenValid(AccessToken) then + if this.SignUpHelpersImpl.IsTokenValid(AccessToken) then exit; if not this.RefreshAccessToken(HttpError) then @@ -200,27 +200,27 @@ codeunit 6390 Authentication local procedure SaveClientCredentials(ClientId: Text; ClientSecret: SecretText) begin - Clear(this.ConnectionSetup); + Clear(this.SignUpConnectionSetup); - this.ConnectionSetup.GetSetup(); - this.StorageSet(this.ConnectionSetup."Client ID", ClientId); - this.StorageSet(this.ConnectionSetup."Client Secret", ClientSecret); - this.ConnectionSetup.Modify(); + this.SignUpConnectionSetup.GetSetup(); + this.StorageSet(this.SignUpConnectionSetup."Client ID", ClientId); + this.StorageSet(this.SignUpConnectionSetup."Client Secret", ClientSecret); + this.SignUpConnectionSetup.Modify(); - Clear(this.ConnectionSetup); + Clear(this.SignUpConnectionSetup); end; [NonDebuggable] local procedure GetClientCredentials(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - APIRequests: Codeunit APIRequests; + SignUpAPIRequests: Codeunit SignUpAPIRequests; begin - APIRequests.GetMarketPlaceCredentials(HttpRequestMessage, HttpResponseMessage); + SignUpAPIRequests.GetMarketPlaceCredentials(HttpRequestMessage, HttpResponseMessage); if not HttpResponseMessage.IsSuccessStatusCode() then exit; - exit(this.HelpersImpl.ParseJsonString(HttpResponseMessage.Content) <> ''); + exit(this.SignUpHelpersImpl.ParseJsonString(HttpResponseMessage.Content) <> ''); end; [NonDebuggable] @@ -242,11 +242,11 @@ codeunit 6390 Authentication ModuleDataScope: DataScope; begin ModuleDataScope := ModuleDataScope::Module; - this.ConnectionSetup.GetSetup(); + this.SignUpConnectionSetup.GetSetup(); exit(this.GetAccessToken(AccessToken, this.GetRootId(), this.GetRootSecret(), - this.StorageGetText(this.ConnectionSetup."Root Tenant", ModuleDataScope))); + this.StorageGetText(this.SignUpConnectionSetup."Root Tenant", ModuleDataScope))); end; [NonDebuggable] @@ -255,11 +255,11 @@ codeunit 6390 Authentication ModuleDataScope: DataScope; begin ModuleDataScope := ModuleDataScope::Module; - this.ConnectionSetup.GetSetup(); + this.SignUpConnectionSetup.GetSetup(); - exit(this.GetAccessToken(AccessToken, this.StorageGetText(this.ConnectionSetup."Client ID", ModuleDataScope), - this.StorageGet(this.ConnectionSetup."Client Secret", ModuleDataScope), - this.StorageGetText(this.ConnectionSetup."Client Tenant", ModuleDataScope))); + exit(this.GetAccessToken(AccessToken, this.StorageGetText(this.SignUpConnectionSetup."Client ID", ModuleDataScope), + this.StorageGet(this.SignUpConnectionSetup."Client Secret", ModuleDataScope), + this.StorageGetText(this.SignUpConnectionSetup."Client Tenant", ModuleDataScope))); end; [NonDebuggable] @@ -270,16 +270,16 @@ codeunit 6390 Authentication Response: Text; begin Clear(AccessToken); - this.ConnectionSetup.GetSetup(); - this.ConnectionSetup.TestField("Authentication URL"); + this.SignUpConnectionSetup.GetSetup(); + this.SignUpConnectionSetup.TestField("Authentication URL"); HttpRequestMessage := this.PrepareRequest(SecretStrSubstNo(this.AuthTemplateTxt, TypeHelper.UriEscapeDataString(ClientId), ClientSecret, TypeHelper.UriEscapeDataString(ClientId)), - StrSubstNo(this.ConnectionSetup."Authentication URL", ClientTenant)); + StrSubstNo(this.SignUpConnectionSetup."Authentication URL", ClientTenant)); if not this.SendRequest(HttpRequestMessage, Response) then exit; - AccessToken := this.HelpersImpl.GetJsonValueFromText(Response, this.AccessTokenTxt); + AccessToken := this.SignUpHelpersImpl.GetJsonValueFromText(Response, this.AccessTokenTxt); exit(not AccessToken.IsEmpty()); end; @@ -382,11 +382,11 @@ codeunit 6390 Authentication if this.FetchSecretFromKeyVault(this.SignUpRootIdTxt, ReturnValue) then exit; - if not this.ConnectionSetup.GetSetup() then + if not this.SignUpConnectionSetup.GetSetup() then exit; - this.ConnectionSetup.TestField("Root App ID"); - ReturnValue := this.StorageGetText(this.ConnectionSetup."Root App ID", DataScope::Module); + this.SignUpConnectionSetup.TestField("Root App ID"); + ReturnValue := this.StorageGetText(this.SignUpConnectionSetup."Root App ID", DataScope::Module); end; local procedure GetRootSecret() ReturnValue: SecretText @@ -394,11 +394,11 @@ codeunit 6390 Authentication if this.FetchSecretFromKeyVault(this.SignUpRootSecretTxt, ReturnValue) then exit; - if not this.ConnectionSetup.GetSetup() then + if not this.SignUpConnectionSetup.GetSetup() then exit; - this.ConnectionSetup.TestField("Root Secret"); - ReturnValue := this.StorageGet(this.ConnectionSetup."Root Secret", DataScope::Module); + this.SignUpConnectionSetup.TestField("Root Secret"); + ReturnValue := this.StorageGet(this.SignUpConnectionSetup."Root Secret", DataScope::Module); end; [NonDebuggable] diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpConnection.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpConnection.Codeunit.al index 1382272ac5..a43e301755 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpConnection.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpConnection.Codeunit.al @@ -7,7 +7,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.EServices.EDocument; using System.Utilities; -codeunit 6391 Connection +codeunit 6391 SignUpConnection { Access = Internal; InherentEntitlements = X; @@ -17,8 +17,8 @@ codeunit 6391 Connection #region variables var - APIRequests: Codeunit APIRequests; - HelpersImpl: Codeunit Helpers; + SignUpAPIRequests: Codeunit SignUpAPIRequests; + SignUpHelpersImpl: Codeunit SignUpHelpers; UnsuccessfulResponseErr: Label 'There was an error sending the request. Response code: %1 and error message: %2', Comment = '%1 - http response status code, e.g. 400, %2- error message'; EnvironmentBlocksErr: Label 'The request to send documents has been blocked. To resolve the problem, enable outgoing HTTP requests for the E-Document apps on the Extension Management page.'; FourZeroThreeErr: Label 'You do not have a valid subscription.'; @@ -45,7 +45,7 @@ codeunit 6391 Connection /// True - if completed successfully procedure SendFilePostRequest(var TempBlob: Codeunit "Temp Blob"; var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean begin - this.APIRequests.SendFilePostRequest(TempBlob, EDocument, HttpRequestMessage, HttpResponseMessage); + this.SignUpAPIRequests.SendFilePostRequest(TempBlob, EDocument, HttpRequestMessage, HttpResponseMessage); exit(this.CheckIfSuccessfulRequest(EDocument, HttpResponseMessage)); end; @@ -58,7 +58,7 @@ codeunit 6391 Connection /// True - if completed successfully procedure CheckDocumentStatus(var EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean begin - this.APIRequests.GetSentDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage); + this.SignUpAPIRequests.GetSentDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage); exit(this.CheckIfSuccessfulRequest(EDocument, HttpResponseMessage)); end; @@ -70,7 +70,7 @@ codeunit 6391 Connection /// True - if completed successfully procedure GetReceivedDocuments(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean begin - if not this.APIRequests.GetReceivedDocumentsRequest(HttpRequestMessage, HttpResponseMessage) then + if not this.SignUpAPIRequests.GetReceivedDocumentsRequest(HttpRequestMessage, HttpResponseMessage) then exit; if not HttpResponseMessage.IsSuccessStatusCode() then @@ -79,7 +79,7 @@ codeunit 6391 Connection else exit; - exit(this.HelpersImpl.ParseJsonString(HttpResponseMessage.Content) <> ''); + exit(this.SignUpHelpersImpl.ParseJsonString(HttpResponseMessage.Content) <> ''); end; /// @@ -91,7 +91,7 @@ codeunit 6391 Connection /// True - if completed successfully procedure GetTargetDocumentRequest(DocumentId: Text; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean begin - this.APIRequests.GetTargetDocumentRequest(DocumentId, HttpRequestMessage, HttpResponseMessage); + this.SignUpAPIRequests.GetTargetDocumentRequest(DocumentId, HttpRequestMessage, HttpResponseMessage); exit(HttpResponseMessage.IsSuccessStatusCode()); end; @@ -104,7 +104,7 @@ codeunit 6391 Connection /// True - if completed successfully procedure RemoveDocumentFromReceived(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean begin - this.APIRequests.PatchReceivedDocument(EDocument, HttpRequestMessage, HttpResponseMessage); + this.SignUpAPIRequests.PatchReceivedDocument(EDocument, HttpRequestMessage, HttpResponseMessage); exit(HttpResponseMessage.IsSuccessStatusCode()); end; @@ -118,12 +118,12 @@ codeunit 6391 Connection /// procedure UpdateMetadataProfile() var - MetadataProfile: Record MetadataProfile; + SignUpMetadataProfile: Record SignUpMetadataProfile; HttpRequestMessage: HttpRequestMessage; HttpResponseMessage: HttpResponseMessage; MetadataProfileContent: Text; begin - this.APIRequests.FetchMetaDataProfiles(HttpRequestMessage, HttpResponseMessage); + this.SignUpAPIRequests.FetchMetaDataProfiles(HttpRequestMessage, HttpResponseMessage); if not HttpResponseMessage.IsSuccessStatusCode() then begin if HttpResponseMessage.HttpStatusCode = 403 then Message(this.FourZeroThreeErr) @@ -135,11 +135,11 @@ codeunit 6391 Connection if not HttpResponseMessage.Content.ReadAs(MetadataProfileContent) then exit; - MetadataProfile.Reset(); - MetadataProfile.DeleteAll(); + SignUpMetadataProfile.Reset(); + SignUpMetadataProfile.DeleteAll(); - if this.MetadataProfileJsonToTable(MetadataProfileContent, MetadataProfile) then - this.DeleteUnusedMetadataProfileReferenses(MetadataProfile); + if this.MetadataProfileJsonToTable(MetadataProfileContent, SignUpMetadataProfile) then + this.DeleteUnusedMetadataProfileReferenses(SignUpMetadataProfile); end; #endregion @@ -160,7 +160,7 @@ codeunit 6391 Connection EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, StrSubstNo(this.UnsuccessfulResponseErr, HttpResponseMessage.HttpStatusCode, HttpResponseMessage.ReasonPhrase)); end; - local procedure MetadataProfileJsonToTable(JsonText: Text; var MetadataProfile: Record MetadataProfile): Boolean + local procedure MetadataProfileJsonToTable(JsonText: Text; var SignUpMetadataProfile: Record SignUpMetadataProfile): Boolean var JsonObject, ProfileJsonObject, ProcessIdentifierJsonObject, DocumentIdentifierJsonObject : JsonObject; JsonArray: JsonArray; @@ -173,41 +173,41 @@ codeunit 6391 Connection foreach JsonToken in JsonArray do if JsonToken.IsObject() then begin ProfileJsonObject := JsonToken.AsObject(); - MetadataProfile.Init(); + SignUpMetadataProfile.Init(); if ProfileJsonObject.SelectToken(this.ProfileIdLbl, JsonToken) then - MetadataProfile."Profile ID" := this.GetJsonValueAsInteger(JsonToken.AsValue()); + SignUpMetadataProfile."Profile ID" := this.GetJsonValueAsInteger(JsonToken.AsValue()); if ProfileJsonObject.SelectToken(this.CommonNameLbl, JsonToken) then - MetadataProfile."Profile Name" := CopyStr(this.GetJsonValueAsText(JsonToken.AsValue()), 1, MaxStrLen(MetadataProfile."Profile Name")); + SignUpMetadataProfile."Profile Name" := CopyStr(this.GetJsonValueAsText(JsonToken.AsValue()), 1, MaxStrLen(SignUpMetadataProfile."Profile Name")); if ProfileJsonObject.SelectToken(this.ProcessIdentifierLbl, JsonToken) then begin ProcessIdentifierJsonObject := JsonToken.AsObject(); if ProcessIdentifierJsonObject.SelectToken(this.SchemeLbl, JsonToken) then - MetadataProfile."Process Identifier Scheme" := CopyStr(this.GetJsonValueAsText(JsonToken.AsValue()), 1, MaxStrLen(MetadataProfile."Process Identifier Scheme")); + SignUpMetadataProfile."Process Identifier Scheme" := CopyStr(this.GetJsonValueAsText(JsonToken.AsValue()), 1, MaxStrLen(SignUpMetadataProfile."Process Identifier Scheme")); if ProcessIdentifierJsonObject.SelectToken(this.ValueLbl, JsonToken) then - MetadataProfile."Process Identifier Value" := CopyStr(this.GetJsonValueAsText(JsonToken.AsValue()), 1, MaxStrLen(MetadataProfile."Process Identifier Value")); + SignUpMetadataProfile."Process Identifier Value" := CopyStr(this.GetJsonValueAsText(JsonToken.AsValue()), 1, MaxStrLen(SignUpMetadataProfile."Process Identifier Value")); end; if ProfileJsonObject.SelectToken(this.DocumentIdentifierLbl, JsonToken) then begin DocumentIdentifierJsonObject := JsonToken.AsObject(); if DocumentIdentifierJsonObject.SelectToken(this.SchemeLbl, JsonToken) then - MetadataProfile."Document Identifier Scheme" := CopyStr(this.GetJsonValueAsText(JsonToken.AsValue()), 1, MaxStrLen(MetadataProfile."Document Identifier Scheme")); + SignUpMetadataProfile."Document Identifier Scheme" := CopyStr(this.GetJsonValueAsText(JsonToken.AsValue()), 1, MaxStrLen(SignUpMetadataProfile."Document Identifier Scheme")); if DocumentIdentifierJsonObject.SelectToken(this.ValueLbl, JsonToken) then - MetadataProfile."Document Identifier Value" := CopyStr(this.GetJsonValueAsText(JsonToken.AsValue()), 1, MaxStrLen(MetadataProfile."Document Identifier Value")); + SignUpMetadataProfile."Document Identifier Value" := CopyStr(this.GetJsonValueAsText(JsonToken.AsValue()), 1, MaxStrLen(SignUpMetadataProfile."Document Identifier Value")); end; - MetadataProfile.Insert(); + SignUpMetadataProfile.Insert(); end; end; - exit(not MetadataProfile.IsEmpty()); + exit(not SignUpMetadataProfile.IsEmpty()); end; - local procedure DeleteUnusedMetadataProfileReferenses(var MetadataProfile: Record MetadataProfile) + local procedure DeleteUnusedMetadataProfileReferenses(var SignUpMetadataProfile: Record SignUpMetadataProfile) var EDocumentService: Record "E-Document Service"; EDocServiceSupportedType: Record "E-Doc. Service Supported Type"; @@ -222,7 +222,7 @@ codeunit 6391 Connection if not EDocServiceSupportedType.FindSet() then repeat if EDocServiceSupportedType."Profile Id" <> 0 then - if not MetadataProfile.Get(EDocServiceSupportedType."Profile Id") then begin + if not SignUpMetadataProfile.Get(EDocServiceSupportedType."Profile Id") then begin EDocServiceSupportedType."Profile Id" := 0; EDocServiceSupportedType.Modify(); end; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpHelpers.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpHelpers.Codeunit.al index e6c72f6d98..0b6a4feef2 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpHelpers.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpHelpers.Codeunit.al @@ -9,7 +9,7 @@ using Microsoft.Utilities; using System.Integration; using Microsoft.eServices.EDocument; -codeunit 6385 Helpers +codeunit 6385 SignUpHelpers { Access = Internal; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfile.Table.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfile.Table.al index 884e563a32..2d9627ae25 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfile.Table.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfile.Table.al @@ -4,7 +4,7 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -table 6382 MetadataProfile +table 6382 SignUpMetadataProfile { Caption = 'MetadataProfile'; Access = Internal; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfiles.Page.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfiles.Page.al index 2415c1ca71..2fcd343821 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfiles.Page.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfiles.Page.al @@ -4,10 +4,10 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -page 6381 MetadataProfiles +page 6381 SignUpMetadataProfiles { PageType = List; - SourceTable = MetadataProfile; + SourceTable = SignUpMetadataProfile; ApplicationArea = All; UsageCategory = None; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al index cdae0fc217..0de2055605 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al @@ -10,7 +10,7 @@ using System.Utilities; using Microsoft.eServices.EDocument.Integration.Send; using Microsoft.eServices.EDocument.Integration.Receive; -codeunit 6383 Processing +codeunit 6383 SignUpProcessing { Access = Internal; InherentEntitlements = X; @@ -23,8 +23,8 @@ codeunit 6383 Processing #region variables var - Connection: Codeunit Connection; - HelpersImpl: Codeunit Helpers; + SignUpConnection: Codeunit SignUpConnection; + SignUpHelpersImpl: Codeunit SignUpHelpers; EDocumentErrorHelper: Codeunit "E-Document Error Helper"; CouldNotRetrieveDocumentErr: Label 'Could not retrieve document with id: %1 from the service', Comment = '%1 - Document ID'; CouldNotSendPatchErr: Label 'Could not Send Patch for document with id: %1', Comment = '%1 - Document ID'; @@ -97,7 +97,7 @@ codeunit 6383 Processing if EDocument."SignUp Document Id" = '' then exit; - if not this.Connection.CheckDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage) then + if not this.SignUpConnection.CheckDocumentStatus(EDocument, HttpRequestMessage, HttpResponseMessage) then exit; SendContext.Http().SetHttpRequestMessage(HttpRequestMessage); @@ -143,7 +143,7 @@ codeunit 6383 Processing JsonToken: JsonToken; ReceiveSucced: Boolean; begin - ReceiveSucced := this.Connection.GetReceivedDocuments(HttpRequestMessage, HttpResponseMessage); + ReceiveSucced := this.SignUpConnection.GetReceivedDocuments(HttpRequestMessage, HttpResponseMessage); ReceiveContext.Http().SetHttpRequestMessage(HttpRequestMessage); ReceiveContext.Http().SetHttpResponseMessage(HttpResponseMessage); if not ReceiveSucced then @@ -197,7 +197,7 @@ codeunit 6383 Processing Clear(ContentData); this.OnBeforeGetTargetDocumentRequest(); - this.Connection.GetTargetDocumentRequest(EDocument."SignUp Document Id", HttpRequestMessage, HttpResponseMessage); + this.SignUpConnection.GetTargetDocumentRequest(EDocument."SignUp Document Id", HttpRequestMessage, HttpResponseMessage); ReceiveContext.Http().SetHttpRequestMessage(HttpRequestMessage); ReceiveContext.Http().SetHttpResponseMessage(HttpResponseMessage); @@ -219,7 +219,7 @@ codeunit 6383 Processing HttpResponseMessage: HttpResponseMessage; begin this.OnBeforeMarkFetched(); - this.Connection.RemoveDocumentFromReceived(EDocument, HttpRequestMessage, HttpResponseMessage); + this.SignUpConnection.RemoveDocumentFromReceived(EDocument, HttpRequestMessage, HttpResponseMessage); ReceiveContext.Http().SetHttpRequestMessage(HttpRequestMessage); ReceiveContext.Http().SetHttpResponseMessage(HttpResponseMessage); @@ -266,7 +266,7 @@ codeunit 6383 Processing Status := ''; StatusDescription := ''; - Result := this.HelpersImpl.ParseJsonString(HttpContentResponse); + Result := this.SignUpHelpersImpl.ParseJsonString(HttpContentResponse); if Result = '' then exit; @@ -313,15 +313,15 @@ codeunit 6383 Processing local procedure SendEDocument(EDocument: Record "E-Document"; TempBlob: Codeunit "Temp Blob"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage); begin - this.Connection.SendFilePostRequest(TempBlob, EDocument, HttpRequestMessage, HttpResponseMessage); + this.SignUpConnection.SendFilePostRequest(TempBlob, EDocument, HttpRequestMessage, HttpResponseMessage); this.SetEDocumentFileID(EDocument."Entry No", this.ParseSendFileResponse(HttpResponseMessage.Content)); end; local procedure ParseReceivedDocument(InputTxt: Text; var DocumentId: Text): Boolean var - Helpers: Codeunit Helpers; + SignUpHelpers: Codeunit SignUpHelpers; begin - DocumentId := Helpers.GetJsonValueFromText(InputTxt, this.TransactionIdTxt); + DocumentId := SignUpHelpers.GetJsonValueFromText(InputTxt, this.TransactionIdTxt); exit(DocumentId <> ''); end; @@ -346,7 +346,7 @@ codeunit 6383 Processing JsonManagement: Codeunit "JSON Management"; Result, Value : Text; begin - Result := this.HelpersImpl.ParseJsonString(HttpContentResponse); + Result := this.SignUpHelpersImpl.ParseJsonString(HttpContentResponse); if Result = '' then exit; @@ -439,7 +439,7 @@ codeunit 6383 Processing local procedure SendAcknowledgePatch(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"): Boolean var EDocumentServiceStatus: Record "E-Document Service Status"; - APIRequests: Codeunit APIRequests; + SignUpAPIRequests: Codeunit SignUpAPIRequests; HttpResponseMessage: HttpResponseMessage; HttpRequestMessage: HttpRequestMessage; begin @@ -448,7 +448,7 @@ codeunit 6383 Processing if not (EDocumentServiceStatus.Status in [EDocumentServiceStatus.Status::Sent, EDocumentServiceStatus.Status::"Pending Response", EDocumentServiceStatus.Status::"Pending Batch"]) then exit; - if APIRequests.PatchDocument(EDocument, HttpRequestMessage, HttpResponseMessage) then begin + if SignUpAPIRequests.PatchDocument(EDocument, HttpRequestMessage, HttpResponseMessage) then begin this.InsertIntegrationLog(EDocument, EDocumentService, HttpRequestMessage, HttpResponseMessage); exit(true); end else From 0d8e05f0b40fd124cdf885f4e8a9adb458d57487 Mon Sep 17 00:00:00 2001 From: geschwint Date: Tue, 11 Feb 2025 11:24:32 +0100 Subject: [PATCH 43/63] Refactor Objectnames - E2E Tests --- .../test/src/IntegrationEvents.Codeunit.al | 4 +- .../test/src/IntegrationHelpers.Codeunit.al | 32 +++++++------- .../test/src/IntegrationTests.Codeunit.al | 42 +++++++++---------- 3 files changed, 39 insertions(+), 39 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationEvents.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationEvents.Codeunit.al index 6708ef7364..28825d089d 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationEvents.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationEvents.Codeunit.al @@ -9,7 +9,7 @@ codeunit 148197 IntegrationEvents LibraryLowerPermissions: Codeunit "Library - Lower Permissions"; IntegrationHelpers: Codeunit IntegrationHelpers; - [EventSubscriber(ObjectType::Codeunit, Codeunit::Processing, OnBeforeGetTargetDocumentRequest, '', true, true)] + [EventSubscriber(ObjectType::Codeunit, Codeunit::SignUpProcessing, OnBeforeGetTargetDocumentRequest, '', true, true)] local procedure ProcessingOnBeforeGetTargetDocumentRequest() begin this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCOEdit'); @@ -17,7 +17,7 @@ codeunit 148197 IntegrationEvents this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCORead'); end; - [EventSubscriber(ObjectType::Codeunit, Codeunit::Processing, OnBeforeGetTargetDocumentRequest, '', true, true)] + [EventSubscriber(ObjectType::Codeunit, Codeunit::SignUpProcessing, OnBeforeGetTargetDocumentRequest, '', true, true)] local procedure ProcessingOnBeforeMarkFetched() begin this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCOEdit'); diff --git a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationHelpers.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationHelpers.Codeunit.al index 427b124aa3..8d490463f0 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationHelpers.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationHelpers.Codeunit.al @@ -15,29 +15,29 @@ codeunit 148196 IntegrationHelpers internal procedure SetAPICode(Path: Text) var - ConnectionSetup: Record ConnectionSetup; + SignUpConnectionSetup: Record SignUpConnectionSetup; begin - ConnectionSetup.Get(); - ConnectionSetup."Service URL" := this.SetMockServiceUrl(Path); - ConnectionSetup.Modify(true); + SignUpConnectionSetup.Get(); + SignUpConnectionSetup."Service URL" := this.SetMockServiceUrl(Path); + SignUpConnectionSetup.Modify(true); end; internal procedure SetCommonConnectionSetup() var - ConnectionSetup: Record ConnectionSetup; - Authentication: Codeunit Authentication; + SignUpConnectionSetup: Record SignUpConnectionSetup; + SignUpAuthentication: Codeunit SignUpAuthentication; begin - ConnectionSetup.Get(); - Authentication.StorageSet(ConnectionSetup."Root App ID", this.DummyId()); - Authentication.StorageSet(ConnectionSetup."Root Secret", this.DummyId()); - Authentication.StorageSet(ConnectionSetup."Root Tenant", this.DummyId()); - Authentication.StorageSet(ConnectionSetup."Client ID", this.DummyId()); - Authentication.StorageSet(ConnectionSetup."Client Secret", this.DummyId()); - Authentication.StorageSet(ConnectionSetup."Client Tenant", this.ClientTenantId()); + SignUpConnectionSetup.Get(); + SignUpAuthentication.StorageSet(SignUpConnectionSetup."Root App ID", this.DummyId()); + SignUpAuthentication.StorageSet(SignUpConnectionSetup."Root Secret", this.DummyId()); + SignUpAuthentication.StorageSet(SignUpConnectionSetup."Root Tenant", this.DummyId()); + SignUpAuthentication.StorageSet(SignUpConnectionSetup."Client ID", this.DummyId()); + SignUpAuthentication.StorageSet(SignUpConnectionSetup."Client Secret", this.DummyId()); + SignUpAuthentication.StorageSet(SignUpConnectionSetup."Client Tenant", this.ClientTenantId()); - ConnectionSetup."Authentication URL" := this.SetMockServiceUrl('/%1/oauth2/token'); - ConnectionSetup."Environment Type" := ConnectionSetup."Environment Type"::Test; - ConnectionSetup.Modify(true); + SignUpConnectionSetup."Authentication URL" := this.SetMockServiceUrl('/%1/oauth2/token'); + SignUpConnectionSetup."Environment Type" := SignUpConnectionSetup."Environment Type"::Test; + SignUpConnectionSetup.Modify(true); end; internal procedure SetMockServiceUrl(Path: Text): Text[250] diff --git a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al index 1df14aaed1..49c7e0aca8 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al @@ -19,7 +19,7 @@ codeunit 148195 IntegrationTests { Subtype = Test; - Permissions = tabledata ConnectionSetup = rimd, + Permissions = tabledata SignUpConnectionSetup = rimd, tabledata "E-Document" = r; var @@ -508,33 +508,33 @@ codeunit 148195 IntegrationTests [Test] procedure GetMetadataProfiles() var - MetadataProfile: Record MetadataProfile; + SignUpMetadataProfile: Record SignUpMetadataProfile; EDocServiceSupportedTypes: TestPage "E-Doc Service Supported Types"; begin this.Initialize(); - MetadataProfile.Reset(); - MetadataProfile.DeleteAll(); + SignUpMetadataProfile.Reset(); + SignUpMetadataProfile.DeleteAll(); // Populate metadata profiles EDocServiceSupportedTypes.OpenView(); EDocServiceSupportedTypes.PopulateMetaData.Invoke(); EDocServiceSupportedTypes.Close(); - this.Assert.TableIsNotEmpty(Database::MetadataProfile); + this.Assert.TableIsNotEmpty(Database::SignUpMetadataProfile); end; local procedure Initialize() var - ConnectionSetup: Record ConnectionSetup; + SignUpConnectionSetup: Record SignUpConnectionSetup; CompanyInformation: Record "Company Information"; ServiceParticipant: Record "Service Participant"; - Authentication: Codeunit Authentication; + SignUpAuthentication: Codeunit SignUpAuthentication; begin this.LibraryLowerPermissions.SetOutsideO365Scope(); - ConnectionSetup.DeleteAll(); - Authentication.InitConnectionSetup(); + SignUpConnectionSetup.DeleteAll(); + SignUpAuthentication.InitConnectionSetup(); this.IntegrationHelpers.SetCommonConnectionSetup(); this.IntegrationHelpers.SetAPIWith200Code(); @@ -585,19 +585,19 @@ codeunit 148195 IntegrationTests local procedure CreateDefaultMetadataProfile() var - MetadataProfile: Record MetadataProfile; + SignUpMetadataProfile: Record SignUpMetadataProfile; begin - if not MetadataProfile.IsEmpty() then - MetadataProfile.DeleteAll(true); - - MetadataProfile.Init(); - MetadataProfile.Validate("Profile ID", this.GetMetadataProfileId()); - MetadataProfile.Validate("Profile Name", 'PEPPOL BIS Billing v 3 Invoice UBL'); - MetadataProfile.Validate("Process Identifier Scheme", 'cenbii-procid-ubl'); - MetadataProfile.Validate("Process Identifier Value", 'urn:fdc:peppol.eu:2017:poacc:billing:01:1.0'); - MetadataProfile.Validate("Document Identifier Scheme", 'busdox-docid-qns'); - MetadataProfile.Validate("Document Identifier Value", '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'); - MetadataProfile.Insert(true); + if not SignUpMetadataProfile.IsEmpty() then + SignUpMetadataProfile.DeleteAll(true); + + SignUpMetadataProfile.Init(); + SignUpMetadataProfile.Validate("Profile ID", this.GetMetadataProfileId()); + SignUpMetadataProfile.Validate("Profile Name", 'PEPPOL BIS Billing v 3 Invoice UBL'); + SignUpMetadataProfile.Validate("Process Identifier Scheme", 'cenbii-procid-ubl'); + SignUpMetadataProfile.Validate("Process Identifier Value", 'urn:fdc:peppol.eu:2017:poacc:billing:01:1.0'); + SignUpMetadataProfile.Validate("Document Identifier Scheme", 'busdox-docid-qns'); + SignUpMetadataProfile.Validate("Document Identifier Value", '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'); + SignUpMetadataProfile.Insert(true); end; local procedure ApplyMetadataProfile(ProfileID: Integer) From e371b4bad8f43dac4e85ca3248035931d476c17c Mon Sep 17 00:00:00 2001 From: geschwint Date: Tue, 11 Feb 2025 17:17:28 +0100 Subject: [PATCH 44/63] Object removal - Not used --- .../test/src/IntegrationEvents.Codeunit.al | 27 ------------------- 1 file changed, 27 deletions(-) delete mode 100644 Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationEvents.Codeunit.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationEvents.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationEvents.Codeunit.al deleted file mode 100644 index 28825d089d..0000000000 --- a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationEvents.Codeunit.al +++ /dev/null @@ -1,27 +0,0 @@ -namespace Microsoft.EServices.EDocumentConnector.SignUp; - - -codeunit 148197 IntegrationEvents -{ - EventSubscriberInstance = Manual; - - var - LibraryLowerPermissions: Codeunit "Library - Lower Permissions"; - IntegrationHelpers: Codeunit IntegrationHelpers; - - [EventSubscriber(ObjectType::Codeunit, Codeunit::SignUpProcessing, OnBeforeGetTargetDocumentRequest, '', true, true)] - local procedure ProcessingOnBeforeGetTargetDocumentRequest() - begin - this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCOEdit'); - this.IntegrationHelpers.SetAPICode('/signup/200/download'); - this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCORead'); - end; - - [EventSubscriber(ObjectType::Codeunit, Codeunit::SignUpProcessing, OnBeforeGetTargetDocumentRequest, '', true, true)] - local procedure ProcessingOnBeforeMarkFetched() - begin - this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCOEdit'); - this.IntegrationHelpers.SetAPICode('/signup/200/markdownloaded'); - this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCORead'); - end; -} \ No newline at end of file From 542cdda2341b819a15af72ad61529e86cb3188aa Mon Sep 17 00:00:00 2001 From: geschwint Date: Tue, 11 Feb 2025 17:21:02 +0100 Subject: [PATCH 45/63] Clarify ToolTip --- .../app/src/Integration/SignUpCompanyInformationExt.TableExt.al | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.TableExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.TableExt.al index 84fa797c5e..8f5b86f167 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.TableExt.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.TableExt.al @@ -12,7 +12,7 @@ tableextension 6381 SignUpCompanyInformationExt extends "Company Information" field(6381; "SignUp Service Participant Id"; Text[100]) { Caption = 'Service Participant Id'; - ToolTip = 'ExFlow E-Invoicing Service Participant Id.'; + ToolTip = 'Specifies the PEPPOL participant identifier registered for your company in the ExFlow E-Invoicing subscription. This identifier is used when you are sending/receiving documents via the PEPPOL network.'; } } From f196ce44c509b79c6804ed7d57fa48347007e2ab Mon Sep 17 00:00:00 2001 From: geschwint Date: Tue, 11 Feb 2025 17:23:11 +0100 Subject: [PATCH 46/63] Assignable Permissions --- .../SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al | 2 +- .../SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al index 8197ae8d43..ef7a386364 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al @@ -7,7 +7,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; permissionset 6382 SignUpEDCOEdit { Access = Internal; - Assignable = false; + Assignable = true; Caption = 'SignUp E-Doc. Connector - Edit', MaxLength = 30; IncludedPermissionSets = SignUpEDCORead; Permissions = tabledata SignUpConnectionSetup = IMD, diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al index 1c0a7c576b..c84f70cd75 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al @@ -9,7 +9,7 @@ using Microsoft.eServices.EDocument; permissionset 6381 SignUpEDCORead { Access = Internal; - Assignable = false; + Assignable = true; Caption = 'SignUp E-Doc. Connector - Read', MaxLength = 30; IncludedPermissionSets = SignUpEDCOObjects; Permissions = tabledata SignUpConnectionSetup = R, From 6d5647a1b98fd219df4f2a27e3e848c61fa741e4 Mon Sep 17 00:00:00 2001 From: geschwint Date: Tue, 11 Feb 2025 17:23:59 +0100 Subject: [PATCH 47/63] Use UnixTimeStamp New Way --- .../SignUp/app/src/SignUpHelpers.Codeunit.al | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpHelpers.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpHelpers.Codeunit.al index 0b6a4feef2..33aadeebab 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpHelpers.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpHelpers.Codeunit.al @@ -6,6 +6,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using System.Reflection; using Microsoft.Utilities; +using System.DateTime; using System.Integration; using Microsoft.eServices.EDocument; @@ -66,11 +67,11 @@ codeunit 6385 SignUpHelpers local procedure GetTokenDateTimeValue(InToken: SecretText; ClaimType: Text): DateTime var - TypeHelper: Codeunit "Type Helper"; + UnixTimestamp: Codeunit "Unix Timestamp"; Timestamp: Decimal; begin if Evaluate(Timestamp, this.GetValueFromToken(InToken, ClaimType)) then - exit(TypeHelper.EvaluateUnixTimestamp(Timestamp)); + exit(UnixTimestamp.EvaluateTimestamp(Timestamp)); end; [NonDebuggable] From 2cf8aa711e7a8ab8f210889ac8029da5d5223f11 Mon Sep 17 00:00:00 2001 From: geschwint Date: Tue, 11 Feb 2025 17:24:53 +0100 Subject: [PATCH 48/63] Use Page Name instead of ID --- .../SignUp/app/src/SignUpMetadataProfile.Table.al | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfile.Table.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfile.Table.al index 2d9627ae25..c52d1cf183 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfile.Table.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfile.Table.al @@ -9,7 +9,7 @@ table 6382 SignUpMetadataProfile Caption = 'MetadataProfile'; Access = Internal; DataClassification = CustomerContent; - LookupPageId = 6381; + LookupPageId = SignUpMetadataProfiles; fields { From 0fc0655d7437356324fc3ac38bb9172e2f1bc368 Mon Sep 17 00:00:00 2001 From: geschwint Date: Tue, 11 Feb 2025 17:26:19 +0100 Subject: [PATCH 49/63] Skip Events in E2E Tests --- .../SignUp/test/src/IntegrationTests.Codeunit.al | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al index 49c7e0aca8..21087e2d5c 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al @@ -474,8 +474,6 @@ codeunit 148195 IntegrationTests procedure SubmitGetDocuments() var EDocument: Record "E-Document"; - //PurchaseHeader: Record "Purchase Header"; - IntegrationEvents: Codeunit IntegrationEvents; EDocumentServicesPage: TestPage "E-Document Service"; TmpDocCount: Integer; begin @@ -493,10 +491,8 @@ codeunit 148195 IntegrationTests EDocumentServicesPage.Close(); TmpDocCount := EDocument.Count(); - BindSubscription(IntegrationEvents); // Manually fire job queue job to import this.LibraryEDocument.RunImportJob(); - UnbindSubscription(IntegrationEvents); // Assert that we have Purchase Invoice created this.Assert.AreEqual(EDocument.Count(), TmpDocCount + 1, 'The document was not imported!'); From 41e476a42d913e8db88ca635f0a4ff8d9c977068 Mon Sep 17 00:00:00 2001 From: geschwint Date: Tue, 11 Feb 2025 17:26:58 +0100 Subject: [PATCH 50/63] Integration Log handling --- .../app/src/SignUpProcessing.Codeunit.al | 57 +------------------ 1 file changed, 2 insertions(+), 55 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al index 0de2055605..63cd053722 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al @@ -26,6 +26,7 @@ codeunit 6383 SignUpProcessing SignUpConnection: Codeunit SignUpConnection; SignUpHelpersImpl: Codeunit SignUpHelpers; EDocumentErrorHelper: Codeunit "E-Document Error Helper"; + EDocumentLogHelper: Codeunit "E-Document Log Helper"; CouldNotRetrieveDocumentErr: Label 'Could not retrieve document with id: %1 from the service', Comment = '%1 - Document ID'; CouldNotSendPatchErr: Label 'Could not Send Patch for document with id: %1', Comment = '%1 - Document ID'; CouldNotRetrieveStatusFromResponseLbl: Label 'Could not retrieve status from response'; @@ -195,7 +196,6 @@ codeunit 6383 SignUpProcessing EDocument.Modify(); Clear(ContentData); - this.OnBeforeGetTargetDocumentRequest(); this.SignUpConnection.GetTargetDocumentRequest(EDocument."SignUp Document Id", HttpRequestMessage, HttpResponseMessage); ReceiveContext.Http().SetHttpRequestMessage(HttpRequestMessage); @@ -218,7 +218,6 @@ codeunit 6383 SignUpProcessing HttpRequestMessage: HttpRequestMessage; HttpResponseMessage: HttpResponseMessage; begin - this.OnBeforeMarkFetched(); this.SignUpConnection.RemoveDocumentFromReceived(EDocument, HttpRequestMessage, HttpResponseMessage); ReceiveContext.Http().SetHttpRequestMessage(HttpRequestMessage); @@ -229,35 +228,6 @@ codeunit 6383 SignUpProcessing #region local methods - local procedure InsertIntegrationLog(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"; HttpRequestMessage: HttpRequestMessage; HttpResponseMessage: HttpResponseMessage) - var - EDocumentIntegrationLog: Record "E-Document Integration Log"; - EDocIntegrationLogRecordRef: RecordRef; - RequestTxt: Text; - begin - if EDocumentService."Service Integration V2" = EDocumentService."Service Integration V2"::"No Integration" then - exit; - - EDocumentIntegrationLog.Validate("E-Doc. Entry No", EDocument."Entry No"); - EDocumentIntegrationLog.Validate("Service Code", EDocumentService.Code); - EDocumentIntegrationLog.Validate("Response Status", HttpResponseMessage.HttpStatusCode()); - EDocumentIntegrationLog.Validate("Request URL", HttpRequestMessage.GetRequestUri()); - EDocumentIntegrationLog.Validate(Method, HttpRequestMessage.Method()); - EDocumentIntegrationLog.Insert(); - - EDocIntegrationLogRecordRef.GetTable(EDocumentIntegrationLog); - - if HttpRequestMessage.Content.ReadAs(RequestTxt) then begin - this.InsertIntegrationBlob(EDocIntegrationLogRecordRef, RequestTxt, EDocumentIntegrationLog.FieldNo(EDocumentIntegrationLog."Request Blob")); - EDocIntegrationLogRecordRef.Modify(); - end; - - if HttpResponseMessage.Content.ReadAs(RequestTxt) then begin - this.InsertIntegrationBlob(EDocIntegrationLogRecordRef, RequestTxt, EDocumentIntegrationLog.FieldNo(EDocumentIntegrationLog."Response Blob")); - EDocIntegrationLogRecordRef.Modify(); - end; - end; - local procedure ParseDocumentResponse(HttpContentResponse: HttpContent; var Status: Text; var StatusDescription: Text): Boolean var JsonManagement: Codeunit "JSON Management"; @@ -380,14 +350,6 @@ codeunit 6383 SignUpProcessing exit(true); end; - local procedure InsertIntegrationBlob(var EDocIntegrationLogRecordRef: RecordRef; Data: Text; FieldNo: Integer) - var - TempBlob: Codeunit "Temp Blob"; - begin - TempBlob.CreateOutStream().WriteText(Data); - TempBlob.ToRecordRef(EDocIntegrationLogRecordRef, FieldNo); - end; - local procedure LeaveJustNewLine(InputText: Text): Text var InputJson, OutputDocumentJsonObject, OutputJsonObject : JsonObject; @@ -449,26 +411,11 @@ codeunit 6383 SignUpProcessing exit; if SignUpAPIRequests.PatchDocument(EDocument, HttpRequestMessage, HttpResponseMessage) then begin - this.InsertIntegrationLog(EDocument, EDocumentService, HttpRequestMessage, HttpResponseMessage); + this.EDocumentLogHelper.InsertIntegrationLog(EDocument, EDocumentService, HttpRequestMessage, HttpResponseMessage); exit(true); end else this.EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, StrSubstNo(this.CouldNotSendPatchErr, EDocument."SignUp Document Id")); end; #endregion - - #region event publishers - - [IntegrationEvent(false, false)] - local procedure OnBeforeGetTargetDocumentRequest() - begin - end; - - [IntegrationEvent(false, false)] - local procedure OnBeforeMarkFetched() - begin - - end; - - #endregion } \ No newline at end of file From 9142d23b1312defe77ed71b3bcb9eb38baf3e9ff Mon Sep 17 00:00:00 2001 From: geschwint Date: Tue, 11 Feb 2025 17:28:23 +0100 Subject: [PATCH 51/63] No hardcoded Identifier Changed scope for isolated storage --- .../SignUp/app/src/SignUpAuthentication.Codeunit.al | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al index af28d075ab..01c381741d 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al @@ -150,8 +150,6 @@ codeunit 6390 SignUpAuthentication var AADTenantID, AADDomainName : Text; begin - Identifier := '10000000-d8ef-4dfb-b761-ffb073057794'; // Hardcoded fake during testing only - if this.GetAADTenantInformation(AADTenantID, AADDomainName) then Identifier := AADTenantID; end; @@ -181,7 +179,7 @@ codeunit 6390 SignUpAuthentication var HttpError: Text; begin - AccessToken := this.StorageGet(this.SignUpAccessTokenKeyTxt, DataScope::Company); + AccessToken := this.StorageGet(this.SignUpAccessTokenKeyTxt, DataScope::Module); if this.SignUpHelpersImpl.IsTokenValid(AccessToken) then exit; @@ -189,7 +187,7 @@ codeunit 6390 SignUpAuthentication if not this.RefreshAccessToken(HttpError) then Error(HttpError); - exit(this.StorageGet(this.SignUpAccessTokenKeyTxt, DataScope::Company)); + exit(this.StorageGet(this.SignUpAccessTokenKeyTxt, DataScope::Module)); end; local procedure GetRootAuthToken() ReturnValue: SecretText; @@ -233,7 +231,7 @@ codeunit 6390 SignUpAuthentication exit; end; - exit(this.SaveSignUpAccessToken(DataScope::Company, SecretToken)); + exit(this.SaveSignUpAccessToken(DataScope::Module, SecretToken)); end; [NonDebuggable] From 5a85e07bda75294f3543e0eb5d4bdd0e29aa94d5 Mon Sep 17 00:00:00 2001 From: geschwint Date: Tue, 11 Feb 2025 17:42:18 +0100 Subject: [PATCH 52/63] Do not replicate data --- .../SignUp/app/src/Setup/SignUpConnectionSetup.Table.al | 1 + 1 file changed, 1 insertion(+) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al index 719e991325..c6608b6350 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al @@ -9,6 +9,7 @@ table 6381 SignUpConnectionSetup Access = Internal; DataPerCompany = false; DataClassification = CustomerContent; + ReplicateData = false; fields { From f23be8b86454cc3cd0ae0aaef0329c96ad8f1486 Mon Sep 17 00:00:00 2001 From: geschwint Date: Wed, 12 Feb 2025 13:48:53 +0100 Subject: [PATCH 53/63] Connection Setup Card Title --- .../SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al index 39f0550383..e16f1428bb 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al @@ -15,7 +15,7 @@ page 6380 SignUpConnectionSetupCard SourceTable = SignUpConnectionSetup; ApplicationArea = Basic, Suite; UsageCategory = None; - Caption = 'E-Document External Connection Setup'; + Caption = 'SignUp Connection Setup'; Extensible = false; From 358d7df059c73513020925dc24e73c134202f402 Mon Sep 17 00:00:00 2001 From: geschwint Date: Wed, 12 Feb 2025 15:24:21 +0100 Subject: [PATCH 54/63] Changed to Actionref --- .../app/src/Setup/SignUpConnectionSetupCard.Page.al | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al index e16f1428bb..e258fd0c69 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al @@ -18,7 +18,6 @@ page 6380 SignUpConnectionSetupCard Caption = 'SignUp Connection Setup'; Extensible = false; - layout { area(Content) @@ -137,9 +136,6 @@ page 6380 SignUpConnectionSetupCard ApplicationArea = Basic, Suite; Caption = 'Open Onboarding'; Image = Setup; - Promoted = true; - PromotedCategory = Process; - PromotedOnly = true; ToolTip = 'Create client credentials and open the onboarding process in a web browser.'; trigger OnAction() @@ -152,6 +148,11 @@ page 6380 SignUpConnectionSetupCard end; } } + + area(Promoted) + { + actionref(InitOnboarding01_Promoted; InitOnboarding01) { } + } } trigger OnOpenPage() From 49a568676f6831b4fba77f026fa8593873fcd543 Mon Sep 17 00:00:00 2001 From: geschwint Date: Thu, 13 Feb 2025 09:00:52 +0100 Subject: [PATCH 55/63] Extend range --- Apps/W1/EDocumentConnectors/SignUp/app/app.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/app.json b/Apps/W1/EDocumentConnectors/SignUp/app/app.json index 3e80be6107..c08e5ea786 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/app.json +++ b/Apps/W1/EDocumentConnectors/SignUp/app/app.json @@ -25,7 +25,7 @@ "idRanges": [ { "from": 6380, - "to": 6389 + "to": 6399 } ], "resourceExposurePolicy": { From 0ee26d925b1367c86d92457c530ddce7fb3529ac Mon Sep 17 00:00:00 2001 From: geschwint Date: Thu, 13 Feb 2025 10:51:00 +0100 Subject: [PATCH 56/63] Rename object files --- ...portedTypeExt.TableExt.al => SignUpEDocSvcTypeExt.TableExt.al} | 0 ...eExtPageExt.PageExt.al => SignUpEDocSvcTypePageExt.PageExt.al} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/{SignUpEDocSvcSupportedTypeExt.TableExt.al => SignUpEDocSvcTypeExt.TableExt.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/{SignUpEDocSvcSupTypeExtPageExt.PageExt.al => SignUpEDocSvcTypePageExt.PageExt.al} (100%) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcSupportedTypeExt.TableExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcTypeExt.TableExt.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcSupportedTypeExt.TableExt.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcTypeExt.TableExt.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcSupTypeExtPageExt.PageExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcTypePageExt.PageExt.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcSupTypeExtPageExt.PageExt.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcTypePageExt.PageExt.al From 35d273dca2b3b8f33b2aae09c0b2a23189a146dd Mon Sep 17 00:00:00 2001 From: geschwint Date: Thu, 13 Feb 2025 10:52:04 +0100 Subject: [PATCH 57/63] Rename objects --- .../SignUpCompanyInformationExt.PageExt.al | 2 +- .../SignUpCompanyInformationExt.TableExt.al | 2 +- .../SignUpEDocSvcTypeExt.TableExt.al | 6 ++-- .../SignUpEDocSvcTypePageExt.PageExt.al | 7 ++--- .../SignUpEDocumentExt.TableExt.al | 2 +- .../SignUpIntegrationEnumExt.EnumExt.al | 4 +-- .../SignUpIntegrationImpl.Codeunit.al | 6 ++-- .../SignUpEDCOEdit.PermissionSet.al | 8 +++--- .../SignUpEDCOObjects.PermissionSet.al | 22 +++++++-------- .../SignUpEDCORead.PermissionSet.al | 8 +++--- .../src/Setup/SignUpConnectionSetup.Table.al | 4 +-- .../Setup/SignUpConnectionSetupCard.Page.al | 6 ++-- .../src/Setup/SignUpEnvironmentType.Enum.al | 2 +- .../app/src/SignUpAPIRequests.Codeunit.al | 28 +++++++++---------- .../app/src/SignUpAuthentication.Codeunit.al | 8 +++--- .../app/src/SignUpConnection.Codeunit.al | 12 ++++---- .../SignUp/app/src/SignUpHelpers.Codeunit.al | 3 +- .../app/src/SignUpMetadataProfile.Table.al | 4 +-- .../app/src/SignUpMetadataProfiles.Page.al | 4 +-- .../app/src/SignUpProcessing.Codeunit.al | 10 +++---- .../test/src/IntegrationHelpers.Codeunit.al | 6 ++-- .../test/src/IntegrationTests.Codeunit.al | 12 ++++---- 22 files changed, 82 insertions(+), 84 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.PageExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.PageExt.al index ea4cb5b240..661072a27a 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.PageExt.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.PageExt.al @@ -6,7 +6,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.Foundation.Company; using Microsoft.eServices.EDocument; -pageextension 6381 SignUpCompanyInformationExt extends "Company Information" +pageextension 6381 "SignUp Company Information Ext" extends "Company Information" { layout { diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.TableExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.TableExt.al index 8f5b86f167..6ed711ec7b 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.TableExt.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.TableExt.al @@ -5,7 +5,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.Foundation.Company; -tableextension 6381 SignUpCompanyInformationExt extends "Company Information" +tableextension 6381 "SignUp Company Information Ext" extends "Company Information" { fields { diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcTypeExt.TableExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcTypeExt.TableExt.al index 8377a775ca..ceceb691a6 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcTypeExt.TableExt.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcTypeExt.TableExt.al @@ -6,7 +6,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.eServices.EDocument; -tableextension 6383 SignUpEDocSvcSupportedTypeExt extends "E-Doc. Service Supported Type" +tableextension 6383 "SignUp E-Doc. Svc. Type Ext" extends "E-Doc. Service Supported Type" { fields { @@ -15,7 +15,7 @@ tableextension 6383 SignUpEDocSvcSupportedTypeExt extends "E-Doc. Service Suppor Caption = 'Profile Id'; ToolTip = 'The unique identifier for the metadata profile.'; DataClassification = CustomerContent; - TableRelation = SignUpMetadataProfile; + TableRelation = "SignUp Metadata Profile"; BlankZero = true; trigger OnValidate() @@ -29,7 +29,7 @@ tableextension 6383 SignUpEDocSvcSupportedTypeExt extends "E-Doc. Service Suppor ToolTip = 'The common name of the metadata profile.'; FieldClass = FlowField; Editable = false; - CalcFormula = lookup(SignUpMetadataProfile."Profile Name" where("Profile ID" = field("Profile Id"))); + CalcFormula = lookup("SignUp Metadata Profile"."Profile Name" where("Profile ID" = field("Profile Id"))); } } } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcTypePageExt.PageExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcTypePageExt.PageExt.al index 5e15aa9ff2..a53844d979 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcTypePageExt.PageExt.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcTypePageExt.PageExt.al @@ -6,9 +6,8 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.eServices.EDocument; -pageextension 6383 SignUpEDocSvcSupTypeExtPageExt extends "E-Doc Service Supported Types" +pageextension 6383 "SignUp EDoc. Svc. Type PageExt" extends "E-Doc Service Supported Types" { - layout { addlast(General) @@ -43,7 +42,7 @@ pageextension 6383 SignUpEDocSvcSupTypeExtPageExt extends "E-Doc Service Support trigger OnAction() var - SignUpConnection: Codeunit SignUpConnection; + SignUpConnection: Codeunit "SignUp Connection"; begin SignUpConnection.UpdateMetadataProfile(); end; @@ -53,7 +52,7 @@ pageextension 6383 SignUpEDocSvcSupTypeExtPageExt extends "E-Doc Service Support trigger OnOpenPage() var - SignUpHelpers: Codeunit SignUpHelpers; + SignUpHelpers: Codeunit "SignUp Helpers"; begin ExFlowEInvoicingVisible := SignUpHelpers.IsExFlowEInvoicing(Rec.GetFilter("E-Document Service Code")); end; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocumentExt.TableExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocumentExt.TableExt.al index 45f308d810..7a8e9dbf49 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocumentExt.TableExt.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocumentExt.TableExt.al @@ -6,7 +6,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.eServices.EDocument; -tableextension 6382 SignUpEDocumentExt extends "E-Document" +tableextension 6382 "SignUp E-Document Ext" extends "E-Document" { fields { diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationEnumExt.EnumExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationEnumExt.EnumExt.al index cd2778e9c0..ded0393c27 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationEnumExt.EnumExt.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationEnumExt.EnumExt.al @@ -6,11 +6,11 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.eServices.EDocument.Integration; using Microsoft.eServices.EDocument.Integration.Interfaces; -enumextension 6380 SignUpIntegrationEnumExt extends "Service Integration" +enumextension 6380 "SignUp Integration Enum Ext" extends "Service Integration" { value(6380; "ExFlow E-Invoicing") { Caption = 'ExFlow E-Invoicing'; - Implementation = IDocumentSender = SignUpIntegrationImpl, IDocumentReceiver = SignUpIntegrationImpl; + Implementation = IDocumentSender = "SignUp Integration Impl.", IDocumentReceiver = "SignUp Integration Impl."; } } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationImpl.Codeunit.al index a5e5ad50c9..d9dc997b80 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationImpl.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationImpl.Codeunit.al @@ -11,12 +11,12 @@ using Microsoft.eServices.EDocument.Integration.Send; using Microsoft.eServices.EDocument.Integration.Receive; -codeunit 6386 SignUpIntegrationImpl implements IDocumentSender, IDocumentReceiver, IDocumentResponseHandler, IReceivedDocumentMarker +codeunit 6386 "SignUp Integration Impl." implements IDocumentSender, IDocumentReceiver, IDocumentResponseHandler, IReceivedDocumentMarker { Access = Internal; var - SignUpProcessing: Codeunit SignUpProcessing; + SignUpProcessing: Codeunit "SignUp Processing"; #region IDocumentSender procedure Send(var EDocument: Record "E-Document"; var EDocumentService: Record "E-Document Service"; SendContext: Codeunit SendContext); @@ -57,7 +57,7 @@ codeunit 6386 SignUpIntegrationImpl implements IDocumentSender, IDocumentReceive [EventSubscriber(ObjectType::Page, Page::"E-Document Service", OnBeforeOpenServiceIntegrationSetupPage, '', false, false)] local procedure OnBeforeOpenServiceIntegrationSetupPage(EDocumentService: Record "E-Document Service"; var IsServiceIntegrationSetupRun: Boolean) var - SignUpConnectionSetupCard: Page SignUpConnectionSetupCard; + SignUpConnectionSetupCard: Page "SignUp Connection Setup Card"; begin if EDocumentService."Service Integration V2" <> EDocumentService."Service Integration V2"::"ExFlow E-Invoicing" then exit; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al index ef7a386364..643743d546 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al @@ -4,13 +4,13 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -permissionset 6382 SignUpEDCOEdit +permissionset 6382 "SignUp EDCO Edit" { Access = Internal; Assignable = true; Caption = 'SignUp E-Doc. Connector - Edit', MaxLength = 30; - IncludedPermissionSets = SignUpEDCORead; - Permissions = tabledata SignUpConnectionSetup = IMD, - tabledata SignUpMetadataProfile = IMD; + IncludedPermissionSets = "SignUp EDCO Read"; + Permissions = tabledata "SignUp Connection Setup" = IMD, + tabledata "SignUp Metadata Profile" = IMD; } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOObjects.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOObjects.PermissionSet.al index d59f0bfbc4..2485fe99e8 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOObjects.PermissionSet.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOObjects.PermissionSet.al @@ -6,21 +6,21 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.eServices.EDocument; -permissionset 6380 SignUpEDCOObjects +permissionset 6380 "SignUp EDCO Objects" { Access = Internal; Assignable = false; Caption = 'SignUp E-Doc. Connector - Obj.', MaxLength = 30; - Permissions = table SignUpConnectionSetup = X, - table SignUpMetadataProfile = X, + Permissions = table "SignUp Connection Setup" = X, + table "SignUp Metadata Profile" = X, table "E-Document Integration Log" = X, - page SignUpConnectionSetupCard = X, - page SignUpMetadataProfiles = X, - codeunit SignUpAPIRequests = X, - codeunit SignUpAuthentication = X, - codeunit SignUpConnection = X, - codeunit SignUpHelpers = X, - codeunit SignUpIntegrationImpl = X, - codeunit SignUpProcessing = X; + page "SignUp Connection Setup Card" = X, + page "SignUp Metadata Profiles" = X, + codeunit "SignUp API Requests" = X, + codeunit "SignUp Authentication" = X, + codeunit "SignUp Connection" = X, + codeunit "SignUp Helpers" = X, + codeunit "SignUp Integration Impl." = X, + codeunit "SignUp Processing" = X; } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al index c84f70cd75..aa51c108ea 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al @@ -6,14 +6,14 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.eServices.EDocument; -permissionset 6381 SignUpEDCORead +permissionset 6381 "SignUp EDCO Read" { Access = Internal; Assignable = true; Caption = 'SignUp E-Doc. Connector - Read', MaxLength = 30; - IncludedPermissionSets = SignUpEDCOObjects; - Permissions = tabledata SignUpConnectionSetup = R, - tabledata SignUpMetadataProfile = R, + IncludedPermissionSets = "SignUp EDCO Objects"; + Permissions = tabledata "SignUp Connection Setup" = R, + tabledata "SignUp Metadata Profile" = R, tabledata "E-Document Integration Log" = rim; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al index c6608b6350..6f9446072b 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al @@ -4,7 +4,7 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -table 6381 SignUpConnectionSetup +table 6381 "SignUp Connection Setup" { Access = Internal; DataPerCompany = false; @@ -33,7 +33,7 @@ table 6381 SignUpConnectionSetup Caption = 'Client Secret'; ToolTip = 'Specifies the client secret.'; } - field(5; "Environment Type"; Enum SignUpEnvironmentType) + field(5; "Environment Type"; Enum "SignUp Environment Type") { Caption = 'Environment Type'; ToolTip = 'Specifies the environment type.'; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al index e258fd0c69..7d9f6fb43d 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al @@ -8,11 +8,11 @@ using System.Telemetry; using Microsoft.Foundation.Company; using System.Environment; -page 6380 SignUpConnectionSetupCard +page 6380 "SignUp Connection Setup Card" { AdditionalSearchTerms = 'SignUp,electronic document,e-invoice,e-document,external,connection,connector'; PageType = Card; - SourceTable = SignUpConnectionSetup; + SourceTable = "SignUp Connection Setup"; ApplicationArea = Basic, Suite; UsageCategory = None; Caption = 'SignUp Connection Setup'; @@ -190,7 +190,7 @@ page 6380 SignUpConnectionSetupCard end; var - SignUpAuthentication: Codeunit SignUpAuthentication; + SignUpAuthentication: Codeunit "SignUp Authentication"; FeatureTelemetry: Codeunit "Feature Telemetry"; [NonDebuggable] ClientID, ClientSecret, ClientTenant, RootID, RootSecret, RootTenant : Text; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpEnvironmentType.Enum.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpEnvironmentType.Enum.al index a4383312f7..f34cd5084a 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpEnvironmentType.Enum.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpEnvironmentType.Enum.al @@ -4,7 +4,7 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -enum 6380 SignUpEnvironmentType +enum 6380 "SignUp Environment Type" { Access = Internal; Caption = 'Environment Type', Locked = true; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAPIRequests.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAPIRequests.Codeunit.al index 23f7eaac67..cea7020c3b 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAPIRequests.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAPIRequests.Codeunit.al @@ -13,7 +13,7 @@ using System.Utilities; using System.Xml; using System.Environment; -codeunit 6389 SignUpAPIRequests +codeunit 6389 "SignUp API Requests" { Access = Internal; InherentEntitlements = X; @@ -69,7 +69,7 @@ codeunit 6389 SignUpAPIRequests /// True if successfully completed procedure SendFilePostRequest(var TempBlob: Codeunit "Temp Blob"; EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - SignUpConnectionSetup: Record SignUpConnectionSetup; + SignUpConnectionSetup: Record "SignUp Connection Setup"; HttpContent: HttpContent; Payload: Text; begin @@ -97,7 +97,7 @@ codeunit 6389 SignUpAPIRequests /// True if successfully completed procedure GetSentDocumentStatus(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - SignUpConnectionSetup: Record SignUpConnectionSetup; + SignUpConnectionSetup: Record "SignUp Connection Setup"; begin this.InitRequest(HttpRequestMessage, HttpResponseMessage); SignUpConnectionSetup.SetLoadFields("Service URL"); @@ -117,7 +117,7 @@ codeunit 6389 SignUpAPIRequests /// True if successfully completed procedure PatchDocument(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - SignUpConnectionSetup: Record SignUpConnectionSetup; + SignUpConnectionSetup: Record "SignUp Connection Setup"; begin this.InitRequest(HttpRequestMessage, HttpResponseMessage); SignUpConnectionSetup.SetLoadFields("Service URL"); @@ -136,7 +136,7 @@ codeunit 6389 SignUpAPIRequests /// True if successfully completed procedure GetReceivedDocumentsRequest(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - SignUpConnectionSetup: Record SignUpConnectionSetup; + SignUpConnectionSetup: Record "SignUp Connection Setup"; begin this.InitRequest(HttpRequestMessage, HttpResponseMessage); SignUpConnectionSetup.SetLoadFields("Service URL"); @@ -156,7 +156,7 @@ codeunit 6389 SignUpAPIRequests /// True if successfully completed procedure GetTargetDocumentRequest(DocumentId: Text; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - SignUpConnectionSetup: Record SignUpConnectionSetup; + SignUpConnectionSetup: Record "SignUp Connection Setup"; begin this.InitRequest(HttpRequestMessage, HttpResponseMessage); SignUpConnectionSetup.SetLoadFields("Service URL"); @@ -177,7 +177,7 @@ codeunit 6389 SignUpAPIRequests /// True if successfully completed procedure PatchReceivedDocument(EDocument: Record "E-Document"; var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - SignUpConnectionSetup: Record SignUpConnectionSetup; + SignUpConnectionSetup: Record "SignUp Connection Setup"; begin this.InitRequest(HttpRequestMessage, HttpResponseMessage); SignUpConnectionSetup.SetLoadFields("Service URL"); @@ -196,7 +196,7 @@ codeunit 6389 SignUpAPIRequests /// Returns true if the metadata profiles were successfully fetched, otherwise false. procedure FetchMetaDataProfiles(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - SignUpConnectionSetup: Record SignUpConnectionSetup; + SignUpConnectionSetup: Record "SignUp Connection Setup"; begin this.InitRequest(HttpRequestMessage, HttpResponseMessage); SignUpConnectionSetup.SetLoadFields("Service URL"); @@ -215,7 +215,7 @@ codeunit 6389 SignUpAPIRequests /// True if successfully completed procedure GetMarketPlaceCredentials(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - SignUpAuthentication: Codeunit SignUpAuthentication; + SignUpAuthentication: Codeunit "SignUp Authentication"; begin this.InitRequest(HttpRequestMessage, HttpResponseMessage); @@ -242,7 +242,7 @@ codeunit 6389 SignUpAPIRequests Clear(HttpResponseMessage); end; - local procedure GetSetup(var SignUpConnectionSetup: Record SignUpConnectionSetup) + local procedure GetSetup(var SignUpConnectionSetup: Record "SignUp Connection Setup") var MissingSetupErrorInfo: ErrorInfo; begin @@ -278,7 +278,7 @@ codeunit 6389 SignUpAPIRequests exit(this.CompanyId); end; - local procedure PrepareContent(var HttpContent: HttpContent; Payload: Text; EDocument: Record "E-Document"; SignUpConnectionSetup: Record SignUpConnectionSetup) + local procedure PrepareContent(var HttpContent: HttpContent; Payload: Text; EDocument: Record "E-Document"; SignUpConnectionSetup: Record "SignUp Connection Setup") var ContentText: Text; HttpHeaders: HttpHeaders; @@ -299,7 +299,7 @@ codeunit 6389 SignUpAPIRequests local procedure SendRequest(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage; RootRequest: Boolean): Boolean var - SignUpAuthentication: Codeunit SignUpAuthentication; + SignUpAuthentication: Codeunit "SignUp Authentication"; HttpClient: HttpClient; HttpHeaders: HttpHeaders; begin @@ -371,12 +371,12 @@ codeunit 6389 SignUpAPIRequests exit(CompanyInformation."Country/Region Code"); end; - local procedure PrepareContentForSend(EDocument: Record "E-Document"; SendingCompanyID: Text; SenderCountryCode: Text; Payload: Text; SendMode: Enum SignUpEnvironmentType): Text + local procedure PrepareContentForSend(EDocument: Record "E-Document"; SendingCompanyID: Text; SenderCountryCode: Text; Payload: Text; SendMode: Enum "SignUp Environment Type"): Text var EDocumentService: Record "E-Document Service"; EDocumentServiceStatus: Record "E-Document Service Status"; EDocServiceSupportedType: Record "E-Doc. Service Supported Type"; - SignUpMetadataProfile: Record SignUpMetadataProfile; + SignUpMetadataProfile: Record "SignUp Metadata Profile"; EDocumentHelper: Codeunit "E-Document Helper"; Base64Convert: Codeunit "Base64 Convert"; JsonObject: JsonObject; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al index 01c381741d..9e59c35afe 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al @@ -10,7 +10,7 @@ using System.Security.Authentication; using System.Azure.KeyVault; using System.Environment; -codeunit 6390 SignUpAuthentication +codeunit 6390 "SignUp Authentication" { Access = Internal; InherentEntitlements = X; @@ -18,8 +18,8 @@ codeunit 6390 SignUpAuthentication #region variables var - SignUpConnectionSetup: Record SignUpConnectionSetup; - SignUpHelpersImpl: Codeunit SignUpHelpers; + SignUpConnectionSetup: Record "SignUp Connection Setup"; + SignUpHelpersImpl: Codeunit "SignUp Helpers"; BearerTxt: Label 'Bearer %1', Comment = '%1 = text value', Locked = true; AuthURLTxt: Label 'https://login.microsoftonline.com/%1/oauth2/token', Comment = '%1 Entra Tenant Id', Locked = true; AuthTemplateTxt: Label 'grant_type=client_credentials&client_id=%1&client_secret=%2&resource=%3', Locked = true; @@ -211,7 +211,7 @@ codeunit 6390 SignUpAuthentication [NonDebuggable] local procedure GetClientCredentials(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage): Boolean var - SignUpAPIRequests: Codeunit SignUpAPIRequests; + SignUpAPIRequests: Codeunit "SignUp API Requests"; begin SignUpAPIRequests.GetMarketPlaceCredentials(HttpRequestMessage, HttpResponseMessage); diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpConnection.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpConnection.Codeunit.al index a43e301755..424c00ac64 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpConnection.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpConnection.Codeunit.al @@ -7,7 +7,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.EServices.EDocument; using System.Utilities; -codeunit 6391 SignUpConnection +codeunit 6391 "SignUp Connection" { Access = Internal; InherentEntitlements = X; @@ -17,8 +17,8 @@ codeunit 6391 SignUpConnection #region variables var - SignUpAPIRequests: Codeunit SignUpAPIRequests; - SignUpHelpersImpl: Codeunit SignUpHelpers; + SignUpAPIRequests: Codeunit "SignUp API Requests"; + SignUpHelpersImpl: Codeunit "SignUp Helpers"; UnsuccessfulResponseErr: Label 'There was an error sending the request. Response code: %1 and error message: %2', Comment = '%1 - http response status code, e.g. 400, %2- error message'; EnvironmentBlocksErr: Label 'The request to send documents has been blocked. To resolve the problem, enable outgoing HTTP requests for the E-Document apps on the Extension Management page.'; FourZeroThreeErr: Label 'You do not have a valid subscription.'; @@ -118,7 +118,7 @@ codeunit 6391 SignUpConnection /// procedure UpdateMetadataProfile() var - SignUpMetadataProfile: Record SignUpMetadataProfile; + SignUpMetadataProfile: Record "SignUp Metadata Profile"; HttpRequestMessage: HttpRequestMessage; HttpResponseMessage: HttpResponseMessage; MetadataProfileContent: Text; @@ -160,7 +160,7 @@ codeunit 6391 SignUpConnection EDocumentErrorHelper.LogSimpleErrorMessage(EDocument, StrSubstNo(this.UnsuccessfulResponseErr, HttpResponseMessage.HttpStatusCode, HttpResponseMessage.ReasonPhrase)); end; - local procedure MetadataProfileJsonToTable(JsonText: Text; var SignUpMetadataProfile: Record SignUpMetadataProfile): Boolean + local procedure MetadataProfileJsonToTable(JsonText: Text; var SignUpMetadataProfile: Record "SignUp Metadata Profile"): Boolean var JsonObject, ProfileJsonObject, ProcessIdentifierJsonObject, DocumentIdentifierJsonObject : JsonObject; JsonArray: JsonArray; @@ -207,7 +207,7 @@ codeunit 6391 SignUpConnection exit(not SignUpMetadataProfile.IsEmpty()); end; - local procedure DeleteUnusedMetadataProfileReferenses(var SignUpMetadataProfile: Record SignUpMetadataProfile) + local procedure DeleteUnusedMetadataProfileReferenses(var SignUpMetadataProfile: Record "SignUp Metadata Profile") var EDocumentService: Record "E-Document Service"; EDocServiceSupportedType: Record "E-Doc. Service Supported Type"; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpHelpers.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpHelpers.Codeunit.al index 33aadeebab..f952f95ecd 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpHelpers.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpHelpers.Codeunit.al @@ -4,13 +4,12 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -using System.Reflection; using Microsoft.Utilities; using System.DateTime; using System.Integration; using Microsoft.eServices.EDocument; -codeunit 6385 SignUpHelpers +codeunit 6385 "SignUp Helpers" { Access = Internal; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfile.Table.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfile.Table.al index c52d1cf183..1b09280c6b 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfile.Table.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfile.Table.al @@ -4,12 +4,12 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -table 6382 SignUpMetadataProfile +table 6382 "SignUp Metadata Profile" { Caption = 'MetadataProfile'; Access = Internal; DataClassification = CustomerContent; - LookupPageId = SignUpMetadataProfiles; + LookupPageId = "SignUp Metadata Profiles"; fields { diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfiles.Page.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfiles.Page.al index 2fcd343821..026d1ee785 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfiles.Page.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfiles.Page.al @@ -4,10 +4,10 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -page 6381 SignUpMetadataProfiles +page 6381 "SignUp Metadata Profiles" { PageType = List; - SourceTable = SignUpMetadataProfile; + SourceTable = "SignUp Metadata Profile"; ApplicationArea = All; UsageCategory = None; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al index 63cd053722..babfcb8efb 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al @@ -10,7 +10,7 @@ using System.Utilities; using Microsoft.eServices.EDocument.Integration.Send; using Microsoft.eServices.EDocument.Integration.Receive; -codeunit 6383 SignUpProcessing +codeunit 6383 "SignUp Processing" { Access = Internal; InherentEntitlements = X; @@ -23,8 +23,8 @@ codeunit 6383 SignUpProcessing #region variables var - SignUpConnection: Codeunit SignUpConnection; - SignUpHelpersImpl: Codeunit SignUpHelpers; + SignUpConnection: Codeunit "SignUp Connection"; + SignUpHelpersImpl: Codeunit "SignUp Helpers"; EDocumentErrorHelper: Codeunit "E-Document Error Helper"; EDocumentLogHelper: Codeunit "E-Document Log Helper"; CouldNotRetrieveDocumentErr: Label 'Could not retrieve document with id: %1 from the service', Comment = '%1 - Document ID'; @@ -289,7 +289,7 @@ codeunit 6383 SignUpProcessing local procedure ParseReceivedDocument(InputTxt: Text; var DocumentId: Text): Boolean var - SignUpHelpers: Codeunit SignUpHelpers; + SignUpHelpers: Codeunit "SignUp Helpers"; begin DocumentId := SignUpHelpers.GetJsonValueFromText(InputTxt, this.TransactionIdTxt); exit(DocumentId <> ''); @@ -401,7 +401,7 @@ codeunit 6383 SignUpProcessing local procedure SendAcknowledgePatch(EDocument: Record "E-Document"; EDocumentService: Record "E-Document Service"): Boolean var EDocumentServiceStatus: Record "E-Document Service Status"; - SignUpAPIRequests: Codeunit SignUpAPIRequests; + SignUpAPIRequests: Codeunit "SignUp API Requests"; HttpResponseMessage: HttpResponseMessage; HttpRequestMessage: HttpRequestMessage; begin diff --git a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationHelpers.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationHelpers.Codeunit.al index 8d490463f0..d13c1e5fdb 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationHelpers.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationHelpers.Codeunit.al @@ -15,7 +15,7 @@ codeunit 148196 IntegrationHelpers internal procedure SetAPICode(Path: Text) var - SignUpConnectionSetup: Record SignUpConnectionSetup; + SignUpConnectionSetup: Record "SignUp Connection Setup"; begin SignUpConnectionSetup.Get(); SignUpConnectionSetup."Service URL" := this.SetMockServiceUrl(Path); @@ -24,8 +24,8 @@ codeunit 148196 IntegrationHelpers internal procedure SetCommonConnectionSetup() var - SignUpConnectionSetup: Record SignUpConnectionSetup; - SignUpAuthentication: Codeunit SignUpAuthentication; + SignUpConnectionSetup: Record "SignUp Connection Setup"; + SignUpAuthentication: Codeunit "SignUp Authentication"; begin SignUpConnectionSetup.Get(); SignUpAuthentication.StorageSet(SignUpConnectionSetup."Root App ID", this.DummyId()); diff --git a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al index 21087e2d5c..a486f8626d 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al @@ -19,7 +19,7 @@ codeunit 148195 IntegrationTests { Subtype = Test; - Permissions = tabledata SignUpConnectionSetup = rimd, + Permissions = tabledata "SignUp Connection Setup" = rimd, tabledata "E-Document" = r; var @@ -504,7 +504,7 @@ codeunit 148195 IntegrationTests [Test] procedure GetMetadataProfiles() var - SignUpMetadataProfile: Record SignUpMetadataProfile; + SignUpMetadataProfile: Record "SignUp Metadata Profile"; EDocServiceSupportedTypes: TestPage "E-Doc Service Supported Types"; begin this.Initialize(); @@ -517,15 +517,15 @@ codeunit 148195 IntegrationTests EDocServiceSupportedTypes.PopulateMetaData.Invoke(); EDocServiceSupportedTypes.Close(); - this.Assert.TableIsNotEmpty(Database::SignUpMetadataProfile); + this.Assert.TableIsNotEmpty(Database::"SignUp Metadata Profile"); end; local procedure Initialize() var - SignUpConnectionSetup: Record SignUpConnectionSetup; + SignUpConnectionSetup: Record "SignUp Connection Setup"; CompanyInformation: Record "Company Information"; ServiceParticipant: Record "Service Participant"; - SignUpAuthentication: Codeunit SignUpAuthentication; + SignUpAuthentication: Codeunit "SignUp Authentication"; begin this.LibraryLowerPermissions.SetOutsideO365Scope(); @@ -581,7 +581,7 @@ codeunit 148195 IntegrationTests local procedure CreateDefaultMetadataProfile() var - SignUpMetadataProfile: Record SignUpMetadataProfile; + SignUpMetadataProfile: Record "SignUp Metadata Profile"; begin if not SignUpMetadataProfile.IsEmpty() then SignUpMetadataProfile.DeleteAll(true); From f06e9f1f5b6bf81e0304bdbe31b7139cc8847a30 Mon Sep 17 00:00:00 2001 From: geschwint Date: Thu, 13 Feb 2025 13:39:09 +0100 Subject: [PATCH 58/63] Renumber objects to range 6440 .. 6449 --- Apps/W1/EDocumentConnectors/SignUp/app/app.json | 4 ++-- .../src/Integration/SignUpCompanyInformationExt.PageExt.al | 2 +- .../src/Integration/SignUpCompanyInformationExt.TableExt.al | 4 ++-- .../app/src/Integration/SignUpEDocSvcTypeExt.TableExt.al | 4 ++-- .../app/src/Integration/SignUpEDocSvcTypePageExt.PageExt.al | 2 +- .../SignUp/app/src/Integration/SignUpEDocumentExt.TableExt.al | 4 ++-- .../app/src/Integration/SignUpIntegrationEnumExt.EnumExt.al | 4 ++-- .../app/src/Integration/SignUpIntegrationImpl.Codeunit.al | 2 +- .../app/src/Permissions/SignUpEDCOEdit.PermissionSet.al | 2 +- .../app/src/Permissions/SignUpEDCOObjects.PermissionSet.al | 2 +- .../app/src/Permissions/SignUpEDCORead.PermissionSet.al | 2 +- .../SignUp/app/src/Setup/SignUpConnectionSetup.Table.al | 2 +- .../SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al | 2 +- .../SignUp/app/src/Setup/SignUpEnvironmentType.Enum.al | 2 +- .../SignUp/app/src/SignUpAPIRequests.Codeunit.al | 2 +- .../SignUp/app/src/SignUpAuthentication.Codeunit.al | 2 +- .../SignUp/app/src/SignUpConnection.Codeunit.al | 2 +- .../SignUp/app/src/SignUpHelpers.Codeunit.al | 2 +- .../SignUp/app/src/SignUpMetadataProfile.Table.al | 2 +- .../SignUp/app/src/SignUpMetadataProfiles.Page.al | 2 +- .../SignUp/app/src/SignUpProcessing.Codeunit.al | 2 +- 21 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/app.json b/Apps/W1/EDocumentConnectors/SignUp/app/app.json index c08e5ea786..7db3feb644 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/app.json +++ b/Apps/W1/EDocumentConnectors/SignUp/app/app.json @@ -24,8 +24,8 @@ "platform": "26.0.0.0", "idRanges": [ { - "from": 6380, - "to": 6399 + "from": 6440, + "to": 6449 } ], "resourceExposurePolicy": { diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.PageExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.PageExt.al index 661072a27a..5084452a96 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.PageExt.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.PageExt.al @@ -6,7 +6,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.Foundation.Company; using Microsoft.eServices.EDocument; -pageextension 6381 "SignUp Company Information Ext" extends "Company Information" +pageextension 6440 "SignUp Company Information Ext" extends "Company Information" { layout { diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.TableExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.TableExt.al index 6ed711ec7b..9fc3e98636 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.TableExt.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpCompanyInformationExt.TableExt.al @@ -5,11 +5,11 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.Foundation.Company; -tableextension 6381 "SignUp Company Information Ext" extends "Company Information" +tableextension 6440 "SignUp Company Information Ext" extends "Company Information" { fields { - field(6381; "SignUp Service Participant Id"; Text[100]) + field(6440; "SignUp Service Participant Id"; Text[100]) { Caption = 'Service Participant Id'; ToolTip = 'Specifies the PEPPOL participant identifier registered for your company in the ExFlow E-Invoicing subscription. This identifier is used when you are sending/receiving documents via the PEPPOL network.'; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcTypeExt.TableExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcTypeExt.TableExt.al index ceceb691a6..bf9148a9f3 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcTypeExt.TableExt.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcTypeExt.TableExt.al @@ -6,11 +6,11 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.eServices.EDocument; -tableextension 6383 "SignUp E-Doc. Svc. Type Ext" extends "E-Doc. Service Supported Type" +tableextension 6441 "SignUp E-Doc. Svc. Type Ext" extends "E-Doc. Service Supported Type" { fields { - field(6381; "Profile Id"; Integer) + field(6440; "Profile Id"; Integer) { Caption = 'Profile Id'; ToolTip = 'The unique identifier for the metadata profile.'; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcTypePageExt.PageExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcTypePageExt.PageExt.al index a53844d979..4a67da2d1c 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcTypePageExt.PageExt.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocSvcTypePageExt.PageExt.al @@ -6,7 +6,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.eServices.EDocument; -pageextension 6383 "SignUp EDoc. Svc. Type PageExt" extends "E-Doc Service Supported Types" +pageextension 6441 "SignUp EDoc. Svc. Type PageExt" extends "E-Doc Service Supported Types" { layout { diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocumentExt.TableExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocumentExt.TableExt.al index 7a8e9dbf49..bd290f2448 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocumentExt.TableExt.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpEDocumentExt.TableExt.al @@ -6,11 +6,11 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.eServices.EDocument; -tableextension 6382 "SignUp E-Document Ext" extends "E-Document" +tableextension 6442 "SignUp E-Document Ext" extends "E-Document" { fields { - field(6381; "SignUp Document Id"; Text[50]) + field(6440; "SignUp Document Id"; Text[50]) { Caption = 'SignUp Document ID'; ToolTip = 'This value is used by ExFlow E-Invoicing'; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationEnumExt.EnumExt.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationEnumExt.EnumExt.al index ded0393c27..59e28180c9 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationEnumExt.EnumExt.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationEnumExt.EnumExt.al @@ -6,9 +6,9 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.eServices.EDocument.Integration; using Microsoft.eServices.EDocument.Integration.Interfaces; -enumextension 6380 "SignUp Integration Enum Ext" extends "Service Integration" +enumextension 6440 "SignUp Integration Enum Ext" extends "Service Integration" { - value(6380; "ExFlow E-Invoicing") + value(6440; "ExFlow E-Invoicing") { Caption = 'ExFlow E-Invoicing'; Implementation = IDocumentSender = "SignUp Integration Impl.", IDocumentReceiver = "SignUp Integration Impl."; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationImpl.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationImpl.Codeunit.al index d9dc997b80..46a1963646 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationImpl.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Integration/SignUpIntegrationImpl.Codeunit.al @@ -11,7 +11,7 @@ using Microsoft.eServices.EDocument.Integration.Send; using Microsoft.eServices.EDocument.Integration.Receive; -codeunit 6386 "SignUp Integration Impl." implements IDocumentSender, IDocumentReceiver, IDocumentResponseHandler, IReceivedDocumentMarker +codeunit 6440 "SignUp Integration Impl." implements IDocumentSender, IDocumentReceiver, IDocumentResponseHandler, IReceivedDocumentMarker { Access = Internal; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al index 643743d546..731f6e504b 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al @@ -4,7 +4,7 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -permissionset 6382 "SignUp EDCO Edit" +permissionset 6442 "SignUp EDCO Edit" { Access = Internal; Assignable = true; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOObjects.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOObjects.PermissionSet.al index 2485fe99e8..96bdb8cfbb 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOObjects.PermissionSet.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOObjects.PermissionSet.al @@ -6,7 +6,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.eServices.EDocument; -permissionset 6380 "SignUp EDCO Objects" +permissionset 6440 "SignUp EDCO Objects" { Access = Internal; Assignable = false; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al index aa51c108ea..2428ebbd0c 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al @@ -6,7 +6,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.eServices.EDocument; -permissionset 6381 "SignUp EDCO Read" +permissionset 6441 "SignUp EDCO Read" { Access = Internal; Assignable = true; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al index 6f9446072b..f41935fda6 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al @@ -4,7 +4,7 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -table 6381 "SignUp Connection Setup" +table 6440 "SignUp Connection Setup" { Access = Internal; DataPerCompany = false; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al index 7d9f6fb43d..2243a77b1f 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al @@ -8,7 +8,7 @@ using System.Telemetry; using Microsoft.Foundation.Company; using System.Environment; -page 6380 "SignUp Connection Setup Card" +page 6440 "SignUp Connection Setup Card" { AdditionalSearchTerms = 'SignUp,electronic document,e-invoice,e-document,external,connection,connector'; PageType = Card; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpEnvironmentType.Enum.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpEnvironmentType.Enum.al index f34cd5084a..84d8345f0a 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpEnvironmentType.Enum.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpEnvironmentType.Enum.al @@ -4,7 +4,7 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -enum 6380 "SignUp Environment Type" +enum 6440 "SignUp Environment Type" { Access = Internal; Caption = 'Environment Type', Locked = true; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAPIRequests.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAPIRequests.Codeunit.al index cea7020c3b..5f2a95f08c 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAPIRequests.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAPIRequests.Codeunit.al @@ -13,7 +13,7 @@ using System.Utilities; using System.Xml; using System.Environment; -codeunit 6389 "SignUp API Requests" +codeunit 6441 "SignUp API Requests" { Access = Internal; InherentEntitlements = X; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al index 9e59c35afe..7c2b826beb 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al @@ -10,7 +10,7 @@ using System.Security.Authentication; using System.Azure.KeyVault; using System.Environment; -codeunit 6390 "SignUp Authentication" +codeunit 6442 "SignUp Authentication" { Access = Internal; InherentEntitlements = X; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpConnection.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpConnection.Codeunit.al index 424c00ac64..78cd970b11 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpConnection.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpConnection.Codeunit.al @@ -7,7 +7,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.EServices.EDocument; using System.Utilities; -codeunit 6391 "SignUp Connection" +codeunit 6443 "SignUp Connection" { Access = Internal; InherentEntitlements = X; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpHelpers.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpHelpers.Codeunit.al index f952f95ecd..c9931da4b9 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpHelpers.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpHelpers.Codeunit.al @@ -9,7 +9,7 @@ using System.DateTime; using System.Integration; using Microsoft.eServices.EDocument; -codeunit 6385 "SignUp Helpers" +codeunit 6444 "SignUp Helpers" { Access = Internal; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfile.Table.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfile.Table.al index 1b09280c6b..6300a20496 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfile.Table.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfile.Table.al @@ -4,7 +4,7 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -table 6382 "SignUp Metadata Profile" +table 6441 "SignUp Metadata Profile" { Caption = 'MetadataProfile'; Access = Internal; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfiles.Page.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfiles.Page.al index 026d1ee785..753b871f80 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfiles.Page.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpMetadataProfiles.Page.al @@ -4,7 +4,7 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -page 6381 "SignUp Metadata Profiles" +page 6441 "SignUp Metadata Profiles" { PageType = List; SourceTable = "SignUp Metadata Profile"; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al index babfcb8efb..316caf1303 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpProcessing.Codeunit.al @@ -10,7 +10,7 @@ using System.Utilities; using Microsoft.eServices.EDocument.Integration.Send; using Microsoft.eServices.EDocument.Integration.Receive; -codeunit 6383 "SignUp Processing" +codeunit 6445 "SignUp Processing" { Access = Internal; InherentEntitlements = X; From 264bfb0c916caca507826b83ead940636e2f1600 Mon Sep 17 00:00:00 2001 From: geschwint Date: Thu, 13 Feb 2025 15:21:17 +0100 Subject: [PATCH 59/63] Restore target=onprem to use internal KeyVault --- Apps/W1/EDocumentConnectors/SignUp/app/app.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/app.json b/Apps/W1/EDocumentConnectors/SignUp/app/app.json index 7db3feb644..b8ed17284a 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/app.json +++ b/Apps/W1/EDocumentConnectors/SignUp/app/app.json @@ -34,7 +34,7 @@ "includeSourceInSymbolFile": true }, "application": "26.0.0.0", - "target": "Cloud", + "target": "OnPrem", "features": [ "TranslationFile" ] From 8fca780279e5b30101b0209c37ddfbc570af4cd6 Mon Sep 17 00:00:00 2001 From: geschwint Date: Fri, 14 Feb 2025 07:39:24 +0100 Subject: [PATCH 60/63] E2E Tests Update --- .../test/src/IntegrationTests.Codeunit.al | 174 ++++++++++++------ 1 file changed, 118 insertions(+), 56 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al index a486f8626d..6a6ff584cc 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al @@ -5,14 +5,15 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; +using System.Threading; +using System.Environment.Configuration; +using System.Apps; using Microsoft.eServices.EDocument; using Microsoft.Inventory.Item; using Microsoft.EServices.EDocument.Service.Participant; using Microsoft.Foundation.Company; -//using Microsoft.Purchases.Document; using Microsoft.Purchases.Vendor; using Microsoft.Sales.Customer; -using System.Threading; using Microsoft.eServices.EDocument.Integration; codeunit 148195 IntegrationTests @@ -36,25 +37,26 @@ codeunit 148195 IntegrationTests IsInitialized: Boolean; IncorrectValueErr: Label 'Wrong value', Locked = true; + #region tests + /// /// Test needs MockService running to work. /// [Test] - [HandlerFunctions('ExternalHttpRequestHandler')] procedure SubmitDocument() var EDocument: Record "E-Document"; JobQueueEntry: Record "Job Queue Entry"; + EDocumentServiceStatus: Record "E-Document Service Status"; EDocumentPage: TestPage "E-Document"; EDocLogList: List of [Enum "E-Document Service Status"]; begin - // Steps: // Pending response -> Sent this.Initialize(); // [Given] Team member this.LibraryLowerPermissions.SetTeamMember(); - this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCORead'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Read'); // [When] Posting invoice and EDocument is created this.LibraryEDocument.PostInvoice(this.Customer); @@ -75,9 +77,10 @@ codeunit 148195 IntegrationTests this.Assert.AreEqual(EDocument."Document No.", EDocumentPage."Document No.".Value(), this.IncorrectValueErr); // [THEN] E-Document Service Status has "Pending Response" - this.Assert.AreEqual(this.EDocumentService.Code, EDocumentPage.EdocoumentServiceStatus."E-Document Service Code".Value(), this.IncorrectValueErr); - this.Assert.AreEqual(Format(Enum::"E-Document Service Status"::"Pending Response"), EDocumentPage.EdocoumentServiceStatus.Status.Value(), this.IncorrectValueErr); - this.Assert.AreEqual('2', EDocumentPage.EdocoumentServiceStatus.Logs.Value(), this.IncorrectValueErr); + EDocumentServiceStatus := this.GetEDocumentServiceStatus(EDocument."Entry No"); + this.Assert.AreEqual(this.EDocumentService.Code, EDocumentServiceStatus."E-Document Service Code", this.IncorrectValueErr); + this.Assert.AreEqual(Enum::"E-Document Service Status"::"Pending Response", EDocumentServiceStatus.Status, this.IncorrectValueErr); + this.Assert.AreEqual(2, this.LogsCount(EDocumentServiceStatus), this.IncorrectValueErr); Clear(EDocLogList); EDocLogList.Add(Enum::"E-Document Service Status"::"Exported"); @@ -106,9 +109,10 @@ codeunit 148195 IntegrationTests this.Assert.AreEqual(EDocument."Document No.", EDocumentPage."Document No.".Value(), this.IncorrectValueErr); // [THEN] E-Document Service Status has Sent - this.Assert.AreEqual(this.EDocumentService.Code, EDocumentPage.EdocoumentServiceStatus."E-Document Service Code".Value(), this.IncorrectValueErr); - this.Assert.AreEqual(Format(Enum::"E-Document Service Status"::"Pending Response"), EDocumentPage.EdocoumentServiceStatus.Status.Value(), this.IncorrectValueErr); - this.Assert.AreEqual('3', EDocumentPage.EdocoumentServiceStatus.Logs.Value(), this.IncorrectValueErr); + EDocumentServiceStatus := this.GetEDocumentServiceStatus(EDocument."Entry No"); + this.Assert.AreEqual(this.EDocumentService.Code, EDocumentServiceStatus."E-Document Service Code", this.IncorrectValueErr); + this.Assert.AreEqual(Enum::"E-Document Service Status"::"Pending Response", EDocumentServiceStatus.Status, this.IncorrectValueErr); + this.Assert.AreEqual(3, this.LogsCount(EDocumentServiceStatus), this.IncorrectValueErr); Clear(EDocLogList); EDocLogList.Add(Enum::"E-Document Service Status"::"Exported"); @@ -130,6 +134,7 @@ codeunit 148195 IntegrationTests var EDocument: Record "E-Document"; JobQueueEntry: Record "Job Queue Entry"; + EDocumentServiceStatus: Record "E-Document Service Status"; EDocumentPage: TestPage "E-Document"; EDocLogList: List of [Enum "E-Document Service Status"]; begin @@ -140,7 +145,7 @@ codeunit 148195 IntegrationTests // [Given] Team member this.LibraryLowerPermissions.SetTeamMember(); - this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCORead'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Read'); // [When] Posting invoice and EDocument is created this.LibraryEDocument.PostInvoice(this.Customer); @@ -163,9 +168,10 @@ codeunit 148195 IntegrationTests this.Assert.AreEqual(EDocument."Document No.", EDocumentPage."Document No.".Value(), this.IncorrectValueErr); // [THEN] E-Document Service Status has pending response - this.Assert.AreEqual(this.EDocumentService.Code, EDocumentPage.EdocoumentServiceStatus."E-Document Service Code".Value(), this.IncorrectValueErr); - this.Assert.AreEqual(Format(Enum::"E-Document Service Status"::"Pending Response"), EDocumentPage.EdocoumentServiceStatus.Status.Value(), this.IncorrectValueErr); - this.Assert.AreEqual('2', EDocumentPage.EdocoumentServiceStatus.Logs.Value(), this.IncorrectValueErr); + EDocumentServiceStatus := this.GetEDocumentServiceStatus(EDocument."Entry No"); + this.Assert.AreEqual(this.EDocumentService.Code, EDocumentServiceStatus."E-Document Service Code", this.IncorrectValueErr); + this.Assert.AreEqual(Enum::"E-Document Service Status"::"Pending Response", EDocumentServiceStatus.Status, this.IncorrectValueErr); + this.Assert.AreEqual(2, this.LogsCount(EDocumentServiceStatus), this.IncorrectValueErr); Clear(EDocLogList); EDocLogList.Add(Enum::"E-Document Service Status"::"Exported"); EDocLogList.Add(Enum::"E-Document Service Status"::"Pending Response"); @@ -177,9 +183,9 @@ codeunit 148195 IntegrationTests EDocumentPage.Close(); // [WHEN] Executing Get Response succesfully - this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCOEdit'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Edit'); this.IntegrationHelpers.SetAPICode('/signup/200/response-pending'); - this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCORead'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Read'); JobQueueEntry.FindJobQueueEntry(JobQueueEntry."Object Type to Run"::Codeunit, Codeunit::"E-Document Get Response"); this.LibraryJobQueue.RunJobQueueDispatcher(JobQueueEntry); @@ -196,9 +202,10 @@ codeunit 148195 IntegrationTests this.Assert.AreEqual(EDocument."Document No.", EDocumentPage."Document No.".Value(), this.IncorrectValueErr); // [THEN] E-Document Service Status has pending response - this.Assert.AreEqual(this.EDocumentService.Code, EDocumentPage.EdocoumentServiceStatus."E-Document Service Code".Value(), this.IncorrectValueErr); - this.Assert.AreEqual(Format(Enum::"E-Document Service Status"::"Pending Response"), EDocumentPage.EdocoumentServiceStatus.Status.Value(), this.IncorrectValueErr); - this.Assert.AreEqual('3', EDocumentPage.EdocoumentServiceStatus.Logs.Value(), this.IncorrectValueErr); + EDocumentServiceStatus := this.GetEDocumentServiceStatus(EDocument."Entry No"); + this.Assert.AreEqual(this.EDocumentService.Code, EDocumentServiceStatus."E-Document Service Code", this.IncorrectValueErr); + this.Assert.AreEqual(Enum::"E-Document Service Status"::"Pending Response", EDocumentServiceStatus.Status, this.IncorrectValueErr); + this.Assert.AreEqual(3, this.LogsCount(EDocumentServiceStatus), this.IncorrectValueErr); Clear(EDocLogList); EDocLogList.Add(Enum::"E-Document Service Status"::"Exported"); @@ -212,9 +219,9 @@ codeunit 148195 IntegrationTests EDocumentPage.Close(); // [WHEN] Executing Get Response succesfully - this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCOEdit'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Edit'); this.IntegrationHelpers.SetAPIWith200Code(); - this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCORead'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Read'); JobQueueEntry.FindJobQueueEntry(JobQueueEntry."Object Type to Run"::Codeunit, Codeunit::"E-Document Get Response"); this.LibraryJobQueue.RunJobQueueDispatcher(JobQueueEntry); @@ -231,9 +238,10 @@ codeunit 148195 IntegrationTests this.Assert.AreEqual(EDocument."Document No.", EDocumentPage."Document No.".Value(), this.IncorrectValueErr); // [THEN] E-Document Service Status has pending response - this.Assert.AreEqual(this.EDocumentService.Code, EDocumentPage.EdocoumentServiceStatus."E-Document Service Code".Value(), this.IncorrectValueErr); - this.Assert.AreEqual(Format(Enum::"E-Document Service Status"::"Pending Response"), EDocumentPage.EdocoumentServiceStatus.Status.Value(), this.IncorrectValueErr); - this.Assert.AreEqual('4', EDocumentPage.EdocoumentServiceStatus.Logs.Value(), this.IncorrectValueErr); + EDocumentServiceStatus := this.GetEDocumentServiceStatus(EDocument."Entry No"); + this.Assert.AreEqual(this.EDocumentService.Code, EDocumentServiceStatus."E-Document Service Code", this.IncorrectValueErr); + this.Assert.AreEqual(Enum::"E-Document Service Status"::"Pending Response", EDocumentServiceStatus.Status, this.IncorrectValueErr); + this.Assert.AreEqual(4, this.LogsCount(EDocumentServiceStatus), this.IncorrectValueErr); Clear(EDocLogList); EDocLogList.Add(Enum::"E-Document Service Status"::"Exported"); @@ -257,6 +265,7 @@ codeunit 148195 IntegrationTests var EDocument: Record "E-Document"; JobQueueEntry: Record "Job Queue Entry"; + EDocumentServiceStatus: Record "E-Document Service Status"; EDocumentPage: TestPage "E-Document"; EDocLogList: List of [Enum "E-Document Service Status"]; begin @@ -267,7 +276,7 @@ codeunit 148195 IntegrationTests // [Given] Team member this.LibraryLowerPermissions.SetTeamMember(); - this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCORead'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Read'); // [When] Posting invoice and EDocument is created this.LibraryEDocument.PostInvoice(this.Customer); @@ -290,9 +299,10 @@ codeunit 148195 IntegrationTests this.Assert.AreEqual(EDocument."Document No.", EDocumentPage."Document No.".Value(), this.IncorrectValueErr); // [THEN] E-Document Service Status has pending response - this.Assert.AreEqual(this.EDocumentService.Code, EDocumentPage.EdocoumentServiceStatus."E-Document Service Code".Value(), this.IncorrectValueErr); - this.Assert.AreEqual(Format(Enum::"E-Document Service Status"::"Pending Response"), EDocumentPage.EdocoumentServiceStatus.Status.Value(), this.IncorrectValueErr); - this.Assert.AreEqual('2', EDocumentPage.EdocoumentServiceStatus.Logs.Value(), this.IncorrectValueErr); + EDocumentServiceStatus := this.GetEDocumentServiceStatus(EDocument."Entry No"); + this.Assert.AreEqual(this.EDocumentService.Code, EDocumentServiceStatus."E-Document Service Code", this.IncorrectValueErr); + this.Assert.AreEqual(Enum::"E-Document Service Status"::"Pending Response", EDocumentServiceStatus.Status, this.IncorrectValueErr); + this.Assert.AreEqual(2, this.LogsCount(EDocumentServiceStatus), this.IncorrectValueErr); Clear(EDocLogList); EDocLogList.Add(Enum::"E-Document Service Status"::"Exported"); @@ -305,9 +315,9 @@ codeunit 148195 IntegrationTests EDocumentPage.Close(); // [WHEN] Executing Get Response succesfully - this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCOEdit'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Edit'); this.IntegrationHelpers.SetAPICode('/signup/200/response-error'); - this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCORead'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Read'); JobQueueEntry.FindJobQueueEntry(JobQueueEntry."Object Type to Run"::Codeunit, Codeunit::"E-Document Get Response"); this.LibraryJobQueue.RunJobQueueDispatcher(JobQueueEntry); @@ -324,9 +334,10 @@ codeunit 148195 IntegrationTests this.Assert.AreEqual(EDocument."Document No.", EDocumentPage."Document No.".Value(), this.IncorrectValueErr); // [THEN] E-Document Service Status has sending error - this.Assert.AreEqual(this.EDocumentService.Code, EDocumentPage.EdocoumentServiceStatus."E-Document Service Code".Value(), this.IncorrectValueErr); - this.Assert.AreEqual(Format(Enum::"E-Document Service Status"::"Sending Error"), EDocumentPage.EdocoumentServiceStatus.Status.Value(), this.IncorrectValueErr); - this.Assert.AreEqual('3', EDocumentPage.EdocoumentServiceStatus.Logs.Value(), this.IncorrectValueErr); + EDocumentServiceStatus := this.GetEDocumentServiceStatus(EDocument."Entry No"); + this.Assert.AreEqual(this.EDocumentService.Code, EDocumentServiceStatus."E-Document Service Code", this.IncorrectValueErr); + this.Assert.AreEqual(Enum::"E-Document Service Status"::"Sending Error", EDocumentServiceStatus.Status, this.IncorrectValueErr); + this.Assert.AreEqual(3, this.LogsCount(EDocumentServiceStatus), this.IncorrectValueErr); Clear(EDocLogList); EDocLogList.Add(Enum::"E-Document Service Status"::"Exported"); @@ -362,9 +373,10 @@ codeunit 148195 IntegrationTests this.Assert.AreEqual(EDocument."Document No.", EDocumentPage."Document No.".Value(), this.IncorrectValueErr); // [THEN] E-Document Service Status has pending response - this.Assert.AreEqual(this.EDocumentService.Code, EDocumentPage.EdocoumentServiceStatus."E-Document Service Code".Value(), this.IncorrectValueErr); - this.Assert.AreEqual(Format(Enum::"E-Document Service Status"::"Pending Response"), EDocumentPage.EdocoumentServiceStatus.Status.Value(), this.IncorrectValueErr); - this.Assert.AreEqual('4', EDocumentPage.EdocoumentServiceStatus.Logs.Value(), this.IncorrectValueErr); + EDocumentServiceStatus := this.GetEDocumentServiceStatus(EDocument."Entry No"); + this.Assert.AreEqual(this.EDocumentService.Code, EDocumentServiceStatus."E-Document Service Code", this.IncorrectValueErr); + this.Assert.AreEqual(Enum::"E-Document Service Status"::"Pending Response", EDocumentServiceStatus.Status, this.IncorrectValueErr); + this.Assert.AreEqual(4, this.LogsCount(EDocumentServiceStatus), this.IncorrectValueErr); Clear(EDocLogList); EDocLogList.Add(Enum::"E-Document Service Status"::"Exported"); @@ -378,9 +390,9 @@ codeunit 148195 IntegrationTests this.Assert.AreEqual('', EDocumentPage.ErrorMessagesPart.Description.Value(), this.IncorrectValueErr); EDocumentPage.Close(); - this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCOEdit'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Edit'); this.IntegrationHelpers.SetAPIWith200Code(); - this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCORead'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Read'); JobQueueEntry.FindJobQueueEntry(JobQueueEntry."Object Type to Run"::Codeunit, Codeunit::"E-Document Get Response"); this.LibraryJobQueue.RunJobQueueDispatcher(JobQueueEntry); @@ -398,9 +410,10 @@ codeunit 148195 IntegrationTests this.Assert.AreEqual(EDocument."Document No.", EDocumentPage."Document No.".Value(), this.IncorrectValueErr); // [THEN] E-Document Service Status has pending response - this.Assert.AreEqual(this.EDocumentService.Code, EDocumentPage.EdocoumentServiceStatus."E-Document Service Code".Value(), this.IncorrectValueErr); - this.Assert.AreEqual(Format(Enum::"E-Document Service Status"::"Pending Response"), EDocumentPage.EdocoumentServiceStatus.Status.Value(), this.IncorrectValueErr); - this.Assert.AreEqual('5', EDocumentPage.EdocoumentServiceStatus.Logs.Value(), this.IncorrectValueErr); + EDocumentServiceStatus := this.GetEDocumentServiceStatus(EDocument."Entry No"); + this.Assert.AreEqual(this.EDocumentService.Code, EDocumentServiceStatus."E-Document Service Code", this.IncorrectValueErr); + this.Assert.AreEqual(Enum::"E-Document Service Status"::"Pending Response", EDocumentServiceStatus.Status, this.IncorrectValueErr); + this.Assert.AreEqual(5, this.LogsCount(EDocumentServiceStatus), this.IncorrectValueErr); Clear(EDocLogList); EDocLogList.Add(Enum::"E-Document Service Status"::"Exported"); @@ -423,6 +436,7 @@ codeunit 148195 IntegrationTests procedure SubmitDocumentServiceDown() var EDocument: Record "E-Document"; + EDocumentServiceStatus: Record "E-Document Service Status"; EDocumentPage: TestPage "E-Document"; EDocLogList: List of [Enum "E-Document Service Status"]; begin @@ -431,7 +445,7 @@ codeunit 148195 IntegrationTests // [Given] Team member this.LibraryLowerPermissions.SetTeamMember(); - this.LibraryLowerPermissions.AddPermissionSet('SignUpEDCORead'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Read'); // [When] Posting invoice and EDocument is created this.LibraryEDocument.PostInvoice(this.Customer); @@ -453,9 +467,10 @@ codeunit 148195 IntegrationTests this.Assert.AreEqual(EDocument."Document No.", EDocumentPage."Document No.".Value(), this.IncorrectValueErr); // [THEN] E-Document Service Status has correct error status - this.Assert.AreEqual(this.EDocumentService.Code, EDocumentPage.EdocoumentServiceStatus."E-Document Service Code".Value(), this.IncorrectValueErr); - this.Assert.AreEqual(Format(Enum::"E-Document Service Status"::"Sending Error"), EDocumentPage.EdocoumentServiceStatus.Status.Value(), this.IncorrectValueErr); - this.Assert.AreEqual('2', EDocumentPage.EdocoumentServiceStatus.Logs.Value(), this.IncorrectValueErr); + EDocumentServiceStatus := this.GetEDocumentServiceStatus(EDocument."Entry No"); + this.Assert.AreEqual(this.EDocumentService.Code, EDocumentServiceStatus."E-Document Service Code", this.IncorrectValueErr); + this.Assert.AreEqual(Enum::"E-Document Service Status"::"Sending Error", EDocumentServiceStatus.Status, this.IncorrectValueErr); + this.Assert.AreEqual(2, this.LogsCount(EDocumentServiceStatus), this.IncorrectValueErr); Clear(EDocLogList); EDocLogList.Add(Enum::"E-Document Service Status"::"Exported"); @@ -520,6 +535,21 @@ codeunit 148195 IntegrationTests this.Assert.TableIsNotEmpty(Database::"SignUp Metadata Profile"); end; + #endregion + + #region handlers + + [ModalPageHandler] + internal procedure EDocServicesPageHandler(var EDocumentServicesPage: TestPage "E-Document Services") + begin + EDocumentServicesPage.Filter.SetFilter(Code, this.EDocumentService.Code); + EDocumentServicesPage.OK().Invoke(); + end; + + #endregion + + #region local methods + local procedure Initialize() var SignUpConnectionSetup: Record "SignUp Connection Setup"; @@ -527,6 +557,7 @@ codeunit 148195 IntegrationTests ServiceParticipant: Record "Service Participant"; SignUpAuthentication: Codeunit "SignUp Authentication"; begin + this.AllowEDocConnectorHttpRequests(); this.LibraryLowerPermissions.SetOutsideO365Scope(); SignUpConnectionSetup.DeleteAll(); @@ -539,8 +570,8 @@ codeunit 148195 IntegrationTests this.CreateDefaultMetadataProfile(); this.LibraryEDocument.SetupStandardVAT(); - this.LibraryEDocument.SetupStandardSalesScenario(this.Customer, this.EDocumentService, Enum::"E-Document Format"::"PEPPOL BIS 3.0", Enum::"Service Integration"::"ExFlow E-Invoicing PTE"); - this.LibraryEDocument.SetupStandardPurchaseScenario(this.Vendor, this.EDocumentService, Enum::"E-Document Format"::"PEPPOL BIS 3.0", Enum::"Service Integration"::"ExFlow E-Invoicing PTE"); + this.LibraryEDocument.SetupStandardSalesScenario(this.Customer, this.EDocumentService, Enum::"E-Document Format"::"PEPPOL BIS 3.0", Enum::"Service Integration"::"ExFlow E-Invoicing"); + this.LibraryEDocument.SetupStandardPurchaseScenario(this.Vendor, this.EDocumentService, Enum::"E-Document Format"::"PEPPOL BIS 3.0", Enum::"Service Integration"::"ExFlow E-Invoicing"); this.EDocumentService."Auto Import" := true; this.EDocumentService."Import Minutes between runs" := 5; this.EDocumentService."Import Start Time" := Time(); @@ -612,18 +643,49 @@ codeunit 148195 IntegrationTests exit(158); end; - [ModalPageHandler] - internal procedure EDocServicesPageHandler(var EDocumentServicesPage: TestPage "E-Document Services") + local procedure AllowEDocConnectorHttpRequests() + var + ModuleInfo: ModuleInfo; begin - EDocumentServicesPage.Filter.SetFilter(Code, this.EDocumentService.Code); - EDocumentServicesPage.OK().Invoke(); + if not NavApp.GetModuleInfo('b56171bd-9a8e-47ad-a527-99f476d5af83', ModuleInfo) then + exit; + + this.AllowOutboundHttpRequests(ModuleInfo); + end; + + local procedure AllowOutboundHttpRequests(ModuleInfo: ModuleInfo) + var + NavAppSetting: Record "NAV App Setting"; + ExtensionManagement: Codeunit "Extension Management"; + begin + if not NavAppSetting.Get(ModuleInfo.Id) then begin + NavAppSetting.Init(); + NavAppSetting.Validate("App ID", ModuleInfo.Id); + NavAppSetting.Insert(true); + end; + + if NavAppSetting."Allow HttpClient Requests" then + exit; + + ExtensionManagement.ConfigureExtensionHttpClientRequestsAllowance(ModuleInfo.PackageId, true); end; - [StrMenuHandler] - internal procedure ExternalHttpRequestHandler(Options: Text[1024]; var Choice: Integer; Instruction: Text[1024]) + local procedure GetEDocumentServiceStatus(EntryNo: Integer) EDocumentServiceStatus: Record "E-Document Service Status" + begin + EDocumentServiceStatus.SetLoadFields("E-Document Service Code", Status); + EDocumentServiceStatus.SetRange("E-Document Entry No", EntryNo); + if EDocumentServiceStatus.FindFirst() then + ; + end; + + local procedure LogsCount(EDocumentServiceStatus: Record "E-Document Service Status"): Integer var - ExternalHttpRequestChoice: Option " ","Allow Always","Allow Once","Block Always","Block Once"; + EDocumentLog: Record "E-Document Log"; begin - Choice := ExternalHttpRequestChoice::"Allow Always"; + EDocumentLog.SetRange("Service Code", EDocumentServiceStatus."E-Document Service Code"); + EDocumentLog.SetRange("E-Doc. Entry No", EDocumentServiceStatus."E-Document Entry No"); + exit(EDocumentLog.Count()); end; + + #endregion } \ No newline at end of file From 754dd001a1d4b18f54c8371ba0fb7b935c04c75a Mon Sep 17 00:00:00 2001 From: geschwint Date: Wed, 19 Feb 2025 19:15:29 +0100 Subject: [PATCH 61/63] Object Rename --- ...pEDCOEdit.PermissionSet.al => SignUpEDocEdit.PermissionSet.al} | 0 ...bjects.PermissionSet.al => SignUpEDocObjects.PermissionSet.al} | 0 ...pEDCORead.PermissionSet.al => SignUpEDocRead.PermissionSet.al} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/{SignUpEDCOEdit.PermissionSet.al => SignUpEDocEdit.PermissionSet.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/{SignUpEDCOObjects.PermissionSet.al => SignUpEDocObjects.PermissionSet.al} (100%) rename Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/{SignUpEDCORead.PermissionSet.al => SignUpEDocRead.PermissionSet.al} (100%) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocEdit.PermissionSet.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOEdit.PermissionSet.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocEdit.PermissionSet.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOObjects.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocObjects.PermissionSet.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCOObjects.PermissionSet.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocObjects.PermissionSet.al diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocRead.PermissionSet.al similarity index 100% rename from Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDCORead.PermissionSet.al rename to Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocRead.PermissionSet.al From 516ab523ee02ce07024e79ca9fe01e524372246c Mon Sep 17 00:00:00 2001 From: geschwint Date: Wed, 19 Feb 2025 19:18:06 +0100 Subject: [PATCH 62/63] Adjustments --- .../SignUpEDocEdit.PermissionSet.al | 6 +- .../SignUpEDocObjects.PermissionSet.al | 2 +- .../SignUpEDocRead.PermissionSet.al | 4 +- .../src/Setup/SignUpConnectionSetup.Table.al | 44 +++---- .../Setup/SignUpConnectionSetupCard.Page.al | 68 +++++------ .../src/Setup/SignUpEnvironmentType.Enum.al | 6 +- .../app/src/SignUpAPIRequests.Codeunit.al | 8 +- .../app/src/SignUpAuthentication.Codeunit.al | 108 ++++++++++-------- .../test/src/IntegrationHelpers.Codeunit.al | 6 +- .../test/src/IntegrationTests.Codeunit.al | 24 ++-- 10 files changed, 142 insertions(+), 134 deletions(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocEdit.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocEdit.PermissionSet.al index 731f6e504b..75a2cf2ca0 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocEdit.PermissionSet.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocEdit.PermissionSet.al @@ -4,13 +4,13 @@ // ------------------------------------------------------------------------------------------------ namespace Microsoft.EServices.EDocumentConnector.SignUp; -permissionset 6442 "SignUp EDCO Edit" +permissionset 6442 "SignUp E-Doc Edit" { Access = Internal; Assignable = true; Caption = 'SignUp E-Doc. Connector - Edit', MaxLength = 30; - IncludedPermissionSets = "SignUp EDCO Read"; + IncludedPermissionSets = "SignUp E-Doc Read"; Permissions = tabledata "SignUp Connection Setup" = IMD, - tabledata "SignUp Metadata Profile" = IMD; + tabledata "SignUp Metadata Profile" = IMD; } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocObjects.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocObjects.PermissionSet.al index 96bdb8cfbb..ea8cdde9e8 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocObjects.PermissionSet.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocObjects.PermissionSet.al @@ -6,7 +6,7 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.eServices.EDocument; -permissionset 6440 "SignUp EDCO Objects" +permissionset 6440 "SignUp E-Doc Objects" { Access = Internal; Assignable = false; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocRead.PermissionSet.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocRead.PermissionSet.al index 2428ebbd0c..b86955a547 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocRead.PermissionSet.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Permissions/SignUpEDocRead.PermissionSet.al @@ -6,12 +6,12 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using Microsoft.eServices.EDocument; -permissionset 6441 "SignUp EDCO Read" +permissionset 6441 "SignUp E-Doc Read" { Access = Internal; Assignable = true; Caption = 'SignUp E-Doc. Connector - Read', MaxLength = 30; - IncludedPermissionSets = "SignUp EDCO Objects"; + IncludedPermissionSets = "SignUp E-Doc Objects"; Permissions = tabledata "SignUp Connection Setup" = R, tabledata "SignUp Metadata Profile" = R, tabledata "E-Document Integration Log" = rim; diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al index f41935fda6..691b9818b9 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetup.Table.al @@ -13,10 +13,10 @@ table 6440 "SignUp Connection Setup" fields { - field(1; PK; Code[10]) + field(1; "Primary Key"; Code[10]) { - Caption = 'PK', Locked = true; - ToolTip = 'PK', Locked = true; + Caption = 'Primary Key', Locked = true; + ToolTip = 'Primary Key', Locked = true; } field(2; "Authentication URL"; Text[2048]) { @@ -49,30 +49,30 @@ table 6440 "SignUp Connection Setup" Rec."Service URL" := CopyStr(Rec."Service URL".TrimEnd('/'), 1, MaxStrLen(Rec."Service URL")); end; } - field(7; "Root App ID"; Guid) + field(7; "Marketplace App ID"; Guid) { - Caption = 'Root App ID'; - ToolTip = 'Specifies the root app ID.'; + Caption = 'Marketplace App ID'; + ToolTip = 'Specifies the Marketplace app ID.'; } - field(8; "Root Secret"; Guid) + field(8; "Marketplace Secret"; Guid) { - Caption = 'Root App Secret'; - ToolTip = 'Specifies the root application secret.'; + Caption = 'Marketplace App Secret'; + ToolTip = 'Specifies the Marketplace application secret.'; } - field(9; "Root Tenant"; Guid) + field(9; "Marketplace Tenant"; Guid) { - Caption = 'Root App Tenant'; - ToolTip = 'Specifies the root application tenant.'; + Caption = 'Marketplace App Tenant'; + ToolTip = 'Specifies the Marketplace application tenant.'; } - field(10; "Root Market URL"; Text[2048]) + field(10; "Marketplace URL"; Text[2048]) { - Caption = 'Root Market URL'; - ToolTip = 'Specifies the root market URL.'; + Caption = 'Marketplace URL'; + ToolTip = 'Specifies the Marketplace URL.'; trigger OnValidate() begin - if Rec."Root Market URL" <> '' then - Rec."Root Market URL" := CopyStr(Rec."Root Market URL".TrimEnd('/'), 1, MaxStrLen("Root Market URL")); + if Rec."Marketplace URL" <> '' then + Rec."Marketplace URL" := CopyStr(Rec."Marketplace URL".TrimEnd('/'), 1, MaxStrLen("Marketplace URL")); end; } field(11; "Client Tenant"; Guid) @@ -84,17 +84,9 @@ table 6440 "SignUp Connection Setup" keys { - key(Key1; PK) + key(Key1; "Primary Key") { Clustered = true; } } - - procedure GetSetup(): Boolean - begin - if not IsNullGuid(Rec.SystemId) then - exit(true); - - exit(Rec.Get()); - end; } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al index 2243a77b1f..9509180fc5 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al @@ -64,49 +64,49 @@ page 6440 "SignUp Connection Setup Card" this.SignUpAuthentication.StorageSet(Rec."Client Tenant", this.ClientTenant); end; } - field(RootID; this.RootID) + field(MarketplaceID; this.MarketplaceID) { - Caption = 'Root App ID'; - ToolTip = 'Specifies the root app id token.'; + Caption = 'Marketplace App ID'; + ToolTip = 'Specifies the Marketplace app id token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; Visible = this.FieldsVisible; trigger OnValidate() begin - this.SignUpAuthentication.StorageSet(Rec."Root App ID", this.RootID); + this.SignUpAuthentication.StorageSet(Rec."Marketplace App ID", this.MarketplaceID); end; } - field(RootSecret; this.RootSecret) + field(MarketplaceSecret; this.MarketplaceSecret) { - Caption = 'Root Secret'; - ToolTip = 'Specifies the root secret token.'; + Caption = 'Marketplace Secret'; + ToolTip = 'Specifies the Marketplace secret token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; Visible = this.FieldsVisible; trigger OnValidate() begin - this.SaveSecret(Rec."Root Secret", this.RootSecret) + this.SaveSecret(Rec."Marketplace Secret", this.MarketplaceSecret); end; } - field(RootTenant; this.RootTenant) + field(MarketplaceTenant; this.MarketplaceTenant) { - Caption = 'Root Tenant ID'; - ToolTip = 'Specifies the root tenant id token.'; + Caption = 'Marketplace Tenant ID'; + ToolTip = 'Specifies the Marketplace tenant id token.'; ApplicationArea = Basic, Suite; ExtendedDatatype = Masked; Visible = this.FieldsVisible; trigger OnValidate() begin - this.SignUpAuthentication.StorageSet(Rec."Root Tenant", this.RootTenant); + this.SignUpAuthentication.StorageSet(Rec."Marketplace Tenant", this.MarketplaceTenant); end; } - field(RootUrl; Rec."Root Market URL") + field(MarketplaceUrl; Rec."Marketplace URL") { - Caption = 'Root URL'; - ToolTip = 'Specifies the root url token.'; + Caption = 'Marketplace URL'; + ToolTip = 'Specifies the Marketplace url token.'; ApplicationArea = Basic, Suite; Visible = this.FieldsVisible; } @@ -131,7 +131,7 @@ page 6440 "SignUp Connection Setup Card" { area(processing) { - action(InitOnboarding01) + action(InitOnboardingAction) { ApplicationArea = Basic, Suite; Caption = 'Open Onboarding'; @@ -140,10 +140,11 @@ page 6440 "SignUp Connection Setup Card" trigger OnAction() begin - this.SignUpAuthentication.CreateClientCredentials(); + if IsNullGuid(Rec."Client ID") or IsNullGuid(Rec."Client Secret") then + this.SignUpAuthentication.CreateClientCredentials(); CurrPage.Update(); this.SetPageVariables(); - Hyperlink(this.SignUpAuthentication.GetRootOnboardingUrl()); + Hyperlink(this.SignUpAuthentication.GetMarketplaceOnboardingUrl()); this.FeatureTelemetry.LogUptake('', this.ExternalServiceTok, Enum::"Feature Uptake Status"::"Set up"); end; } @@ -151,7 +152,7 @@ page 6440 "SignUp Connection Setup Card" area(Promoted) { - actionref(InitOnboarding01_Promoted; InitOnboarding01) { } + actionref(InitOnboarding01_Promoted; InitOnboardingAction) { } } } @@ -161,26 +162,28 @@ page 6440 "SignUp Connection Setup Card" begin this.FieldsVisible := not EnvironmentInformation.IsSaaSInfrastructure(); this.SignUpAuthentication.InitConnectionSetup(); - if Rec.Get() then - ; - this.SetPageVariables(); this.FeatureTelemetry.LogUptake('', this.ExternalServiceTok, Enum::"Feature Uptake Status"::Discovered); end; + trigger OnAfterGetCurrRecord() + begin + this.SetPageVariables(); + end; + local procedure SetPageVariables() begin if not IsNullGuid(Rec."Client ID") then - this.ClientID := this.MaskTxt; + this.ClientID := Rec."Client ID"; if not IsNullGuid(Rec."Client Secret") then - this.ClientSecret := this.MaskTxt; + this.ClientSecret := Rec."Client Secret"; if not IsNullGuid(Rec."Client Tenant") then - this.ClientTenant := this.MaskTxt; - if not IsNullGuid(Rec."Root App ID") then - this.RootID := this.MaskTxt; - if not IsNullGuid(Rec."Root Secret") then - this.RootSecret := this.MaskTxt; - if not IsNullGuid(Rec."Root Tenant") then - this.RootTenant := this.MaskTxt; + this.ClientTenant := Rec."Client Tenant"; + if not IsNullGuid(Rec."Marketplace App ID") then + this.MarketplaceID := Rec."Marketplace App ID"; + if not IsNullGuid(Rec."Marketplace Secret") then + this.MarketplaceSecret := Rec."Marketplace Secret"; + if not IsNullGuid(Rec."Marketplace Tenant") then + this.MarketplaceTenant := Rec."Marketplace Tenant"; end; [NonDebuggable] @@ -193,8 +196,7 @@ page 6440 "SignUp Connection Setup Card" SignUpAuthentication: Codeunit "SignUp Authentication"; FeatureTelemetry: Codeunit "Feature Telemetry"; [NonDebuggable] - ClientID, ClientSecret, ClientTenant, RootID, RootSecret, RootTenant : Text; + ClientID, ClientSecret, ClientTenant, MarketplaceID, MarketplaceSecret, MarketplaceTenant : Text; FieldsVisible: Boolean; ExternalServiceTok: Label 'E-Document - SignUp', Locked = true; - MaskTxt: Label '*', Locked = true; } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpEnvironmentType.Enum.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpEnvironmentType.Enum.al index 84d8345f0a..b5d2d2a758 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpEnvironmentType.Enum.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpEnvironmentType.Enum.al @@ -7,14 +7,14 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; enum 6440 "SignUp Environment Type" { Access = Internal; - Caption = 'Environment Type', Locked = true; + Caption = 'Environment Type'; value(0; Production) { - Caption = 'Production', Locked = true; + Caption = 'Production'; } value(1; Test) { - Caption = 'Test', Locked = true; + Caption = 'Test'; } } \ No newline at end of file diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAPIRequests.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAPIRequests.Codeunit.al index 5f2a95f08c..e1a287a3c6 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAPIRequests.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAPIRequests.Codeunit.al @@ -219,7 +219,7 @@ codeunit 6441 "SignUp API Requests" begin this.InitRequest(HttpRequestMessage, HttpResponseMessage); - HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::POST, SignUpAuthentication.GetRootUrl() + '/api/Registration/init?EntraTenantId=' + SignUpAuthentication.GetBCInstanceIdentifier() + '&EnvironmentName=' + this.GetEnvironmentName()); + HttpRequestMessage := this.PrepareRequestMsg("Http Request Type"::POST, SignUpAuthentication.GetMarketplaceUrl() + '/api/Registration/init?EntraTenantId=' + SignUpAuthentication.GetBCInstanceIdentifier() + '&EnvironmentName=' + this.GetEnvironmentName()); exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage, true)); end; @@ -297,15 +297,15 @@ codeunit 6441 "SignUp API Requests" exit(this.SendRequest(HttpRequestMessage, HttpResponseMessage, false)); end; - local procedure SendRequest(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage; RootRequest: Boolean): Boolean + local procedure SendRequest(var HttpRequestMessage: HttpRequestMessage; var HttpResponseMessage: HttpResponseMessage; MarketplaceRequest: Boolean): Boolean var SignUpAuthentication: Codeunit "SignUp Authentication"; HttpClient: HttpClient; HttpHeaders: HttpHeaders; begin HttpRequestMessage.GetHeaders(HttpHeaders); - if RootRequest then - HttpHeaders.Add(this.AuthorizationTxt, SignUpAuthentication.GetRootBearerAuthToken()) + if MarketplaceRequest then + HttpHeaders.Add(this.AuthorizationTxt, SignUpAuthentication.GetMarketplaceBearerAuthToken()) else HttpHeaders.Add(this.AuthorizationTxt, SignUpAuthentication.GetBearerAuthToken()); exit(HttpClient.Send(HttpRequestMessage, HttpResponseMessage)); diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al index 7c2b826beb..6c60edd9e1 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/SignUpAuthentication.Codeunit.al @@ -23,17 +23,17 @@ codeunit 6442 "SignUp Authentication" BearerTxt: Label 'Bearer %1', Comment = '%1 = text value', Locked = true; AuthURLTxt: Label 'https://login.microsoftonline.com/%1/oauth2/token', Comment = '%1 Entra Tenant Id', Locked = true; AuthTemplateTxt: Label 'grant_type=client_credentials&client_id=%1&client_secret=%2&resource=%3', Locked = true; - ProdRootTenantIdTxt: Label '0d725623-dc26-484f-a090-b09d2003d092', Locked = true; + ProdMarketplaceTenantIdTxt: Label '0d725623-dc26-484f-a090-b09d2003d092', Locked = true; ProdClientTenantIdTxt: Label 'eef4ab2c-2b10-4380-bf4b-214157971162', Locked = true; ProdServiceAPITxt: Label 'https://edoc.exflow.io', Locked = true; - ErrorTokenLbl: Label 'Unable to fetch a root token.'; + ErrorTokenLbl: Label 'Unable to fetch Marketplace token.'; ErrorUnableToCreateClientCredentialsLbl: Label 'Unable to create client credentials.'; ClientIdTxt: Label 'clientId', Locked = true; ClientSecretTxt: Label 'clientSecret', Locked = true; - SignupRootUrlTxt: Label 'signup-root-url', Locked = true; - SignUpRootIdTxt: Label 'signup-root-id', Locked = true; - SignUpRootSecretTxt: Label 'signup-root-secret', Locked = true; - SignUpRootTenantTxt: Label 'signup-root-tenant', Locked = true; + SignupMarketplaceUrlTxt: Label 'signup-marketplace-url', Locked = true; + SignUpMarketplaceIdTxt: Label 'signup-marketplace-id', Locked = true; + SignUpMarketplaceSecretTxt: Label 'signup-marketplace-secret', Locked = true; + SignUpMarketplaceTenantTxt: Label 'signup-marketplace-tenant', Locked = true; SignUpClientTenantTxt: Label 'signup-client-tenant', Locked = true; SignUpServiceAPITxt: Label 'signup-service-api', Locked = true; SignUpAccessTokenKeyTxt: Label '{E45BB975-E67B-4A87-AC24-D409A5EF8301}', Locked = true; @@ -55,7 +55,7 @@ codeunit 6442 "SignUp Authentication" this.SignUpConnectionSetup."Authentication URL" := this.AuthURLTxt; this.SignUpConnectionSetup."Service URL" := this.GetServiceApi(); - this.StorageSet(this.SignUpConnectionSetup."Root Tenant", this.GetRootTenant()); + this.StorageSet(this.SignUpConnectionSetup."Marketplace Tenant", this.GetMarketplaceTenant()); this.StorageSet(this.SignUpConnectionSetup."Client Tenant", this.GetClientTenant()); this.SignUpConnectionSetup.Insert(); end; @@ -64,9 +64,9 @@ codeunit 6442 "SignUp Authentication" /// The method returns the onboarding URL. /// /// Onboarding URL - procedure GetRootOnboardingUrl(): Text + procedure GetMarketplaceOnboardingUrl(): Text begin - exit(this.GetRootUrl() + '/supm/landingpage?EntraTenantId=' + this.GetBCInstanceIdentifier()); + exit(this.GetMarketplaceUrl() + '/supm/landingpage?EntraTenantId=' + this.GetBCInstanceIdentifier()); end; /// @@ -103,12 +103,12 @@ codeunit 6442 "SignUp Authentication" end; /// - /// The method returns the root bearer authentication token. + /// The method returns the Marketplace bearer authentication token. /// - /// Root bearer authentication token - procedure GetRootBearerAuthToken(): SecretText; + /// Marketplace bearer authentication token + procedure GetMarketplaceBearerAuthToken(): SecretText; begin - exit(SecretStrSubstNo(this.BearerTxt, this.GetRootAuthToken())); + exit(SecretStrSubstNo(this.BearerTxt, this.GetMarketplaceAuthToken())); end; /// @@ -120,13 +120,18 @@ codeunit 6442 "SignUp Authentication" procedure StorageSet(var TokenKey: Guid; Value: Text): Boolean var ModuleDataScope: DataScope; + DeleteOk: Boolean; begin ModuleDataScope := ModuleDataScope::Module; this.ValidateValueKey(TokenKey); if Value = '' then begin - if IsolatedStorage.Contains(TokenKey, ModuleDataScope) then - exit(IsolatedStorage.Delete(TokenKey, ModuleDataScope)) + if IsolatedStorage.Contains(TokenKey, ModuleDataScope) then begin + DeleteOk := IsolatedStorage.Delete(TokenKey, ModuleDataScope); + if DeleteOk then + Clear(TokenKey); + exit(DeleteOk); + end; end else exit(IsolatedStorage.Set(TokenKey, Value, ModuleDataScope)); end; @@ -149,26 +154,29 @@ codeunit 6442 "SignUp Authentication" procedure GetBCInstanceIdentifier() Identifier: Text var AADTenantID, AADDomainName : Text; + NullGuid: Guid; begin if this.GetAADTenantInformation(AADTenantID, AADDomainName) then - Identifier := AADTenantID; + Identifier := AADTenantID + else + Identifier := NullGuid; end; /// - /// The method returns the root URL. + /// The method returns the Marketplace URL. /// /// [NonDebuggable] - procedure GetRootUrl() ReturnValue: Text + procedure GetMarketplaceUrl() ReturnValue: Text begin - if this.FetchSecretFromKeyVault(this.SignupRootUrlTxt, ReturnValue) then + if this.FetchSecretFromKeyVault(this.SignupMarketplaceUrlTxt, ReturnValue) then exit; - if not this.SignUpConnectionSetup.GetSetup() then + if not this.SignUpConnectionSetup.Get() then exit; - this.SignUpConnectionSetup.TestField("Root Market URL"); - ReturnValue := this.SignUpConnectionSetup."Root Market URL"; + this.SignUpConnectionSetup.TestField("Marketplace URL"); + ReturnValue := this.SignUpConnectionSetup."Marketplace URL"; end; #endregion @@ -190,9 +198,9 @@ codeunit 6442 "SignUp Authentication" exit(this.StorageGet(this.SignUpAccessTokenKeyTxt, DataScope::Module)); end; - local procedure GetRootAuthToken() ReturnValue: SecretText; + local procedure GetMarketplaceAuthToken() ReturnValue: SecretText; begin - if not this.GetRootAccessToken(ReturnValue) then + if not this.GetMarketplaceAccessToken(ReturnValue) then Error(this.ErrorTokenLbl); end; @@ -200,7 +208,7 @@ codeunit 6442 "SignUp Authentication" begin Clear(this.SignUpConnectionSetup); - this.SignUpConnectionSetup.GetSetup(); + this.SignUpConnectionSetup.Get(); this.StorageSet(this.SignUpConnectionSetup."Client ID", ClientId); this.StorageSet(this.SignUpConnectionSetup."Client Secret", ClientSecret); this.SignUpConnectionSetup.Modify(); @@ -235,16 +243,16 @@ codeunit 6442 "SignUp Authentication" end; [NonDebuggable] - local procedure GetRootAccessToken(var AccessToken: SecretText): Boolean + local procedure GetMarketplaceAccessToken(var AccessToken: SecretText): Boolean var ModuleDataScope: DataScope; begin ModuleDataScope := ModuleDataScope::Module; - this.SignUpConnectionSetup.GetSetup(); + this.SignUpConnectionSetup.Get(); - exit(this.GetAccessToken(AccessToken, this.GetRootId(), - this.GetRootSecret(), - this.StorageGetText(this.SignUpConnectionSetup."Root Tenant", ModuleDataScope))); + exit(this.GetAccessToken(AccessToken, this.GetMarketplaceId(), + this.GetMarketplaceSecret(), + this.StorageGetText(this.SignUpConnectionSetup."Marketplace Tenant", ModuleDataScope))); end; [NonDebuggable] @@ -253,7 +261,7 @@ codeunit 6442 "SignUp Authentication" ModuleDataScope: DataScope; begin ModuleDataScope := ModuleDataScope::Module; - this.SignUpConnectionSetup.GetSetup(); + this.SignUpConnectionSetup.Get(); exit(this.GetAccessToken(AccessToken, this.StorageGetText(this.SignUpConnectionSetup."Client ID", ModuleDataScope), this.StorageGet(this.SignUpConnectionSetup."Client Secret", ModuleDataScope), @@ -268,7 +276,7 @@ codeunit 6442 "SignUp Authentication" Response: Text; begin Clear(AccessToken); - this.SignUpConnectionSetup.GetSetup(); + this.SignUpConnectionSetup.Get(); this.SignUpConnectionSetup.TestField("Authentication URL"); HttpRequestMessage := this.PrepareRequest(SecretStrSubstNo(this.AuthTemplateTxt, TypeHelper.UriEscapeDataString(ClientId), ClientSecret, TypeHelper.UriEscapeDataString(ClientId)), @@ -313,12 +321,18 @@ codeunit 6442 "SignUp Authentication" end; local procedure StorageSet(var TokenKey: Guid; Value: SecretText; TokenDataScope: DataScope): Boolean + var + DeleteOk: Boolean; begin this.ValidateValueKey(TokenKey); if Value.IsEmpty() then begin - if IsolatedStorage.Contains(TokenKey, TokenDataScope) then - exit(IsolatedStorage.Delete(TokenKey, TokenDataScope)) + if IsolatedStorage.Contains(TokenKey, TokenDataScope) then begin + DeleteOk := IsolatedStorage.Delete(TokenKey, TokenDataScope); + if DeleteOk then + Clear(TokenKey); + exit(DeleteOk); + end; end else exit(IsolatedStorage.Set(TokenKey, Value, TokenDataScope)); end; @@ -375,36 +389,36 @@ codeunit 6442 "SignUp Authentication" end; [NonDebuggable] - local procedure GetRootId() ReturnValue: Text + local procedure GetMarketplaceId() ReturnValue: Text begin - if this.FetchSecretFromKeyVault(this.SignUpRootIdTxt, ReturnValue) then + if this.FetchSecretFromKeyVault(this.SignUpMarketplaceIdTxt, ReturnValue) then exit; - if not this.SignUpConnectionSetup.GetSetup() then + if not this.SignUpConnectionSetup.Get() then exit; - this.SignUpConnectionSetup.TestField("Root App ID"); - ReturnValue := this.StorageGetText(this.SignUpConnectionSetup."Root App ID", DataScope::Module); + this.SignUpConnectionSetup.TestField("Marketplace App ID"); + ReturnValue := this.StorageGetText(this.SignUpConnectionSetup."Marketplace App ID", DataScope::Module); end; - local procedure GetRootSecret() ReturnValue: SecretText + local procedure GetMarketplaceSecret() ReturnValue: SecretText begin - if this.FetchSecretFromKeyVault(this.SignUpRootSecretTxt, ReturnValue) then + if this.FetchSecretFromKeyVault(this.SignUpMarketplaceSecretTxt, ReturnValue) then exit; - if not this.SignUpConnectionSetup.GetSetup() then + if not this.SignUpConnectionSetup.Get() then exit; - this.SignUpConnectionSetup.TestField("Root Secret"); - ReturnValue := this.StorageGet(this.SignUpConnectionSetup."Root Secret", DataScope::Module); + this.SignUpConnectionSetup.TestField("Marketplace Secret"); + ReturnValue := this.StorageGet(this.SignUpConnectionSetup."Marketplace Secret", DataScope::Module); end; [NonDebuggable] - local procedure GetRootTenant() ReturnValue: Text + local procedure GetMarketplaceTenant() ReturnValue: Text begin - if this.FetchSecretFromKeyVault(this.SignUpRootTenantTxt, ReturnValue) then + if this.FetchSecretFromKeyVault(this.SignUpMarketplaceTenantTxt, ReturnValue) then exit; - ReturnValue := this.ProdRootTenantIdTxt; + ReturnValue := this.ProdMarketplaceTenantIdTxt; end; local procedure GetClientTenant() ReturnValue: Text diff --git a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationHelpers.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationHelpers.Codeunit.al index d13c1e5fdb..31b5532cdd 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationHelpers.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationHelpers.Codeunit.al @@ -28,9 +28,9 @@ codeunit 148196 IntegrationHelpers SignUpAuthentication: Codeunit "SignUp Authentication"; begin SignUpConnectionSetup.Get(); - SignUpAuthentication.StorageSet(SignUpConnectionSetup."Root App ID", this.DummyId()); - SignUpAuthentication.StorageSet(SignUpConnectionSetup."Root Secret", this.DummyId()); - SignUpAuthentication.StorageSet(SignUpConnectionSetup."Root Tenant", this.DummyId()); + SignUpAuthentication.StorageSet(SignUpConnectionSetup."Marketplace App ID", this.DummyId()); + SignUpAuthentication.StorageSet(SignUpConnectionSetup."Marketplace Secret", this.DummyId()); + SignUpAuthentication.StorageSet(SignUpConnectionSetup."Marketplace Tenant", this.DummyId()); SignUpAuthentication.StorageSet(SignUpConnectionSetup."Client ID", this.DummyId()); SignUpAuthentication.StorageSet(SignUpConnectionSetup."Client Secret", this.DummyId()); SignUpAuthentication.StorageSet(SignUpConnectionSetup."Client Tenant", this.ClientTenantId()); diff --git a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al index 6a6ff584cc..e0af166f59 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al +++ b/Apps/W1/EDocumentConnectors/SignUp/test/src/IntegrationTests.Codeunit.al @@ -56,7 +56,7 @@ codeunit 148195 IntegrationTests // [Given] Team member this.LibraryLowerPermissions.SetTeamMember(); - this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Read'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp E-Doc Read'); // [When] Posting invoice and EDocument is created this.LibraryEDocument.PostInvoice(this.Customer); @@ -145,7 +145,7 @@ codeunit 148195 IntegrationTests // [Given] Team member this.LibraryLowerPermissions.SetTeamMember(); - this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Read'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp E-Doc Read'); // [When] Posting invoice and EDocument is created this.LibraryEDocument.PostInvoice(this.Customer); @@ -183,9 +183,9 @@ codeunit 148195 IntegrationTests EDocumentPage.Close(); // [WHEN] Executing Get Response succesfully - this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Edit'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp E-Doc Edit'); this.IntegrationHelpers.SetAPICode('/signup/200/response-pending'); - this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Read'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp E-Doc Read'); JobQueueEntry.FindJobQueueEntry(JobQueueEntry."Object Type to Run"::Codeunit, Codeunit::"E-Document Get Response"); this.LibraryJobQueue.RunJobQueueDispatcher(JobQueueEntry); @@ -219,9 +219,9 @@ codeunit 148195 IntegrationTests EDocumentPage.Close(); // [WHEN] Executing Get Response succesfully - this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Edit'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp E-Doc Edit'); this.IntegrationHelpers.SetAPIWith200Code(); - this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Read'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp E-Doc Read'); JobQueueEntry.FindJobQueueEntry(JobQueueEntry."Object Type to Run"::Codeunit, Codeunit::"E-Document Get Response"); this.LibraryJobQueue.RunJobQueueDispatcher(JobQueueEntry); @@ -276,7 +276,7 @@ codeunit 148195 IntegrationTests // [Given] Team member this.LibraryLowerPermissions.SetTeamMember(); - this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Read'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp E-Doc Read'); // [When] Posting invoice and EDocument is created this.LibraryEDocument.PostInvoice(this.Customer); @@ -315,9 +315,9 @@ codeunit 148195 IntegrationTests EDocumentPage.Close(); // [WHEN] Executing Get Response succesfully - this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Edit'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp E-Doc Edit'); this.IntegrationHelpers.SetAPICode('/signup/200/response-error'); - this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Read'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp E-Doc Read'); JobQueueEntry.FindJobQueueEntry(JobQueueEntry."Object Type to Run"::Codeunit, Codeunit::"E-Document Get Response"); this.LibraryJobQueue.RunJobQueueDispatcher(JobQueueEntry); @@ -390,9 +390,9 @@ codeunit 148195 IntegrationTests this.Assert.AreEqual('', EDocumentPage.ErrorMessagesPart.Description.Value(), this.IncorrectValueErr); EDocumentPage.Close(); - this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Edit'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp E-Doc Edit'); this.IntegrationHelpers.SetAPIWith200Code(); - this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Read'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp E-Doc Read'); JobQueueEntry.FindJobQueueEntry(JobQueueEntry."Object Type to Run"::Codeunit, Codeunit::"E-Document Get Response"); this.LibraryJobQueue.RunJobQueueDispatcher(JobQueueEntry); @@ -445,7 +445,7 @@ codeunit 148195 IntegrationTests // [Given] Team member this.LibraryLowerPermissions.SetTeamMember(); - this.LibraryLowerPermissions.AddPermissionSet('SignUp EDCO Read'); + this.LibraryLowerPermissions.AddPermissionSet('SignUp E-Doc Read'); // [When] Posting invoice and EDocument is created this.LibraryEDocument.PostInvoice(this.Customer); From 4f1c8947836b565894033bb88aa9eeb0bf83e2b6 Mon Sep 17 00:00:00 2001 From: geschwint Date: Wed, 19 Feb 2025 19:24:35 +0100 Subject: [PATCH 63/63] Unused Using statement --- .../SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al | 1 - 1 file changed, 1 deletion(-) diff --git a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al index 9509180fc5..8be919a078 100644 --- a/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al +++ b/Apps/W1/EDocumentConnectors/SignUp/app/src/Setup/SignUpConnectionSetupCard.Page.al @@ -5,7 +5,6 @@ namespace Microsoft.EServices.EDocumentConnector.SignUp; using System.Telemetry; -using Microsoft.Foundation.Company; using System.Environment; page 6440 "SignUp Connection Setup Card"